From 8bb6b164d51b101aedfff87eedeb5928c1c502da Mon Sep 17 00:00:00 2001 From: Matthew Ball Date: Mon, 20 Jul 2026 20:28:42 -0700 Subject: [PATCH 1/2] test(frontend): cover isSink and isPythonUdf helpers --- .../model/workflow-graph.spec.ts | 84 ++++++++++++++++++- 1 file changed, 82 insertions(+), 2 deletions(-) diff --git a/frontend/src/app/workspace/service/workflow-graph/model/workflow-graph.spec.ts b/frontend/src/app/workspace/service/workflow-graph/model/workflow-graph.spec.ts index 2e1e6b2ef2a..e3227ee5952 100644 --- a/frontend/src/app/workspace/service/workflow-graph/model/workflow-graph.spec.ts +++ b/frontend/src/app/workspace/service/workflow-graph/model/workflow-graph.spec.ts @@ -27,9 +27,23 @@ import { mockSentimentPredicate, mockSentimentResultLink, } from "./mock-workflow-data"; -import { WorkflowGraph } from "./workflow-graph"; +import { + DUAL_INPUT_PORTS_PYTHON_UDF_V2_OP_TYPE, + isPythonUdf, + isSink, + PYTHON_UDF_SOURCE_V2_OP_TYPE, + PYTHON_UDF_V2_OP_TYPE, + VIEW_RESULT_OP_TYPE, + WorkflowGraph, +} from "./workflow-graph"; import { Observable } from "rxjs"; -import { Comment, OperatorLink, PortDescription, PortProperty } from "../../../types/workflow-common.interface"; +import { + Comment, + OperatorLink, + OperatorPredicate, + PortDescription, + PortProperty, +} from "../../../types/workflow-common.interface"; describe("WorkflowGraph", () => { let workflowGraph: WorkflowGraph; @@ -815,4 +829,70 @@ describe("WorkflowGraph", () => { sub.unsubscribe(); }); }); + + describe("isSink", () => { + const makeOperator = (operatorType: string): OperatorPredicate => ({ + operatorID: "op", + operatorType, + operatorVersion: "v", + operatorProperties: {}, + inputPorts: [], + outputPorts: [], + showAdvanced: true, + isDisabled: false, + }); + + it("should return true for the view-result sink operator type", () => { + expect(isSink(makeOperator(VIEW_RESULT_OP_TYPE))).toBe(true); + }); + + it("should return true whenever the operator type contains 'sink' as a substring", () => { + expect(isSink(makeOperator("CsvFileSink"))).toBe(true); + expect(isSink(makeOperator("SinkOperator"))).toBe(true); + }); + + it("should match case-insensitively", () => { + expect(isSink(makeOperator("SINK"))).toBe(true); + expect(isSink(makeOperator("SiNk"))).toBe(true); + expect(isSink(makeOperator("mySINKop"))).toBe(true); + }); + + it("should return false for operator types that do not contain 'sink'", () => { + expect(isSink(makeOperator("ScanSource"))).toBe(false); + expect(isSink(makeOperator("NlpSentiment"))).toBe(false); + expect(isSink(makeOperator(""))).toBe(false); + }); + }); + + describe("isPythonUdf", () => { + const makeOperator = (operatorType: string): OperatorPredicate => ({ + operatorID: "op", + operatorType, + operatorVersion: "v", + operatorProperties: {}, + inputPorts: [], + outputPorts: [], + showAdvanced: true, + isDisabled: false, + }); + + it("should return true for the single-input Python UDF v2 type", () => { + expect(isPythonUdf(makeOperator(PYTHON_UDF_V2_OP_TYPE))).toBe(true); + }); + + it("should return true for the Python UDF source v2 type", () => { + expect(isPythonUdf(makeOperator(PYTHON_UDF_SOURCE_V2_OP_TYPE))).toBe(true); + }); + + it("should return true for the dual-input-ports Python UDF v2 type", () => { + expect(isPythonUdf(makeOperator(DUAL_INPUT_PORTS_PYTHON_UDF_V2_OP_TYPE))).toBe(true); + }); + + it("should return false for operator types outside the Python UDF list", () => { + expect(isPythonUdf(makeOperator("JavaUDF"))).toBe(false); + expect(isPythonUdf(makeOperator("ScanSource"))).toBe(false); + // membership is exact and case-sensitive, so a differently-cased variant must not match + expect(isPythonUdf(makeOperator(PYTHON_UDF_V2_OP_TYPE.toLowerCase()))).toBe(false); + }); + }); }); From 5b95cccf18335d78aacd12e62cea8a9acfdb34ea Mon Sep 17 00:00:00 2001 From: Matthew Ball Date: Tue, 21 Jul 2026 19:52:57 -0700 Subject: [PATCH 2/2] test: address review comments Co-Authored-By: Claude Opus 4.8 --- .../workspace/service/workflow-graph/model/workflow-graph.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/app/workspace/service/workflow-graph/model/workflow-graph.ts b/frontend/src/app/workspace/service/workflow-graph/model/workflow-graph.ts index 4d4bb93edeb..f7c86a66788 100644 --- a/frontend/src/app/workspace/service/workflow-graph/model/workflow-graph.ts +++ b/frontend/src/app/workspace/service/workflow-graph/model/workflow-graph.ts @@ -78,7 +78,7 @@ export const VIEW_RESULT_OP_TYPE = "SimpleSink"; export const VIEW_RESULT_OP_NAME = "View Results"; export function isSink(operator: OperatorPredicate): boolean { - return operator.operatorType.toLocaleLowerCase().includes("sink"); + return operator.operatorType.toLowerCase().includes("sink"); } export function isPythonUdf(operator: OperatorPredicate): boolean {