const makeServiceWorkerEnv = require('service-worker-mock'); global.fetch = require('node-fetch'); jest.mock('node-fetch') global.fetch.mockImplementation((url, init) => { const response = new Response( new Blob( [JSON.stringify({ test: "success" })], {type: "application/json"} ), { status: 200, statusText: "OK", headers: { 'ETag': 'TestingETagHeader' }, url: url }); return Promise.resolve(response); }); /* * we need a Promise.any() polyfill * so here it is * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/any * * TODO: remove once Promise.any() is implemented broadly */ if (typeof Promise.any === 'undefined') { Promise.any = async (promises) => { // Promise.all() is the polar opposite of Promise.any() // in that it returns as soon as there is a first rejection // but without it, it returns an array of resolved results return Promise.all( promises.map(p => { return new Promise((resolve, reject) => // swap reject and resolve, so that we can use Promise.all() // and get the result we need Promise.resolve(p).then(reject, resolve) ); }) // now, swap errors and values back ).then( err => Promise.reject(err), val => Promise.resolve(val) ); }; } describe("plugin: any-of", () => { beforeEach(() => { Object.assign(global, makeServiceWorkerEnv()); jest.resetModules(); global.LibResilientPluginConstructors = new Map() LR = { log: (component, ...items)=>{ console.debug(component + ' :: ', ...items) } } require("../../../plugins/fetch/index.js"); init = { name: 'any-of', uses: [ LibResilientPluginConstructors.get('fetch')(LR), { name: 'reject-all', description: 'Rejects all', version: '0.0.1', fetch: url=>Promise.reject('Reject All!') } ] } self.log = function(component, ...items) { console.debug(component + ' :: ', ...items) } }) test("it should register in LibResilientPluginConstructors", () => { require("../../../plugins/any-of/index.js"); expect(LibResilientPluginConstructors.get('any-of')(LR, init).name).toEqual('any-of'); }); test("it should throw an error when there aren't any wrapped plugins configured", async () => { require("../../../plugins/any-of/index.js"); init = { name: 'any-of', uses: [] } expect.assertions(2); try { await LibResilientPluginConstructors.get('any-of')(LR, init).fetch('https://resilient.is/test.json') } catch (e) { expect(e).toBeInstanceOf(Error) expect(e.toString()).toMatch('No wrapped plugins configured!') } }); test("it should return data from a wrapped plugin", async () => { require("../../../plugins/any-of/index.js"); const response = await LibResilientPluginConstructors.get('any-of')(LR, init).fetch('https://resilient.is/test.json'); expect(fetch).toHaveBeenCalled(); expect(await response.json()).toEqual({test: "success"}) expect(response.url).toEqual('https://resilient.is/test.json') }); test("it should pass Request() init data onto wrapped plugins", async () => { require("../../../plugins/any-of/index.js"); var initTest = { method: "GET", headers: new Headers({"x-stub": "STUB"}), mode: "mode-stub", credentials: "credentials-stub", cache: "cache-stub", referrer: "referrer-stub", // these are not implemented by service-worker-mock // https://github.com/zackargyle/service-workers/blob/master/packages/service-worker-mock/models/Request.js#L20 redirect: undefined, integrity: undefined, cache: undefined } const response = await LibResilientPluginConstructors.get('any-of')(LR, init).fetch('https://resilient.is/test.json', initTest); expect(fetch).toHaveBeenCalled(); expect(fetch).toHaveBeenCalledWith('https://resilient.is/test.json', initTest); expect(await response.json()).toEqual({test: "success"}) expect(response.url).toEqual('https://resilient.is/test.json') }); test("it should throw an error when HTTP status is >= 400", async () => { global.fetch.mockImplementation((url, init) => { const response = new Response( new Blob( ["Not Found"], {type: "text/plain"} ), { status: 404, statusText: "Not Found", url: url }); return Promise.resolve(response); }); require("../../../plugins/any-of/index.js"); expect.assertions(2); try { await LibResilientPluginConstructors.get('any-of')(LR, init).fetch('https://resilient.is/test.json') } catch (e) { if (e instanceof Array) { expect(e[0].toString()).toMatch('Error') } else { expect(e).toBeInstanceOf(AggregateError) } } expect(fetch).toHaveBeenCalled(); }); });