Skip to content

Commit fd92560

Browse files
authored
chore(javascript): assert authMode (#2897)
1 parent dc92daa commit fd92560

File tree

3 files changed

+425
-11
lines changed

3 files changed

+425
-11
lines changed
Lines changed: 348 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,348 @@
1+
import type { EchoResponse } from '@algolia/client-common';
2+
import {
3+
DEFAULT_CONNECT_TIMEOUT_BROWSER,
4+
DEFAULT_READ_TIMEOUT_BROWSER,
5+
DEFAULT_WRITE_TIMEOUT_BROWSER,
6+
} from '@algolia/client-common';
7+
import { echoRequester } from '@algolia/requester-browser-xhr';
8+
9+
import { algoliasearch, apiClientVersion } from '../builds/browser';
10+
import { liteClient } from '../lite/builds/browser';
11+
12+
const client = algoliasearch('APP_ID', 'API_KEY', {
13+
requester: echoRequester(),
14+
});
15+
16+
describe('api', () => {
17+
it('exposes the `appId` currently in use at the root of the API', () => {
18+
expect(client.appId).toEqual('APP_ID');
19+
});
20+
21+
it('provides a `clearCache` method', () => {
22+
expect(client.clearCache).not.toBeUndefined();
23+
});
24+
25+
it('sets the user agent', async () => {
26+
const req = (await client.customPost({
27+
path: '/test',
28+
})) as unknown as EchoResponse;
29+
30+
expect(req.algoliaAgent).toMatchInlineSnapshot(
31+
`"Algolia%20for%20JavaScript%20(${apiClientVersion})%3B%20Search%20(${apiClientVersion})%3B%20Browser"`
32+
);
33+
});
34+
35+
it('throws with undefined API key', () => {
36+
expect(() => algoliasearch('APP_ID', '')).toThrow("`apiKey` is missing")
37+
});
38+
39+
it('throws with undefined app ID', () => {
40+
expect(() => algoliasearch('', 'API_KEY')).toThrow("`appId` is missing")
41+
});
42+
43+
it('provides the search client at the root of the API', () => {
44+
expect(client.search).not.toBeUndefined();
45+
});
46+
47+
describe('_ua', () => {
48+
it('provides a backward compatible `_ua` variable at the root of the client', () => {
49+
expect(client._ua).toEqual(
50+
expect.stringContaining(
51+
`Algolia for JavaScript (${apiClientVersion}); Search (${apiClientVersion});`
52+
)
53+
);
54+
});
55+
56+
it('keeps `_ua` updated with the transporter algolia agent', () => {
57+
expect(client._ua).toEqual(expect.stringMatching(/.*; Browser$/g));
58+
59+
client.addAlgoliaAgent('Jest', '0.0.1');
60+
61+
expect(client._ua).toEqual(
62+
expect.stringMatching(/.*; Jest \(0\.0\.1\)$/g)
63+
);
64+
});
65+
});
66+
67+
it('exposes the search client transporter for the algoliasearch client', () => {
68+
expect(client.transporter).not.toBeUndefined();
69+
expect(client.transporter).toEqual({
70+
algoliaAgent: {
71+
add: expect.any(Function),
72+
value: expect.stringContaining(
73+
`Algolia for JavaScript (${apiClientVersion}); Search (${apiClientVersion});`
74+
),
75+
},
76+
baseHeaders: {
77+
'content-type': 'text/plain',
78+
},
79+
baseQueryParameters: {
80+
'x-algolia-api-key': 'API_KEY',
81+
'x-algolia-application-id': 'APP_ID',
82+
},
83+
hosts: expect.arrayContaining([
84+
{
85+
accept: 'read',
86+
protocol: 'https',
87+
url: 'APP_ID-dsn.algolia.net',
88+
},
89+
{
90+
accept: 'write',
91+
protocol: 'https',
92+
url: 'APP_ID.algolia.net',
93+
},
94+
{
95+
accept: 'readWrite',
96+
protocol: 'https',
97+
url: 'APP_ID-3.algolianet.com',
98+
},
99+
{
100+
accept: 'readWrite',
101+
protocol: 'https',
102+
url: 'APP_ID-1.algolianet.com',
103+
},
104+
{
105+
accept: 'readWrite',
106+
protocol: 'https',
107+
url: 'APP_ID-2.algolianet.com',
108+
},
109+
]),
110+
hostsCache: {
111+
clear: expect.any(Function),
112+
delete: expect.any(Function),
113+
get: expect.any(Function),
114+
set: expect.any(Function),
115+
},
116+
request: expect.any(Function),
117+
requester: {
118+
send: expect.any(Function),
119+
},
120+
requestsCache: {
121+
clear: expect.any(Function),
122+
delete: expect.any(Function),
123+
get: expect.any(Function),
124+
set: expect.any(Function),
125+
},
126+
responsesCache: {
127+
clear: expect.any(Function),
128+
delete: expect.any(Function),
129+
get: expect.any(Function),
130+
set: expect.any(Function),
131+
},
132+
timeouts: {
133+
connect: DEFAULT_CONNECT_TIMEOUT_BROWSER,
134+
read: DEFAULT_READ_TIMEOUT_BROWSER,
135+
write: DEFAULT_WRITE_TIMEOUT_BROWSER,
136+
},
137+
});
138+
});
139+
140+
describe('init clients', () => {
141+
it('provides an init method for the analytics client', () => {
142+
expect(client.initAnalytics).not.toBeUndefined();
143+
});
144+
145+
it('provides an init method for the abtesting client', () => {
146+
expect(client.initAbtesting).not.toBeUndefined();
147+
});
148+
149+
it('provides an init method for the personalization client', () => {
150+
expect(client.initPersonalization).not.toBeUndefined();
151+
});
152+
153+
it('default `init` clients to the root `algoliasearch` credentials', async () => {
154+
const abtestingClient = client.initAbtesting();
155+
const analyticsClient = client.initAnalytics();
156+
const personalizationClient = client.initPersonalization({
157+
region: 'eu',
158+
});
159+
160+
const res1 = (await abtestingClient.customGet({
161+
path: 'abtestingClient',
162+
})) as unknown as EchoResponse;
163+
const res2 = (await analyticsClient.customGet({
164+
path: 'analyticsClient',
165+
})) as unknown as EchoResponse;
166+
const res3 = (await personalizationClient.customGet({
167+
path: 'personalizationClient',
168+
})) as unknown as EchoResponse;
169+
170+
expect(res1.searchParams).toEqual(
171+
expect.objectContaining({
172+
'x-algolia-application-id': 'APP_ID',
173+
'x-algolia-api-key': 'API_KEY',
174+
})
175+
);
176+
expect(res2.searchParams).toEqual(
177+
expect.objectContaining({
178+
'x-algolia-application-id': 'APP_ID',
179+
'x-algolia-api-key': 'API_KEY',
180+
})
181+
);
182+
expect(res3.searchParams).toEqual(
183+
expect.objectContaining({
184+
'x-algolia-application-id': 'APP_ID',
185+
'x-algolia-api-key': 'API_KEY',
186+
})
187+
);
188+
});
189+
190+
it('`init` clients accept different credentials', async () => {
191+
const abtestingClient = client.initAbtesting({
192+
appId: 'appId1',
193+
apiKey: 'apiKey1',
194+
});
195+
const analyticsClient = client.initAnalytics({
196+
appId: 'appId2',
197+
apiKey: 'apiKey2',
198+
});
199+
const personalizationClient = client.initPersonalization({
200+
appId: 'appId3',
201+
apiKey: 'apiKey3',
202+
region: 'eu',
203+
});
204+
205+
const res1 = (await abtestingClient.customGet({
206+
path: 'abtestingClient',
207+
})) as unknown as EchoResponse;
208+
const res2 = (await analyticsClient.customGet({
209+
path: 'analyticsClient',
210+
})) as unknown as EchoResponse;
211+
const res3 = (await personalizationClient.customGet({
212+
path: 'personalizationClient',
213+
})) as unknown as EchoResponse;
214+
215+
expect(res1.searchParams).toEqual(
216+
expect.objectContaining({
217+
'x-algolia-application-id': 'appId1',
218+
'x-algolia-api-key': 'apiKey1',
219+
})
220+
);
221+
expect(res2.searchParams).toEqual(
222+
expect.objectContaining({
223+
'x-algolia-application-id': 'appId2',
224+
'x-algolia-api-key': 'apiKey2',
225+
})
226+
);
227+
expect(res3.searchParams).toEqual(
228+
expect.objectContaining({
229+
'x-algolia-application-id': 'appId3',
230+
'x-algolia-api-key': 'apiKey3',
231+
})
232+
);
233+
});
234+
});
235+
});
236+
237+
describe('bundle', () => {
238+
it('expose both a full bundled package and a lite one', () => {
239+
expect(liteClient).not.toBeUndefined();
240+
expect(algoliasearch).not.toBeUndefined();
241+
});
242+
});
243+
244+
/**
245+
* We only test the legacy signature, as `algoliasearch` inherits methods from the `client-search`.
246+
* The new signatures are already tested in the CTS.
247+
*/
248+
describe('search with legacy signature', () => {
249+
it('allows searching for query', async () => {
250+
const req = (await client.search([
251+
{
252+
indexName: 'theIndexName',
253+
},
254+
])) as unknown as EchoResponse;
255+
256+
expect(req.path).toEqual('/1/indexes/*/queries');
257+
expect(req.method).toEqual('POST');
258+
expect(req.data).toEqual({ requests: [{ indexName: 'theIndexName' }] });
259+
expect(req.searchParams).toStrictEqual({
260+
'x-algolia-api-key': 'API_KEY',
261+
'x-algolia-application-id': 'APP_ID',
262+
});
263+
});
264+
265+
it('allows searching for facet', async () => {
266+
const req = (await client.search([
267+
{
268+
indexName: 'theIndexName',
269+
type: 'facet',
270+
facet: 'theFacet',
271+
},
272+
])) as unknown as EchoResponse;
273+
274+
expect(req.path).toEqual('/1/indexes/*/queries');
275+
expect(req.method).toEqual('POST');
276+
expect(req.data).toEqual({
277+
requests: [
278+
{ indexName: 'theIndexName', type: 'facet', facet: 'theFacet' },
279+
],
280+
});
281+
expect(req.searchParams).toStrictEqual({
282+
'x-algolia-api-key': 'API_KEY',
283+
'x-algolia-application-id': 'APP_ID',
284+
});
285+
});
286+
287+
it('accepts a `params` parameter for `searchParams`', async () => {
288+
const req = (await client.search([
289+
{
290+
indexName: 'theIndexName',
291+
params: {
292+
hitsPerPage: 42,
293+
},
294+
},
295+
])) as unknown as EchoResponse;
296+
297+
expect(req.path).toEqual('/1/indexes/*/queries');
298+
expect(req.method).toEqual('POST');
299+
expect(req.data).toEqual({
300+
requests: [{ indexName: 'theIndexName', hitsPerPage: 42 }],
301+
});
302+
expect(req.searchParams).toStrictEqual({
303+
'x-algolia-api-key': 'API_KEY',
304+
'x-algolia-application-id': 'APP_ID',
305+
});
306+
});
307+
});
308+
309+
describe('init', () => {
310+
test('sets authMode', async () => {
311+
const qpClient = algoliasearch('foo', 'bar', {
312+
authMode: 'WithinQueryParameters',
313+
requester: echoRequester(),
314+
});
315+
const headerClient = algoliasearch('foo', 'bar', {
316+
authMode: 'WithinHeaders',
317+
requester: echoRequester(),
318+
});
319+
320+
const qpResult = (await qpClient.customGet({
321+
path: '1/foo',
322+
})) as unknown as EchoResponse;
323+
expect(qpResult.searchParams).toEqual({
324+
'x-algolia-api-key': 'bar',
325+
'x-algolia-application-id': 'foo',
326+
});
327+
328+
const headerResult = (await headerClient.customGet({
329+
path: '1/bar',
330+
})) as unknown as EchoResponse;
331+
expect(headerResult.headers).toEqual({
332+
accept: 'application/json',
333+
'content-type': 'text/plain',
334+
'x-algolia-api-key': 'bar',
335+
'x-algolia-application-id': 'foo',
336+
});
337+
});
338+
339+
test('defaults to qp', async () => {
340+
const res = (await client.customGet({
341+
path: '1/foo',
342+
})) as unknown as EchoResponse;
343+
expect(res.searchParams).toEqual({
344+
'x-algolia-api-key': 'API_KEY',
345+
'x-algolia-application-id': 'APP_ID',
346+
});
347+
});
348+
});

0 commit comments

Comments
 (0)