From 75bafbfeeb70e4ca395e74e229d5c4dfb2d823a2 Mon Sep 17 00:00:00 2001 From: Nitin Kumar Date: Tue, 17 Aug 2021 20:08:30 +0530 Subject: [PATCH] test: add e2e tests for module federation (#3658) --- .../module-federation.test.js.snap.webpack4 | 17 + .../module-federation.test.js.snap.webpack5 | 25 ++ test/e2e/module-federation.test.js | 325 ++++++++++++++++++ test/integration/ModuleFederation.test.js | 104 ------ 4 files changed, 367 insertions(+), 104 deletions(-) create mode 100644 test/e2e/__snapshots__/module-federation.test.js.snap.webpack4 create mode 100644 test/e2e/__snapshots__/module-federation.test.js.snap.webpack5 create mode 100644 test/e2e/module-federation.test.js delete mode 100644 test/integration/ModuleFederation.test.js diff --git a/test/e2e/__snapshots__/module-federation.test.js.snap.webpack4 b/test/e2e/__snapshots__/module-federation.test.js.snap.webpack4 new file mode 100644 index 0000000000..22761ef170 --- /dev/null +++ b/test/e2e/__snapshots__/module-federation.test.js.snap.webpack4 @@ -0,0 +1,17 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Module federation should work with multi compiler config should use the last entry export: console messages 1`] = `Array []`; + +exports[`Module federation should work with multi compiler config should use the last entry export: page errors 1`] = `Array []`; + +exports[`Module federation should work with object multi-entry config should support the named entry export: console messages 1`] = `Array []`; + +exports[`Module federation should work with object multi-entry config should support the named entry export: page errors 1`] = `Array []`; + +exports[`Module federation should work with object multi-entry config should use the last entry export: console messages 1`] = `Array []`; + +exports[`Module federation should work with object multi-entry config should use the last entry export: page errors 1`] = `Array []`; + +exports[`Module federation should work with simple multi-entry config should use the last entry export: console messages 1`] = `Array []`; + +exports[`Module federation should work with simple multi-entry config should use the last entry export: page errors 1`] = `Array []`; diff --git a/test/e2e/__snapshots__/module-federation.test.js.snap.webpack5 b/test/e2e/__snapshots__/module-federation.test.js.snap.webpack5 new file mode 100644 index 0000000000..4a7cc9fe06 --- /dev/null +++ b/test/e2e/__snapshots__/module-federation.test.js.snap.webpack5 @@ -0,0 +1,25 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Module federation should use plugin should contain hot script in main.js: console messages 1`] = `Array []`; + +exports[`Module federation should use plugin should contain hot script in main.js: page errors 1`] = `Array []`; + +exports[`Module federation should use plugin should contain hot script in remoteEntry.js: console messages 1`] = `Array []`; + +exports[`Module federation should use plugin should contain hot script in remoteEntry.js: page errors 1`] = `Array []`; + +exports[`Module federation should work with multi compiler config should use the last entry export: console messages 1`] = `Array []`; + +exports[`Module federation should work with multi compiler config should use the last entry export: page errors 1`] = `Array []`; + +exports[`Module federation should work with object multi-entry config should support the named entry export: console messages 1`] = `Array []`; + +exports[`Module federation should work with object multi-entry config should support the named entry export: page errors 1`] = `Array []`; + +exports[`Module federation should work with object multi-entry config should use the last entry export: console messages 1`] = `Array []`; + +exports[`Module federation should work with object multi-entry config should use the last entry export: page errors 1`] = `Array []`; + +exports[`Module federation should work with simple multi-entry config should use the last entry export: console messages 1`] = `Array []`; + +exports[`Module federation should work with simple multi-entry config should use the last entry export: page errors 1`] = `Array []`; diff --git a/test/e2e/module-federation.test.js b/test/e2e/module-federation.test.js new file mode 100644 index 0000000000..37c266de18 --- /dev/null +++ b/test/e2e/module-federation.test.js @@ -0,0 +1,325 @@ +"use strict"; + +const webpack = require("webpack"); +const requireFromString = require("require-from-string"); +const Server = require("../../lib/Server"); +const simpleConfig = require("../fixtures/module-federation-config/webpack.config"); +const objectEntryConfig = require("../fixtures/module-federation-config/webpack.object-entry.config"); +const multiConfig = require("../fixtures/module-federation-config/webpack.multi.config"); +const runBrowser = require("../helpers/run-browser"); +const isWebpack5 = require("../helpers/isWebpack5"); +const port = require("../ports-map")["universal-compiler"]; + +const describeOnlyWebpack5 = isWebpack5 ? describe : describe.skip; + +let pluginConfig; + +if (isWebpack5) { + pluginConfig = require("../fixtures/module-federation-config/webpack.plugin"); +} + +describe("Module federation", () => { + describe("should work with simple multi-entry config", () => { + let compiler; + let server; + let page; + let browser; + let pageErrors; + let consoleMessages; + + beforeEach(async () => { + compiler = webpack(simpleConfig); + server = new Server({ port }, compiler); + + await server.start(); + + ({ page, browser } = await runBrowser()); + + pageErrors = []; + consoleMessages = []; + }); + + afterEach(async () => { + await browser.close(); + await server.stop(); + }); + + it("should use the last entry export", async () => { + page + .on("console", (message) => { + consoleMessages.push(message); + }) + .on("pageerror", (error) => { + pageErrors.push(error); + }); + + await page.goto(`http://127.0.0.1:${port}/main.js`, { + waitUntil: "networkidle0", + }); + + const bodyHandle = await page.$("body"); + const textContent = await page.evaluate( + (body) => body.textContent, + bodyHandle + ); + + expect(textContent).toContain("entry1"); + + let exports; + + expect(() => { + exports = requireFromString(textContent); + }).not.toThrow(); + + expect(exports).toEqual("entry2"); + + expect(consoleMessages.map((message) => message.text())).toMatchSnapshot( + "console messages" + ); + + expect(pageErrors).toMatchSnapshot("page errors"); + }); + }); + + describe("should work with object multi-entry config", () => { + let compiler; + let server; + let page; + let browser; + let pageErrors; + let consoleMessages; + + beforeEach(async () => { + compiler = webpack(objectEntryConfig); + server = new Server({ port }, compiler); + + await server.start(); + + ({ page, browser } = await runBrowser()); + + pageErrors = []; + consoleMessages = []; + }); + + afterEach(async () => { + await browser.close(); + await server.stop(); + }); + + it("should use the last entry export", async () => { + page + .on("console", (message) => { + consoleMessages.push(message); + }) + .on("pageerror", (error) => { + pageErrors.push(error); + }); + + await page.goto(`http://127.0.0.1:${port}/main.js`, { + waitUntil: "networkidle0", + }); + + const bodyHandle = await page.$("body"); + const textContent = await page.evaluate( + (body) => body.textContent, + bodyHandle + ); + + expect(textContent).toContain("entry1"); + + let exports; + + expect(() => { + exports = requireFromString(textContent); + }).not.toThrow(); + + expect(exports).toEqual("entry2"); + + expect(consoleMessages.map((message) => message.text())).toMatchSnapshot( + "console messages" + ); + + expect(pageErrors).toMatchSnapshot("page errors"); + }); + + it("should support the named entry export", async () => { + page + .on("console", (message) => { + consoleMessages.push(message); + }) + .on("pageerror", (error) => { + pageErrors.push(error); + }); + + await page.goto(`http://127.0.0.1:${port}/foo.js`, { + waitUntil: "networkidle0", + }); + + const bodyHandle = await page.$("body"); + const textContent = await page.evaluate( + (body) => body.textContent, + bodyHandle + ); + + expect(textContent).not.toContain("entry2"); + + let exports; + + expect(() => { + exports = requireFromString(textContent); + }).not.toThrow(); + + expect(exports).toEqual("entry1"); + + expect(consoleMessages.map((message) => message.text())).toMatchSnapshot( + "console messages" + ); + + expect(pageErrors).toMatchSnapshot("page errors"); + }); + }); + + describe("should work with multi compiler config", () => { + let compiler; + let server; + let page; + let browser; + let pageErrors; + let consoleMessages; + + beforeEach(async () => { + compiler = webpack(multiConfig); + server = new Server({ port }, compiler); + + await server.start(); + + ({ page, browser } = await runBrowser()); + + pageErrors = []; + consoleMessages = []; + }); + + afterEach(async () => { + await browser.close(); + await server.stop(); + }); + + it("should use the last entry export", async () => { + page + .on("console", (message) => { + consoleMessages.push(message); + }) + .on("pageerror", (error) => { + pageErrors.push(error); + }); + + await page.goto(`http://127.0.0.1:${port}/main.js`, { + waitUntil: "networkidle0", + }); + + const bodyHandle = await page.$("body"); + const textContent = await page.evaluate( + (body) => body.textContent, + bodyHandle + ); + + expect(textContent).toContain("entry1"); + + let exports; + + expect(() => { + exports = requireFromString(textContent); + }).not.toThrow(); + + expect(exports).toEqual("entry2"); + + expect(consoleMessages.map((message) => message.text())).toMatchSnapshot( + "console messages" + ); + + expect(pageErrors).toMatchSnapshot("page errors"); + }); + }); + + describeOnlyWebpack5("should use plugin", () => { + let compiler; + let server; + let page; + let browser; + let pageErrors; + let consoleMessages; + + beforeEach(async () => { + compiler = webpack(pluginConfig); + server = new Server({ port }, compiler); + + await server.start(); + + ({ page, browser } = await runBrowser()); + + pageErrors = []; + consoleMessages = []; + }); + + afterEach(async () => { + await browser.close(); + await server.stop(); + }); + + it("should contain hot script in remoteEntry.js", async () => { + page + .on("console", (message) => { + consoleMessages.push(message); + }) + .on("pageerror", (error) => { + pageErrors.push(error); + }); + + await page.goto(`http://127.0.0.1:${port}/remoteEntry.js`, { + waitUntil: "networkidle0", + }); + + const bodyHandle = await page.$("body"); + const remoteEntryTextContent = await page.evaluate( + (body) => body.textContent, + bodyHandle + ); + + expect(remoteEntryTextContent).toMatch(/webpack\/hot\/dev-server\.js/); + + expect(consoleMessages.map((message) => message.text())).toMatchSnapshot( + "console messages" + ); + + expect(pageErrors).toMatchSnapshot("page errors"); + }); + + it("should contain hot script in main.js", async () => { + page + .on("console", (message) => { + consoleMessages.push(message); + }) + .on("pageerror", (error) => { + pageErrors.push(error); + }); + + await page.goto(`http://127.0.0.1:${port}/main.js`, { + waitUntil: "networkidle0", + }); + + const bodyHandle = await page.$("body"); + const mainEntryTextContent = await page.evaluate( + (body) => body.textContent, + bodyHandle + ); + + expect(mainEntryTextContent).toMatch(/webpack\/hot\/dev-server\.js/); + + expect(consoleMessages.map((message) => message.text())).toMatchSnapshot( + "console messages" + ); + + expect(pageErrors).toMatchSnapshot("page errors"); + }); + }); +}); diff --git a/test/integration/ModuleFederation.test.js b/test/integration/ModuleFederation.test.js deleted file mode 100644 index 1dc62b641f..0000000000 --- a/test/integration/ModuleFederation.test.js +++ /dev/null @@ -1,104 +0,0 @@ -"use strict"; - -const webpack = require("webpack"); -const request = require("supertest"); -const requireFromString = require("require-from-string"); -const Server = require("../../lib/Server"); -const simpleConfig = require("../fixtures/module-federation-config/webpack.config"); -const objectEntryConfig = require("../fixtures/module-federation-config/webpack.object-entry.config"); -const multiConfig = require("../fixtures/module-federation-config/webpack.multi.config"); -const port = require("../ports-map")["module-federation"]; -const isWebpack5 = require("../helpers/isWebpack5"); - -let pluginConfig; - -if (isWebpack5) { - pluginConfig = require("../fixtures/module-federation-config/webpack.plugin"); -} - -describe("module federation", () => { - describe.each([ - ["simple multi-entry config", simpleConfig], - ["object multi-entry config", objectEntryConfig], - ["multi compiler config", multiConfig], - ])("%s", (title, config) => { - let server; - let req; - - beforeAll(async () => { - const compiler = webpack(config); - - server = new Server({ port }, compiler); - - await server.start(); - - req = request(server.app); - }); - - afterAll(async () => { - await server.stop(); - }); - - it("should use the last entry export", async () => { - const { text, statusCode } = await req.get("/main.js"); - - expect(statusCode).toEqual(200); - expect(text).toContain("entry1"); - - let exports; - - expect(() => { - exports = requireFromString(text); - }).not.toThrow(); - expect(exports).toEqual("entry2"); - }); - - if (title === "object multi-entry config") { - it("should support the named entry export", async () => { - const { text, statusCode } = await req.get("/foo.js"); - - expect(statusCode).toEqual(200); - expect(text).not.toContain("entry2"); - - let exports; - - expect(() => { - exports = requireFromString(text); - }).not.toThrow(); - - expect(exports).toEqual("entry1"); - }); - } - }); - - (isWebpack5 ? describe : describe.skip)("use plugin", () => { - let server; - let req; - - beforeAll(async () => { - const compiler = webpack(pluginConfig); - - server = new Server({ port }, compiler); - - await server.start(); - - req = request(server.app); - }); - - afterAll(async () => { - await server.stop(); - }); - - it("should contain hot script", async () => { - const responseRemoteEntry = await req.get("/remoteEntry.js"); - - expect(responseRemoteEntry.statusCode).toEqual(200); - expect(responseRemoteEntry.text).toMatch(/webpack\/hot\/dev-server\.js/); - - const responseMain = await req.get("/main.js"); - - expect(responseMain.statusCode).toEqual(200); - expect(responseMain.text).toMatch(/webpack\/hot\/dev-server\.js/); - }); - }); -});