Skip to content

Commit

Permalink
feat(insights): implement sendEvent in all the connectors (3/4) (#4463)
Browse files Browse the repository at this point in the history
* update infiniteHits

* modify createSendEventForHits to accept index instead of helper

* add sendEvent to connectAutocomplete

* add sendEvent to connectGeoSearch

* add sendEvent to connectHierarchicalMenu

* add sendEvent to connectBreadcrumb

* add sendEvent to connectMenu

* add sendEvent to connectNumericMenu

* extract getRefinedState in connectRange

* add sendEvent to connectRange

* add sendEvent to connectRatingMenu

* add sendEvent to connectToggleRefinement

* fix test error

* fix export

* fix type error

* use $$type instead of hard-code

* remove sendEvent from connectBreadcrumb

* moved createSendEvent to the top level in the files

* feat(insights): add tests (4/4) (#4464)

* 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]>

Co-authored-by: Haroen Viaene <[email protected]>
  • Loading branch information
Eunjae Lee and Haroenv authored Sep 2, 2020
1 parent 98b24e1 commit 6ee7a40
Show file tree
Hide file tree
Showing 51 changed files with 3,030 additions and 341 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"
}
]
}
5 changes: 5 additions & 0 deletions src/components/InfiniteHits/InfiniteHits.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import Template from '../Template/Template';
import { SearchResults } from 'algoliasearch-helper';
import { Hits } from '../../types';
import { InfiniteHitsTemplates } from '../../widgets/infinite-hits/infinite-hits';
import { SendEventForHits, BindEventForHits } from '../../lib/utils';

type InfiniteHitsCSSClasses = {
root: string;
Expand All @@ -31,11 +32,14 @@ type InfiniteHitsProps = {
};
isFirstPage: boolean;
isLastPage: boolean;
sendEvent: SendEventForHits;
bindEvent: BindEventForHits;
};

const InfiniteHits = ({
results,
hits,
bindEvent,
hasShowPrevious,
showPrevious,
showMore,
Expand Down Expand Up @@ -86,6 +90,7 @@ const InfiniteHits = ({
...hit,
__hitIndex: position,
}}
bindEvent={bindEvent}
/>
))}
</ol>
Expand Down
15 changes: 15 additions & 0 deletions src/components/InfiniteHits/__tests__/InfiniteHits-test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ describe('InfiniteHits', () => {
disabledLoadMore: 'disabledLoadMore',
};

const sendEvent = () => {};
const bindEvent = () => '';

describe('markup', () => {
it('should render <InfiniteHits /> on first page', () => {
const hits: Hits = [
Expand Down Expand Up @@ -50,6 +53,8 @@ describe('InfiniteHits', () => {
},
},
cssClasses,
sendEvent,
bindEvent,
};

const { container } = render(<InfiniteHits {...props} />);
Expand Down Expand Up @@ -88,6 +93,8 @@ describe('InfiniteHits', () => {
},
},
cssClasses,
sendEvent,
bindEvent,
};

const { container } = render(<InfiniteHits {...props} />);
Expand Down Expand Up @@ -115,6 +122,8 @@ describe('InfiniteHits', () => {
},
},
cssClasses,
sendEvent,
bindEvent,
};

const { container } = render(<InfiniteHits {...props} />);
Expand Down Expand Up @@ -142,6 +151,8 @@ describe('InfiniteHits', () => {
},
},
cssClasses,
sendEvent,
bindEvent,
};

const { container } = render(<InfiniteHits {...props} />);
Expand Down Expand Up @@ -180,6 +191,8 @@ describe('InfiniteHits', () => {
},
},
cssClasses,
sendEvent,
bindEvent,
};

const { container } = render(<InfiniteHits {...props} />);
Expand Down Expand Up @@ -223,6 +236,8 @@ describe('InfiniteHits', () => {
},
},
cssClasses,
sendEvent,
bindEvent,
};

const { container } = render(<InfiniteHits {...props} />);
Expand Down
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',
});
});
});
});
16 changes: 16 additions & 0 deletions src/connectors/autocomplete/connectAutocomplete.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import escapeHits, { TAG_PLACEHOLDER } from '../../lib/escape-highlight';
import {
checkRendering,
createDocumentationMessageGenerator,
createSendEventForHits,
SendEventForHits,
noop,
warning,
} from '../../lib/utils';
Expand Down Expand Up @@ -46,6 +48,11 @@ export type AutocompleteRendererOptions = {
* The full results object from the Algolia API.
*/
results: SearchResults;

/**
* Send event to insights middleware
*/
sendEvent: SendEventForHits;
}>;

/**
Expand Down Expand Up @@ -127,11 +134,20 @@ search.addWidgets([
? escapeHits(scopedResult.results.hits)
: scopedResult.results.hits;

const sendEvent = createSendEventForHits({
instantSearchInstance,
index: scopedResult.results.index,
widgetType: this.$$type!,
});

sendEvent('view', scopedResult.results.hits);

return {
indexId: scopedResult.indexId,
indexName: scopedResult.results.index,
hits: scopedResult.results.hits,
results: scopedResult.results,
sendEvent,
};
});

Expand Down
Loading

0 comments on commit 6ee7a40

Please sign in to comment.