cloudflare/cloudflare-typescript

Public

mirrored fromhttps://github.com/cloudflare/cloudflare-typescriptAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
jacobbednarz-patch-1

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

tests/index.test.ts

398lines · modecode

1// File generated from our OpenAPI spec by Stainless.
2
3import Cloudflare from 'cloudflare';
4import { APIUserAbortError } from 'cloudflare';
5import { Headers } from 'cloudflare/core';
6import defaultFetch, { Response, type RequestInit, type RequestInfo } from 'node-fetch';
7
8describe('instantiate client', () => {
9 const env = process.env;
10
11 beforeEach(() => {
12 jest.resetModules();
13 process.env = { ...env };
14
15 console.warn = jest.fn();
16 });
17
18 afterEach(() => {
19 process.env = env;
20 });
21
22 describe('defaultHeaders', () => {
23 const client = new Cloudflare({
24 baseURL: 'http://localhost:5000/',
25 defaultHeaders: { 'X-My-Default-Header': '2' },
26 apiKey: '144c9defac04969c7bfad8efaa8ea194',
27 apiEmail: 'dev@cloudflare.com',
28 apiToken: 'Sn3lZJTBX6kkg7OdcBUAxOO963GEIyGQqnFTOFYY',
29 userServiceKey: 'My User Service Key',
30 });
31
32 test('they are used in the request', () => {
33 const { req } = client.buildRequest({ path: '/foo', method: 'post' });
34 expect((req.headers as Headers)['x-my-default-header']).toEqual('2');
35 });
36
37 test('can ignore `undefined` and leave the default', () => {
38 const { req } = client.buildRequest({
39 path: '/foo',
40 method: 'post',
41 headers: { 'X-My-Default-Header': undefined },
42 });
43 expect((req.headers as Headers)['x-my-default-header']).toEqual('2');
44 });
45
46 test('can be removed with `null`', () => {
47 const { req } = client.buildRequest({
48 path: '/foo',
49 method: 'post',
50 headers: { 'X-My-Default-Header': null },
51 });
52 expect(req.headers as Headers).not.toHaveProperty('x-my-default-header');
53 });
54 });
55
56 describe('defaultQuery', () => {
57 test('with null query params given', () => {
58 const client = new Cloudflare({
59 baseURL: 'http://localhost:5000/',
60 defaultQuery: { apiVersion: 'foo' },
61 apiKey: '144c9defac04969c7bfad8efaa8ea194',
62 apiEmail: 'dev@cloudflare.com',
63 apiToken: 'Sn3lZJTBX6kkg7OdcBUAxOO963GEIyGQqnFTOFYY',
64 userServiceKey: 'My User Service Key',
65 });
66 expect(client.buildURL('/foo', null)).toEqual('http://localhost:5000/foo?apiVersion=foo');
67 });
68
69 test('multiple default query params', () => {
70 const client = new Cloudflare({
71 baseURL: 'http://localhost:5000/',
72 defaultQuery: { apiVersion: 'foo', hello: 'world' },
73 apiKey: '144c9defac04969c7bfad8efaa8ea194',
74 apiEmail: 'dev@cloudflare.com',
75 apiToken: 'Sn3lZJTBX6kkg7OdcBUAxOO963GEIyGQqnFTOFYY',
76 userServiceKey: 'My User Service Key',
77 });
78 expect(client.buildURL('/foo', null)).toEqual('http://localhost:5000/foo?apiVersion=foo&hello=world');
79 });
80
81 test('overriding with `undefined`', () => {
82 const client = new Cloudflare({
83 baseURL: 'http://localhost:5000/',
84 defaultQuery: { hello: 'world' },
85 apiKey: '144c9defac04969c7bfad8efaa8ea194',
86 apiEmail: 'dev@cloudflare.com',
87 apiToken: 'Sn3lZJTBX6kkg7OdcBUAxOO963GEIyGQqnFTOFYY',
88 userServiceKey: 'My User Service Key',
89 });
90 expect(client.buildURL('/foo', { hello: undefined })).toEqual('http://localhost:5000/foo');
91 });
92 });
93
94 test('custom fetch', async () => {
95 const client = new Cloudflare({
96 baseURL: 'http://localhost:5000/',
97 apiKey: '144c9defac04969c7bfad8efaa8ea194',
98 apiEmail: 'dev@cloudflare.com',
99 apiToken: 'Sn3lZJTBX6kkg7OdcBUAxOO963GEIyGQqnFTOFYY',
100 userServiceKey: 'My User Service Key',
101 fetch: (url) => {
102 return Promise.resolve(
103 new Response(JSON.stringify({ url, custom: true }), {
104 headers: { 'Content-Type': 'application/json' },
105 }),
106 );
107 },
108 });
109
110 const response = await client.get('/foo');
111 expect(response).toEqual({ url: 'http://localhost:5000/foo', custom: true });
112 });
113
114 test('custom signal', async () => {
115 const client = new Cloudflare({
116 baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010',
117 apiKey: '144c9defac04969c7bfad8efaa8ea194',
118 apiEmail: 'dev@cloudflare.com',
119 apiToken: 'Sn3lZJTBX6kkg7OdcBUAxOO963GEIyGQqnFTOFYY',
120 userServiceKey: 'My User Service Key',
121 fetch: (...args) => {
122 return new Promise((resolve, reject) =>
123 setTimeout(
124 () =>
125 defaultFetch(...args)
126 .then(resolve)
127 .catch(reject),
128 300,
129 ),
130 );
131 },
132 });
133
134 const controller = new AbortController();
135 setTimeout(() => controller.abort(), 200);
136
137 const spy = jest.spyOn(client, 'request');
138
139 await expect(client.get('/foo', { signal: controller.signal })).rejects.toThrowError(APIUserAbortError);
140 expect(spy).toHaveBeenCalledTimes(1);
141 });
142
143 describe('baseUrl', () => {
144 test('trailing slash', () => {
145 const client = new Cloudflare({
146 baseURL: 'http://localhost:5000/custom/path/',
147 apiKey: '144c9defac04969c7bfad8efaa8ea194',
148 apiEmail: 'dev@cloudflare.com',
149 apiToken: 'Sn3lZJTBX6kkg7OdcBUAxOO963GEIyGQqnFTOFYY',
150 userServiceKey: 'My User Service Key',
151 });
152 expect(client.buildURL('/foo', null)).toEqual('http://localhost:5000/custom/path/foo');
153 });
154
155 test('no trailing slash', () => {
156 const client = new Cloudflare({
157 baseURL: 'http://localhost:5000/custom/path',
158 apiKey: '144c9defac04969c7bfad8efaa8ea194',
159 apiEmail: 'dev@cloudflare.com',
160 apiToken: 'Sn3lZJTBX6kkg7OdcBUAxOO963GEIyGQqnFTOFYY',
161 userServiceKey: 'My User Service Key',
162 });
163 expect(client.buildURL('/foo', null)).toEqual('http://localhost:5000/custom/path/foo');
164 });
165
166 afterEach(() => {
167 process.env['CLOUDFLARE_BASE_URL'] = undefined;
168 });
169
170 test('explicit option', () => {
171 const client = new Cloudflare({
172 baseURL: 'https://example.com',
173 apiKey: '144c9defac04969c7bfad8efaa8ea194',
174 apiEmail: 'dev@cloudflare.com',
175 apiToken: 'Sn3lZJTBX6kkg7OdcBUAxOO963GEIyGQqnFTOFYY',
176 userServiceKey: 'My User Service Key',
177 });
178 expect(client.baseURL).toEqual('https://example.com');
179 });
180
181 test('env variable', () => {
182 process.env['CLOUDFLARE_BASE_URL'] = 'https://example.com/from_env';
183 const client = new Cloudflare({
184 apiKey: '144c9defac04969c7bfad8efaa8ea194',
185 apiEmail: 'dev@cloudflare.com',
186 apiToken: 'Sn3lZJTBX6kkg7OdcBUAxOO963GEIyGQqnFTOFYY',
187 userServiceKey: 'My User Service Key',
188 });
189 expect(client.baseURL).toEqual('https://example.com/from_env');
190 });
191
192 test('empty env variable', () => {
193 process.env['CLOUDFLARE_BASE_URL'] = ''; // empty
194 const client = new Cloudflare({
195 apiKey: '144c9defac04969c7bfad8efaa8ea194',
196 apiEmail: 'dev@cloudflare.com',
197 apiToken: 'Sn3lZJTBX6kkg7OdcBUAxOO963GEIyGQqnFTOFYY',
198 userServiceKey: 'My User Service Key',
199 });
200 expect(client.baseURL).toEqual('https://api.cloudflare.com/client/v4');
201 });
202
203 test('blank env variable', () => {
204 process.env['CLOUDFLARE_BASE_URL'] = ' '; // blank
205 const client = new Cloudflare({
206 apiKey: '144c9defac04969c7bfad8efaa8ea194',
207 apiEmail: 'dev@cloudflare.com',
208 apiToken: 'Sn3lZJTBX6kkg7OdcBUAxOO963GEIyGQqnFTOFYY',
209 userServiceKey: 'My User Service Key',
210 });
211 expect(client.baseURL).toEqual('https://api.cloudflare.com/client/v4');
212 });
213 });
214
215 test('maxRetries option is correctly set', () => {
216 const client = new Cloudflare({
217 maxRetries: 4,
218 apiKey: '144c9defac04969c7bfad8efaa8ea194',
219 apiEmail: 'dev@cloudflare.com',
220 apiToken: 'Sn3lZJTBX6kkg7OdcBUAxOO963GEIyGQqnFTOFYY',
221 userServiceKey: 'My User Service Key',
222 });
223 expect(client.maxRetries).toEqual(4);
224
225 // default
226 const client2 = new Cloudflare({
227 apiKey: '144c9defac04969c7bfad8efaa8ea194',
228 apiEmail: 'dev@cloudflare.com',
229 apiToken: 'Sn3lZJTBX6kkg7OdcBUAxOO963GEIyGQqnFTOFYY',
230 userServiceKey: 'My User Service Key',
231 });
232 expect(client2.maxRetries).toEqual(2);
233 });
234
235 test('with environment variable arguments', () => {
236 // set options via env var
237 process.env['CLOUDFLARE_API_KEY'] = '144c9defac04969c7bfad8efaa8ea194';
238 process.env['CLOUDFLARE_EMAIL'] = 'dev@cloudflare.com';
239 process.env['CLOUDFLARE_API_TOKEN'] = 'Sn3lZJTBX6kkg7OdcBUAxOO963GEIyGQqnFTOFYY';
240 const client = new Cloudflare({ userServiceKey: 'My User Service Key' });
241 expect(client.apiKey).toBe('144c9defac04969c7bfad8efaa8ea194');
242 expect(client.apiEmail).toBe('dev@cloudflare.com');
243 expect(client.apiToken).toBe('Sn3lZJTBX6kkg7OdcBUAxOO963GEIyGQqnFTOFYY');
244 expect(client.userServiceKey).toBe('My User Service Key');
245 });
246
247 test('with overriden environment variable arguments', () => {
248 // set options via env var
249 process.env['CLOUDFLARE_API_KEY'] = 'another 144c9defac04969c7bfad8efaa8ea194';
250 process.env['CLOUDFLARE_EMAIL'] = 'another dev@cloudflare.com';
251 process.env['CLOUDFLARE_API_TOKEN'] = 'another Sn3lZJTBX6kkg7OdcBUAxOO963GEIyGQqnFTOFYY';
252 const client = new Cloudflare({
253 apiKey: '144c9defac04969c7bfad8efaa8ea194',
254 apiEmail: 'dev@cloudflare.com',
255 apiToken: 'Sn3lZJTBX6kkg7OdcBUAxOO963GEIyGQqnFTOFYY',
256 userServiceKey: 'My User Service Key',
257 });
258 expect(client.apiKey).toBe('144c9defac04969c7bfad8efaa8ea194');
259 expect(client.apiEmail).toBe('dev@cloudflare.com');
260 expect(client.apiToken).toBe('Sn3lZJTBX6kkg7OdcBUAxOO963GEIyGQqnFTOFYY');
261 expect(client.userServiceKey).toBe('My User Service Key');
262 });
263});
264
265describe('request building', () => {
266 const client = new Cloudflare({
267 apiKey: '144c9defac04969c7bfad8efaa8ea194',
268 apiEmail: 'dev@cloudflare.com',
269 apiToken: 'Sn3lZJTBX6kkg7OdcBUAxOO963GEIyGQqnFTOFYY',
270 userServiceKey: 'My User Service Key',
271 });
272
273 describe('Content-Length', () => {
274 test('handles multi-byte characters', () => {
275 const { req } = client.buildRequest({ path: '/foo', method: 'post', body: { value: '—' } });
276 expect((req.headers as Record<string, string>)['content-length']).toEqual('20');
277 });
278
279 test('handles standard characters', () => {
280 const { req } = client.buildRequest({ path: '/foo', method: 'post', body: { value: 'hello' } });
281 expect((req.headers as Record<string, string>)['content-length']).toEqual('22');
282 });
283 });
284
285 describe('custom headers', () => {
286 test('handles undefined', () => {
287 const { req } = client.buildRequest({
288 path: '/foo',
289 method: 'post',
290 body: { value: 'hello' },
291 headers: { 'X-Foo': 'baz', 'x-foo': 'bar', 'x-Foo': undefined, 'x-baz': 'bam', 'X-Baz': null },
292 });
293 expect((req.headers as Record<string, string>)['x-foo']).toEqual('bar');
294 expect((req.headers as Record<string, string>)['x-Foo']).toEqual(undefined);
295 expect((req.headers as Record<string, string>)['X-Foo']).toEqual(undefined);
296 expect((req.headers as Record<string, string>)['x-baz']).toEqual(undefined);
297 });
298 });
299});
300
301describe('retries', () => {
302 test('retry on timeout', async () => {
303 let count = 0;
304 const testFetch = async (url: RequestInfo, { signal }: RequestInit = {}): Promise<Response> => {
305 if (count++ === 0) {
306 return new Promise(
307 (resolve, reject) => signal?.addEventListener('abort', () => reject(new Error('timed out'))),
308 );
309 }
310 return new Response(JSON.stringify({ a: 1 }), { headers: { 'Content-Type': 'application/json' } });
311 };
312
313 const client = new Cloudflare({
314 apiKey: '144c9defac04969c7bfad8efaa8ea194',
315 apiEmail: 'dev@cloudflare.com',
316 apiToken: 'Sn3lZJTBX6kkg7OdcBUAxOO963GEIyGQqnFTOFYY',
317 userServiceKey: 'My User Service Key',
318 timeout: 10,
319 fetch: testFetch,
320 });
321
322 expect(await client.request({ path: '/foo', method: 'get' })).toEqual({ a: 1 });
323 expect(count).toEqual(2);
324 expect(
325 await client
326 .request({ path: '/foo', method: 'get' })
327 .asResponse()
328 .then((r) => r.text()),
329 ).toEqual(JSON.stringify({ a: 1 }));
330 expect(count).toEqual(3);
331 });
332
333 test('retry on 429 with retry-after', async () => {
334 let count = 0;
335 const testFetch = async (url: RequestInfo, { signal }: RequestInit = {}): Promise<Response> => {
336 if (count++ === 0) {
337 return new Response(undefined, {
338 status: 429,
339 headers: {
340 'Retry-After': '0.1',
341 },
342 });
343 }
344 return new Response(JSON.stringify({ a: 1 }), { headers: { 'Content-Type': 'application/json' } });
345 };
346
347 const client = new Cloudflare({
348 apiKey: '144c9defac04969c7bfad8efaa8ea194',
349 apiEmail: 'dev@cloudflare.com',
350 apiToken: 'Sn3lZJTBX6kkg7OdcBUAxOO963GEIyGQqnFTOFYY',
351 userServiceKey: 'My User Service Key',
352 fetch: testFetch,
353 });
354
355 expect(await client.request({ path: '/foo', method: 'get' })).toEqual({ a: 1 });
356 expect(count).toEqual(2);
357 expect(
358 await client
359 .request({ path: '/foo', method: 'get' })
360 .asResponse()
361 .then((r) => r.text()),
362 ).toEqual(JSON.stringify({ a: 1 }));
363 expect(count).toEqual(3);
364 });
365
366 test('retry on 429 with retry-after-ms', async () => {
367 let count = 0;
368 const testFetch = async (url: RequestInfo, { signal }: RequestInit = {}): Promise<Response> => {
369 if (count++ === 0) {
370 return new Response(undefined, {
371 status: 429,
372 headers: {
373 'Retry-After-Ms': '10',
374 },
375 });
376 }
377 return new Response(JSON.stringify({ a: 1 }), { headers: { 'Content-Type': 'application/json' } });
378 };
379
380 const client = new Cloudflare({
381 apiKey: '144c9defac04969c7bfad8efaa8ea194',
382 apiEmail: 'dev@cloudflare.com',
383 apiToken: 'Sn3lZJTBX6kkg7OdcBUAxOO963GEIyGQqnFTOFYY',
384 userServiceKey: 'My User Service Key',
385 fetch: testFetch,
386 });
387
388 expect(await client.request({ path: '/foo', method: 'get' })).toEqual({ a: 1 });
389 expect(count).toEqual(2);
390 expect(
391 await client
392 .request({ path: '/foo', method: 'get' })
393 .asResponse()
394 .then((r) => r.text()),
395 ).toEqual(JSON.stringify({ a: 1 }));
396 expect(count).toEqual(3);
397 });
398});
399