diff --git a/packages/autocomplete-preset-algolia/src/search/__tests__/fetchAlgoliaResults.test.ts b/packages/autocomplete-preset-algolia/src/search/__tests__/fetchAlgoliaResults.test.ts index 7c7316598..a7d5f7358 100644 --- a/packages/autocomplete-preset-algolia/src/search/__tests__/fetchAlgoliaResults.test.ts +++ b/packages/autocomplete-preset-algolia/src/search/__tests__/fetchAlgoliaResults.test.ts @@ -199,4 +199,59 @@ describe('fetchAlgoliaResults', () => { '1.0.0' ); }); + + describe('missing credentials', () => { + test('throws dev error when searchClient has no readable appId', () => { + const searchClient = { + search: createSearchClient().search, + }; + + expect(() => { + fetchAlgoliaResults({ + // @ts-expect-error + searchClient, + queries: [], + userAgents: [{ segment: 'custom-ua', version: '1.0.0' }], + }); + }).toThrowErrorMatchingInlineSnapshot( + `"[Autocomplete] The Algolia \`appId\` was not accessible from the searchClient passed."` + ); + }); + + test('throws dev error when searchClient has no readable apiKey', () => { + const searchClient = { + search: createSearchClient().search, + transporter: { + headers: { + 'x-algolia-application-id': 'appId', + }, + }, + }; + + expect(() => { + fetchAlgoliaResults({ + // @ts-expect-error + searchClient, + queries: [], + userAgents: [{ segment: 'custom-ua', version: '1.0.0' }], + }); + }).toThrowErrorMatchingInlineSnapshot( + `"[Autocomplete] The Algolia \`apiKey\` was not accessible from the searchClient passed."` + ); + }); + + test('does not throw dev error when searchClient is copied', () => { + const searchClient = { + ...createSearchClient(), + }; + + expect(() => { + fetchAlgoliaResults({ + searchClient, + queries: [], + userAgents: [{ segment: 'custom-ua', version: '1.0.0' }], + }); + }).not.toThrow(); + }); + }); }); diff --git a/packages/autocomplete-preset-algolia/src/search/fetchAlgoliaResults.ts b/packages/autocomplete-preset-algolia/src/search/fetchAlgoliaResults.ts index a94090f2b..5be499001 100644 --- a/packages/autocomplete-preset-algolia/src/search/fetchAlgoliaResults.ts +++ b/packages/autocomplete-preset-algolia/src/search/fetchAlgoliaResults.ts @@ -1,6 +1,7 @@ import { userAgents as coreUserAgents, UserAgent, + invariant, } from '@algolia/autocomplete-shared'; import { HIGHLIGHT_PRE_TAG, HIGHLIGHT_POST_TAG } from '../constants'; @@ -28,6 +29,15 @@ export function fetchAlgoliaResults({ const { appId, apiKey } = getAppIdAndApiKey(searchClient); + invariant( + Boolean(appId), + 'The Algolia `appId` was not accessible from the searchClient passed.' + ); + invariant( + Boolean(apiKey), + 'The Algolia `apiKey` was not accessible from the searchClient passed.' + ); + return searchClient .search( queries.map((searchParameters) => { diff --git a/packages/autocomplete-preset-algolia/src/utils/__tests__/getAppIdAndApiKey.test.ts b/packages/autocomplete-preset-algolia/src/utils/__tests__/getAppIdAndApiKey.test.ts index d7606a08e..1e02819ee 100644 --- a/packages/autocomplete-preset-algolia/src/utils/__tests__/getAppIdAndApiKey.test.ts +++ b/packages/autocomplete-preset-algolia/src/utils/__tests__/getAppIdAndApiKey.test.ts @@ -12,4 +12,14 @@ describe('getAppIdAndApiKey', () => { expect(appId).toEqual(APP_ID); expect(apiKey).toEqual(API_KEY); }); + + it('gets undefined appId and apiKey from broken search client', () => { + const searchClient = { + search: algoliasearchV4(APP_ID, API_KEY).search, + }; + // @ts-expect-error + const { appId, apiKey } = getAppIdAndApiKey(searchClient); + expect(appId).toEqual(undefined); + expect(apiKey).toEqual(undefined); + }); }); diff --git a/packages/autocomplete-preset-algolia/src/utils/getAppIdAndApiKey.ts b/packages/autocomplete-preset-algolia/src/utils/getAppIdAndApiKey.ts index f7add01f0..c774b1ed9 100644 --- a/packages/autocomplete-preset-algolia/src/utils/getAppIdAndApiKey.ts +++ b/packages/autocomplete-preset-algolia/src/utils/getAppIdAndApiKey.ts @@ -4,7 +4,7 @@ export function getAppIdAndApiKey(searchClient: SearchClient): { appId: string; apiKey: string; } { - const { headers, queryParameters } = searchClient.transporter; + const { headers = {}, queryParameters = {} } = searchClient.transporter || {}; const APP_ID = 'x-algolia-application-id'; const API_KEY = 'x-algolia-api-key'; const appId = headers[APP_ID] || queryParameters[APP_ID];