From a69cd9b1f902e713e3547021451627f0e71ef281 Mon Sep 17 00:00:00 2001 From: cap-Bernardito Date: Fri, 26 Mar 2021 18:55:51 +0300 Subject: [PATCH 1/2] feat: added `emit` option --- README.md | 9 + src/loader-options.json | 3 + src/loader.js | 4 +- test/__snapshots__/emit-option.test.js.snap | 37 ++ .../validate-loader-options.test.js.snap | 16 +- test/emit-option.test.js | 541 ++++++++++++++++++ test/fixtures/locals.js | 4 + test/fixtures/locals/index.css | 11 + test/fixtures/locals/template.js | 9 + test/fixtures/react.svg | 1 + test/fixtures/style-url.css | 4 + test/fixtures/style-url.js | 1 + test/helpers/getCompiler.js | 7 + 13 files changed, 637 insertions(+), 10 deletions(-) create mode 100644 test/__snapshots__/emit-option.test.js.snap create mode 100644 test/emit-option.test.js create mode 100644 test/fixtures/locals.js create mode 100644 test/fixtures/locals/index.css create mode 100644 test/fixtures/locals/template.js create mode 100644 test/fixtures/react.svg create mode 100644 test/fixtures/style-url.css create mode 100644 test/fixtures/style-url.js diff --git a/README.md b/README.md index 14b373db..b78ce12d 100644 --- a/README.md +++ b/README.md @@ -261,6 +261,7 @@ module.exports = { | Name | Type | Default | Description | | :-----------------------------: | :------------------: | :--------------------------------: | :-------------------------------------------------------------------------------- | | **[`publicPath`](#publicPath)** | `{String\|Function}` | `webpackOptions.output.publicPath` | Specifies a custom public path for the external resources like images, files, etc | +| **[`emit`](#emit)** | `{Boolean}` | `true` | If false, the plugin will extract the CSS but **will not** emit the file | | **[`esModule`](#esModule)** | `{Boolean}` | `true` | Use ES modules syntax | | **[`modules`](#modules)** | `{Object}` | `undefined` | Configuration CSS Modules | @@ -344,6 +345,14 @@ module.exports = { }; ``` +#### `emit` + +Type: `Boolean` +Default: `true` + +If true, emits a file (writes a file to the filesystem). If false, the plugin will extract the CSS but **will not** emit the file. +It is often useful to disable this option for server-side packages. + #### `esModule` Type: `Boolean` diff --git a/src/loader-options.json b/src/loader-options.json index 7e66190d..a863e270 100644 --- a/src/loader-options.json +++ b/src/loader-options.json @@ -12,6 +12,9 @@ } ] }, + "emit": { + "type": "boolean" + }, "esModule": { "type": "boolean" }, diff --git a/src/loader.js b/src/loader.js index 15c2c045..ee8ee4c5 100644 --- a/src/loader.js +++ b/src/loader.js @@ -205,11 +205,11 @@ export function pitch(request) { } const identifierCountMap = new Map(); - + const emit = typeof options.emit !== 'undefined' ? options.emit : true; let lastDep; for (const dependency of dependencies) { - if (!dependency.identifier) { + if (!dependency.identifier || !emit) { // eslint-disable-next-line no-continue continue; } diff --git a/test/__snapshots__/emit-option.test.js.snap b/test/__snapshots__/emit-option.test.js.snap new file mode 100644 index 00000000..0f2bce87 --- /dev/null +++ b/test/__snapshots__/emit-option.test.js.snap @@ -0,0 +1,37 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`emit option should work with locals and invalidate cache when emit option is "false": DOM 1`] = ` +" + style-loader test + + + +css.foo: _1F17fUrdX_cbcyDHpFqmAD +css.bar: _3TZVxmkrZR2cTfifKhDoZn +css.baz: M-pzkE59YBii7EXzFyxE6 +" +`; + +exports[`emit option should work with locals and invalidate cache when emit option is "false": DOM 2`] = ` +" + style-loader test + + + +css.foo-bar: VWLDg_rByGM4Rdhz5T3Ns +css.bar: _3TZVxmkrZR2cTfifKhDoZn +css.baz: M-pzkE59YBii7EXzFyxE6 +" +`; + +exports[`emit option should work with locals when emit option is "false": DOM 1`] = ` +" + style-loader test + + + +css.foo: _1F17fUrdX_cbcyDHpFqmAD +css.bar: _3TZVxmkrZR2cTfifKhDoZn +css.baz: M-pzkE59YBii7EXzFyxE6 +" +`; diff --git a/test/__snapshots__/validate-loader-options.test.js.snap b/test/__snapshots__/validate-loader-options.test.js.snap index dd4b5ffa..a8a95996 100644 --- a/test/__snapshots__/validate-loader-options.test.js.snap +++ b/test/__snapshots__/validate-loader-options.test.js.snap @@ -29,47 +29,47 @@ exports[`validate options should throw an error on the "publicPath" option with exports[`validate options should throw an error on the "unknown" option with "/test/" value 1`] = ` "Invalid options object. Mini CSS Extract Plugin Loader has been initialized using an options object that does not match the API schema. - options has an unknown property 'unknown'. These properties are valid: - object { publicPath?, esModule?, modules? }" + object { publicPath?, emit?, esModule?, modules? }" `; exports[`validate options should throw an error on the "unknown" option with "[]" value 1`] = ` "Invalid options object. Mini CSS Extract Plugin Loader has been initialized using an options object that does not match the API schema. - options has an unknown property 'unknown'. These properties are valid: - object { publicPath?, esModule?, modules? }" + object { publicPath?, emit?, esModule?, modules? }" `; exports[`validate options should throw an error on the "unknown" option with "{"foo":"bar"}" value 1`] = ` "Invalid options object. Mini CSS Extract Plugin Loader has been initialized using an options object that does not match the API schema. - options has an unknown property 'unknown'. These properties are valid: - object { publicPath?, esModule?, modules? }" + object { publicPath?, emit?, esModule?, modules? }" `; exports[`validate options should throw an error on the "unknown" option with "{}" value 1`] = ` "Invalid options object. Mini CSS Extract Plugin Loader has been initialized using an options object that does not match the API schema. - options has an unknown property 'unknown'. These properties are valid: - object { publicPath?, esModule?, modules? }" + object { publicPath?, emit?, esModule?, modules? }" `; exports[`validate options should throw an error on the "unknown" option with "1" value 1`] = ` "Invalid options object. Mini CSS Extract Plugin Loader has been initialized using an options object that does not match the API schema. - options has an unknown property 'unknown'. These properties are valid: - object { publicPath?, esModule?, modules? }" + object { publicPath?, emit?, esModule?, modules? }" `; exports[`validate options should throw an error on the "unknown" option with "false" value 1`] = ` "Invalid options object. Mini CSS Extract Plugin Loader has been initialized using an options object that does not match the API schema. - options has an unknown property 'unknown'. These properties are valid: - object { publicPath?, esModule?, modules? }" + object { publicPath?, emit?, esModule?, modules? }" `; exports[`validate options should throw an error on the "unknown" option with "test" value 1`] = ` "Invalid options object. Mini CSS Extract Plugin Loader has been initialized using an options object that does not match the API schema. - options has an unknown property 'unknown'. These properties are valid: - object { publicPath?, esModule?, modules? }" + object { publicPath?, emit?, esModule?, modules? }" `; exports[`validate options should throw an error on the "unknown" option with "true" value 1`] = ` "Invalid options object. Mini CSS Extract Plugin Loader has been initialized using an options object that does not match the API schema. - options has an unknown property 'unknown'. These properties are valid: - object { publicPath?, esModule?, modules? }" + object { publicPath?, emit?, esModule?, modules? }" `; diff --git a/test/emit-option.test.js b/test/emit-option.test.js new file mode 100644 index 00000000..00c49011 --- /dev/null +++ b/test/emit-option.test.js @@ -0,0 +1,541 @@ +/* eslint-env browser */ +import fs from 'fs'; +import path from 'path'; + +import webpack from 'webpack'; +import del from 'del'; + +import MiniCssExtractPlugin from '../src'; + +import { compile, getCompiler, runInJsDom } from './helpers/index'; + +describe('emit option', () => { + it(`should work without emit option`, async () => { + const compiler = getCompiler( + 'style-url.js', + {}, + { + mode: 'none', + output: { + publicPath: '', + path: path.resolve(__dirname, '../outputs'), + filename: '[name].bundle.js', + }, + + plugins: [ + new MiniCssExtractPlugin({ + filename: '[name].css', + }), + ], + } + ); + const stats = await compile(compiler); + + expect(stats.compilation.getAsset('main.css')).toBeDefined(); + expect(stats.compilation.warnings).toHaveLength(0); + expect(stats.compilation.errors).toHaveLength(0); + }); + + it(`should work when emit option is "true"`, async () => { + const compiler = getCompiler( + 'style-url.js', + { + emit: true, + }, + { + mode: 'none', + output: { + publicPath: '', + path: path.resolve(__dirname, '../outputs'), + filename: '[name].[contenthash].[fullhash].js', + }, + + plugins: [ + new MiniCssExtractPlugin({ + filename: '[name].css', + }), + ], + } + ); + const stats = await compile(compiler); + + expect( + stats.compilation.getAsset( + 'main.9a73ed992e802ad0462e.5e3448a6abbe6ad89a93.js' + ) + ).toBeDefined(); + expect(stats.compilation.getAsset('main.css')).toBeDefined(); + expect(stats.compilation.warnings).toHaveLength(0); + expect(stats.compilation.errors).toHaveLength(0); + }); + + it(`should work when emit option is "false"`, async () => { + const compiler = getCompiler( + 'style-url.js', + { + emit: false, + }, + { + mode: 'none', + output: { + publicPath: '', + path: path.resolve(__dirname, '../outputs'), + filename: '[name].[contenthash].[fullhash].js', + }, + plugins: [ + new MiniCssExtractPlugin({ + filename: '[name].css', + }), + ], + } + ); + const stats = await compile(compiler); + + expect(stats.compilation.getAsset('main.css')).toBeUndefined(); + expect( + stats.compilation.getAsset( + 'main.15f4ba3ceaa4de358bed.0df63dd1b4a35fa4358d.js' + ) + ).toBeDefined(); + expect(stats.compilation.warnings).toHaveLength(0); + expect(stats.compilation.errors).toHaveLength(0); + }); + + it(`should work with locals when emit option is "false"`, async () => { + const compiler = getCompiler( + 'locals.js', + {}, + { + output: { + publicPath: '', + path: path.resolve(__dirname, '../outputs'), + filename: '[name].bundle.js', + }, + module: { + rules: [ + { + test: /\.css$/, + use: [ + { + loader: MiniCssExtractPlugin.loader, + options: { + emit: false, + }, + }, + { + loader: 'css-loader', + options: { + modules: true, + }, + }, + ], + }, + ], + }, + plugins: [ + new MiniCssExtractPlugin({ + filename: '[name].css', + }), + ], + } + ); + const stats = await compile(compiler); + + runInJsDom('main.bundle.js', compiler, stats, (dom) => { + expect(dom.serialize()).toMatchSnapshot('DOM'); + }); + expect(stats.compilation.warnings).toHaveLength(0); + expect(stats.compilation.errors).toHaveLength(0); + }); + + it(`should work with locals and invalidate cache when emit option is "false"`, async () => { + const modifyAsset = path.resolve(__dirname, 'fixtures', 'locals/index.css'); + const modifyAssetContent = fs.readFileSync(modifyAsset); + + class AssetsModifyPlugin { + constructor(options = {}) { + this.options = options; + } + + apply(compiler) { + compiler.hooks.emit.tapAsync( + 'AssetsModifyPlugin', + (compilation, callback) => { + const newContent = modifyAssetContent + .toString() + .replace(/foo/i, 'foo-bar'); + fs.writeFileSync(this.options.file, newContent); + + callback(); + } + ); + } + } + + if (webpack.version[0] !== '4') { + const outputPath = path.resolve(__dirname, './js/cache-memory'); + const webpackConfig = { + mode: 'development', + context: path.resolve(__dirname, './fixtures'), + cache: { + type: 'memory', + }, + entry: './locals.js', + output: { + publicPath: '', + path: outputPath, + }, + module: { + rules: [ + { + test: /\.css$/, + use: [ + { + loader: MiniCssExtractPlugin.loader, + options: { + emit: false, + }, + }, + { + loader: 'css-loader', + options: { + modules: true, + }, + }, + ], + }, + ], + }, + plugins: [ + new MiniCssExtractPlugin({ + filename: '[name].css', + }), + new AssetsModifyPlugin({ + file: modifyAsset, + }), + ], + }; + + await del([outputPath]); + + const compiler1 = webpack(webpackConfig); + + await new Promise((resolve, reject) => { + compiler1.run((error, stats) => { + if (error) { + reject(error); + + return; + } + + compiler1.close(() => { + expect(Object.keys(stats.compilation.assets).sort()) + .toMatchInlineSnapshot(` + Array [ + "main.js", + ] + `); + expect(Array.from(stats.compilation.emittedAssets).sort()) + .toMatchInlineSnapshot(` + Array [ + "main.js", + ] + `); + runInJsDom('main.js', compiler1, stats, (dom) => { + expect(dom.serialize()).toMatchSnapshot('DOM'); + }); + expect(stats.compilation.warnings).toHaveLength(0); + expect(stats.compilation.errors).toHaveLength(0); + + resolve(); + }); + }); + }); + + const compiler2 = webpack(webpackConfig); + + await new Promise((resolve, reject) => { + compiler2.run((error, stats) => { + if (error) { + reject(error); + + return; + } + + compiler2.close(() => { + expect(Object.keys(stats.compilation.assets).sort()) + .toMatchInlineSnapshot(` + Array [ + "main.js", + ] + `); + expect(Array.from(stats.compilation.emittedAssets).sort()) + .toMatchInlineSnapshot(` + Array [ + "main.js", + ] + `); + runInJsDom('main.js', compiler2, stats, (dom) => { + expect(dom.serialize()).toMatchSnapshot('DOM'); + }); + expect(stats.compilation.warnings).toHaveLength(0); + expect(stats.compilation.errors).toHaveLength(0); + + resolve(); + }); + }); + }); + + fs.writeFileSync(modifyAsset, modifyAssetContent); + } else { + expect(true).toBe(true); + } + }); + + it('should work with the "memory" cache and disabled "emit" option', async () => { + if (webpack.version[0] !== '4') { + const outputPath = path.resolve(__dirname, './js/cache-memory'); + const webpackConfig = { + mode: 'development', + context: path.resolve(__dirname, 'fixtures'), + cache: { + type: 'memory', + }, + output: { + path: outputPath, + }, + entry: './style-url.js', + module: { + rules: [ + { + test: /\.css$/, + use: [ + { + loader: MiniCssExtractPlugin.loader, + options: { + publicPath: '', + emit: false, + }, + }, + 'css-loader', + ], + }, + { + test: /\.svg$/, + type: 'asset/resource', + generator: { + filename: 'static/[name][ext][query]', + }, + }, + ], + }, + plugins: [ + new MiniCssExtractPlugin({ + filename: '[name].css', + }), + ], + }; + + await del([outputPath]); + + const compiler1 = webpack(webpackConfig); + + await new Promise((resolve, reject) => { + compiler1.run((error, stats) => { + if (error) { + reject(error); + + return; + } + + compiler1.close(() => { + expect(Object.keys(stats.compilation.assets).sort()) + .toMatchInlineSnapshot(` + Array [ + "main.js", + "static/react.svg", + ] + `); + expect(Array.from(stats.compilation.emittedAssets).sort()) + .toMatchInlineSnapshot(` + Array [ + "main.js", + "static/react.svg", + ] + `); + expect(stats.compilation.warnings).toHaveLength(0); + expect(stats.compilation.errors).toHaveLength(0); + + resolve(); + }); + }); + }); + + const compiler2 = webpack(webpackConfig); + + await new Promise((resolve, reject) => { + compiler2.run((error, stats) => { + if (error) { + reject(error); + + return; + } + + compiler2.close(() => { + expect(Object.keys(stats.compilation.assets).sort()) + .toMatchInlineSnapshot(` + Array [ + "main.js", + "static/react.svg", + ] + `); + expect( + Array.from(stats.compilation.emittedAssets).sort() + ).toMatchInlineSnapshot(`Array []`); + expect(stats.compilation.warnings).toHaveLength(0); + expect(stats.compilation.errors).toHaveLength(0); + + resolve(); + }); + }); + }); + } else { + expect(true).toBe(true); + } + }); + + it('should invalidate the cache with disabled "emit" option', async () => { + class AssetsModifyPlugin { + constructor(options = {}) { + this.options = options; + } + + apply(compiler) { + compiler.hooks.emit.tapAsync( + 'AssetsModifyPlugin', + (compilation, callback) => { + fs.writeFileSync(this.options.file, `.a{color: red;}`); + + callback(); + } + ); + } + } + + if (webpack.version[0] !== '4') { + const outputPath = path.resolve(__dirname, './js/cache-memory'); + const modifyAsset = path.resolve(__dirname, 'fixtures', 'style-url.css'); + const modifyAssetContent = fs.readFileSync(modifyAsset); + const webpackConfig = { + mode: 'development', + context: path.resolve(__dirname, 'fixtures'), + cache: { + type: 'memory', + }, + output: { + path: outputPath, + }, + entry: './style-url.js', + module: { + rules: [ + { + test: /\.css$/, + use: [ + { + loader: MiniCssExtractPlugin.loader, + options: { + publicPath: '', + emit: false, + }, + }, + 'css-loader', + ], + }, + { + test: /\.svg$/, + type: 'asset/resource', + generator: { + filename: 'static/[name][ext][query]', + }, + }, + ], + }, + plugins: [ + new MiniCssExtractPlugin({ + filename: '[name].css', + }), + new AssetsModifyPlugin({ + file: modifyAsset, + }), + ], + }; + + await del([outputPath]); + + const compiler1 = webpack(webpackConfig); + + await new Promise((resolve, reject) => { + compiler1.run((error, stats) => { + if (error) { + reject(error); + + return; + } + + compiler1.close(() => { + expect(Object.keys(stats.compilation.assets).sort()) + .toMatchInlineSnapshot(` + Array [ + "main.js", + "static/react.svg", + ] + `); + expect(Array.from(stats.compilation.emittedAssets).sort()) + .toMatchInlineSnapshot(` + Array [ + "main.js", + "static/react.svg", + ] + `); + expect(stats.compilation.warnings).toHaveLength(0); + expect(stats.compilation.errors).toHaveLength(0); + + resolve(); + }); + }); + }); + + const compiler2 = webpack(webpackConfig); + + await new Promise((resolve, reject) => { + compiler2.run((error, stats) => { + if (error) { + reject(error); + + return; + } + + compiler2.close(() => { + expect(Object.keys(stats.compilation.assets).sort()) + .toMatchInlineSnapshot(` + Array [ + "main.js", + ] + `); + expect( + Array.from(stats.compilation.emittedAssets).sort() + ).toMatchInlineSnapshot(`Array []`); + expect(stats.compilation.warnings).toHaveLength(0); + expect(stats.compilation.errors).toHaveLength(0); + + resolve(); + }); + }); + }); + + fs.writeFileSync(modifyAsset, modifyAssetContent); + } else { + expect(true).toBe(true); + } + }); +}); diff --git a/test/fixtures/locals.js b/test/fixtures/locals.js new file mode 100644 index 00000000..bbc09b2f --- /dev/null +++ b/test/fixtures/locals.js @@ -0,0 +1,4 @@ +import './locals/index.css'; +import html from './locals/template.js'; + +document.body.textContent = html; diff --git a/test/fixtures/locals/index.css b/test/fixtures/locals/index.css new file mode 100644 index 00000000..61760a22 --- /dev/null +++ b/test/fixtures/locals/index.css @@ -0,0 +1,11 @@ +.foo { + color: red; +} + +.bar { + color: coral; +} + +.baz { + color: blue; +} diff --git a/test/fixtures/locals/template.js b/test/fixtures/locals/template.js new file mode 100644 index 00000000..ee01804c --- /dev/null +++ b/test/fixtures/locals/template.js @@ -0,0 +1,9 @@ +import css from './index.css'; + +let html = '\n'; + +for (const key in css) { + html += `css.${key}: ${css[key]}\n`; +} + +export default html; diff --git a/test/fixtures/react.svg b/test/fixtures/react.svg new file mode 100644 index 00000000..5b3b22a4 --- /dev/null +++ b/test/fixtures/react.svg @@ -0,0 +1 @@ +logo-on-dark-bg \ No newline at end of file diff --git a/test/fixtures/style-url.css b/test/fixtures/style-url.css new file mode 100644 index 00000000..52c2b3e4 --- /dev/null +++ b/test/fixtures/style-url.css @@ -0,0 +1,4 @@ +body { + background: red; + background-image: url(./react.svg); +} diff --git a/test/fixtures/style-url.js b/test/fixtures/style-url.js new file mode 100644 index 00000000..7ee6cb6a --- /dev/null +++ b/test/fixtures/style-url.js @@ -0,0 +1 @@ +import './style-url.css'; diff --git a/test/helpers/getCompiler.js b/test/helpers/getCompiler.js index 9283da6f..48a1495c 100644 --- a/test/helpers/getCompiler.js +++ b/test/helpers/getCompiler.js @@ -32,6 +32,13 @@ export default (fixture, loaderOptions = {}, config = {}) => { }, ], }, + { + test: /\.svg$/, + type: 'asset/resource', + generator: { + filename: '[name][ext]', + }, + }, ], }, plugins: [ From 00f75d3535fce141ce7f7e8960b8a1a09f6f635d Mon Sep 17 00:00:00 2001 From: cap-Bernardito Date: Fri, 26 Mar 2021 19:59:12 +0300 Subject: [PATCH 2/2] test: update --- jest.config.js | 1 + ...test.js.snap => HMR.test.js.snap.webpack4} | 0 test/__snapshots__/HMR.test.js.snap.webpack5 | 43 +++++ ...> attributes-option.test.js.snap.webpack4} | 0 .../attributes-option.test.js.snap.webpack5 | 37 ++++ test/__snapshots__/emit-option.test.js.snap | 37 ---- .../emit-option.test.js.snap.webpack4 | 52 ++++++ .../emit-option.test.js.snap.webpack5 | 169 +++++++++++++++++ ...ap => insert-option.test.js.snap.webpack4} | 0 .../insert-option.test.js.snap.webpack5 | 55 ++++++ ...p => linkTag-option.test.js.snap.webpack4} | 0 .../linkTag-option.test.js.snap.webpack5 | 55 ++++++ ...date-loader-options.test.js.snap.webpack4} | 0 ...idate-loader-options.test.js.snap.webpack5 | 75 ++++++++ ...date-plugin-options.test.js.snap.webpack4} | 0 ...idate-plugin-options.test.js.snap.webpack5 | 145 +++++++++++++++ test/emit-option.test.js | 171 +++++++----------- test/helpers/getCompiler.js | 31 +++- test/helpers/snapshotResolver.js | 28 +++ 19 files changed, 751 insertions(+), 148 deletions(-) rename test/__snapshots__/{HMR.test.js.snap => HMR.test.js.snap.webpack4} (100%) create mode 100644 test/__snapshots__/HMR.test.js.snap.webpack5 rename test/__snapshots__/{attributes-option.test.js.snap => attributes-option.test.js.snap.webpack4} (100%) create mode 100644 test/__snapshots__/attributes-option.test.js.snap.webpack5 delete mode 100644 test/__snapshots__/emit-option.test.js.snap create mode 100644 test/__snapshots__/emit-option.test.js.snap.webpack4 create mode 100644 test/__snapshots__/emit-option.test.js.snap.webpack5 rename test/__snapshots__/{insert-option.test.js.snap => insert-option.test.js.snap.webpack4} (100%) create mode 100644 test/__snapshots__/insert-option.test.js.snap.webpack5 rename test/__snapshots__/{linkTag-option.test.js.snap => linkTag-option.test.js.snap.webpack4} (100%) create mode 100644 test/__snapshots__/linkTag-option.test.js.snap.webpack5 rename test/__snapshots__/{validate-loader-options.test.js.snap => validate-loader-options.test.js.snap.webpack4} (100%) create mode 100644 test/__snapshots__/validate-loader-options.test.js.snap.webpack5 rename test/__snapshots__/{validate-plugin-options.test.js.snap => validate-plugin-options.test.js.snap.webpack4} (100%) create mode 100644 test/__snapshots__/validate-plugin-options.test.js.snap.webpack5 create mode 100644 test/helpers/snapshotResolver.js diff --git a/jest.config.js b/jest.config.js index 9d9cc847..0cff348b 100644 --- a/jest.config.js +++ b/jest.config.js @@ -3,4 +3,5 @@ module.exports = { transformIgnorePatterns: ['/node_modules/', '/dist/'], watchPathIgnorePatterns: ['/test/js'], setupFilesAfterEnv: ['/setupTest.js'], + snapshotResolver: './test/helpers/snapshotResolver.js', }; diff --git a/test/__snapshots__/HMR.test.js.snap b/test/__snapshots__/HMR.test.js.snap.webpack4 similarity index 100% rename from test/__snapshots__/HMR.test.js.snap rename to test/__snapshots__/HMR.test.js.snap.webpack4 diff --git a/test/__snapshots__/HMR.test.js.snap.webpack5 b/test/__snapshots__/HMR.test.js.snap.webpack5 new file mode 100644 index 00000000..bf306c32 --- /dev/null +++ b/test/__snapshots__/HMR.test.js.snap.webpack5 @@ -0,0 +1,43 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`HMR should handle error event 1`] = `"[HMR] css reload %s"`; + +exports[`HMR should handle error event 2`] = `""`; + +exports[`HMR should reloads with # link href 1`] = `"[HMR] css reload %s"`; + +exports[`HMR should reloads with # link href 2`] = `""`; + +exports[`HMR should reloads with absolute remove url 1`] = `"[HMR] css reload %s"`; + +exports[`HMR should reloads with absolute remove url 2`] = `""`; + +exports[`HMR should reloads with link without href 1`] = `"[HMR] css reload %s"`; + +exports[`HMR should reloads with link without href 2`] = `""`; + +exports[`HMR should reloads with locals 1`] = `"[HMR] Detected local css modules. Reload all css"`; + +exports[`HMR should reloads with locals 2`] = `""`; + +exports[`HMR should reloads with non http/https link href 1`] = `"[HMR] css reload %s"`; + +exports[`HMR should reloads with non http/https link href 2`] = `""`; + +exports[`HMR should reloads with non-file script in the end of page 1`] = `"[HMR] Reload all css"`; + +exports[`HMR should reloads with non-file script in the end of page 2`] = `""`; + +exports[`HMR should work reload all css 1`] = `"[HMR] Reload all css"`; + +exports[`HMR should work reload all css 2`] = `""`; + +exports[`HMR should works 1`] = `"[HMR] css reload %s"`; + +exports[`HMR should works 2`] = `""`; + +exports[`HMR should works with multiple updates 1`] = `"[HMR] css reload %s"`; + +exports[`HMR should works with multiple updates 2`] = `""`; + +exports[`HMR should works with multiple updates 3`] = `""`; diff --git a/test/__snapshots__/attributes-option.test.js.snap b/test/__snapshots__/attributes-option.test.js.snap.webpack4 similarity index 100% rename from test/__snapshots__/attributes-option.test.js.snap rename to test/__snapshots__/attributes-option.test.js.snap.webpack4 diff --git a/test/__snapshots__/attributes-option.test.js.snap.webpack5 b/test/__snapshots__/attributes-option.test.js.snap.webpack5 new file mode 100644 index 00000000..84007ca0 --- /dev/null +++ b/test/__snapshots__/attributes-option.test.js.snap.webpack5 @@ -0,0 +1,37 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`attributes option should work with attributes option: DOM 1`] = ` +" + style-loader test + + + +

Body

+
+ + + +" +`; + +exports[`attributes option should work with attributes option: errors 1`] = `Array []`; + +exports[`attributes option should work with attributes option: warnings 1`] = `Array []`; + +exports[`attributes option should work without attributes option: DOM 1`] = ` +" + style-loader test + + + +

Body

+
+ + + +" +`; + +exports[`attributes option should work without attributes option: errors 1`] = `Array []`; + +exports[`attributes option should work without attributes option: warnings 1`] = `Array []`; diff --git a/test/__snapshots__/emit-option.test.js.snap b/test/__snapshots__/emit-option.test.js.snap deleted file mode 100644 index 0f2bce87..00000000 --- a/test/__snapshots__/emit-option.test.js.snap +++ /dev/null @@ -1,37 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`emit option should work with locals and invalidate cache when emit option is "false": DOM 1`] = ` -" - style-loader test - - - -css.foo: _1F17fUrdX_cbcyDHpFqmAD -css.bar: _3TZVxmkrZR2cTfifKhDoZn -css.baz: M-pzkE59YBii7EXzFyxE6 -" -`; - -exports[`emit option should work with locals and invalidate cache when emit option is "false": DOM 2`] = ` -" - style-loader test - - - -css.foo-bar: VWLDg_rByGM4Rdhz5T3Ns -css.bar: _3TZVxmkrZR2cTfifKhDoZn -css.baz: M-pzkE59YBii7EXzFyxE6 -" -`; - -exports[`emit option should work with locals when emit option is "false": DOM 1`] = ` -" - style-loader test - - - -css.foo: _1F17fUrdX_cbcyDHpFqmAD -css.bar: _3TZVxmkrZR2cTfifKhDoZn -css.baz: M-pzkE59YBii7EXzFyxE6 -" -`; diff --git a/test/__snapshots__/emit-option.test.js.snap.webpack4 b/test/__snapshots__/emit-option.test.js.snap.webpack4 new file mode 100644 index 00000000..6608229e --- /dev/null +++ b/test/__snapshots__/emit-option.test.js.snap.webpack4 @@ -0,0 +1,52 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`emit option should work when emit option is "false": assets 1`] = ` +Array [ + "main.js", + "react.svg", +] +`; + +exports[`emit option should work when emit option is "false": errors 1`] = `Array []`; + +exports[`emit option should work when emit option is "false": warnings 1`] = `Array []`; + +exports[`emit option should work when emit option is "true": assets 1`] = ` +Array [ + "main.css", + "main.js", + "react.svg", +] +`; + +exports[`emit option should work when emit option is "true": errors 1`] = `Array []`; + +exports[`emit option should work when emit option is "true": warnings 1`] = `Array []`; + +exports[`emit option should work with locals when emit option is "false": DOM 1`] = ` +" + style-loader test + + + +css.foo: _1F17fUrdX_cbcyDHpFqmAD +css.bar: _3TZVxmkrZR2cTfifKhDoZn +css.baz: M-pzkE59YBii7EXzFyxE6 +" +`; + +exports[`emit option should work with locals when emit option is "false": errors 1`] = `Array []`; + +exports[`emit option should work with locals when emit option is "false": warnings 1`] = `Array []`; + +exports[`emit option should work without emit option: assets 1`] = ` +Array [ + "main.bundle.js", + "main.css", + "react.svg", +] +`; + +exports[`emit option should work without emit option: errors 1`] = `Array []`; + +exports[`emit option should work without emit option: warnings 1`] = `Array []`; diff --git a/test/__snapshots__/emit-option.test.js.snap.webpack5 b/test/__snapshots__/emit-option.test.js.snap.webpack5 new file mode 100644 index 00000000..38790a4a --- /dev/null +++ b/test/__snapshots__/emit-option.test.js.snap.webpack5 @@ -0,0 +1,169 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`emit option should invalidate the cache with disabled "emit" option: assets 1`] = ` +Array [ + "main.js", + "static/react.svg", +] +`; + +exports[`emit option should invalidate the cache with disabled "emit" option: assets 2`] = ` +Array [ + "main.js", +] +`; + +exports[`emit option should invalidate the cache with disabled "emit" option: emittedAssets 1`] = ` +Array [ + "main.js", + "static/react.svg", +] +`; + +exports[`emit option should invalidate the cache with disabled "emit" option: emittedAssets 2`] = `Array []`; + +exports[`emit option should invalidate the cache with disabled "emit" option: errors 1`] = `Array []`; + +exports[`emit option should invalidate the cache with disabled "emit" option: errors 2`] = `Array []`; + +exports[`emit option should invalidate the cache with disabled "emit" option: warnings 1`] = `Array []`; + +exports[`emit option should invalidate the cache with disabled "emit" option: warnings 2`] = `Array []`; + +exports[`emit option should work when emit option is "false": assets 1`] = ` +Array [ + "main.js", + "react.svg", +] +`; + +exports[`emit option should work when emit option is "false": errors 1`] = `Array []`; + +exports[`emit option should work when emit option is "false": warnings 1`] = `Array []`; + +exports[`emit option should work when emit option is "true": assets 1`] = ` +Array [ + "main.css", + "main.js", + "react.svg", +] +`; + +exports[`emit option should work when emit option is "true": errors 1`] = `Array []`; + +exports[`emit option should work when emit option is "true": warnings 1`] = `Array []`; + +exports[`emit option should work with locals and invalidate cache when emit option is "false": DOM 1`] = ` +" + style-loader test + + + +css.foo: _1F17fUrdX_cbcyDHpFqmAD +css.bar: _3TZVxmkrZR2cTfifKhDoZn +css.baz: M-pzkE59YBii7EXzFyxE6 +" +`; + +exports[`emit option should work with locals and invalidate cache when emit option is "false": DOM 2`] = ` +" + style-loader test + + + +css.foo-bar: VWLDg_rByGM4Rdhz5T3Ns +css.bar: _3TZVxmkrZR2cTfifKhDoZn +css.baz: M-pzkE59YBii7EXzFyxE6 +" +`; + +exports[`emit option should work with locals and invalidate cache when emit option is "false": assets 1`] = ` +Array [ + "main.js", +] +`; + +exports[`emit option should work with locals and invalidate cache when emit option is "false": assets 2`] = ` +Array [ + "main.js", +] +`; + +exports[`emit option should work with locals and invalidate cache when emit option is "false": emittedAssets 1`] = ` +Array [ + "main.js", +] +`; + +exports[`emit option should work with locals and invalidate cache when emit option is "false": emittedAssets 2`] = ` +Array [ + "main.js", +] +`; + +exports[`emit option should work with locals and invalidate cache when emit option is "false": errors 1`] = `Array []`; + +exports[`emit option should work with locals and invalidate cache when emit option is "false": errors 2`] = `Array []`; + +exports[`emit option should work with locals and invalidate cache when emit option is "false": warnings 1`] = `Array []`; + +exports[`emit option should work with locals and invalidate cache when emit option is "false": warnings 2`] = `Array []`; + +exports[`emit option should work with locals when emit option is "false": DOM 1`] = ` +" + style-loader test + + + +css.foo: _1F17fUrdX_cbcyDHpFqmAD +css.bar: _3TZVxmkrZR2cTfifKhDoZn +css.baz: M-pzkE59YBii7EXzFyxE6 +" +`; + +exports[`emit option should work with locals when emit option is "false": errors 1`] = `Array []`; + +exports[`emit option should work with locals when emit option is "false": warnings 1`] = `Array []`; + +exports[`emit option should work with the "memory" cache and disabled "emit" option: assets 1`] = ` +Array [ + "main.js", + "static/react.svg", +] +`; + +exports[`emit option should work with the "memory" cache and disabled "emit" option: assets 2`] = ` +Array [ + "main.js", + "static/react.svg", +] +`; + +exports[`emit option should work with the "memory" cache and disabled "emit" option: emittedAssets 1`] = ` +Array [ + "main.js", + "static/react.svg", +] +`; + +exports[`emit option should work with the "memory" cache and disabled "emit" option: emittedAssets 2`] = `Array []`; + +exports[`emit option should work with the "memory" cache and disabled "emit" option: errors 1`] = `Array []`; + +exports[`emit option should work with the "memory" cache and disabled "emit" option: errors 2`] = `Array []`; + +exports[`emit option should work with the "memory" cache and disabled "emit" option: warnings 1`] = `Array []`; + +exports[`emit option should work with the "memory" cache and disabled "emit" option: warnings 2`] = `Array []`; + +exports[`emit option should work without emit option: assets 1`] = ` +Array [ + "main.bundle.js", + "main.css", + "react.svg", +] +`; + +exports[`emit option should work without emit option: errors 1`] = `Array []`; + +exports[`emit option should work without emit option: warnings 1`] = `Array []`; diff --git a/test/__snapshots__/insert-option.test.js.snap b/test/__snapshots__/insert-option.test.js.snap.webpack4 similarity index 100% rename from test/__snapshots__/insert-option.test.js.snap rename to test/__snapshots__/insert-option.test.js.snap.webpack4 diff --git a/test/__snapshots__/insert-option.test.js.snap.webpack5 b/test/__snapshots__/insert-option.test.js.snap.webpack5 new file mode 100644 index 00000000..1e8530eb --- /dev/null +++ b/test/__snapshots__/insert-option.test.js.snap.webpack5 @@ -0,0 +1,55 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`insert option should work when insert option is function: DOM 1`] = ` +" + style-loader test + + + +

Body

+
+ + + +" +`; + +exports[`insert option should work when insert option is function: errors 1`] = `Array []`; + +exports[`insert option should work when insert option is function: warnings 1`] = `Array []`; + +exports[`insert option should work when insert option is string: DOM 1`] = ` +" + style-loader test + + + +

Body

+
+ + + +" +`; + +exports[`insert option should work when insert option is string: errors 1`] = `Array []`; + +exports[`insert option should work when insert option is string: warnings 1`] = `Array []`; + +exports[`insert option should work without insert option: DOM 1`] = ` +" + style-loader test + + + +

Body

+
+ + + +" +`; + +exports[`insert option should work without insert option: errors 1`] = `Array []`; + +exports[`insert option should work without insert option: warnings 1`] = `Array []`; diff --git a/test/__snapshots__/linkTag-option.test.js.snap b/test/__snapshots__/linkTag-option.test.js.snap.webpack4 similarity index 100% rename from test/__snapshots__/linkTag-option.test.js.snap rename to test/__snapshots__/linkTag-option.test.js.snap.webpack4 diff --git a/test/__snapshots__/linkTag-option.test.js.snap.webpack5 b/test/__snapshots__/linkTag-option.test.js.snap.webpack5 new file mode 100644 index 00000000..8a4e62d9 --- /dev/null +++ b/test/__snapshots__/linkTag-option.test.js.snap.webpack5 @@ -0,0 +1,55 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`linkType option should work when linkType option is "false": DOM 1`] = ` +" + style-loader test + + + +

Body

+
+ + + +" +`; + +exports[`linkType option should work when linkType option is "false": errors 1`] = `Array []`; + +exports[`linkType option should work when linkType option is "false": warnings 1`] = `Array []`; + +exports[`linkType option should work when linkType option is "text/css": DOM 1`] = ` +" + style-loader test + + + +

Body

+
+ + + +" +`; + +exports[`linkType option should work when linkType option is "text/css": errors 1`] = `Array []`; + +exports[`linkType option should work when linkType option is "text/css": warnings 1`] = `Array []`; + +exports[`linkType option should work without linkType option: DOM 1`] = ` +" + style-loader test + + + +

Body

+
+ + + +" +`; + +exports[`linkType option should work without linkType option: errors 1`] = `Array []`; + +exports[`linkType option should work without linkType option: warnings 1`] = `Array []`; diff --git a/test/__snapshots__/validate-loader-options.test.js.snap b/test/__snapshots__/validate-loader-options.test.js.snap.webpack4 similarity index 100% rename from test/__snapshots__/validate-loader-options.test.js.snap rename to test/__snapshots__/validate-loader-options.test.js.snap.webpack4 diff --git a/test/__snapshots__/validate-loader-options.test.js.snap.webpack5 b/test/__snapshots__/validate-loader-options.test.js.snap.webpack5 new file mode 100644 index 00000000..a8a95996 --- /dev/null +++ b/test/__snapshots__/validate-loader-options.test.js.snap.webpack5 @@ -0,0 +1,75 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`validate options should throw an error on the "esModule" option with "1" value 1`] = ` +"Invalid options object. Mini CSS Extract Plugin Loader has been initialized using an options object that does not match the API schema. + - options.esModule should be a boolean." +`; + +exports[`validate options should throw an error on the "modules" option with "{"namedExport":"false"}" value 1`] = ` +"Invalid options object. Mini CSS Extract Plugin Loader has been initialized using an options object that does not match the API schema. + - options.modules.namedExport should be a boolean. + -> Enables/disables ES modules named export for locals (https://webpack.js.org/plugins/mini-css-extract-plugin/#namedexport)." +`; + +exports[`validate options should throw an error on the "modules" option with "true" value 1`] = ` +"Invalid options object. Mini CSS Extract Plugin Loader has been initialized using an options object that does not match the API schema. + - options.modules should be an object: + object { namedExport? }" +`; + +exports[`validate options should throw an error on the "publicPath" option with "true" value 1`] = ` +"Invalid options object. Mini CSS Extract Plugin Loader has been initialized using an options object that does not match the API schema. + - options.publicPath should be one of these: + string | function + Details: + * options.publicPath should be a string. + * options.publicPath should be an instance of function." +`; + +exports[`validate options should throw an error on the "unknown" option with "/test/" value 1`] = ` +"Invalid options object. Mini CSS Extract Plugin Loader has been initialized using an options object that does not match the API schema. + - options has an unknown property 'unknown'. These properties are valid: + object { publicPath?, emit?, esModule?, modules? }" +`; + +exports[`validate options should throw an error on the "unknown" option with "[]" value 1`] = ` +"Invalid options object. Mini CSS Extract Plugin Loader has been initialized using an options object that does not match the API schema. + - options has an unknown property 'unknown'. These properties are valid: + object { publicPath?, emit?, esModule?, modules? }" +`; + +exports[`validate options should throw an error on the "unknown" option with "{"foo":"bar"}" value 1`] = ` +"Invalid options object. Mini CSS Extract Plugin Loader has been initialized using an options object that does not match the API schema. + - options has an unknown property 'unknown'. These properties are valid: + object { publicPath?, emit?, esModule?, modules? }" +`; + +exports[`validate options should throw an error on the "unknown" option with "{}" value 1`] = ` +"Invalid options object. Mini CSS Extract Plugin Loader has been initialized using an options object that does not match the API schema. + - options has an unknown property 'unknown'. These properties are valid: + object { publicPath?, emit?, esModule?, modules? }" +`; + +exports[`validate options should throw an error on the "unknown" option with "1" value 1`] = ` +"Invalid options object. Mini CSS Extract Plugin Loader has been initialized using an options object that does not match the API schema. + - options has an unknown property 'unknown'. These properties are valid: + object { publicPath?, emit?, esModule?, modules? }" +`; + +exports[`validate options should throw an error on the "unknown" option with "false" value 1`] = ` +"Invalid options object. Mini CSS Extract Plugin Loader has been initialized using an options object that does not match the API schema. + - options has an unknown property 'unknown'. These properties are valid: + object { publicPath?, emit?, esModule?, modules? }" +`; + +exports[`validate options should throw an error on the "unknown" option with "test" value 1`] = ` +"Invalid options object. Mini CSS Extract Plugin Loader has been initialized using an options object that does not match the API schema. + - options has an unknown property 'unknown'. These properties are valid: + object { publicPath?, emit?, esModule?, modules? }" +`; + +exports[`validate options should throw an error on the "unknown" option with "true" value 1`] = ` +"Invalid options object. Mini CSS Extract Plugin Loader has been initialized using an options object that does not match the API schema. + - options has an unknown property 'unknown'. These properties are valid: + object { publicPath?, emit?, esModule?, modules? }" +`; diff --git a/test/__snapshots__/validate-plugin-options.test.js.snap b/test/__snapshots__/validate-plugin-options.test.js.snap.webpack4 similarity index 100% rename from test/__snapshots__/validate-plugin-options.test.js.snap rename to test/__snapshots__/validate-plugin-options.test.js.snap.webpack4 diff --git a/test/__snapshots__/validate-plugin-options.test.js.snap.webpack5 b/test/__snapshots__/validate-plugin-options.test.js.snap.webpack5 new file mode 100644 index 00000000..8d9e1b45 --- /dev/null +++ b/test/__snapshots__/validate-plugin-options.test.js.snap.webpack5 @@ -0,0 +1,145 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`validate options should throw an error on the "attributes" option with "true" value 1`] = ` +"Invalid options object. Mini CSS Extract Plugin has been initialized using an options object that does not match the API schema. + - options.attributes should be an object: + object { … } + -> Adds custom attributes to tag (https://github.com/webpack-contrib/mini-css-extract-plugin#attributes)." +`; + +exports[`validate options should throw an error on the "chunkFilename" option with "true" value 1`] = ` +"Invalid options object. Mini CSS Extract Plugin has been initialized using an options object that does not match the API schema. + - options.chunkFilename should be one of these: + string | function + Details: + * options.chunkFilename should be a string. + * options.chunkFilename should be an instance of function." +`; + +exports[`validate options should throw an error on the "filename" option with "true" value 1`] = ` +"Invalid options object. Mini CSS Extract Plugin has been initialized using an options object that does not match the API schema. + - options.filename should be one of these: + string | function + Details: + * options.filename should be a string. + * options.filename should be an instance of function." +`; + +exports[`validate options should throw an error on the "ignoreOrder" option with "1" value 1`] = ` +"Invalid options object. Mini CSS Extract Plugin has been initialized using an options object that does not match the API schema. + - options.ignoreOrder should be a boolean." +`; + +exports[`validate options should throw an error on the "insert" option with "{}" value 1`] = ` +"Invalid options object. Mini CSS Extract Plugin has been initialized using an options object that does not match the API schema. + - options.insert should be one of these: + string | function + -> Inserts \`\` at the given position (https://github.com/webpack-contrib/mini-css-extract-plugin#insert). + Details: + * options.insert should be a string. + * options.insert should be an instance of function." +`; + +exports[`validate options should throw an error on the "insert" option with "1" value 1`] = ` +"Invalid options object. Mini CSS Extract Plugin has been initialized using an options object that does not match the API schema. + - options.insert should be one of these: + string | function + -> Inserts \`\` at the given position (https://github.com/webpack-contrib/mini-css-extract-plugin#insert). + Details: + * options.insert should be a string. + * options.insert should be an instance of function." +`; + +exports[`validate options should throw an error on the "insert" option with "true" value 1`] = ` +"Invalid options object. Mini CSS Extract Plugin has been initialized using an options object that does not match the API schema. + - options.insert should be one of these: + string | function + -> Inserts \`\` at the given position (https://github.com/webpack-contrib/mini-css-extract-plugin#insert). + Details: + * options.insert should be a string. + * options.insert should be an instance of function." +`; + +exports[`validate options should throw an error on the "linkType" option with "[]" value 1`] = ` +"Invalid options object. Mini CSS Extract Plugin has been initialized using an options object that does not match the API schema. + - options.linkType should be one of these: + \\"text/css\\" | boolean + Details: + * options.linkType should be \\"text/css\\". + * options.linkType should be a boolean." +`; + +exports[`validate options should throw an error on the "linkType" option with "{}" value 1`] = ` +"Invalid options object. Mini CSS Extract Plugin has been initialized using an options object that does not match the API schema. + - options.linkType should be one of these: + \\"text/css\\" | boolean + Details: + * options.linkType should be \\"text/css\\". + * options.linkType should be a boolean." +`; + +exports[`validate options should throw an error on the "linkType" option with "1" value 1`] = ` +"Invalid options object. Mini CSS Extract Plugin has been initialized using an options object that does not match the API schema. + - options.linkType should be one of these: + \\"text/css\\" | boolean + Details: + * options.linkType should be \\"text/css\\". + * options.linkType should be a boolean." +`; + +exports[`validate options should throw an error on the "linkType" option with "invalid/type" value 1`] = ` +"Invalid options object. Mini CSS Extract Plugin has been initialized using an options object that does not match the API schema. + - options.linkType should be one of these: + \\"text/css\\" | boolean + Details: + * options.linkType should be \\"text/css\\". + * options.linkType should be a boolean." +`; + +exports[`validate options should throw an error on the "unknown" option with "/test/" value 1`] = ` +"Invalid options object. Mini CSS Extract Plugin has been initialized using an options object that does not match the API schema. + - options has an unknown property 'unknown'. These properties are valid: + object { filename?, chunkFilename?, ignoreOrder?, insert?, attributes?, linkType? }" +`; + +exports[`validate options should throw an error on the "unknown" option with "[]" value 1`] = ` +"Invalid options object. Mini CSS Extract Plugin has been initialized using an options object that does not match the API schema. + - options has an unknown property 'unknown'. These properties are valid: + object { filename?, chunkFilename?, ignoreOrder?, insert?, attributes?, linkType? }" +`; + +exports[`validate options should throw an error on the "unknown" option with "{"foo":"bar"}" value 1`] = ` +"Invalid options object. Mini CSS Extract Plugin has been initialized using an options object that does not match the API schema. + - options has an unknown property 'unknown'. These properties are valid: + object { filename?, chunkFilename?, ignoreOrder?, insert?, attributes?, linkType? }" +`; + +exports[`validate options should throw an error on the "unknown" option with "{}" value 1`] = ` +"Invalid options object. Mini CSS Extract Plugin has been initialized using an options object that does not match the API schema. + - options has an unknown property 'unknown'. These properties are valid: + object { filename?, chunkFilename?, ignoreOrder?, insert?, attributes?, linkType? }" +`; + +exports[`validate options should throw an error on the "unknown" option with "1" value 1`] = ` +"Invalid options object. Mini CSS Extract Plugin has been initialized using an options object that does not match the API schema. + - options has an unknown property 'unknown'. These properties are valid: + object { filename?, chunkFilename?, ignoreOrder?, insert?, attributes?, linkType? }" +`; + +exports[`validate options should throw an error on the "unknown" option with "false" value 1`] = ` +"Invalid options object. Mini CSS Extract Plugin has been initialized using an options object that does not match the API schema. + - options has an unknown property 'unknown'. These properties are valid: + object { filename?, chunkFilename?, ignoreOrder?, insert?, attributes?, linkType? }" +`; + +exports[`validate options should throw an error on the "unknown" option with "test" value 1`] = ` +"Invalid options object. Mini CSS Extract Plugin has been initialized using an options object that does not match the API schema. + - options has an unknown property 'unknown'. These properties are valid: + object { filename?, chunkFilename?, ignoreOrder?, insert?, attributes?, linkType? }" +`; + +exports[`validate options should throw an error on the "unknown" option with "true" value 1`] = ` +"Invalid options object. Mini CSS Extract Plugin has been initialized using an options object that does not match the API schema. + - options has an unknown property 'unknown'. These properties are valid: + object { filename?, chunkFilename?, ignoreOrder?, insert?, attributes?, linkType? }" +`; diff --git a/test/emit-option.test.js b/test/emit-option.test.js index 00c49011..6015dbbb 100644 --- a/test/emit-option.test.js +++ b/test/emit-option.test.js @@ -7,7 +7,13 @@ import del from 'del'; import MiniCssExtractPlugin from '../src'; -import { compile, getCompiler, runInJsDom } from './helpers/index'; +import { + compile, + getCompiler, + getErrors, + getWarnings, + runInJsDom, +} from './helpers/index'; describe('emit option', () => { it(`should work without emit option`, async () => { @@ -31,9 +37,11 @@ describe('emit option', () => { ); const stats = await compile(compiler); - expect(stats.compilation.getAsset('main.css')).toBeDefined(); - expect(stats.compilation.warnings).toHaveLength(0); - expect(stats.compilation.errors).toHaveLength(0); + expect(Object.keys(stats.compilation.assets).sort()).toMatchSnapshot( + 'assets' + ); + expect(getWarnings(stats)).toMatchSnapshot('warnings'); + expect(getErrors(stats)).toMatchSnapshot('errors'); }); it(`should work when emit option is "true"`, async () => { @@ -47,7 +55,6 @@ describe('emit option', () => { output: { publicPath: '', path: path.resolve(__dirname, '../outputs'), - filename: '[name].[contenthash].[fullhash].js', }, plugins: [ @@ -59,14 +66,11 @@ describe('emit option', () => { ); const stats = await compile(compiler); - expect( - stats.compilation.getAsset( - 'main.9a73ed992e802ad0462e.5e3448a6abbe6ad89a93.js' - ) - ).toBeDefined(); - expect(stats.compilation.getAsset('main.css')).toBeDefined(); - expect(stats.compilation.warnings).toHaveLength(0); - expect(stats.compilation.errors).toHaveLength(0); + expect(Object.keys(stats.compilation.assets).sort()).toMatchSnapshot( + 'assets' + ); + expect(getWarnings(stats)).toMatchSnapshot('warnings'); + expect(getErrors(stats)).toMatchSnapshot('errors'); }); it(`should work when emit option is "false"`, async () => { @@ -80,7 +84,6 @@ describe('emit option', () => { output: { publicPath: '', path: path.resolve(__dirname, '../outputs'), - filename: '[name].[contenthash].[fullhash].js', }, plugins: [ new MiniCssExtractPlugin({ @@ -91,14 +94,11 @@ describe('emit option', () => { ); const stats = await compile(compiler); - expect(stats.compilation.getAsset('main.css')).toBeUndefined(); - expect( - stats.compilation.getAsset( - 'main.15f4ba3ceaa4de358bed.0df63dd1b4a35fa4358d.js' - ) - ).toBeDefined(); - expect(stats.compilation.warnings).toHaveLength(0); - expect(stats.compilation.errors).toHaveLength(0); + expect(Object.keys(stats.compilation.assets).sort()).toMatchSnapshot( + 'assets' + ); + expect(getWarnings(stats)).toMatchSnapshot('warnings'); + expect(getErrors(stats)).toMatchSnapshot('errors'); }); it(`should work with locals when emit option is "false"`, async () => { @@ -144,8 +144,8 @@ describe('emit option', () => { runInJsDom('main.bundle.js', compiler, stats, (dom) => { expect(dom.serialize()).toMatchSnapshot('DOM'); }); - expect(stats.compilation.warnings).toHaveLength(0); - expect(stats.compilation.errors).toHaveLength(0); + expect(getWarnings(stats)).toMatchSnapshot('warnings'); + expect(getErrors(stats)).toMatchSnapshot('errors'); }); it(`should work with locals and invalidate cache when emit option is "false"`, async () => { @@ -229,23 +229,17 @@ describe('emit option', () => { } compiler1.close(() => { - expect(Object.keys(stats.compilation.assets).sort()) - .toMatchInlineSnapshot(` - Array [ - "main.js", - ] - `); - expect(Array.from(stats.compilation.emittedAssets).sort()) - .toMatchInlineSnapshot(` - Array [ - "main.js", - ] - `); + expect( + Object.keys(stats.compilation.assets).sort() + ).toMatchSnapshot(`assets`); + expect( + Array.from(stats.compilation.emittedAssets).sort() + ).toMatchSnapshot(`emittedAssets`); runInJsDom('main.js', compiler1, stats, (dom) => { expect(dom.serialize()).toMatchSnapshot('DOM'); }); - expect(stats.compilation.warnings).toHaveLength(0); - expect(stats.compilation.errors).toHaveLength(0); + expect(getWarnings(stats)).toMatchSnapshot('warnings'); + expect(getErrors(stats)).toMatchSnapshot('errors'); resolve(); }); @@ -263,23 +257,17 @@ describe('emit option', () => { } compiler2.close(() => { - expect(Object.keys(stats.compilation.assets).sort()) - .toMatchInlineSnapshot(` - Array [ - "main.js", - ] - `); - expect(Array.from(stats.compilation.emittedAssets).sort()) - .toMatchInlineSnapshot(` - Array [ - "main.js", - ] - `); + expect( + Object.keys(stats.compilation.assets).sort() + ).toMatchSnapshot(`assets`); + expect( + Array.from(stats.compilation.emittedAssets).sort() + ).toMatchSnapshot(`emittedAssets`); runInJsDom('main.js', compiler2, stats, (dom) => { expect(dom.serialize()).toMatchSnapshot('DOM'); }); - expect(stats.compilation.warnings).toHaveLength(0); - expect(stats.compilation.errors).toHaveLength(0); + expect(getWarnings(stats)).toMatchSnapshot('warnings'); + expect(getErrors(stats)).toMatchSnapshot('errors'); resolve(); }); @@ -349,22 +337,14 @@ describe('emit option', () => { } compiler1.close(() => { - expect(Object.keys(stats.compilation.assets).sort()) - .toMatchInlineSnapshot(` - Array [ - "main.js", - "static/react.svg", - ] - `); - expect(Array.from(stats.compilation.emittedAssets).sort()) - .toMatchInlineSnapshot(` - Array [ - "main.js", - "static/react.svg", - ] - `); - expect(stats.compilation.warnings).toHaveLength(0); - expect(stats.compilation.errors).toHaveLength(0); + expect( + Object.keys(stats.compilation.assets).sort() + ).toMatchSnapshot(`assets`); + expect( + Array.from(stats.compilation.emittedAssets).sort() + ).toMatchSnapshot(`emittedAssets`); + expect(getWarnings(stats)).toMatchSnapshot('warnings'); + expect(getErrors(stats)).toMatchSnapshot('errors'); resolve(); }); @@ -382,18 +362,14 @@ describe('emit option', () => { } compiler2.close(() => { - expect(Object.keys(stats.compilation.assets).sort()) - .toMatchInlineSnapshot(` - Array [ - "main.js", - "static/react.svg", - ] - `); + expect( + Object.keys(stats.compilation.assets).sort() + ).toMatchSnapshot(`assets`); expect( Array.from(stats.compilation.emittedAssets).sort() - ).toMatchInlineSnapshot(`Array []`); - expect(stats.compilation.warnings).toHaveLength(0); - expect(stats.compilation.errors).toHaveLength(0); + ).toMatchSnapshot(`emittedAssets`); + expect(getWarnings(stats)).toMatchSnapshot('warnings'); + expect(getErrors(stats)).toMatchSnapshot('errors'); resolve(); }); @@ -483,22 +459,14 @@ describe('emit option', () => { } compiler1.close(() => { - expect(Object.keys(stats.compilation.assets).sort()) - .toMatchInlineSnapshot(` - Array [ - "main.js", - "static/react.svg", - ] - `); - expect(Array.from(stats.compilation.emittedAssets).sort()) - .toMatchInlineSnapshot(` - Array [ - "main.js", - "static/react.svg", - ] - `); - expect(stats.compilation.warnings).toHaveLength(0); - expect(stats.compilation.errors).toHaveLength(0); + expect( + Object.keys(stats.compilation.assets).sort() + ).toMatchSnapshot(`assets`); + expect( + Array.from(stats.compilation.emittedAssets).sort() + ).toMatchSnapshot(`emittedAssets`); + expect(getWarnings(stats)).toMatchSnapshot('warnings'); + expect(getErrors(stats)).toMatchSnapshot('errors'); resolve(); }); @@ -516,17 +484,14 @@ describe('emit option', () => { } compiler2.close(() => { - expect(Object.keys(stats.compilation.assets).sort()) - .toMatchInlineSnapshot(` - Array [ - "main.js", - ] - `); + expect( + Object.keys(stats.compilation.assets).sort() + ).toMatchSnapshot(`assets`); expect( Array.from(stats.compilation.emittedAssets).sort() - ).toMatchInlineSnapshot(`Array []`); - expect(stats.compilation.warnings).toHaveLength(0); - expect(stats.compilation.errors).toHaveLength(0); + ).toMatchSnapshot(`emittedAssets`); + expect(getWarnings(stats)).toMatchSnapshot('warnings'); + expect(getErrors(stats)).toMatchSnapshot('errors'); resolve(); }); diff --git a/test/helpers/getCompiler.js b/test/helpers/getCompiler.js index 48a1495c..0b4b03df 100644 --- a/test/helpers/getCompiler.js +++ b/test/helpers/getCompiler.js @@ -32,14 +32,29 @@ export default (fixture, loaderOptions = {}, config = {}) => { }, ], }, - { - test: /\.svg$/, - type: 'asset/resource', - generator: { - filename: '[name][ext]', - }, - }, - ], + ].concat( + webpack.version[0] !== '4' + ? { + test: /\.svg$/, + type: 'asset/resource', + generator: { + filename: '[name][ext]', + }, + } + : [ + { + test: /\.svg$/i, + rules: [ + { + loader: 'file-loader', + options: { + name: '[name].[ext]', + }, + }, + ], + }, + ] + ), }, plugins: [ new MiniCssExtractPlugin({ diff --git a/test/helpers/snapshotResolver.js b/test/helpers/snapshotResolver.js new file mode 100644 index 00000000..742ee5b6 --- /dev/null +++ b/test/helpers/snapshotResolver.js @@ -0,0 +1,28 @@ +const path = require('path'); + +const webpack = require('webpack'); + +// eslint-disable-next-line global-require +const [webpackVersion] = webpack.version; +const snapshotExtension = `.snap.webpack${webpackVersion}`; + +// eslint-disable-next-line no-console +console.log('Current webpack version:', webpackVersion); + +module.exports = { + resolveSnapshotPath: (testPath) => + path.join( + path.dirname(testPath), + '__snapshots__', + `${path.basename(testPath)}${snapshotExtension}` + ), + resolveTestPath: (snapshotPath) => + snapshotPath + .replace(`${path.sep}__snapshots__`, '') + .slice(0, -snapshotExtension.length), + testPathForConsistencyCheck: path.join( + 'consistency_check', + '__tests__', + 'example.test.js' + ), +};