diff --git a/src/__tests__/context.test.js b/src/__tests__/context.test.js index 0f62dee..61f41fc 100644 --- a/src/__tests__/context.test.js +++ b/src/__tests__/context.test.js @@ -3560,4 +3560,74 @@ describe("Context", () => { ]); }); }); + + describe("customFieldValue()", () => { + it("should return custom field value", () => { + const context = new Context(sdk, contextOptions, contextParams, getContextResponse); + expect(context.pending()).toEqual(0); + const value = context.customFieldValue("exp_test_custom_fields", "country"); + + expect(context.isReady()).toEqual(true); + expect(value).toEqual("US,PT,ES"); + }); + + it("should return parsed JSON fields", () => { + const context = new Context(sdk, contextOptions, contextParams, getContextResponse); + expect(context.pending()).toEqual(0); + + expect(context.customFieldValue("exp_test_abc", "json_object")).toEqual({ 123: 1, 456: 0 }); + expect(context.customFieldValue("exp_test_abc", "json_array")).toEqual(["hello", "world"]); + expect(context.customFieldValue("exp_test_abc", "json_number")).toEqual(123); + expect(context.customFieldValue("exp_test_abc", "json_string")).toEqual("hello"); + expect(context.customFieldValue("exp_test_abc", "json_boolean")).toEqual(true); + expect(context.customFieldValue("exp_test_abc", "json_null")).toEqual(null); + }); + + it("should return string and text fields", () => { + const context = new Context(sdk, contextOptions, contextParams, getContextResponse); + expect(context.pending()).toEqual(0); + + expect(context.customFieldValue("exp_test_custom_fields", "text_field")).toEqual("hello text"); + expect(context.customFieldValue("exp_test_custom_fields", "string_field")).toEqual("hello string"); + }); + + it("should return parsed number fields", () => { + const context = new Context(sdk, contextOptions, contextParams, getContextResponse); + expect(context.pending()).toEqual(0); + + expect(context.customFieldValue("exp_test_custom_fields", "number_field")).toEqual(123); + }); + + it("should return parsed boolean fields", () => { + const context = new Context(sdk, contextOptions, contextParams, getContextResponse); + expect(context.pending()).toEqual(0); + + expect(context.customFieldValue("exp_test_custom_fields", "boolean_field")).toEqual(true); + expect(context.customFieldValue("exp_test_custom_fields", "false_boolean_field")).toEqual(false); + }); + + it("should console an error when JSON cannot be parsed", () => { + const errorSpy = jest.spyOn(console, "error"); + const context = new Context(sdk, contextOptions, contextParams, getContextResponse); + expect(context.pending()).toEqual(0); + + expect(context.customFieldValue("exp_test_abc", "json_invalid")).toEqual(null); + expect(errorSpy).toHaveBeenCalledTimes(1); + expect(errorSpy).toHaveBeenCalledWith( + "Failed to parse JSON custom field value 'json_invalid' for experiment 'exp_test_abc'" + ); + }); + + it("should console an error when a field type is invalid", () => { + const errorSpy = jest.spyOn(console, "error"); + const context = new Context(sdk, contextOptions, contextParams, getContextResponse); + expect(context.pending()).toEqual(0); + + expect(context.customFieldValue("exp_test_custom_fields", "invalid_type_field")).toEqual(null); + expect(errorSpy).toHaveBeenCalledTimes(1); + expect(errorSpy).toHaveBeenCalledWith( + "Unknown custom field type 'invalid' for experiment 'exp_test_custom_fields' and key 'invalid_type_field'" + ); + }); + }); }); diff --git a/src/context.ts b/src/context.ts index d45269c..d34bfea 100644 --- a/src/context.ts +++ b/src/context.ts @@ -634,6 +634,47 @@ export default class Context { return this._customFieldKeys(); } + private _customFieldValue(experimentName: string, key: string): JSONValue { + const experiment = this._index[experimentName]; + + if (experiment != null) { + const field = experiment.data.customFieldValues?.find((x) => x.name === key); + if (field != null) { + switch (field.type) { + case "text": + case "string": + return field.value; + case "number": + return Number(field.value); + case "json": + try { + if (field.value === "null") return null; + if (field.value === "") return ""; + return JSON.parse(field.value); + } catch (e) { + console.error(`Failed to parse JSON custom field value '${key}' for experiment '${experimentName}'`); + return null; + } + case "boolean": + return field.value === "true"; + default: + console.error( + `Unknown custom field type '${field.type}' for experiment '${experimentName}' and key '${key}' - you may need to upgrade to the latest SDK version` + ); + return null; + } + } + } + + return null; + } + + customFieldValue(experimentName: string, key: string) { + this._checkReady(true); + + return this._customFieldValue(experimentName, key); + } + private _variableValue(key: string, defaultValue: string): string { for (const i in this._indexVariables[key]) { const experimentName = this._indexVariables[key][i].data.name;