From e429e5a1c8c7720aced52dbf1f41962a6f771eea Mon Sep 17 00:00:00 2001 From: pipopotamasu Date: Tue, 18 Mar 2025 10:06:05 -0400 Subject: [PATCH] feat(feature option): new feature option to navigate to Labs or Catalog page for platform feature Added a new feature option 'entrypoint' which enables a user to choose which page they want to land on . Currently, they can choose 'labs' or 'catalog' for this option which navigates them to Labs page or Catalog page. This option is available when they use 'platform' feature. --- .eslintrc.js | 2 +- src/feature/featureType.ts | 11 ++- src/feature/featureUtil.spec.ts | 116 +++++++++++++++++++++++++------- src/feature/featureUtil.ts | 18 ++++- 4 files changed, 119 insertions(+), 28 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index 4801049..dc443ad 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -26,7 +26,7 @@ module.exports = { "@typescript-eslint/ban-ts-comment": "off", "@typescript-eslint/explicit-function-return-type": "off", "@typescript-eslint/explicit-module-boundary-types": "error", - "@typescript-eslint/no-unused-vars": "error", + "@typescript-eslint/no-unused-vars": ["error", { varsIgnorePattern: "^_" }], "@typescript-eslint/no-use-before-define": "error", "@typescript-eslint/no-var-requires": "error", "@typescript-eslint/prefer-for-of": "error", diff --git a/src/feature/featureType.ts b/src/feature/featureType.ts index 80ae77d..c03598d 100644 --- a/src/feature/featureType.ts +++ b/src/feature/featureType.ts @@ -5,6 +5,10 @@ const FEATURE_TYPES = { platform: "platform", }; +type Entrypoint = "catalog" | "labs"; + +const ENTRYPOINTS: Entrypoint[] = ["catalog", "labs"]; + type FeatureType = keyof typeof FEATURE_TYPES; type PatientOptions = { @@ -19,9 +23,12 @@ type PatientOptions = { discount?: number; }; type TreatmentPlanOptions = { patient?: PatientOptions; secretToken: string }; +type PlatformOptions = TreatmentPlanOptions & { entrypoint?: Entrypoint }; -type FeatureOptions = F extends "treatmentPlan" | "platform" +type FeatureOptions = F extends "treatmentPlan" ? TreatmentPlanOptions + : F extends "platform" + ? PlatformOptions : Record; interface Feature { @@ -34,8 +41,10 @@ interface Feature { export { FeatureType, FeatureOptions, + PlatformOptions, TreatmentPlanOptions, PatientOptions, Feature, FEATURE_TYPES, + ENTRYPOINTS, }; diff --git a/src/feature/featureUtil.spec.ts b/src/feature/featureUtil.spec.ts index cb869a6..f21e890 100644 --- a/src/feature/featureUtil.spec.ts +++ b/src/feature/featureUtil.spec.ts @@ -32,34 +32,102 @@ describe("getFeatureUrl", () => { }); describe("feature type", () => { - it("returns the proper url when the feature type is 'treatmentPlan'", async () => { - const url = await getFeatureURL( - "treatmentPlan", - mockFeatureOptions, - mockFullscriptOptions, - mockFrameId - ); + describe("the feature type is 'treatmentPlan'", () => { + it("returns the proper url", async () => { + const url = await getFeatureURL( + "treatmentPlan", + mockFeatureOptions, + mockFullscriptOptions, + mockFrameId + ); - expect(url).toEqual( - `https://us-snd.fullscript.io/api/embeddable/session/treatment_plans/new?data_token=${encodeURIComponent( - mockDataToken - )}&secret_token=secretToken&public_key=publicKey&frame_id=uuid&target_origin=http://localhost` - ); + expect(url).toEqual( + `https://us-snd.fullscript.io/api/embeddable/session/treatment_plans/new?data_token=${encodeURIComponent( + mockDataToken + )}&secret_token=secretToken&public_key=publicKey&frame_id=uuid&target_origin=http://localhost` + ); + }); + + it("doesn't add entrypoint to the url when entrypoint is given", async () => { + const url = await getFeatureURL( + "treatmentPlan", + // @ts-expect-error + { ...mockFeatureOptions, entrypoint: "labs" }, + mockFullscriptOptions, + mockFrameId + ); + + expect(url).toEqual( + `https://us-snd.fullscript.io/api/embeddable/session/treatment_plans/new?data_token=${encodeURIComponent( + mockDataToken + )}&secret_token=secretToken&public_key=publicKey&frame_id=uuid&target_origin=http://localhost` + ); + }); }); - it("returns the proper url when the feature type is 'platform'", async () => { - const url = await getFeatureURL( - "platform", - mockFeatureOptions, - mockFullscriptOptions, - mockFrameId - ); + describe("the feature type is 'platform'", () => { + it("returns the proper url", async () => { + const url = await getFeatureURL( + "platform", + mockFeatureOptions, + mockFullscriptOptions, + mockFrameId + ); - expect(url).toEqual( - `https://us-snd.fullscript.io/api/embeddable/session/embed/entry?data_token=${encodeURIComponent( - mockDataToken - )}&secret_token=secretToken&public_key=publicKey&frame_id=uuid&target_origin=http://localhost` - ); + expect(url).toEqual( + `https://us-snd.fullscript.io/api/embeddable/session/embed/entry?data_token=${encodeURIComponent( + mockDataToken + )}&secret_token=secretToken&public_key=publicKey&frame_id=uuid&target_origin=http://localhost` + ); + }); + + describe("entrypoint", () => { + it("adds labs entrypoint to the url when it is given", async () => { + const url = await getFeatureURL( + "platform", + { ...mockFeatureOptions, entrypoint: "labs" }, + mockFullscriptOptions, + mockFrameId + ); + + expect(url).toEqual( + `https://us-snd.fullscript.io/api/embeddable/session/embed/entry?data_token=${encodeURIComponent( + mockDataToken + )}&secret_token=secretToken&entrypoint=labs&public_key=publicKey&frame_id=uuid&target_origin=http://localhost` + ); + }); + + it("adds catalog entrypoint to the url when it is given", async () => { + const url = await getFeatureURL( + "platform", + { ...mockFeatureOptions, entrypoint: "catalog" }, + mockFullscriptOptions, + mockFrameId + ); + + expect(url).toEqual( + `https://us-snd.fullscript.io/api/embeddable/session/embed/entry?data_token=${encodeURIComponent( + mockDataToken + )}&secret_token=secretToken&entrypoint=catalog&public_key=publicKey&frame_id=uuid&target_origin=http://localhost` + ); + }); + + it("doesn't add entrypoint to the url when an invalid entrypoint is given", async () => { + const url = await getFeatureURL( + "platform", + // @ts-expect-error + { ...mockFeatureOptions, entrypoint: "invalid" }, + mockFullscriptOptions, + mockFrameId + ); + + expect(url).toEqual( + `https://us-snd.fullscript.io/api/embeddable/session/embed/entry?data_token=${encodeURIComponent( + mockDataToken + )}&secret_token=secretToken&public_key=publicKey&frame_id=uuid&target_origin=http://localhost` + ); + }); + }); }); }); diff --git a/src/feature/featureUtil.ts b/src/feature/featureUtil.ts index 7e454d8..0556dfb 100644 --- a/src/feature/featureUtil.ts +++ b/src/feature/featureUtil.ts @@ -3,8 +3,21 @@ import { validateFeatureType } from "../fullscriptJsValidator"; import { buildQueryString } from "../utils"; import { FEATURE_PATHS } from "./featurePath"; -import { FeatureType, FeatureOptions } from "./featureType"; +import { ENTRYPOINTS, FeatureType, FeatureOptions } from "./featureType"; +const getValidFeatureOptions = ( + featureType: FeatureType, + featureOptions: FeatureOptions +) => { + if ("entrypoint" in featureOptions) { + if (featureType === "treatmentPlan" || !ENTRYPOINTS.includes(featureOptions.entrypoint)) { + const { entrypoint: _removed, ...validOptions } = featureOptions; + return validOptions; + } + } + + return featureOptions; +}; const getFeatureURL = async ( featureType: F, featureOptions: FeatureOptions, @@ -12,8 +25,9 @@ const getFeatureURL = async ( frameId: string ): Promise => { const { publicKey, env, domain } = fullscriptOptions; + const queryString = await buildQueryString({ - ...featureOptions, + ...getValidFeatureOptions(featureType, featureOptions), fullscriptOptions, publicKey, frameId,