UNPKG

salsify-experiences-sdk

Version:

SDK to be used by commerce websites to implement product experiences.

133 lines (115 loc) 4.2 kB
/** * @jest-environment jsdom * @jest-environment-options {"url": "https://salsify-ecdn.com/sdk/client-id/lang-code/BTF/id-type/existing-product/index.html"} */ import SdkApi from '../api' import { MessageChannel as WorkerThreadsMessageChannel } from 'worker_threads' import { SDK_VERSION } from '../version' const uuidRegex = /^[0-9a-f]{8}\b-[0-9a-f]{4}\b-[0-9a-f]{4}\b-[0-9a-f]{4}\b-[0-9a-f]{12}$/ const defaultOptions = { clientId: 'client-id', } describe('SdkApi', () => { let sdk: SdkApi beforeEach(() => { sdk = new SdkApi('npm') }) describe('SDK context communication', () => { let contextReceived: (value?: unknown) => void const waitForContext = (): Promise<unknown> => new Promise(resolve => (contextReceived = resolve)) let messageListener: ((event: MessageEvent) => void) | undefined let channel: MessageChannel | undefined // workaround for https://github.com/jsdom/jsdom/issues/2745 const messageMonkeyPatch = (event: MessageEvent): void => { if (event.origin === '' && event.data.messageType === 'contextRequest') { event.stopImmediatePropagation() const eventWithOriginInitDict: MessageEventInit = { data: event.data, origin: 'https://salsify-ecdn.com', source: window, } if (channel) { eventWithOriginInitDict.ports = [channel.port2] } const eventWithOrigin: MessageEvent = new MessageEvent('message', eventWithOriginInitDict) window.dispatchEvent(eventWithOrigin) } } beforeAll(() => { window.addEventListener('message', messageMonkeyPatch) }) afterAll(() => { window.removeEventListener('message', messageMonkeyPatch) }) beforeEach(() => { messageListener = jest.fn().mockImplementation((event: MessageEvent) => { if (event.data.clientId) { contextReceived() } }) sdk.init(defaultOptions) }) afterEach(() => { messageListener = undefined }) test('Using MessageChannel', async () => { channel = new WorkerThreadsMessageChannel() as unknown as MessageChannel channel!.port1.onmessage = messageListener! window.postMessage({ messageType: 'contextRequest' }, '*', [channel!.port2]) await waitForContext() expect(messageListener).toHaveBeenCalledTimes(1) expect(messageListener).toHaveBeenCalledWith( expect.objectContaining({ data: { url: 'https://salsify-ecdn.com/sdk/client-id/lang-code/BTF/id-type/existing-product/index.html', sessionId: expect.stringMatching(uuidRegex), pageSessionId: expect.stringMatching(uuidRegex), tracking: true, clientId: defaultOptions.clientId, languageCode: 'en-US', enhancedContent: { idType: 'SDKID', }, version: SDK_VERSION, jsSource: 'npm', }, }) ) channel!.port1.onmessage = null channel = undefined }) test('Using postMessage', async () => { window.addEventListener('message', messageListener!) window.postMessage({ messageType: 'contextRequest' }, '*') await waitForContext() expect(messageListener).toHaveBeenCalledTimes(2) expect(messageListener).toHaveBeenNthCalledWith( 1, expect.objectContaining({ data: { messageType: 'contextRequest', }, }) ) expect(messageListener).toHaveBeenNthCalledWith( 2, expect.objectContaining({ data: { url: 'https://salsify-ecdn.com/sdk/client-id/lang-code/BTF/id-type/existing-product/index.html', sessionId: expect.stringMatching(uuidRegex), pageSessionId: expect.stringMatching(uuidRegex), tracking: true, clientId: defaultOptions.clientId, languageCode: 'en-US', enhancedContent: { idType: 'SDKID', }, version: SDK_VERSION, jsSource: 'npm', }, }) ) window.removeEventListener('message', messageListener!) }) }) })