UNPKG

14.3 kBJavaScriptView Raw
1"use strict";
2Object.defineProperty(exports, "__esModule", { value: true });
3const nock = require("nock");
4const querystring = require("querystring");
5const http_1 = require("./http");
6nock.disableNetConnect();
7let api;
8beforeEach(() => {
9 api = nock('https://api.jdxcode.com');
10});
11afterEach(() => {
12 api.done();
13});
14afterEach(() => {
15 nock.cleanAll();
16});
17describe('HTTP.get()', () => {
18 test('makes a GET request', async () => {
19 api.get('/').reply(200, { message: 'ok' });
20 let { body } = await http_1.HTTP.get('https://api.jdxcode.com');
21 expect(body).toEqual({ message: 'ok' });
22 });
23 test('makes a GET request', async () => {
24 api.get('/').reply(200, { message: 'ok' }, {
25 'content-type': 'application/json; charset=UTF-8',
26 });
27 let { body } = await http_1.HTTP.get('https://api.jdxcode.com');
28 expect(body).toEqual({ message: 'ok' });
29 });
30 test('gets headers', async () => {
31 api.get('/').reply(200, { message: 'ok' }, { myheader: 'ok' });
32 let { body, headers } = await http_1.HTTP.get('https://api.jdxcode.com');
33 expect(body).toEqual({ message: 'ok' });
34 expect(headers).toMatchObject({ myheader: 'ok' });
35 });
36 test('can build a new HTTP with defaults', async () => {
37 const MyHTTP = http_1.HTTP.create({ host: 'api.jdxcode.com' });
38 api.get('/').reply(200, { message: 'ok' });
39 let { body } = await MyHTTP.get('/');
40 expect(body).toEqual({ message: 'ok' });
41 });
42 test('makes a request to a port', async () => {
43 api = nock('https://api.jdxcode.com:3000');
44 api.get('/').reply(200, { message: 'ok' });
45 let { body } = await http_1.HTTP.get('https://api.jdxcode.com:3000');
46 expect(body).toEqual({ message: 'ok' });
47 });
48 test('allows specifying the port', async () => {
49 api = nock('https://api.jdxcode.com:3000');
50 api.get('/').reply(200, { message: 'ok' });
51 let { body } = await http_1.HTTP.get('https://api.jdxcode.com', { port: 3000 });
52 expect(body).toEqual({ message: 'ok' });
53 });
54 test('makes a http GET request', async () => {
55 api = nock('http://api.jdxcode.com');
56 api.get('/').reply(200, { message: 'ok' });
57 let { body } = await http_1.HTTP.get('http://api.jdxcode.com');
58 expect(body).toEqual({ message: 'ok' });
59 });
60 test('can set default user agent', async () => {
61 http_1.HTTP.defaults.headers = { 'user-agent': 'mynewuseragent' };
62 api
63 .matchHeader('user-agent', `mynewuseragent`)
64 .get('/')
65 .reply(200, { message: 'ok' });
66 let { body } = await http_1.HTTP.get('https://api.jdxcode.com/');
67 expect(body).toEqual({ message: 'ok' });
68 delete http_1.HTTP.defaults.headers['user-agent'];
69 });
70 test('can set user agent as a global', async () => {
71 global['http-call'] = { userAgent: 'mynewuseragent' };
72 api
73 .matchHeader('user-agent', `mynewuseragent`)
74 .get('/')
75 .reply(200, { message: 'ok' });
76 let { body } = await http_1.HTTP.get('https://api.jdxcode.com/');
77 expect(body).toEqual({ message: 'ok' });
78 delete global['http-call'];
79 });
80 test('sets user-agent header', async () => {
81 api
82 .matchHeader('user-agent', `http-call/${require('../package.json').version} node-${process.version}`)
83 .get('/')
84 .reply(200, { message: 'ok' });
85 await http_1.HTTP.get('https://api.jdxcode.com');
86 });
87 test('sets custom headers', async () => {
88 api
89 .matchHeader('foo', 'bar')
90 .get('/')
91 .reply(200);
92 let headers = { foo: 'bar' };
93 await http_1.HTTP.get('https://api.jdxcode.com', { headers });
94 });
95 test('does not fail on undefined header', async () => {
96 api.get('/').reply(200);
97 let headers = { foo: undefined };
98 await http_1.HTTP.get('https://api.jdxcode.com', { headers });
99 });
100 describe('wait mocked out', () => {
101 let wait = http_1.HTTP.prototype._wait;
102 beforeAll(() => {
103 http_1.HTTP.prototype._wait = jest.fn();
104 });
105 afterAll(() => {
106 http_1.HTTP.prototype._wait = wait;
107 });
108 test('retries then succeeds', async () => {
109 api.get('/').replyWithError({ message: 'timed out 1', code: 'ETIMEDOUT' });
110 api.get('/').replyWithError({ message: 'timed out 2', code: 'ETIMEDOUT' });
111 api.get('/').replyWithError({ message: 'timed out 3', code: 'ETIMEDOUT' });
112 api.get('/').replyWithError({ message: 'timed out 4', code: 'ETIMEDOUT' });
113 api.get('/').reply(200, { message: 'foo' });
114 let { body } = await http_1.HTTP.get('https://api.jdxcode.com');
115 expect(body).toEqual({ message: 'foo' });
116 });
117 test('retries 5 times on ETIMEDOUT', async () => {
118 expect.assertions(1);
119 api.get('/').replyWithError({ message: 'timed out 1', code: 'ETIMEDOUT' });
120 api.get('/').replyWithError({ message: 'timed out 2', code: 'ETIMEDOUT' });
121 api.get('/').replyWithError({ message: 'timed out 3', code: 'ETIMEDOUT' });
122 api.get('/').replyWithError({ message: 'timed out 4', code: 'ETIMEDOUT' });
123 api.get('/').replyWithError({ message: 'timed out 5', code: 'ETIMEDOUT' });
124 api.get('/').replyWithError({ message: 'timed out 6', code: 'ETIMEDOUT' });
125 try {
126 await http_1.HTTP.get('https://api.jdxcode.com');
127 }
128 catch (err) {
129 expect(err.message).toEqual('timed out 6');
130 }
131 });
132 });
133 test('retries on ENOTFOUND', async () => {
134 api.get('/').replyWithError({ message: 'not found', code: 'ENOTFOUND' });
135 api.get('/').reply(200, { message: 'foo' });
136 let { body } = await http_1.HTTP.get('https://api.jdxcode.com');
137 expect(body).toMatchObject({ message: 'foo' });
138 });
139 test('errors on EFOOBAR', async () => {
140 expect.assertions(1);
141 api.get('/').replyWithError({ message: 'oom', code: 'OUT_OF_MEM' });
142 try {
143 await http_1.HTTP.get('https://api.jdxcode.com');
144 }
145 catch (err) {
146 expect(err.message).toEqual('oom');
147 }
148 });
149 test('displays 404 error', async () => {
150 expect.assertions(2);
151 api.get('/').reply(404, 'oops! not found');
152 try {
153 await http_1.HTTP.get('https://api.jdxcode.com');
154 }
155 catch (err) {
156 expect(err.statusCode).toEqual(404);
157 expect(err.message).toEqual(`HTTP Error 404 for GET https://api.jdxcode.com:443/
158oops! not found`);
159 }
160 });
161 test('displays error message', async () => {
162 expect.assertions(3);
163 api.get('/').reply(404, { message: 'uh oh', otherinfo: [1, 2, 3] });
164 try {
165 await http_1.HTTP.get('https://api.jdxcode.com');
166 }
167 catch (err) {
168 expect(err.statusCode).toEqual(404);
169 expect(err.message).toEqual(`HTTP Error 404 for GET https://api.jdxcode.com:443/
170uh oh`);
171 expect(err.body).toMatchObject({ otherinfo: [1, 2, 3] });
172 }
173 });
174 test('displays object error', async () => {
175 expect.assertions(3);
176 api.get('/').reply(404, { otherinfo: [1, 2, 3] });
177 try {
178 await http_1.HTTP.get('https://api.jdxcode.com');
179 }
180 catch (err) {
181 expect(err.statusCode).toEqual(404);
182 expect(err.message).toEqual(`HTTP Error 404 for GET https://api.jdxcode.com:443/
183{ otherinfo: [ 1, 2, 3 ] }`);
184 expect(err.body).toMatchObject({ otherinfo: [1, 2, 3] });
185 }
186 });
187 test('follows redirect', async () => {
188 api.get('/foo1').reply(302, null, { Location: 'https://api.jdxcode.com/foo2' });
189 api.get('/foo2').reply(302, null, { Location: 'https://api.jdxcode.com/foo3' });
190 api.get('/foo3').reply(200, { success: true });
191 await http_1.HTTP.get('https://api.jdxcode.com/foo1');
192 });
193 test('follows redirect only 10 times', async () => {
194 api.get('/foo1').reply(302, null, { Location: 'https://api.jdxcode.com/foo2' });
195 api.get('/foo2').reply(302, null, { Location: 'https://api.jdxcode.com/foo3' });
196 api.get('/foo3').reply(302, null, { Location: 'https://api.jdxcode.com/foo4' });
197 api.get('/foo4').reply(302, null, { Location: 'https://api.jdxcode.com/foo5' });
198 api.get('/foo5').reply(302, null, { Location: 'https://api.jdxcode.com/foo6' });
199 api.get('/foo6').reply(302, null, { Location: 'https://api.jdxcode.com/foo7' });
200 api.get('/foo7').reply(302, null, { Location: 'https://api.jdxcode.com/foo8' });
201 api.get('/foo8').reply(302, null, { Location: 'https://api.jdxcode.com/foo9' });
202 api.get('/foo9').reply(302, null, { Location: 'https://api.jdxcode.com/foo10' });
203 api.get('/foo10').reply(302, null, { Location: 'https://api.jdxcode.com/foo11' });
204 api.get('/foo11').reply(302, null, { Location: 'https://api.jdxcode.com/foo12' });
205 expect.assertions(1);
206 try {
207 await http_1.HTTP.get('https://api.jdxcode.com/foo1');
208 }
209 catch (err) {
210 expect(err.message).toEqual('Redirect loop at https://api.jdxcode.com:443/foo11');
211 }
212 });
213});
214describe('HTTP.post()', () => {
215 test('makes a POST request', async () => {
216 api.post('/', { foo: 'bar' }).reply(200, { message: 'ok' });
217 let { body } = await http_1.HTTP.post('https://api.jdxcode.com', { body: { foo: 'bar' } });
218 expect(body).toEqual({ message: 'ok' });
219 });
220 test('does not include a body if no body is passed in', async () => {
221 api.post('/').reply(200, { message: 'ok' });
222 let { body } = await http_1.HTTP.post('https://api.jdxcode.com');
223 expect(body).toEqual({ message: 'ok' });
224 });
225 test('faithfully passes custom-encoded content-types', async () => {
226 let apiEncoded = nock('https://api.jdxcode.com', {
227 reqheaders: {
228 'Content-Type': 'application/x-www-form-urlencoded',
229 },
230 });
231 let body = {
232 karate: 'chop',
233 judo: 'throw',
234 taewkondo: 'kick',
235 jujitsu: 'strangle',
236 };
237 let options = {
238 headers: {
239 'Content-Type': 'application/x-www-form-urlencoded',
240 },
241 body: querystring.stringify(body),
242 };
243 apiEncoded.post('/', querystring.stringify(body)).reply(200, { message: 'ok' });
244 let rsp = await http_1.HTTP.post('https://api.jdxcode.com/', options);
245 expect(rsp.body).toEqual({ message: 'ok' });
246 });
247});
248describe('HTTP.parseBody()', () => {
249 let body;
250 let http;
251 beforeEach(() => {
252 body = {
253 karate: 'chop',
254 judo: 'throw',
255 taewkondo: 'kick',
256 jujitsu: 'strangle',
257 };
258 http = new http_1.HTTP('www.duckduckgo.com', { body });
259 });
260 it('sets the Content-Length', () => {
261 expect(http.options.headers['Content-Length']).toEqual(Buffer.byteLength(JSON.stringify(body)).toString());
262 });
263 it('sets the Content-Type to JSON when Content-Type is unspecified', () => {
264 expect(http.options.headers['content-type']).toEqual('application/json');
265 });
266 it('does not set the Content Type if it already exists', () => {
267 let options = {
268 headers: {
269 'Content-Type': 'application/x-www-form-urlencoded',
270 },
271 body: querystring.stringify(body),
272 };
273 http = new http_1.HTTP('www.duckduckgo.com', options);
274 expect(http.options.headers['content-type']).toEqual('application/x-www-form-urlencoded');
275 });
276 it('resets the value for http.body object', () => {
277 expect(http.body).toBe(undefined);
278 });
279 it('sets the requestBody to the body contents', () => {
280 expect(http.options.body).toBe(JSON.stringify(body));
281 });
282 describe('with next-range header', () => {
283 beforeEach(() => {
284 api
285 .get('/')
286 .reply(206, [1, 2, 3], {
287 'next-range': '4',
288 })
289 .get('/')
290 // .matchHeader('range', '4')
291 .reply(206, [4, 5, 6], {
292 'next-range': '7',
293 })
294 .get('/')
295 // .matchHeader('range', '7')
296 .reply(206, [7, 8, 9]);
297 });
298 test('gets next body when next-range is set', async () => {
299 let { body } = await http_1.HTTP.get('https://api.jdxcode.com');
300 expect(body).toEqual([1, 2, 3, 4, 5, 6, 7, 8, 9]);
301 });
302 });
303});
304describe('HTTP.put()', () => {
305 test('makes a PUT request', async () => {
306 api.put('/', { foo: 'bar' }).reply(200, { message: 'ok' });
307 let { body } = await http_1.HTTP.put('https://api.jdxcode.com', { body: { foo: 'bar' } });
308 expect(body).toEqual({ message: 'ok' });
309 });
310});
311describe('HTTP.patch()', () => {
312 test('makes a PATCH request', async () => {
313 api.patch('/', { foo: 'bar' }).reply(200, { message: 'ok' });
314 let { body } = await http_1.HTTP.patch('https://api.jdxcode.com', { body: { foo: 'bar' } });
315 expect(body).toEqual({ message: 'ok' });
316 });
317});
318describe('HTTP.delete()', () => {
319 test('makes a DELETE request', async () => {
320 api.delete('/', { foo: 'bar' }).reply(200, { message: 'ok' });
321 let { body } = await http_1.HTTP.delete('https://api.jdxcode.com', { body: { foo: 'bar' } });
322 expect(body).toEqual({ message: 'ok' });
323 });
324});
325describe('HTTP.stream()', () => {
326 test('streams a response', async (done) => {
327 api = nock('http://api.jdxcode.com');
328 api.get('/').reply(200, { message: 'ok' });
329 let { response } = await http_1.HTTP.stream('http://api.jdxcode.com');
330 response.setEncoding('utf8');
331 response.on('data', data => expect(data).toEqual('{"message":"ok"}'));
332 response.on('end', done);
333 });
334});