You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@texera.apache.org by gi...@apache.org on 2026/06/13 18:54:13 UTC

(texera) branch gh-readonly-queue/main/pr-5624-58e5b43a54184c249f2d04a51fb73aef779b49c3 created (now aceca29cbd)

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

github-merge-queue[bot] pushed a change to branch gh-readonly-queue/main/pr-5624-58e5b43a54184c249f2d04a51fb73aef779b49c3
in repository https://gitbox.apache.org/repos/asf/texera.git


      at aceca29cbd test(frontend): expand OperatorReuseCacheStatusService spec coverage (#5624)

This branch includes the following new commits:

     new aceca29cbd test(frontend): expand OperatorReuseCacheStatusService spec coverage (#5624)

The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.



(texera) 01/01: test(frontend): expand OperatorReuseCacheStatusService spec coverage (#5624)

Posted by gi...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

github-merge-queue[bot] pushed a commit to branch gh-readonly-queue/main/pr-5624-58e5b43a54184c249f2d04a51fb73aef779b49c3
in repository https://gitbox.apache.org/repos/asf/texera.git

commit aceca29cbda1f223ac17753efb58eba726e58b2f
Author: Benjamin Le <12...@users.noreply.github.com>
AuthorDate: Sat Jun 13 11:54:04 2026 -0700

    test(frontend): expand OperatorReuseCacheStatusService spec coverage (#5624)
    
    ### What changes were proposed in this PR?
    Expands the existing spec for `OperatorReuseCacheStatusService`, which
    previously only checked `should be created`. Adds behavior-focused tests
    covering both constructor subscriptions: the `CacheStatusUpdateEvent`
    websocket handler and the `getReuseCacheOperatorsChangedStream` handler.
    Tests verify that `JointUIService.changeOperatorReuseCacheStatus` is
    called correctly for each operator, that the `mainJointPaper` null guard
    is respected in both handlers, and that empty operator lists do not
    throw.
    
    ### Any related issues, documentation, discussions?
    Closes #5543
    
    ### How was this PR tested?
    New tests run via `yarn test -- operator-reuse-cache-status` and `yarn
    lint`. 6 tests passing.
    
    ### Was this PR authored or co-authored using generative AI tooling?
    Generated-by: Claude (Claude Sonnet 4.6)
    
    Co-authored-by: Benjamin Le <be...@uci.edu>
---
 .../operator-reuse-cache-status.service.spec.ts    | 120 ++++++++++++++++++++-
 1 file changed, 119 insertions(+), 1 deletion(-)

diff --git a/frontend/src/app/workspace/service/workflow-status/operator-reuse-cache-status.service.spec.ts b/frontend/src/app/workspace/service/workflow-status/operator-reuse-cache-status.service.spec.ts
index 0c3ccb89fd..bbfd9c55d8 100644
--- a/frontend/src/app/workspace/service/workflow-status/operator-reuse-cache-status.service.spec.ts
+++ b/frontend/src/app/workspace/service/workflow-status/operator-reuse-cache-status.service.spec.ts
@@ -18,10 +18,13 @@
  */
 
 import { TestBed } from "@angular/core/testing";
+import { Subject } from "rxjs";
 import { OperatorMetadataService } from "../operator-metadata/operator-metadata.service";
 import { StubOperatorMetadataService } from "../operator-metadata/stub-operator-metadata.service";
-
 import { OperatorReuseCacheStatusService } from "./operator-reuse-cache-status.service";
+import { JointUIService } from "../joint-ui/joint-ui.service";
+import { WorkflowActionService } from "../workflow-graph/model/workflow-action.service";
+import { WorkflowWebsocketService } from "../workflow-websocket/workflow-websocket.service";
 import { HttpClientTestingModule } from "@angular/common/http/testing";
 import { commonTestProviders } from "../../../common/testing/test-utils";
 
@@ -46,3 +49,118 @@ describe("OperatorCacheStatusService", () => {
     expect(service).toBeTruthy();
   });
 });
+
+describe("OperatorCacheStatusService - behavior", () => {
+  let service: OperatorReuseCacheStatusService;
+  let cacheStatusEvents$: Subject<any>;
+  let reuseCacheOpsChanged$: Subject<any>;
+  let mockJointUIService: any;
+  let mockJointGraphWrapper: any;
+  let mockTexeraGraph: any;
+  let mockWorkflowActionService: any;
+  let mockWorkflowWebsocketService: any;
+  const mockMainJointPaper = {};
+
+  beforeEach(() => {
+    cacheStatusEvents$ = new Subject<any>();
+    reuseCacheOpsChanged$ = new Subject<any>();
+
+    mockJointUIService = {
+      changeOperatorReuseCacheStatus: vi.fn(),
+    };
+
+    mockJointGraphWrapper = {
+      getMainJointPaper: vi.fn().mockReturnValue(mockMainJointPaper),
+    };
+
+    mockTexeraGraph = {
+      getReuseCacheOperatorsChangedStream: vi.fn().mockReturnValue(reuseCacheOpsChanged$),
+      getOperator: vi.fn().mockImplementation((opID: string) => ({ operatorID: opID })),
+    };
+
+    mockWorkflowActionService = {
+      getTexeraGraph: vi.fn().mockReturnValue(mockTexeraGraph),
+      getJointGraphWrapper: vi.fn().mockReturnValue(mockJointGraphWrapper),
+    };
+
+    mockWorkflowWebsocketService = {
+      subscribeToEvent: vi.fn().mockReturnValue(cacheStatusEvents$),
+    };
+
+    TestBed.configureTestingModule({
+      providers: [
+        OperatorReuseCacheStatusService,
+        { provide: JointUIService, useValue: mockJointUIService },
+        { provide: WorkflowActionService, useValue: mockWorkflowActionService },
+        { provide: WorkflowWebsocketService, useValue: mockWorkflowWebsocketService },
+      ],
+    });
+
+    service = TestBed.inject(OperatorReuseCacheStatusService);
+  });
+
+  it("calls changeOperatorReuseCacheStatus for each operator in a CacheStatusUpdateEvent", () => {
+    const event = {
+      cacheStatusMap: {
+        op1: "cache",
+        op2: "no-cache",
+      },
+    };
+
+    cacheStatusEvents$.next(event);
+
+    expect(mockJointUIService.changeOperatorReuseCacheStatus).toHaveBeenCalledTimes(2);
+    expect(mockJointUIService.changeOperatorReuseCacheStatus).toHaveBeenCalledWith(
+      mockMainJointPaper,
+      { operatorID: "op1" },
+      "cache"
+    );
+    expect(mockJointUIService.changeOperatorReuseCacheStatus).toHaveBeenCalledWith(
+      mockMainJointPaper,
+      { operatorID: "op2" },
+      "no-cache"
+    );
+  });
+
+  it("does not call changeOperatorReuseCacheStatus when mainJointPaper is null on CacheStatusUpdateEvent", () => {
+    mockJointGraphWrapper.getMainJointPaper.mockReturnValue(null);
+
+    cacheStatusEvents$.next({ cacheStatusMap: { op1: "cache" } });
+
+    expect(mockJointUIService.changeOperatorReuseCacheStatus).not.toHaveBeenCalled();
+  });
+
+  it("calls changeOperatorReuseCacheStatus for all ops in a reuse cache operators changed event", () => {
+    const event = {
+      newReuseCacheOps: ["op1", "op2"],
+      newUnreuseCacheOps: ["op3"],
+    };
+
+    reuseCacheOpsChanged$.next(event);
+
+    expect(mockJointUIService.changeOperatorReuseCacheStatus).toHaveBeenCalledTimes(3);
+    expect(mockJointUIService.changeOperatorReuseCacheStatus).toHaveBeenCalledWith(mockMainJointPaper, {
+      operatorID: "op1",
+    });
+    expect(mockJointUIService.changeOperatorReuseCacheStatus).toHaveBeenCalledWith(mockMainJointPaper, {
+      operatorID: "op2",
+    });
+    expect(mockJointUIService.changeOperatorReuseCacheStatus).toHaveBeenCalledWith(mockMainJointPaper, {
+      operatorID: "op3",
+    });
+  });
+
+  it("does not call changeOperatorReuseCacheStatus when mainJointPaper is null on reuse cache changed event", () => {
+    mockJointGraphWrapper.getMainJointPaper.mockReturnValue(null);
+
+    reuseCacheOpsChanged$.next({ newReuseCacheOps: ["op1"], newUnreuseCacheOps: [] });
+
+    expect(mockJointUIService.changeOperatorReuseCacheStatus).not.toHaveBeenCalled();
+  });
+
+  it("does not throw when reuse cache changed event has empty operator lists", () => {
+    expect(() => {
+      reuseCacheOpsChanged$.next({ newReuseCacheOps: [], newUnreuseCacheOps: [] });
+    }).not.toThrow();
+  });
+});