Skip to content

Commit

Permalink
feat(insights): add tests (4/4) (#4464)
Browse files Browse the repository at this point in the history
* add tests for userToken

* fix import paths

* fix test cases to accept null instead of false as insightsClient

* update bundlesize

* fix lint errors

* test sendEventToInsights

* use $$type instead of hard-code

* remove sendEvent from connectBreadcrumb

* moved createSendEvent to the top level in the files

* log insights event from storybook

* add test for connectors

* add tests for createSendEvent helpers

* add integration tests for hits and infinite-hits widgets with bindEvent in templates

* update bundlesize

* Update src/connectors/hits/__tests__/connectHits-test.ts

Co-authored-by: Haroen Viaene <[email protected]>

* use factory function instead of globally exposed variables

* clean up

* update comment

* use runAllMicroTasks instead of nextTick

* fix: type errors

* fix wrong import paths

* fix: pass insightsClient to onEvent as the second parameter

* update titles of describe blocks

Co-authored-by: Haroen Viaene <[email protected]>
  • Loading branch information
Eunjae Lee and Haroenv authored Sep 2, 2020
1 parent 5b89264 commit 27f3125
Show file tree
Hide file tree
Showing 29 changed files with 2,300 additions and 124 deletions.
9 changes: 9 additions & 0 deletions .storybook/playgrounds/default.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import instantsearch from '../../src/index';
import { panel, numericMenu, hits } from '../../src/widgets';
import { createInsightsMiddleware } from '../../src/middlewares';

export const hitsItemTemplate = `
<div
Expand Down Expand Up @@ -126,6 +127,14 @@ function instantSearchPlayground({
container: pagination,
}),
]);

const insights = createInsightsMiddleware({
insightsClient: null,
onEvent: props => {
console.log('insights onEvent', props);
},
});
search.EXPERIMENTAL_use(insights);
}

export default instantSearchPlayground;
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -142,11 +142,11 @@
"bundlesize": [
{
"path": "./dist/instantsearch.production.min.js",
"maxSize": "64 kB"
"maxSize": "64.50 kB"
},
{
"path": "./dist/instantsearch.development.js",
"maxSize": "160 kB"
"maxSize": "150.40 kB"
}
]
}
150 changes: 150 additions & 0 deletions src/connectors/autocomplete/__tests__/connectAutocomplete-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -566,4 +566,154 @@ search.addWidgets([
);
});
});

describe('insights', () => {
const createRenderedWidget = () => {
const searchClient = createSearchClient();
const render = jest.fn();
const makeWidget = connectAutocomplete(render);
const widget = makeWidget({ escapeHTML: false });

const helper = algoliasearchHelper(searchClient, '', {});
helper.search = jest.fn();

const initOptions = createInitOptions({ helper });
const instantSearchInstance = initOptions.instantSearchInstance;
widget.init!(initOptions);

const firstIndexHits = [
{
name: 'Hit 1-1',
objectID: '1-1',
__queryID: 'test-query-id',
__position: 0,
},
];
const secondIndexHits = [
{
name: 'Hit 2-1',
objectID: '2-1',
__queryID: 'test-query-id',
__position: 0,
},
{
name: 'Hit 2-2',
objectID: '2-2',
__queryID: 'test-query-id',
__position: 1,
},
];

const scopedResults = [
{
indexId: 'indexId0',
results: new SearchResults(helper.state, [
createSingleSearchResponse({
index: 'indexName0',
hits: firstIndexHits,
}),
]),
helper,
},
{
indexId: 'indexId1',
results: new SearchResults(helper.state, [
createSingleSearchResponse({
index: 'indexName1',
hits: secondIndexHits,
}),
]),
helper,
},
];

widget.render!(
createRenderOptions({ instantSearchInstance, helper, scopedResults })
);

const sendEventToInsights = instantSearchInstance.sendEventToInsights as jest.Mock;

return {
instantSearchInstance,
sendEventToInsights,
render,
firstIndexHits,
secondIndexHits,
};
};

it('sends view event when hits are rendered', () => {
const { sendEventToInsights } = createRenderedWidget();
expect(sendEventToInsights).toHaveBeenCalledTimes(2);
expect(sendEventToInsights.mock.calls[0][0]).toEqual({
eventType: 'view',
insightsMethod: 'viewedObjectIDs',
payload: {
eventName: 'Hits Viewed',
index: 'indexName0',
objectIDs: ['1-1'],
},
widgetType: 'ais.autocomplete',
});
expect(sendEventToInsights.mock.calls[1][0]).toEqual({
eventType: 'view',
insightsMethod: 'viewedObjectIDs',
payload: {
eventName: 'Hits Viewed',
index: 'indexName1',
objectIDs: ['2-1', '2-2'],
},
widgetType: 'ais.autocomplete',
});
});

it('sends click event', () => {
const {
sendEventToInsights,
render,
secondIndexHits,
} = createRenderedWidget();
expect(sendEventToInsights).toHaveBeenCalledTimes(2); // two view events for each index by render

const { indices } = render.mock.calls[render.mock.calls.length - 1][0];
indices[1].sendEvent('click', secondIndexHits[0], 'Product Added');
expect(sendEventToInsights).toHaveBeenCalledTimes(3);
expect(sendEventToInsights.mock.calls[2][0]).toEqual({
eventType: 'click',
insightsMethod: 'clickedObjectIDsAfterSearch',
payload: {
eventName: 'Product Added',
index: 'indexName1',
objectIDs: ['2-1'],
positions: [0],
queryID: 'test-query-id',
},
widgetType: 'ais.autocomplete',
});
});

it('sends conversion event', () => {
const {
sendEventToInsights,
render,
firstIndexHits,
} = createRenderedWidget();
expect(sendEventToInsights).toHaveBeenCalledTimes(2); // two view events for each index by render

const { indices } = render.mock.calls[render.mock.calls.length - 1][0];
indices[0].sendEvent('conversion', firstIndexHits[0], 'Product Ordered');
expect(sendEventToInsights).toHaveBeenCalledTimes(3);
expect(sendEventToInsights.mock.calls[2][0]).toEqual({
eventType: 'conversion',
insightsMethod: 'convertedObjectIDsAfterSearch',
payload: {
eventName: 'Product Ordered',
index: 'indexName0',
objectIDs: ['1-1'],
queryID: 'test-query-id',
},
widgetType: 'ais.autocomplete',
});
});
});
});
121 changes: 121 additions & 0 deletions src/connectors/geo-search/__tests__/connectGeoSearch-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -1347,4 +1347,125 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/geo-search/
expect(searchParametersAfter.insideBoundingBox).toBeUndefined();
});
});

describe('insights', () => {
const createRenderedWidget = () => {
const hits = [
{
objectID: 123,
_geoloc: { lat: 10, lng: 12 },
__position: 0,
__queryID: 'test-query-id',
},
{
objectID: 456,
_geoloc: { lat: 12, lng: 14 },
__position: 1,
__queryID: 'test-query-id',
},
{
objectID: 789,
_geoloc: { lat: 14, lng: 16 },
__position: 2,
__queryID: 'test-query-id',
},
];
const render = jest.fn();
const unmount = jest.fn();

const customGeoSearch = connectGeoSearch(render, unmount);
const widget = customGeoSearch();

const instantSearchInstance = createInstantSearch();
const { mainHelper: helper } = instantSearchInstance;

widget.init({
state: helper.state,
instantSearchInstance,
helper,
});

widget.render({
results: new SearchResults(helper.state, [
{
hits,
},
]),
helper,
instantSearchInstance,
});

return {
render,
instantSearchInstance,
hits,
};
};

it('sends view event when hits are rendered', () => {
const { instantSearchInstance } = createRenderedWidget();
expect(instantSearchInstance.sendEventToInsights).toHaveBeenCalledTimes(
1
);
expect(instantSearchInstance.sendEventToInsights).toHaveBeenCalledWith({
eventType: 'view',
insightsMethod: 'viewedObjectIDs',
payload: {
eventName: 'Hits Viewed',
index: 'indexName',
objectIDs: [123, 456, 789],
},
widgetType: 'ais.geoSearch',
});
});

it('sends click event', () => {
const { instantSearchInstance, render, hits } = createRenderedWidget();
expect(instantSearchInstance.sendEventToInsights).toHaveBeenCalledTimes(
1
); // view event by render

const { sendEvent } = render.mock.calls[render.mock.calls.length - 1][0];
sendEvent('click', hits[0], 'Location Added');
expect(instantSearchInstance.sendEventToInsights).toHaveBeenCalledTimes(
2
);
expect(instantSearchInstance.sendEventToInsights).toHaveBeenCalledWith({
eventType: 'click',
insightsMethod: 'clickedObjectIDsAfterSearch',
payload: {
eventName: 'Location Added',
index: 'indexName',
objectIDs: [123],
positions: [0],
queryID: 'test-query-id',
},
widgetType: 'ais.geoSearch',
});
});

it('sends conversion event', () => {
const { instantSearchInstance, render, hits } = createRenderedWidget();
expect(instantSearchInstance.sendEventToInsights).toHaveBeenCalledTimes(
1
); // view event by render

const { sendEvent } = render.mock.calls[render.mock.calls.length - 1][0];
sendEvent('conversion', hits[0], 'Location Saved');
expect(instantSearchInstance.sendEventToInsights).toHaveBeenCalledTimes(
2
);
expect(instantSearchInstance.sendEventToInsights).toHaveBeenCalledWith({
eventType: 'conversion',
insightsMethod: 'convertedObjectIDsAfterSearch',
payload: {
eventName: 'Location Saved',
index: 'indexName',
objectIDs: [123],
queryID: 'test-query-id',
},
widgetType: 'ais.geoSearch',
});
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -1128,4 +1128,48 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/hierarchica
);
});
});

describe('insights', () => {
it('sends event when a facet is added', () => {
const rendering = jest.fn();
const instantSearchInstance = createInstantSearch();
const makeWidget = connectHierarchicalMenu(rendering);
const widget = makeWidget({
attributes: ['category', 'sub_category'],
});

const helper = jsHelper(
{},
'',
widget.getWidgetSearchParameters(new SearchParameters(), {
uiState: {},
})
);
helper.search = jest.fn();

widget.init({
helper,
state: helper.state,
createURL: () => '#',
instantSearchInstance,
});

const firstRenderingOptions = rendering.mock.calls[0][0];
const { refine } = firstRenderingOptions;
refine('value');
expect(instantSearchInstance.sendEventToInsights).toHaveBeenCalledTimes(
1
);
expect(instantSearchInstance.sendEventToInsights).toHaveBeenCalledWith({
eventType: 'click',
insightsMethod: 'clickedFilters',
payload: {
eventName: 'Filter Applied',
filters: ['category:"value"'],
index: '',
},
widgetType: 'ais.hierarchicalMenu',
});
});
});
});
Loading

0 comments on commit 27f3125

Please sign in to comment.