From 552ea46c436c63a63bf588054f98824b68c3b7e7 Mon Sep 17 00:00:00 2001 From: Bryan Housel Date: Fri, 26 Apr 2019 22:25:57 -0400 Subject: [PATCH] Wrap the fake-fetch methods with sinon.fakeServer-like interface This mimics `respondWith` and `respond` to keep the tests mostly similar between `FakeFetch` and `sinon.fakeServer` Major difference is that all the fakeServer tests which were sync are now async and this is probably unavoidable. --- test/spec/spec_helpers.js | 133 +++++++++++++++++++++++++++++--------- 1 file changed, 101 insertions(+), 32 deletions(-) diff --git a/test/spec/spec_helpers.js b/test/spec/spec_helpers.js index aaf859894..26769ef52 100644 --- a/test/spec/spec_helpers.js +++ b/test/spec/spec_helpers.js @@ -57,41 +57,110 @@ Array.from = function(what) { // see https://github.com/sinonjs/nise/issues/7 // // None of the alternatives really worked well, -// so I'm just pasting the `fake-fetch` methods here. +// so I'm just wrapping the `fake-fetch` methods in here. // - https://github.com/msn0/fake-fetch // - https://github.com/wheresrhys/fetch-mock -window.fakeFetch = { - install: function () { - sinon.stub(window, 'fetch'); - }, - restore: function () { - window.fetch.restore(); - }, - getUrl: function () { - return window.fetch.firstCall.args[0]; - }, - getOptions: function () { - return window.fetch.firstCall.args[1] || {}; - }, - getMethod: function () { - return this.getOptions().method || 'get'; - }, - getBody: function () { - return this.getOptions().body || ''; - }, - getRequestHeaders: function () { - return this.getOptions().headers || {}; - }, - respondWith: function (data, options) { - return window.fetch.callsFake(function() { - return Promise.resolve(new Response(data, options)); +window.fakeFetch = function() { + var _responders = []; + var _requests = []; + + function fake(url, options) { + options = Object.assign({ method: 'get', headers: {}, body: '' }, options); + return new Promise(function(resolve, reject) { + _requests.push({ + url: url, options: options, resolve: resolve, reject: reject + }); }); } -}; -Object.defineProperty( - window.fakeFetch, 'called', { - get: function() { return !!window.fetch.firstCall; } - } -); + return { + requests: function() { + return _requests; + }, + + create: function () { + _responders = []; + _requests = []; + sinon.stub(window, 'fetch').callsFake(fake); + return this; + }, + + restore: function () { + window.fetch.restore(); + }, + + getUrl: function () { + return window.fetch.firstCall.args[0]; + }, + + getOptions: function () { + return window.fetch.firstCall.args[1] || {}; + }, + + getMethod: function () { + return this.getOptions().method || 'get'; + }, + + getBody: function () { + return this.getOptions().body || ''; + }, + + getRequestHeaders: function () { + return this.getOptions().headers || {}; + }, + + respondWith: function(method, match, response) { + var status = 200; + var headers = { 'Content-Type': 'text/html' }; + var body = 'OK'; + + if (typeof response === 'string') { + body = response; + } else if (Array.isArray(response) && response.length === 3) { + status = response[0]; + headers = Object.assign(headers, response[1] || {}); + body = response[2]; + } + + headers['Content-Length'] = body.length; + var data = new Blob([body], { type: headers['Content-Type'] }); + var options = { status: status, headers: headers }; + + _responders.push({ + method: method, + match: match, + respond: function() { return new Response(data, options); } + }); + }, + + respond: function () { + _requests.forEach(function(request) { + var didMatch = false; + for (var i = 0; i < _responders.length; i++) { + var responder = _responders[i]; + if (responder.method.toLowerCase() !== request.options.method.toLowerCase()) { + continue; // skip if method doesn't match (get/post) + } + + if (responder.match.constructor.name === 'RegExp') { + didMatch = responder.match.test(request.url); + } else if (typeof responder.match === 'string') { + didMatch = (request.url.indexOf(responder.match) !== -1); + } + + if (didMatch) { + request.resolve(responder.respond()); + break; + } + } + if (!didMatch) { + request.reject(new Response( + new Blob(['404'], { type: 'text/plain' }), + { status: 404, statusText: 'Not Found' } + )); + } + }); + } + }; +};