From 97244a54449295bf2cf57c15987398a3d5f6f1c0 Mon Sep 17 00:00:00 2001 From: eunjae-lee Date: Mon, 9 Nov 2020 14:08:38 +0100 Subject: [PATCH 1/7] test: test if insightsClient does not throw when an event is sent right after creating the middleware --- .../__tests__/createInsightsMiddleware.ts | 16 ++++++++++++++++ test/mock/createInsightsClient.ts | 14 +++++++++++++- 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/src/middlewares/__tests__/createInsightsMiddleware.ts b/src/middlewares/__tests__/createInsightsMiddleware.ts index 1cd291fa49..817defcf20 100644 --- a/src/middlewares/__tests__/createInsightsMiddleware.ts +++ b/src/middlewares/__tests__/createInsightsMiddleware.ts @@ -79,6 +79,22 @@ describe('insights', () => { }); }); + it('does not throw when an event is sent right after the creation', () => { + const { insightsClient, instantSearchInstance } = createTestEnvironment(); + createInsightsMiddleware({ + insightsClient, + })({ instantSearchInstance }); + + expect(() => { + insightsClient('viewedObjectIDs', { + userToken: 'my-user-token', + index: instantSearchInstance.indexName, + eventName: 'Products Viewed', + objectIDs: ['obj-id0', 'obj-id1'], + }); + }).not.toThrow(); + }); + it('warns dev if userToken is set before creating the middleware', () => { const { insightsClient, instantSearchInstance } = createTestEnvironment(); insightsClient('setUserToken', 'abc'); diff --git a/test/mock/createInsightsClient.ts b/test/mock/createInsightsClient.ts index b4cff2c4d5..ace76062dd 100644 --- a/test/mock/createInsightsClient.ts +++ b/test/mock/createInsightsClient.ts @@ -26,13 +26,25 @@ export function createAlgoliaAnalytics() { callback(values._userToken); } }; + const viewedObjectIDs = jest.fn(() => { + if (!values._apiKey) { + throw new Error( + 'apiKey is missing, please provide it so we can authenticate the application' + ); + } + if (!values._appId) { + throw new Error( + 'appId is missing, please provide it, so we can properly attribute data to your application' + ); + } + }); return { setUserToken, init, _get, onUserTokenChange, - viewedObjectIDs: jest.fn(), + viewedObjectIDs, }; } From 9effefd71eb43592e7d045b604d4e2d5b2f7e50e Mon Sep 17 00:00:00 2001 From: eunjae-lee Date: Mon, 9 Nov 2020 17:01:34 +0100 Subject: [PATCH 2/7] fix: restore user token which was set before creating the middleware --- .../__tests__/createInsightsMiddleware.ts | 102 +++++++++--------- src/middlewares/createInsightsMiddleware.ts | 74 ++++++------- src/types/insights.ts | 8 +- test/mock/createInsightsClient.ts | 14 ++- 4 files changed, 101 insertions(+), 97 deletions(-) diff --git a/src/middlewares/__tests__/createInsightsMiddleware.ts b/src/middlewares/__tests__/createInsightsMiddleware.ts index 817defcf20..82015ef01e 100644 --- a/src/middlewares/__tests__/createInsightsMiddleware.ts +++ b/src/middlewares/__tests__/createInsightsMiddleware.ts @@ -36,6 +36,30 @@ describe('insights', () => { }; }; + const createUmdTestEnvironment = () => { + const { + insightsClient, + libraryLoadedAndProcessQueue, + } = createInsightsUmdVersion(); + const instantSearchInstance = createInstantSearch({ + client: algoliasearch('myAppId', 'myApiKey'), + }); + const helper = algoliasearchHelper({} as SearchClient, ''); + const getUserToken = () => { + return (helper.state as any).userToken; + }; + instantSearchInstance.mainIndex = { + getHelper: () => helper, + } as Index; + return { + insightsClient, + libraryLoadedAndProcessQueue, + instantSearchInstance, + helper, + getUserToken, + }; + }; + beforeEach(() => { warning.cache = {}; }); @@ -79,40 +103,37 @@ describe('insights', () => { }); }); - it('does not throw when an event is sent right after the creation', () => { - const { insightsClient, instantSearchInstance } = createTestEnvironment(); - createInsightsMiddleware({ + it('does not throw when an event is sent right after the creation in UMD', done => { + const { + insightsClient, + libraryLoadedAndProcessQueue, + instantSearchInstance, + } = createUmdTestEnvironment(); + + const middleware = createInsightsMiddleware({ insightsClient, })({ instantSearchInstance }); + middleware.subscribe(); + + setTimeout(() => { + libraryLoadedAndProcessQueue(); + done(); + }, 20); expect(() => { - insightsClient('viewedObjectIDs', { - userToken: 'my-user-token', - index: instantSearchInstance.indexName, - eventName: 'Products Viewed', - objectIDs: ['obj-id0', 'obj-id1'], + instantSearchInstance.sendEventToInsights({ + eventType: 'view', + insightsMethod: 'viewedObjectIDs', + payload: { + eventName: 'Hits Viewed', + index: '', + objectIDs: ['1', '2'], + }, + widgetType: 'ais.hits', }); }).not.toThrow(); }); - it('warns dev if userToken is set before creating the middleware', () => { - const { insightsClient, instantSearchInstance } = createTestEnvironment(); - insightsClient('setUserToken', 'abc'); - expect(() => { - createInsightsMiddleware({ - insightsClient, - })({ instantSearchInstance }); - }) - .toWarnDev(`[InstantSearch.js]: You set userToken before \`createInsightsMiddleware()\` and it is ignored. -Please set the token after the \`createInsightsMiddleware()\` call. - -createInsightsMiddleware({ /* ... */ }); - -insightsClient('setUserToken', 'your-user-token'); -// or -aa('setUserToken', 'your-user-token');`); - }); - it('applies clickAnalytics', () => { const { insightsClient, @@ -169,7 +190,7 @@ aa('setUserToken', 'your-user-token');`); expect(getUserToken()).toEqual(ANONYMOUS_TOKEN); }); - it('ignores userToken set before init', () => { + it('applies userToken which was set before init', () => { const { insightsClient, instantSearchInstance, @@ -182,33 +203,10 @@ aa('setUserToken', 'your-user-token');`); insightsClient, })({ instantSearchInstance }); middleware.subscribe(); - expect(getUserToken()).toEqual(ANONYMOUS_TOKEN); + expect(getUserToken()).toEqual('token-from-queue-before-init'); }); describe('umd', () => { - const createUmdTestEnvironment = () => { - const { - insightsClient, - libraryLoadedAndProcessQueue, - } = createInsightsUmdVersion(); - const instantSearchInstance = createInstantSearch({ - client: algoliasearch('myAppId', 'myApiKey'), - }); - const helper = algoliasearchHelper({} as SearchClient, ''); - const getUserToken = () => { - return (helper.state as any).userToken; - }; - instantSearchInstance.mainIndex = { - getHelper: () => helper, - } as Index; - return { - insightsClient, - libraryLoadedAndProcessQueue, - instantSearchInstance, - helper, - getUserToken, - }; - }; it('applies userToken from queue if exists', () => { const { insightsClient, @@ -238,6 +236,7 @@ aa('setUserToken', 'your-user-token');`); insightsClient, instantSearchInstance, getUserToken, + libraryLoadedAndProcessQueue, } = createUmdTestEnvironment(); // call init and setUserToken even before the library is loaded. @@ -252,6 +251,7 @@ aa('setUserToken', 'your-user-token');`); insightsClient, })({ instantSearchInstance }); middleware.subscribe(); + libraryLoadedAndProcessQueue(); expect(getUserToken()).toEqual('token-from-queue'); }); diff --git a/src/middlewares/createInsightsMiddleware.ts b/src/middlewares/createInsightsMiddleware.ts index 09cd78ee21..c6e4b4c315 100644 --- a/src/middlewares/createInsightsMiddleware.ts +++ b/src/middlewares/createInsightsMiddleware.ts @@ -38,26 +38,35 @@ export const createInsightsMiddleware: CreateInsightsMiddleware = props => { _insightsClient === null ? (noop as InsightsClient) : _insightsClient; return ({ instantSearchInstance }) => { - insightsClient('_get', '_hasCredentials', (hasCredentials: boolean) => { - if (!hasCredentials) { - const [appId, apiKey] = getAppIdAndApiKey(instantSearchInstance.client); - insightsClient('_get', '_userToken', (userToken: string) => { - warning( - !userToken, - `You set userToken before \`createInsightsMiddleware()\` and it is ignored. -Please set the token after the \`createInsightsMiddleware()\` call. - -createInsightsMiddleware({ /* ... */ }); - -insightsClient('setUserToken', 'your-user-token'); -// or -aa('setUserToken', 'your-user-token'); - ` - ); - }); - insightsClient('init', { appId, apiKey }); - } + const [appId, apiKey] = getAppIdAndApiKey(instantSearchInstance.client); + let queuedUserToken: string | undefined = undefined; + let userTokenBeforeInit: string | undefined = undefined; + if (Array.isArray((insightsClient as any).queue)) { + // Context: The umd build of search-insights is asynchronously loaded by the snippet. + // + // When user calls `aa('setUserToken', 'my-user-token')` before `search-insights` is loaded, + // ['setUserToken', 'my-user-token'] gets stored in `aa.queue`. + // Whenever `search-insights` is finally loaded, it will process the queue. + // + // But here's the reason why we handle it here: + // At this point, even though `search-insights` is not loaded yet, + // we still want to read the token from the queue. + // Otherwise, the first search call will be fired without the token. + (insightsClient as any).queue.forEach(([method, firstArgument]) => { + if (method === 'setUserToken') { + queuedUserToken = firstArgument; + } + }); + } + insightsClient('_get', '_userToken', (userToken: string) => { + // If user has called `aa('setUserToken', 'my-user-token')` before creating + // the `insights` middleware, we store them temporarily and + // set it later on. + // + // Otherwise, the `init` call might override it with anonymous user token. + userTokenBeforeInit = userToken; }); + insightsClient('init', { appId, apiKey }); return { onStateChange() {}, @@ -76,28 +85,19 @@ aa('setUserToken', 'your-user-token'); .getHelper()! .setQueryParameter('clickAnalytics', true); - if (hasInsightsClient) { + const anonymousUserToken = getInsightsAnonymousUserTokenInternal(); + if (hasInsightsClient && anonymousUserToken) { // When `aa('init', { ... })` is called, it creates an anonymous user token in cookie. // We can set it as userToken. - setUserTokenToSearch(getInsightsAnonymousUserTokenInternal()); + setUserTokenToSearch(anonymousUserToken); + } + + if (queuedUserToken) { + insightsClient('setUserToken', queuedUserToken); } - if (Array.isArray((insightsClient as any).queue)) { - // Context: The umd build of search-insights is asynchronously loaded by the snippet. - // - // When user calls `aa('setUserToken', 'my-user-token')` before `search-insights` is loaded, - // ['setUserToken', 'my-user-token'] gets stored in `aa.queue`. - // Whenever `search-insights` is finally loaded, it will process the queue. - // - // But here's the reason why we handle it here: - // At this point, even though `search-insights` is not loaded yet, - // we still want to read the token from the queue. - // Otherwise, the first search call will be fired without the token. - (insightsClient as any).queue.forEach(([method, firstArgument]) => { - if (method === 'setUserToken') { - setUserTokenToSearch(firstArgument); - } - }); + if (userTokenBeforeInit) { + insightsClient('setUserToken', userTokenBeforeInit); } // This updates userToken which is set explicitly by `aa('setUserToken', userToken)` diff --git a/src/types/insights.ts b/src/types/insights.ts index 743229cfe3..e781e7f06e 100644 --- a/src/types/insights.ts +++ b/src/types/insights.ts @@ -12,6 +12,11 @@ export type InsightsClientPayload = { positions?: number[]; }; +export type InsightsSetUserToken = ( + method: 'setUserToken', + userToken: string +) => void; + export type InsightsSendEvent = ( method: InsightsClientMethod, payload: InsightsClientPayload @@ -40,7 +45,8 @@ export type InsightsInit = ( export type InsightsClient = InsightsSendEvent & InsightsOnUserTokenChange & InsightsGet & - InsightsInit; + InsightsInit & + InsightsSetUserToken; export type InsightsClientWrapper = ( method: InsightsClientMethod, diff --git a/test/mock/createInsightsClient.ts b/test/mock/createInsightsClient.ts index ace76062dd..ee52fc30b5 100644 --- a/test/mock/createInsightsClient.ts +++ b/test/mock/createInsightsClient.ts @@ -26,17 +26,15 @@ export function createAlgoliaAnalytics() { callback(values._userToken); } }; - const viewedObjectIDs = jest.fn(() => { - if (!values._apiKey) { - throw new Error( - 'apiKey is missing, please provide it so we can authenticate the application' - ); - } - if (!values._appId) { + const sendEvent = () => { + if (!values._hasCredentials) { throw new Error( - 'appId is missing, please provide it, so we can properly attribute data to your application' + "Before calling any methods on the analytics, you first need to call the 'init' function with appId and apiKey parameters" ); } + }; + const viewedObjectIDs = jest.fn(() => { + sendEvent(); }); return { From 1d3c977c153aef1a228f962b1a7cc58b19bab32e Mon Sep 17 00:00:00 2001 From: eunjae-lee Date: Mon, 9 Nov 2020 17:42:14 +0100 Subject: [PATCH 3/7] test: make it clearer --- .../__tests__/createInsightsMiddleware.ts | 17 +++++++++++++++-- test/mock/createInsightsClient.ts | 3 +++ 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/src/middlewares/__tests__/createInsightsMiddleware.ts b/src/middlewares/__tests__/createInsightsMiddleware.ts index 82015ef01e..3e8c0f8620 100644 --- a/src/middlewares/__tests__/createInsightsMiddleware.ts +++ b/src/middlewares/__tests__/createInsightsMiddleware.ts @@ -116,9 +116,16 @@ describe('insights', () => { middleware.subscribe(); setTimeout(() => { - libraryLoadedAndProcessQueue(); + // When the library is loaded later, it consumes the queue and sends the event. + const { algoliaAnalytics } = libraryLoadedAndProcessQueue(); + expect(algoliaAnalytics.viewedObjectIDs).toHaveBeenCalledTimes(1); + expect(algoliaAnalytics.viewedObjectIDs).toHaveBeenCalledWith({ + eventName: 'Hits Viewed', + index: '', + objectIDs: ['1', '2'], + }); done(); - }, 20); + }, 200); expect(() => { instantSearchInstance.sendEventToInsights({ @@ -132,6 +139,12 @@ describe('insights', () => { widgetType: 'ais.hits', }); }).not.toThrow(); + + // The library is not loaded yet, so it stays in the queue. + expect(insightsClient.queue[insightsClient.queue.length - 1]).toEqual([ + 'viewedObjectIDs', + { eventName: 'Hits Viewed', index: '', objectIDs: ['1', '2'] }, + ]); }); it('applies clickAnalytics', () => { diff --git a/test/mock/createInsightsClient.ts b/test/mock/createInsightsClient.ts index ee52fc30b5..643fe6d8e6 100644 --- a/test/mock/createInsightsClient.ts +++ b/test/mock/createInsightsClient.ts @@ -74,6 +74,9 @@ export function createInsightsUmdVersion() { queue.push = ([methodName, ...args]) => { _aa(methodName, ...args); }; + return { + algoliaAnalytics: instance, + }; }, }; } From fa7ea26d1c4c4d2a49960cd89a731d50a6fea9f2 Mon Sep 17 00:00:00 2001 From: eunjae-lee Date: Thu, 12 Nov 2020 10:43:15 +0100 Subject: [PATCH 4/7] use find instead of loop --- src/middlewares/createInsightsMiddleware.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/middlewares/createInsightsMiddleware.ts b/src/middlewares/createInsightsMiddleware.ts index c6e4b4c315..5b6d464351 100644 --- a/src/middlewares/createInsightsMiddleware.ts +++ b/src/middlewares/createInsightsMiddleware.ts @@ -52,11 +52,11 @@ export const createInsightsMiddleware: CreateInsightsMiddleware = props => { // At this point, even though `search-insights` is not loaded yet, // we still want to read the token from the queue. // Otherwise, the first search call will be fired without the token. - (insightsClient as any).queue.forEach(([method, firstArgument]) => { - if (method === 'setUserToken') { - queuedUserToken = firstArgument; - } - }); + [, queuedUserToken] = + (insightsClient as any).queue + .slice() + .reverse() + .find(([method]) => method === 'setUserToken') || []; } insightsClient('_get', '_userToken', (userToken: string) => { // If user has called `aa('setUserToken', 'my-user-token')` before creating From 5ddedeec8806d997372d27de340f1194cce2e174 Mon Sep 17 00:00:00 2001 From: eunjae-lee Date: Thu, 12 Nov 2020 10:48:14 +0100 Subject: [PATCH 5/7] add queue to InsightsClient type --- src/middlewares/createInsightsMiddleware.ts | 5 +++-- src/types/insights.ts | 4 +++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/middlewares/createInsightsMiddleware.ts b/src/middlewares/createInsightsMiddleware.ts index 5b6d464351..f227469d57 100644 --- a/src/middlewares/createInsightsMiddleware.ts +++ b/src/middlewares/createInsightsMiddleware.ts @@ -41,7 +41,8 @@ export const createInsightsMiddleware: CreateInsightsMiddleware = props => { const [appId, apiKey] = getAppIdAndApiKey(instantSearchInstance.client); let queuedUserToken: string | undefined = undefined; let userTokenBeforeInit: string | undefined = undefined; - if (Array.isArray((insightsClient as any).queue)) { + + if (Array.isArray(insightsClient.queue)) { // Context: The umd build of search-insights is asynchronously loaded by the snippet. // // When user calls `aa('setUserToken', 'my-user-token')` before `search-insights` is loaded, @@ -53,7 +54,7 @@ export const createInsightsMiddleware: CreateInsightsMiddleware = props => { // we still want to read the token from the queue. // Otherwise, the first search call will be fired without the token. [, queuedUserToken] = - (insightsClient as any).queue + insightsClient.queue .slice() .reverse() .find(([method]) => method === 'setUserToken') || []; diff --git a/src/types/insights.ts b/src/types/insights.ts index e781e7f06e..eb147791f0 100644 --- a/src/types/insights.ts +++ b/src/types/insights.ts @@ -46,7 +46,9 @@ export type InsightsClient = InsightsSendEvent & InsightsOnUserTokenChange & InsightsGet & InsightsInit & - InsightsSetUserToken; + InsightsSetUserToken & { + queue?: Array<[string, any]>; + }; export type InsightsClientWrapper = ( method: InsightsClientMethod, From 8b10f8940ac1b6e94ab8cb3757688207f57353fd Mon Sep 17 00:00:00 2001 From: eunjae-lee Date: Thu, 12 Nov 2020 10:49:24 +0100 Subject: [PATCH 6/7] clean up flow --- src/middlewares/createInsightsMiddleware.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/middlewares/createInsightsMiddleware.ts b/src/middlewares/createInsightsMiddleware.ts index f227469d57..f52db1ec04 100644 --- a/src/middlewares/createInsightsMiddleware.ts +++ b/src/middlewares/createInsightsMiddleware.ts @@ -93,12 +93,12 @@ export const createInsightsMiddleware: CreateInsightsMiddleware = props => { setUserTokenToSearch(anonymousUserToken); } - if (queuedUserToken) { - insightsClient('setUserToken', queuedUserToken); - } - + // We consider the `userToken` coming from a `init` call to have a higher + // importance than the one coming from the queue. if (userTokenBeforeInit) { insightsClient('setUserToken', userTokenBeforeInit); + } else if (queuedUserToken) { + insightsClient('setUserToken', queuedUserToken); } // This updates userToken which is set explicitly by `aa('setUserToken', userToken)` From 0add3dcab5e1f18e57e86fdcc6f00ed6bdc7e909 Mon Sep 17 00:00:00 2001 From: eunjae-lee Date: Thu, 12 Nov 2020 11:14:24 +0100 Subject: [PATCH 7/7] change the way to test viewedObjectIDs --- .../__tests__/createInsightsMiddleware.ts | 51 +++++++++---------- test/mock/createInsightsClient.ts | 33 ++++++------ 2 files changed, 43 insertions(+), 41 deletions(-) diff --git a/src/middlewares/__tests__/createInsightsMiddleware.ts b/src/middlewares/__tests__/createInsightsMiddleware.ts index 3e8c0f8620..2d8c4aa988 100644 --- a/src/middlewares/__tests__/createInsightsMiddleware.ts +++ b/src/middlewares/__tests__/createInsightsMiddleware.ts @@ -6,6 +6,7 @@ import { createAlgoliaAnalytics, createInsightsClient, createInsightsUmdVersion, + AlgoliaAnalytics, ANONYMOUS_TOKEN, } from '../../../test/mock/createInsightsClient'; import { warning } from '../../lib/utils'; @@ -36,11 +37,11 @@ describe('insights', () => { }; }; - const createUmdTestEnvironment = () => { + const createUmdTestEnvironment = (algoliaAnalytics?: AlgoliaAnalytics) => { const { insightsClient, libraryLoadedAndProcessQueue, - } = createInsightsUmdVersion(); + } = createInsightsUmdVersion(algoliaAnalytics); const instantSearchInstance = createInstantSearch({ client: algoliasearch('myAppId', 'myApiKey'), }); @@ -103,48 +104,46 @@ describe('insights', () => { }); }); - it('does not throw when an event is sent right after the creation in UMD', done => { + it('does not throw when an event is sent right after the creation in UMD', () => { + const algoliaAnalytics = createAlgoliaAnalytics(); const { insightsClient, libraryLoadedAndProcessQueue, instantSearchInstance, - } = createUmdTestEnvironment(); + } = createUmdTestEnvironment(algoliaAnalytics); const middleware = createInsightsMiddleware({ insightsClient, })({ instantSearchInstance }); middleware.subscribe(); - setTimeout(() => { - // When the library is loaded later, it consumes the queue and sends the event. - const { algoliaAnalytics } = libraryLoadedAndProcessQueue(); - expect(algoliaAnalytics.viewedObjectIDs).toHaveBeenCalledTimes(1); - expect(algoliaAnalytics.viewedObjectIDs).toHaveBeenCalledWith({ + // It tries to send an event. + instantSearchInstance.sendEventToInsights({ + eventType: 'view', + insightsMethod: 'viewedObjectIDs', + payload: { eventName: 'Hits Viewed', index: '', objectIDs: ['1', '2'], - }); - done(); - }, 200); - - expect(() => { - instantSearchInstance.sendEventToInsights({ - eventType: 'view', - insightsMethod: 'viewedObjectIDs', - payload: { - eventName: 'Hits Viewed', - index: '', - objectIDs: ['1', '2'], - }, - widgetType: 'ais.hits', - }); - }).not.toThrow(); + }, + widgetType: 'ais.hits', + }); + expect(algoliaAnalytics.viewedObjectIDs).toHaveBeenCalledTimes(0); - // The library is not loaded yet, so it stays in the queue. + // But, the library hasn't been loaded yet, so the event stays in the queue. expect(insightsClient.queue[insightsClient.queue.length - 1]).toEqual([ 'viewedObjectIDs', { eventName: 'Hits Viewed', index: '', objectIDs: ['1', '2'] }, ]); + + // When the library is loaded later, it consumes the queue and sends the event. + libraryLoadedAndProcessQueue(); + expect(algoliaAnalytics.viewedObjectIDs).toHaveBeenCalledTimes(1); + expect(algoliaAnalytics.viewedObjectIDs).toHaveBeenCalledWith({ + eventName: 'Hits Viewed', + index: '', + objectIDs: ['1', '2'], + }); }); it('applies clickAnalytics', () => { diff --git a/test/mock/createInsightsClient.ts b/test/mock/createInsightsClient.ts index 643fe6d8e6..e4fca92cbc 100644 --- a/test/mock/createInsightsClient.ts +++ b/test/mock/createInsightsClient.ts @@ -1,5 +1,16 @@ export const ANONYMOUS_TOKEN = 'anonymous-user-id-1'; +export type AlgoliaAnalytics = { + setUserToken: (userToken: string) => void; + init: ({ appId, apiKey }) => void; + _get: (key: string, callback: Function) => void; + onUserTokenChange: ( + callback: Function, + options?: { immediate?: boolean } + ) => void; + viewedObjectIDs: Function; +}; + export function createAlgoliaAnalytics() { let values: any = {}; const setValues = obj => { @@ -26,16 +37,7 @@ export function createAlgoliaAnalytics() { callback(values._userToken); } }; - const sendEvent = () => { - if (!values._hasCredentials) { - throw new Error( - "Before calling any methods on the analytics, you first need to call the 'init' function with appId and apiKey parameters" - ); - } - }; - const viewedObjectIDs = jest.fn(() => { - sendEvent(); - }); + const viewedObjectIDs = jest.fn(); return { setUserToken, @@ -43,7 +45,7 @@ export function createAlgoliaAnalytics() { _get, onUserTokenChange, viewedObjectIDs, - }; + } as AlgoliaAnalytics; } export function createInsightsClient(instance = createAlgoliaAnalytics()) { @@ -55,7 +57,9 @@ export function createInsightsClient(instance = createAlgoliaAnalytics()) { }; } -export function createInsightsUmdVersion() { +export function createInsightsUmdVersion( + algoliaAnalytics = createAlgoliaAnalytics() +) { const globalObject: any = {}; globalObject.aa = (...args) => { globalObject.aa.queue = globalObject.aa.queue || []; @@ -65,8 +69,7 @@ export function createInsightsUmdVersion() { return { insightsClient: globalObject.aa, libraryLoadedAndProcessQueue: () => { - const instance = createAlgoliaAnalytics(); - const _aa = createInsightsClient(instance); + const _aa = createInsightsClient(algoliaAnalytics); const queue = globalObject.aa.queue; queue.forEach(([methodName, ...args]) => { _aa(methodName, ...args); @@ -75,7 +78,7 @@ export function createInsightsUmdVersion() { _aa(methodName, ...args); }; return { - algoliaAnalytics: instance, + algoliaAnalytics, }; }, };