UNPKG

@ledgerhq/live-common

Version:
400 lines (355 loc) • 13.7 kB
import { DeviceModelId } from "@ledgerhq/types-devices"; import { PostOnboardingActionId, PostOnboardingState } from "@ledgerhq/types-live"; import reducer, { hubStateSelector, initialState, postOnboardingDeviceModelIdSelector, postOnboardingSelector, walletEntryPointEligibleForPortfolioSelector, } from "./reducer"; import { importPostOnboardingState, initPostOnboarding, setPostOnboardingActionCompleted, clearPostOnboardingLastActionCompleted, hidePostOnboardingWalletEntryPoint, setPostOnboardingWalletEntryPointEligibility, } from "./actions"; const initializationParamsA: Parameters<typeof initPostOnboarding> = [ { deviceModelId: DeviceModelId.nanoX, actionsIds: [ PostOnboardingActionId.claimMock, PostOnboardingActionId.migrateAssetsMock, PostOnboardingActionId.personalizeMock, ], }, ]; // initialState -> importPostOnboardingState(...initializationParamsA) const stateA0: PostOnboardingState = { deviceModelId: DeviceModelId.nanoX, walletEntryPointDismissed: false, entryPointFirstDisplayedDate: new Date("2020-01-20"), walletEntryPointEligibleForPortfolio: null, actionsToComplete: [ PostOnboardingActionId.claimMock, PostOnboardingActionId.migrateAssetsMock, PostOnboardingActionId.personalizeMock, ], actionsCompleted: { [PostOnboardingActionId.claimMock]: false, [PostOnboardingActionId.migrateAssetsMock]: false, [PostOnboardingActionId.personalizeMock]: false, }, lastActionCompleted: null, postOnboardingInProgress: true, }; // stateA0 -> setPostOnboardingActionCompleted(claimMock) const stateA1: PostOnboardingState = { deviceModelId: DeviceModelId.nanoX, walletEntryPointDismissed: false, entryPointFirstDisplayedDate: new Date("2020-01-20"), walletEntryPointEligibleForPortfolio: null, actionsToComplete: [ PostOnboardingActionId.claimMock, PostOnboardingActionId.migrateAssetsMock, PostOnboardingActionId.personalizeMock, ], actionsCompleted: { [PostOnboardingActionId.claimMock]: true, // stateA0 -> setPostOnboardingActionCompleted(claimMock) [PostOnboardingActionId.migrateAssetsMock]: false, [PostOnboardingActionId.personalizeMock]: false, }, lastActionCompleted: PostOnboardingActionId.claimMock, // stateA0 -> setPostOnboardingActionCompleted(claimMock) postOnboardingInProgress: true, }; // stateA1 -> clearPostOnboardingLastActionCompleted() const stateA2: PostOnboardingState = { deviceModelId: DeviceModelId.nanoX, walletEntryPointDismissed: false, entryPointFirstDisplayedDate: new Date("2020-01-20"), walletEntryPointEligibleForPortfolio: null, actionsToComplete: [ PostOnboardingActionId.claimMock, PostOnboardingActionId.migrateAssetsMock, PostOnboardingActionId.personalizeMock, ], actionsCompleted: { [PostOnboardingActionId.claimMock]: true, [PostOnboardingActionId.migrateAssetsMock]: false, [PostOnboardingActionId.personalizeMock]: false, }, lastActionCompleted: null, // stateA1 -> clearPostOnboardingLastActionCompleted() postOnboardingInProgress: true, }; // stateA2 -> setPostOnboardingActionCompleted(personalizeMock) const stateA3: PostOnboardingState = { deviceModelId: DeviceModelId.nanoX, walletEntryPointDismissed: false, entryPointFirstDisplayedDate: new Date("2020-01-20"), walletEntryPointEligibleForPortfolio: null, actionsToComplete: [ PostOnboardingActionId.claimMock, PostOnboardingActionId.migrateAssetsMock, PostOnboardingActionId.personalizeMock, ], actionsCompleted: { [PostOnboardingActionId.claimMock]: true, [PostOnboardingActionId.migrateAssetsMock]: false, [PostOnboardingActionId.personalizeMock]: true, // stateA2 -> setPostOnboardingActionCompleted(personalizeMock) }, lastActionCompleted: PostOnboardingActionId.personalizeMock, // stateA2 -> setPostOnboardingActionCompleted(personalizeMock) postOnboardingInProgress: true, }; // stateA3 -> hidePostOnboardingWalletEntryPoint() const stateA4: PostOnboardingState = { deviceModelId: DeviceModelId.nanoX, walletEntryPointDismissed: true, // stateA3 -> hidePostOnboardingWalletEntryPoint() entryPointFirstDisplayedDate: null, walletEntryPointEligibleForPortfolio: null, actionsToComplete: [ PostOnboardingActionId.claimMock, PostOnboardingActionId.migrateAssetsMock, PostOnboardingActionId.personalizeMock, ], actionsCompleted: { [PostOnboardingActionId.claimMock]: true, [PostOnboardingActionId.migrateAssetsMock]: false, [PostOnboardingActionId.personalizeMock]: true, }, lastActionCompleted: PostOnboardingActionId.personalizeMock, postOnboardingInProgress: true, }; const initializationParamsB: Parameters<typeof initPostOnboarding> = [ { deviceModelId: DeviceModelId.nanoS, actionsIds: [PostOnboardingActionId.claimMock], }, ]; // initialState -> importPostOnboardingState(...initializationParamsB) const stateB0 = { deviceModelId: DeviceModelId.nanoS, walletEntryPointDismissed: false, entryPointFirstDisplayedDate: new Date("2020-01-20"), walletEntryPointEligibleForPortfolio: null, actionsToComplete: [PostOnboardingActionId.claimMock], actionsCompleted: { [PostOnboardingActionId.claimMock]: false }, lastActionCompleted: null, postOnboardingInProgress: true, }; // stateB0 -> setPostOnboardingActionCompleted(claimMock) const stateB1 = { deviceModelId: DeviceModelId.nanoS, walletEntryPointDismissed: false, entryPointFirstDisplayedDate: new Date("2020-01-20"), walletEntryPointEligibleForPortfolio: null, actionsToComplete: [PostOnboardingActionId.claimMock], actionsCompleted: { [PostOnboardingActionId.claimMock]: true }, lastActionCompleted: PostOnboardingActionId.claimMock, postOnboardingInProgress: true, }; const initializationParamsC: Parameters<typeof initPostOnboarding> = [ { deviceModelId: DeviceModelId.nanoSP, actionsIds: [], }, ]; // initialState -> importPostOnboardingState(...initializationParamsC) const stateC0 = { deviceModelId: DeviceModelId.nanoSP, walletEntryPointDismissed: false, entryPointFirstDisplayedDate: new Date("2020-01-20"), walletEntryPointEligibleForPortfolio: null, actionsToComplete: [], actionsCompleted: {}, lastActionCompleted: null, postOnboardingInProgress: true, }; describe("postOnboarding reducer (& action creators)", () => { beforeAll(() => { jest.useFakeTimers().setSystemTime(new Date("2020-01-20")); }); afterAll(() => { jest.runOnlyPendingTimers(); jest.useRealTimers(); }); let state; beforeEach(() => { // reset state to initial state; state = reducer(undefined, {} as any); }); it("should initialize the state properly", () => { expect(state).toEqual(initialState); }); it("should handle importPostOnboardingState", () => { state = reducer(state, importPostOnboardingState({ newState: stateA0 })); expect(state).toEqual(stateA0); state = reducer(state, importPostOnboardingState({ newState: stateA1 })); expect(state).toEqual(stateA1); }); it("should handle initPostOnboarding", () => { state = reducer(state, initPostOnboarding(...initializationParamsA)); expect(state).toEqual(stateA0); }); it("should handle setPostOnboardingActionCompleted", () => { state = stateA0; state = reducer( state, setPostOnboardingActionCompleted({ actionId: PostOnboardingActionId.claimMock, }), ); expect(state).toEqual(stateA1); }); it("should handle clearPostOnboardingLastActionCompleted", () => { state = stateA1; state = reducer(state, clearPostOnboardingLastActionCompleted()); expect(state).toEqual({ ...stateA2 }); }); it("should handle hidePostOnboardingWalletEntryPoint", () => { state = stateA3; state = reducer(state, hidePostOnboardingWalletEntryPoint()); expect(state).toEqual(stateA4); }); it("should handle setPostOnboardingWalletEntryPointEligibility", () => { state = stateA0; state = reducer(state, setPostOnboardingWalletEntryPointEligibility(true)); expect(state.walletEntryPointEligibleForPortfolio).toBe(true); state = reducer(state, setPostOnboardingWalletEntryPointEligibility(false)); expect(state.walletEntryPointEligibleForPortfolio).toBe(false); const stateBefore = state; state = reducer(state, { type: "POST_ONBOARDING_SET_WALLET_ENTRY_POINT_ELIGIBILITY", // @ts-expect-error - testing with null payload payload: null, }); expect(state).toBe(stateBefore); expect(state.walletEntryPointEligibleForPortfolio).toBe(false); state = reducer(state, { type: "POST_ONBOARDING_SET_WALLET_ENTRY_POINT_ELIGIBILITY", payload: undefined, }); expect(state).toBe(stateBefore); state = reducer(state, { type: "POST_ONBOARDING_SET_WALLET_ENTRY_POINT_ELIGIBILITY", // @ts-expect-error - testing with string payload payload: "true", }); expect(state).toBe(stateBefore); }); it("should handle successive actions properly", () => { // initializing state with new device & set of actions state = reducer(state, initPostOnboarding(...initializationParamsA)); expect(state).toEqual(stateA0); // setting completed for claimMock state = reducer( state, setPostOnboardingActionCompleted({ actionId: PostOnboardingActionId.claimMock, }), ); expect(state).toEqual(stateA1); // clearing last completed action state = reducer(state, clearPostOnboardingLastActionCompleted()); expect(state).toEqual(stateA2); // setting completed for personalizeMock state = reducer( state, setPostOnboardingActionCompleted({ actionId: PostOnboardingActionId.personalizeMock, }), ); expect(state).toEqual(stateA3); // hiding wallet entrypoint state = reducer(state, hidePostOnboardingWalletEntryPoint()); expect(state).toEqual(stateA4); // initializing state with new device & set of actions state = reducer(state, initPostOnboarding(...initializationParamsB)); expect(state).toEqual(stateB0); // setting completed for claimMock state = reducer( state, setPostOnboardingActionCompleted({ actionId: PostOnboardingActionId.claimMock, }), ); expect(state).toEqual(stateB1); // initializing state with new device & set of actions state = reducer(state, initPostOnboarding(...initializationParamsC)); expect(state).toEqual(stateC0); }); }); describe("postOnboarding selectors", () => { it("should keep valid device ids", () => { const stateValidDeviceId: PostOnboardingState = { deviceModelId: DeviceModelId.nanoX, walletEntryPointDismissed: false, entryPointFirstDisplayedDate: new Date("2020-01-20"), actionsToComplete: [], actionsCompleted: {}, lastActionCompleted: null, postOnboardingInProgress: false, walletEntryPointEligibleForPortfolio: null, }; const storeState = { postOnboarding: stateValidDeviceId }; const postOnboarding = postOnboardingSelector(storeState); expect(postOnboarding).toEqual(stateValidDeviceId); const hubState = hubStateSelector(storeState); expect(hubState).toEqual({ deviceModelId: stateValidDeviceId.deviceModelId, actionsToComplete: stateValidDeviceId.actionsToComplete, actionsCompleted: stateValidDeviceId.actionsCompleted, lastActionCompleted: stateValidDeviceId.lastActionCompleted, postOnboardingInProgress: false, }); const deviceModelId = postOnboardingDeviceModelIdSelector(storeState); expect(deviceModelId).toEqual(stateValidDeviceId.deviceModelId); }); it('should sanitize "nanoFTS" device ids to "stax"', () => { const stateValidDeviceId: PostOnboardingState = { // @ts-expect-error - testing with "nanoFTS" device id deviceModelId: "nanoFTS", walletEntryPointDismissed: false, entryPointFirstDisplayedDate: new Date("2020-01-20"), actionsToComplete: [], actionsCompleted: {}, lastActionCompleted: null, postOnboardingInProgress: false, walletEntryPointEligibleForPortfolio: null, }; const storeState = { postOnboarding: stateValidDeviceId }; const postOnboarding = postOnboardingSelector(storeState); expect(postOnboarding).toEqual({ ...stateValidDeviceId, deviceModelId: DeviceModelId.stax, }); const hubState = hubStateSelector(storeState); expect(hubState).toEqual({ deviceModelId: DeviceModelId.stax, actionsToComplete: stateValidDeviceId.actionsToComplete, actionsCompleted: stateValidDeviceId.actionsCompleted, lastActionCompleted: stateValidDeviceId.lastActionCompleted, postOnboardingInProgress: false, }); const deviceModelId = postOnboardingDeviceModelIdSelector(storeState); expect(deviceModelId).toEqual(DeviceModelId.stax); }); it("should return walletEntryPointEligibleForPortfolio from state", () => { const storeStateTrue = { postOnboarding: { ...initialState, walletEntryPointEligibleForPortfolio: true, }, }; expect(walletEntryPointEligibleForPortfolioSelector(storeStateTrue)).toBe(true); const storeStateFalse = { postOnboarding: { ...initialState, walletEntryPointEligibleForPortfolio: false, }, }; expect(walletEntryPointEligibleForPortfolioSelector(storeStateFalse)).toBe(false); const storeStateNull = { postOnboarding: initialState }; expect(walletEntryPointEligibleForPortfolioSelector(storeStateNull)).toBe(null); }); });