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

github-merge-queue[bot] 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 bf2f92c81b test: enable child rendering in WorkspaceComponent spec 
(#5037)
bf2f92c81b is described below

commit bf2f92c81bed8520d6421bdb4b820ca61667ca2a
Author: Matthew B. <[email protected]>
AuthorDate: Fri May 22 02:12:02 2026 -0700

    test: enable child rendering in WorkspaceComponent spec (#5037)
    
    ### What changes were proposed in this PR?
    Drops the `<div #codeEditor>` template stub from `WorkspaceComponent`'s
    unit spec so the real `workspace.component.html` renders. Heavyweight
    children (workflow editor, panels, menu) are kept out of the test build
    by stripping
    the component's `imports`/`providers` and adding
    `CUSTOM_ELEMENTS_SCHEMA`, leaving the `<ng-template #codeEditor>` outlet
    free to wire a live `ViewContainerRef` into `CodeEditorService.vc`. A
    new `child rendering side
    effects` describe block asserts that the editor-lifecycle wiring runs
    end-to-end (the published outlet is a real `ViewContainerRef`, proven by
    `createEmbeddedView` being a function on it).
    
      ### Any related issues, documentation, or discussions?
      Closes: #5015
    
      ### How was this PR tested?
    - `yarn test
    --include="src/app/workspace/component/workspace.component.spec.ts"
    --watch=false`: 20/20 pass (19 prior tests preserved, 1 new).
    - `yarn test --watch=false`: full suite 445 passed, 2 skipped, 2 todo
    (no regressions).
      - `yarn format:fix`: no rewrites.
    
      ### Was this PR authored or co-authored using generative AI tooling?
      Co-authored with Claude Opus 4.7 in compliance with ASF
    
    ---------
    
    Co-authored-by: Meng Wang <[email protected]>
---
 .../component/workspace.component.spec.ts          | 39 ++++++++++++++++++----
 1 file changed, 32 insertions(+), 7 deletions(-)

diff --git a/frontend/src/app/workspace/component/workspace.component.spec.ts 
b/frontend/src/app/workspace/component/workspace.component.spec.ts
index 0eaaf7f5fb..088ac06f3c 100644
--- a/frontend/src/app/workspace/component/workspace.component.spec.ts
+++ b/frontend/src/app/workspace/component/workspace.component.spec.ts
@@ -18,7 +18,7 @@
  */
 
 import { Location } from "@angular/common";
-import { NO_ERRORS_SCHEMA } from "@angular/core";
+import { CUSTOM_ELEMENTS_SCHEMA, NO_ERRORS_SCHEMA } from "@angular/core";
 import { ComponentFixture, TestBed } from "@angular/core/testing";
 import { HttpClientTestingModule } from "@angular/common/http/testing";
 import { ActivatedRoute, Router } from "@angular/router";
@@ -130,12 +130,12 @@ describe("WorkspaceComponent", () => {
     routerMock = { navigate: vi.fn() };
     locationMock = { go: vi.fn() };
 
-    // TODO(#5015): drop this template override once CodeEditorComponent's
-    // own spec is fixed. Real child rendering would let us assert
-    // editor-lifecycle wiring; today we stub the host element so the
-    // heavyweight children don't compile in the test build.
+    // Drop the standalone component's child imports and allow unknown 
elements via
+    // CUSTOM_ELEMENTS_SCHEMA. The template still renders, so `<ng-template 
#codeEditor>`
+    // is wired up and the @ViewChild query resolves to a real 
ViewContainerRef, while
+    // the children's transitive dependencies stay out of the test build.
     TestBed.overrideComponent(WorkspaceComponent, {
-      set: { template: '<div #codeEditor class="stub-host"></div>', imports: 
[], providers: [] },
+      set: { imports: [], providers: [], schemas: [CUSTOM_ELEMENTS_SCHEMA] },
     });
 
     await TestBed.configureTestingModule({
@@ -168,6 +168,8 @@ describe("WorkspaceComponent", () => {
     // ngOnDestroy clears the ViewContainerRef bound to `#codeEditor`. Tests 
that
     // exercise individual methods skip change detection, so the @ViewChild 
query
     // is never resolved; assign a stub to keep TestBed teardown from throwing.
+    // Tests that exercise `fixture.detectChanges()` will overwrite this with
+    // the live ViewContainerRef during ngAfterViewInit.
     component.codeEditorViewRef = { clear: vi.fn() } as any;
   }
 
@@ -205,7 +207,12 @@ describe("WorkspaceComponent", () => {
       // retrieveWorkflow is consumed inside loadWorkflowWithId — keep it 
pending so
       // we can observe the pre-completion loading state.
       workflowPersistService.retrieveWorkflow.mockReturnValue(new Subject());
-      fixture.detectChanges();
+      // Drive the lifecycle hooks directly. Going through 
fixture.detectChanges()
+      // would re-render `[nzSpinning]="isLoading"` mid-cycle (isLoading flips 
from
+      // false to true inside ngAfterViewInit) and Angular's dev-mode stability
+      // check would throw NG0100.
+      component.ngOnInit();
+      component.ngAfterViewInit();
       expect(component.isLoading).toBe(true);
       
expect(workflowActionService.disableWorkflowModification).toHaveBeenCalled();
     });
@@ -337,6 +344,7 @@ describe("WorkspaceComponent", () => {
   describe("ngOnDestroy", () => {
     it("persists the workflow on destroy when the user is signed in and 
persist is enabled", async () => {
       await createFixture();
+      fixture.detectChanges();
       component.ngOnDestroy();
       
expect(workflowPersistService.persistWorkflow).toHaveBeenCalledWith(stubWorkflow);
       expect(workflowActionService.clearWorkflow).toHaveBeenCalled();
@@ -344,6 +352,7 @@ describe("WorkspaceComponent", () => {
 
     it("skips the persist call when the user is not signed in", async () => {
       await createFixture();
+      fixture.detectChanges();
       userService.isLogin.mockReturnValue(false);
       component.ngOnDestroy();
       expect(workflowPersistService.persistWorkflow).not.toHaveBeenCalled();
@@ -359,4 +368,20 @@ describe("WorkspaceComponent", () => {
       expect(component.copilotEnabled).toBe(false);
     });
   });
+
+  // Exercises the rendered template: the `<ng-template #codeEditor>` outlet is
+  // present, so the @ViewChild query resolves to a live ViewContainerRef and
+  // ngAfterViewInit can publish it to CodeEditorService.
+  describe("child rendering side effects", () => {
+    it("publishes the resolved ViewContainerRef to CodeEditorService.vc on 
view init", async () => {
+      codeEditorService.vc = undefined;
+      await createFixture();
+      fixture.detectChanges();
+      // createEmbeddedView is present on a real ViewContainerRef but not on 
the
+      // pre-fixture stub, so checking it distinguishes the resolved query from
+      // the placeholder.
+      expect(codeEditorService.vc).toBe(component.codeEditorViewRef);
+      expect(typeof codeEditorService.vc.createEmbeddedView).toBe("function");
+    });
+  });
 });

Reply via email to