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-6687-43bd4b01ad1796cc18ee9c7397cc006e88c6993a
in repository https://gitbox.apache.org/repos/asf/texera.git

commit 368227aea6f1c6972d74ae1512dbeb6840b917a2
Author: Matthew B. <[email protected]>
AuthorDate: Tue Jul 21 18:52:03 2026 -0700

    test(frontend): cover mutateProperty (#6687)
    
    ### What changes were proposed in this PR?
    - Add unit tests for the static DynamicSchemaService.mutateProperty
    helper.
    - Cover top-level replacement with an untouched original, recursion
    through properties, definitions, and array items, and the no-match path.
    ### Any related issues, documentation, discussions?
    Closes: #6686
    ### 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/dynamic-schema/dynamic-schema.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
    
    ---------
    
    Signed-off-by: Xinyuan Lin <[email protected]>
    Co-authored-by: Yicong Huang 
<[email protected]>
    Co-authored-by: Xinyuan Lin <[email protected]>
    Co-authored-by: Copilot Autofix powered by AI 
<[email protected]>
---
 .../dynamic-schema/dynamic-schema.service.spec.ts  | 117 +++++++++++++++++++++
 1 file changed, 117 insertions(+)

diff --git 
a/frontend/src/app/workspace/service/dynamic-schema/dynamic-schema.service.spec.ts
 
b/frontend/src/app/workspace/service/dynamic-schema/dynamic-schema.service.spec.ts
index 75dc21193a..e5997027c9 100644
--- 
a/frontend/src/app/workspace/service/dynamic-schema/dynamic-schema.service.spec.ts
+++ 
b/frontend/src/app/workspace/service/dynamic-schema/dynamic-schema.service.spec.ts
@@ -32,6 +32,7 @@ import { OperatorPredicate } from 
"../../types/workflow-common.interface";
 import { mockScanSourceSchema } from 
"../operator-metadata/mock-operator-metadata.data";
 import { WorkflowUtilService } from 
"../workflow-graph/util/workflow-util.service";
 import { commonTestProviders } from "../../../common/testing/test-utils";
+import { CustomJSONSchema7 } from "../../types/custom-json-schema.interface";
 
 describe("DynamicSchemaService", () => {
   beforeEach(() => {
@@ -142,3 +143,119 @@ describe("DynamicSchemaService", () => {
     })
   );
 });
+
+describe("DynamicSchemaService.mutateProperty", () => {
+  const matchByName = (name: string) => (propertyName: string, _: 
CustomJSONSchema7) => propertyName === name;
+  const markMutated = (_: string, propertyValue: CustomJSONSchema7): 
CustomJSONSchema7 => ({
+    ...propertyValue,
+    description: "mutated",
+  });
+
+  it("should replace a matched top-level property without mutating the 
original schema", () => {
+    const original = {
+      type: "object",
+      properties: {
+        target: { type: "string", description: "original" },
+        other: { type: "number" },
+      },
+    } as CustomJSONSchema7;
+
+    const result = DynamicSchemaService.mutateProperty(original, 
matchByName("target"), markMutated);
+
+    // the returned schema has the matched property mutated
+    expect((result.properties!.target as 
CustomJSONSchema7).description).toEqual("mutated");
+    // the non-matching property is left untouched
+    expect(result.properties!.other).toEqual({ type: "number" });
+    // the original schema object is deep cloned and stays unchanged
+    expect((original.properties!.target as 
CustomJSONSchema7).description).toEqual("original");
+    expect(result).not.toBe(original);
+  });
+
+  it("should recurse into nested object properties to find the matched 
property", () => {
+    const original = {
+      type: "object",
+      properties: {
+        nested: {
+          type: "object",
+          properties: {
+            deepTarget: { type: "string", description: "original" },
+          },
+        },
+      },
+    } as CustomJSONSchema7;
+
+    const result = DynamicSchemaService.mutateProperty(original, 
matchByName("deepTarget"), markMutated);
+
+    const nested = result.properties!.nested as CustomJSONSchema7;
+    expect((nested.properties!.deepTarget as 
CustomJSONSchema7).description).toEqual("mutated");
+  });
+
+  it("should recurse into definitions to find the matched property", () => {
+    const original = {
+      type: "object",
+      definitions: {
+        target: { type: "string", description: "original" },
+      },
+    } as CustomJSONSchema7;
+
+    const result = DynamicSchemaService.mutateProperty(original, 
matchByName("target"), markMutated);
+
+    expect((result.definitions!.target as 
CustomJSONSchema7).description).toEqual("mutated");
+  });
+
+  it("should recurse into array items and single-schema items to find the 
matched property", () => {
+    const original = {
+      type: "object",
+      properties: {
+        listTuple: {
+          type: "array",
+          items: [
+            {
+              type: "object",
+              properties: {
+                target: { type: "string", description: "original" },
+              },
+            },
+          ],
+        },
+        listSchema: {
+          type: "array",
+          items: {
+            type: "object",
+            properties: {
+              target: { type: "string", description: "original" },
+            },
+          },
+        },
+      },
+    } as CustomJSONSchema7;
+
+    const result = DynamicSchemaService.mutateProperty(original, 
matchByName("target"), markMutated);
+
+    const listTuple = result.properties!.listTuple as CustomJSONSchema7;
+    const firstItem = (listTuple.items as CustomJSONSchema7[])[0];
+    expect((firstItem.properties!.target as 
CustomJSONSchema7).description).toEqual("mutated");
+
+    const listSchema = result.properties!.listSchema as CustomJSONSchema7;
+    const itemSchema = listSchema.items as CustomJSONSchema7;
+    expect((itemSchema.properties!.target as 
CustomJSONSchema7).description).toEqual("mutated");
+  });
+
+  it("should not invoke the mutation function when nothing matches", () => {
+    const original = {
+      type: "object",
+      properties: {
+        a: { type: "string" },
+        b: { type: "number" },
+      },
+    } as CustomJSONSchema7;
+    const mutationSpy = vi.fn((_: string, value: CustomJSONSchema7) => value);
+
+    const result = DynamicSchemaService.mutateProperty(original, 
matchByName("missing"), mutationSpy);
+
+    expect(mutationSpy).not.toHaveBeenCalled();
+    // with no match the clone is structurally equal to the original
+    expect(result).toEqual(original);
+    expect(result).not.toBe(original);
+  });
+});

Reply via email to