import { expect, describe, it } from "vitest"; import type { AttributesQueryValue, RaqbChild } from "@calcom/lib/raqb/types"; import type { Attribute } from "@calcom/lib/service/attribute/server/getAttributes"; import { AttributeType } from "@calcom/prisma/enums"; import { RoutingFormFieldType } from "@calcom/routing-forms/lib/FieldTypes"; import { resolveQueryValue } from "./resolveQueryValue"; // Test Data Builders for AttributesQueryValue const createQueryValueRule = (overrides?: Partial): RaqbChild => ({ type: "rule", properties: { field: "default-field", operator: "select_equals", value: ["default-value"], valueSrc: ["value"], valueError: [null], valueType: ["select"], }, ...overrides, }); const createAttributesQueryValue = (overrides?: { id?: string; type?: "group" | "switch_group"; children1?: Record; properties?: any; }): AttributesQueryValue => ({ id: overrides?.id || "test-id", type: overrides?.type || "group", children1: overrides?.children1 || {}, properties: overrides?.properties, }); const createQueryValueWithRule = ({ ruleId, field, operator, value, valueSrc = ["value"], valueError = [null], valueType = ["select"], }: { ruleId: string; field: string; operator: string; value: any[]; valueSrc?: string[]; valueError?: (string | null)[]; valueType?: string[]; }): AttributesQueryValue => { return createAttributesQueryValue({ children1: { [ruleId]: createQueryValueRule({ type: "rule", properties: { field, operator, value, valueSrc, valueError, valueType, }, }), }, }); }; const createComplexQueryValue = ({ id, rules, }: { id?: string; rules: Array<{ ruleId: string; field: string; operator: string; value: any[]; valueSrc?: string[]; valueError?: (string | null)[]; valueType?: string[]; }>; }): AttributesQueryValue => { const children1: Record = {}; rules.forEach((rule) => { children1[rule.ruleId] = createQueryValueRule({ type: "rule", properties: { field: rule.field, operator: rule.operator, value: rule.value, valueSrc: rule.valueSrc || ["value"], valueError: rule.valueError || [null], valueType: rule.valueType || ["select"], }, }); }); return createAttributesQueryValue({ id, children1, }); }; const createNestedGroupQueryValue = ({ groups, }: { groups: Array<{ groupId: string; rules: Array<{ ruleId: string; field: string; operator?: string; value: any[]; valueSrc?: string[]; valueError?: (string | null)[]; valueType?: string[]; }>; }>; }): AttributesQueryValue => { const children1: Record = {}; groups.forEach((group) => { const groupChildren: Record = {}; group.rules.forEach((rule) => { groupChildren[rule.ruleId] = createQueryValueRule({ type: "rule", properties: { field: rule.field, operator: rule.operator || "select_equals", value: rule.value, valueSrc: rule.valueSrc || ["value"], valueError: rule.valueError || [null], valueType: rule.valueType || ["select"], }, }); }); children1[group.groupId] = { type: "group", children1: groupChildren, } as RaqbChild; }); return createAttributesQueryValue({ type: "group", children1, }); }; describe("resolveQueryValue", () => { const mockFields = [ { id: "location", type: RoutingFormFieldType.MULTI_SELECT, label: "Location", options: [ { id: "delhi", label: "Delhi" }, { id: "mumbai", label: "Mumbai" }, { id: "paris", label: "Paris" }, { id: "berlin", label: "Berlin" }, { id: "new-york", label: "New York" }, { id: "amsterdam", label: "Amsterdam" }, { id: "haryana", label: "Haryana" }, { id: "tokyo", label: "Tokyo" }, { id: "chennai", label: "Chennai" }, { id: "sao-paulo", label: "São Paulo" }, { id: "zurich", label: "Zürich" }, ], }, { id: "city", type: RoutingFormFieldType.SINGLE_SELECT, label: "City", options: [ { id: "mumbai", label: "Mumbai" }, { id: "delhi", label: "Delhi" }, { id: "chennai", label: "Chennai" }, { id: "tokyo", label: "Tokyo" }, ], }, ]; // Mock attributes for testing const mockAttributes: Attribute[] = [ { id: "attr-1", name: "Location", slug: "location", type: AttributeType.MULTI_SELECT, options: [ { id: "opt-1", value: "New York", slug: "new-york" }, { id: "opt-2", value: "London", slug: "london" }, ], }, { id: "attr-2", name: "City", slug: "city", type: AttributeType.SINGLE_SELECT, options: [ { id: "opt-3", value: "Mumbai", slug: "mumbai" }, { id: "opt-4", value: "Delhi", slug: "delhi" }, ], }, ]; describe("attribute option ID to label conversion for field matching", () => { /** * These tests verify that attribute option IDs are replaced with their lowercase labels * to enable comparison with form field values that are connected through "Value of Field". * Labels are converted to lowercase to ensure case-insensitive matching between * attribute options and field values. */ it("converts single option ID to lowercase label", () => { const queryValue = createQueryValueWithRule({ ruleId: "rule1", field: "attr-1", operator: "select_equals", value: ["opt-1"], }); const result = resolveQueryValue({ queryValue, dynamicFieldValueOperands: undefined, attributes: mockAttributes, }); expect(result).toEqual( expect.objectContaining({ children1: { rule1: { type: "rule", properties: expect.objectContaining({ field: "attr-1", operator: "select_equals", value: ["new york"], // opt-1 -> "New York" -> "new york" for field matching }), }, }, }) ); }); it("converts multiple option IDs to labels in multiselect", () => { const queryValue = createQueryValueWithRule({ ruleId: "rule1", field: "attr-1", operator: "multiselect_some_in", value: [["opt-1", "opt-2", "opt-3", "opt-4"]], valueType: ["multiselect"], }); const result = resolveQueryValue({ queryValue, dynamicFieldValueOperands: undefined, attributes: mockAttributes, }); expect(result).toEqual( expect.objectContaining({ children1: { rule1: { type: "rule", properties: expect.objectContaining({ field: "attr-1", operator: "multiselect_some_in", value: [["new york", "london", "mumbai", "delhi"]], // All IDs converted to lowercase labels }), }, }, }) ); }); it("converts option IDs across multiple rules", () => { const queryValue = createComplexQueryValue({ rules: [ { ruleId: "rule1", field: "attr-1", operator: "select_equals", value: ["opt-1"], }, { ruleId: "rule2", field: "attr-2", operator: "select_equals", value: ["opt-3"], }, ], }); const result = resolveQueryValue({ queryValue, dynamicFieldValueOperands: undefined, attributes: mockAttributes, }); expect(result).toEqual( expect.objectContaining({ children1: { rule1: { type: "rule", properties: expect.objectContaining({ value: ["new york"], // opt-1 converted to label }), }, rule2: { type: "rule", properties: expect.objectContaining({ value: ["mumbai"], // opt-3 converted to label }), }, }, }) ); }); it("converts option IDs before field template resolution", () => { const queryValue = createQueryValueWithRule({ ruleId: "rule1", field: "attr-1", operator: "multiselect_some_in", value: [["opt-1", "{field:location}"]], valueType: ["multiselect"], }); const result = resolveQueryValue({ queryValue, dynamicFieldValueOperands: { fields: mockFields, response: { location: { value: ["Paris"], label: "Paris" }, }, }, attributes: mockAttributes, }); expect(result).toEqual( expect.objectContaining({ children1: { rule1: { type: "rule", properties: expect.objectContaining({ value: [["new york", "paris"]], // Option ID converted first, then field template resolved }), }, }, }) ); }); it("preserves special chars in labels while lowercasing", () => { const specialAttributes: Attribute[] = [ { id: "attr-special", name: "Special", slug: "special", type: AttributeType.SINGLE_SELECT, options: [ { id: "opt-special-1", value: "São Paulo", slug: "sao-paulo" }, { id: "opt-special-2", value: "Zürich", slug: "zurich" }, ], }, ]; const queryValue = createQueryValueWithRule({ ruleId: "rule1", field: "attr-special", operator: "select_equals", value: ["opt-special-1"], }); const result = resolveQueryValue({ queryValue, dynamicFieldValueOperands: undefined, attributes: specialAttributes, }); expect(result).toEqual( expect.objectContaining({ children1: { rule1: { type: "rule", properties: expect.objectContaining({ value: ["são paulo"], // Special chars preserved, only case changed for matching }), }, }, }) ); }); it("keeps non-matching IDs unchanged", () => { const queryValue = createQueryValueWithRule({ ruleId: "rule1", field: "attr-1", operator: "select_equals", value: ["non-existent-id", "opt-1"], }); const result = resolveQueryValue({ queryValue, dynamicFieldValueOperands: undefined, attributes: mockAttributes, }); expect(result).toEqual( expect.objectContaining({ children1: { rule1: { type: "rule", properties: expect.objectContaining({ value: ["non-existent-id", "new york"], // Unknown IDs kept, valid ones converted }), }, }, }) ); }); it("handles missing attributes gracefully", () => { const queryValue = createQueryValueWithRule({ ruleId: "rule1", field: "attr-1", operator: "select_equals", value: ["opt-1"], }); const result = resolveQueryValue({ queryValue, dynamicFieldValueOperands: undefined, attributes: [], // No attributes }); expect(result).toEqual( expect.objectContaining({ children1: { rule1: { type: "rule", properties: expect.objectContaining({ value: ["opt-1"], // No attributes to resolve against }), }, }, }) ); }); it("handles attributes without options", () => { const attributesWithoutOptions: Attribute[] = [ { id: "attr-no-options", name: "No Options", slug: "no-options", type: AttributeType.TEXT, options: [], // Empty options array }, ]; const queryValue = createQueryValueWithRule({ ruleId: "rule1", field: "attr-no-options", operator: "text_equals", value: ["some-value"], }); const result = resolveQueryValue({ queryValue, dynamicFieldValueOperands: undefined, attributes: attributesWithoutOptions, }); expect(result).toEqual( expect.objectContaining({ children1: { rule1: { type: "rule", properties: expect.objectContaining({ value: ["some-value"], // TEXT attributes don't have options to convert }), }, }, }) ); }); it("converts IDs in nested group structures", () => { const queryValue = createNestedGroupQueryValue({ groups: [ { groupId: "group1", rules: [ { ruleId: "rule1", field: "attr-1", operator: "multiselect_some_in", value: [["opt-1", "opt-2"]], valueType: ["multiselect"], }, { ruleId: "rule2", field: "attr-2", operator: "select_equals", value: ["opt-3"], }, ], }, ], }); const result = resolveQueryValue({ queryValue, dynamicFieldValueOperands: undefined, attributes: mockAttributes, }); expect(result).toEqual( expect.objectContaining({ children1: { group1: { type: "group", children1: { rule1: { type: "rule", properties: expect.objectContaining({ value: [["new york", "london"]], // opt-1, opt-2 converted to labels }), }, rule2: { type: "rule", properties: expect.objectContaining({ value: ["mumbai"], // opt-3 converted to label }), }, }, }, }, }) ); }); it("converts IDs alongside field templates in arrays", () => { const queryValue = createQueryValueWithRule({ ruleId: "rule1", field: "attr-1", operator: "multiselect_some_in", value: [["opt-1", "{field:city}", "opt-2", "{field:location}"]], valueType: ["multiselect"], }); const result = resolveQueryValue({ queryValue, dynamicFieldValueOperands: { fields: mockFields, response: { city: { value: "Tokyo", label: "Tokyo" }, location: { value: ["Berlin", "Paris"], label: "Berlin, Paris" }, }, }, attributes: mockAttributes, }); expect(result).toEqual( expect.objectContaining({ children1: { rule1: { type: "rule", properties: expect.objectContaining({ value: [["new york", "tokyo", "london", "berlin", "paris"]], // opt-1->"new york", opt-2->"london", field templates resolved }), }, }, }) ); }); }); it("should handle simple field template replacement with single value", () => { const queryValue = createQueryValueWithRule({ ruleId: "a8a89bba", field: "city", operator: "select_equals", value: ["{field:city}"], }); const result = resolveQueryValue({ queryValue, dynamicFieldValueOperands: { fields: mockFields, response: { city: { label: "Mumbai", value: "Mumbai" }, }, }, attributes: mockAttributes, }); expect(result).toEqual( expect.objectContaining({ children1: { a8a89bba: { type: "rule", properties: expect.objectContaining({ field: "city", operator: "select_equals", value: ["mumbai"], }), }, }, }) ); }); it("should handle field template in double-nested array for multiselect", () => { const queryValue = createQueryValueWithRule({ ruleId: "rule1", field: "location", operator: "multiselect_some_in", value: [["{field:location}"]], valueType: ["multiselect"], }); const result = resolveQueryValue({ queryValue, dynamicFieldValueOperands: { fields: mockFields, response: { location: { label: "Delhi", value: "Delhi" }, }, }, attributes: mockAttributes, }); expect(result).toEqual( expect.objectContaining({ children1: { rule1: { type: "rule", properties: expect.objectContaining({ field: "location", operator: "multiselect_some_in", value: [["delhi"]], }), }, }, }) ); }); it("should handle mixed array with field template and regular values", () => { const queryValue = { children1: { rule1: { type: "rule", properties: { field: "location", operator: "multiselect_some_in", value: [["{field:location}", "Chennai"]], }, }, }, } as unknown as AttributesQueryValue; const result = resolveQueryValue({ queryValue, dynamicFieldValueOperands: { fields: mockFields, response: { location: { value: "Delhi", label: "Delhi" }, // Single value, not array }, }, attributes: mockAttributes, }); expect(result).toEqual( expect.objectContaining({ children1: { rule1: { type: "rule", properties: { field: "location", operator: "multiselect_some_in", value: [["delhi", "Chennai"]], // Single value replaced }, }, }, }) ); }); it("should handle multiple field templates in the same array", () => { const queryValue = { children1: { rule1: { type: "rule", properties: { field: "multifield", operator: "multiselect_some_in", value: [["{field:location}", "{field:city}"]], }, }, }, } as unknown as AttributesQueryValue; const result = resolveQueryValue({ queryValue, dynamicFieldValueOperands: { fields: mockFields, response: { location: { value: ["Delhi"], label: "Delhi" }, city: { value: "Mumbai", label: "Mumbai" }, }, }, attributes: mockAttributes, }); expect(result).toEqual( expect.objectContaining({ children1: { rule1: { type: "rule", properties: { field: "multifield", operator: "multiselect_some_in", value: [["delhi", "mumbai"]], }, }, }, }) ); }); it("should handle field template with no response value", () => { const queryValue = { children1: { rule1: { type: "rule", properties: { field: "location", operator: "select_equals", value: ["{field:location}"], }, }, }, } as unknown as AttributesQueryValue; const result = resolveQueryValue({ queryValue, dynamicFieldValueOperands: { fields: mockFields, response: {}, // No response for location field }, attributes: mockAttributes, }); expect(result).toEqual( expect.objectContaining({ children1: { rule1: { type: "rule", properties: { field: "location", operator: "select_equals", value: ["{field:location}"], // Should remain unchanged }, }, }, }) ); }); it("should handle field template with unknown field", () => { const queryValue = { children1: { rule1: { type: "rule", properties: { field: "unknown", operator: "select_equals", value: ["{field:unknown}"], }, }, }, } as unknown as AttributesQueryValue; const result = resolveQueryValue({ queryValue, dynamicFieldValueOperands: { fields: mockFields, response: { unknown: { value: "test", label: "test" }, }, }, attributes: mockAttributes, }); expect(result).toEqual( expect.objectContaining({ children1: { rule1: { type: "rule", properties: { field: "unknown", operator: "select_equals", value: ["{field:unknown}"], // Should remain unchanged }, }, }, }) ); }); it("should handle complex nested structure", () => { const queryValue = createAttributesQueryValue({ id: "test", type: "group", children1: { rule1: createQueryValueRule({ type: "rule", properties: { field: "attr1", operator: "multiselect_some_in", value: [["{field:location}", "Fixed-Value"]], valueType: ["multiselect"], }, }), }, }); const result = resolveQueryValue({ queryValue, dynamicFieldValueOperands: { fields: mockFields, response: { location: { value: ["Delhi", "Haryana"], label: "Delhi, Haryana" }, }, }, attributes: mockAttributes, }); expect(result).toEqual( expect.objectContaining({ id: "test", type: "group", children1: { rule1: { type: "rule", properties: expect.objectContaining({ field: "attr1", value: [["delhi", "haryana", "Fixed-Value"]], operator: "multiselect_some_in", }), }, }, }) ); }); it("should handle empty array values", () => { const queryValue = { children1: { rule1: { type: "rule", properties: { field: "location", operator: "multiselect_some_in", value: [["{field:location}"]], }, }, }, } as unknown as AttributesQueryValue; const result = resolveQueryValue({ queryValue, dynamicFieldValueOperands: { fields: mockFields, response: { location: { value: [], label: "" }, // Empty array }, }, attributes: mockAttributes, }); expect(result).toEqual( expect.objectContaining({ children1: { rule1: { type: "rule", properties: { field: "location", operator: "multiselect_some_in", value: [[]], // Should be empty array }, }, }, }) ); }); it("should handle no dynamicFieldValueOperands", () => { const queryValue = { children1: { rule1: { type: "rule", properties: { field: "location", value: ["{field:location}"], }, }, }, } as unknown as AttributesQueryValue; const result = resolveQueryValue({ queryValue, dynamicFieldValueOperands: undefined, attributes: mockAttributes, }); expect(result).toEqual(queryValue); // Should return unchanged }); it("should preserve case for non-template values in mixed arrays", () => { const queryValue = { children1: { rule1: { type: "rule", properties: { field: "location", operator: "multiselect_some_in", value: [["{field:location}", "Chennai", "MUMBAI"]], }, }, }, } as unknown as AttributesQueryValue; const result = resolveQueryValue({ queryValue, dynamicFieldValueOperands: { fields: mockFields, response: { location: { value: ["Delhi"], label: "Delhi" }, }, }, attributes: mockAttributes, }); expect(result).toEqual( expect.objectContaining({ children1: { rule1: { type: "rule", properties: { field: "location", operator: "multiselect_some_in", value: [["delhi", "Chennai", "MUMBAI"]], // Only field template value is lowercased }, }, }, }) ); }); it("should handle deeply nested field templates", () => { const queryValue = createNestedGroupQueryValue({ groups: [ { groupId: "group1", rules: [ { ruleId: "rule1", field: "location", value: [["{field:location}", "Fixed1"]], valueType: ["multiselect"], }, { ruleId: "rule2", field: "city", value: [["{field:city}", "Fixed2"]], valueType: ["multiselect"], }, ], }, ], }); const result = resolveQueryValue({ queryValue, dynamicFieldValueOperands: { fields: mockFields, response: { location: { value: ["Delhi", "Mumbai"], label: "Delhi, Mumbai" }, city: { value: "Chennai", label: "Chennai" }, }, }, attributes: mockAttributes, }); expect(result).toEqual( expect.objectContaining({ type: "group", children1: { group1: { type: "group", children1: { rule1: { type: "rule", properties: expect.objectContaining({ field: "location", value: [["delhi", "mumbai", "Fixed1"]], }), }, rule2: { type: "rule", properties: expect.objectContaining({ field: "city", value: [["chennai", "Fixed2"]], }), }, }, }, }, }) ); }); it("should handle field template with array containing special characters", () => { const queryValue = { children1: { rule1: { type: "rule", properties: { field: "location", value: [["{field:location}"]], }, }, }, } as unknown as AttributesQueryValue; const result = resolveQueryValue({ queryValue, dynamicFieldValueOperands: { fields: mockFields, response: { location: { value: ["New York", "São Paulo", "Zürich"], label: "New York, São Paulo, Zürich" }, }, }, attributes: mockAttributes, }); expect(result).toEqual( expect.objectContaining({ children1: { rule1: { type: "rule", properties: { field: "location", value: [["new york", "são paulo", "zürich"]], }, }, }, }) ); }); it("should handle null and undefined values gracefully", () => { const queryValue = { children1: { rule1: { type: "rule", properties: { field: "mixed", value: [["{field:location}", null, "{field:city}"]], }, }, }, } as unknown as AttributesQueryValue; const result = resolveQueryValue({ queryValue, dynamicFieldValueOperands: { fields: mockFields, response: { location: { value: ["Delhi"], label: "Delhi" }, city: { value: null as any, label: "" }, // null value }, }, attributes: mockAttributes, }); expect(result).toEqual( expect.objectContaining({ children1: { rule1: { type: "rule", properties: { field: "mixed", value: [["delhi", null, "{field:city}"]], // city remains as template due to null value }, }, }, }) ); }); it("should handle numeric values from fields", () => { const numericFields = [ { id: "age", type: RoutingFormFieldType.NUMBER, label: "Age", options: [] }, { id: "count", type: RoutingFormFieldType.NUMBER, label: "Count", options: [] }, ]; const queryValue = { children1: { rule1: { type: "rule", properties: { field: "numbers", value: [["{field:age}", "{field:count}", 42]], }, }, }, } as unknown as AttributesQueryValue; const result = resolveQueryValue({ queryValue, dynamicFieldValueOperands: { fields: numericFields, response: { age: { value: 25, label: "25" }, count: { value: 100, label: "100" }, }, }, attributes: mockAttributes, }); expect(result).toEqual( expect.objectContaining({ children1: { rule1: { type: "rule", properties: { field: "numbers", value: [["25", "100", 42]], }, }, }, }) ); }); it("should handle very large arrays efficiently", () => { const largeArray = new Array(100).fill("item"); const queryValue = { children1: { rule1: { type: "rule", properties: { field: "location", value: [["{field:location}", ...largeArray]], }, }, }, } as unknown as AttributesQueryValue; const result = resolveQueryValue({ queryValue, dynamicFieldValueOperands: { fields: mockFields, response: { location: { value: ["Delhi", "Mumbai"], label: "Delhi, Mumbai" }, }, }, attributes: mockAttributes, }); expect(result.children1?.rule1.properties?.value[0]).toHaveLength(102); // 2 from field + 100 items expect(result.children1?.rule1.properties?.value[0].slice(0, 2)).toEqual(["delhi", "mumbai"]); }); it("should handle edge case with empty string field values", () => { const queryValue = { children1: { rule1: { type: "rule", properties: { field: "location", value: [["{field:location}"]], }, }, }, } as unknown as AttributesQueryValue; const result = resolveQueryValue({ queryValue, dynamicFieldValueOperands: { fields: mockFields, response: { location: { value: ["", " ", "Delhi"], label: ", , Delhi" }, // Empty and whitespace strings }, }, attributes: mockAttributes, }); expect(result).toEqual( expect.objectContaining({ children1: { rule1: { type: "rule", properties: { field: "location", value: [["", " ", "delhi"]], }, }, }, }) ); }); it("should handle field templates with hyphens and underscores in field names", () => { const specialFields = [ { id: "field-with-dashes", type: RoutingFormFieldType.TEXT, label: "Dashed Field", options: [] }, { id: "field_with_underscores", type: RoutingFormFieldType.TEXT, label: "Underscored Field", options: [], }, ]; const queryValue = { children1: { rule1: { type: "rule", properties: { field: "special", value: ["{field:field-with-dashes}", "{field:field_with_underscores}"], }, }, }, } as unknown as AttributesQueryValue; const result = resolveQueryValue({ queryValue, dynamicFieldValueOperands: { fields: specialFields, response: { "field-with-dashes": { value: "Value2", label: "Value2" }, field_with_underscores: { value: "Value3", label: "Value3" }, }, }, attributes: mockAttributes, }); expect(result).toEqual( expect.objectContaining({ children1: { rule1: { type: "rule", properties: { field: "special", value: ["value2", "value3"], }, }, }, }) ); }); it("should handle field templates in different JSON value types", () => { const queryValue = { children1: { rule1: { type: "rule", properties: { field: "city", value: "{field:city}", }, }, rule2: { type: "rule", properties: { field: "city", value: ["{field:city}"], }, }, rule3: { type: "rule", properties: { field: "location", value: [["{field:location}"]], }, }, rule4: { type: "rule", properties: { field: "mixed", customProp: "{field:city}", nested: { value: ["{field:location}"], }, }, }, }, } as unknown as AttributesQueryValue; const result = resolveQueryValue({ queryValue, dynamicFieldValueOperands: { fields: mockFields, response: { location: { value: ["Delhi", "Mumbai"], label: "Delhi, Mumbai" }, city: { value: "Chennai", label: "Chennai" }, }, }, attributes: mockAttributes, }); expect(result).toEqual( expect.objectContaining({ children1: { rule1: { type: "rule", properties: { field: "city", value: "chennai", }, }, rule2: { type: "rule", properties: { field: "city", value: ["chennai"], }, }, rule3: { type: "rule", properties: { field: "location", value: [["delhi", "mumbai"]], }, }, rule4: { type: "rule", properties: { field: "mixed", customProp: "chennai", nested: { value: ["delhi", "mumbai"], }, }, }, }, }) ); }); it("should handle empty response object", () => { const queryValue = { children1: { rule1: { type: "rule", properties: { field: "location", value: [["{field:location}", "Fixed"]], }, }, }, } as unknown as AttributesQueryValue; const result = resolveQueryValue({ queryValue, dynamicFieldValueOperands: { fields: mockFields, response: {}, // Empty response }, attributes: mockAttributes, }); expect(result).toEqual( expect.objectContaining({ children1: { rule1: { type: "rule", properties: { field: "location", value: [["{field:location}", "Fixed"]], // Template unchanged }, }, }, }) ); }); it("should handle response with empty field value object", () => { const queryValue = { children1: { rule1: { type: "rule", properties: { field: "location", value: [["{field:location}"]], }, }, }, } as unknown as AttributesQueryValue; const result = resolveQueryValue({ queryValue, dynamicFieldValueOperands: { fields: mockFields, response: { location: {} as any, // Empty object, no value property }, }, attributes: mockAttributes, }); expect(result).toEqual( expect.objectContaining({ children1: { rule1: { type: "rule", properties: { field: "location", value: [["{field:location}"]], // Template unchanged }, }, }, }) ); }); it("should handle multiple occurrences of the same field template", () => { const queryValue = { children1: { rule1: { type: "rule", properties: { field: "city", value: ["{field:city}"], }, }, rule2: { type: "rule", properties: { field: "city", value: ["{field:city}"], }, }, rule3: { type: "rule", properties: { field: "city", value: [["{field:city}", "{field:city}"]], }, }, }, } as unknown as AttributesQueryValue; const result = resolveQueryValue({ queryValue, dynamicFieldValueOperands: { fields: mockFields, response: { city: { value: "Mumbai", label: "Mumbai" }, }, }, attributes: mockAttributes, }); expect(result).toEqual( expect.objectContaining({ children1: { rule1: { type: "rule", properties: { field: "city", value: ["mumbai"], }, }, rule2: { type: "rule", properties: { field: "city", value: ["mumbai"], }, }, rule3: { type: "rule", properties: { field: "city", value: [["mumbai", "mumbai"]], }, }, }, }) ); }); it("should handle invalid query structure gracefully", () => { // Test with an invalid query structure const invalidQueryValue = null as unknown as AttributesQueryValue; const result = resolveQueryValue({ queryValue: invalidQueryValue, dynamicFieldValueOperands: { fields: mockFields, response: { city: { value: "Mumbai", label: "Mumbai" }, }, }, attributes: mockAttributes, }); expect(result).toBeNull(); }); it("should handle valid JSON that causes processing errors gracefully", () => { const queryValue = { children1: { rule1: { type: "rule", properties: { field: "nonexistent", value: ["{field:nonexistent}"], }, }, rule2: { type: "rule", properties: { field: "city", customField: "{field:city}", }, }, }, } as unknown as AttributesQueryValue; const result = resolveQueryValue({ queryValue, dynamicFieldValueOperands: { fields: mockFields, response: { city: { value: "Mumbai", label: "Mumbai" }, }, }, attributes: mockAttributes, }); // Non-existent field should remain as-is, existing field should be resolved expect(result).toEqual( expect.objectContaining({ children1: { rule1: { type: "rule", properties: { field: "nonexistent", value: ["{field:nonexistent}"], }, }, rule2: { type: "rule", properties: { field: "city", customField: "mumbai", }, }, }, }) ); }); it("should handle field templates in deeply nested object structures", () => { const queryValue = { children1: { rule1: { type: "rule", properties: { field: "complex", metadata: { level1: { value: "{field:city}", level2: { items: ["{field:location}"], level3: { nested: [["{field:city}"]], static: "preserved", }, }, }, }, value: ["test"], }, }, }, } as unknown as AttributesQueryValue; const result = resolveQueryValue({ queryValue, dynamicFieldValueOperands: { fields: mockFields, response: { city: { value: "Mumbai", label: "Mumbai" }, location: { value: ["Delhi", "Chennai"], label: "Delhi, Chennai" }, }, }, attributes: mockAttributes, }); // Verify all nested properties are preserved with templates resolved const props = result.children1?.rule1.properties as any; expect(props.metadata.level1.level2.level3.static).toBe("preserved"); expect(props.metadata.level1.value).toBe("mumbai"); expect(props.metadata.level1.level2.items).toEqual(["delhi", "chennai"]); expect(props.metadata.level1.level2.level3.nested).toEqual([["mumbai"]]); expect(props.value).toEqual(["test"]); }); it("should handle extremely deep object nesting without stack overflow", () => { let deepObj: any = { value: "{field:city}" }; for (let i = 0; i < 100; i++) { deepObj = { nested: deepObj, level: i }; } const queryValue = { children1: { rule1: { type: "rule", properties: deepObj, }, }, } as unknown as AttributesQueryValue; const result = resolveQueryValue({ queryValue, dynamicFieldValueOperands: { fields: mockFields, response: { city: { value: "Mumbai", label: "Mumbai" }, }, }, attributes: mockAttributes, }); // Navigate to deepest level to verify it was processed let current = result.children1?.rule1.properties as any; for (let i = 99; i >= 0; i--) { expect(current.level).toBe(i); current = current.nested; } expect(current.value).toBe("mumbai"); }); it("should preserve all JavaScript primitive types in nested structures", () => { const queryValue = { children1: { rule1: { type: "rule", properties: { stringField: "{field:city}", numberField: 42, bigintField: 9007199254740991, booleanField: true, nullField: null, nested: { array: ["{field:location}", 123, false, null], decimal: 3.14159, negative: -100, zero: 0, emptyString: "", specialChars: "!@#$%^&*()", }, }, }, }, } as unknown as AttributesQueryValue; const result = resolveQueryValue({ queryValue, dynamicFieldValueOperands: { fields: mockFields, response: { city: { value: "Mumbai", label: "Mumbai" }, location: { value: ["Delhi"], label: "Delhi" }, }, }, attributes: mockAttributes, }); const props = result.children1?.rule1.properties as any; expect(props.stringField).toBe("mumbai"); expect(props.numberField).toBe(42); expect(props.bigintField).toBe(9007199254740991); expect(props.booleanField).toBe(true); expect(props.nullField).toBeNull(); expect(props.nested.array).toEqual(["delhi", 123, false, null]); expect(props.nested.decimal).toBe(3.14159); expect(props.nested.negative).toBe(-100); expect(props.nested.zero).toBe(0); expect(props.nested.emptyString).toBe(""); expect(props.nested.specialChars).toBe("!@#$%^&*()"); }); it("should process field templates within objects inside arrays", () => { const queryValue = { children1: { rule1: { type: "rule", properties: { value: [ { id: 1, city: "{field:city}" }, { id: 2, locations: ["{field:location}"] }, { id: 3, nested: { value: [["{field:city}"]] } }, ], }, }, }, } as unknown as AttributesQueryValue; const result = resolveQueryValue({ queryValue, dynamicFieldValueOperands: { fields: mockFields, response: { city: { value: "Mumbai", label: "Mumbai" }, location: { value: ["Delhi", "Chennai"], label: "Delhi, Chennai" }, }, }, attributes: mockAttributes, }); const props = result.children1?.rule1.properties as any; expect(props.value[0]).toEqual({ id: 1, city: "mumbai" }); expect(props.value[1]).toEqual({ id: 2, locations: ["delhi", "chennai"], }); expect(props.value[2]).toEqual({ id: 3, nested: { value: [["mumbai"]] }, }); }); });