Skip to content

Commit c2f7832

Browse files
Fixed the typo from NonAdult to NotAdult in LegalAgeGroupClassification Interface (#2858)
* Fixed the typo from NonAdult to NotAdult in LegalAgeGroupClassification * adding chnagefile * adding a backcompt fix * adding unit tests * Fix for the enum in runtime * add the runtime * increase package size --------- Co-authored-by: Jeff Klouda <[email protected]>
1 parent 705be57 commit c2f7832

File tree

8 files changed

+159
-8
lines changed

8 files changed

+159
-8
lines changed
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"type": "patch",
3+
"comment": "Fixed the typo from `NonAdult` to `NotAdult` in `LegalAgeGroupClassification` Enum.",
4+
"packageName": "@microsoft/teams-js",
5+
"email": "[email protected]",
6+
"dependentChangeType": "patch"
7+
}

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@
162162
"brotli": false,
163163
"path": "./packages/teams-js/dist/esm/packages/teams-js/src/index.js",
164164
"import": "{ app, authentication, pages }",
165-
"limit": "57.69 KB"
165+
"limit": "58.32 KB"
166166
},
167167
{
168168
"brotli": false,

packages/teams-js/src/internal/appHelpers.ts

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,12 @@ import * as Handlers from '../internal/handlers'; // Conflict with some names
1414
import { ensureInitializeCalled, ensureInitialized, processAdditionalValidOrigins } from '../internal/internalAPIs';
1515
import { getLogger } from '../internal/telemetry';
1616
import { isNullOrUndefined } from '../internal/typeCheckUtilities';
17-
import { compareSDKVersions, inServerSideRenderingEnvironment, runWithTimeout } from '../internal/utils';
17+
import {
18+
compareSDKVersions,
19+
inServerSideRenderingEnvironment,
20+
normalizeAgeGroupValue,
21+
runWithTimeout,
22+
} from '../internal/utils';
1823
import * as app from '../public/app/app';
1924
import { FrameContexts } from '../public/constants';
2025
import * as dialog from '../public/dialog/dialog';
@@ -149,12 +154,14 @@ function initializeHelper(apiVersionTag: string, validMessageOrigins?: string[])
149154
// After Teams updates its client code, we can remove this default code.
150155
try {
151156
initializeHelperLogger('Parsing %s', runtimeConfig);
152-
const givenRuntimeConfig: IBaseRuntime | null = JSON.parse(runtimeConfig);
157+
let givenRuntimeConfig: IBaseRuntime | null = JSON.parse(runtimeConfig);
153158
initializeHelperLogger('Checking if %o is a valid runtime object', givenRuntimeConfig ?? 'null');
154159
// Check that givenRuntimeConfig is a valid instance of IBaseRuntime
155160
if (!givenRuntimeConfig || !givenRuntimeConfig.apiVersion) {
156161
throw new Error('Received runtime config is invalid');
157162
}
163+
// Normalize ageGroup value for backward compatibility
164+
givenRuntimeConfig = normalizeAgeGroupValue(givenRuntimeConfig);
158165
runtimeConfig && applyRuntimeConfig(givenRuntimeConfig);
159166
} catch (e) {
160167
if (e instanceof SyntaxError) {
@@ -167,14 +174,15 @@ function initializeHelper(apiVersionTag: string, validMessageOrigins?: string[])
167174
if (!isNaN(compareSDKVersions(runtimeConfig, defaultSDKVersionForCompatCheck))) {
168175
GlobalVars.clientSupportedSDKVersion = runtimeConfig;
169176
}
170-
const givenRuntimeConfig: IBaseRuntime | null = JSON.parse(clientSupportedSDKVersion);
177+
let givenRuntimeConfig: IBaseRuntime | null = JSON.parse(clientSupportedSDKVersion);
171178
initializeHelperLogger('givenRuntimeConfig parsed to %o', givenRuntimeConfig ?? 'null');
172179

173180
if (!givenRuntimeConfig) {
174181
throw new Error(
175182
'givenRuntimeConfig string was successfully parsed. However, it parsed to value of null',
176183
);
177184
} else {
185+
givenRuntimeConfig = normalizeAgeGroupValue(givenRuntimeConfig);
178186
applyRuntimeConfig(givenRuntimeConfig);
179187
}
180188
} catch (e) {

packages/teams-js/src/internal/utils.ts

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,9 @@ import { Buffer } from 'buffer';
44
import * as uuid from 'uuid';
55

66
import { minAdaptiveCardVersion } from '../public/constants';
7-
import { AdaptiveCardVersion, SdkError } from '../public/interfaces';
7+
import { AdaptiveCardVersion, LegalAgeGroupClassification, SdkError } from '../public/interfaces';
88
import * as pages from '../public/pages/pages';
9+
import { IBaseRuntime } from '../public/runtime';
910

1011
/**
1112
* @internal
@@ -566,3 +567,34 @@ export function isPrimitiveOrPlainObject(value: unknown, depth: number = 0): boo
566567
// Check all properties of the object recursively
567568
return Object.keys(value).every((key) => isPrimitiveOrPlainObject(value[key], depth + 1));
568569
}
570+
571+
/**
572+
* Normalizes legacy ageGroup values for backward compatibility
573+
* @param runtimeConfig - The runtime configuration object to normalize
574+
* @returns A new IBaseRuntime object with normalized ageGroup values
575+
*/
576+
export function normalizeAgeGroupValue(runtimeConfig: IBaseRuntime): IBaseRuntime {
577+
// If no ageGroup exists, return the original config
578+
if (!runtimeConfig.hostVersionsInfo?.appEligibilityInformation?.ageGroup) {
579+
return runtimeConfig;
580+
}
581+
582+
const ageGroup = runtimeConfig.hostVersionsInfo.appEligibilityInformation.ageGroup as unknown as string;
583+
584+
// If the ageGroup doesn't need normalization, return the original config
585+
if (ageGroup?.toLowerCase() !== 'nonadult') {
586+
return runtimeConfig;
587+
}
588+
589+
// Create a new config with the normalized ageGroup value
590+
return {
591+
...runtimeConfig,
592+
hostVersionsInfo: {
593+
...runtimeConfig.hostVersionsInfo,
594+
appEligibilityInformation: {
595+
...runtimeConfig.hostVersionsInfo.appEligibilityInformation,
596+
ageGroup: LegalAgeGroupClassification.NotAdult,
597+
},
598+
},
599+
};
600+
}

packages/teams-js/src/private/copilot/eligibility.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import { sendAndUnwrap } from '../../internal/communication';
1111
import { ensureInitialized } from '../../internal/internalAPIs';
1212
import { ApiName, ApiVersionNumber, getApiVersionTag, getLogger } from '../../internal/telemetry';
1313
import { errorNotSupportedOnPlatform } from '../../public/constants';
14-
import { AppEligibilityInformation, isSdkError, SdkError } from '../../public/interfaces';
14+
import { AppEligibilityInformation, isSdkError, LegalAgeGroupClassification, SdkError } from '../../public/interfaces';
1515
import { runtime } from '../../public/runtime';
1616

1717
const copilotTelemetryVersionNumber: ApiVersionNumber = ApiVersionNumber.V_2;
@@ -73,6 +73,10 @@ export async function getEligibilityInfo(forceRefresh?: boolean): Promise<AppEli
7373
if (!isEligibilityInfoValid(response)) {
7474
throw new Error('Error deserializing eligibility information');
7575
}
76+
// convert nonAdult age group to NotAdult
77+
if ((response.ageGroup as unknown as string)?.toLowerCase() === 'nonadult') {
78+
response.ageGroup = LegalAgeGroupClassification.NotAdult;
79+
}
7680
return response;
7781
}
7882

packages/teams-js/src/public/interfaces.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1304,7 +1304,12 @@ export enum LegalAgeGroupClassification {
13041304
* United Kingdom, European Union, or South Korea, and the user's age is between a minor and an adult age
13051305
* (as stipulated based on country or region). Generally, this means that teenagers are considered as notAdult in regulated countries.
13061306
*/
1307-
NonAdult = 'nonAdult',
1307+
NotAdult = 'notAdult',
1308+
/**
1309+
* @deprecated To provide back compatibility for the NonAdult enum value coming from the hubs
1310+
*/
1311+
// eslint-disable-next-line @typescript-eslint/no-duplicate-enum-values
1312+
NonAdult = 'notAdult',
13081313
}
13091314

13101315
/**

packages/teams-js/test/internal/utils.spec.ts

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,14 @@ import {
55
getBase64StringFromBlob,
66
hasScriptTags,
77
isPrimitiveOrPlainObject,
8+
normalizeAgeGroupValue,
89
validateId,
910
validateUrl,
1011
validateUuid,
1112
} from '../../src/internal/utils';
1213
import { AppId, pages } from '../../src/public';
13-
import { ClipboardSupportedMimeType } from '../../src/public/interfaces';
14+
import { ClipboardSupportedMimeType, LegalAgeGroupClassification } from '../../src/public/interfaces';
15+
import { IBaseRuntime } from '../../src/public/runtime';
1416
import { UUID } from '../../src/public/uuidObject';
1517

1618
describe('utils', () => {
@@ -610,4 +612,51 @@ describe('utils', () => {
610612
expect(isPrimitiveOrPlainObject(createNestedObject(1000))).toBe(true);
611613
});
612614
});
615+
describe('normalizeAgeGroupValue', () => {
616+
const createMockRuntimeConfig = (ageGroup?: string | LegalAgeGroupClassification): IBaseRuntime => ({
617+
apiVersion: 4,
618+
supports: {},
619+
hostVersionsInfo: {
620+
appEligibilityInformation: {
621+
ageGroup: ageGroup as LegalAgeGroupClassification,
622+
cohort: null,
623+
isCopilotEligible: false,
624+
isCopilotEnabledRegion: true,
625+
isOptedOutByAdmin: false,
626+
userClassification: null,
627+
},
628+
},
629+
});
630+
631+
describe('when ageGroup needs normalization', () => {
632+
it('should normalize "nonAdult" to NotAdult', () => {
633+
const input = createMockRuntimeConfig('nonAdult');
634+
const result = normalizeAgeGroupValue(input);
635+
636+
expect(result.hostVersionsInfo?.appEligibilityInformation?.ageGroup).toBe(LegalAgeGroupClassification.NotAdult);
637+
expect(result).not.toBe(input); // Should return a new object
638+
});
639+
640+
it('should normalize "NonAdult" to NotAdult (case insensitive)', () => {
641+
const input = createMockRuntimeConfig('NonAdult');
642+
const result = normalizeAgeGroupValue(input);
643+
644+
expect(result.hostVersionsInfo?.appEligibilityInformation?.ageGroup).toBe(LegalAgeGroupClassification.NotAdult);
645+
});
646+
647+
it('should normalize "NONADULT" to NotAdult (case insensitive)', () => {
648+
const input = createMockRuntimeConfig('NONADULT');
649+
const result = normalizeAgeGroupValue(input);
650+
651+
expect(result.hostVersionsInfo?.appEligibilityInformation?.ageGroup).toBe(LegalAgeGroupClassification.NotAdult);
652+
});
653+
654+
it('should normalize "noNaDuLt" to NotAdult (mixed case)', () => {
655+
const input = createMockRuntimeConfig('noNaDuLt');
656+
const result = normalizeAgeGroupValue(input);
657+
658+
expect(result.hostVersionsInfo?.appEligibilityInformation?.ageGroup).toBe(LegalAgeGroupClassification.NotAdult);
659+
});
660+
});
661+
});
613662
});

packages/teams-js/test/private/copilot.spec.ts

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,24 @@ const copilotInHostVersionsInfoRuntimeConfig: Runtime = {
5757
},
5858
};
5959

60+
const copilotInHostVersionsInfoRuntimeConfigWithNonAdult: Runtime = {
61+
apiVersion: 4,
62+
hostVersionsInfo: {
63+
appEligibilityInformation: { ...mockedAppEligibilityInformation, ageGroup: LegalAgeGroupClassification.NonAdult },
64+
},
65+
supports: {
66+
pages: {
67+
appButton: {},
68+
tabs: {},
69+
config: {},
70+
backStack: {},
71+
fullTrust: {},
72+
},
73+
teamsCore: {},
74+
logs: {},
75+
},
76+
};
77+
6078
const copilotRuntimeConfig: Runtime = {
6179
apiVersion: 4,
6280
supports: {
@@ -140,6 +158,12 @@ describe('copilot', () => {
140158
expect(copilot.eligibility.isSupported()).toBeTruthy();
141159
});
142160

161+
it('isSupported should return true if eligibility information is on the runtimeConfig with nonAdult enum', async () => {
162+
await utils.initializeWithContext(FrameContexts.content);
163+
utils.setRuntimeConfig(copilotInHostVersionsInfoRuntimeConfigWithNonAdult);
164+
expect(copilot.eligibility.isSupported()).toBeTruthy();
165+
});
166+
143167
it('isSupported should return true if copilot.eligibility is supported', async () => {
144168
await utils.initializeWithContext(FrameContexts.content);
145169
utils.setRuntimeConfig(copilotRuntimeConfig);
@@ -201,6 +225,28 @@ describe('copilot', () => {
201225
return expect(promise).resolves.toEqual(mockedAppEligibilityInformation);
202226
});
203227

228+
it('correct the ageGroup from nonAdult to notAdult', async () => {
229+
await utils.initializeWithContext(frameContext);
230+
utils.setRuntimeConfig(copilotRuntimeConfig);
231+
232+
const promise = copilot.eligibility.getEligibilityInfo();
233+
const message = utils.findMessageByFunc('copilot.eligibility.getEligibilityInfo');
234+
expect(message).not.toBeNull();
235+
const mockedAppEligibilityInformationWithInCorrectedAgeGroup = {
236+
...mockedAppEligibilityInformation,
237+
ageGroup: LegalAgeGroupClassification.NonAdult,
238+
};
239+
if (message) {
240+
utils.respondToMessage(message, mockedAppEligibilityInformationWithInCorrectedAgeGroup);
241+
}
242+
const mockedAppEligibilityInformationWithCorrectedAgeGroup = {
243+
...mockedAppEligibilityInformation,
244+
ageGroup: LegalAgeGroupClassification.NotAdult,
245+
};
246+
247+
return expect(promise).resolves.toEqual(mockedAppEligibilityInformationWithCorrectedAgeGroup);
248+
});
249+
204250
it(`should pass forceRefresh parameter if it exists - with context ${frameContext}`, async () => {
205251
expect.assertions(1);
206252
await utils.initializeWithContext(frameContext);

0 commit comments

Comments
 (0)