From ca4318ce695da1dcc0d989ed62eb58b3f288a270 Mon Sep 17 00:00:00 2001 From: Kevin J Gao <32936811+gaokevin1@users.noreply.github.com> Date: Mon, 16 Dec 2024 13:31:02 -0800 Subject: [PATCH] feat:add moment type support --- packages/sdks/web-js-sdk/src/sdk/fedcm.ts | 23 ++++++- packages/sdks/web-js-sdk/test/fedcm.test.ts | 70 +++++++++++++++++++++ 2 files changed, 92 insertions(+), 1 deletion(-) diff --git a/packages/sdks/web-js-sdk/src/sdk/fedcm.ts b/packages/sdks/web-js-sdk/src/sdk/fedcm.ts index 181f27657..c885d3b14 100644 --- a/packages/sdks/web-js-sdk/src/sdk/fedcm.ts +++ b/packages/sdks/web-js-sdk/src/sdk/fedcm.ts @@ -100,6 +100,8 @@ type OneTapInitialize = ({ type PromptNotification = { isSkippedMoment: () => boolean; + isDismissedMoment: () => boolean; + getMomentType: () => string; }; /** @@ -113,6 +115,7 @@ const createFedCM = (sdk: CoreSdk, projectId: string) => ({ oneTapConfig?: OneTapConfig, loginOptions?: LoginOptions, onSkip?: () => void, + onDismissed?: () => void, ) { const readyProvider = provider ?? 'google'; const startResponse = await sdk.oauth.startNative( @@ -150,8 +153,26 @@ const createFedCM = (sdk: CoreSdk, projectId: string) => ({ }); googleClient.prompt((notification) => { - if (notification?.isSkippedMoment()) { + const momentType = notification?.getMomentType(); + + if (!momentType) { + // Default to skipping behavior if no notification is provided onSkip?.(); + return; + } + + switch (momentType) { + case 'skipped': + onSkip?.(); + break; + case 'dismissed': + onDismissed?.(); + break; + case 'display': + break; + default: + reportError(`Unexpected One Tap moment type: ${momentType}`); + break; } }); }); diff --git a/packages/sdks/web-js-sdk/test/fedcm.test.ts b/packages/sdks/web-js-sdk/test/fedcm.test.ts index 263a61252..cd3822b27 100644 --- a/packages/sdks/web-js-sdk/test/fedcm.test.ts +++ b/packages/sdks/web-js-sdk/test/fedcm.test.ts @@ -135,6 +135,76 @@ describe('fedcm', () => { expect(onSkip).toHaveBeenCalled(); }); }); + describe('momentType handling', () => { + it('handles skipped moment correctly', async () => { + coreJs.oauth.startNative.mockResolvedValue({ + ok: true, + data: { clientId: 'C123', stateId: 'S123', nonce: 'N123' }, + }); + + const onSkip = jest.fn(); + + sdk.fedcm.oneTap( + 'google', + { auto_select: true }, + { stepup: false }, + onSkip, + ); + await new Promise(process.nextTick); + + const promptCallback = googleClient.prompt.mock.calls[0][0]; + promptCallback({ getMomentType: () => 'skipped', isSkippedMoment: () => true }); + + expect(onSkip).toHaveBeenCalled(); + }); + + it('handles dismissed moment correctly', async () => { + coreJs.oauth.startNative.mockResolvedValue({ + ok: true, + data: { clientId: 'C123', stateId: 'S123', nonce: 'N123' }, + }); + + const onDismissed = jest.fn(); + + sdk.fedcm.oneTap( + 'google', + { auto_select: true }, + { stepup: false }, + undefined, + onDismissed, + ); + await new Promise(process.nextTick); + + const promptCallback = googleClient.prompt.mock.calls[0][0]; + promptCallback({ getMomentType: () => 'dismissed', isDismissedMoment: () => true }); + + expect(onDismissed).toHaveBeenCalled(); + }); + + it('handles display moment correctly', async () => { + coreJs.oauth.startNative.mockResolvedValue({ + ok: true, + data: { clientId: 'C123', stateId: 'S123', nonce: 'N123' }, + }); + + const onDisplay = jest.fn(); + + sdk.fedcm.oneTap( + 'google', + { auto_select: true }, + { stepup: false }, + undefined, + undefined, + ); + await new Promise(process.nextTick); + + const promptCallback = googleClient.prompt.mock.calls[0][0]; + promptCallback({ getMomentType: () => 'display' }); + + // Verify no callbacks are called for 'display' + expect(onDisplay).not.toHaveBeenCalled() + }); + }); describe('launch', () => { it('should call navigator.credentials.get with correct parameters', async () => { const mockGet = jest.fn();