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 a351f44fbf test(frontend): cover WorkflowUtilService untested helpers 
(#6689)
a351f44fbf is described below

commit a351f44fbf08920d7d9dfe806614ffc4c8ed5a83
Author: Matthew B. <[email protected]>
AuthorDate: Fri Jul 24 00:20:06 2026 -0700

    test(frontend): cover WorkflowUtilService untested helpers (#6689)
    
    ### What changes were proposed in this PR?
    - Add unit tests for updateOperatorVersion covering port rebuild, port
    preservation, and the unknown-type error.
    - Add unit tests for the static parseWorkflowInfo string parsing and
    object passthrough, and for getNewCommentBox default position and unique
    ids.
    ### Any related issues, documentation, discussions?
    Closes: #6688
    ### How was this PR tested?
    - Run: `cd frontend && node --max-old-space-size=8192
    ./node_modules/nx/dist/bin/nx.js test gui --watch=false
    
--include=src/app/workspace/service/workflow-graph/util/workflow-util.service.spec.ts`,
    expect the suite passing.
    - Test-only change; no production code is modified.
    ### Was this PR authored or co-authored using generative AI tooling?
    Co-authored with Claude Opus 4.8 in compliance with ASF
    
    ---------
    
    Co-authored-by: Claude Opus 4.8 <[email protected]>
    Co-authored-by: Xinyuan Lin <[email protected]>
---
 .../util/workflow-util.service.spec.ts             | 128 ++++++++++++++++++++-
 1 file changed, 127 insertions(+), 1 deletion(-)

diff --git 
a/frontend/src/app/workspace/service/workflow-graph/util/workflow-util.service.spec.ts
 
b/frontend/src/app/workspace/service/workflow-graph/util/workflow-util.service.spec.ts
index 41b47d49b4..adb4353525 100644
--- 
a/frontend/src/app/workspace/service/workflow-graph/util/workflow-util.service.spec.ts
+++ 
b/frontend/src/app/workspace/service/workflow-graph/util/workflow-util.service.spec.ts
@@ -22,8 +22,10 @@ import { OperatorMetadataService } from 
"./../../operator-metadata/operator-meta
 import { inject, TestBed } from "@angular/core/testing";
 
 import { WorkflowUtilService } from "./workflow-util.service";
-import { mockScanSourceSchema } from 
"../../operator-metadata/mock-operator-metadata.data";
+import { mockMultiInputOutputSchema, mockScanSourceSchema } from 
"../../operator-metadata/mock-operator-metadata.data";
 import { commonTestProviders } from "../../../../common/testing/test-utils";
+import { OperatorPredicate } from "../../../types/workflow-common.interface";
+import { ExecutionMode, Workflow, WorkflowContent } from 
"../../../../common/type/workflow";
 
 describe("WorkflowUtilService", () => {
   let workflowUtilService: WorkflowUtilService;
@@ -101,4 +103,128 @@ describe("WorkflowUtilService", () => {
     // assert all IDs are distinct
     expect(idSet.size).toEqual(repeat);
   });
+
+  it("should rebuild ports and version from the schema when the operator has 
no ports", () => {
+    const op: OperatorPredicate = {
+      operatorID: "op-1",
+      operatorType: mockMultiInputOutputSchema.operatorType,
+      operatorVersion: "stale-version",
+      operatorProperties: {},
+      inputPorts: [],
+      outputPorts: [],
+      showAdvanced: false,
+      isDisabled: false,
+    };
+
+    const updated = workflowUtilService.updateOperatorVersion(op);
+
+    // version is refreshed from the schema
+    
expect(updated.operatorVersion).toEqual(mockMultiInputOutputSchema.operatorVersion);
+    // ports are regenerated from the schema's port metadata
+    expect(updated.inputPorts.map(port => port.portID)).toEqual(["input-0", 
"input-1", "input-2"]);
+    expect(updated.outputPorts.map(port => port.portID)).toEqual(["output-0", 
"output-1", "output-2"]);
+  });
+
+  it("should keep the operator's existing ports when they are already 
present", () => {
+    const existingInputPorts = [{ portID: "input-existing", displayName: 
"keep-me" }];
+    const existingOutputPorts = [{ portID: "output-existing", displayName: 
"keep-me-too" }];
+    const op: OperatorPredicate = {
+      operatorID: "op-2",
+      operatorType: mockMultiInputOutputSchema.operatorType,
+      operatorVersion: "stale-version",
+      operatorProperties: {},
+      inputPorts: existingInputPorts,
+      outputPorts: existingOutputPorts,
+      showAdvanced: false,
+      isDisabled: false,
+    };
+
+    const updated = workflowUtilService.updateOperatorVersion(op);
+
+    // existing ports are preserved untouched, only the version is refreshed
+    expect(updated.inputPorts).toEqual(existingInputPorts);
+    expect(updated.outputPorts).toEqual(existingOutputPorts);
+    
expect(updated.operatorVersion).toEqual(mockMultiInputOutputSchema.operatorVersion);
+  });
+
+  it("should throw an error when updating the version of an operator with an 
unknown type", () => {
+    const op: OperatorPredicate = {
+      operatorID: "op-3",
+      operatorType: "non-exist-operator-type",
+      operatorVersion: "v1",
+      operatorProperties: {},
+      inputPorts: [],
+      outputPorts: [],
+      showAdvanced: false,
+      isDisabled: false,
+    };
+
+    expect(() => 
workflowUtilService.updateOperatorVersion(op)).toThrowError(new RegExp("doesn't 
exist"));
+  });
+
+  it("should parse the workflow content string into an object", () => {
+    const content: WorkflowContent = {
+      operators: [],
+      operatorPositions: {},
+      links: [],
+      commentBoxes: [],
+      settings: { dataTransferBatchSize: 400, executionMode: 
ExecutionMode.PIPELINED },
+    };
+    const workflow = {
+      name: "test-workflow",
+      description: undefined,
+      wid: 1,
+      creationTime: undefined,
+      lastModifiedTime: undefined,
+      isPublished: 0,
+      readonly: false,
+      content: JSON.stringify(content) as any,
+    } as unknown as Workflow;
+
+    const parsed = WorkflowUtilService.parseWorkflowInfo(workflow);
+
+    // the string content is replaced with the parsed object
+    expect(typeof parsed.content).toEqual("object");
+    expect(parsed.content).toEqual(content);
+  });
+
+  it("should leave workflow content untouched when it is already an object", 
() => {
+    const content: WorkflowContent = {
+      operators: [],
+      operatorPositions: {},
+      links: [],
+      commentBoxes: [],
+      settings: { dataTransferBatchSize: 400, executionMode: 
ExecutionMode.PIPELINED },
+    };
+    const workflow = {
+      name: "test-workflow",
+      description: undefined,
+      wid: 1,
+      creationTime: undefined,
+      lastModifiedTime: undefined,
+      isPublished: 0,
+      readonly: false,
+      content,
+    } as unknown as Workflow;
+
+    const parsed = WorkflowUtilService.parseWorkflowInfo(workflow);
+
+    // an object content is returned as-is
+    expect(parsed.content).toBe(content);
+  });
+
+  it("should create a fresh comment box at the default position", () => {
+    const commentBox = workflowUtilService.getNewCommentBox();
+
+    expect(commentBox.commentBoxID).toMatch(/^commentBox-/);
+    expect(commentBox.comments).toEqual([]);
+    expect(commentBox.commentBoxPosition).toEqual({ x: 500, y: 20 });
+  });
+
+  it("should generate a distinct comment box each time", () => {
+    const first = workflowUtilService.getNewCommentBox();
+    const second = workflowUtilService.getNewCommentBox();
+
+    expect(first.commentBoxID).not.toEqual(second.commentBoxID);
+  });
 });

Reply via email to