Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(insights): automatically add insights middleware #5488

Merged
merged 5 commits into from
Feb 23, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions bundlesize.config.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,11 @@
},
{
"path": "packages/react-instantsearch-hooks/dist/umd/ReactInstantSearchHooks.min.js",
"maxSize": "41.75 kB"
"maxSize": "42.75 kB"
},
{
"path": "packages/react-instantsearch-hooks-web/dist/umd/ReactInstantSearchHooksDOM.min.js",
"maxSize": "51.25 kB"
"maxSize": "52.25 kB"
},
{
"path": "packages/react-instantsearch-dom/dist/umd/ReactInstantSearchDOM.min.js",
Expand All @@ -42,11 +42,11 @@
},
{
"path": "packages/vue-instantsearch/vue2/umd/index.js",
"maxSize": "60 kB"
"maxSize": "61.25 kB"
},
{
"path": "packages/vue-instantsearch/vue3/umd/index.js",
"maxSize": "60 kB"
"maxSize": "61.25 kB"
},
{
"path": "packages/vue-instantsearch/vue2/cjs/index.js",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import './Refresh.css';

export function Refresh() {
const { refresh } = useInstantSearch();

return (
<button
className="Refresh"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -855,8 +855,8 @@ search.addWidgets([
stalledSearchDelay: 1,
indexName: 'indexName',
});
instantSearchInstance.sendEventToInsights = jest.fn();
instantSearchInstance.start();
instantSearchInstance.sendEventToInsights = jest.fn();

instantSearchInstance.addWidgets([widget]);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/configure-r
{
indexName: 'indexName',
params: {
clickAnalytics: true,
facets: [],
facetFilters: ['objectID:-1'],
tagFilters: '',
Expand Down Expand Up @@ -166,6 +167,7 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/configure-r
{
indexName: 'indexName',
params: {
clickAnalytics: true,
facets: [],
facetFilters: ['objectID:-1'],
tagFilters: '',
Expand Down Expand Up @@ -211,6 +213,7 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/configure-r
{
indexName: 'indexName',
params: {
clickAnalytics: true,
facets: [],
facetFilters: ['objectID:-1'],
tagFilters: '',
Expand Down Expand Up @@ -274,6 +277,7 @@ See https://www.algolia.com/doc/api-reference/api-parameters/optionalFilters/`);
{
indexName: 'indexName',
params: {
clickAnalytics: true,
facets: [],
facetFilters: ['objectID:-1'],
tagFilters: '',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1748,8 +1748,8 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/geo-search/
stalledSearchDelay: 1,
indexName: 'indexName',
});
instantSearchInstance.sendEventToInsights = jest.fn();
instantSearchInstance.start();
instantSearchInstance.sendEventToInsights = jest.fn();

instantSearchInstance.addWidgets([widget]);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -868,8 +868,8 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/hits/js/#co
stalledSearchDelay: 1,
indexName: 'indexName',
});
instantSearchInstance.sendEventToInsights = jest.fn();
instantSearchInstance.start();
instantSearchInstance.sendEventToInsights = jest.fn();

instantSearchInstance.addWidgets([widget]);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1458,8 +1458,8 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/infinite-hi
stalledSearchDelay: 1,
indexName: 'indexName',
});
instantSearchInstance.sendEventToInsights = jest.fn();
instantSearchInstance.start();
instantSearchInstance.sendEventToInsights = jest.fn();

instantSearchInstance.addWidgets([widget]);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,11 @@ function getStateWithoutPage(state: PlainSearchParameters) {
return rest;
}

function normalizeState(state: PlainSearchParameters) {
const { clickAnalytics, userToken, ...rest } = state || {};
return rest;
}
Comment on lines +156 to +159
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if infiniteHits is added before start, it's reading from the cache before the insights middleware is started, and thus it doesn't have clickAnalytics + userToken yet

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

to solve this, we could change some things about the insights middleware to make sure we have the search parameters right away, even before init, but that's currently not possible yet (helper is null)


function getInMemoryCache<THit extends BaseHit>(): InfiniteHitsCache<THit> {
let cachedHits: InfiniteHitsCachedHits<THit> | null = null;
let cachedState: PlainSearchParameters | null = null;
Expand Down Expand Up @@ -237,7 +242,7 @@ const connectInfiniteHits: InfiniteHitsConnector = function connectInfiniteHits(
page:
getFirstReceivedPage(
helper.state,
cache.read({ state: helper.state }) || {}
cache.read({ state: normalizeState(helper.state) }) || {}
) - 1,
})
.searchWithoutTriggeringOnStateChange();
Expand All @@ -250,7 +255,7 @@ const connectInfiniteHits: InfiniteHitsConnector = function connectInfiniteHits(
.setPage(
getLastReceivedPage(
helper.state,
cache.read({ state: helper.state }) || {}
cache.read({ state: normalizeState(helper.state) }) || {}
) + 1
)
.search();
Expand Down Expand Up @@ -308,7 +313,7 @@ const connectInfiniteHits: InfiniteHitsConnector = function connectInfiniteHits(
*/
const state = parent.getPreviousState() || existingState;

const cachedHits = cache.read({ state }) || {};
const cachedHits = cache.read({ state: normalizeState(state) }) || {};

if (!results) {
showPrevious = getShowPrevious(helper);
Expand Down Expand Up @@ -355,7 +360,7 @@ const connectInfiniteHits: InfiniteHitsConnector = function connectInfiniteHits(
instantSearchInstance.status === 'idle'
) {
cachedHits[page] = transformedHits;
cache.write({ state, hits: cachedHits });
cache.write({ state: normalizeState(state), hits: cachedHits });
}
currentPageHits = transformedHits;

Expand Down
12 changes: 10 additions & 2 deletions packages/instantsearch.js/src/lib/InstantSearch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import type {
import type { RouterProps } from '../middlewares/createRouterMiddleware';
import { createRouterMiddleware } from '../middlewares/createRouterMiddleware';
import type { InsightsEvent } from '../middlewares/createInsightsMiddleware';
import { createInsightsMiddleware } from '../middlewares/createInsightsMiddleware';
import {
createMetadataMiddleware,
isMetadataEnabled,
Expand Down Expand Up @@ -297,12 +298,17 @@ See ${createDocumentationLink({
this.sendEventToInsights = noop;

if (routing) {
const routerOptions = typeof routing === 'boolean' ? undefined : routing;
const routerOptions = typeof routing === 'boolean' ? {} : routing;
routerOptions.$$internal = true;
this.use(createRouterMiddleware(routerOptions));
}

// This is the default middleware,
// any user-provided middleware will be added later and override this one.
this.use(createInsightsMiddleware({ $$internal: true }));
Comment on lines +306 to +308
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

something still needs to be fixed here, the script is always loaded from the internal middleware, even if users add a different middleware later (even right after). Not too sure how to fix that yet

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

solved through #5493


if (isMetadataEnabled()) {
this.use(createMetadataMiddleware());
this.use(createMetadataMiddleware({ $$internal: true }));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nitpick: this is technically always internal, it could be set statically in createMetadataMiddleware().

}
}

Expand All @@ -312,6 +318,8 @@ See ${createDocumentationLink({
public use(...middleware: Middleware[]): this {
const newMiddlewareList = middleware.map((fn) => {
const newMiddleware = {
$$type: '__unknown__',
$$internal: false,
subscribe: noop,
started: noop,
unsubscribe: noop,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ describe('middleware', () => {
});

const middlewareDefinition: MiddlewareDefinition = {
$$type: 'fake',
$$internal: false,
onStateChange: jest.fn(),
subscribe: jest.fn(),
started: jest.fn(),
Expand Down Expand Up @@ -96,6 +98,8 @@ describe('middleware', () => {
});

const middlewareDefinition: MiddlewareDefinition = {
$$type: 'fake',
$$internal: false,
onStateChange: jest.fn(),
subscribe: jest.fn(),
started: jest.fn(),
Expand Down
38 changes: 28 additions & 10 deletions packages/instantsearch.js/src/lib/__tests__/InstantSearch-test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -449,29 +449,47 @@ See https://www.algolia.com/doc/api-reference/widgets/configure/js/`);
});

it("doesn't add metadata middleware by default", () => {
const useSpy = jest.spyOn(InstantSearch.prototype, 'use');

// eslint-disable-next-line no-new
new InstantSearch({
const search = new InstantSearch({
searchClient: createSearchClient(),
indexName: 'test',
});

expect(useSpy).toHaveBeenCalledTimes(0);
expect(
search.middleware.map(({ instance: { $$type, $$internal } }) => ({
$$type,
$$internal,
}))
).toEqual([
{
$$type: 'ais.insights',
$$internal: true,
},
]);
});

it('adds metadata middleware on the Crawler user agent', () => {
userAgentMock = algoliaUserAgent;

const useSpy = jest.spyOn(InstantSearch.prototype, 'use');

// eslint-disable-next-line no-new
new InstantSearch({
const search = new InstantSearch({
searchClient: createSearchClient(),
indexName: 'test',
});

expect(useSpy).toHaveBeenCalledTimes(1);
expect(
search.middleware.map(({ instance: { $$type, $$internal } }) => ({
$$type,
$$internal,
}))
).toEqual([
{
$$type: 'ais.insights',
$$internal: true,
},
{
$$type: 'ais.metadata',
$$internal: true,
},
]);
});
});
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -418,6 +418,79 @@ See documentation: https://www.algolia.com/doc/guides/building-search-ui/going-f
'insights-middleware'
);
});

it('removes default middleware if user adds a custom one', () => {
const { instantSearchInstance } = createTestEnvironment();

// just the internal one
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],
},
},
]
`);

instantSearchInstance.use(createInsightsMiddleware({}));

// just the user-provided one
expect(instantSearchInstance.middleware).toHaveLength(1);
expect(instantSearchInstance.middleware).toMatchInlineSnapshot(`
[
{
"creator": [Function],
"instance": {
"$$internal": false,
"$$type": "ais.insights",
"onStateChange": [Function],
"started": [Function],
"subscribe": [Function],
"unsubscribe": [Function],
},
},
]
`);

instantSearchInstance.use(createInsightsMiddleware({}));

// both user-provided
expect(instantSearchInstance.middleware).toHaveLength(2);
expect(instantSearchInstance.middleware).toMatchInlineSnapshot(`
[
{
"creator": [Function],
"instance": {
"$$internal": false,
"$$type": "ais.insights",
"onStateChange": [Function],
"started": [Function],
"subscribe": [Function],
"unsubscribe": [Function],
},
},
{
"creator": [Function],
"instance": {
"$$internal": false,
"$$type": "ais.insights",
"onStateChange": [Function],
"started": [Function],
"subscribe": [Function],
"unsubscribe": [Function],
},
},
]
`);
});
});

describe('userToken', () => {
Expand Down
Loading