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");
+ });
+ });
});