Skip to content

Commit

Permalink
chore: [IOCOM-1763] Refactor of push notification engagement screen d…
Browse files Browse the repository at this point in the history
…isplay logic (#6464)

## Short description
update of push notification screen display logic following the intended
final behaviour

## List of changes proposed in this pull request
- addition of missing selectors for engagement screen display logic
- addition of missing selector in engagement banner display logic
- addition of non-persisted state for engagement banner logic
- tests fix and missing test

## How to test
with the dev-server active, update `LANDING_SCREEN_BANNERS_ENABLED_MAP`
to have `PUSH_NOTIFICATIONS_REMINDER:true`, then disable push
notifications for IO and log out of the app if you are in an active
session.
Then, after launching the app again, make sure that the behaviour is as
follows:

1) on login, you should be prompted to enable notifications in the app,
and no matter the choice you should not see the push engagement screen
or the push notifications banner in the messages home

2) after closing and re-opening the app, if push notifications are still
disabled, you should see the engagement screen, but not the push
notifications banner in the homescreen
3) after closing and re-opening once more, you should still not see the
engagement screen, but the banner should be now shown.

if push notifications are enabled, you should never see either the
engagement screen or the push notifications banner.
  • Loading branch information
forrest57 authored Dec 13, 2024
1 parent b4f9164 commit 9d41018
Show file tree
Hide file tree
Showing 21 changed files with 129 additions and 129 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ exports[`featuresPersistor should match snapshot 1`] = `
},
"landingBanners": {
"ITW_DISCOVERY": true,
"PUSH_NOTIFICATIONS_REMINDER": false,
"PUSH_NOTIFICATIONS_REMINDER": true,
"SETTINGS_DISCOVERY": true,
},
"loginFeatures": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
exports[`landingScreenBannersReducer should match snapshot: undefined_no_action 1`] = `
{
"ITW_DISCOVERY": true,
"PUSH_NOTIFICATIONS_REMINDER": false,
"PUSH_NOTIFICATIONS_REMINDER": true,
"SETTINGS_DISCOVERY": true,
}
`;
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ export type LandingScreenBannerId =
keyof typeof LANDING_SCREEN_BANNERS_ENABLED_MAP;

export const LANDING_SCREEN_BANNERS_ENABLED_MAP = {
PUSH_NOTIFICATIONS_REMINDER: false,
PUSH_NOTIFICATIONS_REMINDER: true,
ITW_DISCOVERY: true,
SETTINGS_DISCOVERY: true
} as const;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@ import { useIONavigation } from "../../../navigation/params/AppParamsList";
import { openSystemNotificationSettingsScreen } from "../utils";
import I18n from "../../../i18n";
import { useIODispatch } from "../../../store/hooks";
import { setEngagementScreenShown } from "../store/actions/userBehaviour";
import {
trackSystemNotificationPermissionScreenOutcome,
trackSystemNotificationPermissionScreenShown
} from "../analytics";
import { IOScrollViewCentredContent } from "../../../components/ui/IOScrollViewCentredContent";
import { setEngagementScreenShown } from "../store/actions/environment";

export const SystemNotificationPermissionsScreen = () => {
const dispatch = useIODispatch();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ import { mockAccessibilityInfo } from "../../../../utils/testAccessibility";
import { renderScreenWithNavigationStoreContext } from "../../../../utils/testWrapper";
import * as analytics from "../../analytics";
import { NOTIFICATIONS_ROUTES } from "../../navigation/routes";
import { setEngagementScreenShown } from "../../store/actions/userBehaviour";
import * as utils from "../../utils";
import { SystemNotificationPermissionsScreen } from "../SystemNotificationPermissionsScreen";
import { setEngagementScreenShown } from "../../store/actions/environment";

const mockGoBack = jest.fn();
const mockSetNavigationOptions = jest.fn();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import { setPushPermissionsRequestDuration } from "../environment";
import {
setEngagementScreenShown,
setPushPermissionsRequestDuration
} from "../environment";

describe("setPushPermissionsRequestDuration", () => {
it("Should match expected values", () => {
Expand All @@ -7,3 +10,10 @@ describe("setPushPermissionsRequestDuration", () => {
expect(action.payload).toBe(1000);
});
});
describe("setEngagementScreenShown", () => {
it("Should match expected values", () => {
const action = setEngagementScreenShown();
expect(action.type).toBe("SET_ENGAGEMENT_SCREEN_SHOWN");
expect(action.payload).toBe(undefined);
});
});
Original file line number Diff line number Diff line change
@@ -1,18 +1,9 @@
import {
resetNotificationBannerDismissState,
setEngagementScreenShown,
setPushNotificationBannerForceDismissed,
setUserDismissedNotificationsBanner
} from "../userBehaviour";

describe("setEngagementScreenShown", () => {
it("Should match expected values", () => {
const action = setEngagementScreenShown();
expect(action.type).toBe("SET_ENGAGEMENT_SCREEN_SHOWN");
expect(action.payload).toBe(undefined);
});
});

describe("setUserDismissedNotificationsBanner", () => {
it("Should match expected values", () => {
const action = setUserDismissedNotificationsBanner();
Expand Down
6 changes: 5 additions & 1 deletion ts/features/pushNotifications/store/actions/environment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,11 @@ export const updateSystemNotificationsEnabled = createStandardAction(
export const setPushPermissionsRequestDuration = createStandardAction(
"SET_PUSH_PERMISSIONS_REQUEST_DURATION"
)<number>();
export const setEngagementScreenShown = createStandardAction(
"SET_ENGAGEMENT_SCREEN_SHOWN"
)<void>();

export type NotificationPermissionsActions =
| ActionType<typeof updateSystemNotificationsEnabled>
| ActionType<typeof setPushPermissionsRequestDuration>;
| ActionType<typeof setPushPermissionsRequestDuration>
| ActionType<typeof setEngagementScreenShown>;
4 changes: 0 additions & 4 deletions ts/features/pushNotifications/store/actions/userBehaviour.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
import { ActionType, createStandardAction } from "typesafe-actions";

export const setEngagementScreenShown = createStandardAction(
"SET_ENGAGEMENT_SCREEN_SHOWN"
)<void>();
export const setUserDismissedNotificationsBanner = createStandardAction(
"SET_USER_DISMISSED_NOTIFICATIONS_BANNER"
)<void>();
Expand All @@ -14,7 +11,6 @@ export const resetNotificationBannerDismissState = createStandardAction(
)<void>();

export type UserBehaviourActions =
| ActionType<typeof setEngagementScreenShown>
| ActionType<typeof setUserDismissedNotificationsBanner>
| ActionType<typeof resetNotificationBannerDismissState>
| ActionType<typeof setPushNotificationBannerForceDismissed>;
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
exports[`environment reducer initial state should match expected values 1`] = `
{
"applicationInitialized": false,
"engagementScreenShownThisSession": false,
"onboardingInstructionsShown": false,
"pushNotificationPermissionsRequestDuration": undefined,
"systemNotificationsEnabled": false,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ exports[`Main pushNotifications reducer notificationsReducer initial state shoul
{
"environment": {
"applicationInitialized": false,
"engagementScreenShownThisSession": false,
"onboardingInstructionsShown": false,
"pushNotificationPermissionsRequestDuration": undefined,
"systemNotificationsEnabled": false,
Expand All @@ -14,11 +15,8 @@ exports[`Main pushNotifications reducer notificationsReducer initial state shoul
},
"pendingMessage": null,
"userBehaviour": {
"engagementScreenShown": false,
"pushNotificationsBanner": {
"forceDismissionDate": undefined,
"timesDismissed": 0,
},
"pushNotificationBannerDismissalCount": 0,
"pushNotificationBannerForceDismissionDate": undefined,
},
}
`;
Expand All @@ -27,6 +25,7 @@ exports[`Main pushNotifications reducer persistedNotificationsReducer initial st
{
"environment": {
"applicationInitialized": false,
"engagementScreenShownThisSession": false,
"onboardingInstructionsShown": false,
"pushNotificationPermissionsRequestDuration": undefined,
"systemNotificationsEnabled": false,
Expand All @@ -37,11 +36,8 @@ exports[`Main pushNotifications reducer persistedNotificationsReducer initial st
},
"pendingMessage": null,
"userBehaviour": {
"engagementScreenShown": false,
"pushNotificationsBanner": {
"forceDismissionDate": undefined,
"timesDismissed": 0,
},
"pushNotificationBannerDismissalCount": 0,
"pushNotificationBannerForceDismissionDate": undefined,
},
}
`;
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,7 @@

exports[`userBehaviourReducer Should match snapshot 1`] = `
{
"engagementScreenShown": false,
"pushNotificationsBanner": {
"forceDismissionDate": undefined,
"timesDismissed": 0,
},
"pushNotificationBannerDismissalCount": 0,
"pushNotificationBannerForceDismissionDate": undefined,
}
`;
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,15 @@ import {
} from "../../../../../store/actions/application";
import { GlobalState } from "../../../../../store/reducers/types";
import {
setEngagementScreenShown,
setPushPermissionsRequestDuration,
updateSystemNotificationsEnabled
} from "../../actions/environment";
import { notificationsInfoScreenConsent } from "../../actions/profileNotificationPermissions";
import {
areNotificationPermissionsEnabled,
INITIAL_STATE,
environmentReducer
environmentReducer,
INITIAL_STATE
} from "../environment";

describe("environment reducer initial state", () => {
Expand Down Expand Up @@ -42,7 +43,8 @@ describe("environmentReducer", () => {
{
applicationInitialized: false,
onboardingInstructionsShown: false,
systemNotificationsEnabled: true
systemNotificationsEnabled: true,
engagementScreenShownThisSession: false
},
updateSystemNotificationsEnabled(false)
);
Expand All @@ -55,7 +57,8 @@ describe("environmentReducer", () => {
{
applicationInitialized: false,
onboardingInstructionsShown: false,
systemNotificationsEnabled: false
systemNotificationsEnabled: false,
engagementScreenShownThisSession: false
},
notificationsInfoScreenConsent()
);
Expand All @@ -68,7 +71,8 @@ describe("environmentReducer", () => {
{
applicationInitialized: false,
onboardingInstructionsShown: false,
systemNotificationsEnabled: false
systemNotificationsEnabled: false,
engagementScreenShownThisSession: false
},
applicationInitialized({ actionsToWaitFor: [] })
);
Expand All @@ -81,14 +85,27 @@ describe("environmentReducer", () => {
{
applicationInitialized: true,
onboardingInstructionsShown: false,
systemNotificationsEnabled: false
systemNotificationsEnabled: false,
engagementScreenShownThisSession: false
},
setPushPermissionsRequestDuration(100)
);
expect(userBehaviourState.pushNotificationPermissionsRequestDuration).toBe(
100
);
});
it("'engagementScreenShownThisSession' should be 'true' after receiving 'setEngagementScreenShown'", () => {
const userBehaviourState = environmentReducer(
{
applicationInitialized: true,
onboardingInstructionsShown: false,
systemNotificationsEnabled: false,
engagementScreenShownThisSession: false
},
setEngagementScreenShown()
);
expect(userBehaviourState.engagementScreenShownThisSession).toBe(true);
});
});

describe("areNotificationPermissionsEnabled selector", () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,29 +48,38 @@ describe("shouldShowEngagementScreenSelector", () => {
[false, true].forEach(applicationInitialized =>
[false, true].forEach(onboardingInstructionsShown =>
[false, true].forEach(systemNotificationsEnabled =>
[false, true].forEach(engagementScreenShown => {
const expectedOutput =
applicationInitialized &&
!onboardingInstructionsShown &&
!systemNotificationsEnabled &&
!engagementScreenShown;
it(`Should output '${expectedOutput}' when 'applicationInitialized' is '${applicationInitialized}' , 'onboardingInstructionsShown' is '${onboardingInstructionsShown}' , 'systemNotificationsEnabled' is '${systemNotificationsEnabled} ' and 'engagementScreenShown' is '${engagementScreenShown}' `, () => {
const state = {
notifications: {
environment: {
applicationInitialized,
onboardingInstructionsShown,
systemNotificationsEnabled
[false, true].forEach(userFromSuccessLogin =>
[10, 900].forEach(pushNotificationPermissionsRequestDuration => {
const expectedOutput =
userFromSuccessLogin &&
!systemNotificationsEnabled &&
pushNotificationPermissionsRequestDuration < 750 &&
applicationInitialized &&
!onboardingInstructionsShown;

it(`Should output '${expectedOutput}' when 'applicationInitialized' is '${applicationInitialized}' , 'onboardingInstructionsShown' is '${onboardingInstructionsShown}' , 'systemNotificationsEnabled' is '${systemNotificationsEnabled} ' `, () => {
const state = {
features: {
loginFeatures: {
loginInfo: {
userFromSuccessLogin
}
}
},
userBehaviour: {
engagementScreenShown
notifications: {
environment: {
applicationInitialized,
onboardingInstructionsShown,
systemNotificationsEnabled,
pushNotificationPermissionsRequestDuration
}
}
}
} as GlobalState;
const output = shouldShowEngagementScreenSelector(state);
expect(output).toBe(expectedOutput);
});
})
} as GlobalState;
const output = shouldShowEngagementScreenSelector(state);
expect(output).toBe(expectedOutput);
});
})
)
)
)
);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,36 +1,25 @@
import { applicationChangeState } from "../../../../../store/actions/application";
import {
resetNotificationBannerDismissState,
setEngagementScreenShown,
setPushNotificationBannerForceDismissed,
setUserDismissedNotificationsBanner
} from "../../actions/userBehaviour";
import { INITIAL_STATE, userBehaviourReducer } from "../userBehaviour";
import { userBehaviourReducer, UserBehaviourState } from "../userBehaviour";

describe("userBehaviourReducer", () => {
it("INITIAL_STATE should match expected values", () => {
expect(INITIAL_STATE.engagementScreenShown).toBe(false);
});
it("Should match snapshot", () => {
const userBehaviourState = userBehaviourReducer(
undefined,
applicationChangeState("active")
);
expect(userBehaviourState).toMatchSnapshot();
});
it("'engagementScreenShown' should be 'true' after receiving 'setEngagementScreenShown'", () => {
const userBehaviourState = userBehaviourReducer(
undefined,
setEngagementScreenShown()
);
expect(userBehaviourState.engagementScreenShown).toBe(true);
});
it(' "pushNotificationsBanner.timesDismissed" should be "1" after receiving "setUserDismissedNotificationsBanner"', () => {
const userBehaviourState = userBehaviourReducer(
undefined,
setUserDismissedNotificationsBanner()
);
expect(userBehaviourState.pushNotificationsBanner.timesDismissed).toBe(1);
expect(userBehaviourState.pushNotificationBannerDismissalCount).toBe(1);
});
it(' "pushNotificationsBanner.forceDismissionDate" should be "Date" after receiving "setPushNotificationBannerForceDismissed"', () => {
const userBehaviourState = userBehaviourReducer(
Expand All @@ -39,17 +28,17 @@ describe("userBehaviourReducer", () => {
);

expect(
typeof userBehaviourState.pushNotificationsBanner.forceDismissionDate
typeof userBehaviourState.pushNotificationBannerForceDismissionDate
).toBe("number");
});
it("pushNotificationsBanner should match initial state upon receiving 'resetNotificationBannerDismissState", () => {
const userBehaviourState = userBehaviourReducer(
undefined,
resetNotificationBannerDismissState()
);
expect(userBehaviourState.pushNotificationsBanner).toEqual({
timesDismissed: 0,
forceDismissionDate: undefined
});
expect(userBehaviourState).toEqual({
pushNotificationBannerDismissalCount: 0,
pushNotificationBannerForceDismissionDate: undefined
} as UserBehaviourState);
});
});
Loading

0 comments on commit 9d41018

Please sign in to comment.