diff --git a/.gitignore b/.gitignore index 368fbf5..2518a0b 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ node_modules npm-debug.log .DS_Store /polyfill/index.js +coverage diff --git a/src/index.mjs b/src/index.mjs index 96066f6..84c7f43 100644 --- a/src/index.mjs +++ b/src/index.mjs @@ -1,37 +1,22 @@ +import response from './lib/response'; + +const regex = /^(.*?):[^\S\n]*([\s\S]*?)$/gm; + export default function(url, options) { options = options || {}; return new Promise( (resolve, reject) => { const request = new XMLHttpRequest(); - const keys = []; - const all = []; - const headers = {}; - - const response = () => ({ - ok: (request.status/100|0) == 2, // 200-299 - statusText: request.statusText, - status: request.status, - url: request.responseURL, - text: () => Promise.resolve(request.responseText), - json: () => Promise.resolve(request.responseText).then(JSON.parse), - blob: () => Promise.resolve(new Blob([request.response])), - clone: response, - headers: { - keys: () => keys, - entries: () => all, - get: n => headers[n.toLowerCase()], - has: n => n.toLowerCase() in headers - } - }); request.open(options.method || 'get', url, true); request.onload = () => { - request.getAllResponseHeaders().replace(/^(.*?):[^\S\n]*([\s\S]*?)$/gm, (m, key, value) => { - keys.push(key = key.toLowerCase()); + const all = [], keys = [], raw = {}; + request.getAllResponseHeaders().replace(regex, (m, key, value) => { all.push([key, value]); - headers[key] = headers[key] ? `${headers[key]},${value}` : value; + keys.push(key = key.toLowerCase()); + raw[key] = raw[key] ? `${raw[key]},${value}` : value; }); - resolve(response()); + resolve(response(request, all, keys, raw)); }; request.onerror = reject; diff --git a/src/lib/response.mjs b/src/lib/response.mjs new file mode 100644 index 0000000..4c2a548 --- /dev/null +++ b/src/lib/response.mjs @@ -0,0 +1,18 @@ +export default function response (request, all, keys, raw) { + return { + ok: (request.status/100|0) == 2, // 200-299 + statusText: request.statusText, + status: request.status, + url: request.responseURL, + text: () => Promise.resolve(request.responseText), + json: () => Promise.resolve(request.responseText).then(JSON.parse), + blob: () => Promise.resolve(new Blob([request.response])), + clone: () => response(request, all, keys, raw), + headers: { + keys: () => keys, + entries: () => all, + get: n => raw[n.toLowerCase()], + has: n => n.toLowerCase() in raw + } + }; +} diff --git a/test/lib/response.js b/test/lib/response.js new file mode 100644 index 0000000..24cd324 --- /dev/null +++ b/test/lib/response.js @@ -0,0 +1,32 @@ +import response from '../../src/lib/response.mjs'; + +describe('response()', () => { + const raw = { 'x-foo': 'foo', 'x-bar': 'bar' }; + const keys = Object.keys(raw); + const all = Object.entries(raw); + const resp = response({}, all, keys, raw); + + it('returns text()', () => response({ responseText: 'A passing test.' }, [], [], {}) + .text() + .then((text) => expect(text).toBe('A passing test.')) + ); + + it('returns blob()', () => response({ response: 'A passing test.' }) + .blob() + .then((text) => expect(text.toString()).toBe(new Blob(['A passing test.']).toString())) + ); + + it('returns headers', () => { + expect(resp.headers.entries()).toEqual(all); + }); + + it('returns header keys', () => { + expect(resp.headers.keys()).toEqual(['x-foo', 'x-bar']); + }); + + it('returns headers has', () => { + expect(resp.headers.has('x-foo')).toBe(true); + expect(resp.headers.has('x-bar')).toBe(true); + expect(resp.headers.has('x-baz')).toBe(false); + }); +});