Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(message overrides): extract message content with Platform-Specific Overrides #12917

Merged
Show file tree
Hide file tree
Changes from 24 commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
9eaa5cc
extract message content with Platform-Specific Overrides
buddyeorl Jan 28, 2024
37eb6e5
added default platform when getClientInfo returns an undefined platform
buddyeorl Jan 28, 2024
965f58f
mocking getClientInfo shouldn't override mock utils
buddyeorl Jan 28, 2024
83f9210
Merge branch 'main' into in-app-messaging/fix/extract-content-with-pl…
buddyeorl Jan 29, 2024
9bcef3b
Merge branch 'main' into in-app-messaging/fix/extract-content-with-pl…
buddyeorl Jan 30, 2024
767dd02
Merge branch 'main' into in-app-messaging/fix/extract-content-with-pl…
buddyeorl Feb 3, 2024
7594f26
moved logic to extractContent fn, updated tests
buddyeorl Feb 4, 2024
d4f0b4b
Merge branch 'in-app-messaging/fix/extract-content-with-platform-over…
buddyeorl Feb 4, 2024
91df63b
exposed internal type InAppMessageButton
buddyeorl Feb 4, 2024
71d8851
added empty line
buddyeorl Feb 4, 2024
556f739
return immediately if os is falsy
buddyeorl Feb 4, 2024
8448b9c
fixed lint warning
buddyeorl Feb 4, 2024
290a55f
Merge branch 'main' into in-app-messaging/fix/extract-content-with-pl…
buddyeorl Feb 5, 2024
8c56fe4
pinpoint internal type exports, mergeOverride test util, simplified d…
buddyeorl Feb 12, 2024
3c07425
Merge branch 'main' into in-app-messaging/fix/extract-content-with-pl…
buddyeorl Feb 12, 2024
2439885
removed unnecessary spread operator
buddyeorl Feb 12, 2024
8d9b4ab
Merge branch 'in-app-messaging/fix/extract-content-with-platform-over…
buddyeorl Feb 12, 2024
5307825
refactored merging fn
buddyeorl Feb 12, 2024
a7d9f43
prettier
buddyeorl Feb 18, 2024
d7721c3
flatten test structure
buddyeorl Feb 18, 2024
b53cefc
minor update
buddyeorl Feb 18, 2024
59828bd
minor update
buddyeorl Feb 18, 2024
3a58f15
updated merge override fns signature and associated tests
buddyeorl Feb 19, 2024
7ff8b96
extracted getButtonConfig fn and refactored to add data existence che…
buddyeorl Feb 19, 2024
f7eb800
removed unnecessary optional chaining operators
buddyeorl Feb 19, 2024
124b767
Merge branch 'main' into in-app-messaging/fix/extract-content-with-pl…
buddyeorl Mar 1, 2024
f1ccb7f
Merge branch 'main' into in-app-messaging/fix/extract-content-with-pl…
Samaritan1011001 Mar 13, 2024
94c8851
Merge branch 'main' into in-app-messaging/fix/extract-content-with-pl…
Samaritan1011001 Mar 14, 2024
0fc25fd
Merge branch 'main' into in-app-messaging/fix/extract-content-with-pl…
Samaritan1011001 Mar 18, 2024
0ae90d2
Merge branch 'main' into in-app-messaging/fix/extract-content-with-pl…
Samaritan1011001 Mar 18, 2024
5c1c5c1
Merge branch 'main' into in-app-messaging/fix/extract-content-with-pl…
Samaritan1011001 Mar 19, 2024
a0714ea
Merge branch 'main' into in-app-messaging/fix/extract-content-with-pl…
Samaritan1011001 Apr 15, 2024
aa52fe7
fixed lint issues
buddyeorl Apr 16, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 @@ -24,7 +24,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' },
buddyeorl marked this conversation as resolved.
Show resolved Hide resolved
{ 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