Skip to content

Commit fdf2b34

Browse files
authored
fix(metadata): ensure safe user agent detection (#993)
1 parent de0e375 commit fdf2b34

File tree

5 files changed

+34
-4
lines changed

5 files changed

+34
-4
lines changed

packages/autocomplete-core/src/__tests__/metadata.test.ts

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,29 @@ describe('metadata', () => {
3636
expect(document.head).toMatchInlineSnapshot(`<head />`);
3737
});
3838

39+
test('does not enable metadata with a window but no navigator', async () => {
40+
createPlayground(createAutocomplete, {
41+
environment: {
42+
...createEnvironmentWithUserAgent(),
43+
navigator: undefined,
44+
},
45+
});
46+
47+
await defer(noop, 0);
48+
49+
expect(document.head).toMatchInlineSnapshot(`<head />`);
50+
});
51+
52+
test("does not enable metadata when navigator is different from browser's (React Native)", async () => {
53+
createPlayground(createAutocomplete, {
54+
environment: createEnvironmentWithUserAgent(),
55+
});
56+
57+
await defer(noop, 0);
58+
59+
expect(document.head).toMatchInlineSnapshot(`<head />`);
60+
});
61+
3962
test('enables metadata with Algolia Crawler user agents', async () => {
4063
createPlayground(createAutocomplete, {
4164
environment: algoliaCrawlerEnvironment,
@@ -158,7 +181,7 @@ describe('metadata', () => {
158181
});
159182
});
160183

161-
function createEnvironmentWithUserAgent(userAgent: string) {
184+
function createEnvironmentWithUserAgent(userAgent?: string) {
162185
return {
163186
...global,
164187
navigator: {

packages/autocomplete-core/src/getPropGetters.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,7 @@ export function getPropGetters<
170170
const { inputElement, maxLength = 512, ...rest } = providedProps || {};
171171
const activeItem = getActiveItem(store.getState());
172172

173-
const userAgent = props.environment.navigator?.userAgent;
173+
const userAgent = props.environment.navigator?.userAgent || '';
174174
const shouldFallbackKeyHint = isSamsung(userAgent);
175175
const enterKeyHint =
176176
activeItem?.itemUrl && !shouldFallbackKeyHint ? 'go' : 'search';

packages/autocomplete-core/src/metadata.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ export function injectMetadata({
6262
metadata,
6363
environment,
6464
}: InlineMetadataParams) {
65-
const isMetadataEnabled = environment.navigator?.userAgent.includes(
65+
const isMetadataEnabled = environment.navigator?.userAgent?.includes(
6666
'Algolia Crawler'
6767
);
6868

packages/autocomplete-core/src/types/AutocompleteEnvironment.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,8 @@ export type AutocompleteEnvironment =
1111
assign: Location['assign'];
1212
};
1313
open: Window['open'];
14-
navigator: Window['navigator'];
14+
// In React Native, `navigator` is polyfilled and doesn't have all
15+
// properties traditionally exposed in the browser.
16+
// https://github.com/facebook/react-native/blob/8bd3edec88148d0ab1f225d2119435681fbbba33/Libraries/Core/setUpNavigator.js
17+
navigator?: Partial<Window['navigator']>;
1518
};

packages/autocomplete-core/src/utils/__tests__/isSamsung.test.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,4 +200,8 @@ describe('isSamsung', () => {
200200
});
201201
});
202202
});
203+
204+
test('returns false with an empty user agent', () => {
205+
expect(isSamsung('')).toEqual(false);
206+
});
203207
});

0 commit comments

Comments
 (0)