Skip to content

Commit

Permalink
feat: added magicHtml option (#3717)
Browse files Browse the repository at this point in the history
  • Loading branch information
snitin315 committed Aug 23, 2021
1 parent 3a04c60 commit 4831f58
Show file tree
Hide file tree
Showing 16 changed files with 422 additions and 7 deletions.
2 changes: 2 additions & 0 deletions README.md
Expand Up @@ -132,6 +132,8 @@ Options:
--ipc [value] Listen to a unix socket.
--live-reload Enables reload/refresh the page(s) when file changes are detected (enabled by default).
--no-live-reload Negative 'live-reload' option.
--magic-html Enables/Disables magic HTML routes (enabled by default).
--no-magic-html Negative 'magic-html' option.
--open [value...] Allows to configure dev server to open the browser(s) and page(s) after server had been started (set it to
true to open your default browser).
--no-open Negative 'open' option.
Expand Down
13 changes: 13 additions & 0 deletions bin/cli-flags.js
Expand Up @@ -534,6 +534,19 @@ module.exports = {
simpleType: "boolean",
multiple: false,
},
"magic-html": {
configs: [
{
type: "boolean",
multiple: false,
description: "Enables/Disables magic HTML routes (enabled by default).",
path: "magicHtml",
},
],
description: "Enables/Disables magic HTML routes (enabled by default).",
simpleType: "boolean",
multiple: false,
},
open: {
configs: [
{
Expand Down
7 changes: 6 additions & 1 deletion lib/Server.js
Expand Up @@ -431,6 +431,9 @@ class Server {
options.liveReload =
typeof options.liveReload !== "undefined" ? options.liveReload : true;

options.magicHtml =
typeof options.magicHtml !== "undefined" ? options.magicHtml : true;

// https://github.com/webpack/webpack-dev-server/issues/1990
const defaultOpenOptions = { wait: false };
const getOpenItemsFromObject = ({ target, ...rest }) => {
Expand Down Expand Up @@ -1132,7 +1135,9 @@ class Server {
runnableFeatures.push("staticServeIndex", "staticWatch");
}

runnableFeatures.push("magicHtml");
if (this.options.magicHtml) {
runnableFeatures.push("magicHtml");
}

if (this.options.onAfterSetupMiddleware) {
runnableFeatures.push("onAfterSetupMiddleware");
Expand Down
8 changes: 8 additions & 0 deletions lib/options.json
Expand Up @@ -331,6 +331,11 @@
"description": "Enables reload/refresh the page(s) when file changes are detected (enabled by default).",
"link": "https://webpack.js.org/configuration/dev-server/#devserverlivereload"
},
"MagicHTML": {
"type": "boolean",
"description": "Enables/Disables magic HTML routes (enabled by default).",
"link": "https://webpack.js.org/configuration/dev-server/#devservermagichtml"
},
"OnAfterSetupMiddleware": {
"instanceof": "Function",
"description": "Provides the ability to execute a custom function and apply custom middleware(s) after all other middlewares.",
Expand Down Expand Up @@ -729,6 +734,9 @@
"liveReload": {
"$ref": "#/definitions/LiveReload"
},
"magicHtml": {
"$ref": "#/definitions/MagicHTML"
},
"onAfterSetupMiddleware": {
"$ref": "#/definitions/OnAfterSetupMiddleware"
},
Expand Down
7 changes: 7 additions & 0 deletions test/__snapshots__/validate-options.test.js.snap.webpack4
Expand Up @@ -439,6 +439,13 @@ exports[`options validate should throw an error on the "liveReload" option with
-> Read more at https://webpack.js.org/configuration/dev-server/#devserverlivereload"
`;

exports[`options validate should throw an error on the "magicHtml" option with 'string' value 1`] = `
"ValidationError: Invalid options object. Dev Server has been initialized using an options object that does not match the API schema.
- options.magicHtml should be a boolean.
-> Enables/Disables magic HTML routes (enabled by default).
-> Read more at https://webpack.js.org/configuration/dev-server/#devservermagichtml"
`;

exports[`options validate should throw an error on the "onAfterSetupMiddleware" option with 'false' value 1`] = `
"ValidationError: Invalid options object. Dev Server has been initialized using an options object that does not match the API schema.
- options.onAfterSetupMiddleware should be an instance of function.
Expand Down
7 changes: 7 additions & 0 deletions test/__snapshots__/validate-options.test.js.snap.webpack5
Expand Up @@ -439,6 +439,13 @@ exports[`options validate should throw an error on the "liveReload" option with
-> Read more at https://webpack.js.org/configuration/dev-server/#devserverlivereload"
`;

exports[`options validate should throw an error on the "magicHtml" option with 'string' value 1`] = `
"ValidationError: Invalid options object. Dev Server has been initialized using an options object that does not match the API schema.
- options.magicHtml should be a boolean.
-> Enables/Disables magic HTML routes (enabled by default).
-> Read more at https://webpack.js.org/configuration/dev-server/#devservermagichtml"
`;

exports[`options validate should throw an error on the "onAfterSetupMiddleware" option with 'false' value 1`] = `
"ValidationError: Invalid options object. Dev Server has been initialized using an options object that does not match the API schema.
- options.onAfterSetupMiddleware should be an instance of function.
Expand Down
2 changes: 2 additions & 0 deletions test/cli/__snapshots__/basic.test.js.snap.webpack4
Expand Up @@ -99,6 +99,8 @@ Options:
--ipc [value] Listen to a unix socket.
--live-reload Enables reload/refresh the page(s) when file changes are detected (enabled by default).
--no-live-reload Disables reload/refresh the page(s) when file changes are detected (enabled by default)
--magic-html Enables/Disables magic HTML routes (enabled by default).
--no-magic-html Negative 'magic-html' option.
--open [value...] Allows to configure dev server to open the browser(s) and page(s) after server had been started (set it to true to open your default browser).
--no-open Does not open the default browser.
--open-target <value...> Opens specified page in browser.
Expand Down
2 changes: 2 additions & 0 deletions test/cli/__snapshots__/basic.test.js.snap.webpack5
Expand Up @@ -98,6 +98,8 @@ Options:
--ipc [value] Listen to a unix socket.
--live-reload Enables reload/refresh the page(s) when file changes are detected (enabled by default).
--no-live-reload Negative 'live-reload' option.
--magic-html Enables/Disables magic HTML routes (enabled by default).
--no-magic-html Negative 'magic-html' option.
--open [value...] Allows to configure dev server to open the browser(s) and page(s) after server had been started (set it to true to open your default browser).
--no-open Negative 'open' option.
--open-target <value...> Opens specified page in browser.
Expand Down
18 changes: 18 additions & 0 deletions test/cli/magicHtml-option.test.js
@@ -0,0 +1,18 @@
"use strict";

const { testBin } = require("../helpers/test-bin");
const port = require("../ports-map")["cli-magic-html"];

describe('"liveReload" CLI option', () => {
it('should work using "--magic-html"', async () => {
const { exitCode } = await testBin(["--port", port, "--magic-html"]);

expect(exitCode).toEqual(0);
});

it('should work using "--no-magic-html"', async () => {
const { exitCode } = await testBin(["--port", port, "--no-magic-html"]);

expect(exitCode).toEqual(0);
});
});
40 changes: 40 additions & 0 deletions test/e2e/__snapshots__/magic-html.test.js.snap.webpack4
@@ -0,0 +1,40 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`magicHtml option disabled should not handle GET request to magic async html: console messages 1`] = `
Array [
"Failed to load resource: the server responded with a status of 404 (Not Found)",
]
`;

exports[`magicHtml option disabled should not handle GET request to magic async html: response headers content-type 1`] = `"text/html; charset=utf-8"`;

exports[`magicHtml option disabled should not handle GET request to magic async html: response status 1`] = `404`;

exports[`magicHtml option disabled should not handle HEAD request to magic async html: console messages 1`] = `
Array [
"Failed to load resource: the server responded with a status of 404 (Not Found)",
]
`;

exports[`magicHtml option disabled should not handle HEAD request to magic async html: response headers content-type 1`] = `"text/html; charset=utf-8"`;

exports[`magicHtml option disabled should not handle HEAD request to magic async html: response status 1`] = `404`;

exports[`magicHtml option enabled should handle GET request to magic async html: console messages 1`] = `
Array [
"[HMR] Waiting for update signal from WDS...",
"Hey.",
"[webpack-dev-server] Hot Module Replacement enabled.",
"[webpack-dev-server] Live Reloading enabled.",
]
`;

exports[`magicHtml option enabled should handle GET request to magic async html: response headers content-type 1`] = `"text/html; charset=utf-8"`;

exports[`magicHtml option enabled should handle GET request to magic async html: response status 1`] = `200`;

exports[`magicHtml option enabled should handle HEAD request to magic async html: console messages 1`] = `Array []`;

exports[`magicHtml option enabled should handle HEAD request to magic async html: response headers content-type 1`] = `"text/html; charset=utf-8"`;

exports[`magicHtml option enabled should handle HEAD request to magic async html: response status 1`] = `200`;
40 changes: 40 additions & 0 deletions test/e2e/__snapshots__/magic-html.test.js.snap.webpack5
@@ -0,0 +1,40 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`magicHtml option disabled should not handle GET request to magic async html: console messages 1`] = `
Array [
"Failed to load resource: the server responded with a status of 404 (Not Found)",
]
`;

exports[`magicHtml option disabled should not handle GET request to magic async html: response headers content-type 1`] = `"text/html; charset=utf-8"`;

exports[`magicHtml option disabled should not handle GET request to magic async html: response status 1`] = `404`;

exports[`magicHtml option disabled should not handle HEAD request to magic async html: console messages 1`] = `
Array [
"Failed to load resource: the server responded with a status of 404 (Not Found)",
]
`;

exports[`magicHtml option disabled should not handle HEAD request to magic async html: response headers content-type 1`] = `"text/html; charset=utf-8"`;

exports[`magicHtml option disabled should not handle HEAD request to magic async html: response status 1`] = `404`;

exports[`magicHtml option enabled should handle GET request to magic async html: console messages 1`] = `
Array [
"[HMR] Waiting for update signal from WDS...",
"Hey.",
"[webpack-dev-server] Hot Module Replacement enabled.",
"[webpack-dev-server] Live Reloading enabled.",
]
`;

exports[`magicHtml option enabled should handle GET request to magic async html: response headers content-type 1`] = `"text/html; charset=utf-8"`;

exports[`magicHtml option enabled should handle GET request to magic async html: response status 1`] = `200`;

exports[`magicHtml option enabled should handle HEAD request to magic async html: console messages 1`] = `Array []`;

exports[`magicHtml option enabled should handle HEAD request to magic async html: response headers content-type 1`] = `"text/html; charset=utf-8"`;

exports[`magicHtml option enabled should handle HEAD request to magic async html: response status 1`] = `200`;
167 changes: 167 additions & 0 deletions test/e2e/magic-html.test.js
@@ -0,0 +1,167 @@
"use strict";

const webpack = require("webpack");
const Server = require("../../lib/Server");
const config = require("../fixtures/client-config/webpack.config");
const runBrowser = require("../helpers/run-browser");
const port = require("../ports-map")["magic-html-option"];

describe("magicHtml option", () => {
describe("enabled", () => {
let compiler;
let server;
let page;
let browser;
let pageErrors;
let consoleMessages;

beforeEach(async () => {
compiler = webpack(config);
server = new Server({ port, magicHtml: true }, compiler);

await server.start();

({ page, browser } = await runBrowser());

pageErrors = [];
consoleMessages = [];
});

afterEach(async () => {
await browser.close();
await server.stop();
});

it("should handle GET request to magic async html", async () => {
page
.on("console", (message) => {
consoleMessages.push(message);
})
.on("pageerror", (error) => {
pageErrors.push(error);
});

const response = await page.goto(`http://127.0.0.1:${port}/main`, {
waitUntil: "networkidle0",
});

expect(response.headers()["content-type"]).toMatchSnapshot(
"response headers content-type"
);

expect(response.status()).toMatchSnapshot("response status");

expect(consoleMessages.map((message) => message.text())).toMatchSnapshot(
"console messages"
);
});

it("should handle HEAD request to magic async html", async () => {
await page.setRequestInterception(true);

page
.on("console", (message) => {
consoleMessages.push(message);
})
.on("pageerror", (error) => {
pageErrors.push(error);
})
.on("request", (interceptedRequest) => {
interceptedRequest.continue({ method: "HEAD" });
});

const response = await page.goto(`http://127.0.0.1:${port}/main`, {
waitUntil: "networkidle0",
});

expect(response.headers()["content-type"]).toMatchSnapshot(
"response headers content-type"
);

expect(response.status()).toMatchSnapshot("response status");

expect(consoleMessages.map((message) => message.text())).toMatchSnapshot(
"console messages"
);
});
});

describe("disabled", () => {
let compiler;
let server;
let page;
let browser;
let pageErrors;
let consoleMessages;

beforeEach(async () => {
compiler = webpack(config);
server = new Server({ port, magicHtml: false }, compiler);

await server.start();

({ page, browser } = await runBrowser());

pageErrors = [];
consoleMessages = [];
});

afterEach(async () => {
await browser.close();
await server.stop();
});

it("should not handle GET request to magic async html", async () => {
page
.on("console", (message) => {
consoleMessages.push(message);
})
.on("pageerror", (error) => {
pageErrors.push(error);
});

const response = await page.goto(`http://127.0.0.1:${port}/main`, {
waitUntil: "networkidle0",
});

expect(response.headers()["content-type"]).toMatchSnapshot(
"response headers content-type"
);

expect(response.status()).toMatchSnapshot("response status");

expect(consoleMessages.map((message) => message.text())).toMatchSnapshot(
"console messages"
);
});

it("should not handle HEAD request to magic async html", async () => {
await page.setRequestInterception(true);

page
.on("console", (message) => {
consoleMessages.push(message);
})
.on("pageerror", (error) => {
pageErrors.push(error);
})
.on("request", (interceptedRequest) => {
interceptedRequest.continue({ method: "HEAD" });
});

const response = await page.goto(`http://127.0.0.1:${port}/main`, {
waitUntil: "networkidle0",
});

expect(response.headers()["content-type"]).toMatchSnapshot(
"response headers content-type"
);

expect(response.status()).toMatchSnapshot("response status");

expect(consoleMessages.map((message) => message.text())).toMatchSnapshot(
"console messages"
);
});
});
});

0 comments on commit 4831f58

Please sign in to comment.