-
Notifications
You must be signed in to change notification settings - Fork 331
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(core): introduce metadata (#774)
- Loading branch information
1 parent
798547f
commit 79212d6
Showing
10 changed files
with
373 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
169 changes: 169 additions & 0 deletions
169
packages/autocomplete-core/src/__tests__/metadata.test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,169 @@ | ||
import { createAlgoliaInsightsPlugin } from '@algolia/autocomplete-plugin-algolia-insights'; | ||
import { noop, version } from '@algolia/autocomplete-shared'; | ||
import insightsClient from 'search-insights'; | ||
|
||
import { createPlayground, defer } from '../../../../test/utils'; | ||
import { createAutocomplete } from '../createAutocomplete'; | ||
|
||
beforeEach(() => { | ||
document.head.innerHTML = ''; | ||
}); | ||
|
||
const algoliaCrawlerEnvironment = createEnvironmentWithUserAgent( | ||
'Algolia Crawler 2.303.5' | ||
); | ||
|
||
describe('metadata', () => { | ||
test('does not enable metadata with regular user agents', async () => { | ||
createPlayground(createAutocomplete, { | ||
environment: createEnvironmentWithUserAgent( | ||
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:93.0) Gecko/20100101 Firefox/93.0' | ||
), | ||
}); | ||
|
||
await defer(noop, 0); | ||
|
||
expect(document.head).toMatchInlineSnapshot(`<head />`); | ||
}); | ||
|
||
test('does not enable metadata with no window', async () => { | ||
createPlayground(createAutocomplete, { | ||
environment: {}, | ||
}); | ||
|
||
await defer(noop, 0); | ||
|
||
expect(document.head).toMatchInlineSnapshot(`<head />`); | ||
}); | ||
|
||
test('enables metadata with Algolia Crawler user agents', async () => { | ||
createPlayground(createAutocomplete, { | ||
environment: algoliaCrawlerEnvironment, | ||
}); | ||
|
||
await defer(noop, 0); | ||
|
||
expect( | ||
JSON.parse( | ||
document.head.querySelector<HTMLMetaElement>( | ||
'meta[name="algolia:metadata"]' | ||
).content | ||
) | ||
).toEqual({ | ||
options: { 'autocomplete-core': ['environment'] }, | ||
plugins: [], | ||
ua: [{ segment: 'autocomplete-core', version }], | ||
}); | ||
}); | ||
|
||
test('exposes user agents', async () => { | ||
createPlayground(createAutocomplete, { | ||
environment: algoliaCrawlerEnvironment, | ||
}); | ||
|
||
await defer(noop, 0); | ||
|
||
expect( | ||
JSON.parse( | ||
document.head.querySelector<HTMLMetaElement>( | ||
'meta[name="algolia:metadata"]' | ||
).content | ||
).ua | ||
).toEqual([{ segment: 'autocomplete-core', version }]); | ||
}); | ||
|
||
test('exposes passed options', async () => { | ||
createPlayground(createAutocomplete, { | ||
openOnFocus: true, | ||
placeholder: 'Start searching', | ||
environment: algoliaCrawlerEnvironment, | ||
}); | ||
|
||
await defer(noop, 0); | ||
|
||
expect( | ||
JSON.parse( | ||
document.head.querySelector<HTMLMetaElement>( | ||
'meta[name="algolia:metadata"]' | ||
).content | ||
).options | ||
).toEqual({ | ||
'autocomplete-core': ['openOnFocus', 'placeholder', 'environment'], | ||
}); | ||
}); | ||
|
||
test('exposes passed plugins and their passed options', async () => { | ||
const algoliaInsightsPlugin = createAlgoliaInsightsPlugin({ | ||
insightsClient, | ||
onItemsChange: noop, | ||
}); | ||
|
||
createPlayground(createAutocomplete, { | ||
environment: algoliaCrawlerEnvironment, | ||
plugins: [algoliaInsightsPlugin], | ||
}); | ||
|
||
await defer(noop, 0); | ||
|
||
expect( | ||
JSON.parse( | ||
document.head.querySelector<HTMLMetaElement>( | ||
'meta[name="algolia:metadata"]' | ||
).content | ||
).plugins | ||
).toEqual([ | ||
{ | ||
name: 'aa.algoliaInsightsPlugin', | ||
options: ['insightsClient', 'onItemsChange'], | ||
}, | ||
]); | ||
}); | ||
|
||
test('exposes custom plugins', async () => { | ||
createPlayground(createAutocomplete, { | ||
environment: algoliaCrawlerEnvironment, | ||
plugins: [ | ||
{ | ||
name: 'customPlugin', | ||
}, | ||
], | ||
}); | ||
|
||
await defer(noop, 0); | ||
|
||
expect( | ||
JSON.parse( | ||
document.head.querySelector<HTMLMetaElement>( | ||
'meta[name="algolia:metadata"]' | ||
).content | ||
).plugins | ||
).toEqual([{ name: 'customPlugin', options: [] }]); | ||
}); | ||
|
||
test('does not set a fallback name for unnamed custom plugins', async () => { | ||
createPlayground(createAutocomplete, { | ||
environment: algoliaCrawlerEnvironment, | ||
plugins: [{}], | ||
}); | ||
|
||
await defer(noop, 0); | ||
|
||
expect( | ||
JSON.parse( | ||
document.head.querySelector<HTMLMetaElement>( | ||
'meta[name="algolia:metadata"]' | ||
).content | ||
).plugins | ||
).toEqual([{ options: [] }]); | ||
}); | ||
}); | ||
|
||
function createEnvironmentWithUserAgent(userAgent: string) { | ||
return { | ||
...global, | ||
navigator: { | ||
...global.navigator, | ||
userAgent, | ||
}, | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
import { UserAgent, userAgents } from '@algolia/autocomplete-shared'; | ||
|
||
import { | ||
AutocompleteEnvironment, | ||
AutocompleteOptions, | ||
AutocompleteOptionsWithMetadata, | ||
AutocompletePlugin, | ||
BaseItem, | ||
} from '.'; | ||
|
||
type AutocompleteMetadata = { | ||
plugins: Array<{ | ||
name: string | undefined; | ||
options: string[]; | ||
}>; | ||
options: Record<string, string[]>; | ||
ua: UserAgent[]; | ||
}; | ||
|
||
type GetMetadataParams<TItem extends BaseItem, TData = unknown> = { | ||
plugins: Array<AutocompletePlugin<TItem, TData>>; | ||
options: AutocompleteOptionsWithMetadata<TItem>; | ||
}; | ||
|
||
export function getMetadata<TItem extends BaseItem, TData = unknown>({ | ||
plugins, | ||
options, | ||
}: GetMetadataParams<TItem, TData>) { | ||
const optionsKey = ((options.__autocomplete_metadata | ||
?.userAgents as UserAgent[]) || [])[0]?.segment; | ||
|
||
const extraOptions = optionsKey | ||
? { | ||
[optionsKey]: Object.keys( | ||
(options.__autocomplete_metadata | ||
?.options as AutocompleteOptions<TItem>) || {} | ||
), | ||
} | ||
: {}; | ||
|
||
return { | ||
plugins: plugins.map((plugin) => ({ | ||
name: plugin.name, | ||
options: Object.keys(plugin.__autocomplete_pluginOptions || []), | ||
})), | ||
options: { | ||
'autocomplete-core': Object.keys(options), | ||
...extraOptions, | ||
}, | ||
ua: userAgents.concat( | ||
(options.__autocomplete_metadata?.userAgents as any) || [] | ||
), | ||
}; | ||
} | ||
|
||
type InlineMetadataParams = { | ||
metadata: AutocompleteMetadata; | ||
environment: AutocompleteEnvironment; | ||
}; | ||
|
||
export function injectMetadata({ | ||
metadata, | ||
environment, | ||
}: InlineMetadataParams) { | ||
const isMetadataEnabled = environment.navigator?.userAgent.includes( | ||
'Algolia Crawler' | ||
); | ||
|
||
if (isMetadataEnabled) { | ||
const metadataContainer = environment.document.createElement('meta'); | ||
const headRef = environment.document.querySelector('head'); | ||
|
||
metadataContainer.name = 'algolia:metadata'; | ||
|
||
setTimeout(() => { | ||
metadataContainer.content = JSON.stringify(metadata); | ||
headRef!.appendChild(metadataContainer); | ||
}, 0); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.