From ea2e8b579e79b1b7879d456cc708a91b4a98ff09 Mon Sep 17 00:00:00 2001 From: Sam Selikoff Date: Thu, 19 Sep 2019 16:11:45 -0400 Subject: [PATCH] Add regex support to passthrough (#138) * Louder errors * Passthrough can take a function --- .../external/browser-only/passthrough-test.js | 46 +++++++++++++++++- __tests__/internal/unit/server-test.js | 35 -------------- lib/assert.js | 2 + lib/server.js | 47 +++++++++++++++---- 4 files changed, 84 insertions(+), 46 deletions(-) diff --git a/__tests__/external/browser-only/passthrough-test.js b/__tests__/external/browser-only/passthrough-test.js index 7862beac..31615b7d 100644 --- a/__tests__/external/browser-only/passthrough-test.js +++ b/__tests__/external/browser-only/passthrough-test.js @@ -1,6 +1,6 @@ import { Server } from "@miragejs/server"; -describe("External |Browser only | Passthrough", () => { +describe("External | Browser only | Passthrough", () => { let server, originalError; beforeEach(() => { @@ -152,4 +152,48 @@ describe("External |Browser only | Passthrough", () => { "Network request failed" ); }); + + test("it can take a function", async () => { + server.config({ + routes() { + this.passthrough(request => { + return request.url === "/users"; + }); + } + }); + + await expect(fetch("/users")).rejects.toThrow("Network request failed"); + + await expect(fetch("/movies")).rejects.toThrow( + `Mirage: Your app tried to GET '/movies'` + ); + }); + + test("it passes through common build tool-related paths", async () => { + await expect(fetch("/abc.hot-update.json")).rejects.toThrow( + "Network request failed" + ); + await expect(fetch("/movies")).rejects.toThrow( + `Mirage: Your app tried to GET '/movies'` + ); + + await expect(fetch("/def.hot-update.json")).rejects.toThrow( + "Network request failed" + ); + await expect(fetch("/movies")).rejects.toThrow( + `Mirage: Your app tried to GET '/movies'` + ); + }); +}); + +test("a new server created with useDefaultPassthroughs set to false ignores default passthrougsh", async () => { + let server = new Server({ + useDefaultPassthroughs: false + }); + + await expect(fetch("/abc.hot-update.json")).rejects.toThrow( + "Mirage: Your app tried to GET '/abc.hot-update.json'" + ); + + server.shutdown(); }); diff --git a/__tests__/internal/unit/server-test.js b/__tests__/internal/unit/server-test.js index 5ab3cf32..2e8a9fd9 100644 --- a/__tests__/internal/unit/server-test.js +++ b/__tests__/internal/unit/server-test.js @@ -1,6 +1,5 @@ import { Server, - defaultPassthroughs, Model, Factory, belongsTo, @@ -1455,37 +1454,3 @@ describe("Unit | Server #buildList", function() { ); }); }); - -describe("Unit | Server #defaultPassthroughs", function() { - test("server configures default passthroughs when useDefaultPassthroughs is true", () => { - let server = new Server({ useDefaultPassthroughs: true }); - - expect.assertions(defaultPassthroughs.length); - defaultPassthroughs.forEach(passthroughUrl => { - let passthroughRequest = { method: "GET", url: passthroughUrl }; - let isPassedThrough = server.pretender.checkPassthrough( - passthroughRequest - ); - - expect(isPassedThrough).toBeTruthy(); - }); - - server.shutdown(); - }); - - test("server does not configure default passthroughs when useDefaultPassthroughs is false", () => { - let server = new Server({ useDefaultPassthroughs: false }); - - expect.assertions(defaultPassthroughs.length); - defaultPassthroughs.forEach(passthroughUrl => { - let passthroughRequest = { method: "GET", url: passthroughUrl }; - let isPassedThrough = server.pretender.checkPassthrough( - passthroughRequest - ); - - expect(!isPassedThrough).toBeTruthy(); - }); - - server.shutdown(); - }); -}); diff --git a/lib/assert.js b/lib/assert.js index 6e76fb36..12a3c922 100644 --- a/lib/assert.js +++ b/lib/assert.js @@ -14,10 +14,12 @@ let errorProps = [ */ export default function assert(bool, text) { if (typeof bool === "string" && !text) { + // console.error(`Mirage: ${bool}`); throw new MirageError(bool); } if (!bool) { + // console.error(`Mirage: ${text}`); throw new MirageError(text.replace(/^ +/gm, "") || "Assertion failed"); } } diff --git a/lib/server.js b/lib/server.js index bdd94f7b..c1d69934 100644 --- a/lib/server.js +++ b/lib/server.js @@ -28,7 +28,9 @@ function createPretender(server) { this.passthroughRequest = function(verb, path, request) { if (server.shouldLog()) { console.log( - `Passthrough request: ${verb.toUpperCase()} ${request.url}` + `Mirage: Passthrough request for ${verb.toUpperCase()} ${ + request.url + }` ); } }; @@ -62,10 +64,23 @@ function createPretender(server) { } }; + let originalCheckPassthrough = this.checkPassthrough; + this.checkPassthrough = function(request) { + let shouldPassthrough = server.passthroughChecks.some( + passthroughCheck => passthroughCheck(request) + ); + + if (shouldPassthrough) { + this[request.method.toLowerCase()](request.url, this.passthrough); + } + + return originalCheckPassthrough.apply(this, arguments); + }; + this.unhandledRequest = function(verb, path) { path = decodeURI(path); assert( - `Your app tried to ${verb} '${path}', but there was no route defined to handle this request. Defined a route for this endpoint in your baseConfig. Did you forget to define a namespace?` + `Your app tried to ${verb} '${path}', but there was no route defined to handle this request. Define a route for this endpoint in your routes() config. Did you forget to define a namespace?` ); }; }, @@ -86,7 +101,10 @@ const defaultInflector = { singularize, pluralize }; */ const defaultPassthroughs = [ "http://localhost:0/chromecheckurl", // mobile chrome - "http://localhost:30820/socket.io" // electron + "http://localhost:30820/socket.io", // electron + request => { + return /.+\.hot-update.json$/.test(request.url); + } ]; /** @@ -175,6 +193,8 @@ export default class Server { } config(config = {}) { + this.passthroughChecks = this.passthroughChecks || []; + let didOverrideConfig = config.environment && (this.environment && this.environment !== config.environment); @@ -426,7 +446,11 @@ export default class Server { this.loadFixtures(); } - if (config.useDefaultPassthroughs) { + let useDefaultPassthroughs = + typeof config.useDefaultPassthroughs !== "undefined" + ? config.useDefaultPassthroughs + : true; + if (useDefaultPassthroughs) { this._configureDefaultPassthroughs(); } } @@ -540,17 +564,20 @@ export default class Server { let lastArg = paths[paths.length - 1]; if (paths.length === 0) { - // paths = ['http://localhost:7357']; paths = ["/**", "/"]; } else if (Array.isArray(lastArg)) { verbs = paths.pop(); } - verbs.forEach(verb => { - paths.forEach(path => { - let fullPath = this._getFullPath(path); - this.pretender[verb](fullPath, this.pretender.passthrough); - }); + paths.forEach(path => { + if (typeof path === "function") { + this.passthroughChecks.push(path); + } else { + verbs.forEach(verb => { + let fullPath = this._getFullPath(path); + this.pretender[verb](fullPath, this.pretender.passthrough); + }); + } }); } }