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