Skip to content

Commit

Permalink
feat(js): add JS user agent to Algolia requests (#420)
Browse files Browse the repository at this point in the history
  • Loading branch information
francoischalifour authored Feb 1, 2021
1 parent 226fc54 commit fab2d57
Show file tree
Hide file tree
Showing 16 changed files with 289 additions and 79 deletions.
4 changes: 2 additions & 2 deletions bundlesize.config.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@
},
{
"path": "packages/autocomplete-js/dist/umd/index.production.js",
"maxSize": "13.65 kB"
"maxSize": "13.75 kB"
},
{
"path": "packages/autocomplete-preset-algolia/dist/umd/index.production.js",
"maxSize": "1.75 kB"
"maxSize": "2 kB"
},
{
"path": "packages/autocomplete-plugin-algolia-insights/dist/umd/index.production.js",
Expand Down
29 changes: 29 additions & 0 deletions packages/autocomplete-js/src/__tests__/getAlgoliaHits.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import algoliaPreset from '@algolia/autocomplete-preset-algolia';

import { createSearchClient } from '../../../../test/utils';
import { getAlgoliaHits } from '../getAlgoliaHits';
import { version } from '../version';

jest.mock('@algolia/autocomplete-preset-algolia', () => {
const module = jest.requireActual('@algolia/autocomplete-preset-algolia');

return {
...module,
getAlgoliaHits: jest.fn(),
};
});

describe('getAlgoliaHits', () => {
test('forwards params to the preset function', () => {
const searchClient = createSearchClient();

getAlgoliaHits({ searchClient, queries: [] });

expect(algoliaPreset.getAlgoliaHits).toHaveBeenCalledTimes(1);
expect(algoliaPreset.getAlgoliaHits).toHaveBeenCalledWith({
searchClient,
queries: [],
userAgents: [{ segment: 'autocomplete-js', version }],
});
});
});
29 changes: 29 additions & 0 deletions packages/autocomplete-js/src/__tests__/getAlgoliaResults.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import algoliaPreset from '@algolia/autocomplete-preset-algolia';

import { createSearchClient } from '../../../../test/utils';
import { getAlgoliaResults } from '../getAlgoliaResults';
import { version } from '../version';

jest.mock('@algolia/autocomplete-preset-algolia', () => {
const module = jest.requireActual('@algolia/autocomplete-preset-algolia');

return {
...module,
getAlgoliaResults: jest.fn(),
};
});

describe('getAlgoliaResults', () => {
test('forwards params to the preset function', () => {
const searchClient = createSearchClient();

getAlgoliaResults({ searchClient, queries: [] });

expect(algoliaPreset.getAlgoliaResults).toHaveBeenCalledTimes(1);
expect(algoliaPreset.getAlgoliaResults).toHaveBeenCalledWith({
searchClient,
queries: [],
userAgents: [{ segment: 'autocomplete-js', version }],
});
});
});
17 changes: 17 additions & 0 deletions packages/autocomplete-js/src/getAlgoliaHits.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import {
getAlgoliaHits as getAlgoliaHitsOriginal,
SearchParams,
} from '@algolia/autocomplete-preset-algolia';

import { version } from './version';

export function getAlgoliaHits<TRecord>({
searchClient,
queries,
}: Pick<SearchParams, 'searchClient' | 'queries'>) {
return getAlgoliaHitsOriginal<TRecord>({
searchClient,
queries,
userAgents: [{ segment: 'autocomplete-js', version }],
});
}
17 changes: 17 additions & 0 deletions packages/autocomplete-js/src/getAlgoliaResults.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import {
getAlgoliaResults as getAlgoliaResultsOriginal,
SearchParams,
} from '@algolia/autocomplete-preset-algolia';

import { version } from './version';

export function getAlgoliaResults<TRecord>({
searchClient,
queries,
}: Pick<SearchParams, 'searchClient' | 'queries'>) {
return getAlgoliaResultsOriginal<TRecord>({
searchClient,
queries,
userAgents: [{ segment: 'autocomplete-js', version }],
});
}
6 changes: 2 additions & 4 deletions packages/autocomplete-js/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
export * from './autocomplete';
export * from './getAlgoliaHits';
export * from './getAlgoliaResults';
export * from './highlight';
export {
getAlgoliaResults,
getAlgoliaHits,
} from '@algolia/autocomplete-preset-algolia';
export * from './types';
1 change: 1 addition & 0 deletions packages/autocomplete-js/src/version.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const version = '1.0.0-alpha.39';
1 change: 1 addition & 0 deletions packages/autocomplete-preset-algolia/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ export * from './highlight/parseAlgoliaHitReverseSnippet';
export * from './highlight/parseAlgoliaHitSnippet';
export * from './search/getAlgoliaHits';
export * from './search/getAlgoliaResults';
export type { SearchParams } from './search/search';
Original file line number Diff line number Diff line change
@@ -1,54 +1,13 @@
import {
MultipleQueriesResponse,
SearchResponse,
} from '@algolia/client-search';

createMultiSearchResponse,
createSearchClient,
} from '../../../../../test/utils';
import { version } from '../../version';
import { getAlgoliaHits } from '../getAlgoliaHits';
import { getAlgoliaResults } from '../getAlgoliaResults';

