Skip to content

Commit

Permalink
feat(clerk-js): Add tests and the mockNativeRuntime helper
Browse files Browse the repository at this point in the history
  • Loading branch information
BRKalow committed Aug 22, 2023
1 parent 7ec06e7 commit c4b749b
Show file tree
Hide file tree
Showing 2 changed files with 75 additions and 1 deletion.
39 changes: 38 additions & 1 deletion packages/clerk-js/src/core/clerk.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type { ActiveSessionResource, SignInJSON, SignUpJSON, TokenResource } from '@clerk/types';
import { waitFor } from '@testing-library/dom';

import { mockNativeRuntime } from '../testUtils';
import Clerk from './clerk';
import { eventBus, events } from './events';
import type { AuthConfig, DisplayConfig, Organization } from './resources/internal';
Expand Down Expand Up @@ -91,7 +92,10 @@ describe('Clerk singleton', () => {
};

Object.defineProperty(global.window, 'location', { value: mockWindowLocation });
Object.defineProperty(global.window.document, 'hasFocus', { value: () => true, configurable: true });

if (typeof globalThis.document !== 'undefined') {
Object.defineProperty(global.window.document, 'hasFocus', { value: () => true, configurable: true });
}

const mockAddEventListener = (type: string, callback: (e: any) => void) => {
if (type === 'message') {
Expand Down Expand Up @@ -295,6 +299,39 @@ describe('Clerk singleton', () => {
expect(sut.session).toMatchObject(mockSession);
});
});

mockNativeRuntime(() => {
it('calls session.touch in a non-standard browser', async () => {
mockClientFetch.mockReturnValue(Promise.resolve({ activeSessions: [mockSession] }));

const sut = new Clerk(frontendApi);
await sut.load({ standardBrowser: false });

const executionOrder: string[] = [];
mockSession.touch.mockImplementationOnce(() => {
sut.session = mockSession as any;
executionOrder.push('session.touch');
return Promise.resolve();
});
cookieSpy.mockImplementationOnce(() => {
executionOrder.push('set cookie');
return Promise.resolve();
});
const beforeEmitMock = jest.fn().mockImplementationOnce(() => {
executionOrder.push('before emit');
return Promise.resolve();
});

await sut.setActive({ organization: { id: 'org-id' } as Organization, beforeEmit: beforeEmitMock });

expect(executionOrder).toEqual(['session.touch', 'before emit']);
expect(mockSession.touch).toHaveBeenCalled();
expect((mockSession as any as ActiveSessionResource)?.lastActiveOrganizationId).toEqual('org-id');
expect(cookieSpy).not.toHaveBeenCalled();
expect(beforeEmitMock).toBeCalledWith(mockSession);
expect(sut.session).toMatchObject(mockSession);
});
});
});

describe('.load()', () => {
Expand Down
37 changes: 37 additions & 0 deletions packages/clerk-js/src/testUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,43 @@ const render = (ui: React.ReactElement, options?: RenderOptions) => {
return { ..._render(ui, { ...options }), userEvent };
};

/**
* Helper method to mock a native runtime environment for specific test cases, currently targeted at React Native.
* Makes some assumptions about our runtime detection utilities in `packages/clerk-js/src/utils/runtime.ts`.
*
* Usage:
*
* ```js
* mockNativeRuntime(() => {
* // test cases
* it('simulates native', () => {
* expect(typeof document).toBe('undefined');
* });
* });
* ```
*/
export const mockNativeRuntime = (fn: () => void) => {
describe('native runtime', () => {
let spyDocument: jest.SpyInstance;
let spyNavigator: jest.SpyInstance;

beforeAll(() => {
spyDocument = jest.spyOn(globalThis, 'document', 'get');
spyDocument.mockReturnValue(undefined);

spyNavigator = jest.spyOn(globalThis.navigator, 'product', 'get');
spyNavigator.mockReturnValue('ReactNative');
});

afterAll(() => {
spyDocument.mockRestore();
spyNavigator.mockRestore();
});

fn();
});
};

export * from './ui/utils/test/runFakeTimers';
export * from './ui/utils/test/createFixtures';
export * from '@testing-library/react';
Expand Down

0 comments on commit c4b749b

Please sign in to comment.