From 837764344980fe2b9f40fd34cb2566c7e4018127 Mon Sep 17 00:00:00 2001 From: Erin Date: Fri, 30 Aug 2024 16:52:13 -0700 Subject: [PATCH] Fix a bug where null values in RuntimeConfig cause initialize to fail (#2490) * Handle the case where `null` values in the `RuntimeConfig` from the host SDK will cause an error, ultimately causing `app.initialize` to fail. * Update the `AppEligibilityInformation` interface to match the definition in the host SDK library and add a unit test to validate handling `null` values. * Change file * Update change file --------- Co-authored-by: Erin --- ...-1257aa2f-91cd-490f-94ba-d9fd85728ddf.json | 7 ++++ packages/teams-js/src/internal/utils.ts | 3 ++ packages/teams-js/src/public/interfaces.ts | 2 +- .../teams-js/test/private/copilot.spec.ts | 34 +++++++++++++++++++ 4 files changed, 45 insertions(+), 1 deletion(-) create mode 100644 change/@microsoft-teams-js-1257aa2f-91cd-490f-94ba-d9fd85728ddf.json diff --git a/change/@microsoft-teams-js-1257aa2f-91cd-490f-94ba-d9fd85728ddf.json b/change/@microsoft-teams-js-1257aa2f-91cd-490f-94ba-d9fd85728ddf.json new file mode 100644 index 0000000000..28aa0c07e7 --- /dev/null +++ b/change/@microsoft-teams-js-1257aa2f-91cd-490f-94ba-d9fd85728ddf.json @@ -0,0 +1,7 @@ +{ + "type": "patch", + "comment": "Fixed a bug with `AppEligibilityInformation` that could cause `app.initialize` to fail.", + "packageName": "@microsoft/teams-js", + "email": "erinha@users.noreply.github.com", + "dependentChangeType": "patch" +} diff --git a/packages/teams-js/src/internal/utils.ts b/packages/teams-js/src/internal/utils.ts index 6b1aa4c50c..03b12c82e8 100644 --- a/packages/teams-js/src/internal/utils.ts +++ b/packages/teams-js/src/internal/utils.ts @@ -94,6 +94,9 @@ export function generateGUID(): string { */ export function deepFreeze(obj: T): T { Object.keys(obj).forEach((prop) => { + if (obj[prop] === null || obj[prop] === undefined) { + return; + } if (typeof obj[prop] === 'object') { deepFreeze(obj[prop]); } diff --git a/packages/teams-js/src/public/interfaces.ts b/packages/teams-js/src/public/interfaces.ts index 7ed4deabd3..70ba0427c4 100644 --- a/packages/teams-js/src/public/interfaces.ts +++ b/packages/teams-js/src/public/interfaces.ts @@ -1135,7 +1135,7 @@ export interface AppEligibilityInformation { /** * Education Eligibility Information for the app user */ - userClassification: UserClassification; + userClassification: UserClassification | null; } /** diff --git a/packages/teams-js/test/private/copilot.spec.ts b/packages/teams-js/test/private/copilot.spec.ts index 1ae2485f77..9e08e072ca 100644 --- a/packages/teams-js/test/private/copilot.spec.ts +++ b/packages/teams-js/test/private/copilot.spec.ts @@ -18,6 +18,15 @@ const mockedAppEligibilityInformation = { }, }; +const mockedAppEligibilityInformationUserClassificationNull = { + cohort: Cohort.BCAIS, + ageGroup: LegalAgeGroupClassification.Adult, + isCopilotEnabledRegion: true, + isCopilotEligible: true, + isOptedOutByAdmin: false, + userClassification: null, +}; + const copilotRuntimeConfig: Runtime = { apiVersion: 4, hostVersionsInfo: { @@ -35,6 +44,25 @@ const copilotRuntimeConfig: Runtime = { logs: {}, }, }; + +const copilotRuntimeConfigWithUserClassificationNull: Runtime = { + apiVersion: 4, + hostVersionsInfo: { + appEligibilityInformation: mockedAppEligibilityInformationUserClassificationNull, + }, + supports: { + pages: { + appButton: {}, + tabs: {}, + config: {}, + backStack: {}, + fullTrust: {}, + }, + teamsCore: {}, + logs: {}, + }, +}; + describe('copilot', () => { let utils: Utils; beforeEach(() => { @@ -73,5 +101,11 @@ describe('copilot', () => { expect.objectContaining(errorNotSupportedOnPlatform), ); }); + it('should return null userClassification if the host provided eligibility information with userClassification as null', async () => { + await utils.initializeWithContext(FrameContexts.content); + utils.setRuntimeConfig(copilotRuntimeConfigWithUserClassificationNull); + expect(copilot.eligibility.isSupported()).toBeTruthy(); + expect(copilot.eligibility.getEligibilityInfo()).toBe(mockedAppEligibilityInformationUserClassificationNull); + }); }); });