cloudflare/cloudflare-typescript

Public

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

CodeCommitsIssuesPull requestsActionsInsightsSecurity
v3.0.0-beta.11

Branches

Tags

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

Clone

HTTPS

Download ZIP

tests/index.test.ts

351lines · modecode

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