From 3c0645cbb044c999a3027ec211cfc954752d1415 Mon Sep 17 00:00:00 2001 From: Braxton Ward Date: Tue, 21 Jul 2026 11:14:47 -0600 Subject: [PATCH] feat: support account deeplink step (SDK-695) Add 'account' to the Step constant so apps can deeplink directly to an Account/Merchant page. The accountId config property and the native iOS (3.34.0) and Android (3.23.0) SDKs already support this; this exposes the step value and adds config-to-JSON conversion test coverage. --- src/__tests__/index.test.tsx | 74 +++++++++++++++++++++++++++++++++++- src/constants.tsx | 1 + 2 files changed, 74 insertions(+), 1 deletion(-) diff --git a/src/__tests__/index.test.tsx b/src/__tests__/index.test.tsx index bf84291..a0f0e87 100644 --- a/src/__tests__/index.test.tsx +++ b/src/__tests__/index.test.tsx @@ -1 +1,73 @@ -it.todo('write a test'); +const mockIOSTransact = jest.fn(); +const mockAndroidTransact = jest.fn(); + +jest.mock('react-native', () => ({ + Platform: { OS: 'ios', select: (obj: any) => obj.ios ?? obj.default }, + NativeModules: { TransactReactNative: {} }, + Appearance: { getColorScheme: () => 'light' }, + NativeEventEmitter: jest.fn(), + DeviceEventEmitter: { addListener: jest.fn() }, +})); + +jest.mock('../ios', () => ({ + AtomicIOS: { transact: (...args: any[]) => mockIOSTransact(...args) }, +})); +jest.mock('../android', () => ({ + AtomicAndroid: { transact: (...args: any[]) => mockAndroidTransact(...args) }, +})); + +import { Atomic, Step } from '../index'; + +beforeEach(() => { + mockIOSTransact.mockClear(); + mockAndroidTransact.mockClear(); +}); + +describe('account deeplink config', () => { + it('exposes account as a valid deeplink step', () => { + expect(Step.ACCOUNT).toBe('account'); + }); + + it('forwards the account step and accountId through config-to-JSON conversion', () => { + Atomic.transact({ + config: { + publicToken: 'pt-abc-123', + scope: 'user-link', + deeplink: { step: Step.ACCOUNT, accountId: 'abc123' }, + tasks: [{ operation: 'auth' }], + }, + }); + + expect(mockIOSTransact).toHaveBeenCalledTimes(1); + + // The RN bridge serializes the config to JSON before it reaches native. + // Round-trip it here to assert the account deeplink survives that conversion. + const { config } = mockIOSTransact.mock.calls[0][0]; + const serialized = JSON.parse(JSON.stringify(config)); + + expect(serialized.deeplink).toEqual({ + step: 'account', + accountId: 'abc123', + }); + }); + + it('leaves other deeplink steps and payload fields unchanged', () => { + Atomic.transact({ + config: { + publicToken: 'pt-abc-123', + scope: 'user-link', + deeplink: { step: Step.SEARCH_COMPANY, companyId: 'co-1' }, + tasks: [{ operation: 'auth' }], + }, + }); + + const { config } = mockIOSTransact.mock.calls[0][0]; + const serialized = JSON.parse(JSON.stringify(config)); + + expect(serialized.deeplink).toEqual({ + step: 'search-company', + companyId: 'co-1', + }); + expect(serialized.deeplink.accountId).toBeUndefined(); + }); +}); diff --git a/src/constants.tsx b/src/constants.tsx index b05c675..8852467 100644 --- a/src/constants.tsx +++ b/src/constants.tsx @@ -62,6 +62,7 @@ export const Step = { LOGIN_PAYROLL: 'login-payroll', SEARCH_COMPANY: 'search-company', SEARCH_PAYROLL: 'search-payroll', + ACCOUNT: 'account', } as const; export type StepType = (typeof Step)[keyof typeof Step] | (string & {});