Skip to content

Commit

Permalink
fix(message overrides): extract message content with Platform-Specifi…
Browse files Browse the repository at this point in the history
…c Overrides (#12917)

* extract message content with Platform-Specific Overrides

* added default platform when getClientInfo returns an undefined platform

* mocking getClientInfo shouldn't override mock utils

* moved logic to extractContent fn, updated tests

* exposed internal type InAppMessageButton

* added empty line

* return immediately if os is falsy

* fixed lint warning

* pinpoint internal type exports, mergeOverride test util, simplified data object

* removed unnecessary spread operator

* refactored merging fn

* prettier

* flatten test structure

* minor update

* minor update

* updated merge override fns signature and associated tests

* extracted getButtonConfig fn and refactored to add data existence checks.

* removed unnecessary optional chaining operators

* fixed lint issues

---------

Co-authored-by: ManojNB <[email protected]>
  • Loading branch information
buddyeorl and Samaritan1011001 authored Apr 18, 2024
1 parent 1625424 commit cb91437
Show file tree
Hide file tree
Showing 8 changed files with 342 additions and 9 deletions.
8 changes: 7 additions & 1 deletion packages/core/src/awsClients/pinpoint/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,10 @@ export {
UpdateEndpointInput,
UpdateEndpointOutput,
} from './updateEndpoint';
export { Event, InAppMessageCampaign, EventsBatch } from './types';
export {
Event,
InAppMessageCampaign,
EventsBatch,
InAppMessageButton,
OverrideButtonConfiguration,
} from './types';
2 changes: 1 addition & 1 deletion packages/core/src/libraryUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ export { LegacyConfig } from './singleton/types';
export { ADD_OAUTH_LISTENER } from './singleton/constants';
export { amplifyUuid } from './utils/amplifyUuid';
export { AmplifyUrl, AmplifyUrlSearchParams } from './utils/amplifyUrl';

export { getClientInfo } from './utils';
// Auth utilities
export {
decodeJWT,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
/**
* @jest-environment node
*/
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

import {
extractContent,
mapOSPlatform,
} from '../../../../../src/inAppMessaging/providers/pinpoint/utils/helpers';

import {
nonBrowserConfigTestCases,
pinpointInAppMessage,
extractedContent,
nativeButtonOverrides,
} from '../../../../testUtils/data';
import { mergeExpectedContentWithExpectedOverride, mergeInAppMessageWithOverrides } from '../../../../testUtils/mergeInAppMessageWithOverrides';

jest.mock('@aws-amplify/core');

jest.mock('@aws-amplify/core/internals/utils', () => {
const originalModule = jest.requireActual(
'@aws-amplify/core/internals/utils',
);
return {
...originalModule,
getClientInfo: jest.fn(), // Setup as a Jest mock function without implementation
};
});

describe('InAppMessaging Provider Utils (running natively)', () => {
describe('mapOSPlatform method', () => {
nonBrowserConfigTestCases.forEach(({ os, expectedPlatform }) => {
test(`correctly maps OS "${os}" to ConfigPlatformType "${expectedPlatform}"`, () => {
const result = mapOSPlatform(os);
expect(result).toBe(expectedPlatform);
});
});
});

describe('extractContent with overrides', () => {
nativeButtonOverrides.forEach(
({ buttonOverrides, configPlatform, mappedPlatform }) => {
const message = mergeInAppMessageWithOverrides(
pinpointInAppMessage,
mappedPlatform,
buttonOverrides,
);
const expectedContent = mergeExpectedContentWithExpectedOverride(
extractedContent[0],
buttonOverrides,
);

test(`correctly extracts content for ${configPlatform}`, () => {
const utils = require('@aws-amplify/core/internals/utils');
// Dynamically override the mock for getClientInfo
utils.getClientInfo.mockImplementation(() => ({
platform: configPlatform,
}));

const [firstContent] = extractContent(message);
expect(firstContent.primaryButton).toStrictEqual(
expectedContent.primaryButton,
);
expect(firstContent.secondaryButton).toStrictEqual(
expectedContent.secondaryButton,
);
});
},
);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
extractMetadata,
getStartOfDay,
isBeforeEndDate,
mapOSPlatform,
matchesAttributes,
matchesEventType,
matchesMetrics,
Expand All @@ -19,13 +20,29 @@ import {
extractedContent,
extractedMetadata,
pinpointInAppMessage,
browserConfigTestCases,
browserButtonOverrides,
} from '../../../../testUtils/data';
import { InAppMessagingEvent } from '../../../../../src/inAppMessaging/types';
import { InAppMessagingEvent } from '../../../../../src/inAppMessaging/types';
import {
mergeExpectedContentWithExpectedOverride,
mergeInAppMessageWithOverrides,
} from '../../../../testUtils/mergeInAppMessageWithOverrides';

jest.mock('@aws-amplify/core');
jest.mock('@aws-amplify/core/internals/providers/pinpoint');
jest.mock('../../../../../src/inAppMessaging/providers/pinpoint/utils');

jest.mock('@aws-amplify/core/internals/utils', () => {
const originalModule = jest.requireActual(
'@aws-amplify/core/internals/utils',
);
return {
...originalModule,
getClientInfo: jest.fn(), // Setup as a Jest mock function without implementation
};
});

const HOUR_IN_MS = 1000 * 60 * 60;

describe('InAppMessaging Provider Utils', () => {
Expand Down Expand Up @@ -271,4 +288,45 @@ describe('InAppMessaging Provider Utils', () => {

expect(extractMetadata(message)).toStrictEqual(extractedMetadata);
});

describe('mapOSPlatform method (running in a browser)', () => {
browserConfigTestCases.forEach(({ os, expectedPlatform }) => {
test(`correctly maps OS "${os}" to ConfigPlatformType "${expectedPlatform}"`, () => {
const result = mapOSPlatform(os);
expect(result).toBe(expectedPlatform);
});
});
});

describe('extractContent with overrides (running in a browser)', () => {
browserButtonOverrides.forEach(
({ buttonOverrides, configPlatform, mappedPlatform }) => {
const message = mergeInAppMessageWithOverrides(
pinpointInAppMessage,
mappedPlatform,
buttonOverrides,
);
const expectedContent = mergeExpectedContentWithExpectedOverride(
extractedContent[0],
buttonOverrides,
);

test(`correctly extracts content for ${configPlatform}`, () => {
const utils = require('@aws-amplify/core/internals/utils');
// Dynamically override the mock for getClientInfo
utils.getClientInfo.mockImplementation(() => ({
platform: configPlatform,
}));

const [firstContent] = extractContent(message);
expect(firstContent.primaryButton).toStrictEqual(
expectedContent.primaryButton,
);
expect(firstContent.secondaryButton).toStrictEqual(
expectedContent.secondaryButton,
);
});
},
);
});
});
90 changes: 88 additions & 2 deletions packages/notifications/__tests__/testUtils/data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,17 @@
// SPDX-License-Identifier: Apache-2.0

import { PinpointAnalyticsEvent } from '@aws-amplify/core/internals/providers/pinpoint';
import type { InAppMessageCampaign as PinpointInAppMessage } from '@aws-amplify/core/internals/aws-clients/pinpoint';
import {
type InAppMessageCampaign as PinpointInAppMessage,
OverrideButtonConfiguration,
} from '@aws-amplify/core/internals/aws-clients/pinpoint';
import {
InAppMessage,
InAppMessageContent,
InAppMessagingEvent,
} from '../../src/inAppMessaging/types';
import { PushNotificationMessage } from '../../src/pushNotifications';
import { ButtonConfigPlatform } from '../../src/inAppMessaging/types/message';

export const credentials = {
credentials: {
Expand Down Expand Up @@ -183,7 +188,7 @@ export const pinpointInAppMessage: PinpointInAppMessage = {
TreatmentId: 'T1',
};

export const extractedContent = [
export const extractedContent: InAppMessageContent[] = [
{
body: {
content: 'Body content',
Expand All @@ -210,6 +215,67 @@ export const extractedContent = [
},
];

export const nativeButtonOverrides: {
configPlatform: 'ios' | 'android';
mappedPlatform: ButtonConfigPlatform;
buttonOverrides: {
primaryButton: OverrideButtonConfiguration;
secondaryButton: OverrideButtonConfiguration;
};
}[] = [
{
configPlatform: 'android',
mappedPlatform: 'Android',
buttonOverrides: {
primaryButton: {
ButtonAction: 'DEEP_LINK',
Link: 'android-app://primaryButtonLink',
},
secondaryButton: {
ButtonAction: 'LINK',
Link: 'android-app://secondaryButtonLink',
},
},
},
{
configPlatform: 'ios',
mappedPlatform: 'IOS',
buttonOverrides: {
primaryButton: {
ButtonAction: 'DEEP_LINK',
Link: 'ios-app://primaryButtonLink',
},
secondaryButton: {
ButtonAction: 'LINK',
Link: 'ios-app://secondaryButtonLink',
},
},
},
];
export const browserButtonOverrides: {
configPlatform: 'web';
mappedPlatform: ButtonConfigPlatform;
buttonOverrides: {
primaryButton: OverrideButtonConfiguration;
secondaryButton: OverrideButtonConfiguration;
};
}[] = [
{
configPlatform: 'web',
mappedPlatform: 'Web',
buttonOverrides: {
primaryButton: {
ButtonAction: 'LINK',
Link: 'https://webPrimaryButtonLink.com',
},
secondaryButton: {
ButtonAction: 'LINK',
Link: 'https://webSecondaryButtonLink.com',
},
},
},
];

export const extractedMetadata = {
customData: { foo: 'bar' },
endDate: '2021-01-01T00:00:00Z',
Expand Down Expand Up @@ -295,3 +361,23 @@ export const completionHandlerId = 'completion-handler-id';
export const userAgentValue = 'user-agent-value';

export const channelType = 'APNS_SANDBOX';

export const browserConfigTestCases = [
{ os: 'android', expectedPlatform: 'Web' },
{ os: 'ios', expectedPlatform: 'Web' },
{ os: 'windows', expectedPlatform: 'Web' },
{ os: 'macos', expectedPlatform: 'Web' },
{ os: 'linux', expectedPlatform: 'Web' },
{ os: 'unix', expectedPlatform: 'Web' },
{ os: 'unknown', expectedPlatform: 'Web' },
];

export const nonBrowserConfigTestCases = [
{ os: 'android', expectedPlatform: 'Android' },
{ os: 'ios', expectedPlatform: 'IOS' },
{ os: 'windows', expectedPlatform: 'DefaultConfig' },
{ os: 'macos', expectedPlatform: 'DefaultConfig' },
{ os: 'linux', expectedPlatform: 'DefaultConfig' },
{ os: 'unix', expectedPlatform: 'DefaultConfig' },
{ os: 'unknown', expectedPlatform: 'DefaultConfig' },
];
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

import { cloneDeep } from 'lodash';
import {
InAppMessageCampaign,
OverrideButtonConfiguration,
} from '@aws-amplify/core/internals/aws-clients/pinpoint';
import {
ButtonConfigPlatform,
InAppMessageButton,
InAppMessageContent,
} from '../../src/inAppMessaging/types/message';

export const mergeInAppMessageWithOverrides = (
pinpointInAppMessage: InAppMessageCampaign,
mappedPlatform: ButtonConfigPlatform,
buttonOverrides?: {
primaryButton: OverrideButtonConfiguration;
secondaryButton: OverrideButtonConfiguration;
},
): InAppMessageCampaign => {
const message = cloneDeep(pinpointInAppMessage);
if (message?.InAppMessage?.Content) {
message.InAppMessage.Content[0] = {
...message.InAppMessage.Content[0],
PrimaryBtn: {
...message.InAppMessage.Content[0].PrimaryBtn,
[mappedPlatform]: buttonOverrides?.primaryButton,
},
SecondaryBtn: {
...message.InAppMessage.Content[0].SecondaryBtn,
[mappedPlatform]: buttonOverrides?.secondaryButton,
},
};
}
return message;
};

export const mergeExpectedContentWithExpectedOverride = (
inAppMessage: InAppMessageContent,
expectedButtonConfig: {
primaryButton: OverrideButtonConfiguration;
secondaryButton: OverrideButtonConfiguration;
},
): InAppMessageContent => {
let expectedContent = cloneDeep(inAppMessage);
expectedContent.primaryButton = {
...expectedContent.primaryButton,
action: expectedButtonConfig.primaryButton.ButtonAction,
url: expectedButtonConfig.primaryButton.Link,
} as InAppMessageButton;
expectedContent.secondaryButton = {
...expectedContent.secondaryButton,
action: expectedButtonConfig.secondaryButton.ButtonAction,
url: expectedButtonConfig.secondaryButton.Link,
} as InAppMessageButton;
return expectedContent;
};
Loading

0 comments on commit cb91437

Please sign in to comment.