This is an automated email from the ASF dual-hosted git repository.

Yicong-Huang pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/texera.git


The following commit(s) were added to refs/heads/main by this push:
     new 41a8197022 test(frontend): re-enable 4 user-workflow / dashboard / 
list-item specs (#4944)
41a8197022 is described below

commit 41a8197022a16b98867a8495b2061d86d771b555
Author: Yicong Huang <[email protected]>
AuthorDate: Tue May 5 17:07:46 2026 -0700

    test(frontend): re-enable 4 user-workflow / dashboard / list-item specs 
(#4944)
    
    ### What changes were proposed in this PR?
    
    Drop 4 entries from the spec exclusion lists in `tsconfig.spec.json` and
    `angular.json`'s test target, port their TestBed setups to the
    standalone-component shape, and fix one malformed template attribute
    that jsdom won't tolerate.
    
    **Specs re-enabled:**
    
    - `dashboard.component.spec.ts` — extends `socialAuthServiceMock` with
    `initState` (the Google sign-in directive subscribes to it in its
    constructor) and adds an `AdminSettingsService` stub; switches to
    `imports: [DashboardComponent]` so its standalone graph carries
    `GoogleSigninButtonModule` instead of relying on `NO_ERRORS_SCHEMA`.
    - `user-project-list-item.component.spec.ts` — wraps the component in a
    `TestHostComponent` template `<nz-list><texera-user-project-list-item
    .../></nz-list>` so the `<nz-list-item>`-rooted component finds an
    `NzListComponent` provider; adds `provideRouter([])` for the embedded
    `[routerLink]`.
    - `user-workflow-list-item.component.spec.ts` — same `<nz-list>` host
    wrapper.
    - `user-workflow.component.spec.ts` — switches `declarations: [...]` to
    `imports: [...]` for the now-standalone children; converts
    `beforeEach(waitForAsync(...))` to `beforeEach(async () => ...)` so the
    setup runs outside the per-`it` ProxyZone wrapper.
    
    **Drive-by template fix:**
    
    `user-workflow.component.html` had a stray `]="true"` line — left over
    from #4873's `[nzBorderless]="true"` → `nzVariant="borderless"` rewrite.
    Browsers silently tolerate the malformed attribute, but jsdom throws
    `InvalidCharacterError: "]" did not match the Name production` during
    `setAttribute`, which is why the spec couldn't run under Vitest.
    
    After this PR, the exclude list contains only specs gated on Vitest
    browser mode (#4866) or specs whose body is still a placeholder.
    
    ### Any related issues, documentation, discussions?
    
    Part of #4880.
    
    ### How was this PR tested?
    
    `yarn install && yarn ng test --watch=false` exits 0 locally; `yarn
    format:ci` is clean. CI exercises the same test command on the ubuntu /
    windows / macos frontend matrices.
    
    ```
    Test Files  56 passed | 3 skipped (59)
         Tests  248 passed | 8 skipped | 2 todo (258)
    ```
    
    ### Was this PR authored or co-authored using generative AI tooling?
    
    Generated-by: Claude Opus 4.7 (1M context)
    
    Co-authored-by: Claude Opus 4.7 (1M context) <[email protected]>
---
 frontend/angular.json                              |  4 ---
 .../component/dashboard.component.spec.ts          | 20 +++++++----
 .../user-project-list-item.component.spec.ts       | 39 +++++++++++++++++-----
 .../user-workflow-list-item.component.spec.ts      | 39 +++++++++++++++++-----
 .../user-workflow/user-workflow.component.html     |  1 -
 .../user-workflow/user-workflow.component.spec.ts  | 20 +++++------
 frontend/src/tsconfig.spec.json                    | 13 +-------
 7 files changed, 85 insertions(+), 51 deletions(-)

diff --git a/frontend/angular.json b/frontend/angular.json
index 6e840bdb52..fabc6ba8ce 100644
--- a/frontend/angular.json
+++ b/frontend/angular.json
@@ -97,10 +97,6 @@
               "**/drag-drop.service.spec.ts",
               
"**/app/common/formly/preset-wrapper/preset-wrapper.component.spec.ts",
               "**/app/common/service/user/config/user-config.service.spec.ts",
-              "**/app/dashboard/component/dashboard.component.spec.ts",
-              
"**/app/dashboard/component/user/user-project/user-project-list-item/user-project-list-item.component.spec.ts",
-              
"**/app/dashboard/component/user/user-workflow/user-workflow-list-item/user-workflow-list-item.component.spec.ts",
-              
"**/app/dashboard/component/user/user-workflow/user-workflow.component.spec.ts",
               
"**/app/workspace/component/code-editor-dialog/code-debugger.component.spec.ts",
               
"**/app/workspace/component/code-editor-dialog/code-editor.component.spec.ts",
               
"**/app/workspace/component/codearea-custom-template/codearea-custom-template.component.spec.ts",
diff --git a/frontend/src/app/dashboard/component/dashboard.component.spec.ts 
b/frontend/src/app/dashboard/component/dashboard.component.spec.ts
index d5b01934f6..ca6cf086b6 100644
--- a/frontend/src/app/dashboard/component/dashboard.component.spec.ts
+++ b/frontend/src/app/dashboard/component/dashboard.component.spec.ts
@@ -19,13 +19,14 @@
 
 import { ComponentFixture, TestBed } from "@angular/core/testing";
 import { DashboardComponent } from "./dashboard.component";
-import { ChangeDetectorRef, EventEmitter, NgZone, NO_ERRORS_SCHEMA } from 
"@angular/core";
+import { ChangeDetectorRef, EventEmitter, NgZone } from "@angular/core";
 import { By } from "@angular/platform-browser";
-import { of } from "rxjs";
+import { EMPTY, of } from "rxjs";
 
 import { UserService } from "../../common/service/user/user.service";
 import { FlarumService } from "../service/user/flarum/flarum.service";
 import { SocialAuthService } from "@abacritt/angularx-social-login";
+import { AdminSettingsService } from 
"../service/admin/settings/admin-settings.service";
 import {
   ActivatedRoute,
   ActivatedRouteSnapshot,
@@ -50,6 +51,7 @@ describe("DashboardComponent", () => {
   let cdrMock: Partial<ChangeDetectorRef>;
   let ngZoneMock: Partial<NgZone>;
   let socialAuthServiceMock: Partial<SocialAuthService>;
+  let adminSettingsServiceMock: Partial<AdminSettingsService>;
   let activatedRouteMock: Partial<ActivatedRoute>;
 
   const activatedRouteSnapshotMock: Partial<ActivatedRouteSnapshot> = {
@@ -105,7 +107,14 @@ describe("DashboardComponent", () => {
     };
 
     socialAuthServiceMock = {
-      authState: of(),
+      authState: EMPTY,
+      // GoogleSigninButtonDirective subscribes to initState in its 
constructor;
+      // EMPTY keeps the subscription open without triggering 
google.accounts.id.renderButton.
+      initState: EMPTY,
+    };
+
+    adminSettingsServiceMock = {
+      getSetting: vi.fn().mockReturnValue(EMPTY),
     };
 
     activatedRouteMock = {
@@ -113,8 +122,7 @@ describe("DashboardComponent", () => {
     };
 
     await TestBed.configureTestingModule({
-      declarations: [DashboardComponent],
-      imports: [HttpClientTestingModule],
+      imports: [DashboardComponent, HttpClientTestingModule],
       providers: [
         { provide: UserService, useValue: userServiceMock },
         { provide: Router, useValue: routerMock },
@@ -122,10 +130,10 @@ describe("DashboardComponent", () => {
         { provide: ChangeDetectorRef, useValue: cdrMock },
         { provide: NgZone, useValue: ngZoneMock },
         { provide: SocialAuthService, useValue: socialAuthServiceMock },
+        { provide: AdminSettingsService, useValue: adminSettingsServiceMock },
         { provide: ActivatedRoute, useValue: activatedRouteMock },
         ...commonTestProviders,
       ],
-      schemas: [NO_ERRORS_SCHEMA],
     }).compileComponents();
   });
 
diff --git 
a/frontend/src/app/dashboard/component/user/user-project/user-project-list-item/user-project-list-item.component.spec.ts
 
b/frontend/src/app/dashboard/component/user/user-project/user-project-list-item/user-project-list-item.component.spec.ts
index 813e556497..1eec8b69b0 100644
--- 
a/frontend/src/app/dashboard/component/user/user-project/user-project-list-item/user-project-list-item.component.spec.ts
+++ 
b/frontend/src/app/dashboard/component/user/user-project/user-project-list-item/user-project-list-item.component.spec.ts
@@ -17,21 +17,42 @@
  * under the License.
  */
 
+import { Component, ViewChild } from "@angular/core";
 import { ComponentFixture, TestBed } from "@angular/core/testing";
 import { UserProjectListItemComponent } from 
"./user-project-list-item.component";
 import { NotificationService } from 
"src/app/common/service/notification/notification.service";
 import { UserProjectService } from 
"../../../../service/user/project/user-project.service";
 import { DashboardProject } from 
"../../../../type/dashboard-project.interface";
 import { HttpClientTestingModule } from "@angular/common/http/testing";
+import { NzListComponent } from "ng-zorro-antd/list";
 import { NzModalService } from "ng-zorro-antd/modal";
+import { provideRouter } from "@angular/router";
 import { StubUserService } from 
"../../../../../common/service/user/stub-user.service";
 import { UserService } from "../../../../../common/service/user/user.service";
-import { HighlightSearchTermsPipe } from 
"../../user-workflow/user-workflow-list-item/highlight-search-terms.pipe";
 import { commonTestProviders } from "../../../../../common/testing/test-utils";
 
+// UserProjectListItemComponent is rooted at <nz-list-item>; instantiating it
+// outside an <nz-list> host throws "No provider found for NzListComponent".
+@Component({
+  standalone: true,
+  imports: [NzListComponent, UserProjectListItemComponent],
+  template: `
+    <nz-list>
+      <texera-user-project-list-item
+        [entry]="entry"
+        [editable]="editable"></texera-user-project-list-item>
+    </nz-list>
+  `,
+})
+class TestHostComponent {
+  entry!: DashboardProject;
+  editable = true;
+  @ViewChild(UserProjectListItemComponent, { static: true }) inner!: 
UserProjectListItemComponent;
+}
+
 describe("UserProjectListItemComponent", () => {
   let component: UserProjectListItemComponent;
-  let fixture: ComponentFixture<UserProjectListItemComponent>;
+  let hostFixture: ComponentFixture<TestHostComponent>;
   const januaryFirst1970 = 28800000; // 1970-01-01 in PST
   const testProject: DashboardProject = {
     color: null,
@@ -45,24 +66,24 @@ describe("UserProjectListItemComponent", () => {
 
   beforeEach(async () => {
     await TestBed.configureTestingModule({
-      declarations: [UserProjectListItemComponent, HighlightSearchTermsPipe],
+      imports: [TestHostComponent, HttpClientTestingModule],
       providers: [
         NotificationService,
         UserProjectService,
         NzModalService,
         { provide: UserService, useClass: StubUserService },
+        provideRouter([]),
         ...commonTestProviders,
       ],
-      imports: [HttpClientTestingModule],
     }).compileComponents();
   });
 
   beforeEach(() => {
-    fixture = TestBed.createComponent(UserProjectListItemComponent);
-    component = fixture.componentInstance;
-    component.entry = testProject;
-    component.editable = true;
-    fixture.detectChanges();
+    hostFixture = TestBed.createComponent(TestHostComponent);
+    hostFixture.componentInstance.entry = testProject;
+    hostFixture.componentInstance.editable = true;
+    hostFixture.detectChanges();
+    component = hostFixture.componentInstance.inner;
   });
 
   it("should create", () => {
diff --git 
a/frontend/src/app/dashboard/component/user/user-workflow/user-workflow-list-item/user-workflow-list-item.component.spec.ts
 
b/frontend/src/app/dashboard/component/user/user-workflow/user-workflow-list-item/user-workflow-list-item.component.spec.ts
index afade00123..a73bffe9d0 100644
--- 
a/frontend/src/app/dashboard/component/user/user-workflow/user-workflow-list-item/user-workflow-list-item.component.spec.ts
+++ 
b/frontend/src/app/dashboard/component/user/user-workflow/user-workflow-list-item/user-workflow-list-item.component.spec.ts
@@ -17,6 +17,7 @@
  * under the License.
  */
 
+import { Component, ViewChild } from "@angular/core";
 import { ComponentFixture, TestBed, waitForAsync } from 
"@angular/core/testing";
 import { UserWorkflowListItemComponent } from 
"./user-workflow-list-item.component";
 import { FileSaverService } from 
"../../../../service/user/file/file-saver.service";
@@ -26,34 +27,56 @@ import { StubWorkflowPersistService } from 
"../../../../../common/service/workfl
 import { WorkflowPersistService } from 
"../../../../../common/service/workflow-persist/workflow-persist.service";
 import { UserProjectService } from 
"../../../../service/user/project/user-project.service";
 import { StubUserProjectService } from 
"../../../../service/user/project/stub-user-project.service";
+import { NzListComponent } from "ng-zorro-antd/list";
 import { NzModalModule } from "ng-zorro-antd/modal";
 import { HttpClientTestingModule } from "@angular/common/http/testing";
-import { HighlightSearchTermsPipe } from "./highlight-search-terms.pipe";
+import { provideRouter } from "@angular/router";
+import { DashboardEntry } from "../../../../type/dashboard-entry";
 import { NzTooltipModule } from "ng-zorro-antd/tooltip";
 import { commonTestProviders } from "../../../../../common/testing/test-utils";
+
+// UserWorkflowListItemComponent is rooted at <nz-list-item>; instantiating it
+// outside an <nz-list> host throws "No provider found for NzListComponent".
+@Component({
+  standalone: true,
+  imports: [NzListComponent, UserWorkflowListItemComponent],
+  template: `
+    <nz-list>
+      <texera-user-workflow-list-item
+        [entry]="entry"
+        [editable]="editable"></texera-user-workflow-list-item>
+    </nz-list>
+  `,
+})
+class TestHostComponent {
+  entry!: DashboardEntry;
+  editable = true;
+  @ViewChild(UserWorkflowListItemComponent, { static: true }) inner!: 
UserWorkflowListItemComponent;
+}
+
 describe("UserWorkflowListItemComponent", () => {
   let component: UserWorkflowListItemComponent;
-  let fixture: ComponentFixture<UserWorkflowListItemComponent>;
+  let fixture: ComponentFixture<TestHostComponent>;
   const fileSaverServiceSpy = { saveAs: vi.fn() } as any;
   beforeEach(async () => {
     await TestBed.configureTestingModule({
-      imports: [NzModalModule, HttpClientTestingModule, NzTooltipModule],
-      declarations: [UserWorkflowListItemComponent, HighlightSearchTermsPipe],
+      imports: [TestHostComponent, NzModalModule, HttpClientTestingModule, 
NzTooltipModule],
       providers: [
         { provide: WorkflowPersistService, useValue: new 
StubWorkflowPersistService(testWorkflowEntries) },
         { provide: UserProjectService, useValue: new StubUserProjectService() 
},
         { provide: FileSaverService, useValue: fileSaverServiceSpy },
+        provideRouter([]),
         ...commonTestProviders,
       ],
     }).compileComponents();
   });
 
   beforeEach(() => {
-    fixture = TestBed.createComponent(UserWorkflowListItemComponent);
-    component = fixture.componentInstance;
-    component.entry = testWorkflowEntries[0];
-    component.editable = true;
+    fixture = TestBed.createComponent(TestHostComponent);
+    fixture.componentInstance.entry = testWorkflowEntries[0];
+    fixture.componentInstance.editable = true;
     fixture.detectChanges();
+    component = fixture.componentInstance.inner;
   });
 
   it("should create", () => {
diff --git 
a/frontend/src/app/dashboard/component/user/user-workflow/user-workflow.component.html
 
b/frontend/src/app/dashboard/component/user/user-workflow/user-workflow.component.html
index 7f3d431ae9..1873658797 100644
--- 
a/frontend/src/app/dashboard/component/user/user-workflow/user-workflow.component.html
+++ 
b/frontend/src/app/dashboard/component/user/user-workflow/user-workflow.component.html
@@ -146,7 +146,6 @@
       nzMode="tags"
       nzPlaceHolder="Search all workflows"
       nzVariant="borderless"
-      ]="true"
       [nzOpen]="false"
       ngDefaultControl
       [(ngModel)]="filters.masterFilterList"
diff --git 
a/frontend/src/app/dashboard/component/user/user-workflow/user-workflow.component.spec.ts
 
b/frontend/src/app/dashboard/component/user/user-workflow/user-workflow.component.spec.ts
index 2e9b111101..4344b5e5a7 100644
--- 
a/frontend/src/app/dashboard/component/user/user-workflow/user-workflow.component.spec.ts
+++ 
b/frontend/src/app/dashboard/component/user/user-workflow/user-workflow.component.spec.ts
@@ -17,7 +17,7 @@
  * under the License.
  */
 
-import { ComponentFixture, TestBed, waitForAsync } from 
"@angular/core/testing";
+import { ComponentFixture, TestBed } from "@angular/core/testing";
 import { RouterTestingModule } from "@angular/router/testing";
 import { HttpClientTestingModule } from "@angular/common/http/testing";
 import { FormsModule, ReactiveFormsModule } from "@angular/forms";
@@ -67,17 +67,10 @@ describe("SavedWorkflowSectionComponent", () => {
 
   let downloadServiceSpy: any;
 
-  beforeEach(waitForAsync(() => {
+  beforeEach(async () => {
     downloadServiceSpy = { downloadWorkflowsAsZip: vi.fn() } as any;
 
-    TestBed.configureTestingModule({
-      declarations: [
-        UserWorkflowComponent,
-        ShareAccessComponent,
-        FiltersComponent,
-        UserWorkflowListItemComponent,
-        SearchResultsComponent,
-      ],
+    await TestBed.configureTestingModule({
       providers: [
         NzModalService,
         { provide: WorkflowPersistService, useValue: new 
StubWorkflowPersistService(testWorkflowEntries) },
@@ -95,6 +88,11 @@ describe("SavedWorkflowSectionComponent", () => {
         ...commonTestProviders,
       ],
       imports: [
+        UserWorkflowComponent,
+        ShareAccessComponent,
+        FiltersComponent,
+        UserWorkflowListItemComponent,
+        SearchResultsComponent,
         FormsModule,
         RouterTestingModule,
         HttpClientTestingModule,
@@ -114,7 +112,7 @@ describe("SavedWorkflowSectionComponent", () => {
         NzButtonModule,
       ],
     }).compileComponents();
-  }));
+  });
 
   beforeEach(() => {
     fixture = TestBed.createComponent(UserWorkflowComponent);
diff --git a/frontend/src/tsconfig.spec.json b/frontend/src/tsconfig.spec.json
index c0d4dddbb1..474fe72573 100644
--- a/frontend/src/tsconfig.spec.json
+++ b/frontend/src/tsconfig.spec.json
@@ -38,17 +38,6 @@
     
"**/app/workspace/component/left-panel/time-travel/time-travel.component.spec.ts",
     
"**/app/workspace/component/left-panel/versions-list/versions-list.component.spec.ts",
     
"**/app/workspace/component/property-editor/operator-property-edit-frame/operator-property-edit-frame.component.spec.ts",
-    
"**/app/workspace/component/workflow-editor/workflow-editor.component.spec.ts",
-
-    // Component templates rooted at <nz-list-item>: outside an <nz-list>
-    // host these throw `No provider found for NzListComponent`. Need a
-    // wrapper TestHostComponent that mounts them inside <nz-list>.
-    
"**/app/dashboard/component/user/user-project/user-project-list-item/user-project-list-item.component.spec.ts",
-    
"**/app/dashboard/component/user/user-workflow/user-workflow-list-item/user-workflow-list-item.component.spec.ts",
-    // user-workflow embeds the list-item above, cascading the same NzList 
host issue.
-    
"**/app/dashboard/component/user/user-workflow/user-workflow.component.spec.ts",
-    // Dashboard renders <asl-google-signin-button> which dereferences fields 
on the
-    // SocialAuthService stub that our minimal mock doesn't provide.
-    "**/app/dashboard/component/dashboard.component.spec.ts"
+    
"**/app/workspace/component/workflow-editor/workflow-editor.component.spec.ts"
   ]
 }

Reply via email to