Skip to content

Commit

Permalink
fix(insights): only init if version allows it (#5529)
Browse files Browse the repository at this point in the history
Co-authored-by: Dhaya <154633+dhayab@users.noreply.github.com>
  • Loading branch information
2 people authored and Haroenv committed Apr 18, 2023
1 parent f2ab2fc commit fa98e21
Show file tree
Hide file tree
Showing 5 changed files with 110 additions and 34 deletions.
2 changes: 1 addition & 1 deletion packages/instantsearch.js/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
"htm": "^3.0.0",
"preact": "^10.10.0",
"qs": "^6.5.1 < 6.10",
"search-insights": "^2.1.0"
"search-insights": "^2.4.0"
},
"peerDependencies": {
"algoliasearch": ">= 3.1 < 6"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,7 @@ describe('insights', () => {

it('notifies when the script fails to be added', () => {
const { instantSearchInstance } = createTestEnvironment();
/* eslint-disable deprecation/deprecation */
const createElement = document.createElement;
document.createElement = () => {
throw new Error('error');
Expand All @@ -277,6 +278,7 @@ describe('insights', () => {
instantSearchInstance.use(createInsightsMiddleware());

document.createElement = createElement;
/* eslint-enable deprecation/deprecation */
});

it('notifies when the script fails to load', () => {
Expand Down Expand Up @@ -309,25 +311,11 @@ describe('insights', () => {
apiKey: 'myApiKey',
appId: 'myAppId',
region: 'de',
partial: true,
useCookie: false,
});
});

it('throws when search client does not have credentials', () => {
const { insightsClient } = createInsights();
const instantSearchInstance = createInstantSearch({
// @ts-expect-error fake client
client: { search: () => {} },
});
expect(() =>
createInsightsMiddleware({
insightsClient,
})({ instantSearchInstance })
).toThrowErrorMatchingInlineSnapshot(
`"apiKey is missing, please provide it so we can authenticate the application"`
);
});

it('warns when search client does not have credentials', () => {
const { insightsClient } = createInsights();
const instantSearchInstance = createInstantSearch({
Expand Down Expand Up @@ -581,6 +569,74 @@ See documentation: https://www.algolia.com/doc/guides/building-search-ui/going-f
]
`);
});

it('does not call `init` when default middleware is used', () => {
const { instantSearchInstance, insightsClient } = createTestEnvironment({
insights: true,
});

instantSearchInstance.use(
createInsightsMiddleware({ $$internal: true, insightsClient })
);

expect(instantSearchInstance.middleware).toHaveLength(1);
expect(instantSearchInstance.middleware).toMatchInlineSnapshot(`
[
{
"creator": [Function],
"instance": {
"$$internal": true,
"$$type": "ais.insights",
"onStateChange": [Function],
"started": [Function],
"subscribe": [Function],
"unsubscribe": [Function],
},
},
]
`);
expect(insightsClient).not.toHaveBeenCalledWith('init', {
apiKey: 'myApiKey',
appId: 'myAppId',
partial: true,
useCookie: true,
});
});

it('does call `init` when `initParams` are passed', () => {
const { instantSearchInstance, insightsClient } = createTestEnvironment();

instantSearchInstance.use(
createInsightsMiddleware({
$$internal: true,
insightsClient,
insightsInitParams: { useCookie: false },
})
);

expect(instantSearchInstance.middleware).toHaveLength(1);
expect(instantSearchInstance.middleware).toMatchInlineSnapshot(`
[
{
"creator": [Function],
"instance": {
"$$internal": true,
"$$type": "ais.insights",
"onStateChange": [Function],
"started": [Function],
"subscribe": [Function],
"unsubscribe": [Function],
},
},
]
`);
expect(insightsClient).toHaveBeenCalledWith('init', {
apiKey: 'myApiKey',
appId: 'myAppId',
partial: true,
useCookie: false,
});
});
});

describe('userToken', () => {
Expand Down Expand Up @@ -768,7 +824,7 @@ See documentation: https://www.algolia.com/doc/guides/building-search-ui/going-f
},
]);

insightsClient('setUserToken', undefined);
insightsClient('setUserToken', '');

await wait(0);
expect(instantSearchInstance.client.search).toHaveBeenCalledTimes(2);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ export function createInsightsMiddleware<

if (!potentialInsightsClient) {
window.AlgoliaAnalyticsObject = pointer;

if (!window[pointer]) {
window[pointer] = (...args: any[]) => {
if (!window[pointer].queue) {
Expand Down Expand Up @@ -138,12 +139,18 @@ export function createInsightsMiddleware<
// Otherwise, the `init` call might override it with anonymous user token.
userTokenBeforeInit = userToken;
});
insightsClient('init', {
appId,
apiKey,
useCookie: true,
...insightsInitParams,
});

// Only `init` if the `insightsInitParams` option is passed or
// if the `insightsClient` version doesn't supports optional `init` calling.
if (insightsInitParams || !isModernInsightsClient(insightsClient)) {
insightsClient('init', {
appId,
apiKey,
useCookie: true,
partial: true,
...insightsInitParams,
});
}

let initialParameters: PlainSearchParameters;
let helper: AlgoliaSearchHelper;
Expand Down Expand Up @@ -306,6 +313,10 @@ See documentation: https://www.algolia.com/doc/guides/building-search-ui/going-f
};
}

/**
* Determines if a given insights `client` supports the optional call to `init`
* and the ability to set credentials via extra parameters when sending events.
*/
function isModernInsightsClient(client: InsightsClientWithGlobals): boolean {
const [major, minor] = (client.version || '').split('.').map(Number);

Expand Down
23 changes: 16 additions & 7 deletions tests/mocks/createInsightsClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,15 @@ import {
} from 'search-insights';

import type { InsightsClient } from 'instantsearch.js';
import { castToJestMock } from '@instantsearch/testutils/castToJestMock';

/**
* Tests that rely on this mock interface have side effects caused by
* the import of search-insights. The following code deletes those side effects.
*/
try {
delete window.AlgoliaAnalyticsObject;
} catch (error) {} // eslint-disable-line no-empty

export function createInsights<TVersion extends string | undefined = '2.4.0'>({
forceVersion = '2.4.0',
Expand All @@ -16,22 +25,22 @@ export function createInsights<TVersion extends string | undefined = '2.4.0'>({
requestFn: jest.fn(),
})
);
const mockedInsightsClient = castToJestMock(
jest.fn(getFunctionalInterface(analytics)) as InsightsClient
);

if (forceVersion) {
return {
analytics,
insightsClient: Object.assign(
jest.fn(getFunctionalInterface(analytics)),
{
version: forceVersion,
}
),
insightsClient: Object.assign(mockedInsightsClient, {
version: forceVersion,
}),
};
}

return {
analytics,
insightsClient: jest.fn(getFunctionalInterface(analytics)),
insightsClient: mockedInsightsClient,
};
}

Expand Down
8 changes: 4 additions & 4 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -30442,10 +30442,10 @@ scule@^0.2.1:
resolved "https://registry.yarnpkg.com/scule/-/scule-0.2.1.tgz#0c1dc847b18e07219ae9a3832f2f83224e2079dc"
integrity sha512-M9gnWtn3J0W+UhJOHmBxBTwv8mZCan5i1Himp60t6vvZcor0wr+IM0URKmIglsWJ7bRujNAVVN77fp+uZaWoKg==

search-insights@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/search-insights/-/search-insights-2.1.0.tgz#42822fa325062ec5bf050c5f8cad58f0c5b21310"
integrity sha512-mWIVsZ5igQnlM2tC0HJCtGWKQcBhLhkasZoZZS2exUfZPpRowVWEvyyYTWU3M0rUKWlWLWFCYvJ3HGTSSCsOcw==
search-insights@^2.4.0:
version "2.4.0"
resolved "https://registry.yarnpkg.com/search-insights/-/search-insights-2.4.0.tgz#7b6b19527dd186b459f6e2dd7e01f7a3de96ffe7"
integrity sha512-AqXxWFEIZTfOf0brQLvoAZcotrVX0xR/VoPCzBxsTZF/yO+izIH1eFCtKizR/dGI8NCMOTdc7l90hAOI68dBbg==

section-iterator@^2.0.0:
version "2.0.0"
Expand Down

0 comments on commit fa98e21

Please sign in to comment.