UNPKG

11.7 kBJavaScriptView Raw
1'use strict';
2
3const assert = require('assert');
4const frisby = require('../src/frisby');
5const mocks = require('./fixtures/http_mocks');
6
7const testHost = 'http://api.example.com';
8
9describe('Frisby', function() {
10
11 it('Test expectStatus works as... well, expected', function(doneFn) {
12 mocks.use(['getUser1']);
13
14 frisby.fetch(testHost + '/users/1')
15 .expect('status', 200)
16 .done(doneFn);
17 });
18
19 it('should handle a 204 response with no content', function(doneFn) {
20 mocks.use(['noContent']);
21
22 frisby.fetch(testHost + '/contents/none')
23 .expect('status', 204)
24 .done(doneFn);
25 });
26
27 it('should handle a 204 response with no content and then()', function(doneFn) {
28 mocks.use(['noContent']);
29
30 frisby.fetch(testHost + '/contents/none')
31 .expect('status', 204)
32 .then((res) => {
33 expect(res.body).toEqual('');
34 })
35 .done(doneFn);
36 });
37
38 it('should support JSON natively', function (doneFn) {
39 mocks.use(['createUser2']);
40
41 frisby.post(testHost + '/users', {
42 body: {
43 email: 'user@example.com',
44 password: 'password'
45 }
46 })
47 .expect('status', 201)
48 .done(doneFn);
49 });
50
51 it('should allow custom expect handlers to be registered and used', function (doneFn) {
52 mocks.use(['getUser1']);
53
54 // Add our custom expect handler
55 frisby.addExpectHandler('customUserResponse', function(response) {
56 let json = response.json;
57 expect(json.id).toBe(1);
58 expect(json.email).toBe('joe.schmoe@example.com');
59 });
60
61 // Use it!
62 frisby.get(testHost + '/users/1')
63 .expect('customUserResponse')
64 .done(doneFn);
65
66 // Remove said custom handler
67 frisby.removeExpectHandler('customUserResponse');
68 });
69
70 it('should allow custom expect functions to be used without registering them', function (doneFn) {
71 mocks.use(['getUser1']);
72
73 frisby.get(testHost + '/users/1')
74 .then(function (res) {
75 let json = res.json;
76
77 expect(json.id).toBe(1);
78 expect(json.email).toBe('joe.schmoe@example.com');
79 })
80 .done(doneFn);
81 });
82
83 it('should allow POST with empty request body', function (doneFn) {
84 mocks.use(['postError']);
85
86 frisby.post(testHost + '/error')
87 .expect('status', 400)
88 .expect('json', {
89 result: 'error'
90 })
91 .done(doneFn);
92 });
93
94 it('should allow DELETE with request body', function (doneFn) {
95 mocks.use(['deleteUsers']);
96
97 frisby.delete(testHost + '/users', {
98 body: {
99 data: [
100 {id: 2},
101 {id: 3}
102 ]
103 }
104 })
105 .expect('status', 200)
106 .expect('json', {
107 data: [
108 {id: 2},
109 {id: 3}
110 ]
111 })
112 .done(doneFn);
113 });
114
115 it('should allow DELETE with text request body', function (doneFn) {
116 mocks.use(['deleteContent']);
117
118 frisby.delete(testHost + '/contents/1', {
119 headers: {
120 'Content-Type': 'application/x-www-form-urlencoded'
121 },
122 body: 'something something'
123 })
124 .expect('status', 200)
125 .expect('bodyContains', 'something something')
126 .done(doneFn);
127 });
128
129 it('should call Frisby spec delete()', function(doneFn) {
130 mocks.use(['deleteUser1']);
131
132 frisby.setup({ request: { inspectOnFailure: false } })
133 .delete(testHost + '/users/1')
134 .expect('status', 204)
135 .done(doneFn);
136 });
137
138 it('should use new responseBody when returning another Frisby spec from then()', function (doneFn) {
139 mocks.use(['getUser1', 'getUser2WithDelay']);
140
141 frisby.get(testHost + '/users/1')
142 .expect('json', { id: 1 })
143 .then(frisby.get(testHost + '/users/2')
144 .expect('json', { id: 2 })
145 )
146 .then(function (res) {
147 expect(res.json.id).toBe(2);
148 })
149 .done(doneFn);
150 });
151
152 it('should use new responseBody when returning another Frisby spec inside then()', function (doneFn) {
153 mocks.use(['getUser1', 'getUser2WithDelay']);
154
155 frisby.get(testHost + '/users/1')
156 .expect('json', { id: 1 })
157 .then(function () {
158 return frisby.get(testHost + '/users/2')
159 .expect('json', { id: 2 });
160 })
161 .then(function (res) {
162 expect(res.json.id).toBe(2);
163 })
164 .done(doneFn);
165 });
166
167 it('should use new responseBody when returning another Frisby spec inside then() with multiple specs chained', function (doneFn) {
168 mocks.use(['getUser1', 'getUser2WithDelay']);
169
170 frisby.get(testHost + '/users/1')
171 .expect('json', { id: 1 })
172 .then(function () {
173 mocks.use(['getUser1WithDelay']);
174
175 return frisby.get(testHost + '/users/1')
176 .expect('json', { id: 1 });
177 })
178 .then(function (res) {
179 expect(res.json.id).toBe(1);
180 })
181 .then(function () {
182 return frisby.get(testHost + '/users/2')
183 .expect('json', { id: 2 });
184 })
185 .then(function (res) {
186 expect(res.json.id).toBe(2);
187 })
188 .done(doneFn);
189 });
190
191 it('use function allows modifications for current Frisby spec', function(doneFn) {
192 mocks.use(['getUser1WithAuth']);
193
194 let withAuthHeader = function (spec) {
195 spec.setup({
196 request: {
197 headers: { 'authorization': 'Basic Auth' }
198 }
199 });
200 };
201
202 frisby.use(withAuthHeader)
203 .fetch(testHost + '/users/1/auth')
204 .expect('status', 200)
205 .done(doneFn);
206 });
207
208 it('frisby setup merges options with previous options already set', function(doneFn) {
209 mocks.use(['twoHeaders']);
210
211 // Should merge headers so both are present
212 frisby.setup({
213 request: {
214 headers: { 'One': 'one' }
215 }
216 })
217 .setup({
218 request: {
219 headers: { 'Two': 'two' }
220 }
221 })
222 .fetch(testHost + '/two-headers')
223 .expect('status', 200)
224 .done(doneFn);
225 });
226
227 it('frisby setup second parameter replaces setup options instead of merging them', function(doneFn) {
228 mocks.use(['getUser1WithAuth']);
229
230 // Second call uses 'true' as 2nd argument, so it should overwrite options
231 frisby.setup({
232 request: {
233 headers: { 'authorizationX': 'Basic AuthX' }
234 }
235 })
236 .setup({
237 request: {
238 headers: { 'authorization': 'Basic Auth' }
239 }
240 }, true)
241 .fetch(testHost + '/users/1/auth')
242 .expect('status', 200)
243 .done(doneFn);
244 });
245
246 it('frisby timeout is configurable per spec', function(doneFn) {
247 mocks.use(['timeout']);
248
249 // Test timeout by catching timeout error and running assertions on it
250 frisby.timeout(10)
251 .use(function (spec) {
252 expect(spec.timeout()).toBe(10);
253 })
254 .fetch(testHost + '/timeout')
255 .catch(function (err) {
256 expect(err.name).toBe('FetchError');
257 })
258 .done(doneFn);
259 });
260
261 it('should allow custom headers to be set for future requests', function(doneFn) {
262 mocks.use(['setCookie', 'requireCookie']);
263
264 // Call path only
265 frisby.get(testHost + '/cookies/set')
266 .expect('status', 200)
267 .expect('header', 'Set-Cookie')
268 .then((res) => {
269 let cookie1 = res.headers.get('Set-Cookie');
270
271 return frisby.get(testHost + '/cookies/check', {
272 headers: {
273 'Cookie': cookie1
274 }
275 })
276 .expect('status', 200);
277 })
278 .done(doneFn);
279 });
280
281 it('baseUrl sets global baseUrl to be used with all relative URLs', function(doneFn) {
282 mocks.use(['getUser1']);
283
284 // Set baseUrl
285 frisby.baseUrl(testHost);
286
287 // Call path only
288 frisby.fetch('/users/1')
289 .expect('status', 200)
290 .done(doneFn);
291 });
292
293 it('should accept urls which include multibyte characters', function(doneFn) {
294 mocks.use(['multibyte']);
295
296 frisby.fetch(testHost + '/こんにちは')
297 .expect('status', 200)
298 .done(doneFn);
299 });
300
301 it('should auto encode URIs that do not use fetch() with the urlEncode: false option set', function(doneFn) {
302 mocks.use(['urlEncoded']);
303
304 frisby.get(testHost + '/ftp//etc/os-release%00.md')
305 .expect('status', 200)
306 .done(doneFn);
307 });
308
309 it('should not encode URIs that use fetch() with the urlEncode: false option set', function(doneFn) {
310 mocks.use(['notUrlEncoded']);
311
312 frisby.fetch(testHost + '/ftp//etc/os-release%00.md', {}, { urlEncode: false })
313 .expect('status', 200)
314 .done(doneFn);
315 });
316
317 it('should throw an error and a deprecation warning if you try to call v0.x frisby.create()', function() {
318 assert.throws(function(err) {
319 // OLD style of Frisby - will not work (throws error)
320 frisby.create('this will surely throw an error!')
321 .expectStatus(200)
322 .toss();
323 }, /ERROR/i);
324 });
325
326 it('should be able to extend FrisbySpec with a custom class', function() {
327 let OriginalFrisbySpec = frisby.FrisbySpec;
328
329 class FrisbySpecExtended extends OriginalFrisbySpec {
330 customMethod() {
331 return true;
332 }
333 }
334
335 // Have frisby use our class
336 frisby.FrisbySpec = FrisbySpecExtended;
337
338 let actual = frisby.fromJSON({}).customMethod();
339 let expected = true;
340
341 assert.equal(actual, expected);
342
343 // Restore original FrisbySpec class
344 frisby.FrisbySpec = OriginalFrisbySpec;
345 });
346
347 it('should use new responseBody when returning another Frisby spec inside catch()', function (doneFn) {
348 mocks.use(['getUser1', 'getUser2WithDelay']);
349
350 frisby.get(testHost + '/users/10')
351 .expect('json', { id: 10 })
352 .then(function (res) {
353 fail('this function will never be called.');
354 })
355 .catch(function (err) {
356 expect(err.name).toContain('FetchError');
357
358 return frisby.setup({ request: { inspectOnFailure: false } })
359 .get(testHost + '/users/1')
360 .expect('json', { id: 10 });
361 })
362 .then(function (res) {
363 fail('this function will never be called.');
364 })
365 .catch(function (err) {
366 expect(err.name).toContain('AssertionError');
367
368 return frisby.get(testHost + '/users/2')
369 .expect('json', { id: 2 });
370 })
371 .then(function (res) {
372 expect(res.json.id).toBe(2);
373 })
374 .done(doneFn);
375 });
376
377 it('should output invalid body and reason in error message', function(doneFn) {
378 mocks.use(['invalidJSON']);
379
380 frisby.setup({ request: { inspectOnFailure: false } })
381 .get(testHost + '/res/invalid')
382 .then(function (res) {
383 fail('this function will never be called.');
384 })
385 .catch(function (err) {
386 expect(err.message).toMatch(/^Invalid json response /);
387 expect(err.message).toMatch(/body: '.*'/);
388 expect(err.message).toMatch(/reason: '.+'/);
389 })
390 .done(doneFn);
391 });
392
393 it('receive response body as raw buffer', function(doneFn) {
394 mocks.use(['getUser1']);
395
396 frisby.setup({ request: { rawBody: true } })
397 .get(testHost + '/users/1')
398 .expect('status', 200)
399 .expect('header', 'Content-Type', /json/)
400 .then(res => {
401 expect(res.json).toBeUndefined();
402 expect(res.body).not.toBeInstanceOf(String);
403 return String.fromCharCode.apply(null, new Uint8Array(res.body));
404 })
405 .then(text => {
406 expect(text).toContain('joe.schmoe@example.com');
407 })
408 .done(doneFn);
409 });
410
411 it('should support http method OPTIONS', function(doneFn) {
412 mocks.use(['options']);
413
414 frisby.options(testHost + '/')
415 .expect('status', 204)
416 .expect('header', 'Access-Control-Allow-Methods', /GET/)
417 .done(doneFn);
418 });
419
420 it('Test FrisbySpec finally', function(doneFn) {
421 mocks.use(['getUser1']);
422
423 frisby.fetch(testHost + '/users/1')
424 .expect('status', 200)
425 .finally(() => {
426 })
427 .done(doneFn);
428 });
429});