diff --git a/README.md b/README.md index 21c112e0..a2d88c86 100644 --- a/README.md +++ b/README.md @@ -287,15 +287,19 @@ plugins: [ ### `Events` -To allow other [plugins](https://github.com/webpack/docs/wiki/plugins) to alter the HTML this plugin executes the following events: +To allow other [plugins](https://github.com/webpack/docs/wiki/plugins) to alter the HTML this plugin executes +[tapable](https://github.com/webpack/tapable/tree/master) hooks. -#### `AsyncSeriesWaterfallHook` +The [lib/hooks.js](https://github.com/jantimon/html-webpack-plugin/blob/master/lib/hooks.js) contains all information +about which values are passed. -* `htmlWebpackPluginBeforeHtmlGeneration` -* `htmlWebpackPluginBeforeHtmlProcessing` -* `htmlWebpackPluginAlterAssetTags` -* `htmlWebpackPluginAfterHtmlProcessing` -* `htmlWebpackPluginAfterEmit` +You can tap into the following async hooks: + +* `beforeHtmlGeneration` +* `beforeHtmlProcessing` +* `alterAssetTags` +* `afterHtmlProcessing` +* `afterEmit` Example implementation: [html-webpack-harddisk-plugin](https://github.com/jantimon/html-webpack-harddisk-plugin) @@ -308,8 +312,10 @@ function MyPlugin(options) { MyPlugin.prototype.apply = function (compiler) { compiler.hooks.compilation.tap('MyPlugin', (compilation) => { console.log('The compiler is starting a new compilation...'); - HtmlWebpackPlugin.getHooks(compilation).htmlWebpackPluginAfterHtmlProcessing.tapAsync( - 'MyPlugin', + + // | HOOK NAME | + HtmlWebpackPlugin.getHooks(compilation).afterHtmlProcessing.tapAsync( + 'MyPlugin', // <-- Set a meaningful name here for stacktraces (data, cb) => { data.html += 'The Magic Footer' diff --git a/examples/appcache/dist/webpack-4/manifest.appcache b/examples/appcache/dist/webpack-4/manifest.appcache index 3345da36..49b02bec 100644 --- a/examples/appcache/dist/webpack-4/manifest.appcache +++ b/examples/appcache/dist/webpack-4/manifest.appcache @@ -1,5 +1,5 @@ CACHE MANIFEST -# 95a89258cd32fe3f01e3 +# a351a7eb0665a7fa27b3 0714810ae3fb211173e2964249507195.png bundle.js diff --git a/examples/appcache/webpack.config.js b/examples/appcache/webpack.config.js index 1ff488e2..b1214f0f 100755 --- a/examples/appcache/webpack.config.js +++ b/examples/appcache/webpack.config.js @@ -13,8 +13,8 @@ module.exports = { filename: 'bundle.js' }, module: { - loaders: [ - { test: /\.css$/, loader: ExtractTextPlugin.extract('style-loader', 'css-loader') }, + rules: [ + { test: /\.css$/, loader: ExtractTextPlugin.extract({ fallback: 'style-loader', use: 'css-loader' }) }, { test: /\.png$/, loader: 'file-loader' }, { test: /\.html$/, loader: 'html-loader?-removeOptionalTags' } ] diff --git a/examples/build-examples.js b/examples/build-examples.js index f4f0f9cb..509e68f6 100644 --- a/examples/build-examples.js +++ b/examples/build-examples.js @@ -10,17 +10,6 @@ var fs = require('fs'); var path = require('path'); var rimraf = require('rimraf'); var webpack = require('webpack'); -var ExtractTextPlugin = require('extract-text-webpack-plugin'); - -if (Number(webpackMajorVersion) > 1) { - var extractOriginal = ExtractTextPlugin.extract; - ExtractTextPlugin.extract = function (fallback, use) { - return extractOriginal({ - fallback: fallback, - use: use - }); - }; -} var examples = fs.readdirSync(__dirname).filter(function (file) { return fs.statSync(path.join(__dirname, file)).isDirectory(); @@ -39,10 +28,6 @@ examples.forEach(function (exampleName) { })); config.mode = 'production'; config.optimization = { minimizer: [] }; - if (config.module && config.module.loaders) { - config.module.rules = config.module.loaders; - delete config.module.loaders; - } } rimraf.sync(path.join(examplePath, 'dist', 'webpack-' + webpackMajorVersion)); diff --git a/examples/custom-template/webpack.config.js b/examples/custom-template/webpack.config.js index ddfc3027..7d604271 100755 --- a/examples/custom-template/webpack.config.js +++ b/examples/custom-template/webpack.config.js @@ -12,8 +12,8 @@ module.exports = { filename: 'bundle.js' }, module: { - loaders: [ - { test: /\.css$/, loader: ExtractTextPlugin.extract('style-loader', 'css-loader') }, + rules: [ + { test: /\.css$/, loader: ExtractTextPlugin.extract({ fallback: 'style-loader', use: 'css-loader' }) }, { test: /\.png$/, loader: 'file-loader' } ] }, diff --git a/examples/default/webpack.config.js b/examples/default/webpack.config.js index fe86ecf7..6d5f9ae7 100755 --- a/examples/default/webpack.config.js +++ b/examples/default/webpack.config.js @@ -10,7 +10,7 @@ module.exports = { filename: 'bundle.js' }, module: { - loaders: [ + rules: [ { test: /\.css$/, loader: 'style-loader!css-loader' }, { test: /\.png$/, loader: 'file-loader' } ] diff --git a/examples/favicon/webpack.config.js b/examples/favicon/webpack.config.js index 43229eea..ed68241a 100755 --- a/examples/favicon/webpack.config.js +++ b/examples/favicon/webpack.config.js @@ -11,8 +11,8 @@ module.exports = { filename: 'bundle.js' }, module: { - loaders: [ - { test: /\.css$/, loader: ExtractTextPlugin.extract('style-loader', 'css-loader') }, + rules: [ + { test: /\.css$/, loader: ExtractTextPlugin.extract({ fallback: 'style-loader', use: 'css-loader' }) }, { test: /\.png$/, loader: 'file-loader' } ] }, diff --git a/examples/html-loader/webpack.config.js b/examples/html-loader/webpack.config.js index 7e0c7629..2958c6c7 100755 --- a/examples/html-loader/webpack.config.js +++ b/examples/html-loader/webpack.config.js @@ -11,8 +11,8 @@ module.exports = { filename: 'bundle.js' }, module: { - loaders: [ - { test: /\.css$/, loader: ExtractTextPlugin.extract('style-loader', 'css-loader') }, + rules: [ + { test: /\.css$/, loader: ExtractTextPlugin.extract({ fallback: 'style-loader', use: 'css-loader' }) }, { test: /\.png$/, loader: 'file-loader' }, { test: /\.html$/, loader: 'html-loader' } ] diff --git a/examples/inline/webpack.config.js b/examples/inline/webpack.config.js index 15cabfdb..f4328b10 100755 --- a/examples/inline/webpack.config.js +++ b/examples/inline/webpack.config.js @@ -12,8 +12,8 @@ module.exports = { filename: 'bundle.js' }, module: { - loaders: [ - { test: /\.css$/, loader: ExtractTextPlugin.extract('style-loader', 'css-loader') }, + rules: [ + { test: /\.css$/, loader: ExtractTextPlugin.extract({ fallback: 'style-loader', use: 'css-loader' }) }, { test: /\.jade$/, loader: 'jade-loader' } ] }, diff --git a/examples/jade-loader/dist/webpack-4/index.html b/examples/jade-loader/dist/webpack-4/index.html index 1cbcdf85..e720b253 100644 --- a/examples/jade-loader/dist/webpack-4/index.html +++ b/examples/jade-loader/dist/webpack-4/index.html @@ -1 +1 @@ -Jade demo
Current time

1999-01-01T05:00:00.000Z

\ No newline at end of file +Jade demo
Current time

1998-12-31T23:00:00.000Z

\ No newline at end of file diff --git a/examples/jade-loader/webpack.config.js b/examples/jade-loader/webpack.config.js index 26c0f66a..cf9d284e 100755 --- a/examples/jade-loader/webpack.config.js +++ b/examples/jade-loader/webpack.config.js @@ -11,8 +11,8 @@ module.exports = { filename: 'bundle.js' }, module: { - loaders: [ - { test: /\.css$/, loader: ExtractTextPlugin.extract('style-loader', 'css-loader') }, + rules: [ + { test: /\.css$/, loader: ExtractTextPlugin.extract({ fallback: 'style-loader', use: 'css-loader' }) }, { test: /\.png$/, loader: 'file-loader' }, { test: /\.jade$/, loader: 'jade-loader' } ] diff --git a/examples/javascript-advanced/webpack.config.js b/examples/javascript-advanced/webpack.config.js index d1d3d636..be24ecc2 100644 --- a/examples/javascript-advanced/webpack.config.js +++ b/examples/javascript-advanced/webpack.config.js @@ -11,8 +11,8 @@ module.exports = { filename: 'bundle.js' }, module: { - loaders: [ - { test: /\.css$/, loader: ExtractTextPlugin.extract('style-loader', 'css-loader') }, + rules: [ + { test: /\.css$/, loader: ExtractTextPlugin.extract({ fallback: 'style-loader', use: 'css-loader' }) }, { test: /\.png$/, loader: 'file-loader' }, { test: /\.html$/, loader: 'html-loader' } ] diff --git a/examples/javascript/dist/webpack-4/index.html b/examples/javascript/dist/webpack-4/index.html index 2d600e19..c273d21c 100644 --- a/examples/javascript/dist/webpack-4/index.html +++ b/examples/javascript/dist/webpack-4/index.html @@ -1,2 +1,2 @@ -Hello World from backend2018-02-14T04:00:28.077Z

Partial

+Hello World from backend2018-07-09T17:14:39.242Z

Partial

\ No newline at end of file diff --git a/examples/javascript/webpack.config.js b/examples/javascript/webpack.config.js index d1d3d636..be24ecc2 100644 --- a/examples/javascript/webpack.config.js +++ b/examples/javascript/webpack.config.js @@ -11,8 +11,8 @@ module.exports = { filename: 'bundle.js' }, module: { - loaders: [ - { test: /\.css$/, loader: ExtractTextPlugin.extract('style-loader', 'css-loader') }, + rules: [ + { test: /\.css$/, loader: ExtractTextPlugin.extract({ fallback: 'style-loader', use: 'css-loader' }) }, { test: /\.png$/, loader: 'file-loader' }, { test: /\.html$/, loader: 'html-loader' } ] diff --git a/examples/sort-manually/webpack.config.js b/examples/sort-manually/webpack.config.js index 98b0b186..6b01825d 100644 --- a/examples/sort-manually/webpack.config.js +++ b/examples/sort-manually/webpack.config.js @@ -17,8 +17,8 @@ module.exports = { filename: '[name].js' }, module: { - loaders: [ - { test: /\.css$/, loader: ExtractTextPlugin.extract('style-loader', 'css-loader') }, + rules: [ + { test: /\.css$/, loader: ExtractTextPlugin.extract({ fallback: 'style-loader', use: 'css-loader' }) }, { test: /\.png$/, loader: 'file-loader' }, { test: /\.html$/, loader: 'html-loader' } ] diff --git a/index.js b/index.js index 4a3e7fa8..e85f2d05 100644 --- a/index.js +++ b/index.js @@ -111,11 +111,11 @@ class HtmlWebpackPlugin { }); compiler.hooks.emit.tapAsync('HtmlWebpackPlugin', - /** - * Hook into the webpack emit phase - * @param {WebpackCompilation} compilation - * @param {() => void} callback - */ + /** + * Hook into the webpack emit phase + * @param {WebpackCompilation} compilation + * @param {() => void} callback + */ (compilation, callback) => { // Clear the childCompilerCache childCompiler.clearCache(compiler); @@ -156,7 +156,7 @@ class HtmlWebpackPlugin { }); } }) - // Wait for the compilation to finish + // Wait for the compilation to finish .then(() => compilationPromise) .then(compiledTemplate => { // Allow to use a custom function / string instead @@ -167,22 +167,22 @@ class HtmlWebpackPlugin { // and replace it with its content return self.evaluateCompilationResult(compilation, compiledTemplate); }) - // Allow plugins to make changes to the assets before invoking the template - // This only makes sense to use if `inject` is `false` - .then(compilationResult => getHtmlWebpackPluginHooks(compilation).htmlWebpackPluginBeforeHtmlGeneration.promise({ + // Allow plugins to make changes to the assets before invoking the template + // This only makes sense to use if `inject` is `false` + .then(compilationResult => getHtmlWebpackPluginHooks(compilation).beforeHtmlGeneration.promise({ assets: assets, outputName: self.childCompilationOutputName, plugin: self }) .then(() => compilationResult)) - // Execute the template + // Execute the template .then(compilationResult => typeof compilationResult !== 'function' ? compilationResult : self.executeTemplate(compilationResult, assets, compilation)) - // Allow plugins to change the html before assets are injected + // Allow plugins to change the html before assets are injected .then(html => { const pluginArgs = {html: html, assets: assets, plugin: self, outputName: self.childCompilationOutputName}; - return getHtmlWebpackPluginHooks(compilation).htmlWebpackPluginBeforeHtmlProcessing.promise(pluginArgs); + return getHtmlWebpackPluginHooks(compilation).beforeHtmlProcessing.promise(pluginArgs); }) .then(result => { const html = result.html; @@ -191,34 +191,34 @@ class HtmlWebpackPlugin { const assetTags = self.generateHtmlTagObjects(assets); const pluginArgs = {head: assetTags.head, body: assetTags.body, plugin: self, outputName: self.childCompilationOutputName}; // Allow plugins to change the assetTag definitions - return getHtmlWebpackPluginHooks(compilation).htmlWebpackPluginAlterAssetTags.promise(pluginArgs) + return getHtmlWebpackPluginHooks(compilation).alterAssetTags.promise(pluginArgs) .then(result => self.postProcessHtml(html, assets, { body: result.body, head: result.head }) .then(html => _.extend(result, {html: html, assets: assets}))); }) - // Allow plugins to change the html after assets are injected + // Allow plugins to change the html after assets are injected .then(result => { const html = result.html; const assets = result.assets; const pluginArgs = {html: html, assets: assets, plugin: self, outputName: self.childCompilationOutputName}; - return getHtmlWebpackPluginHooks(compilation).htmlWebpackPluginAfterHtmlProcessing.promise(pluginArgs) + return getHtmlWebpackPluginHooks(compilation).afterHtmlProcessing.promise(pluginArgs) .then(result => result.html); }) .catch(err => { - // In case anything went wrong the promise is resolved - // with the error message and an error is logged + // In case anything went wrong the promise is resolved + // with the error message and an error is logged compilation.errors.push(prettyError(err, compiler.context).toString()); // Prevent caching self.hash = null; return self.options.showErrors ? prettyError(err, compiler.context).toHtml() : 'ERROR'; }) .then(html => { - // Replace the compilation result with the evaluated html code + // Replace the compilation result with the evaluated html code compilation.assets[self.childCompilationOutputName] = { source: () => html, size: () => html.length }; }) - .then(() => getHtmlWebpackPluginHooks(compilation).htmlWebpackPluginAfterEmit.promise({ + .then(() => getHtmlWebpackPluginHooks(compilation).afterEmit.promise({ html: compilation.assets[self.childCompilationOutputName], outputName: self.childCompilationOutputName, plugin: self @@ -226,7 +226,7 @@ class HtmlWebpackPlugin { console.error(err); return null; }).then(() => null)) - // Let webpack continue with it + // Let webpack continue with it .then(() => { callback(); }); diff --git a/lib/chunksorter.js b/lib/chunksorter.js index d555fbac..40d9909d 100644 --- a/lib/chunksorter.js +++ b/lib/chunksorter.js @@ -6,15 +6,14 @@ * @type {{[sortmode: string] : (entryPointNames: Array, compilation, htmlWebpackPluginOptions) => Array }} * This file contains different sort methods for the entry chunks names */ -const sortFunctions = {}; -module.exports = sortFunctions; +module.exports = {}; /** * Performs identity mapping (no-sort). * @param {Array} chunks the chunks to sort * @return {Array} The sorted chunks */ -sortFunctions.none = chunks => chunks; +module.exports.none = chunks => chunks; /** * Sort manually by the chunks @@ -23,7 +22,7 @@ sortFunctions.none = chunks => chunks; * @param htmlWebpackPluginOptions the plugin options * @return {string[]} The sorted chunks */ -sortFunctions.manual = (entryPointNames, compilation, htmlWebpackPluginOptions) => { +module.exports.manual = (entryPointNames, compilation, htmlWebpackPluginOptions) => { const chunks = htmlWebpackPluginOptions.chunks; if (!Array.isArray(chunks)) { return entryPointNames; @@ -38,4 +37,4 @@ sortFunctions.manual = (entryPointNames, compilation, htmlWebpackPluginOptions) /** * Defines the default sorter. */ -sortFunctions.auto = module.exports.none; +module.exports.auto = module.exports.none; diff --git a/lib/hooks.js b/lib/hooks.js index 49d6595b..77480e79 100644 --- a/lib/hooks.js +++ b/lib/hooks.js @@ -15,7 +15,8 @@ const AsyncSeriesWaterfallHook = require('tapable').AsyncSeriesWaterfallHook; // The following typedef holds the API definition for all available hooks // to allow easier access when using ts-check or typescript inside plugins /** @typedef {{ - htmlWebpackPluginBeforeHtmlGeneration: + + beforeHtmlGeneration: AsyncSeriesWaterfallHook<{ assets: { publicPath: string, @@ -25,7 +26,8 @@ const AsyncSeriesWaterfallHook = require('tapable').AsyncSeriesWaterfallHook; outputName: string, plugin: HtmlWebpackPlugin }>, - htmlWebpackPluginBeforeHtmlProcessing: + + beforeHtmlProcessing: AsyncSeriesWaterfallHook<{ html: string, assets: { @@ -36,7 +38,8 @@ const AsyncSeriesWaterfallHook = require('tapable').AsyncSeriesWaterfallHook; outputName: string, plugin: HtmlWebpackPlugin, }>, - htmlWebpackPluginAfterHtmlProcessing: + + afterHtmlProcessing: AsyncSeriesWaterfallHook<{ html: string, assets: { @@ -47,19 +50,22 @@ const AsyncSeriesWaterfallHook = require('tapable').AsyncSeriesWaterfallHook; outputName: string, plugin: HtmlWebpackPlugin, }>, - htmlWebpackPluginAlterAssetTags: + + alterAssetTags: AsyncSeriesWaterfallHook<{ head: Array, body: Array, outputName: string, plugin: HtmlWebpackPlugin }>, - htmlWebpackPluginAfterEmit: + + afterEmit: AsyncSeriesWaterfallHook<{ html: string, outputName: string, plugin: HtmlWebpackPlugin }>, + }} HtmlWebpackPluginHooks */ @@ -81,13 +87,7 @@ function getHtmlWebpackPluginHooks (compilation) { hooks = createHtmlWebpackPluginHooks(); htmlWebpackPluginHooksMap.set(compilation, hooks); } - return { - htmlWebpackPluginBeforeHtmlGeneration: hooks.htmlWebpackPluginBeforeHtmlGeneration, - htmlWebpackPluginBeforeHtmlProcessing: hooks.htmlWebpackPluginBeforeHtmlProcessing, - htmlWebpackPluginAlterAssetTags: hooks.htmlWebpackPluginAlterAssetTags, - htmlWebpackPluginAfterHtmlProcessing: hooks.htmlWebpackPluginAfterHtmlProcessing, - htmlWebpackPluginAfterEmit: hooks.htmlWebpackPluginAfterEmit - }; + return hooks; } /** @@ -98,11 +98,11 @@ function getHtmlWebpackPluginHooks (compilation) { */ function createHtmlWebpackPluginHooks () { return { - htmlWebpackPluginBeforeHtmlGeneration: new AsyncSeriesWaterfallHook(['pluginArgs']), - htmlWebpackPluginBeforeHtmlProcessing: new AsyncSeriesWaterfallHook(['pluginArgs']), - htmlWebpackPluginAlterAssetTags: new AsyncSeriesWaterfallHook(['pluginArgs']), - htmlWebpackPluginAfterHtmlProcessing: new AsyncSeriesWaterfallHook(['pluginArgs']), - htmlWebpackPluginAfterEmit: new AsyncSeriesWaterfallHook(['pluginArgs']) + beforeHtmlGeneration: new AsyncSeriesWaterfallHook(['pluginArgs']), + beforeHtmlProcessing: new AsyncSeriesWaterfallHook(['pluginArgs']), + alterAssetTags: new AsyncSeriesWaterfallHook(['pluginArgs']), + afterHtmlProcessing: new AsyncSeriesWaterfallHook(['pluginArgs']), + afterEmit: new AsyncSeriesWaterfallHook(['pluginArgs']) }; } diff --git a/package.json b/package.json index 911b124f..364e0696 100644 --- a/package.json +++ b/package.json @@ -15,7 +15,8 @@ "posttest": "tsc", "commit": "git-cz", "build-examples": "node examples/build-examples.js", - "test": "jasmine", + "test": "jest --runInBand", + "test-watch": "jest --runInBand --watch", "release": "standard-version" }, "semistandard": { @@ -35,8 +36,7 @@ "html-loader": "^0.4.4", "jade": "^1.11.0", "jade-loader": "^0.8.0", - "jasmine": "^2.5.2", - "jasmine-diff-matchers": "^2.0.0", + "jest": "23.3.0", "rimraf": "^2.5.4", "semistandard": "8.0.0", "standard-version": "^4.3.0", @@ -76,5 +76,9 @@ "commitizen": { "path": "./node_modules/cz-conventional-changelog" } + }, + "jest": { + "watchPathIgnorePatterns": ["/dist"], + "testEnvironment": "node" } } diff --git a/spec/BasicSpec.js b/spec/basic.spec.js similarity index 90% rename from spec/BasicSpec.js rename to spec/basic.spec.js index 345f9243..faa047cd 100644 --- a/spec/BasicSpec.js +++ b/spec/basic.spec.js @@ -2,7 +2,7 @@ * Integration and unit tests for all features but caching */ -/* eslint-env jasmine */ +/* eslint-env jest */ 'use strict'; var path = require('path'); @@ -16,9 +16,7 @@ var webpackMajorVersion = Number(require('webpack/package.json').version.split(' if (isNaN(webpackMajorVersion)) { throw new Error('Cannot parse webpack major version'); } -if (webpackMajorVersion < 4) { - var CommonsChunkPlugin = require('webpack/lib/optimize/CommonsChunkPlugin'); -} + var HtmlWebpackPlugin = require('../index.js'); if (Number(extractTextPluginMajorVersion) > 1) { @@ -31,45 +29,12 @@ if (Number(extractTextPluginMajorVersion) > 1) { }; } -var OUTPUT_DIR = path.join(__dirname, '../dist'); +var OUTPUT_DIR = path.resolve(__dirname, '../dist/basic-spec'); -jasmine.getEnv().defaultTimeoutInterval = 30000; - -function transformCommonChunkConfigToOptimization (config) { - if (config.name === 'common') { - return { - splitChunks: { - cacheGroups: { - commons: { - chunks: 'initial', - name: config.name, - enforce: true - } - } - } - }; - } else { - throw new Error('Unrecognized common chunk config'); - } -} +jest.setTimeout(30000); +process.on('unhandledRejection', r => console.log(r)); function testHtmlPlugin (webpackConfig, expectedResults, outputFile, done, expectErrors, expectWarnings) { - if (webpackMajorVersion >= 4) { - webpackConfig.mode = 'development'; - if (webpackConfig.module && webpackConfig.module.loaders) { - webpackConfig.module.rules = webpackConfig.module.loaders; - delete webpackConfig.module.loaders; - } - } - if (webpackConfig.__commonsChunk) { - if (webpackMajorVersion < 4) { - webpackConfig.plugins = webpackConfig.plugins || []; - webpackConfig.plugins.unshift(new CommonsChunkPlugin(webpackConfig.__commonsChunk)); - } else { - webpackConfig.optimization = transformCommonChunkConfigToOptimization(webpackConfig.__commonsChunk); - } - delete webpackConfig.__commonsChunk; - } outputFile = outputFile || 'index.html'; webpack(webpackConfig, function (err, stats) { expect(err).toBeFalsy(); @@ -133,26 +98,6 @@ function getChunksInfoFromStats (stats) { return chunksInfo; } -function tapCompilationEvent (compilation, eventName, handler) { - // Webpack 4 has a new interface - if (compilation.hooks) { - return HtmlWebpackPlugin.getHooks(compilation)[trainCaseToCamelCase(eventName)].tapAsync( - 'AsyncPlugin' + tapCompilationEvent.counter++, - handler - ); - } else { - return compilation.plugin(eventName, handler); - } -} -// There's probably a better way to do this -tapCompilationEvent.counter = 0; - -function trainCaseToCamelCase (word) { - return word.replace(/-([\w])/g, function (match, p1) { - return p1.toUpperCase(); - }); -} - describe('HtmlWebpackPlugin', function () { beforeEach(function (done) { rimraf(OUTPUT_DIR, done); @@ -160,6 +105,7 @@ describe('HtmlWebpackPlugin', function () { it('generates a default index.html file for a single entry point', function (done) { testHtmlPlugin({ + mode: 'production', entry: path.join(__dirname, 'fixtures/index.js'), output: { path: OUTPUT_DIR, @@ -171,6 +117,7 @@ describe('HtmlWebpackPlugin', function () { it('generates a default index.html file with multiple entry points', function (done) { testHtmlPlugin({ + mode: 'production', entry: { util: path.join(__dirname, 'fixtures/util.js'), app: path.join(__dirname, 'fixtures/index.js') @@ -185,6 +132,7 @@ describe('HtmlWebpackPlugin', function () { it('allows you to specify a custom loader without injection', function (done) { testHtmlPlugin({ + mode: 'production', entry: { app: path.join(__dirname, 'fixtures/index.js') }, @@ -202,6 +150,7 @@ describe('HtmlWebpackPlugin', function () { it('should pass through loader errors', function (done) { testHtmlPlugin({ + mode: 'production', entry: { app: path.join(__dirname, 'fixtures/index.js') }, @@ -219,11 +168,12 @@ describe('HtmlWebpackPlugin', function () { it('uses a custom loader from webpacks config', function (done) { testHtmlPlugin({ + mode: 'production', entry: { app: path.join(__dirname, 'fixtures/index.js') }, module: { - loaders: [ + rules: [ {test: /\.jade$/, loader: 'jade-loader'} ] }, @@ -241,6 +191,7 @@ describe('HtmlWebpackPlugin', function () { it('works when using html-loader', function (done) { testHtmlPlugin({ + mode: 'production', entry: { app: path.join(__dirname, 'fixtures/index.js') }, @@ -258,6 +209,7 @@ describe('HtmlWebpackPlugin', function () { it('allows you to specify your own HTML template file', function (done) { testHtmlPlugin({ + mode: 'production', entry: { app: path.join(__dirname, 'fixtures/index.js') }, @@ -275,6 +227,7 @@ describe('HtmlWebpackPlugin', function () { it('allows you to inject the assets into a given html file', function (done) { testHtmlPlugin({ + mode: 'production', entry: { util: path.join(__dirname, 'fixtures/util.js'), app: path.join(__dirname, 'fixtures/index.js') @@ -292,6 +245,7 @@ describe('HtmlWebpackPlugin', function () { it('allows you to inject the assets into the body of the given template', function (done) { testHtmlPlugin({ + mode: 'production', entry: { util: path.join(__dirname, 'fixtures/util.js'), app: path.join(__dirname, 'fixtures/index.js') @@ -309,6 +263,7 @@ describe('HtmlWebpackPlugin', function () { it('allows you to inject the assets into the head of the given template', function (done) { testHtmlPlugin({ + mode: 'production', entry: { util: path.join(__dirname, 'fixtures/util.js'), app: path.join(__dirname, 'fixtures/index.js') @@ -326,6 +281,7 @@ describe('HtmlWebpackPlugin', function () { it('allows you to inject a specified asset into a given html file', function (done) { testHtmlPlugin({ + mode: 'production', entry: { util: path.join(__dirname, 'fixtures/util.js'), app: path.join(__dirname, 'fixtures/index.js') @@ -344,6 +300,7 @@ describe('HtmlWebpackPlugin', function () { it('allows you to inject a specified asset into a given html file', function (done) { testHtmlPlugin({ + mode: 'production', entry: { util: path.join(__dirname, 'fixtures/util.js'), app: path.join(__dirname, 'fixtures/index.js') @@ -362,6 +319,7 @@ describe('HtmlWebpackPlugin', function () { it('allows you to use chunkhash with asset into a given html file', function (done) { testHtmlPlugin({ + mode: 'production', entry: { app: path.join(__dirname, 'fixtures/index.js') }, @@ -382,6 +340,7 @@ describe('HtmlWebpackPlugin', function () { it('allows you to disable injection', function (done) { testHtmlPlugin({ + mode: 'production', entry: { util: path.join(__dirname, 'fixtures/util.js'), app: path.join(__dirname, 'fixtures/index.js') @@ -399,6 +358,7 @@ describe('HtmlWebpackPlugin', function () { it('allows you to specify your own HTML template function', function (done) { testHtmlPlugin({ + mode: 'production', entry: {app: path.join(__dirname, 'fixtures/index.js')}, output: { path: OUTPUT_DIR, @@ -415,6 +375,7 @@ describe('HtmlWebpackPlugin', function () { it('works with source maps', function (done) { testHtmlPlugin({ + mode: 'development', devtool: 'sourcemap', entry: path.join(__dirname, 'fixtures/index.js'), output: { @@ -427,6 +388,7 @@ describe('HtmlWebpackPlugin', function () { it('handles hashes in bundle filenames', function (done) { testHtmlPlugin({ + mode: 'production', entry: path.join(__dirname, 'fixtures/index.js'), output: { path: OUTPUT_DIR, @@ -438,9 +400,10 @@ describe('HtmlWebpackPlugin', function () { it('handles hashes in the directory which has the bundle file', function (done) { testHtmlPlugin({ + mode: 'production', entry: path.join(__dirname, 'fixtures/index.js'), output: { - path: path.join(__dirname, '../dist'), + path: OUTPUT_DIR, publicPath: '/dist/[hash]/', filename: 'index_bundle_[hash].js' }, @@ -450,6 +413,7 @@ describe('HtmlWebpackPlugin', function () { it('allows to append hashes to the assets', function (done) { testHtmlPlugin({ + mode: 'production', entry: path.join(__dirname, 'fixtures/index.js'), output: { path: OUTPUT_DIR, @@ -461,6 +425,7 @@ describe('HtmlWebpackPlugin', function () { it('allows to append hashes to the assets', function (done) { testHtmlPlugin({ + mode: 'production', entry: path.join(__dirname, 'fixtures/index.js'), output: { path: OUTPUT_DIR, @@ -472,13 +437,14 @@ describe('HtmlWebpackPlugin', function () { it('should work with the css extract plugin', function (done) { testHtmlPlugin({ + mode: 'production', entry: path.join(__dirname, 'fixtures/theme.js'), output: { path: OUTPUT_DIR, filename: 'index_bundle.js' }, module: { - loaders: [ + rules: [ { test: /\.css$/, loader: ExtractTextPlugin.extract('style-loader', 'css-loader') } ] }, @@ -491,6 +457,7 @@ describe('HtmlWebpackPlugin', function () { it('should work with the css extract plugin on windows and protocol relative urls support (#205)', function (done) { testHtmlPlugin({ + mode: 'production', entry: path.join(__dirname, 'fixtures/theme.js'), output: { path: OUTPUT_DIR, @@ -498,7 +465,7 @@ describe('HtmlWebpackPlugin', function () { publicPath: '//localhost:8080/' }, module: { - loaders: [ + rules: [ { test: /\.css$/, loader: ExtractTextPlugin.extract('style-loader', 'css-loader') } ] }, @@ -511,13 +478,14 @@ describe('HtmlWebpackPlugin', function () { it('should allow to add cache hashes to with the css assets', function (done) { testHtmlPlugin({ + mode: 'production', entry: path.join(__dirname, 'fixtures/theme.js'), output: { path: OUTPUT_DIR, filename: 'index_bundle.js' }, module: { - loaders: [ + rules: [ { test: /\.css$/, loader: ExtractTextPlugin.extract('style-loader', 'css-loader') } ] }, @@ -530,13 +498,14 @@ describe('HtmlWebpackPlugin', function () { it('should inject css files when using the extract text plugin', function (done) { testHtmlPlugin({ + mode: 'production', entry: path.join(__dirname, 'fixtures/theme.js'), output: { path: OUTPUT_DIR, filename: 'index_bundle.js' }, module: { - loaders: [ + rules: [ { test: /\.css$/, loader: ExtractTextPlugin.extract('style-loader', 'css-loader') } ] }, @@ -549,13 +518,14 @@ describe('HtmlWebpackPlugin', function () { it('should allow to add cache hashes to with injected css assets', function (done) { testHtmlPlugin({ + mode: 'production', entry: path.join(__dirname, 'fixtures/theme.js'), output: { path: OUTPUT_DIR, filename: 'index_bundle.js' }, module: { - loaders: [ + rules: [ { test: /\.css$/, loader: ExtractTextPlugin.extract('style-loader', 'css-loader') } ] }, @@ -568,13 +538,14 @@ describe('HtmlWebpackPlugin', function () { it('should output xhtml link stylesheet tag', function (done) { testHtmlPlugin({ + mode: 'production', entry: path.join(__dirname, 'fixtures/theme.js'), output: { path: OUTPUT_DIR, filename: 'index_bundle.js' }, module: { - loaders: [ + rules: [ { test: /\.css$/, loader: ExtractTextPlugin.extract('style-loader', 'css-loader') } ] }, @@ -587,6 +558,7 @@ describe('HtmlWebpackPlugin', function () { it('prepends the webpack public path to script src', function (done) { testHtmlPlugin({ + mode: 'production', entry: path.join(__dirname, 'fixtures/index.js'), output: { path: OUTPUT_DIR, @@ -599,6 +571,7 @@ describe('HtmlWebpackPlugin', function () { it('handles subdirectories in the webpack output bundles', function (done) { testHtmlPlugin({ + mode: 'production', entry: path.join(__dirname, 'fixtures/index.js'), output: { path: OUTPUT_DIR, @@ -610,6 +583,7 @@ describe('HtmlWebpackPlugin', function () { it('handles subdirectories in the webpack output bundles along with a public path', function (done) { testHtmlPlugin({ + mode: 'production', entry: path.join(__dirname, 'fixtures/index.js'), output: { path: OUTPUT_DIR, @@ -622,6 +596,7 @@ describe('HtmlWebpackPlugin', function () { it('allows you to configure the title of the generated HTML page', function (done) { testHtmlPlugin({ + mode: 'production', entry: path.join(__dirname, 'fixtures/index.js'), output: { path: OUTPUT_DIR, @@ -633,6 +608,7 @@ describe('HtmlWebpackPlugin', function () { it('allows you to configure the output filename', function (done) { testHtmlPlugin({ + mode: 'production', entry: path.join(__dirname, 'fixtures/index.js'), output: { path: OUTPUT_DIR, @@ -644,6 +620,7 @@ describe('HtmlWebpackPlugin', function () { it('will replace [hash] in the filename with the child compilation hash', function (done) { testHtmlPlugin({ + mode: 'production', entry: path.join(__dirname, 'fixtures/index.js'), output: { path: OUTPUT_DIR, @@ -657,6 +634,7 @@ describe('HtmlWebpackPlugin', function () { it('allows you to use an absolute output filename', function (done) { testHtmlPlugin({ + mode: 'production', entry: path.join(__dirname, 'fixtures/index.js'), output: { path: OUTPUT_DIR, @@ -670,6 +648,7 @@ describe('HtmlWebpackPlugin', function () { it('allows you to use an absolute output filename outside the output path', function (done) { testHtmlPlugin({ + mode: 'production', entry: path.join(__dirname, 'fixtures/index.js'), output: { path: path.join(OUTPUT_DIR, 'app'), @@ -683,6 +662,7 @@ describe('HtmlWebpackPlugin', function () { it('allows you to use an relative output filename outside the output path', function (done) { testHtmlPlugin({ + mode: 'production', entry: path.join(__dirname, 'fixtures/index.js'), output: { path: path.join(OUTPUT_DIR, 'app'), @@ -696,6 +676,7 @@ describe('HtmlWebpackPlugin', function () { it('will try to use a relative name if the filename is in a subdirectory', function (done) { testHtmlPlugin({ + mode: 'production', entry: path.join(__dirname, 'fixtures/index.js'), output: { path: OUTPUT_DIR, @@ -707,6 +688,7 @@ describe('HtmlWebpackPlugin', function () { it('will try to use a relative name if the filename and the script are in a subdirectory', function (done) { testHtmlPlugin({ + mode: 'production', entry: path.join(__dirname, 'fixtures/index.js'), output: { path: OUTPUT_DIR, @@ -718,6 +700,7 @@ describe('HtmlWebpackPlugin', function () { it('allows you write multiple HTML files', function (done) { testHtmlPlugin({ + mode: 'production', entry: { app: path.join(__dirname, 'fixtures/index.js') }, @@ -745,13 +728,14 @@ describe('HtmlWebpackPlugin', function () { it('should inject js css files even if the html file is incomplete', function (done) { testHtmlPlugin({ + mode: 'production', entry: path.join(__dirname, 'fixtures/theme.js'), output: { path: OUTPUT_DIR, filename: 'index_bundle.js' }, module: { - loaders: [ + rules: [ { test: /\.css$/, loader: ExtractTextPlugin.extract('style-loader', 'css-loader') } ] }, @@ -764,6 +748,7 @@ describe('HtmlWebpackPlugin', function () { it('exposes the webpack configuration to templates', function (done) { testHtmlPlugin({ + mode: 'production', entry: { app: path.join(__dirname, 'fixtures/index.js') }, @@ -782,7 +767,7 @@ describe('HtmlWebpackPlugin', function () { var examplePlugin = { apply: function (compiler) { compiler.plugin('compilation', function (compilation) { - tapCompilationEvent(compilation, 'html-webpack-plugin-alter-asset-tags', function (object, callback) { + HtmlWebpackPlugin.getHooks(compilation).alterAssetTags.tapAsync('HtmlWebpackPluginTest', (object, callback) => { expect(typeof object.body).toBe('object'); expect(typeof object.head).toBe('object'); eventFired = true; @@ -794,6 +779,7 @@ describe('HtmlWebpackPlugin', function () { var shouldExpectWarnings = webpackMajorVersion < 4; testHtmlPlugin({ + mode: 'production', entry: { app: path.join(__dirname, 'fixtures/index.js') }, @@ -816,7 +802,7 @@ describe('HtmlWebpackPlugin', function () { var examplePlugin = { apply: function (compiler) { compiler.plugin('compilation', function (compilation) { - tapCompilationEvent(compilation, 'html-webpack-plugin-alter-asset-tags', function (pluginArgs, callback) { + HtmlWebpackPlugin.getHooks(compilation).alterAssetTags.tapAsync('HtmlWebpackPluginTest', (pluginArgs, callback) => { pluginArgs.body = pluginArgs.body.map(function (tag) { if (tag.tagName === 'script') { tag.attributes.async = true; @@ -829,6 +815,7 @@ describe('HtmlWebpackPlugin', function () { } }; testHtmlPlugin({ + mode: 'production', entry: { app: path.join(__dirname, 'fixtures/index.js') }, @@ -849,7 +836,7 @@ describe('HtmlWebpackPlugin', function () { var examplePlugin = { apply: function (compiler) { compiler.plugin('compilation', function (compilation) { - tapCompilationEvent(compilation, 'html-webpack-plugin-alter-asset-tags', function (pluginArgs, callback) { + HtmlWebpackPlugin.getHooks(compilation).alterAssetTags.tapAsync('HtmlWebpackPluginTest', (pluginArgs, callback) => { pluginArgs.body = pluginArgs.body.map(function (tag) { if (tag.tagName === 'script') { tag.attributes.async = false; @@ -862,6 +849,7 @@ describe('HtmlWebpackPlugin', function () { } }; testHtmlPlugin({ + mode: 'production', entry: { app: path.join(__dirname, 'fixtures/index.js') }, @@ -883,7 +871,7 @@ describe('HtmlWebpackPlugin', function () { var examplePlugin = { apply: function (compiler) { compiler.plugin('compilation', function (compilation) { - tapCompilationEvent(compilation, 'html-webpack-plugin-before-html-processing', function (object, callback) { + HtmlWebpackPlugin.getHooks(compilation).beforeHtmlProcessing.tapAsync('HtmlWebpackPluginTest', (object, callback) => { eventFired = true; callback(); }); @@ -893,6 +881,7 @@ describe('HtmlWebpackPlugin', function () { var shouldExpectWarnings = webpackMajorVersion < 4; testHtmlPlugin({ + mode: 'production', entry: { app: path.join(__dirname, 'fixtures/index.js') }, @@ -916,7 +905,7 @@ describe('HtmlWebpackPlugin', function () { var examplePlugin = { apply: function (compiler) { compiler.plugin('compilation', function (compilation) { - tapCompilationEvent(compilation, 'html-webpack-plugin-after-html-processing', function (object, callback) { + HtmlWebpackPlugin.getHooks(compilation).afterHtmlProcessing.tapAsync('HtmlWebpackPluginTest', (object, callback) => { eventFired = true; callback(); }); @@ -925,6 +914,7 @@ describe('HtmlWebpackPlugin', function () { }; var shouldExpectWarnings = webpackMajorVersion < 4; testHtmlPlugin({ + mode: 'production', entry: { app: path.join(__dirname, 'fixtures/index.js') }, @@ -948,7 +938,7 @@ describe('HtmlWebpackPlugin', function () { var examplePlugin = { apply: function (compiler) { compiler.plugin('compilation', function (compilation) { - tapCompilationEvent(compilation, 'html-webpack-plugin-after-emit', function (object, callback) { + HtmlWebpackPlugin.getHooks(compilation).afterEmit.tapAsync('HtmlWebpackPluginTest', (object, callback) => { eventFired = true; callback(); }); @@ -956,6 +946,7 @@ describe('HtmlWebpackPlugin', function () { } }; testHtmlPlugin({ + mode: 'production', entry: { app: path.join(__dirname, 'fixtures/index.js') }, @@ -978,7 +969,7 @@ describe('HtmlWebpackPlugin', function () { var examplePlugin = { apply: function (compiler) { compiler.plugin('compilation', function (compilation) { - tapCompilationEvent(compilation, 'html-webpack-plugin-after-html-processing', function (object, callback) { + HtmlWebpackPlugin.getHooks(compilation).afterHtmlProcessing.tapAsync('HtmlWebpackPluginTest', (object, callback) => { eventFired = true; object.html += 'Injected by plugin'; callback(); @@ -989,6 +980,7 @@ describe('HtmlWebpackPlugin', function () { var shouldExpectWarnings = webpackMajorVersion < 4; testHtmlPlugin({ + mode: 'production', entry: { app: path.join(__dirname, 'fixtures/index.js') }, @@ -1013,7 +1005,7 @@ describe('HtmlWebpackPlugin', function () { var examplePlugin = { apply: function (compiler) { compiler.plugin('compilation', function (compilation) { - tapCompilationEvent(compilation, 'html-webpack-plugin-after-html-processing', function (object, callback) { + HtmlWebpackPlugin.getHooks(compilation).afterHtmlProcessing.tapAsync('HtmlWebpackPluginTest', (object, callback) => { eventFiredForFirstPlugin = true; object.html += 'Injected by first plugin'; callback(null, object); @@ -1024,7 +1016,7 @@ describe('HtmlWebpackPlugin', function () { var secondExamplePlugin = { apply: function (compiler) { compiler.plugin('compilation', function (compilation) { - tapCompilationEvent(compilation, 'html-webpack-plugin-after-html-processing', function (object, callback) { + HtmlWebpackPlugin.getHooks(compilation).afterHtmlProcessing.tapAsync('HtmlWebpackPluginTest', (object, callback) => { eventFiredForSecondPlugin = true; object.html += ' Injected by second plugin'; callback(null); @@ -1035,6 +1027,7 @@ describe('HtmlWebpackPlugin', function () { var shouldExpectWarnings = webpackMajorVersion < 4; testHtmlPlugin({ + mode: 'production', entry: { app: path.join(__dirname, 'fixtures/index.js') }, @@ -1061,7 +1054,7 @@ describe('HtmlWebpackPlugin', function () { var examplePlugin = { apply: function (compiler) { compiler.plugin('compilation', function (compilation) { - tapCompilationEvent(compilation, 'html-webpack-plugin-after-html-processing', function (object, callback) { + HtmlWebpackPlugin.getHooks(compilation).afterHtmlProcessing.tapAsync('HtmlWebpackPluginTest', (object, callback) => { eventFiredForFirstPlugin = true; var result = _.extend(object, { html: object.html + 'Injected by first plugin' @@ -1074,7 +1067,7 @@ describe('HtmlWebpackPlugin', function () { var secondExamplePlugin = { apply: function (compiler) { compiler.plugin('compilation', function (compilation) { - tapCompilationEvent(compilation, 'html-webpack-plugin-after-html-processing', function (object, callback) { + HtmlWebpackPlugin.getHooks(compilation).afterHtmlProcessing.tapAsync('HtmlWebpackPluginTest', (object, callback) => { eventFiredForSecondPlugin = true; object.html += ' Injected by second plugin'; callback(null); @@ -1085,6 +1078,7 @@ describe('HtmlWebpackPlugin', function () { var shouldExpectWarnings = webpackMajorVersion < 4; testHtmlPlugin({ + mode: 'production', entry: { app: path.join(__dirname, 'fixtures/index.js') }, @@ -1111,7 +1105,7 @@ describe('HtmlWebpackPlugin', function () { var examplePlugin = { apply: function (compiler) { compiler.plugin('compilation', function (compilation) { - tapCompilationEvent(compilation, 'html-webpack-plugin-after-html-processing', function (object, callback) { + HtmlWebpackPlugin.getHooks(compilation).afterHtmlProcessing.tapAsync('HtmlWebpackPluginTest', (object, callback) => { eventFiredForFirstPlugin = true; var result = _.extend(object, { html: object.html + 'Injected by first plugin' @@ -1124,7 +1118,7 @@ describe('HtmlWebpackPlugin', function () { var secondExamplePlugin = { apply: function (compiler) { compiler.plugin('compilation', function (compilation) { - tapCompilationEvent(compilation, 'html-webpack-plugin-after-html-processing', function (object, callback) { + HtmlWebpackPlugin.getHooks(compilation).afterHtmlProcessing.tapAsync('HtmlWebpackPluginTest', (object, callback) => { eventFiredForSecondPlugin = true; var result = _.extend(object, { html: object.html + ' Injected by second plugin' @@ -1136,6 +1130,7 @@ describe('HtmlWebpackPlugin', function () { }; testHtmlPlugin({ + mode: 'production', entry: { app: path.join(__dirname, 'fixtures/index.js') }, @@ -1160,7 +1155,7 @@ describe('HtmlWebpackPlugin', function () { var examplePlugin = { apply: function (compiler) { compiler.plugin('compilation', function (compilation) { - tapCompilationEvent(compilation, 'html-webpack-plugin-before-html-processing', function (object, callback) { + HtmlWebpackPlugin.getHooks(compilation).beforeHtmlProcessing.tapAsync('HtmlWebpackPluginTest', (object, callback) => { eventFired = true; object.assets.js.push({path: 'funky-script.js'}); object.html += 'Injected by plugin'; @@ -1172,6 +1167,7 @@ describe('HtmlWebpackPlugin', function () { var shouldExpectWarnings = webpackMajorVersion < 4; testHtmlPlugin({ + mode: 'production', entry: { app: path.join(__dirname, 'fixtures/index.js') }, @@ -1195,7 +1191,7 @@ describe('HtmlWebpackPlugin', function () { var examplePlugin = { apply: function (compiler) { compiler.plugin('compilation', function (compilation) { - tapCompilationEvent(compilation, 'html-webpack-plugin-before-html-generation', function (object, callback) { + HtmlWebpackPlugin.getHooks(compilation).beforeHtmlGeneration.tapAsync('HtmlWebpackPluginTest', (object, callback) => { eventFired = true; object.assets.js.push({path: 'funky-script.js'}); callback(); @@ -1204,6 +1200,7 @@ describe('HtmlWebpackPlugin', function () { } }; testHtmlPlugin({ + mode: 'production', entry: { app: path.join(__dirname, 'fixtures/index.js') }, @@ -1226,6 +1223,7 @@ describe('HtmlWebpackPlugin', function () { it('works with commons chunk plugin', function (done) { testHtmlPlugin({ + mode: 'production', entry: { util: path.join(__dirname, 'fixtures/util.js'), index: path.join(__dirname, 'fixtures/index.js') @@ -1234,9 +1232,16 @@ describe('HtmlWebpackPlugin', function () { path: OUTPUT_DIR, filename: '[name]_bundle.js' }, - __commonsChunk: { - name: 'common', - filename: 'common_bundle.js' + optimization: { + splitChunks: { + cacheGroups: { + commons: { + chunks: 'initial', + name: 'common', + enforce: true + } + } + } }, plugins: [ new HtmlWebpackPlugin() @@ -1248,6 +1253,7 @@ describe('HtmlWebpackPlugin', function () { it('adds a favicon', function (done) { testHtmlPlugin({ + mode: 'production', entry: path.join(__dirname, 'fixtures/index.js'), output: { path: OUTPUT_DIR, @@ -1263,6 +1269,7 @@ describe('HtmlWebpackPlugin', function () { it('adds a meta tag', function (done) { testHtmlPlugin({ + mode: 'production', entry: path.join(__dirname, 'fixtures/index.js'), output: { path: OUTPUT_DIR, @@ -1283,6 +1290,7 @@ describe('HtmlWebpackPlugin', function () { it('adds a meta tag with short notation', function (done) { testHtmlPlugin({ + mode: 'production', entry: path.join(__dirname, 'fixtures/index.js'), output: { path: OUTPUT_DIR, @@ -1300,6 +1308,7 @@ describe('HtmlWebpackPlugin', function () { it('adds a favicon with publicPath set to /some/', function (done) { testHtmlPlugin({ + mode: 'production', entry: path.join(__dirname, 'fixtures/index.js'), output: { path: OUTPUT_DIR, @@ -1316,6 +1325,7 @@ describe('HtmlWebpackPlugin', function () { it('adds a favicon with publicPath set to /some', function (done) { testHtmlPlugin({ + mode: 'production', entry: path.join(__dirname, 'fixtures/index.js'), output: { path: OUTPUT_DIR, @@ -1332,6 +1342,7 @@ describe('HtmlWebpackPlugin', function () { it('adds a favicon with a publichPath set to [hash]/ and replaces the hash', function (done) { testHtmlPlugin({ + mode: 'production', entry: path.join(__dirname, 'fixtures/index.js'), output: { path: OUTPUT_DIR, @@ -1348,6 +1359,7 @@ describe('HtmlWebpackPlugin', function () { it('adds a favicon with inject enabled', function (done) { testHtmlPlugin({ + mode: 'production', entry: path.join(__dirname, 'fixtures/index.js'), output: { path: OUTPUT_DIR, @@ -1364,6 +1376,7 @@ describe('HtmlWebpackPlugin', function () { it('adds a favicon with xhtml enabled', function (done) { testHtmlPlugin({ + mode: 'production', entry: path.join(__dirname, 'fixtures/index.js'), output: { path: OUTPUT_DIR, @@ -1381,6 +1394,7 @@ describe('HtmlWebpackPlugin', function () { it('shows an error if the favicon could not be load', function (done) { testHtmlPlugin({ + mode: 'production', entry: path.join(__dirname, 'fixtures/index.js'), output: { path: OUTPUT_DIR, @@ -1398,6 +1412,7 @@ describe('HtmlWebpackPlugin', function () { it('adds a manifest', function (done) { var AppCachePlugin = require('appcache-webpack-plugin'); testHtmlPlugin({ + mode: 'production', entry: path.join(__dirname, 'fixtures/index.js'), output: { path: OUTPUT_DIR, @@ -1413,6 +1428,7 @@ describe('HtmlWebpackPlugin', function () { it('does not add a manifest if already present', function (done) { var AppCachePlugin = require('appcache-webpack-plugin'); testHtmlPlugin({ + mode: 'production', entry: path.join(__dirname, 'fixtures/index.js'), output: { path: OUTPUT_DIR, @@ -1429,6 +1445,7 @@ describe('HtmlWebpackPlugin', function () { it('works with webpack bannerplugin', function (done) { testHtmlPlugin({ + mode: 'production', entry: path.join(__dirname, 'fixtures/index.js'), output: { path: OUTPUT_DIR, @@ -1443,6 +1460,7 @@ describe('HtmlWebpackPlugin', function () { it('shows an error when a template fails to load', function (done) { testHtmlPlugin({ + mode: 'development', entry: path.join(__dirname, 'fixtures/index.js'), output: { path: OUTPUT_DIR, @@ -1458,6 +1476,7 @@ describe('HtmlWebpackPlugin', function () { it('should sort the chunks in auto mode', function (done) { testHtmlPlugin({ + mode: 'production', entry: { util: path.join(__dirname, 'fixtures/util.js'), index: path.join(__dirname, 'fixtures/index.js') @@ -1466,9 +1485,16 @@ describe('HtmlWebpackPlugin', function () { path: OUTPUT_DIR, filename: '[name]_bundle.js' }, - __commonsChunk: { - name: 'common', - filename: 'common_bundle.js' + optimization: { + splitChunks: { + cacheGroups: { + commons: { + chunks: 'initial', + name: 'common', + enforce: true + } + } + } }, plugins: [ new HtmlWebpackPlugin({ @@ -1482,6 +1508,7 @@ describe('HtmlWebpackPlugin', function () { it('should sort the chunks in custom (reverse alphabetical) order', function (done) { testHtmlPlugin({ + mode: 'production', entry: { b: path.join(__dirname, 'fixtures/index.js'), c: path.join(__dirname, 'fixtures/util.js'), @@ -1509,6 +1536,7 @@ describe('HtmlWebpackPlugin', function () { it('should sort manually by the chunks', function (done) { testHtmlPlugin({ + mode: 'production', entry: { b: path.join(__dirname, 'fixtures/util.js'), a: path.join(__dirname, 'fixtures/theme.js'), @@ -1520,13 +1548,20 @@ describe('HtmlWebpackPlugin', function () { filename: '[name]_bundle.js' }, module: { - loaders: [ + rules: [ { test: /\.css$/, loader: 'css-loader' } ] }, - __commonsChunk: { - name: 'common', - filename: 'common_bundle.js' + optimization: { + splitChunks: { + cacheGroups: { + commons: { + chunks: 'initial', + name: 'common', + enforce: true + } + } + } }, plugins: [ new HtmlWebpackPlugin({ @@ -1540,6 +1575,7 @@ describe('HtmlWebpackPlugin', function () { it('should add the webpack compilation object as a property of the templateParam object', function (done) { testHtmlPlugin({ + mode: 'production', entry: path.join(__dirname, 'fixtures/index.js'), output: { path: OUTPUT_DIR, @@ -1556,6 +1592,7 @@ describe('HtmlWebpackPlugin', function () { it('should allow to disable template parameters', function (done) { testHtmlPlugin({ + mode: 'production', entry: path.join(__dirname, 'fixtures/index.js'), output: { path: OUTPUT_DIR, @@ -1573,6 +1610,7 @@ describe('HtmlWebpackPlugin', function () { it('should allow to set specific template parameters', function (done) { testHtmlPlugin({ + mode: 'production', entry: path.join(__dirname, 'fixtures/index.js'), output: { path: OUTPUT_DIR, @@ -1590,6 +1628,7 @@ describe('HtmlWebpackPlugin', function () { it('should allow to set specific template parameters using a function', function (done) { testHtmlPlugin({ + mode: 'production', entry: path.join(__dirname, 'fixtures/index.js'), output: { path: OUTPUT_DIR, @@ -1609,6 +1648,7 @@ describe('HtmlWebpackPlugin', function () { it('should not treat templateContent set to an empty string as missing', function (done) { testHtmlPlugin({ + mode: 'production', entry: {app: path.join(__dirname, 'fixtures/index.js')}, output: { path: OUTPUT_DIR, @@ -1623,6 +1663,7 @@ describe('HtmlWebpackPlugin', function () { it('allows you to inject the assets into the body of the given spaced closing tag template', function (done) { testHtmlPlugin({ + mode: 'production', entry: path.join(__dirname, 'fixtures/index.js'), output: { path: OUTPUT_DIR, @@ -1637,6 +1678,7 @@ describe('HtmlWebpackPlugin', function () { it('allows you to inject the assets into the head of the given spaced closing tag template', function (done) { testHtmlPlugin({ + mode: 'production', entry: path.join(__dirname, 'fixtures/index.js'), output: { path: OUTPUT_DIR, diff --git a/spec/CachingSpec.js b/spec/caching.spec.js similarity index 90% rename from spec/CachingSpec.js rename to spec/caching.spec.js index de548075..94c4e04d 100644 --- a/spec/CachingSpec.js +++ b/spec/caching.spec.js @@ -2,7 +2,7 @@ * Integration tests for caching */ -/* eslint-env jasmine */ +/* eslint-env jest */ 'use strict'; var path = require('path'); @@ -12,12 +12,13 @@ var WebpackRecompilationSimulator = require('webpack-recompilation-simulator'); var HtmlWebpackPlugin = require('../index.js'); var webpackMajorVersion = require('webpack/package.json').version.split('.')[0]; -var OUTPUT_DIR = path.join(__dirname, '../dist'); +var OUTPUT_DIR = path.join(__dirname, '../dist/caching-spec'); -jasmine.getEnv().defaultTimeoutInterval = 30000; +jest.setTimeout(30000); +process.on('unhandledRejection', r => console.log(r)); function setUpCompiler (htmlWebpackPlugin) { - spyOn(htmlWebpackPlugin, 'evaluateCompilationResult').and.callThrough(); + jest.spyOn(htmlWebpackPlugin, 'evaluateCompilationResult'); var webpackConfig = { entry: path.join(__dirname, 'fixtures/index.js'), output: { @@ -64,7 +65,7 @@ describe('HtmlWebpackPluginCaching', function () { expect(getCompiledModuleCount(stats.toJson())) .toBe(0); // Verify that the html was processed only during the inital build - expect(htmlWebpackPlugin.evaluateCompilationResult.calls.count()) + expect(htmlWebpackPlugin.evaluateCompilationResult.mock.calls.length) .toBe(1); // Verify that the child compilation was executed twice expect(htmlWebpackPlugin.childCompilerHash) @@ -89,7 +90,7 @@ describe('HtmlWebpackPluginCaching', function () { expect(getCompiledModuleCount(stats.toJson())) .toBe(1); // Verify that the html was processed only during the inital build - expect(htmlWebpackPlugin.evaluateCompilationResult.calls.count()) + expect(htmlWebpackPlugin.evaluateCompilationResult.mock.calls.length) .toBe(1); // Verify that the child compilation was executed only once expect(htmlWebpackPlugin.childCompilerHash) @@ -116,7 +117,7 @@ describe('HtmlWebpackPluginCaching', function () { expect(getCompiledModuleCount(stats.toJson())) .toBe(1); // Verify that the html was processed on every run - expect(htmlWebpackPlugin.evaluateCompilationResult.calls.count()) + expect(htmlWebpackPlugin.evaluateCompilationResult.mock.calls.length) .toBe(2); // Verify that the child compilation was executed only once expect(htmlWebpackPlugin.childCompilerHash) @@ -144,7 +145,7 @@ describe('HtmlWebpackPluginCaching', function () { expect(getCompiledModuleCount(stats.toJson())) .toBe(1); // Verify that the html was processed twice - expect(htmlWebpackPlugin.evaluateCompilationResult.calls.count()) + expect(htmlWebpackPlugin.evaluateCompilationResult.mock.calls.length) .toBe(2); // Verify that the child compilation was executed twice expect(htmlWebpackPlugin.childCompilerHash) diff --git a/spec/ExampleSpec.js b/spec/example.spec.js similarity index 84% rename from spec/ExampleSpec.js rename to spec/example.spec.js index 378c7fa5..8b51a201 100644 --- a/spec/ExampleSpec.js +++ b/spec/example.spec.js @@ -3,7 +3,7 @@ * and matches them against their dist folder */ -/* eslint-env jasmine */ +/* eslint-env jest */ 'use strict'; var path = require('path'); @@ -12,19 +12,19 @@ var rimraf = require('rimraf'); var fs = require('fs'); var webpackMajorVersion = require('webpack/package.json').version.split('.')[0]; -var OUTPUT_DIR = path.join(__dirname, '../dist'); +var OUTPUT_DIR = path.resolve(__dirname, '../dist'); -jasmine.getEnv().defaultTimeoutInterval = 30000; +jest.setTimeout(30000); function runExample (exampleName, done) { var examplePath = path.resolve(__dirname, '..', 'examples', exampleName); var exampleOutput = path.join(OUTPUT_DIR, exampleName); - var fixturePath = path.join(examplePath, 'dist', 'webpack-' + webpackMajorVersion); + var fixturePath = path.resolve(examplePath, 'dist', 'webpack-' + webpackMajorVersion); // Clear old results rimraf(exampleOutput, function () { var options = require(path.join(examplePath, 'webpack.config.js')); options.context = examplePath; - options.output.path = exampleOutput; + options.output.path = exampleOutput + path.sep; if (Number(webpackMajorVersion) >= 4) { options.plugins.unshift(new webpack.LoaderOptionsPlugin({ options: { @@ -39,7 +39,10 @@ function runExample (exampleName, done) { options.optimization = { minimizer: [] }; } - webpack(options, function (err) { + webpack(options, function (err, stats) { + expect(err).toBeFalsy(); + expect(stats.compilation.errors).toEqual([]); + var dircompare = require('dir-compare'); var res = dircompare.compareSync(fixturePath, exampleOutput, {compareSize: true}); @@ -48,22 +51,16 @@ function runExample (exampleName, done) { }).forEach(function (diff) { var file1Contents = fs.readFileSync(path.join(diff.path1, diff.name1)).toString(); var file2Contents = fs.readFileSync(path.join(diff.path2, diff.name2)).toString(); - expect(file1Contents).diffPatch(file2Contents); - expect(file1Contents).toBe(file2Contents); + expect(file1Contents).toEqual(file2Contents); }); - expect(err).toBeFalsy(); expect(res.same).toBe(true); - done(); + rimraf(exampleOutput, done); }); }); } describe('HtmlWebpackPlugin Examples', function () { - beforeEach(function () { - jasmine.addMatchers(require('jasmine-diff-matchers').diffPatch); - }); - it('appcache example', function (done) { runExample('appcache', done); });