function createSingleSearchResponse<THit>(
partialResponse: Partial<SearchResponse<THit>> = {}
): SearchResponse<THit> {
const {
query = '',
page = 0,
hitsPerPage = 20,
hits = [],
nbHits = hits.length,
nbPages = Math.ceil(nbHits / hitsPerPage),
params = '',
exhaustiveNbHits = true,
exhaustiveFacetsCount = true,
processingTimeMS = 0,
...rest
} = partialResponse;

return {
page,
hitsPerPage,
nbHits,
nbPages,
processingTimeMS,
hits,
query,
params,
exhaustiveNbHits,
exhaustiveFacetsCount,
...rest,
};
}

function createMultiSearchResponse<THit>(
...partialReponses: Array<Partial<SearchResponse<THit>>>
): MultipleQueriesResponse<THit> {
return {
results: partialReponses.map(createSingleSearchResponse),
};
}

function createSearchClient(): any {
return {
function createTestSearchClient() {
return createSearchClient({
search: jest.fn(() =>
Promise.resolve(
createMultiSearchResponse<{ label: string }>(
Expand All @@ -57,12 +16,12 @@ function createSearchClient(): any {
)
)
),
};
});
}

describe('getAlgoliaResults', () => {
test('with default options', async () => {
const searchClient = createSearchClient();
const searchClient = createTestSearchClient();

const results = await getAlgoliaResults({
searchClient,
Expand Down Expand Up @@ -93,7 +52,7 @@ describe('getAlgoliaResults', () => {
});

test('with custom search parameters', async () => {
const searchClient = createSearchClient();
const searchClient = createTestSearchClient();

const results = await getAlgoliaResults({
searchClient,
Expand Down Expand Up @@ -130,9 +89,8 @@ describe('getAlgoliaResults', () => {
]);
});

test('attaches Algolia agent', async () => {
const searchClient = createSearchClient();
searchClient.addAlgoliaAgent = jest.fn();
test('attaches default Algolia agent', async () => {
const searchClient = createTestSearchClient();

await getAlgoliaResults({
searchClient,
Expand All @@ -156,11 +114,33 @@ describe('getAlgoliaResults', () => {
version
);
});

test('allows custom user agents', async () => {
const searchClient = createTestSearchClient();

await getAlgoliaResults({
searchClient,
queries: [],
userAgents: [{ segment: 'custom-ua', version: '1.0.0' }],
});

expect(searchClient.addAlgoliaAgent).toHaveBeenCalledTimes(2);
expect(searchClient.addAlgoliaAgent).toHaveBeenNthCalledWith(
1,
'autocomplete-core',
version
);
expect(searchClient.addAlgoliaAgent).toHaveBeenNthCalledWith(
2,
'custom-ua',
'1.0.0'
);
});
});

describe('getAlgoliaHits', () => {
test('with default options', async () => {
const searchClient = createSearchClient();
const searchClient = createTestSearchClient();

const hits = await getAlgoliaHits({
searchClient,
Expand Down Expand Up @@ -191,7 +171,7 @@ describe('getAlgoliaHits', () => {
});

test('with custom search parameters', async () => {
const searchClient = createSearchClient();
const searchClient = createTestSearchClient();

const hits = await getAlgoliaHits({
searchClient,
Expand Down Expand Up @@ -229,8 +209,7 @@ describe('getAlgoliaHits', () => {
});

test('attaches Algolia agent', async () => {
const searchClient = createSearchClient();
searchClient.addAlgoliaAgent = jest.fn();
const searchClient = createTestSearchClient();

await getAlgoliaHits({
searchClient,
Expand All @@ -254,4 +233,26 @@ describe('getAlgoliaHits', () => {
version
);
});

test('allows custom user agents', async () => {
const searchClient = createTestSearchClient();

await getAlgoliaHits({
searchClient,
queries: [],
userAgents: [{ segment: 'custom-ua', version: '1.0.0' }],
});

expect(searchClient.addAlgoliaAgent).toHaveBeenCalledTimes(2);
expect(searchClient.addAlgoliaAgent).toHaveBeenNthCalledWith(
1,
'autocomplete-core',
version
);
expect(searchClient.addAlgoliaAgent).toHaveBeenNthCalledWith(
2,
'custom-ua',
'1.0.0'
);
});
});
27 changes: 15 additions & 12 deletions packages/autocomplete-preset-algolia/src/search/getAlgoliaHits.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,21 @@ import { search, SearchParams } from './search';
export function getAlgoliaHits<TRecord>({
searchClient,
queries,
userAgents,
}: SearchParams): Promise<Array<Array<Hit<TRecord>>>> {
return search<TRecord>({ searchClient, queries }).then((response) => {
const results = response.results;
return search<TRecord>({ searchClient, queries, userAgents }).then(
(response) => {
const results = response.results;

return results.map((result) =>
result.hits.map((hit) => {
return {
...hit,
__autocomplete_indexName: result.index,
__autocomplete_queryID: result.queryID,
};
})
);
});
return results.map((result) =>
result.hits.map((hit) => {
return {
...hit,
__autocomplete_indexName: result.index,
__autocomplete_queryID: result.queryID,
};
})
);
}
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,11 @@ import { search, SearchParams } from './search';
export function getAlgoliaResults<TRecord>({
searchClient,
queries,
userAgents,
}: SearchParams): Promise<Array<SearchResponse<TRecord>>> {
return search<TRecord>({ searchClient, queries }).then((response) => {
return response.results;
});
return search<TRecord>({ searchClient, queries, userAgents }).then(
(response) => {
return response.results;
}
);
}
17 changes: 15 additions & 2 deletions packages/autocomplete-preset-algolia/src/search/search.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,27 @@ import { SearchClient } from 'algoliasearch/lite';
import { HIGHLIGHT_PRE_TAG, HIGHLIGHT_POST_TAG } from '../constants';
import { version } from '../version';

type UserAgent = { segment: string; version?: string };
export interface SearchParams {
searchClient: SearchClient;
queries: MultipleQueriesQuery[];
userAgents?: UserAgent[];
}

export function search<TRecord>({ searchClient, queries }: SearchParams) {
export function search<TRecord>({
searchClient,
queries,
userAgents = [],
}: SearchParams) {
if (typeof searchClient.addAlgoliaAgent === 'function') {
searchClient.addAlgoliaAgent('autocomplete-core', version);
const algoliaAgents: UserAgent[] = [
{ segment: 'autocomplete-core', version },
...userAgents,
];

algoliaAgents.forEach(({ segment, version }) => {
searchClient.addAlgoliaAgent(segment, version);
});
}

return searchClient.search<TRecord>(
Expand Down
1 change: 1 addition & 0 deletions ship.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ module.exports = {
version,
files: [
path.resolve(dir, 'packages', 'autocomplete-core', 'src', 'version.ts'),
path.resolve(dir, 'packages', 'autocomplete-js', 'src', 'version.ts'),
path.resolve(
dir,
'packages',
Expand Down
Loading

0 comments on commit fab2d57

Please sign in to comment.