Repository: webpack-contrib/uglifyjs-webpack-plugin
Pull request #336 (2018-07-31 19:22:08)

Refactor tests
<!--
1. [Read and sign the CLA](https://cla.js.foundation/webpack/webpack.js.org). This needs to be done only once. PRs that haven't signed it won't be accepted.
2. Check out the [development guide](https://webpack.js.org/development/) for the API and development guidelines.
3. Read through the PR diff carefully as sometimes this can reveal issues. The work will be reviewed, but this can save some effort.
-->
Simplify test code and more tests


Patch:
diff --git a/src/index.js b/src/index.js
index dab8c02..08997a0 100644
--- a/src/index.js
+++ b/src/index.js
@@ -80,9 +80,10 @@ class UglifyJsPlugin {
         column: err.col,
       });
 
-      if (original && original.source) {
+      if (original && original.source && requestShortener) {
         return new Error(`${file} from UglifyJs\n${err.message} [${requestShortener.shorten(original.source)}:${original.line},${original.column}][${file}:${err.line},${err.col}]`);
       }
+
       return new Error(`${file} from UglifyJs\n${err.message} [${file}:${err.line},${err.col}]`);
     } else if (err.stack) {
       return new Error(`${file} from UglifyJs\n${err.stack}`);
@@ -93,33 +94,34 @@ class UglifyJsPlugin {
 
   static buildWarning(warning, file, sourceMap, warningsFilter, requestShortener) {
     if (!file || !sourceMap) {
-      return warning;
+      return `UglifyJs Plugin: ${warning}`;
     }
 
+    let warningMessage = warning;
+
     const match = warningRegex.exec(warning);
-    const line = +match[1];
-    const column = +match[2];
-    const original = sourceMap.originalPositionFor({
-      line,
-      column,
-    });
-
-    if (!warningsFilter(original.source)) {
-      return null;
-    }
 
-    let warningMessage = warning.replace(warningRegex, '');
+    if (match) {
+      const line = +match[1];
+      const column = +match[2];
+      const original = sourceMap.originalPositionFor({
+        line,
+        column,
+      });
+
+      if (warningsFilter && !warningsFilter(original.source)) {
+        return null;
+      }
 
-    if (original && original.source && original.source !== file) {
-      warningMessage += `[${requestShortener.shorten(original.source)}:${original.line},${original.column}]`;
+      if (original && original.source && original.source !== file && requestShortener) {
+        warningMessage = `${warningMessage.replace(warningRegex, '')}[${requestShortener.shorten(original.source)}:${original.line},${original.column}]`;
+      }
     }
 
     return `UglifyJs Plugin: ${warningMessage} in ${file}`;
   }
 
   apply(compiler) {
-    const requestShortener = new RequestShortener(compiler.context);
-
     const buildModuleFn = (moduleArg) => {
       // to get detailed location info about errors
       moduleArg.useSourceMap = true;
@@ -158,6 +160,7 @@ class UglifyJsPlugin {
                 inputSourceMap = map;
               } else {
                 inputSourceMap = map;
+
                 compilation.warnings.push(
                   new Error(`${file} contains invalid source map`),
                 );
@@ -209,7 +212,7 @@ class UglifyJsPlugin {
                 error,
                 file,
                 UglifyJsPlugin.buildSourceMap(inputSourceMap),
-                requestShortener,
+                new RequestShortener(compiler.context),
               ),
             );
           }
@@ -240,7 +243,7 @@ class UglifyJsPlugin {
                 error,
                 file,
                 sourceMap,
-                requestShortener,
+                new RequestShortener(compiler.context),
               ),
             );
 
@@ -272,7 +275,8 @@ class UglifyJsPlugin {
 
               if (banner) {
                 outputSource = new ConcatSource(
-                  `/*! ${banner} */\n`, outputSource,
+                  `/*! ${banner} */\n`,
+                  outputSource,
                 );
               }
             }
@@ -286,7 +290,9 @@ class UglifyJsPlugin {
                 compilation.assets[commentsFile].add(commentsSource);
               } else {
                 compilation.assets[commentsFile] = new ConcatSource(
-                  compilation.assets[commentsFile], '\n', commentsSource,
+                  compilation.assets[commentsFile],
+                  '\n',
+                  commentsSource,
                 );
               }
             } else {
@@ -305,7 +311,7 @@ class UglifyJsPlugin {
                 file,
                 sourceMap,
                 this.options.warningsFilter,
-                requestShortener,
+                new RequestShortener(compiler.context),
               );
 
               if (builtWarning) {
@@ -321,6 +327,7 @@ class UglifyJsPlugin {
       });
     };
 
+    /* istanbul ignore if */
     if (compiler.hooks) {
       const plugin = { name: 'UglifyJSPlugin' };
 
diff --git a/src/uglify/Runner.js b/src/uglify/Runner.js
index c9c2266..69ee09e 100644
--- a/src/uglify/Runner.js
+++ b/src/uglify/Runner.js
@@ -20,6 +20,7 @@ export default class Runner {
   }
 
   runTasks(tasks, callback) {
+    /* istanbul ignore if */
     if (!tasks.length) {
       callback(null, []);
       return;
@@ -33,8 +34,8 @@ export default class Runner {
       this.boundWorkers = (options, cb) => {
         try {
           cb(null, minify(options));
-        } catch (errors) {
-          cb(errors);
+        } catch (error) {
+          cb(error);
         }
       };
     }


Test patch:
diff --git a/test/UglifyJsPlugin.test.js b/test/UglifyJsPlugin.test.js
index 27ec597..4894c87 100644
--- a/test/UglifyJsPlugin.test.js
+++ b/test/UglifyJsPlugin.test.js
@@ -1,373 +1,26 @@
-import { RawSource } from 'webpack-sources';
+import RequestShortener from 'webpack/lib/RequestShortener';
 import UglifyJsPlugin from '../src/index';
-import { cleanErrorStack, compile, createCompiler, PluginEnvironment } from './helpers';
+import { cleanErrorStack, compile, createCompiler } from './helpers';
 
 describe('UglifyJsPlugin', () => {
-  it('should exported as function', () => {
-    expect(typeof new UglifyJsPlugin().apply).toBe('function');
-  });
-
-  describe('when applied with no options', () => {
-    let eventBindings;
-    let eventBinding;
-
-    beforeEach(() => {
-      const pluginEnvironment = new PluginEnvironment();
-      const compilerEnv = pluginEnvironment.getEnvironmentStub();
-      compilerEnv.context = '';
-
-      const plugin = new UglifyJsPlugin();
-      plugin.apply(compilerEnv);
-      eventBindings = pluginEnvironment.getEventBindings();
-    });
-
-    it('binds one event handler', () => {
-      expect(eventBindings.length).toBe(1);
-    });
-
-    describe('compilation handler', () => {
-      beforeEach(() => {
-        [eventBinding] = eventBindings;
-      });
-
-      it('binds to compilation event', () => {
-        expect(eventBinding.name).toBe('compilation');
-      });
-
-      describe('when called', () => {
-        let chunkPluginEnvironment;
-        let compilationEventBindings;
-        let compilationEventBinding;
-        let compilation;
-        let callback;
-
-        beforeEach(() => {
-          chunkPluginEnvironment = new PluginEnvironment();
-          compilation = chunkPluginEnvironment.getEnvironmentStub();
-          compilation.assets = {
-            'test.js': {},
-            'test1.js': '',
-            'test2.js': {
-              source: () => 'invalid javascript',
-            },
-            'test3.js': {
-              source: () => '/** @preserve Foo Bar */ function foo(longVariableName) { longVariableName = 1; }',
-            },
-          };
-          compilation.warnings = [];
-          compilation.errors = [];
-
-          eventBinding.handler(compilation);
-          compilationEventBindings = chunkPluginEnvironment.getEventBindings();
-        });
-
-        it('binds one event handler', () => {
-          expect(compilationEventBindings.length).toBe(1);
-        });
-
-        describe('optimize-chunk-assets handler', () => {
-          beforeEach(() => {
-            [compilationEventBinding] = compilationEventBindings;
-          });
-
-          it('binds to optimize-chunk-assets event', () => {
-            expect(compilationEventBinding.name).toEqual('optimize-chunk-assets');
-          });
-
-          it('only calls callback once', () => {
-            callback = jest.fn();
-            compilationEventBinding.handler([''], () => {
-              callback();
-              expect(callback.mock.calls.length).toBe(1);
-            });
-          });
-
-          it('default only parses filenames ending with .js', () => {
-            compilationEventBinding.handler([{
-              files: ['test', 'test.js'],
-            }], () => {
-              expect(Object.keys(compilation.assets).length).toBe(4);
-            });
-          });
-
-          it('empty asset', () => {
-            compilationEventBinding.handler([{
-              files: ['test.js'],
-            }], () => {
-              expect(compilation.assets['test.js']).toEqual({});
-            });
-          });
-
-          it('outputs stack trace errors for invalid asset', () => {
-            compilationEventBinding.handler([{
-              files: ['test1.js'],
-            }], () => {
-              expect(compilation.errors.length).toBe(1);
-              expect(compilation.errors[0]).toBeInstanceOf(Error);
-              expect(compilation.errors[0].message).toEqual(expect.stringContaining('asset.source is not a function'));
-            });
-          });
-
-          it('outputs parsing errors for invalid javascript', () => {
-            compilationEventBinding.handler([{
-              files: ['test2.js'],
-            }], () => {
-              expect(compilation.errors.length).toBe(1);
-              expect(compilation.errors[0]).toBeInstanceOf(Error);
-              expect(compilation.errors[0].message).toEqual(expect.stringContaining('Unexpected token'));
-              expect(compilation.errors[0].message).toEqual(expect.stringContaining('[test2.js:1,8]'));
-            });
-          });
-
-          it('outputs no errors for valid javascript', () => {
-            compilationEventBinding.handler([{
-              files: ['test3.js'],
-            }], () => {
-              expect(compilation.errors.length).toBe(0);
-            });
-          });
-
-          it('outputs RawSource for valid javascript', () => {
-            compilationEventBinding.handler([{
-              files: ['test3.js'],
-            }], () => {
-              expect(compilation.assets['test3.js']).toBeInstanceOf(RawSource);
-            });
-          });
-
-          it('outputs mangled javascript', () => {
-            compilationEventBinding.handler([{
-              files: ['test3.js'],
-            }], () => {
-              // eslint-disable-next-line no-underscore-dangle
-              expect(compilation.assets['test3.js']._value).not.toEqual(expect.stringContaining('longVariableName'));
-            });
-          });
-
-          it('compresses and does not output beautified javascript', () => {
-            compilationEventBinding.handler([{
-              files: ['test3.js'],
-            }], () => {
-              // eslint-disable-next-line no-underscore-dangle
-              expect(compilation.assets['test3.js']._value).not.toEqual(expect.stringContaining('\n'));
-            });
-          });
-
-          it('preserves comments', () => {
-            compilationEventBinding.handler([{
-              files: ['test3.js'],
-            }], () => {
-              // eslint-disable-next-line no-underscore-dangle
-              expect(compilation.assets['test3.js']._value).toEqual(expect.stringContaining('/**'));
-            });
-          });
-        });
-      });
-    });
-
-    it('matches snapshot', () => {
-      const compiler = createCompiler();
-      new UglifyJsPlugin().apply(compiler);
-
-      return compile(compiler).then((stats) => {
-        const errors = stats.compilation.errors.map(cleanErrorStack);
-        const warnings = stats.compilation.warnings.map(cleanErrorStack);
-
-        expect(errors).toMatchSnapshot('errors');
-        expect(warnings).toMatchSnapshot('warnings');
-
-        for (const file in stats.compilation.assets) {
-          if (Object.prototype.hasOwnProperty.call(stats.compilation.assets, file)) {
-            expect(stats.compilation.assets[file].source()).toMatchSnapshot(file);
-          }
-        }
-      });
-    });
-  });
-
-  it('should handle validation errors', () => {
-    /* eslint-disable no-new */
-    expect(() => {
-      new UglifyJsPlugin({ test: /foo/ });
-    }).not.toThrow('Validation Error');
-
-    expect(() => {
-      new UglifyJsPlugin({ test: [/foo/] });
-    }).not.toThrow('Validation Error');
-
-    expect(() => {
-      new UglifyJsPlugin({ include: /foo/ });
-    }).not.toThrow('Validation Error');
-
-    expect(() => {
-      new UglifyJsPlugin({ include: [/foo/] });
-    }).not.toThrow('Validation Error');
-
-    expect(() => {
-      new UglifyJsPlugin({ exclude: /foo/ });
-    }).not.toThrow('Validation Error');
-
-    expect(() => {
-      new UglifyJsPlugin({ exclude: [/foo/] });
-    }).not.toThrow('Validation Error');
-
-    expect(() => {
-      new UglifyJsPlugin({ doesntExist: true });
-    }).toThrowErrorMatchingSnapshot();
-
-    expect(() => {
-      new UglifyJsPlugin({ cache: true });
-    }).not.toThrow('Validation Error');
-
-    expect(() => {
-      new UglifyJsPlugin({ cache: false });
-    }).not.toThrow('Validation Error');
-
-    expect(() => {
-      new UglifyJsPlugin({ cache: 'path/to/cache/directory' });
-    }).not.toThrow('Validation Error');
-
-    expect(() => {
-      new UglifyJsPlugin({ cache: {} });
-    }).toThrowErrorMatchingSnapshot();
-
-    expect(() => {
-      new UglifyJsPlugin({ cacheKeys() {} });
-    }).not.toThrow('Validation Error');
-
-    expect(() => {
-      new UglifyJsPlugin({ parallel: true });
-    }).not.toThrow('Validation Error');
-
-    expect(() => {
-      new UglifyJsPlugin({ parallel: false });
-    }).not.toThrow('Validation Error');
-
-    expect(() => {
-      new UglifyJsPlugin({ parallel: 2 });
-    }).not.toThrow('Validation Error');
-
-    expect(() => {
-      new UglifyJsPlugin({ parallel: '2' });
-    }).toThrowErrorMatchingSnapshot();
-
-    expect(() => {
-      new UglifyJsPlugin({ parallel: {} });
-    }).toThrowErrorMatchingSnapshot();
-
-    expect(() => {
-      new UglifyJsPlugin({ sourceMap: true });
-    }).not.toThrow('Validation Error');
-
-    expect(() => {
-      new UglifyJsPlugin({ sourceMap: false });
-    }).not.toThrow('Validation Error');
-
-    expect(() => {
-      new UglifyJsPlugin({ sourceMap: 'true' });
-    }).toThrowErrorMatchingSnapshot();
-
-    expect(() => {
-      new UglifyJsPlugin({ minify() {} });
-    }).not.toThrow('Validation Error');
-
-    expect(() => {
-      new UglifyJsPlugin({ uglifyOptions: null });
-    }).toThrowErrorMatchingSnapshot();
-
-    expect(() => {
-      new UglifyJsPlugin({ uglifyOptions: {} });
-    }).not.toThrow('Validation Error');
-
-    expect(() => {
-      new UglifyJsPlugin({
-        uglifyOptions: {
-          ecma: 5,
-          warnings: false,
-          parse: {},
-          compress: true,
-          mangle: { inline: false },
-          output: { comments: /^\**!|@preserve|@license|@cc_on/ },
-          toplevel: false,
-          nameCache: {},
-          ie8: false,
-          keep_classnames: false,
-          keep_fnames: false,
-          safari10: false,
-        },
-      });
-    }).not.toThrow('Validation Error');
-
-    expect(() => {
-      new UglifyJsPlugin({ uglifyOptions: { ie8: false } });
-    }).not.toThrow('Validation Error');
-
-    expect(() => {
-      new UglifyJsPlugin({ uglifyOptions: { ie8: true } });
-    }).not.toThrow('Validation Error');
-
-    expect(() => {
-      new UglifyJsPlugin({ uglifyOptions: { ie8: 'false' } });
-    }).toThrowErrorMatchingSnapshot();
-
-    expect(() => {
-      new UglifyJsPlugin({ uglifyOptions: { emca: 5 } });
-    }).not.toThrow();
-
-    expect(() => {
-      new UglifyJsPlugin({ uglifyOptions: { emca: 8 } });
-    }).not.toThrow();
-
-    expect(() => {
-      new UglifyJsPlugin({ uglifyOptions: { ecma: 7.5 } });
-    }).toThrowErrorMatchingSnapshot();
-
-    expect(() => {
-      new UglifyJsPlugin({ uglifyOptions: { ecma: true } });
-    }).toThrowErrorMatchingSnapshot();
-
-    expect(() => {
-      new UglifyJsPlugin({ uglifyOptions: { ecma: '5' } });
-    }).toThrowErrorMatchingSnapshot();
-
-    expect(() => {
-      new UglifyJsPlugin({ uglifyOptions: { ecma: 3 } });
-    }).toThrowErrorMatchingSnapshot();
-
-    expect(() => {
-      new UglifyJsPlugin({ uglifyOptions: { ecma: 10 } });
-    }).toThrowErrorMatchingSnapshot();
-
-    expect(() => {
-      new UglifyJsPlugin({ extractComments: true });
-    }).not.toThrow('Validation Error');
-
-    expect(() => {
-      new UglifyJsPlugin({ extractComments: false });
-    }).not.toThrow('Validation Error');
-
-    expect(() => {
-      new UglifyJsPlugin({ extractComments: /comment/ });
-    }).not.toThrow('Validation Error');
-
-    expect(() => {
-      new UglifyJsPlugin({ extractComments() {} });
-    }).not.toThrow('Validation Error');
-
-    expect(() => {
-      new UglifyJsPlugin({ warningsFilter() {} });
-    }).not.toThrow('Validation Error');
-  });
-
-  it('should contains error when uglify has unknown option', () => {
+  const rawSourceMap = {
+    version: 3,
+    file: 'test.js',
+    names: ['bar', 'baz', 'n'],
+    sources: ['one.js', 'two.js'],
+    sourceRoot: 'http://example.com/www/js/',
+    mappings: 'CAAC,IAAI,IAAM,SAAUA,GAClB,OAAOC,IAAID;CCDb,IAAI,IAAM,SAAUE,GAClB,OAAOA',
+  };
+  const emptyRawSourceMap = {
+    version: 3,
+    sources: [],
+    mappings: '',
+  };
+
+  it('should works (without options)', () => {
     const compiler = createCompiler();
-    new UglifyJsPlugin({
-      uglifyOptions: {
-        output: {
-          unknown: true,
-        },
-      },
-    }).apply(compiler);
+
+    new UglifyJsPlugin().apply(compiler);
 
     return compile(compiler).then((stats) => {
       const errors = stats.compilation.errors.map(cleanErrorStack);
@@ -385,20 +38,6 @@ describe('UglifyJsPlugin', () => {
   });
 
   it('isSourceMap method', () => {
-    const rawSourceMap = {
-      version: 3,
-      file: 'min.js',
-      names: ['bar', 'baz', 'n'],
-      sources: ['one.js', 'two.js'],
-      sourceRoot: 'http://example.com/www/js/',
-      mappings: 'CAAC,IAAI,IAAM,SAAUA,GAClB,OAAOC,IAAID;CCDb,IAAI,IAAM,SAAUE,GAClB,OAAOA',
-    };
-    const emptyRawSourceMap = {
-      version: 3,
-      sources: [],
-      mappings: '',
-    };
-
     expect(UglifyJsPlugin.isSourceMap(null)).toBe(false);
     expect(UglifyJsPlugin.isSourceMap()).toBe(false);
     expect(UglifyJsPlugin.isSourceMap({})).toBe(false);
@@ -414,4 +53,97 @@ describe('UglifyJsPlugin', () => {
     expect(UglifyJsPlugin.isSourceMap(rawSourceMap)).toBe(true);
     expect(UglifyJsPlugin.isSourceMap(emptyRawSourceMap)).toBe(true);
   });
+
+  it('buildSourceMap method', () => {
+    expect(UglifyJsPlugin.buildSourceMap()).toBe(null);
+    expect(UglifyJsPlugin.buildSourceMap('invalid')).toBe(null);
+    expect(UglifyJsPlugin.buildSourceMap({})).toBe(null);
+    expect(UglifyJsPlugin.buildSourceMap(rawSourceMap)).toMatchSnapshot();
+  });
+
+  it('buildError method', () => {
+    const error = new Error('Message');
+
+    error.stack = null;
+
+    expect(UglifyJsPlugin.buildError(error, 'test.js')).toMatchSnapshot();
+
+    const errorWithLineAndCol = new Error('Message');
+
+    errorWithLineAndCol.stack = null;
+    errorWithLineAndCol.line = 1;
+    errorWithLineAndCol.col = 1;
+
+    expect(
+      UglifyJsPlugin.buildError(
+        errorWithLineAndCol,
+        'test.js',
+        UglifyJsPlugin.buildSourceMap(rawSourceMap),
+      ),
+    ).toMatchSnapshot();
+
+    const otherErrorWithLineAndCol = new Error('Message');
+
+    otherErrorWithLineAndCol.stack = null;
+    otherErrorWithLineAndCol.line = 1;
+    otherErrorWithLineAndCol.col = 1;
+
+    expect(
+      UglifyJsPlugin.buildError(
+        otherErrorWithLineAndCol,
+        'test.js',
+        UglifyJsPlugin.buildSourceMap(rawSourceMap),
+        new RequestShortener('http://example.com/www/js/'),
+      ),
+    ).toMatchSnapshot();
+
+    const errorWithStack = new Error('Message');
+
+    errorWithStack.stack = 'Stack';
+
+    expect(UglifyJsPlugin.buildError(errorWithStack, 'test.js')).toMatchSnapshot();
+  });
+
+  it('buildWarning method', () => {
+    expect(UglifyJsPlugin.buildWarning('Warning[foo:1,1]')).toMatchSnapshot();
+    expect(UglifyJsPlugin.buildWarning('Warning[foo:1,1]', 'test.js')).toMatchSnapshot();
+    expect(
+      UglifyJsPlugin.buildWarning(
+        'Warning[foo:1,1]',
+        'test.js',
+        UglifyJsPlugin.buildSourceMap(rawSourceMap),
+      ),
+    ).toMatchSnapshot();
+    expect(
+      UglifyJsPlugin.buildWarning(
+        'Warning[foo:1,1]', 'test.js',
+        UglifyJsPlugin.buildSourceMap(rawSourceMap),
+      ),
+    ).toMatchSnapshot();
+    expect(
+      UglifyJsPlugin.buildWarning(
+        'Warning[foo:1,1]',
+        'test.js',
+        UglifyJsPlugin.buildSourceMap(rawSourceMap),
+        () => true,
+      ),
+    ).toMatchSnapshot();
+    expect(
+      UglifyJsPlugin.buildWarning(
+        'Warning[foo:1,1]',
+        'test.js',
+        UglifyJsPlugin.buildSourceMap(rawSourceMap),
+        () => false,
+      ),
+    ).toMatchSnapshot();
+    expect(
+      UglifyJsPlugin.buildWarning(
+        'Warning[foo:1,1]',
+        'test.js',
+        UglifyJsPlugin.buildSourceMap(rawSourceMap),
+        () => true,
+        new RequestShortener('http://example.com/www/js/'),
+      ),
+    ).toMatchSnapshot();
+  });
 });
diff --git a/test/__snapshots__/UglifyJsPlugin.test.js.snap b/test/__snapshots__/UglifyJsPlugin.test.js.snap
index 0acf575..ed4afc1 100644
--- a/test/__snapshots__/UglifyJsPlugin.test.js.snap
+++ b/test/__snapshots__/UglifyJsPlugin.test.js.snap
@@ -1,234 +1,79 @@
 // Jest Snapshot v1, https://goo.gl/fbAQLP
 
-exports[`UglifyJsPlugin should contains error when uglify has unknown option: errors 1`] = `
-Array [
-  "Error: main.0c220ec66316af2c1b24.js from UglifyJs
-DefaultsError: \`unknown\` is not a supported option",
-  "Error: manifest.d6857f782c13a99b5917.js from UglifyJs
-DefaultsError: \`unknown\` is not a supported option",
-]
+exports[`UglifyJsPlugin buildError method 1`] = `
+[Error: test.js from UglifyJs
+Message]
 `;
 
-exports[`UglifyJsPlugin should contains error when uglify has unknown option: main.0c220ec66316af2c1b24.js 1`] = `
-"webpackJsonp([0],[
-/* 0 */
-/***/ (function(module, exports) {
-
-// foo
-/* @preserve*/
-// bar
-const a = 2 + 2;
-
-module.exports = function Foo() {
-  const b = 2 + 2;
-  console.log(b + 1 + 2);
-};
-
-
-/***/ })
-],[0]);"
-`;
-
-exports[`UglifyJsPlugin should contains error when uglify has unknown option: manifest.d6857f782c13a99b5917.js 1`] = `
-"/******/ (function(modules) { // webpackBootstrap
-/******/ 	// install a JSONP callback for chunk loading
-/******/ 	var parentJsonpFunction = window[\\"webpackJsonp\\"];
-/******/ 	window[\\"webpackJsonp\\"] = function webpackJsonpCallback(chunkIds, moreModules, executeModules) {
-/******/ 		// add \\"moreModules\\" to the modules object,
-/******/ 		// then flag all \\"chunkIds\\" as loaded and fire callback
-/******/ 		var moduleId, chunkId, i = 0, resolves = [], result;
-/******/ 		for(;i < chunkIds.length; i++) {
-/******/ 			chunkId = chunkIds[i];
-/******/ 			if(installedChunks[chunkId]) {
-/******/ 				resolves.push(installedChunks[chunkId][0]);
-/******/ 			}
-/******/ 			installedChunks[chunkId] = 0;
-/******/ 		}
-/******/ 		for(moduleId in moreModules) {
-/******/ 			if(Object.prototype.hasOwnProperty.call(moreModules, moduleId)) {
-/******/ 				modules[moduleId] = moreModules[moduleId];
-/******/ 			}
-/******/ 		}
-/******/ 		if(parentJsonpFunction) parentJsonpFunction(chunkIds, moreModules, executeModules);
-/******/ 		while(resolves.length) {
-/******/ 			resolves.shift()();
-/******/ 		}
-/******/ 		if(executeModules) {
-/******/ 			for(i=0; i < executeModules.length; i++) {
-/******/ 				result = __webpack_require__(__webpack_require__.s = executeModules[i]);
-/******/ 			}
-/******/ 		}
-/******/ 		return result;
-/******/ 	};
-/******/
-/******/ 	// The module cache
-/******/ 	var installedModules = {};
-/******/
-/******/ 	// objects to store loaded and loading chunks
-/******/ 	var installedChunks = {
-/******/ 		1: 0
-/******/ 	};
-/******/
-/******/ 	// The require function
-/******/ 	function __webpack_require__(moduleId) {
-/******/
-/******/ 		// Check if module is in cache
-/******/ 		if(installedModules[moduleId]) {
-/******/ 			return installedModules[moduleId].exports;
-/******/ 		}
-/******/ 		// Create a new module (and put it into the cache)
-/******/ 		var module = installedModules[moduleId] = {
-/******/ 			i: moduleId,
-/******/ 			l: false,
-/******/ 			exports: {}
-/******/ 		};
-/******/
-/******/ 		// Execute the module function
-/******/ 		modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
-/******/
-/******/ 		// Flag the module as loaded
-/******/ 		module.l = true;
-/******/
-/******/ 		// Return the exports of the module
-/******/ 		return module.exports;
-/******/ 	}
-/******/
-/******/
-/******/ 	// expose the modules object (__webpack_modules__)
-/******/ 	__webpack_require__.m = modules;
-/******/
-/******/ 	// expose the module cache
-/******/ 	__webpack_require__.c = installedModules;
-/******/
-/******/ 	// define getter function for harmony exports
-/******/ 	__webpack_require__.d = function(exports, name, getter) {
-/******/ 		if(!__webpack_require__.o(exports, name)) {
-/******/ 			Object.defineProperty(exports, name, {
-/******/ 				configurable: false,
-/******/ 				enumerable: true,
-/******/ 				get: getter
-/******/ 			});
-/******/ 		}
-/******/ 	};
-/******/
-/******/ 	// getDefaultExport function for compatibility with non-harmony modules
-/******/ 	__webpack_require__.n = function(module) {
-/******/ 		var getter = module && module.__esModule ?
-/******/ 			function getDefault() { return module['default']; } :
-/******/ 			function getModuleExports() { return module; };
-/******/ 		__webpack_require__.d(getter, 'a', getter);
-/******/ 		return getter;
-/******/ 	};
-/******/
-/******/ 	// Object.prototype.hasOwnProperty.call
-/******/ 	__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
-/******/
-/******/ 	// __webpack_public_path__
-/******/ 	__webpack_require__.p = \\"\\";
-/******/
-/******/ 	// on error function for async loading
-/******/ 	__webpack_require__.oe = function(err) { console.error(err); throw err; };
-/******/ })
-/************************************************************************/
-/******/ ([]);"
-`;
-
-exports[`UglifyJsPlugin should contains error when uglify has unknown option: warnings 1`] = `Array []`;
-
-exports[`UglifyJsPlugin should handle validation errors 1`] = `
-"UglifyJs Plugin Invalid Options
-
-options['doesntExist'] is an invalid additional property
-"
-`;
-
-exports[`UglifyJsPlugin should handle validation errors 2`] = `
-"UglifyJs Plugin Invalid Options
-
-options.cache should be boolean
-options.cache should be string
-options.cache should match exactly one schema in oneOf
-"
-`;
-
-exports[`UglifyJsPlugin should handle validation errors 3`] = `
-"UglifyJs Plugin Invalid Options
-
-options.parallel should be boolean
-options.parallel should be integer
-options.parallel should match exactly one schema in oneOf
-"
+exports[`UglifyJsPlugin buildError method 2`] = `
+[Error: test.js from UglifyJs
+Message [test.js:1,1]]
 `;
 
-exports[`UglifyJsPlugin should handle validation errors 4`] = `
-"UglifyJs Plugin Invalid Options
-
-options.parallel should be boolean
-options.parallel should be integer
-options.parallel should match exactly one schema in oneOf
-"
+exports[`UglifyJsPlugin buildError method 3`] = `
+[Error: test.js from UglifyJs
+Message [./one.js:1,1][test.js:1,1]]
 `;
 
-exports[`UglifyJsPlugin should handle validation errors 5`] = `
-"UglifyJs Plugin Invalid Options
-
-options.sourceMap should be boolean
-"
+exports[`UglifyJsPlugin buildError method 4`] = `
+[Error: test.js from UglifyJs
+Stack]
 `;
 
-exports[`UglifyJsPlugin should handle validation errors 6`] = `
-"UglifyJs Plugin Invalid Options
-
-options.uglifyOptions should be object
-"
+exports[`UglifyJsPlugin buildSourceMap method 1`] = `
+SourceMapConsumer {
+  "_absoluteSources": Array [
+    "http://example.com/www/js/one.js",
+    "http://example.com/www/js/two.js",
+  ],
+  "_mappings": "CAAC,IAAI,IAAM,SAAUA,GAClB,OAAOC,IAAID;CCDb,IAAI,IAAM,SAAUE,GAClB,OAAOA",
+  "_names": ArraySet {
+    "_array": Array [
+      "bar",
+      "baz",
+      "n",
+    ],
+    "_set": Map {
+      "bar" => 0,
+      "baz" => 1,
+      "n" => 2,
+    },
+  },
+  "_sourceMapURL": undefined,
+  "_sources": ArraySet {
+    "_array": Array [
+      "one.js",
+      "two.js",
+    ],
+    "_set": Map {
+      "one.js" => 0,
+      "two.js" => 1,
+    },
+  },
+  "file": "test.js",
+  "sourceRoot": "http://example.com/www/js/",
+  "sourcesContent": null,
+}
 `;
 
-exports[`UglifyJsPlugin should handle validation errors 7`] = `
-"UglifyJs Plugin Invalid Options
+exports[`UglifyJsPlugin buildWarning method 1`] = `"UglifyJs Plugin: Warning[foo:1,1]"`;
 
-options.uglifyOptions.ie8 should be boolean
-"
-`;
-
-exports[`UglifyJsPlugin should handle validation errors 8`] = `
-"UglifyJs Plugin Invalid Options
+exports[`UglifyJsPlugin buildWarning method 2`] = `"UglifyJs Plugin: Warning[foo:1,1]"`;
 
-options.uglifyOptions.ecma should be integer
-"
-`;
+exports[`UglifyJsPlugin buildWarning method 3`] = `"UglifyJs Plugin: Warning[foo:1,1] in test.js"`;
 
-exports[`UglifyJsPlugin should handle validation errors 9`] = `
-"UglifyJs Plugin Invalid Options
+exports[`UglifyJsPlugin buildWarning method 4`] = `"UglifyJs Plugin: Warning[foo:1,1] in test.js"`;
 
-options.uglifyOptions.ecma should be integer
-"
-`;
+exports[`UglifyJsPlugin buildWarning method 5`] = `"UglifyJs Plugin: Warning[foo:1,1] in test.js"`;
 
-exports[`UglifyJsPlugin should handle validation errors 10`] = `
-"UglifyJs Plugin Invalid Options
+exports[`UglifyJsPlugin buildWarning method 6`] = `null`;
 
-options.uglifyOptions.ecma should be integer
-"
-`;
-
-exports[`UglifyJsPlugin should handle validation errors 11`] = `
-"UglifyJs Plugin Invalid Options
-
-options.uglifyOptions.ecma should be >= 5
-"
-`;
-
-exports[`UglifyJsPlugin should handle validation errors 12`] = `
-"UglifyJs Plugin Invalid Options
-
-options.uglifyOptions.ecma should be <= 8
-"
-`;
+exports[`UglifyJsPlugin buildWarning method 7`] = `"UglifyJs Plugin: Warning[./one.js:1,1] in test.js"`;
 
-exports[`UglifyJsPlugin when applied with no options matches snapshot: errors 1`] = `Array []`;
+exports[`UglifyJsPlugin should works (without options): errors 1`] = `Array []`;
 
-exports[`UglifyJsPlugin when applied with no options matches snapshot: main.0c220ec66316af2c1b24.js 1`] = `"webpackJsonp([0],[function(o,n){o.exports=function(){console.log(7)}}],[0]);"`;
+exports[`UglifyJsPlugin should works (without options): main.0c220ec66316af2c1b24.js 1`] = `"webpackJsonp([0],[function(o,n){o.exports=function(){console.log(7)}}],[0]);"`;
 
-exports[`UglifyJsPlugin when applied with no options matches snapshot: manifest.d6857f782c13a99b5917.js 1`] = `"!function(r){var n=window.webpackJsonp;window.webpackJsonp=function(e,u,c){for(var f,i,p,a=0,l=[];a<e.length;a++)i=e[a],o[i]&&l.push(o[i][0]),o[i]=0;for(f in u)Object.prototype.hasOwnProperty.call(u,f)&&(r[f]=u[f]);for(n&&n(e,u,c);l.length;)l.shift()();if(c)for(a=0;a<c.length;a++)p=t(t.s=c[a]);return p};var e={},o={1:0};function t(n){if(e[n])return e[n].exports;var o=e[n]={i:n,l:!1,exports:{}};return r[n].call(o.exports,o,o.exports,t),o.l=!0,o.exports}t.m=r,t.c=e,t.d=function(r,n,e){t.o(r,n)||Object.defineProperty(r,n,{configurable:!1,enumerable:!0,get:e})},t.n=function(r){var n=r&&r.__esModule?function(){return r.default}:function(){return r};return t.d(n,\\"a\\",n),n},t.o=function(r,n){return Object.prototype.hasOwnProperty.call(r,n)},t.p=\\"\\",t.oe=function(r){throw console.error(r),r}}([]);"`;
+exports[`UglifyJsPlugin should works (without options): manifest.d6857f782c13a99b5917.js 1`] = `"!function(r){var n=window.webpackJsonp;window.webpackJsonp=function(e,u,c){for(var f,i,p,a=0,l=[];a<e.length;a++)i=e[a],o[i]&&l.push(o[i][0]),o[i]=0;for(f in u)Object.prototype.hasOwnProperty.call(u,f)&&(r[f]=u[f]);for(n&&n(e,u,c);l.length;)l.shift()();if(c)for(a=0;a<c.length;a++)p=t(t.s=c[a]);return p};var e={},o={1:0};function t(n){if(e[n])return e[n].exports;var o=e[n]={i:n,l:!1,exports:{}};return r[n].call(o.exports,o,o.exports,t),o.l=!0,o.exports}t.m=r,t.c=e,t.d=function(r,n,e){t.o(r,n)||Object.defineProperty(r,n,{configurable:!1,enumerable:!0,get:e})},t.n=function(r){var n=r&&r.__esModule?function(){return r.default}:function(){return r};return t.d(n,\\"a\\",n),n},t.o=function(r,n){return Object.prototype.hasOwnProperty.call(r,n)},t.p=\\"\\",t.oe=function(r){throw console.error(r),r}}([]);"`;
 
-exports[`UglifyJsPlugin when applied with no options matches snapshot: warnings 1`] = `Array []`;
+exports[`UglifyJsPlugin should works (without options): warnings 1`] = `Array []`;
diff --git a/test/__snapshots__/cache-option.test.js.snap b/test/__snapshots__/cache-option.test.js.snap
index ad5e3d8..68582aa 100644
--- a/test/__snapshots__/cache-option.test.js.snap
+++ b/test/__snapshots__/cache-option.test.js.snap
@@ -202,3 +202,148 @@ exports[`when applied with \`cache\` option matches snapshot for \`true\` value:
 exports[`when applied with \`cache\` option matches snapshot for \`true\` value: warnings 1`] = `Array []`;
 
 exports[`when applied with \`cache\` option matches snapshot for \`true\` value: warnings 2`] = `Array []`;
+
+exports[`when applied with \`cache\` option matches snapshot for errors into \`cacheKeys\` option: errors 1`] = `
+Array [
+  "Error: one.91254a4178472993cf9f.js from UglifyJs
+Error: message",
+  "Error: two.e9fc295fcef530d66dc5.js from UglifyJs
+Error: message",
+  "Error: three.16209e63e6e5fb2ca2e3.js from UglifyJs
+Error: message",
+  "Error: four.0741ac92c5e76ec45240.js from UglifyJs
+Error: message",
+  "Error: manifest.f504b5c36c66d8aa6a74.js from UglifyJs
+Error: message",
+]
+`;
+
+exports[`when applied with \`cache\` option matches snapshot for errors into \`cacheKeys\` option: four.0741ac92c5e76ec45240.js 1`] = `"webpackJsonp([3],[],[0]);"`;
+
+exports[`when applied with \`cache\` option matches snapshot for errors into \`cacheKeys\` option: manifest.f504b5c36c66d8aa6a74.js 1`] = `
+"/******/ (function(modules) { // webpackBootstrap
+/******/ 	// install a JSONP callback for chunk loading
+/******/ 	var parentJsonpFunction = window[\\"webpackJsonp\\"];
+/******/ 	window[\\"webpackJsonp\\"] = function webpackJsonpCallback(chunkIds, moreModules, executeModules) {
+/******/ 		// add \\"moreModules\\" to the modules object,
+/******/ 		// then flag all \\"chunkIds\\" as loaded and fire callback
+/******/ 		var moduleId, chunkId, i = 0, resolves = [], result;
+/******/ 		for(;i < chunkIds.length; i++) {
+/******/ 			chunkId = chunkIds[i];
+/******/ 			if(installedChunks[chunkId]) {
+/******/ 				resolves.push(installedChunks[chunkId][0]);
+/******/ 			}
+/******/ 			installedChunks[chunkId] = 0;
+/******/ 		}
+/******/ 		for(moduleId in moreModules) {
+/******/ 			if(Object.prototype.hasOwnProperty.call(moreModules, moduleId)) {
+/******/ 				modules[moduleId] = moreModules[moduleId];
+/******/ 			}
+/******/ 		}
+/******/ 		if(parentJsonpFunction) parentJsonpFunction(chunkIds, moreModules, executeModules);
+/******/ 		while(resolves.length) {
+/******/ 			resolves.shift()();
+/******/ 		}
+/******/ 		if(executeModules) {
+/******/ 			for(i=0; i < executeModules.length; i++) {
+/******/ 				result = __webpack_require__(__webpack_require__.s = executeModules[i]);
+/******/ 			}
+/******/ 		}
+/******/ 		return result;
+/******/ 	};
+/******/
+/******/ 	// The module cache
+/******/ 	var installedModules = {};
+/******/
+/******/ 	// objects to store loaded and loading chunks
+/******/ 	var installedChunks = {
+/******/ 		4: 0
+/******/ 	};
+/******/
+/******/ 	// The require function
+/******/ 	function __webpack_require__(moduleId) {
+/******/
+/******/ 		// Check if module is in cache
+/******/ 		if(installedModules[moduleId]) {
+/******/ 			return installedModules[moduleId].exports;
+/******/ 		}
+/******/ 		// Create a new module (and put it into the cache)
+/******/ 		var module = installedModules[moduleId] = {
+/******/ 			i: moduleId,
+/******/ 			l: false,
+/******/ 			exports: {}
+/******/ 		};
+/******/
+/******/ 		// Execute the module function
+/******/ 		modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
+/******/
+/******/ 		// Flag the module as loaded
+/******/ 		module.l = true;
+/******/
+/******/ 		// Return the exports of the module
+/******/ 		return module.exports;
+/******/ 	}
+/******/
+/******/
+/******/ 	// expose the modules object (__webpack_modules__)
+/******/ 	__webpack_require__.m = modules;
+/******/
+/******/ 	// expose the module cache
+/******/ 	__webpack_require__.c = installedModules;
+/******/
+/******/ 	// define getter function for harmony exports
+/******/ 	__webpack_require__.d = function(exports, name, getter) {
+/******/ 		if(!__webpack_require__.o(exports, name)) {
+/******/ 			Object.defineProperty(exports, name, {
+/******/ 				configurable: false,
+/******/ 				enumerable: true,
+/******/ 				get: getter
+/******/ 			});
+/******/ 		}
+/******/ 	};
+/******/
+/******/ 	// getDefaultExport function for compatibility with non-harmony modules
+/******/ 	__webpack_require__.n = function(module) {
+/******/ 		var getter = module && module.__esModule ?
+/******/ 			function getDefault() { return module['default']; } :
+/******/ 			function getModuleExports() { return module; };
+/******/ 		__webpack_require__.d(getter, 'a', getter);
+/******/ 		return getter;
+/******/ 	};
+/******/
+/******/ 	// Object.prototype.hasOwnProperty.call
+/******/ 	__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
+/******/
+/******/ 	// __webpack_public_path__
+/******/ 	__webpack_require__.p = \\"\\";
+/******/
+/******/ 	// on error function for async loading
+/******/ 	__webpack_require__.oe = function(err) { console.error(err); throw err; };
+/******/ })
+/************************************************************************/
+/******/ ([
+/* 0 */
+/***/ (function(module, exports) {
+
+// foo
+/* @preserve*/
+// bar
+const a = 2 + 2;
+
+module.exports = function Foo() {
+  const b = 2 + 2;
+  console.log(b + 1 + 2);
+};
+
+
+/***/ })
+/******/ ]);"
+`;
+
+exports[`when applied with \`cache\` option matches snapshot for errors into \`cacheKeys\` option: one.91254a4178472993cf9f.js 1`] = `"webpackJsonp([0],[],[0]);"`;
+
+exports[`when applied with \`cache\` option matches snapshot for errors into \`cacheKeys\` option: three.16209e63e6e5fb2ca2e3.js 1`] = `"webpackJsonp([2],[],[0]);"`;
+
+exports[`when applied with \`cache\` option matches snapshot for errors into \`cacheKeys\` option: two.e9fc295fcef530d66dc5.js 1`] = `"webpackJsonp([1],[],[0]);"`;
+
+exports[`when applied with \`cache\` option matches snapshot for errors into \`cacheKeys\` option: warnings 1`] = `Array []`;
diff --git a/test/__snapshots__/extractComments-option.test.js.snap b/test/__snapshots__/extractComments-option.test.js.snap
index 9fc6d02..9193bc4 100644
--- a/test/__snapshots__/extractComments-option.test.js.snap
+++ b/test/__snapshots__/extractComments-option.test.js.snap
@@ -1,130 +1,1995 @@
 // Jest Snapshot v1, https://goo.gl/fbAQLP
 
-exports[`when options.extractComments normalizes when options.extractComments is boolean - "true": errors 1`] = `Array []`;
+exports[`when applied with \`extractComments\` option matches snapshot for a \`/Foo/\` value (regexp): chunks/0.0.42bf13661c716a174f76.js 1`] = `
+"/*! For license information please see 0.0.42bf13661c716a174f76.js.LICENSE */
+webpackJsonp([0],[,function(n,o){n.exports=Math.random()}]);"
+`;
 
-exports[`when options.extractComments normalizes when options.extractComments is boolean - "true": test.js 1`] = `"var foo=1;"`;
+exports[`when applied with \`extractComments\` option matches snapshot for a \`/Foo/\` value (regexp): chunks/0.0.42bf13661c716a174f76.js.LICENSE 1`] = `
+"/*! Legal Foo */
 
-exports[`when options.extractComments normalizes when options.extractComments is boolean - "true": test1.js 1`] = `
-"/*! For license information please see test1.js.LICENSE */
-var foo=1;"
-`;
+// Foo
 
-exports[`when options.extractComments normalizes when options.extractComments is boolean - "true": test1.js.LICENSE 1`] = `
-"/*! Legal Comment */
+/*
+ Foo Bar
+ */
+
+/*
+* Foo
+*/
 "
 `;
 
-exports[`when options.extractComments normalizes when options.extractComments is boolean - "true": warnings 1`] = `Array []`;
+exports[`when applied with \`extractComments\` option matches snapshot for a \`/Foo/\` value (regexp): errors 1`] = `Array []`;
 
-exports[`when options.extractComments normalizes when options.extractComments is function: errors 1`] = `Array []`;
+exports[`when applied with \`extractComments\` option matches snapshot for a \`/Foo/\` value (regexp): filename/manifest.3221d314bfa94c03ba98.js 1`] = `"!function(e){var n=window.webpackJsonp;window.webpackJsonp=function(r,c,u){for(var a,i,f,s=0,l=[];s<r.length;s++)i=r[s],t[i]&&l.push(t[i][0]),t[i]=0;for(a in c)Object.prototype.hasOwnProperty.call(c,a)&&(e[a]=c[a]);for(n&&n(r,c,u);l.length;)l.shift()();if(u)for(s=0;s<u.length;s++)f=o(o.s=u[s]);return f};var r={},t={2:0};function o(n){if(r[n])return r[n].exports;var t=r[n]={i:n,l:!1,exports:{}};return e[n].call(t.exports,t,t.exports,o),t.l=!0,t.exports}o.e=function(e){var n=t[e];if(0===n)return new Promise(function(e){e()});if(n)return n[2];var r=new Promise(function(r,o){n=t[e]=[r,o]});n[2]=r;var c=document.getElementsByTagName(\\"head\\")[0],u=document.createElement(\\"script\\");u.type=\\"text/javascript\\",u.charset=\\"utf-8\\",u.async=!0,u.timeout=12e4,o.nc&&u.setAttribute(\\"nonce\\",o.nc),u.src=o.p+\\"chunks/\\"+e+\\".\\"+({}[e]||e)+\\".\\"+{0:\\"42bf13661c716a174f76\\"}[e]+\\".js\\";var a=setTimeout(i,12e4);function i(){u.onerror=u.onload=null,clearTimeout(a);var n=t[e];0!==n&&(n&&n[1](new Error(\\"Loading chunk \\"+e+\\" failed.\\")),t[e]=void 0)}return u.onerror=u.onload=i,c.appendChild(u),r},o.m=e,o.c=r,o.d=function(e,n,r){o.o(e,n)||Object.defineProperty(e,n,{configurable:!1,enumerable:!0,get:r})},o.n=function(e){var n=e&&e.__esModule?function(){return e.default}:function(){return e};return o.d(n,\\"a\\",n),n},o.o=function(e,n){return Object.prototype.hasOwnProperty.call(e,n)},o.p=\\"\\",o.oe=function(e){throw console.error(e),e}}([]);"`;
 
-exports[`when options.extractComments normalizes when options.extractComments is function: test.js 1`] = `
-"/*! For license information please see test.js.LICENSE */
-var foo=1;"
+exports[`when applied with \`extractComments\` option matches snapshot for a \`/Foo/\` value (regexp): filename/one.1ba6f44f8286da40c97f.js 1`] = `
+"/*! For license information please see one.1ba6f44f8286da40c97f.js.LICENSE */
+webpackJsonp([1],[function(n,e,o){o.e(0).then(o.bind(null,1)),n.exports=Math.random()}],[0]);"
 `;
 
-exports[`when options.extractComments normalizes when options.extractComments is function: test.js.LICENSE 1`] = `
-"// Comment
+exports[`when applied with \`extractComments\` option matches snapshot for a \`/Foo/\` value (regexp): filename/one.1ba6f44f8286da40c97f.js.LICENSE 1`] = `
+"/*! Legal Foo */
+
+// Foo
+
+/*
+ Foo Bar
+ */
+
+/*
+* Foo
+*/
 "
 `;
 
-exports[`when options.extractComments normalizes when options.extractComments is function: test1.js 1`] = `
-"/*! For license information please see test1.js.LICENSE */
-var foo=1;"
-`;
+exports[`when applied with \`extractComments\` option matches snapshot for a \`/Foo/\` value (regexp): warnings 1`] = `Array []`;
 
-exports[`when options.extractComments normalizes when options.extractComments is function: test1.js.LICENSE 1`] = `
-"/* Comment */
-"
+exports[`when applied with \`extractComments\` option matches snapshot for a \`Foo\` value (string): chunks/0.0.42bf13661c716a174f76.js 1`] = `
+"/*! For license information please see 0.0.42bf13661c716a174f76.js.LICENSE */
+webpackJsonp([0],[,function(n,o){n.exports=Math.random()}]);"
 `;
 
-exports[`when options.extractComments normalizes when options.extractComments is function: warnings 1`] = `Array []`;
+exports[`when applied with \`extractComments\` option matches snapshot for a \`Foo\` value (string): chunks/0.0.42bf13661c716a174f76.js.LICENSE 1`] = `
+"/*! Legal Foo */
 
-exports[`when options.extractComments normalizes when options.extractComments is not specify: errors 1`] = `Array []`;
+// Foo
 
-exports[`when options.extractComments normalizes when options.extractComments is not specify: test.js 1`] = `"var foo=1;"`;
+/*
+ Foo Bar
+ */
 
-exports[`when options.extractComments normalizes when options.extractComments is not specify: test1.js 1`] = `
-"/*! Legal Comment */
-var foo=1;"
+/*
+* Foo
+*/
+"
 `;
 
-exports[`when options.extractComments normalizes when options.extractComments is not specify: warnings 1`] = `Array []`;
+exports[`when applied with \`extractComments\` option matches snapshot for a \`Foo\` value (string): errors 1`] = `Array []`;
 
-exports[`when options.extractComments normalizes when options.extractComments is object: errors 1`] = `Array []`;
+exports[`when applied with \`extractComments\` option matches snapshot for a \`Foo\` value (string): filename/manifest.3221d314bfa94c03ba98.js 1`] = `"!function(e){var n=window.webpackJsonp;window.webpackJsonp=function(r,c,u){for(var a,i,f,s=0,l=[];s<r.length;s++)i=r[s],t[i]&&l.push(t[i][0]),t[i]=0;for(a in c)Object.prototype.hasOwnProperty.call(c,a)&&(e[a]=c[a]);for(n&&n(r,c,u);l.length;)l.shift()();if(u)for(s=0;s<u.length;s++)f=o(o.s=u[s]);return f};var r={},t={2:0};function o(n){if(r[n])return r[n].exports;var t=r[n]={i:n,l:!1,exports:{}};return e[n].call(t.exports,t,t.exports,o),t.l=!0,t.exports}o.e=function(e){var n=t[e];if(0===n)return new Promise(function(e){e()});if(n)return n[2];var r=new Promise(function(r,o){n=t[e]=[r,o]});n[2]=r;var c=document.getElementsByTagName(\\"head\\")[0],u=document.createElement(\\"script\\");u.type=\\"text/javascript\\",u.charset=\\"utf-8\\",u.async=!0,u.timeout=12e4,o.nc&&u.setAttribute(\\"nonce\\",o.nc),u.src=o.p+\\"chunks/\\"+e+\\".\\"+({}[e]||e)+\\".\\"+{0:\\"42bf13661c716a174f76\\"}[e]+\\".js\\";var a=setTimeout(i,12e4);function i(){u.onerror=u.onload=null,clearTimeout(a);var n=t[e];0!==n&&(n&&n[1](new Error(\\"Loading chunk \\"+e+\\" failed.\\")),t[e]=void 0)}return u.onerror=u.onload=i,c.appendChild(u),r},o.m=e,o.c=r,o.d=function(e,n,r){o.o(e,n)||Object.defineProperty(e,n,{configurable:!1,enumerable:!0,get:r})},o.n=function(e){var n=e&&e.__esModule?function(){return e.default}:function(){return e};return o.d(n,\\"a\\",n),n},o.o=function(e,n){return Object.prototype.hasOwnProperty.call(e,n)},o.p=\\"\\",o.oe=function(e){throw console.error(e),e}}([]);"`;
 
-exports[`when options.extractComments normalizes when options.extractComments is object: test.js 1`] = `
-"/*! License information can be found in test.license.js */
-var foo=1;"
+exports[`when applied with \`extractComments\` option matches snapshot for a \`Foo\` value (string): filename/one.1ba6f44f8286da40c97f.js 1`] = `
+"/*! For license information please see one.1ba6f44f8286da40c97f.js.LICENSE */
+webpackJsonp([1],[function(n,e,o){o.e(0).then(o.bind(null,1)),n.exports=Math.random()}],[0]);"
 `;
 
-exports[`when options.extractComments normalizes when options.extractComments is object: test.license.js 1`] = `
-"// Comment
+exports[`when applied with \`extractComments\` option matches snapshot for a \`Foo\` value (string): filename/one.1ba6f44f8286da40c97f.js.LICENSE 1`] = `
+"/*! Legal Foo */
+
+// Foo
+
+/*
+ Foo Bar
+ */
+
+/*
+* Foo
+*/
 "
 `;
 
-exports[`when options.extractComments normalizes when options.extractComments is object: warnings 1`] = `Array []`;
+exports[`when applied with \`extractComments\` option matches snapshot for a \`Foo\` value (string): warnings 1`] = `Array []`;
 
-exports[`when options.extractComments normalizes when options.extractComments is regex: errors 1`] = `Array []`;
+exports[`when applied with \`extractComments\` option matches snapshot for a \`all\` value (string): chunks/0.0.42bf13661c716a174f76.js 1`] = `
+"/*! For license information please see 0.0.42bf13661c716a174f76.js.LICENSE */
+webpackJsonp([0],[,function(n,o){n.exports=Math.random()}]);"
+`;
 
-exports[`when options.extractComments normalizes when options.extractComments is regex: test.js 1`] = `"var foo=1;"`;
+exports[`when applied with \`extractComments\` option matches snapshot for a \`all\` value (string): chunks/0.0.42bf13661c716a174f76.js.LICENSE 1`] = `
+"/* 0 */
 
-exports[`when options.extractComments normalizes when options.extractComments is regex: test1.js 1`] = `
-"/*! For license information please see test1.js.LICENSE */
-var foo=1;"
-`;
+/* 1 */
 
-exports[`when options.extractComments normalizes when options.extractComments is regex: test1.js.LICENSE 1`] = `
-"// foo
+/***/
+
+/* 1 */
+
+/***/
+
+/*! Legal Comment */
+
+/**
+ * @preserve Copyright 2009 SomeThirdParty.
+ * Here is the full license text and copyright
+ * notice for this file. Note that the notice can span several
+ * lines and is only terminated by the closing star and slash:
+ */
+
+/**
+ * Utility functions for the foo package.
+ * @license Apache-2.0
+ */
+
+/*! Legal Foo */
+
+// Foo
+
+/*
+ Foo Bar
+ */
+
+/*
+* Foo
+*/
+
+/***/
 "
 `;
 
-exports[`when options.extractComments normalizes when options.extractComments is regex: warnings 1`] = `Array []`;
+exports[`when applied with \`extractComments\` option matches snapshot for a \`all\` value (string): errors 1`] = `Array []`;
 
-exports[`when options.extractComments normalizes when options.extractComments is string - "all" && license file should be relative source file: errors 1`] = `Array []`;
-
-exports[`when options.extractComments normalizes when options.extractComments is string - "all" && license file should be relative source file: nested/nested/test1.js 1`] = `
-"/*! For license information please see test1.js.LICENSE */
-var foo=1;"
+exports[`when applied with \`extractComments\` option matches snapshot for a \`all\` value (string): filename/manifest.3221d314bfa94c03ba98.js 1`] = `
+"/*! For license information please see manifest.3221d314bfa94c03ba98.js.LICENSE */
+!function(e){var n=window.webpackJsonp;window.webpackJsonp=function(r,c,u){for(var a,i,f,s=0,l=[];s<r.length;s++)i=r[s],t[i]&&l.push(t[i][0]),t[i]=0;for(a in c)Object.prototype.hasOwnProperty.call(c,a)&&(e[a]=c[a]);for(n&&n(r,c,u);l.length;)l.shift()();if(u)for(s=0;s<u.length;s++)f=o(o.s=u[s]);return f};var r={},t={2:0};function o(n){if(r[n])return r[n].exports;var t=r[n]={i:n,l:!1,exports:{}};return e[n].call(t.exports,t,t.exports,o),t.l=!0,t.exports}o.e=function(e){var n=t[e];if(0===n)return new Promise(function(e){e()});if(n)return n[2];var r=new Promise(function(r,o){n=t[e]=[r,o]});n[2]=r;var c=document.getElementsByTagName(\\"head\\")[0],u=document.createElement(\\"script\\");u.type=\\"text/javascript\\",u.charset=\\"utf-8\\",u.async=!0,u.timeout=12e4,o.nc&&u.setAttribute(\\"nonce\\",o.nc),u.src=o.p+\\"chunks/\\"+e+\\".\\"+({}[e]||e)+\\".\\"+{0:\\"42bf13661c716a174f76\\"}[e]+\\".js\\";var a=setTimeout(i,12e4);function i(){u.onerror=u.onload=null,clearTimeout(a);var n=t[e];0!==n&&(n&&n[1](new Error(\\"Loading chunk \\"+e+\\" failed.\\")),t[e]=void 0)}return u.onerror=u.onload=i,c.appendChild(u),r},o.m=e,o.c=r,o.d=function(e,n,r){o.o(e,n)||Object.defineProperty(e,n,{configurable:!1,enumerable:!0,get:r})},o.n=function(e){var n=e&&e.__esModule?function(){return e.default}:function(){return e};return o.d(n,\\"a\\",n),n},o.o=function(e,n){return Object.prototype.hasOwnProperty.call(e,n)},o.p=\\"\\",o.oe=function(e){throw console.error(e),e}}([]);"
 `;
 
-exports[`when options.extractComments normalizes when options.extractComments is string - "all" && license file should be relative source file: nested/nested/test1.js.LICENSE 1`] = `
-"/* Comment */
+exports[`when applied with \`extractComments\` option matches snapshot for a \`all\` value (string): filename/manifest.3221d314bfa94c03ba98.js.LICENSE 1`] = `
+"/******/
+
+// webpackBootstrap
+
+/******/
+
+// install a JSONP callback for chunk loading
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+// add \\"moreModules\\" to the modules object,
+
+/******/
+
+// then flag all \\"chunkIds\\" as loaded and fire callback
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+// The module cache
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+// objects to store loaded and loading chunks
+
+/******/
+
+/******/
+
+/******/
+
+// The require function
+
+/******/
+
+/******/
+
+/******/
+
+// Check if module is in cache
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+// Create a new module (and put it into the cache)
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+// Execute the module function
+
+/******/
+
+/******/
+
+/******/
+
+// Return the exports of the module
+
+/******/
+
+/******/
+
+/******/
+
+// Flag the module as loaded
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+// This file contains only the entry chunk.
+
+/******/
+
+// The chunk loading function for additional chunks
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+// a Promise means \\"currently loading\\".
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+// setup Promise in chunk cache
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+// start chunk loading
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+// avoid mem leaks in IE.
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+// expose the modules object (__webpack_modules__)
+
+/******/
+
+/******/
+
+/******/
+
+// expose the module cache
+
+/******/
+
+/******/
+
+/******/
+
+// define getter function for harmony exports
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+// getDefaultExport function for compatibility with non-harmony modules
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+// Object.prototype.hasOwnProperty.call
+
+/******/
+
+/******/
+
+/******/
+
+// __webpack_public_path__
+
+/******/
+
+/******/
+
+/******/
+
+// on error function for async loading
+
+/******/
+
+/************************************************************************/
+
+/******/
 "
 `;
 
-exports[`when options.extractComments normalizes when options.extractComments is string - "all" && license file should be relative source file: nested/test.js 1`] = `
-"/*! For license information please see test.js.LICENSE */
-var foo=1;"
+exports[`when applied with \`extractComments\` option matches snapshot for a \`all\` value (string): filename/one.1ba6f44f8286da40c97f.js 1`] = `
+"/*! For license information please see one.1ba6f44f8286da40c97f.js.LICENSE */
+webpackJsonp([1],[function(n,e,o){o.e(0).then(o.bind(null,1)),n.exports=Math.random()}],[0]);"
 `;
 
-exports[`when options.extractComments normalizes when options.extractComments is string - "all" && license file should be relative source file: nested/test.js.LICENSE 1`] = `
-"// Comment
+exports[`when applied with \`extractComments\` option matches snapshot for a \`all\` value (string): filename/one.1ba6f44f8286da40c97f.js.LICENSE 1`] = `
+"/* 0 */
+
+/***/
+
+/* import() */
+
+/*! Legal Comment */
+
+/**
+ * @preserve Copyright 2009 SomeThirdParty.
+ * Here is the full license text and copyright
+ * notice for this file. Note that the notice can span several
+ * lines and is only terminated by the closing star and slash:
+ */
+
+/**
+ * Utility functions for the foo package.
+ * @license Apache-2.0
+ */
+
+/*! Legal Foo */
+
+// Foo
+
+/*
+ Foo Bar
+ */
+
+/*
+* Foo
+*/
 "
 `;
 
-exports[`when options.extractComments normalizes when options.extractComments is string - "all" && license file should be relative source file: warnings 1`] = `Array []`;
+exports[`when applied with \`extractComments\` option matches snapshot for a \`all\` value (string): warnings 1`] = `Array []`;
+
+exports[`when applied with \`extractComments\` option matches snapshot for a \`false\` value: chunks/0.0.42bf13661c716a174f76.js 1`] = `
+"webpackJsonp([0],[,function(n,o){
+/*! Legal Comment */
+/**
+ * @preserve Copyright 2009 SomeThirdParty.
+ * Here is the full license text and copyright
+ * notice for this file. Note that the notice can span several
+ * lines and is only terminated by the closing star and slash:
+ */
+/**
+ * Utility functions for the foo package.
+ * @license Apache-2.0
+ */
+/*! Legal Foo */
+n.exports=Math.random()}]);"
+`;
+
+exports[`when applied with \`extractComments\` option matches snapshot for a \`false\` value: errors 1`] = `Array []`;
+
+exports[`when applied with \`extractComments\` option matches snapshot for a \`false\` value: filename/manifest.3221d314bfa94c03ba98.js 1`] = `"!function(e){var n=window.webpackJsonp;window.webpackJsonp=function(r,c,u){for(var a,i,f,s=0,l=[];s<r.length;s++)i=r[s],t[i]&&l.push(t[i][0]),t[i]=0;for(a in c)Object.prototype.hasOwnProperty.call(c,a)&&(e[a]=c[a]);for(n&&n(r,c,u);l.length;)l.shift()();if(u)for(s=0;s<u.length;s++)f=o(o.s=u[s]);return f};var r={},t={2:0};function o(n){if(r[n])return r[n].exports;var t=r[n]={i:n,l:!1,exports:{}};return e[n].call(t.exports,t,t.exports,o),t.l=!0,t.exports}o.e=function(e){var n=t[e];if(0===n)return new Promise(function(e){e()});if(n)return n[2];var r=new Promise(function(r,o){n=t[e]=[r,o]});n[2]=r;var c=document.getElementsByTagName(\\"head\\")[0],u=document.createElement(\\"script\\");u.type=\\"text/javascript\\",u.charset=\\"utf-8\\",u.async=!0,u.timeout=12e4,o.nc&&u.setAttribute(\\"nonce\\",o.nc),u.src=o.p+\\"chunks/\\"+e+\\".\\"+({}[e]||e)+\\".\\"+{0:\\"42bf13661c716a174f76\\"}[e]+\\".js\\";var a=setTimeout(i,12e4);function i(){u.onerror=u.onload=null,clearTimeout(a);var n=t[e];0!==n&&(n&&n[1](new Error(\\"Loading chunk \\"+e+\\" failed.\\")),t[e]=void 0)}return u.onerror=u.onload=i,c.appendChild(u),r},o.m=e,o.c=r,o.d=function(e,n,r){o.o(e,n)||Object.defineProperty(e,n,{configurable:!1,enumerable:!0,get:r})},o.n=function(e){var n=e&&e.__esModule?function(){return e.default}:function(){return e};return o.d(n,\\"a\\",n),n},o.o=function(e,n){return Object.prototype.hasOwnProperty.call(e,n)},o.p=\\"\\",o.oe=function(e){throw console.error(e),e}}([]);"`;
+
+exports[`when applied with \`extractComments\` option matches snapshot for a \`false\` value: filename/one.1ba6f44f8286da40c97f.js 1`] = `
+"webpackJsonp([1],[function(n,e,o){o.e(0).then(o.bind(null,1)),
+/*! Legal Comment */
+/**
+ * @preserve Copyright 2009 SomeThirdParty.
+ * Here is the full license text and copyright
+ * notice for this file. Note that the notice can span several
+ * lines and is only terminated by the closing star and slash:
+ */
+/**
+ * Utility functions for the foo package.
+ * @license Apache-2.0
+ */
+/*! Legal Foo */
+n.exports=Math.random()}],[0]);"
+`;
 
-exports[`when options.extractComments normalizes when options.extractComments is string: errors 1`] = `Array []`;
+exports[`when applied with \`extractComments\` option matches snapshot for a \`false\` value: warnings 1`] = `Array []`;
 
-exports[`when options.extractComments normalizes when options.extractComments is string: test.js 1`] = `
-"/*! For license information please see test.js.LICENSE */
-var foo=1;"
+exports[`when applied with \`extractComments\` option matches snapshot for a \`function value: chunks/0.0.42bf13661c716a174f76.js 1`] = `
+"/*! For license information please see 0.0.42bf13661c716a174f76.js.LICENSE */
+webpackJsonp([0],[,function(n,o){n.exports=Math.random()}]);"
 `;
 
-exports[`when options.extractComments normalizes when options.extractComments is string: test.js.LICENSE 1`] = `
-"// Comment
+exports[`when applied with \`extractComments\` option matches snapshot for a \`function value: chunks/0.0.42bf13661c716a174f76.js.LICENSE 1`] = `
+"/* 0 */
+
+/* 1 */
+
+/***/
+
+/* 1 */
+
+/***/
+
+/*! Legal Comment */
+
+/**
+ * @preserve Copyright 2009 SomeThirdParty.
+ * Here is the full license text and copyright
+ * notice for this file. Note that the notice can span several
+ * lines and is only terminated by the closing star and slash:
+ */
+
+/**
+ * Utility functions for the foo package.
+ * @license Apache-2.0
+ */
+
+/*! Legal Foo */
+
+// Foo
+
+/*
+ Foo Bar
+ */
+
+/*
+* Foo
+*/
+
+/***/
 "
 `;
 
-exports[`when options.extractComments normalizes when options.extractComments is string: test1.js 1`] = `
-"/*! For license information please see test1.js.LICENSE */
-var foo=1;"
+exports[`when applied with \`extractComments\` option matches snapshot for a \`function value: errors 1`] = `Array []`;
+
+exports[`when applied with \`extractComments\` option matches snapshot for a \`function value: filename/manifest.3221d314bfa94c03ba98.js 1`] = `
+"/*! For license information please see manifest.3221d314bfa94c03ba98.js.LICENSE */
+!function(e){var n=window.webpackJsonp;window.webpackJsonp=function(r,c,u){for(var a,i,f,s=0,l=[];s<r.length;s++)i=r[s],t[i]&&l.push(t[i][0]),t[i]=0;for(a in c)Object.prototype.hasOwnProperty.call(c,a)&&(e[a]=c[a]);for(n&&n(r,c,u);l.length;)l.shift()();if(u)for(s=0;s<u.length;s++)f=o(o.s=u[s]);return f};var r={},t={2:0};function o(n){if(r[n])return r[n].exports;var t=r[n]={i:n,l:!1,exports:{}};return e[n].call(t.exports,t,t.exports,o),t.l=!0,t.exports}o.e=function(e){var n=t[e];if(0===n)return new Promise(function(e){e()});if(n)return n[2];var r=new Promise(function(r,o){n=t[e]=[r,o]});n[2]=r;var c=document.getElementsByTagName(\\"head\\")[0],u=document.createElement(\\"script\\");u.type=\\"text/javascript\\",u.charset=\\"utf-8\\",u.async=!0,u.timeout=12e4,o.nc&&u.setAttribute(\\"nonce\\",o.nc),u.src=o.p+\\"chunks/\\"+e+\\".\\"+({}[e]||e)+\\".\\"+{0:\\"42bf13661c716a174f76\\"}[e]+\\".js\\";var a=setTimeout(i,12e4);function i(){u.onerror=u.onload=null,clearTimeout(a);var n=t[e];0!==n&&(n&&n[1](new Error(\\"Loading chunk \\"+e+\\" failed.\\")),t[e]=void 0)}return u.onerror=u.onload=i,c.appendChild(u),r},o.m=e,o.c=r,o.d=function(e,n,r){o.o(e,n)||Object.defineProperty(e,n,{configurable:!1,enumerable:!0,get:r})},o.n=function(e){var n=e&&e.__esModule?function(){return e.default}:function(){return e};return o.d(n,\\"a\\",n),n},o.o=function(e,n){return Object.prototype.hasOwnProperty.call(e,n)},o.p=\\"\\",o.oe=function(e){throw console.error(e),e}}([]);"
 `;
 
-exports[`when options.extractComments normalizes when options.extractComments is string: test1.js.LICENSE 1`] = `
-"/* Comment */
-"
+exports[`when applied with \`extractComments\` option matches snapshot for a \`function value: filename/manifest.3221d314bfa94c03ba98.js.LICENSE 1`] = `
+"/******/
+
+// webpackBootstrap
+
+/******/
+
+// install a JSONP callback for chunk loading
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+// add \\"moreModules\\" to the modules object,
+
+/******/
+
+// then flag all \\"chunkIds\\" as loaded and fire callback
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+// The module cache
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+// objects to store loaded and loading chunks
+
+/******/
+
+/******/
+
+/******/
+
+// The require function
+
+/******/
+
+/******/
+
+/******/
+
+// Check if module is in cache
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+// Create a new module (and put it into the cache)
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+// Execute the module function
+
+/******/
+
+/******/
+
+/******/
+
+// Return the exports of the module
+
+/******/
+
+/******/
+
+/******/
+
+// Flag the module as loaded
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+// This file contains only the entry chunk.
+
+/******/
+
+// The chunk loading function for additional chunks
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+// a Promise means \\"currently loading\\".
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+// setup Promise in chunk cache
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+// start chunk loading
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+// avoid mem leaks in IE.
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+// expose the modules object (__webpack_modules__)
+
+/******/
+
+/******/
+
+/******/
+
+// expose the module cache
+
+/******/
+
+/******/
+
+/******/
+
+// define getter function for harmony exports
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+// getDefaultExport function for compatibility with non-harmony modules
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+// Object.prototype.hasOwnProperty.call
+
+/******/
+
+/******/
+
+/******/
+
+// __webpack_public_path__
+
+/******/
+
+/******/
+
+/******/
+
+// on error function for async loading
+
+/******/
+
+/************************************************************************/
+
+/******/
+"
+`;
+
+exports[`when applied with \`extractComments\` option matches snapshot for a \`function value: filename/one.1ba6f44f8286da40c97f.js 1`] = `
+"/*! For license information please see one.1ba6f44f8286da40c97f.js.LICENSE */
+webpackJsonp([1],[function(n,e,o){o.e(0).then(o.bind(null,1)),n.exports=Math.random()}],[0]);"
+`;
+
+exports[`when applied with \`extractComments\` option matches snapshot for a \`function value: filename/one.1ba6f44f8286da40c97f.js.LICENSE 1`] = `
+"/* 0 */
+
+/***/
+
+/* import() */
+
+/*! Legal Comment */
+
+/**
+ * @preserve Copyright 2009 SomeThirdParty.
+ * Here is the full license text and copyright
+ * notice for this file. Note that the notice can span several
+ * lines and is only terminated by the closing star and slash:
+ */
+
+/**
+ * Utility functions for the foo package.
+ * @license Apache-2.0
+ */
+
+/*! Legal Foo */
+
+// Foo
+
+/*
+ Foo Bar
+ */
+
+/*
+* Foo
+*/
+"
+`;
+
+exports[`when applied with \`extractComments\` option matches snapshot for a \`function value: warnings 1`] = `Array []`;
+
+exports[`when applied with \`extractComments\` option matches snapshot for a \`some\` value (string): chunks/0.0.42bf13661c716a174f76.js 1`] = `
+"/*! For license information please see 0.0.42bf13661c716a174f76.js.LICENSE */
+webpackJsonp([0],[,function(n,o){n.exports=Math.random()}]);"
+`;
+
+exports[`when applied with \`extractComments\` option matches snapshot for a \`some\` value (string): chunks/0.0.42bf13661c716a174f76.js.LICENSE 1`] = `
+"/**
+ * @preserve Copyright 2009 SomeThirdParty.
+ * Here is the full license text and copyright
+ * notice for this file. Note that the notice can span several
+ * lines and is only terminated by the closing star and slash:
+ */
+
+/**
+ * Utility functions for the foo package.
+ * @license Apache-2.0
+ */
+"
+`;
+
+exports[`when applied with \`extractComments\` option matches snapshot for a \`some\` value (string): errors 1`] = `Array []`;
+
+exports[`when applied with \`extractComments\` option matches snapshot for a \`some\` value (string): filename/manifest.3221d314bfa94c03ba98.js 1`] = `"!function(e){var n=window.webpackJsonp;window.webpackJsonp=function(r,c,u){for(var a,i,f,s=0,l=[];s<r.length;s++)i=r[s],t[i]&&l.push(t[i][0]),t[i]=0;for(a in c)Object.prototype.hasOwnProperty.call(c,a)&&(e[a]=c[a]);for(n&&n(r,c,u);l.length;)l.shift()();if(u)for(s=0;s<u.length;s++)f=o(o.s=u[s]);return f};var r={},t={2:0};function o(n){if(r[n])return r[n].exports;var t=r[n]={i:n,l:!1,exports:{}};return e[n].call(t.exports,t,t.exports,o),t.l=!0,t.exports}o.e=function(e){var n=t[e];if(0===n)return new Promise(function(e){e()});if(n)return n[2];var r=new Promise(function(r,o){n=t[e]=[r,o]});n[2]=r;var c=document.getElementsByTagName(\\"head\\")[0],u=document.createElement(\\"script\\");u.type=\\"text/javascript\\",u.charset=\\"utf-8\\",u.async=!0,u.timeout=12e4,o.nc&&u.setAttribute(\\"nonce\\",o.nc),u.src=o.p+\\"chunks/\\"+e+\\".\\"+({}[e]||e)+\\".\\"+{0:\\"42bf13661c716a174f76\\"}[e]+\\".js\\";var a=setTimeout(i,12e4);function i(){u.onerror=u.onload=null,clearTimeout(a);var n=t[e];0!==n&&(n&&n[1](new Error(\\"Loading chunk \\"+e+\\" failed.\\")),t[e]=void 0)}return u.onerror=u.onload=i,c.appendChild(u),r},o.m=e,o.c=r,o.d=function(e,n,r){o.o(e,n)||Object.defineProperty(e,n,{configurable:!1,enumerable:!0,get:r})},o.n=function(e){var n=e&&e.__esModule?function(){return e.default}:function(){return e};return o.d(n,\\"a\\",n),n},o.o=function(e,n){return Object.prototype.hasOwnProperty.call(e,n)},o.p=\\"\\",o.oe=function(e){throw console.error(e),e}}([]);"`;
+
+exports[`when applied with \`extractComments\` option matches snapshot for a \`some\` value (string): filename/one.1ba6f44f8286da40c97f.js 1`] = `
+"/*! For license information please see one.1ba6f44f8286da40c97f.js.LICENSE */
+webpackJsonp([1],[function(n,e,o){o.e(0).then(o.bind(null,1)),n.exports=Math.random()}],[0]);"
+`;
+
+exports[`when applied with \`extractComments\` option matches snapshot for a \`some\` value (string): filename/one.1ba6f44f8286da40c97f.js.LICENSE 1`] = `
+"/**
+ * @preserve Copyright 2009 SomeThirdParty.
+ * Here is the full license text and copyright
+ * notice for this file. Note that the notice can span several
+ * lines and is only terminated by the closing star and slash:
+ */
+
+/**
+ * Utility functions for the foo package.
+ * @license Apache-2.0
+ */
+"
+`;
+
+exports[`when applied with \`extractComments\` option matches snapshot for a \`some\` value (string): warnings 1`] = `Array []`;
+
+exports[`when applied with \`extractComments\` option matches snapshot for a \`true\` value: chunks/0.0.42bf13661c716a174f76.js 1`] = `
+"/*! For license information please see 0.0.42bf13661c716a174f76.js.LICENSE */
+webpackJsonp([0],[,function(n,o){n.exports=Math.random()}]);"
+`;
+
+exports[`when applied with \`extractComments\` option matches snapshot for a \`true\` value: chunks/0.0.42bf13661c716a174f76.js.LICENSE 1`] = `
+"/*! Legal Comment */
+
+/**
+ * @preserve Copyright 2009 SomeThirdParty.
+ * Here is the full license text and copyright
+ * notice for this file. Note that the notice can span several
+ * lines and is only terminated by the closing star and slash:
+ */
+
+/**
+ * Utility functions for the foo package.
+ * @license Apache-2.0
+ */
+
+/*! Legal Foo */
+"
+`;
+
+exports[`when applied with \`extractComments\` option matches snapshot for a \`true\` value: errors 1`] = `Array []`;
+
+exports[`when applied with \`extractComments\` option matches snapshot for a \`true\` value: filename/manifest.3221d314bfa94c03ba98.js 1`] = `"!function(e){var n=window.webpackJsonp;window.webpackJsonp=function(r,c,u){for(var a,i,f,s=0,l=[];s<r.length;s++)i=r[s],t[i]&&l.push(t[i][0]),t[i]=0;for(a in c)Object.prototype.hasOwnProperty.call(c,a)&&(e[a]=c[a]);for(n&&n(r,c,u);l.length;)l.shift()();if(u)for(s=0;s<u.length;s++)f=o(o.s=u[s]);return f};var r={},t={2:0};function o(n){if(r[n])return r[n].exports;var t=r[n]={i:n,l:!1,exports:{}};return e[n].call(t.exports,t,t.exports,o),t.l=!0,t.exports}o.e=function(e){var n=t[e];if(0===n)return new Promise(function(e){e()});if(n)return n[2];var r=new Promise(function(r,o){n=t[e]=[r,o]});n[2]=r;var c=document.getElementsByTagName(\\"head\\")[0],u=document.createElement(\\"script\\");u.type=\\"text/javascript\\",u.charset=\\"utf-8\\",u.async=!0,u.timeout=12e4,o.nc&&u.setAttribute(\\"nonce\\",o.nc),u.src=o.p+\\"chunks/\\"+e+\\".\\"+({}[e]||e)+\\".\\"+{0:\\"42bf13661c716a174f76\\"}[e]+\\".js\\";var a=setTimeout(i,12e4);function i(){u.onerror=u.onload=null,clearTimeout(a);var n=t[e];0!==n&&(n&&n[1](new Error(\\"Loading chunk \\"+e+\\" failed.\\")),t[e]=void 0)}return u.onerror=u.onload=i,c.appendChild(u),r},o.m=e,o.c=r,o.d=function(e,n,r){o.o(e,n)||Object.defineProperty(e,n,{configurable:!1,enumerable:!0,get:r})},o.n=function(e){var n=e&&e.__esModule?function(){return e.default}:function(){return e};return o.d(n,\\"a\\",n),n},o.o=function(e,n){return Object.prototype.hasOwnProperty.call(e,n)},o.p=\\"\\",o.oe=function(e){throw console.error(e),e}}([]);"`;
+
+exports[`when applied with \`extractComments\` option matches snapshot for a \`true\` value: filename/one.1ba6f44f8286da40c97f.js 1`] = `
+"/*! For license information please see one.1ba6f44f8286da40c97f.js.LICENSE */
+webpackJsonp([1],[function(n,e,o){o.e(0).then(o.bind(null,1)),n.exports=Math.random()}],[0]);"
+`;
+
+exports[`when applied with \`extractComments\` option matches snapshot for a \`true\` value: filename/one.1ba6f44f8286da40c97f.js.LICENSE 1`] = `
+"/*! Legal Comment */
+
+/**
+ * @preserve Copyright 2009 SomeThirdParty.
+ * Here is the full license text and copyright
+ * notice for this file. Note that the notice can span several
+ * lines and is only terminated by the closing star and slash:
+ */
+
+/**
+ * Utility functions for the foo package.
+ * @license Apache-2.0
+ */
+
+/*! Legal Foo */
+"
+`;
+
+exports[`when applied with \`extractComments\` option matches snapshot for a \`true\` value: warnings 1`] = `Array []`;
+
+exports[`when applied with \`extractComments\` option matches snapshot for a object value (extracts comments to a single file): chunks/0.0.42bf13661c716a174f76.js 1`] = `
+"/*! License information can be found in extracted-comments.js */
+webpackJsonp([0],[,function(n,o){n.exports=Math.random()}]);"
+`;
+
+exports[`when applied with \`extractComments\` option matches snapshot for a object value (extracts comments to a single file): errors 1`] = `Array []`;
+
+exports[`when applied with \`extractComments\` option matches snapshot for a object value (extracts comments to a single file): extracted-comments.js 1`] = `
+"/* 0 */
+
+/* 1 */
+
+/***/
+
+/* 1 */
+
+/***/
+
+/*! Legal Comment */
+
+/**
+ * @preserve Copyright 2009 SomeThirdParty.
+ * Here is the full license text and copyright
+ * notice for this file. Note that the notice can span several
+ * lines and is only terminated by the closing star and slash:
+ */
+
+/**
+ * Utility functions for the foo package.
+ * @license Apache-2.0
+ */
+
+/*! Legal Foo */
+
+// Foo
+
+/*
+ Foo Bar
+ */
+
+/*
+* Foo
+*/
+
+/***/
+
+/* 0 */
+
+/***/
+
+/* import() */
+
+/*! Legal Comment */
+
+/**
+ * @preserve Copyright 2009 SomeThirdParty.
+ * Here is the full license text and copyright
+ * notice for this file. Note that the notice can span several
+ * lines and is only terminated by the closing star and slash:
+ */
+
+/**
+ * Utility functions for the foo package.
+ * @license Apache-2.0
+ */
+
+/*! Legal Foo */
+
+// Foo
+
+/*
+ Foo Bar
+ */
+
+/*
+* Foo
+*/
+
+/******/
+
+// webpackBootstrap
+
+/******/
+
+// install a JSONP callback for chunk loading
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+// add \\"moreModules\\" to the modules object,
+
+/******/
+
+// then flag all \\"chunkIds\\" as loaded and fire callback
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+// The module cache
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+// objects to store loaded and loading chunks
+
+/******/
+
+/******/
+
+/******/
+
+// The require function
+
+/******/
+
+/******/
+
+/******/
+
+// Check if module is in cache
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+// Create a new module (and put it into the cache)
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+// Execute the module function
+
+/******/
+
+/******/
+
+/******/
+
+// Return the exports of the module
+
+/******/
+
+/******/
+
+/******/
+
+// Flag the module as loaded
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+// This file contains only the entry chunk.
+
+/******/
+
+// The chunk loading function for additional chunks
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+// a Promise means \\"currently loading\\".
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+// setup Promise in chunk cache
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+// start chunk loading
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+// avoid mem leaks in IE.
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+// expose the modules object (__webpack_modules__)
+
+/******/
+
+/******/
+
+/******/
+
+// expose the module cache
+
+/******/
+
+/******/
+
+/******/
+
+// define getter function for harmony exports
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+// getDefaultExport function for compatibility with non-harmony modules
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+// Object.prototype.hasOwnProperty.call
+
+/******/
+
+/******/
+
+/******/
+
+// __webpack_public_path__
+
+/******/
+
+/******/
+
+/******/
+
+// on error function for async loading
+
+/******/
+
+/************************************************************************/
+
+/******/
+"
+`;
+
+exports[`when applied with \`extractComments\` option matches snapshot for a object value (extracts comments to a single file): filename/manifest.3221d314bfa94c03ba98.js 1`] = `
+"/*! License information can be found in extracted-comments.js */
+!function(e){var n=window.webpackJsonp;window.webpackJsonp=function(r,c,u){for(var a,i,f,s=0,l=[];s<r.length;s++)i=r[s],t[i]&&l.push(t[i][0]),t[i]=0;for(a in c)Object.prototype.hasOwnProperty.call(c,a)&&(e[a]=c[a]);for(n&&n(r,c,u);l.length;)l.shift()();if(u)for(s=0;s<u.length;s++)f=o(o.s=u[s]);return f};var r={},t={2:0};function o(n){if(r[n])return r[n].exports;var t=r[n]={i:n,l:!1,exports:{}};return e[n].call(t.exports,t,t.exports,o),t.l=!0,t.exports}o.e=function(e){var n=t[e];if(0===n)return new Promise(function(e){e()});if(n)return n[2];var r=new Promise(function(r,o){n=t[e]=[r,o]});n[2]=r;var c=document.getElementsByTagName(\\"head\\")[0],u=document.createElement(\\"script\\");u.type=\\"text/javascript\\",u.charset=\\"utf-8\\",u.async=!0,u.timeout=12e4,o.nc&&u.setAttribute(\\"nonce\\",o.nc),u.src=o.p+\\"chunks/\\"+e+\\".\\"+({}[e]||e)+\\".\\"+{0:\\"42bf13661c716a174f76\\"}[e]+\\".js\\";var a=setTimeout(i,12e4);function i(){u.onerror=u.onload=null,clearTimeout(a);var n=t[e];0!==n&&(n&&n[1](new Error(\\"Loading chunk \\"+e+\\" failed.\\")),t[e]=void 0)}return u.onerror=u.onload=i,c.appendChild(u),r},o.m=e,o.c=r,o.d=function(e,n,r){o.o(e,n)||Object.defineProperty(e,n,{configurable:!1,enumerable:!0,get:r})},o.n=function(e){var n=e&&e.__esModule?function(){return e.default}:function(){return e};return o.d(n,\\"a\\",n),n},o.o=function(e,n){return Object.prototype.hasOwnProperty.call(e,n)},o.p=\\"\\",o.oe=function(e){throw console.error(e),e}}([]);"
+`;
+
+exports[`when applied with \`extractComments\` option matches snapshot for a object value (extracts comments to a single file): filename/one.1ba6f44f8286da40c97f.js 1`] = `
+"/*! License information can be found in extracted-comments.js */
+webpackJsonp([1],[function(n,e,o){o.e(0).then(o.bind(null,1)),n.exports=Math.random()}],[0]);"
+`;
+
+exports[`when applied with \`extractComments\` option matches snapshot for a object value (extracts comments to a single file): warnings 1`] = `Array []`;
+
+exports[`when applied with \`extractComments\` option matches snapshot for a object value (extracts comments to multiple files): chunks/0.0.42bf13661c716a174f76.js 1`] = `
+"/*! License information can be found in chunks/0.0.42bf13661c716a174f76.license.js */
+webpackJsonp([0],[,function(n,o){n.exports=Math.random()}]);"
+`;
+
+exports[`when applied with \`extractComments\` option matches snapshot for a object value (extracts comments to multiple files): chunks/0.0.42bf13661c716a174f76.license.js 1`] = `
+"/* 0 */
+
+/* 1 */
+
+/***/
+
+/* 1 */
+
+/***/
+
+/*! Legal Comment */
+
+/**
+ * @preserve Copyright 2009 SomeThirdParty.
+ * Here is the full license text and copyright
+ * notice for this file. Note that the notice can span several
+ * lines and is only terminated by the closing star and slash:
+ */
+
+/**
+ * Utility functions for the foo package.
+ * @license Apache-2.0
+ */
+
+/*! Legal Foo */
+
+// Foo
+
+/*
+ Foo Bar
+ */
+
+/*
+* Foo
+*/
+
+/***/
+"
+`;
+
+exports[`when applied with \`extractComments\` option matches snapshot for a object value (extracts comments to multiple files): errors 1`] = `Array []`;
+
+exports[`when applied with \`extractComments\` option matches snapshot for a object value (extracts comments to multiple files): filename/manifest.3221d314bfa94c03ba98.js 1`] = `
+"/*! License information can be found in filename/manifest.3221d314bfa94c03ba98.license.js */
+!function(e){var n=window.webpackJsonp;window.webpackJsonp=function(r,c,u){for(var a,i,f,s=0,l=[];s<r.length;s++)i=r[s],t[i]&&l.push(t[i][0]),t[i]=0;for(a in c)Object.prototype.hasOwnProperty.call(c,a)&&(e[a]=c[a]);for(n&&n(r,c,u);l.length;)l.shift()();if(u)for(s=0;s<u.length;s++)f=o(o.s=u[s]);return f};var r={},t={2:0};function o(n){if(r[n])return r[n].exports;var t=r[n]={i:n,l:!1,exports:{}};return e[n].call(t.exports,t,t.exports,o),t.l=!0,t.exports}o.e=function(e){var n=t[e];if(0===n)return new Promise(function(e){e()});if(n)return n[2];var r=new Promise(function(r,o){n=t[e]=[r,o]});n[2]=r;var c=document.getElementsByTagName(\\"head\\")[0],u=document.createElement(\\"script\\");u.type=\\"text/javascript\\",u.charset=\\"utf-8\\",u.async=!0,u.timeout=12e4,o.nc&&u.setAttribute(\\"nonce\\",o.nc),u.src=o.p+\\"chunks/\\"+e+\\".\\"+({}[e]||e)+\\".\\"+{0:\\"42bf13661c716a174f76\\"}[e]+\\".js\\";var a=setTimeout(i,12e4);function i(){u.onerror=u.onload=null,clearTimeout(a);var n=t[e];0!==n&&(n&&n[1](new Error(\\"Loading chunk \\"+e+\\" failed.\\")),t[e]=void 0)}return u.onerror=u.onload=i,c.appendChild(u),r},o.m=e,o.c=r,o.d=function(e,n,r){o.o(e,n)||Object.defineProperty(e,n,{configurable:!1,enumerable:!0,get:r})},o.n=function(e){var n=e&&e.__esModule?function(){return e.default}:function(){return e};return o.d(n,\\"a\\",n),n},o.o=function(e,n){return Object.prototype.hasOwnProperty.call(e,n)},o.p=\\"\\",o.oe=function(e){throw console.error(e),e}}([]);"
+`;
+
+exports[`when applied with \`extractComments\` option matches snapshot for a object value (extracts comments to multiple files): filename/manifest.3221d314bfa94c03ba98.license.js 1`] = `
+"/******/
+
+// webpackBootstrap
+
+/******/
+
+// install a JSONP callback for chunk loading
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+// add \\"moreModules\\" to the modules object,
+
+/******/
+
+// then flag all \\"chunkIds\\" as loaded and fire callback
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+// The module cache
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+// objects to store loaded and loading chunks
+
+/******/
+
+/******/
+
+/******/
+
+// The require function
+
+/******/
+
+/******/
+
+/******/
+
+// Check if module is in cache
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+// Create a new module (and put it into the cache)
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+// Execute the module function
+
+/******/
+
+/******/
+
+/******/
+
+// Return the exports of the module
+
+/******/
+
+/******/
+
+/******/
+
+// Flag the module as loaded
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+// This file contains only the entry chunk.
+
+/******/
+
+// The chunk loading function for additional chunks
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+// a Promise means \\"currently loading\\".
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+// setup Promise in chunk cache
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+// start chunk loading
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+// avoid mem leaks in IE.
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+// expose the modules object (__webpack_modules__)
+
+/******/
+
+/******/
+
+/******/
+
+// expose the module cache
+
+/******/
+
+/******/
+
+/******/
+
+// define getter function for harmony exports
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+// getDefaultExport function for compatibility with non-harmony modules
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+/******/
+
+// Object.prototype.hasOwnProperty.call
+
+/******/
+
+/******/
+
+/******/
+
+// __webpack_public_path__
+
+/******/
+
+/******/
+
+/******/
+
+// on error function for async loading
+
+/******/
+
+/************************************************************************/
+
+/******/
+"
+`;
+
+exports[`when applied with \`extractComments\` option matches snapshot for a object value (extracts comments to multiple files): filename/one.1ba6f44f8286da40c97f.js 1`] = `
+"/*! License information can be found in filename/one.1ba6f44f8286da40c97f.license.js */
+webpackJsonp([1],[function(n,e,o){o.e(0).then(o.bind(null,1)),n.exports=Math.random()}],[0]);"
+`;
+
+exports[`when applied with \`extractComments\` option matches snapshot for a object value (extracts comments to multiple files): filename/one.1ba6f44f8286da40c97f.license.js 1`] = `
+"/* 0 */
+
+/***/
+
+/* import() */
+
+/*! Legal Comment */
+
+/**
+ * @preserve Copyright 2009 SomeThirdParty.
+ * Here is the full license text and copyright
+ * notice for this file. Note that the notice can span several
+ * lines and is only terminated by the closing star and slash:
+ */
+
+/**
+ * Utility functions for the foo package.
+ * @license Apache-2.0
+ */
+
+/*! Legal Foo */
+
+// Foo
+
+/*
+ Foo Bar
+ */
+
+/*
+* Foo
+*/
+"
+`;
+
+exports[`when applied with \`extractComments\` option matches snapshot for a object value (extracts comments to multiple files): warnings 1`] = `Array []`;
+
+exports[`when applied with \`extractComments\` option matches snapshot when is not specify: chunks/0.0.42bf13661c716a174f76.js 1`] = `
+"webpackJsonp([0],[,function(n,o){
+/*! Legal Comment */
+/**
+ * @preserve Copyright 2009 SomeThirdParty.
+ * Here is the full license text and copyright
+ * notice for this file. Note that the notice can span several
+ * lines and is only terminated by the closing star and slash:
+ */
+/**
+ * Utility functions for the foo package.
+ * @license Apache-2.0
+ */
+/*! Legal Foo */
+n.exports=Math.random()}]);"
+`;
+
+exports[`when applied with \`extractComments\` option matches snapshot when is not specify: errors 1`] = `Array []`;
+
+exports[`when applied with \`extractComments\` option matches snapshot when is not specify: filename/manifest.3221d314bfa94c03ba98.js 1`] = `"!function(e){var n=window.webpackJsonp;window.webpackJsonp=function(r,c,u){for(var a,i,f,s=0,l=[];s<r.length;s++)i=r[s],t[i]&&l.push(t[i][0]),t[i]=0;for(a in c)Object.prototype.hasOwnProperty.call(c,a)&&(e[a]=c[a]);for(n&&n(r,c,u);l.length;)l.shift()();if(u)for(s=0;s<u.length;s++)f=o(o.s=u[s]);return f};var r={},t={2:0};function o(n){if(r[n])return r[n].exports;var t=r[n]={i:n,l:!1,exports:{}};return e[n].call(t.exports,t,t.exports,o),t.l=!0,t.exports}o.e=function(e){var n=t[e];if(0===n)return new Promise(function(e){e()});if(n)return n[2];var r=new Promise(function(r,o){n=t[e]=[r,o]});n[2]=r;var c=document.getElementsByTagName(\\"head\\")[0],u=document.createElement(\\"script\\");u.type=\\"text/javascript\\",u.charset=\\"utf-8\\",u.async=!0,u.timeout=12e4,o.nc&&u.setAttribute(\\"nonce\\",o.nc),u.src=o.p+\\"chunks/\\"+e+\\".\\"+({}[e]||e)+\\".\\"+{0:\\"42bf13661c716a174f76\\"}[e]+\\".js\\";var a=setTimeout(i,12e4);function i(){u.onerror=u.onload=null,clearTimeout(a);var n=t[e];0!==n&&(n&&n[1](new Error(\\"Loading chunk \\"+e+\\" failed.\\")),t[e]=void 0)}return u.onerror=u.onload=i,c.appendChild(u),r},o.m=e,o.c=r,o.d=function(e,n,r){o.o(e,n)||Object.defineProperty(e,n,{configurable:!1,enumerable:!0,get:r})},o.n=function(e){var n=e&&e.__esModule?function(){return e.default}:function(){return e};return o.d(n,\\"a\\",n),n},o.o=function(e,n){return Object.prototype.hasOwnProperty.call(e,n)},o.p=\\"\\",o.oe=function(e){throw console.error(e),e}}([]);"`;
+
+exports[`when applied with \`extractComments\` option matches snapshot when is not specify: filename/one.1ba6f44f8286da40c97f.js 1`] = `
+"webpackJsonp([1],[function(n,e,o){o.e(0).then(o.bind(null,1)),
+/*! Legal Comment */
+/**
+ * @preserve Copyright 2009 SomeThirdParty.
+ * Here is the full license text and copyright
+ * notice for this file. Note that the notice can span several
+ * lines and is only terminated by the closing star and slash:
+ */
+/**
+ * Utility functions for the foo package.
+ * @license Apache-2.0
+ */
+/*! Legal Foo */
+n.exports=Math.random()}],[0]);"
 `;
 
-exports[`when options.extractComments normalizes when options.extractComments is string: warnings 1`] = `Array []`;
+exports[`when applied with \`extractComments\` option matches snapshot when is not specify: warnings 1`] = `Array []`;
diff --git a/test/__snapshots__/minify-option.test.js.snap b/test/__snapshots__/minify-option.test.js.snap
index 790f54a..f19f08d 100644
--- a/test/__snapshots__/minify-option.test.js.snap
+++ b/test/__snapshots__/minify-option.test.js.snap
@@ -244,3 +244,289 @@ exports[`when applied with \`minify\` option matches snapshot for \`uglify-js\`
 exports[`when applied with \`minify\` option matches snapshot for \`uglify-js\` minifier: manifest.js 1`] = `"!function(i){var p=window.webpackJsonp;window.webpackJsonp=function(r,n,e){for(var o,t,u,c=0,f=[];c<r.length;c++)t=r[c],a[t]&&f.push(a[t][0]),a[t]=0;for(o in n)Object.prototype.hasOwnProperty.call(n,o)&&(i[o]=n[o]);for(p&&p(r,n,e);f.length;)f.shift()();if(e)for(c=0;c<e.length;c++)u=l(l.s=e[c]);return u};var e={},a={1:0};function l(r){if(e[r])return e[r].exports;var n=e[r]={i:r,l:!1,exports:{}};return i[r].call(n.exports,n,n.exports,l),n.l=!0,n.exports}l.m=i,l.c=e,l.d=function(r,n,e){l.o(r,n)||Object.defineProperty(r,n,{configurable:!1,enumerable:!0,get:e})},l.n=function(r){var n=r&&r.__esModule?function(){return r.default}:function(){return r};return l.d(n,\\"a\\",n),n},l.o=function(r,n){return Object.prototype.hasOwnProperty.call(r,n)},l.p=\\"\\",l.oe=function(r){throw console.error(r),r}}([]);"`;
 
 exports[`when applied with \`minify\` option matches snapshot for \`uglify-js\` minifier: warnings 1`] = `Array []`;
+
+exports[`when applied with \`minify\` option matches snapshot for errors into \`minify\` option and \`parallel\` is \`true\`: errors 1`] = `
+Array [
+  "Error: main.js from UglifyJs
+Error: Error",
+  "Error: manifest.js from UglifyJs
+Error: Error",
+]
+`;
+
+exports[`when applied with \`minify\` option matches snapshot for errors into \`minify\` option and \`parallel\` is \`true\`: main.js 1`] = `
+"webpackJsonp([0],[
+/* 0 */
+/***/ (function(module, __webpack_exports__, __webpack_require__) {
+
+\\"use strict\\";
+Object.defineProperty(__webpack_exports__, \\"__esModule\\", { value: true });
+class Point {
+  constructor(x, y) {
+    this.x = x;
+    this.y = y;
+  }
+
+  static distance(a, b) {
+    const dx = a.x - b.x;
+    const dy = a.y - b.y;
+
+    return Math.hypot(dx, dy);
+  }
+}
+
+/* harmony default export */ __webpack_exports__[\\"default\\"] = (Point);
+
+
+/***/ })
+],[0]);"
+`;
+
+exports[`when applied with \`minify\` option matches snapshot for errors into \`minify\` option and \`parallel\` is \`true\`: manifest.js 1`] = `
+"/******/ (function(modules) { // webpackBootstrap
+/******/ 	// install a JSONP callback for chunk loading
+/******/ 	var parentJsonpFunction = window[\\"webpackJsonp\\"];
+/******/ 	window[\\"webpackJsonp\\"] = function webpackJsonpCallback(chunkIds, moreModules, executeModules) {
+/******/ 		// add \\"moreModules\\" to the modules object,
+/******/ 		// then flag all \\"chunkIds\\" as loaded and fire callback
+/******/ 		var moduleId, chunkId, i = 0, resolves = [], result;
+/******/ 		for(;i < chunkIds.length; i++) {
+/******/ 			chunkId = chunkIds[i];
+/******/ 			if(installedChunks[chunkId]) {
+/******/ 				resolves.push(installedChunks[chunkId][0]);
+/******/ 			}
+/******/ 			installedChunks[chunkId] = 0;
+/******/ 		}
+/******/ 		for(moduleId in moreModules) {
+/******/ 			if(Object.prototype.hasOwnProperty.call(moreModules, moduleId)) {
+/******/ 				modules[moduleId] = moreModules[moduleId];
+/******/ 			}
+/******/ 		}
+/******/ 		if(parentJsonpFunction) parentJsonpFunction(chunkIds, moreModules, executeModules);
+/******/ 		while(resolves.length) {
+/******/ 			resolves.shift()();
+/******/ 		}
+/******/ 		if(executeModules) {
+/******/ 			for(i=0; i < executeModules.length; i++) {
+/******/ 				result = __webpack_require__(__webpack_require__.s = executeModules[i]);
+/******/ 			}
+/******/ 		}
+/******/ 		return result;
+/******/ 	};
+/******/
+/******/ 	// The module cache
+/******/ 	var installedModules = {};
+/******/
+/******/ 	// objects to store loaded and loading chunks
+/******/ 	var installedChunks = {
+/******/ 		1: 0
+/******/ 	};
+/******/
+/******/ 	// The require function
+/******/ 	function __webpack_require__(moduleId) {
+/******/
+/******/ 		// Check if module is in cache
+/******/ 		if(installedModules[moduleId]) {
+/******/ 			return installedModules[moduleId].exports;
+/******/ 		}
+/******/ 		// Create a new module (and put it into the cache)
+/******/ 		var module = installedModules[moduleId] = {
+/******/ 			i: moduleId,
+/******/ 			l: false,
+/******/ 			exports: {}
+/******/ 		};
+/******/
+/******/ 		// Execute the module function
+/******/ 		modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
+/******/
+/******/ 		// Flag the module as loaded
+/******/ 		module.l = true;
+/******/
+/******/ 		// Return the exports of the module
+/******/ 		return module.exports;
+/******/ 	}
+/******/
+/******/
+/******/ 	// expose the modules object (__webpack_modules__)
+/******/ 	__webpack_require__.m = modules;
+/******/
+/******/ 	// expose the module cache
+/******/ 	__webpack_require__.c = installedModules;
+/******/
+/******/ 	// define getter function for harmony exports
+/******/ 	__webpack_require__.d = function(exports, name, getter) {
+/******/ 		if(!__webpack_require__.o(exports, name)) {
+/******/ 			Object.defineProperty(exports, name, {
+/******/ 				configurable: false,
+/******/ 				enumerable: true,
+/******/ 				get: getter
+/******/ 			});
+/******/ 		}
+/******/ 	};
+/******/
+/******/ 	// getDefaultExport function for compatibility with non-harmony modules
+/******/ 	__webpack_require__.n = function(module) {
+/******/ 		var getter = module && module.__esModule ?
+/******/ 			function getDefault() { return module['default']; } :
+/******/ 			function getModuleExports() { return module; };
+/******/ 		__webpack_require__.d(getter, 'a', getter);
+/******/ 		return getter;
+/******/ 	};
+/******/
+/******/ 	// Object.prototype.hasOwnProperty.call
+/******/ 	__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
+/******/
+/******/ 	// __webpack_public_path__
+/******/ 	__webpack_require__.p = \\"\\";
+/******/
+/******/ 	// on error function for async loading
+/******/ 	__webpack_require__.oe = function(err) { console.error(err); throw err; };
+/******/ })
+/************************************************************************/
+/******/ ([]);"
+`;
+
+exports[`when applied with \`minify\` option matches snapshot for errors into \`minify\` option and \`parallel\` is \`true\`: warnings 1`] = `Array []`;
+
+exports[`when applied with \`minify\` option matches snapshot for errors into \`minify\` option: errors 1`] = `
+Array [
+  "Error: main.js from UglifyJs
+Error: Error",
+  "Error: manifest.js from UglifyJs
+Error: Error",
+]
+`;
+
+exports[`when applied with \`minify\` option matches snapshot for errors into \`minify\` option: main.js 1`] = `
+"webpackJsonp([0],[
+/* 0 */
+/***/ (function(module, __webpack_exports__, __webpack_require__) {
+
+\\"use strict\\";
+Object.defineProperty(__webpack_exports__, \\"__esModule\\", { value: true });
+class Point {
+  constructor(x, y) {
+    this.x = x;
+    this.y = y;
+  }
+
+  static distance(a, b) {
+    const dx = a.x - b.x;
+    const dy = a.y - b.y;
+
+    return Math.hypot(dx, dy);
+  }
+}
+
+/* harmony default export */ __webpack_exports__[\\"default\\"] = (Point);
+
+
+/***/ })
+],[0]);"
+`;
+
+exports[`when applied with \`minify\` option matches snapshot for errors into \`minify\` option: manifest.js 1`] = `
+"/******/ (function(modules) { // webpackBootstrap
+/******/ 	// install a JSONP callback for chunk loading
+/******/ 	var parentJsonpFunction = window[\\"webpackJsonp\\"];
+/******/ 	window[\\"webpackJsonp\\"] = function webpackJsonpCallback(chunkIds, moreModules, executeModules) {
+/******/ 		// add \\"moreModules\\" to the modules object,
+/******/ 		// then flag all \\"chunkIds\\" as loaded and fire callback
+/******/ 		var moduleId, chunkId, i = 0, resolves = [], result;
+/******/ 		for(;i < chunkIds.length; i++) {
+/******/ 			chunkId = chunkIds[i];
+/******/ 			if(installedChunks[chunkId]) {
+/******/ 				resolves.push(installedChunks[chunkId][0]);
+/******/ 			}
+/******/ 			installedChunks[chunkId] = 0;
+/******/ 		}
+/******/ 		for(moduleId in moreModules) {
+/******/ 			if(Object.prototype.hasOwnProperty.call(moreModules, moduleId)) {
+/******/ 				modules[moduleId] = moreModules[moduleId];
+/******/ 			}
+/******/ 		}
+/******/ 		if(parentJsonpFunction) parentJsonpFunction(chunkIds, moreModules, executeModules);
+/******/ 		while(resolves.length) {
+/******/ 			resolves.shift()();
+/******/ 		}
+/******/ 		if(executeModules) {
+/******/ 			for(i=0; i < executeModules.length; i++) {
+/******/ 				result = __webpack_require__(__webpack_require__.s = executeModules[i]);
+/******/ 			}
+/******/ 		}
+/******/ 		return result;
+/******/ 	};
+/******/
+/******/ 	// The module cache
+/******/ 	var installedModules = {};
+/******/
+/******/ 	// objects to store loaded and loading chunks
+/******/ 	var installedChunks = {
+/******/ 		1: 0
+/******/ 	};
+/******/
+/******/ 	// The require function
+/******/ 	function __webpack_require__(moduleId) {
+/******/
+/******/ 		// Check if module is in cache
+/******/ 		if(installedModules[moduleId]) {
+/******/ 			return installedModules[moduleId].exports;
+/******/ 		}
+/******/ 		// Create a new module (and put it into the cache)
+/******/ 		var module = installedModules[moduleId] = {
+/******/ 			i: moduleId,
+/******/ 			l: false,
+/******/ 			exports: {}
+/******/ 		};
+/******/
+/******/ 		// Execute the module function
+/******/ 		modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
+/******/
+/******/ 		// Flag the module as loaded
+/******/ 		module.l = true;
+/******/
+/******/ 		// Return the exports of the module
+/******/ 		return module.exports;
+/******/ 	}
+/******/
+/******/
+/******/ 	// expose the modules object (__webpack_modules__)
+/******/ 	__webpack_require__.m = modules;
+/******/
+/******/ 	// expose the module cache
+/******/ 	__webpack_require__.c = installedModules;
+/******/
+/******/ 	// define getter function for harmony exports
+/******/ 	__webpack_require__.d = function(exports, name, getter) {
+/******/ 		if(!__webpack_require__.o(exports, name)) {
+/******/ 			Object.defineProperty(exports, name, {
+/******/ 				configurable: false,
+/******/ 				enumerable: true,
+/******/ 				get: getter
+/******/ 			});
+/******/ 		}
+/******/ 	};
+/******/
+/******/ 	// getDefaultExport function for compatibility with non-harmony modules
+/******/ 	__webpack_require__.n = function(module) {
+/******/ 		var getter = module && module.__esModule ?
+/******/ 			function getDefault() { return module['default']; } :
+/******/ 			function getModuleExports() { return module; };
+/******/ 		__webpack_require__.d(getter, 'a', getter);
+/******/ 		return getter;
+/******/ 	};
+/******/
+/******/ 	// Object.prototype.hasOwnProperty.call
+/******/ 	__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
+/******/
+/******/ 	// __webpack_public_path__
+/******/ 	__webpack_require__.p = \\"\\";
+/******/
+/******/ 	// on error function for async loading
+/******/ 	__webpack_require__.oe = function(err) { console.error(err); throw err; };
+/******/ })
+/************************************************************************/
+/******/ ([]);"
+`;
+
+exports[`when applied with \`minify\` option matches snapshot for errors into \`minify\` option: warnings 1`] = `Array []`;
diff --git a/test/__snapshots__/sourceMap-option.test.js.snap b/test/__snapshots__/sourceMap-option.test.js.snap
index ad1cdd6..46ffeaa 100644
--- a/test/__snapshots__/sourceMap-option.test.js.snap
+++ b/test/__snapshots__/sourceMap-option.test.js.snap
@@ -1,401 +1,65 @@
 // Jest Snapshot v1, https://goo.gl/fbAQLP
 
-exports[`when options.sourceMap true and options.parallel true compilation handler when called optimize-chunk-assets handler only calls callback once: errors 1`] = `Array []`;
+exports[`when options.sourceMap matches snapshot for a single \`false\` value (\`devtool\` is \`false\`): errors 1`] = `Array []`;
 
-exports[`when options.sourceMap true and options.parallel true compilation handler when called optimize-chunk-assets handler only calls callback once: warnings 1`] = `
-Array [
-  [Error: test4.js contains invalid source map],
-]
-`;
-
-exports[`when options.sourceMap true and options.parallel true matches snapshot: asset main.0c220ec66316af2c1b24.js 1`] = `"webpackJsonp([0],[function(o,n){o.exports=function(){console.log(7)}}],[0]);"`;
-
-exports[`when options.sourceMap true and options.parallel true matches snapshot: asset manifest.d6857f782c13a99b5917.js 1`] = `"!function(r){var n=window.webpackJsonp;window.webpackJsonp=function(e,u,c){for(var f,i,p,a=0,l=[];a<e.length;a++)i=e[a],o[i]&&l.push(o[i][0]),o[i]=0;for(f in u)Object.prototype.hasOwnProperty.call(u,f)&&(r[f]=u[f]);for(n&&n(e,u,c);l.length;)l.shift()();if(c)for(a=0;a<c.length;a++)p=t(t.s=c[a]);return p};var e={},o={1:0};function t(n){if(e[n])return e[n].exports;var o=e[n]={i:n,l:!1,exports:{}};return r[n].call(o.exports,o,o.exports,t),o.l=!0,o.exports}t.m=r,t.c=e,t.d=function(r,n,e){t.o(r,n)||Object.defineProperty(r,n,{configurable:!1,enumerable:!0,get:e})},t.n=function(r){var n=r&&r.__esModule?function(){return r.default}:function(){return r};return t.d(n,\\"a\\",n),n},t.o=function(r,n){return Object.prototype.hasOwnProperty.call(r,n)},t.p=\\"\\",t.oe=function(r){throw console.error(r),r}}([]);"`;
-
-exports[`when options.sourceMap true and options.parallel true matches snapshot: errors 1`] = `Array []`;
-
-exports[`when options.sourceMap true and options.parallel true matches snapshot: source map main.0c220ec66316af2c1b24.js 1`] = `
-Object {
-  "file": "x",
-  "mappings": "gCAKAA,EAAAC,QAAA,WAEAC,QAAAC,IAAAC",
-  "names": Array [
-    "module",
-    "exports",
-    "console",
-    "log",
-    "b",
-  ],
-  "sources": Array [],
-  "sourcesContent": Array [
-    "// foo
-/* @preserve*/
-// bar
-const a = 2 + 2;
-
-module.exports = function Foo() {
-  const b = 2 + 2;
-  console.log(b + 1 + 2);
-};
-",
-  ],
-  "version": 3,
-}
-`;
+exports[`when options.sourceMap matches snapshot for a single \`false\` value (\`devtool\` is \`false\`): main.0c220ec66316af2c1b24.js 1`] = `"webpackJsonp([0],[function(o,n){o.exports=function(){console.log(7)}}],[0]);"`;
 
-exports[`when options.sourceMap true and options.parallel true matches snapshot: source map manifest.d6857f782c13a99b5917.js 1`] = `
-Object {
-  "file": "x",
-  "mappings": "aACA,IAAAA,EAAAC,OAAA,aACAA,OAAA,sBAAAC,EAAAC,EAAAC,GAIA,IADA,IAAAC,EAAAC,EAAAC,EAAAC,EAAA,EAAAC,KACQD,EAAAN,EAAAQ,OAAoBF,IAC5BF,EAAAJ,EAAAM,GACAG,EAAAL,IACAG,EAAAG,KAAAD,EAAAL,GAAA,IAEAK,EAAAL,GAAA,EAEA,IAAAD,KAAAF,EACAU,OAAAC,UAAAC,eAAAC,KAAAb,EAAAE,KACAY,EAAAZ,GAAAF,EAAAE,IAIA,IADAL,KAAAE,EAAAC,EAAAC,GACAK,EAAAC,QACAD,EAAAS,OAAAT,GAEA,GAAAL,EACA,IAAAI,EAAA,EAAYA,EAAAJ,EAAAM,OAA2BF,IACvCD,EAAAY,IAAAC,EAAAhB,EAAAI,IAGA,OAAAD,GAIA,IAAAc,KAGAV,GACAW,EAAA,GAIA,SAAAH,EAAAd,GAGA,GAAAgB,EAAAhB,GACA,OAAAgB,EAAAhB,GAAAkB,QAGA,IAAAC,EAAAH,EAAAhB,IACAG,EAAAH,EACAoB,GAAA,EACAF,YAUA,OANAN,EAAAZ,GAAAW,KAAAQ,EAAAD,QAAAC,IAAAD,QAAAJ,GAGAK,EAAAC,GAAA,EAGAD,EAAAD,QAKAJ,EAAAO,EAAAT,EAGAE,EAAAQ,EAAAN,EAGAF,EAAAS,EAAA,SAAAL,EAAAM,EAAAC,GACAX,EAAAY,EAAAR,EAAAM,IACAhB,OAAAmB,eAAAT,EAAAM,GACAI,cAAA,EACAC,YAAA,EACAC,IAAAL,KAMAX,EAAAiB,EAAA,SAAAZ,GACA,IAAAM,EAAAN,KAAAa,WACA,WAA2B,OAAAb,EAAA,SAC3B,WAAiC,OAAAA,GAEjC,OADAL,EAAAS,EAAAE,EAAA,IAAAA,GACAA,GAIAX,EAAAY,EAAA,SAAAO,EAAAC,GAAsD,OAAA1B,OAAAC,UAAAC,eAAAC,KAAAsB,EAAAC,IAGtDpB,EAAAqB,EAAA,GAGArB,EAAAsB,GAAA,SAAAC,GAA8D,MAApBC,QAAAC,MAAAF,GAAoBA",
-  "names": Array [
-    "parentJsonpFunction",
-    "window",
-    "chunkIds",
-    "moreModules",
-    "executeModules",
-    "moduleId",
-    "chunkId",
-    "result",
-    "i",
-    "resolves",
-    "length",
-    "installedChunks",
-    "push",
-    "Object",
-    "prototype",
-    "hasOwnProperty",
-    "call",
-    "modules",
-    "shift",
-    "__webpack_require__",
-    "s",
-    "installedModules",
-    "1",
-    "exports",
-    "module",
-    "l",
-    "m",
-    "c",
-    "d",
-    "name",
-    "getter",
-    "o",
-    "defineProperty",
-    "configurable",
-    "enumerable",
-    "get",
-    "n",
-    "__esModule",
-    "object",
-    "property",
-    "p",
-    "oe",
-    "err",
-    "console",
-    "error",
-  ],
-  "sources": Array [],
-  "sourcesContent": Array [
-    " 	// install a JSONP callback for chunk loading
- 	var parentJsonpFunction = window[\\"webpackJsonp\\"];
- 	window[\\"webpackJsonp\\"] = function webpackJsonpCallback(chunkIds, moreModules, executeModules) {
- 		// add \\"moreModules\\" to the modules object,
- 		// then flag all \\"chunkIds\\" as loaded and fire callback
- 		var moduleId, chunkId, i = 0, resolves = [], result;
- 		for(;i < chunkIds.length; i++) {
- 			chunkId = chunkIds[i];
- 			if(installedChunks[chunkId]) {
- 				resolves.push(installedChunks[chunkId][0]);
- 			}
- 			installedChunks[chunkId] = 0;
- 		}
- 		for(moduleId in moreModules) {
- 			if(Object.prototype.hasOwnProperty.call(moreModules, moduleId)) {
- 				modules[moduleId] = moreModules[moduleId];
- 			}
- 		}
- 		if(parentJsonpFunction) parentJsonpFunction(chunkIds, moreModules, executeModules);
- 		while(resolves.length) {
- 			resolves.shift()();
- 		}
- 		if(executeModules) {
- 			for(i=0; i < executeModules.length; i++) {
- 				result = __webpack_require__(__webpack_require__.s = executeModules[i]);
- 			}
- 		}
- 		return result;
- 	};
+exports[`when options.sourceMap matches snapshot for a single \`false\` value (\`devtool\` is \`false\`): manifest.d6857f782c13a99b5917.js 1`] = `"!function(r){var n=window.webpackJsonp;window.webpackJsonp=function(e,u,c){for(var f,i,p,a=0,l=[];a<e.length;a++)i=e[a],o[i]&&l.push(o[i][0]),o[i]=0;for(f in u)Object.prototype.hasOwnProperty.call(u,f)&&(r[f]=u[f]);for(n&&n(e,u,c);l.length;)l.shift()();if(c)for(a=0;a<c.length;a++)p=t(t.s=c[a]);return p};var e={},o={1:0};function t(n){if(e[n])return e[n].exports;var o=e[n]={i:n,l:!1,exports:{}};return r[n].call(o.exports,o,o.exports,t),o.l=!0,o.exports}t.m=r,t.c=e,t.d=function(r,n,e){t.o(r,n)||Object.defineProperty(r,n,{configurable:!1,enumerable:!0,get:e})},t.n=function(r){var n=r&&r.__esModule?function(){return r.default}:function(){return r};return t.d(n,\\"a\\",n),n},t.o=function(r,n){return Object.prototype.hasOwnProperty.call(r,n)},t.p=\\"\\",t.oe=function(r){throw console.error(r),r}}([]);"`;
 
- 	// The module cache
- 	var installedModules = {};
+exports[`when options.sourceMap matches snapshot for a single \`false\` value (\`devtool\` is \`false\`): warnings 1`] = `Array []`;
 
- 	// objects to store loaded and loading chunks
- 	var installedChunks = {
- 		1: 0
- 	};
+exports[`when options.sourceMap matches snapshot for a single \`false\` value (\`devtool\` is \`source-map\`): errors 1`] = `Array []`;
 
- 	// The require function
- 	function __webpack_require__(moduleId) {
+exports[`when options.sourceMap matches snapshot for a single \`false\` value (\`devtool\` is \`source-map\`): main.0c220ec66316af2c1b24.js 1`] = `"webpackJsonp([0],[function(o,n){o.exports=function(){console.log(7)}}],[0]);"`;
 
- 		// Check if module is in cache
- 		if(installedModules[moduleId]) {
- 			return installedModules[moduleId].exports;
- 		}
- 		// Create a new module (and put it into the cache)
- 		var module = installedModules[moduleId] = {
- 			i: moduleId,
- 			l: false,
- 			exports: {}
- 		};
+exports[`when options.sourceMap matches snapshot for a single \`false\` value (\`devtool\` is \`source-map\`): manifest.d6857f782c13a99b5917.js 1`] = `"!function(r){var n=window.webpackJsonp;window.webpackJsonp=function(e,u,c){for(var f,i,p,a=0,l=[];a<e.length;a++)i=e[a],o[i]&&l.push(o[i][0]),o[i]=0;for(f in u)Object.prototype.hasOwnProperty.call(u,f)&&(r[f]=u[f]);for(n&&n(e,u,c);l.length;)l.shift()();if(c)for(a=0;a<c.length;a++)p=t(t.s=c[a]);return p};var e={},o={1:0};function t(n){if(e[n])return e[n].exports;var o=e[n]={i:n,l:!1,exports:{}};return r[n].call(o.exports,o,o.exports,t),o.l=!0,o.exports}t.m=r,t.c=e,t.d=function(r,n,e){t.o(r,n)||Object.defineProperty(r,n,{configurable:!1,enumerable:!0,get:e})},t.n=function(r){var n=r&&r.__esModule?function(){return r.default}:function(){return r};return t.d(n,\\"a\\",n),n},t.o=function(r,n){return Object.prototype.hasOwnProperty.call(r,n)},t.p=\\"\\",t.oe=function(r){throw console.error(r),r}}([]);"`;
 
- 		// Execute the module function
- 		modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
+exports[`when options.sourceMap matches snapshot for a single \`false\` value (\`devtool\` is \`source-map\`): warnings 1`] = `Array []`;
 
- 		// Flag the module as loaded
- 		module.l = true;
+exports[`when options.sourceMap matches snapshot for a single \`true\` value (\`devtool\` is \`false\`): errors 1`] = `Array []`;
 
- 		// Return the exports of the module
- 		return module.exports;
- 	}
+exports[`when options.sourceMap matches snapshot for a single \`true\` value (\`devtool\` is \`false\`): main.0c220ec66316af2c1b24.js 1`] = `"webpackJsonp([0],[function(o,n){o.exports=function(){console.log(7)}}],[0]);"`;
 
+exports[`when options.sourceMap matches snapshot for a single \`true\` value (\`devtool\` is \`false\`): manifest.d6857f782c13a99b5917.js 1`] = `"!function(r){var n=window.webpackJsonp;window.webpackJsonp=function(e,u,c){for(var f,i,p,a=0,l=[];a<e.length;a++)i=e[a],o[i]&&l.push(o[i][0]),o[i]=0;for(f in u)Object.prototype.hasOwnProperty.call(u,f)&&(r[f]=u[f]);for(n&&n(e,u,c);l.length;)l.shift()();if(c)for(a=0;a<c.length;a++)p=t(t.s=c[a]);return p};var e={},o={1:0};function t(n){if(e[n])return e[n].exports;var o=e[n]={i:n,l:!1,exports:{}};return r[n].call(o.exports,o,o.exports,t),o.l=!0,o.exports}t.m=r,t.c=e,t.d=function(r,n,e){t.o(r,n)||Object.defineProperty(r,n,{configurable:!1,enumerable:!0,get:e})},t.n=function(r){var n=r&&r.__esModule?function(){return r.default}:function(){return r};return t.d(n,\\"a\\",n),n},t.o=function(r,n){return Object.prototype.hasOwnProperty.call(r,n)},t.p=\\"\\",t.oe=function(r){throw console.error(r),r}}([]);"`;
 
- 	// expose the modules object (__webpack_modules__)
- 	__webpack_require__.m = modules;
+exports[`when options.sourceMap matches snapshot for a single \`true\` value (\`devtool\` is \`false\`): warnings 1`] = `Array []`;
 
- 	// expose the module cache
- 	__webpack_require__.c = installedModules;
+exports[`when options.sourceMap matches snapshot for a single \`true\` value (\`devtool\` is \`source-map\`) and source map invalid: broken-source-map.js 1`] = `"var test = 1;"`;
 
- 	// define getter function for harmony exports
- 	__webpack_require__.d = function(exports, name, getter) {
- 		if(!__webpack_require__.o(exports, name)) {
- 			Object.defineProperty(exports, name, {
- 				configurable: false,
- 				enumerable: true,
- 				get: getter
- 			});
- 		}
- 	};
-
- 	// getDefaultExport function for compatibility with non-harmony modules
- 	__webpack_require__.n = function(module) {
- 		var getter = module && module.__esModule ?
- 			function getDefault() { return module['default']; } :
- 			function getModuleExports() { return module; };
- 		__webpack_require__.d(getter, 'a', getter);
- 		return getter;
- 	};
-
- 	// Object.prototype.hasOwnProperty.call
- 	__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
-
- 	// __webpack_public_path__
- 	__webpack_require__.p = \\"\\";
-
- 	// on error function for async loading
- 	__webpack_require__.oe = function(err) { console.error(err); throw err; };
-",
-  ],
-  "version": 3,
-}
+exports[`when options.sourceMap matches snapshot for a single \`true\` value (\`devtool\` is \`source-map\`) and source map invalid: errors 1`] = `
+Array [
+  "Error: broken-source-map.js from UglifyJs
+Error: \\"version\\" is a required argument.",
+]
 `;
 
-exports[`when options.sourceMap true and options.parallel true matches snapshot: warnings 1`] = `Array []`;
+exports[`when options.sourceMap matches snapshot for a single \`true\` value (\`devtool\` is \`source-map\`) and source map invalid: main.4dff64fd1192e906e901.js 1`] = `
+"!function(n){var t={};function e(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return n[r].call(o.exports,o,o.exports,e),o.l=!0,o.exports}e.m=n,e.c=t,e.d=function(n,t,r){e.o(n,t)||Object.defineProperty(n,t,{configurable:!1,enumerable:!0,get:r})},e.n=function(n){var t=n&&n.__esModule?function(){return n.default}:function(){return n};return e.d(t,\\"a\\",t),t},e.o=function(n,t){return Object.prototype.hasOwnProperty.call(n,t)},e.p=\\"\\",e(e.s=0)}([function(n,t){n.exports=function(){console.log(7)}}]);
+//# sourceMappingURL=main.4dff64fd1192e906e901.js.map"
+`;
 
-exports[`when options.sourceMap true compilation handler when called optimize-chunk-assets handler only calls callback once: errors 1`] = `Array []`;
+exports[`when options.sourceMap matches snapshot for a single \`true\` value (\`devtool\` is \`source-map\`) and source map invalid: main.4dff64fd1192e906e901.js.map 1`] = `"{\\"version\\":3,\\"sources\\":[\\"webpack:///webpack/bootstrap a5a00654339b12ca9959\\",\\"webpack:///./test/fixtures/entry.js\\"],\\"names\\":[\\"installedModules\\",\\"__webpack_require__\\",\\"moduleId\\",\\"exports\\",\\"module\\",\\"i\\",\\"l\\",\\"modules\\",\\"call\\",\\"m\\",\\"c\\",\\"d\\",\\"name\\",\\"getter\\",\\"o\\",\\"Object\\",\\"defineProperty\\",\\"configurable\\",\\"enumerable\\",\\"get\\",\\"n\\",\\"__esModule\\",\\"object\\",\\"property\\",\\"prototype\\",\\"hasOwnProperty\\",\\"p\\",\\"s\\",\\"console\\",\\"log\\",\\"b\\"],\\"mappings\\":\\"aACA,IAAAA,KAGA,SAAAC,EAAAC,GAGA,GAAAF,EAAAE,GACA,OAAAF,EAAAE,GAAAC,QAGA,IAAAC,EAAAJ,EAAAE,IACAG,EAAAH,EACAI,GAAA,EACAH,YAUA,OANAI,EAAAL,GAAAM,KAAAJ,EAAAD,QAAAC,IAAAD,QAAAF,GAGAG,EAAAE,GAAA,EAGAF,EAAAD,QAKAF,EAAAQ,EAAAF,EAGAN,EAAAS,EAAAV,EAGAC,EAAAU,EAAA,SAAAR,EAAAS,EAAAC,GACAZ,EAAAa,EAAAX,EAAAS,IACAG,OAAAC,eAAAb,EAAAS,GACAK,cAAA,EACAC,YAAA,EACAC,IAAAN,KAMAZ,EAAAmB,EAAA,SAAAhB,GACA,IAAAS,EAAAT,KAAAiB,WACA,WAA2B,OAAAjB,EAAA,SAC3B,WAAiC,OAAAA,GAEjC,OADAH,EAAAU,EAAAE,EAAA,IAAAA,GACAA,GAIAZ,EAAAa,EAAA,SAAAQ,EAAAC,GAAsD,OAAAR,OAAAS,UAAAC,eAAAjB,KAAAc,EAAAC,IAGtDtB,EAAAyB,EAAA,GAGAzB,IAAA0B,EAAA,mBCxDAvB,EAAAD,QAAA,WAEAyB,QAAAC,IAAAC\\",\\"file\\":\\"main.4dff64fd1192e906e901.js\\",\\"sourcesContent\\":[\\" \\\\t// The module cache\\\\n \\\\tvar installedModules = {};\\\\n\\\\n \\\\t// The require function\\\\n \\\\tfunction __webpack_require__(moduleId) {\\\\n\\\\n \\\\t\\\\t// Check if module is in cache\\\\n \\\\t\\\\tif(installedModules[moduleId]) {\\\\n \\\\t\\\\t\\\\treturn installedModules[moduleId].exports;\\\\n \\\\t\\\\t}\\\\n \\\\t\\\\t// Create a new module (and put it into the cache)\\\\n \\\\t\\\\tvar module = installedModules[moduleId] = {\\\\n \\\\t\\\\t\\\\ti: moduleId,\\\\n \\\\t\\\\t\\\\tl: false,\\\\n \\\\t\\\\t\\\\texports: {}\\\\n \\\\t\\\\t};\\\\n\\\\n \\\\t\\\\t// Execute the module function\\\\n \\\\t\\\\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\\\\n\\\\n \\\\t\\\\t// Flag the module as loaded\\\\n \\\\t\\\\tmodule.l = true;\\\\n\\\\n \\\\t\\\\t// Return the exports of the module\\\\n \\\\t\\\\treturn module.exports;\\\\n \\\\t}\\\\n\\\\n\\\\n \\\\t// expose the modules object (__webpack_modules__)\\\\n \\\\t__webpack_require__.m = modules;\\\\n\\\\n \\\\t// expose the module cache\\\\n \\\\t__webpack_require__.c = installedModules;\\\\n\\\\n \\\\t// define getter function for harmony exports\\\\n \\\\t__webpack_require__.d = function(exports, name, getter) {\\\\n \\\\t\\\\tif(!__webpack_require__.o(exports, name)) {\\\\n \\\\t\\\\t\\\\tObject.defineProperty(exports, name, {\\\\n \\\\t\\\\t\\\\t\\\\tconfigurable: false,\\\\n \\\\t\\\\t\\\\t\\\\tenumerable: true,\\\\n \\\\t\\\\t\\\\t\\\\tget: getter\\\\n \\\\t\\\\t\\\\t});\\\\n \\\\t\\\\t}\\\\n \\\\t};\\\\n\\\\n \\\\t// getDefaultExport function for compatibility with non-harmony modules\\\\n \\\\t__webpack_require__.n = function(module) {\\\\n \\\\t\\\\tvar getter = module && module.__esModule ?\\\\n \\\\t\\\\t\\\\tfunction getDefault() { return module['default']; } :\\\\n \\\\t\\\\t\\\\tfunction getModuleExports() { return module; };\\\\n \\\\t\\\\t__webpack_require__.d(getter, 'a', getter);\\\\n \\\\t\\\\treturn getter;\\\\n \\\\t};\\\\n\\\\n \\\\t// Object.prototype.hasOwnProperty.call\\\\n \\\\t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\\\\n\\\\n \\\\t// __webpack_public_path__\\\\n \\\\t__webpack_require__.p = \\\\\\"\\\\\\";\\\\n\\\\n \\\\t// Load entry module and return exports\\\\n \\\\treturn __webpack_require__(__webpack_require__.s = 0);\\\\n\\\\n\\\\n\\\\n// WEBPACK FOOTER //\\\\n// webpack/bootstrap a5a00654339b12ca9959\\",\\"// foo\\\\n/* @preserve*/\\\\n// bar\\\\nconst a = 2 + 2;\\\\n\\\\nmodule.exports = function Foo() {\\\\n  const b = 2 + 2;\\\\n  console.log(b + 1 + 2);\\\\n};\\\\n\\\\n\\\\n\\\\n//////////////////\\\\n// WEBPACK FOOTER\\\\n// ./test/fixtures/entry.js\\\\n// module id = 0\\\\n// module chunks = 0\\"],\\"sourceRoot\\":\\"\\"}"`;
 
-exports[`when options.sourceMap true compilation handler when called optimize-chunk-assets handler only calls callback once: warnings 1`] = `
+exports[`when options.sourceMap matches snapshot for a single \`true\` value (\`devtool\` is \`source-map\`) and source map invalid: warnings 1`] = `
 Array [
-  [Error: test4.js contains invalid source map],
+  "Error: broken-source-map.js contains invalid source map",
 ]
 `;
 
-exports[`when options.sourceMap true matches snapshot: asset main.0c220ec66316af2c1b24.js 1`] = `"webpackJsonp([0],[function(o,n){o.exports=function(){console.log(7)}}],[0]);"`;
-
-exports[`when options.sourceMap true matches snapshot: asset manifest.d6857f782c13a99b5917.js 1`] = `"!function(r){var n=window.webpackJsonp;window.webpackJsonp=function(e,u,c){for(var f,i,p,a=0,l=[];a<e.length;a++)i=e[a],o[i]&&l.push(o[i][0]),o[i]=0;for(f in u)Object.prototype.hasOwnProperty.call(u,f)&&(r[f]=u[f]);for(n&&n(e,u,c);l.length;)l.shift()();if(c)for(a=0;a<c.length;a++)p=t(t.s=c[a]);return p};var e={},o={1:0};function t(n){if(e[n])return e[n].exports;var o=e[n]={i:n,l:!1,exports:{}};return r[n].call(o.exports,o,o.exports,t),o.l=!0,o.exports}t.m=r,t.c=e,t.d=function(r,n,e){t.o(r,n)||Object.defineProperty(r,n,{configurable:!1,enumerable:!0,get:e})},t.n=function(r){var n=r&&r.__esModule?function(){return r.default}:function(){return r};return t.d(n,\\"a\\",n),n},t.o=function(r,n){return Object.prototype.hasOwnProperty.call(r,n)},t.p=\\"\\",t.oe=function(r){throw console.error(r),r}}([]);"`;
+exports[`when options.sourceMap matches snapshot for a single \`true\` value (\`devtool\` is \`source-map\`): errors 1`] = `Array []`;
 
-exports[`when options.sourceMap true matches snapshot: errors 1`] = `Array []`;
-
-exports[`when options.sourceMap true matches snapshot: source map main.0c220ec66316af2c1b24.js 1`] = `
-Object {
-  "file": "x",
-  "mappings": "gCAKAA,EAAAC,QAAA,WAEAC,QAAAC,IAAAC",
-  "names": Array [
-    "module",
-    "exports",
-    "console",
-    "log",
-    "b",
-  ],
-  "sources": Array [],
-  "sourcesContent": Array [
-    "// foo
-/* @preserve*/
-// bar
-const a = 2 + 2;
-
-module.exports = function Foo() {
-  const b = 2 + 2;
-  console.log(b + 1 + 2);
-};
-",
-  ],
-  "version": 3,
-}
+exports[`when options.sourceMap matches snapshot for a single \`true\` value (\`devtool\` is \`source-map\`): main.0c220ec66316af2c1b24.js 1`] = `
+"webpackJsonp([0],[function(o,n){o.exports=function(){console.log(7)}}],[0]);
+//# sourceMappingURL=main.0c220ec66316af2c1b24.js.map"
 `;
 
-exports[`when options.sourceMap true matches snapshot: source map manifest.d6857f782c13a99b5917.js 1`] = `
-Object {
-  "file": "x",
-  "mappings": "aACA,IAAAA,EAAAC,OAAA,aACAA,OAAA,sBAAAC,EAAAC,EAAAC,GAIA,IADA,IAAAC,EAAAC,EAAAC,EAAAC,EAAA,EAAAC,KACQD,EAAAN,EAAAQ,OAAoBF,IAC5BF,EAAAJ,EAAAM,GACAG,EAAAL,IACAG,EAAAG,KAAAD,EAAAL,GAAA,IAEAK,EAAAL,GAAA,EAEA,IAAAD,KAAAF,EACAU,OAAAC,UAAAC,eAAAC,KAAAb,EAAAE,KACAY,EAAAZ,GAAAF,EAAAE,IAIA,IADAL,KAAAE,EAAAC,EAAAC,GACAK,EAAAC,QACAD,EAAAS,OAAAT,GAEA,GAAAL,EACA,IAAAI,EAAA,EAAYA,EAAAJ,EAAAM,OAA2BF,IACvCD,EAAAY,IAAAC,EAAAhB,EAAAI,IAGA,OAAAD,GAIA,IAAAc,KAGAV,GACAW,EAAA,GAIA,SAAAH,EAAAd,GAGA,GAAAgB,EAAAhB,GACA,OAAAgB,EAAAhB,GAAAkB,QAGA,IAAAC,EAAAH,EAAAhB,IACAG,EAAAH,EACAoB,GAAA,EACAF,YAUA,OANAN,EAAAZ,GAAAW,KAAAQ,EAAAD,QAAAC,IAAAD,QAAAJ,GAGAK,EAAAC,GAAA,EAGAD,EAAAD,QAKAJ,EAAAO,EAAAT,EAGAE,EAAAQ,EAAAN,EAGAF,EAAAS,EAAA,SAAAL,EAAAM,EAAAC,GACAX,EAAAY,EAAAR,EAAAM,IACAhB,OAAAmB,eAAAT,EAAAM,GACAI,cAAA,EACAC,YAAA,EACAC,IAAAL,KAMAX,EAAAiB,EAAA,SAAAZ,GACA,IAAAM,EAAAN,KAAAa,WACA,WAA2B,OAAAb,EAAA,SAC3B,WAAiC,OAAAA,GAEjC,OADAL,EAAAS,EAAAE,EAAA,IAAAA,GACAA,GAIAX,EAAAY,EAAA,SAAAO,EAAAC,GAAsD,OAAA1B,OAAAC,UAAAC,eAAAC,KAAAsB,EAAAC,IAGtDpB,EAAAqB,EAAA,GAGArB,EAAAsB,GAAA,SAAAC,GAA8D,MAApBC,QAAAC,MAAAF,GAAoBA",
-  "names": Array [
-    "parentJsonpFunction",
-    "window",
-    "chunkIds",
-    "moreModules",
-    "executeModules",
-    "moduleId",
-    "chunkId",
-    "result",
-    "i",
-    "resolves",
-    "length",
-    "installedChunks",
-    "push",
-    "Object",
-    "prototype",
-    "hasOwnProperty",
-    "call",
-    "modules",
-    "shift",
-    "__webpack_require__",
-    "s",
-    "installedModules",
-    "1",
-    "exports",
-    "module",
-    "l",
-    "m",
-    "c",
-    "d",
-    "name",
-    "getter",
-    "o",
-    "defineProperty",
-    "configurable",
-    "enumerable",
-    "get",
-    "n",
-    "__esModule",
-    "object",
-    "property",
-    "p",
-    "oe",
-    "err",
-    "console",
-    "error",
-  ],
-  "sources": Array [],
-  "sourcesContent": Array [
-    " 	// install a JSONP callback for chunk loading
- 	var parentJsonpFunction = window[\\"webpackJsonp\\"];
- 	window[\\"webpackJsonp\\"] = function webpackJsonpCallback(chunkIds, moreModules, executeModules) {
- 		// add \\"moreModules\\" to the modules object,
- 		// then flag all \\"chunkIds\\" as loaded and fire callback
- 		var moduleId, chunkId, i = 0, resolves = [], result;
- 		for(;i < chunkIds.length; i++) {
- 			chunkId = chunkIds[i];
- 			if(installedChunks[chunkId]) {
- 				resolves.push(installedChunks[chunkId][0]);
- 			}
- 			installedChunks[chunkId] = 0;
- 		}
- 		for(moduleId in moreModules) {
- 			if(Object.prototype.hasOwnProperty.call(moreModules, moduleId)) {
- 				modules[moduleId] = moreModules[moduleId];
- 			}
- 		}
- 		if(parentJsonpFunction) parentJsonpFunction(chunkIds, moreModules, executeModules);
- 		while(resolves.length) {
- 			resolves.shift()();
- 		}
- 		if(executeModules) {
- 			for(i=0; i < executeModules.length; i++) {
- 				result = __webpack_require__(__webpack_require__.s = executeModules[i]);
- 			}
- 		}
- 		return result;
- 	};
-
- 	// The module cache
- 	var installedModules = {};
-
- 	// objects to store loaded and loading chunks
- 	var installedChunks = {
- 		1: 0
- 	};
-
- 	// The require function
- 	function __webpack_require__(moduleId) {
-
- 		// Check if module is in cache
- 		if(installedModules[moduleId]) {
- 			return installedModules[moduleId].exports;
- 		}
- 		// Create a new module (and put it into the cache)
- 		var module = installedModules[moduleId] = {
- 			i: moduleId,
- 			l: false,
- 			exports: {}
- 		};
-
- 		// Execute the module function
- 		modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
-
- 		// Flag the module as loaded
- 		module.l = true;
-
- 		// Return the exports of the module
- 		return module.exports;
- 	}
+exports[`when options.sourceMap matches snapshot for a single \`true\` value (\`devtool\` is \`source-map\`): main.0c220ec66316af2c1b24.js.map 1`] = `"{\\"version\\":3,\\"sources\\":[\\"webpack:///./test/fixtures/entry.js\\"],\\"names\\":[\\"module\\",\\"exports\\",\\"console\\",\\"log\\",\\"b\\"],\\"mappings\\":\\"gCAKAA,EAAAC,QAAA,WAEAC,QAAAC,IAAAC\\",\\"file\\":\\"main.0c220ec66316af2c1b24.js\\",\\"sourcesContent\\":[\\"// foo\\\\n/* @preserve*/\\\\n// bar\\\\nconst a = 2 + 2;\\\\n\\\\nmodule.exports = function Foo() {\\\\n  const b = 2 + 2;\\\\n  console.log(b + 1 + 2);\\\\n};\\\\n\\\\n\\\\n\\\\n//////////////////\\\\n// WEBPACK FOOTER\\\\n// ./test/fixtures/entry.js\\\\n// module id = 0\\\\n// module chunks = 0\\"],\\"sourceRoot\\":\\"\\"}"`;
 
-
- 	// expose the modules object (__webpack_modules__)
- 	__webpack_require__.m = modules;
-
- 	// expose the module cache
- 	__webpack_require__.c = installedModules;
-
- 	// define getter function for harmony exports
- 	__webpack_require__.d = function(exports, name, getter) {
- 		if(!__webpack_require__.o(exports, name)) {
- 			Object.defineProperty(exports, name, {
- 				configurable: false,
- 				enumerable: true,
- 				get: getter
- 			});
- 		}
- 	};
-
- 	// getDefaultExport function for compatibility with non-harmony modules
- 	__webpack_require__.n = function(module) {
- 		var getter = module && module.__esModule ?
- 			function getDefault() { return module['default']; } :
- 			function getModuleExports() { return module; };
- 		__webpack_require__.d(getter, 'a', getter);
- 		return getter;
- 	};
-
- 	// Object.prototype.hasOwnProperty.call
- 	__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
-
- 	// __webpack_public_path__
- 	__webpack_require__.p = \\"\\";
-
- 	// on error function for async loading
- 	__webpack_require__.oe = function(err) { console.error(err); throw err; };
-",
-  ],
-  "version": 3,
-}
+exports[`when options.sourceMap matches snapshot for a single \`true\` value (\`devtool\` is \`source-map\`): manifest.d6857f782c13a99b5917.js 1`] = `
+"!function(r){var n=window.webpackJsonp;window.webpackJsonp=function(e,u,c){for(var f,i,p,a=0,l=[];a<e.length;a++)i=e[a],o[i]&&l.push(o[i][0]),o[i]=0;for(f in u)Object.prototype.hasOwnProperty.call(u,f)&&(r[f]=u[f]);for(n&&n(e,u,c);l.length;)l.shift()();if(c)for(a=0;a<c.length;a++)p=t(t.s=c[a]);return p};var e={},o={1:0};function t(n){if(e[n])return e[n].exports;var o=e[n]={i:n,l:!1,exports:{}};return r[n].call(o.exports,o,o.exports,t),o.l=!0,o.exports}t.m=r,t.c=e,t.d=function(r,n,e){t.o(r,n)||Object.defineProperty(r,n,{configurable:!1,enumerable:!0,get:e})},t.n=function(r){var n=r&&r.__esModule?function(){return r.default}:function(){return r};return t.d(n,\\"a\\",n),n},t.o=function(r,n){return Object.prototype.hasOwnProperty.call(r,n)},t.p=\\"\\",t.oe=function(r){throw console.error(r),r}}([]);
+//# sourceMappingURL=manifest.d6857f782c13a99b5917.js.map"
 `;
 
-exports[`when options.sourceMap true matches snapshot: warnings 1`] = `Array []`;
+exports[`when options.sourceMap matches snapshot for a single \`true\` value (\`devtool\` is \`source-map\`): manifest.d6857f782c13a99b5917.js.map 1`] = `"{\\"version\\":3,\\"sources\\":[\\"webpack:///webpack/bootstrap 88fec89b06900e3e594c\\"],\\"names\\":[\\"parentJsonpFunction\\",\\"window\\",\\"chunkIds\\",\\"moreModules\\",\\"executeModules\\",\\"moduleId\\",\\"chunkId\\",\\"result\\",\\"i\\",\\"resolves\\",\\"length\\",\\"installedChunks\\",\\"push\\",\\"Object\\",\\"prototype\\",\\"hasOwnProperty\\",\\"call\\",\\"modules\\",\\"shift\\",\\"__webpack_require__\\",\\"s\\",\\"installedModules\\",\\"1\\",\\"exports\\",\\"module\\",\\"l\\",\\"m\\",\\"c\\",\\"d\\",\\"name\\",\\"getter\\",\\"o\\",\\"defineProperty\\",\\"configurable\\",\\"enumerable\\",\\"get\\",\\"n\\",\\"__esModule\\",\\"object\\",\\"property\\",\\"p\\",\\"oe\\",\\"err\\",\\"console\\",\\"error\\"],\\"mappings\\":\\"aACA,IAAAA,EAAAC,OAAA,aACAA,OAAA,sBAAAC,EAAAC,EAAAC,GAIA,IADA,IAAAC,EAAAC,EAAAC,EAAAC,EAAA,EAAAC,KACQD,EAAAN,EAAAQ,OAAoBF,IAC5BF,EAAAJ,EAAAM,GACAG,EAAAL,IACAG,EAAAG,KAAAD,EAAAL,GAAA,IAEAK,EAAAL,GAAA,EAEA,IAAAD,KAAAF,EACAU,OAAAC,UAAAC,eAAAC,KAAAb,EAAAE,KACAY,EAAAZ,GAAAF,EAAAE,IAIA,IADAL,KAAAE,EAAAC,EAAAC,GACAK,EAAAC,QACAD,EAAAS,OAAAT,GAEA,GAAAL,EACA,IAAAI,EAAA,EAAYA,EAAAJ,EAAAM,OAA2BF,IACvCD,EAAAY,IAAAC,EAAAhB,EAAAI,IAGA,OAAAD,GAIA,IAAAc,KAGAV,GACAW,EAAA,GAIA,SAAAH,EAAAd,GAGA,GAAAgB,EAAAhB,GACA,OAAAgB,EAAAhB,GAAAkB,QAGA,IAAAC,EAAAH,EAAAhB,IACAG,EAAAH,EACAoB,GAAA,EACAF,YAUA,OANAN,EAAAZ,GAAAW,KAAAQ,EAAAD,QAAAC,IAAAD,QAAAJ,GAGAK,EAAAC,GAAA,EAGAD,EAAAD,QAKAJ,EAAAO,EAAAT,EAGAE,EAAAQ,EAAAN,EAGAF,EAAAS,EAAA,SAAAL,EAAAM,EAAAC,GACAX,EAAAY,EAAAR,EAAAM,IACAhB,OAAAmB,eAAAT,EAAAM,GACAI,cAAA,EACAC,YAAA,EACAC,IAAAL,KAMAX,EAAAiB,EAAA,SAAAZ,GACA,IAAAM,EAAAN,KAAAa,WACA,WAA2B,OAAAb,EAAA,SAC3B,WAAiC,OAAAA,GAEjC,OADAL,EAAAS,EAAAE,EAAA,IAAAA,GACAA,GAIAX,EAAAY,EAAA,SAAAO,EAAAC,GAAsD,OAAA1B,OAAAC,UAAAC,eAAAC,KAAAsB,EAAAC,IAGtDpB,EAAAqB,EAAA,GAGArB,EAAAsB,GAAA,SAAAC,GAA8D,MAApBC,QAAAC,MAAAF,GAAoBA\\",\\"file\\":\\"manifest.d6857f782c13a99b5917.js\\",\\"sourcesContent\\":[\\" \\\\t// install a JSONP callback for chunk loading\\\\n \\\\tvar parentJsonpFunction = window[\\\\\\"webpackJsonp\\\\\\"];\\\\n \\\\twindow[\\\\\\"webpackJsonp\\\\\\"] = function webpackJsonpCallback(chunkIds, moreModules, executeModules) {\\\\n \\\\t\\\\t// add \\\\\\"moreModules\\\\\\" to the modules object,\\\\n \\\\t\\\\t// then flag all \\\\\\"chunkIds\\\\\\" as loaded and fire callback\\\\n \\\\t\\\\tvar moduleId, chunkId, i = 0, resolves = [], result;\\\\n \\\\t\\\\tfor(;i < chunkIds.length; i++) {\\\\n \\\\t\\\\t\\\\tchunkId = chunkIds[i];\\\\n \\\\t\\\\t\\\\tif(installedChunks[chunkId]) {\\\\n \\\\t\\\\t\\\\t\\\\tresolves.push(installedChunks[chunkId][0]);\\\\n \\\\t\\\\t\\\\t}\\\\n \\\\t\\\\t\\\\tinstalledChunks[chunkId] = 0;\\\\n \\\\t\\\\t}\\\\n \\\\t\\\\tfor(moduleId in moreModules) {\\\\n \\\\t\\\\t\\\\tif(Object.prototype.hasOwnProperty.call(moreModules, moduleId)) {\\\\n \\\\t\\\\t\\\\t\\\\tmodules[moduleId] = moreModules[moduleId];\\\\n \\\\t\\\\t\\\\t}\\\\n \\\\t\\\\t}\\\\n \\\\t\\\\tif(parentJsonpFunction) parentJsonpFunction(chunkIds, moreModules, executeModules);\\\\n \\\\t\\\\twhile(resolves.length) {\\\\n \\\\t\\\\t\\\\tresolves.shift()();\\\\n \\\\t\\\\t}\\\\n \\\\t\\\\tif(executeModules) {\\\\n \\\\t\\\\t\\\\tfor(i=0; i < executeModules.length; i++) {\\\\n \\\\t\\\\t\\\\t\\\\tresult = __webpack_require__(__webpack_require__.s = executeModules[i]);\\\\n \\\\t\\\\t\\\\t}\\\\n \\\\t\\\\t}\\\\n \\\\t\\\\treturn result;\\\\n \\\\t};\\\\n\\\\n \\\\t// The module cache\\\\n \\\\tvar installedModules = {};\\\\n\\\\n \\\\t// objects to store loaded and loading chunks\\\\n \\\\tvar installedChunks = {\\\\n \\\\t\\\\t1: 0\\\\n \\\\t};\\\\n\\\\n \\\\t// The require function\\\\n \\\\tfunction __webpack_require__(moduleId) {\\\\n\\\\n \\\\t\\\\t// Check if module is in cache\\\\n \\\\t\\\\tif(installedModules[moduleId]) {\\\\n \\\\t\\\\t\\\\treturn installedModules[moduleId].exports;\\\\n \\\\t\\\\t}\\\\n \\\\t\\\\t// Create a new module (and put it into the cache)\\\\n \\\\t\\\\tvar module = installedModules[moduleId] = {\\\\n \\\\t\\\\t\\\\ti: moduleId,\\\\n \\\\t\\\\t\\\\tl: false,\\\\n \\\\t\\\\t\\\\texports: {}\\\\n \\\\t\\\\t};\\\\n\\\\n \\\\t\\\\t// Execute the module function\\\\n \\\\t\\\\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\\\\n\\\\n \\\\t\\\\t// Flag the module as loaded\\\\n \\\\t\\\\tmodule.l = true;\\\\n\\\\n \\\\t\\\\t// Return the exports of the module\\\\n \\\\t\\\\treturn module.exports;\\\\n \\\\t}\\\\n\\\\n\\\\n \\\\t// expose the modules object (__webpack_modules__)\\\\n \\\\t__webpack_require__.m = modules;\\\\n\\\\n \\\\t// expose the module cache\\\\n \\\\t__webpack_require__.c = installedModules;\\\\n\\\\n \\\\t// define getter function for harmony exports\\\\n \\\\t__webpack_require__.d = function(exports, name, getter) {\\\\n \\\\t\\\\tif(!__webpack_require__.o(exports, name)) {\\\\n \\\\t\\\\t\\\\tObject.defineProperty(exports, name, {\\\\n \\\\t\\\\t\\\\t\\\\tconfigurable: false,\\\\n \\\\t\\\\t\\\\t\\\\tenumerable: true,\\\\n \\\\t\\\\t\\\\t\\\\tget: getter\\\\n \\\\t\\\\t\\\\t});\\\\n \\\\t\\\\t}\\\\n \\\\t};\\\\n\\\\n \\\\t// getDefaultExport function for compatibility with non-harmony modules\\\\n \\\\t__webpack_require__.n = function(module) {\\\\n \\\\t\\\\tvar getter = module && module.__esModule ?\\\\n \\\\t\\\\t\\\\tfunction getDefault() { return module['default']; } :\\\\n \\\\t\\\\t\\\\tfunction getModuleExports() { return module; };\\\\n \\\\t\\\\t__webpack_require__.d(getter, 'a', getter);\\\\n \\\\t\\\\treturn getter;\\\\n \\\\t};\\\\n\\\\n \\\\t// Object.prototype.hasOwnProperty.call\\\\n \\\\t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\\\\n\\\\n \\\\t// __webpack_public_path__\\\\n \\\\t__webpack_require__.p = \\\\\\"\\\\\\";\\\\n\\\\n \\\\t// on error function for async loading\\\\n \\\\t__webpack_require__.oe = function(err) { console.error(err); throw err; };\\\\n\\\\n\\\\n\\\\n// WEBPACK FOOTER //\\\\n// webpack/bootstrap 88fec89b06900e3e594c\\"],\\"sourceRoot\\":\\"\\"}"`;
+
+exports[`when options.sourceMap matches snapshot for a single \`true\` value (\`devtool\` is \`source-map\`): warnings 1`] = `Array []`;
diff --git a/test/__snapshots__/uglifyOptions-option.test.js.snap b/test/__snapshots__/uglifyOptions-option.test.js.snap
index d940f7b..366fdd2 100644
--- a/test/__snapshots__/uglifyOptions-option.test.js.snap
+++ b/test/__snapshots__/uglifyOptions-option.test.js.snap
@@ -596,6 +596,141 @@ exports[`when applied with uglifyOptions options matches snapshot for \`toplevel
 
 exports[`when applied with uglifyOptions options matches snapshot for \`toplevel\` option (boolean \`true\` value): warnings 1`] = `Array []`;
 
+exports[`when applied with uglifyOptions options matches snapshot for \`unknown\` option: errors 1`] = `
+Array [
+  "Error: main.0c220ec66316af2c1b24.js from UglifyJs
+DefaultsError: \`unknown\` is not a supported option",
+  "Error: manifest.d6857f782c13a99b5917.js from UglifyJs
+DefaultsError: \`unknown\` is not a supported option",
+]
+`;
+
+exports[`when applied with uglifyOptions options matches snapshot for \`unknown\` option: main.0c220ec66316af2c1b24.js 1`] = `
+"webpackJsonp([0],[
+/* 0 */
+/***/ (function(module, exports) {
+
+// foo
+/* @preserve*/
+// bar
+const a = 2 + 2;
+
+module.exports = function Foo() {
+  const b = 2 + 2;
+  console.log(b + 1 + 2);
+};
+
+
+/***/ })
+],[0]);"
+`;
+
+exports[`when applied with uglifyOptions options matches snapshot for \`unknown\` option: manifest.d6857f782c13a99b5917.js 1`] = `
+"/******/ (function(modules) { // webpackBootstrap
+/******/ 	// install a JSONP callback for chunk loading
+/******/ 	var parentJsonpFunction = window[\\"webpackJsonp\\"];
+/******/ 	window[\\"webpackJsonp\\"] = function webpackJsonpCallback(chunkIds, moreModules, executeModules) {
+/******/ 		// add \\"moreModules\\" to the modules object,
+/******/ 		// then flag all \\"chunkIds\\" as loaded and fire callback
+/******/ 		var moduleId, chunkId, i = 0, resolves = [], result;
+/******/ 		for(;i < chunkIds.length; i++) {
+/******/ 			chunkId = chunkIds[i];
+/******/ 			if(installedChunks[chunkId]) {
+/******/ 				resolves.push(installedChunks[chunkId][0]);
+/******/ 			}
+/******/ 			installedChunks[chunkId] = 0;
+/******/ 		}
+/******/ 		for(moduleId in moreModules) {
+/******/ 			if(Object.prototype.hasOwnProperty.call(moreModules, moduleId)) {
+/******/ 				modules[moduleId] = moreModules[moduleId];
+/******/ 			}
+/******/ 		}
+/******/ 		if(parentJsonpFunction) parentJsonpFunction(chunkIds, moreModules, executeModules);
+/******/ 		while(resolves.length) {
+/******/ 			resolves.shift()();
+/******/ 		}
+/******/ 		if(executeModules) {
+/******/ 			for(i=0; i < executeModules.length; i++) {
+/******/ 				result = __webpack_require__(__webpack_require__.s = executeModules[i]);
+/******/ 			}
+/******/ 		}
+/******/ 		return result;
+/******/ 	};
+/******/
+/******/ 	// The module cache
+/******/ 	var installedModules = {};
+/******/
+/******/ 	// objects to store loaded and loading chunks
+/******/ 	var installedChunks = {
+/******/ 		1: 0
+/******/ 	};
+/******/
+/******/ 	// The require function
+/******/ 	function __webpack_require__(moduleId) {
+/******/
+/******/ 		// Check if module is in cache
+/******/ 		if(installedModules[moduleId]) {
+/******/ 			return installedModules[moduleId].exports;
+/******/ 		}
+/******/ 		// Create a new module (and put it into the cache)
+/******/ 		var module = installedModules[moduleId] = {
+/******/ 			i: moduleId,
+/******/ 			l: false,
+/******/ 			exports: {}
+/******/ 		};
+/******/
+/******/ 		// Execute the module function
+/******/ 		modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
+/******/
+/******/ 		// Flag the module as loaded
+/******/ 		module.l = true;
+/******/
+/******/ 		// Return the exports of the module
+/******/ 		return module.exports;
+/******/ 	}
+/******/
+/******/
+/******/ 	// expose the modules object (__webpack_modules__)
+/******/ 	__webpack_require__.m = modules;
+/******/
+/******/ 	// expose the module cache
+/******/ 	__webpack_require__.c = installedModules;
+/******/
+/******/ 	// define getter function for harmony exports
+/******/ 	__webpack_require__.d = function(exports, name, getter) {
+/******/ 		if(!__webpack_require__.o(exports, name)) {
+/******/ 			Object.defineProperty(exports, name, {
+/******/ 				configurable: false,
+/******/ 				enumerable: true,
+/******/ 				get: getter
+/******/ 			});
+/******/ 		}
+/******/ 	};
+/******/
+/******/ 	// getDefaultExport function for compatibility with non-harmony modules
+/******/ 	__webpack_require__.n = function(module) {
+/******/ 		var getter = module && module.__esModule ?
+/******/ 			function getDefault() { return module['default']; } :
+/******/ 			function getModuleExports() { return module; };
+/******/ 		__webpack_require__.d(getter, 'a', getter);
+/******/ 		return getter;
+/******/ 	};
+/******/
+/******/ 	// Object.prototype.hasOwnProperty.call
+/******/ 	__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
+/******/
+/******/ 	// __webpack_public_path__
+/******/ 	__webpack_require__.p = \\"\\";
+/******/
+/******/ 	// on error function for async loading
+/******/ 	__webpack_require__.oe = function(err) { console.error(err); throw err; };
+/******/ })
+/************************************************************************/
+/******/ ([]);"
+`;
+
+exports[`when applied with uglifyOptions options matches snapshot for \`unknown\` option: warnings 1`] = `Array []`;
+
 exports[`when applied with uglifyOptions options matches snapshot for \`warnings\` option (boolean \`false\` value): errors 1`] = `Array []`;
 
 exports[`when applied with uglifyOptions options matches snapshot for \`warnings\` option (boolean \`false\` value): main.b30dcc7a86bd9929c922.js 1`] = `"webpackJsonp([0],[function(n,c){}],[0]);"`;
@@ -612,7 +747,7 @@ exports[`when applied with uglifyOptions options matches snapshot for \`warnings
 
 exports[`when applied with uglifyOptions options matches snapshot for \`warnings\` option (boolean \`true\` value): warnings 1`] = `
 Array [
-  "Dropping unreachable code [main.b30dcc7a86bd9929c922.js:5,41]",
-  "Dropping unused function foo [main.b30dcc7a86bd9929c922.js:5,9]",
+  "UglifyJs Plugin: Dropping unreachable code [main.b30dcc7a86bd9929c922.js:5,41]",
+  "UglifyJs Plugin: Dropping unused function foo [main.b30dcc7a86bd9929c922.js:5,9]",
 ]
 `;
diff --git a/test/__snapshots__/validation.test.js.snap b/test/__snapshots__/validation.test.js.snap
new file mode 100644
index 0000000..ff3f4ae
--- /dev/null
+++ b/test/__snapshots__/validation.test.js.snap
@@ -0,0 +1,91 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`validation 1`] = `
+"UglifyJs Plugin Invalid Options
+
+options['doesntExist'] is an invalid additional property
+"
+`;
+
+exports[`validation 2`] = `
+"UglifyJs Plugin Invalid Options
+
+options.cache should be boolean
+options.cache should be string
+options.cache should match exactly one schema in oneOf
+"
+`;
+
+exports[`validation 3`] = `
+"UglifyJs Plugin Invalid Options
+
+options.parallel should be boolean
+options.parallel should be integer
+options.parallel should match exactly one schema in oneOf
+"
+`;
+
+exports[`validation 4`] = `
+"UglifyJs Plugin Invalid Options
+
+options.parallel should be boolean
+options.parallel should be integer
+options.parallel should match exactly one schema in oneOf
+"
+`;
+
+exports[`validation 5`] = `
+"UglifyJs Plugin Invalid Options
+
+options.sourceMap should be boolean
+"
+`;
+
+exports[`validation 6`] = `
+"UglifyJs Plugin Invalid Options
+
+options.uglifyOptions should be object
+"
+`;
+
+exports[`validation 7`] = `
+"UglifyJs Plugin Invalid Options
+
+options.uglifyOptions.ie8 should be boolean
+"
+`;
+
+exports[`validation 8`] = `
+"UglifyJs Plugin Invalid Options
+
+options.uglifyOptions.ecma should be integer
+"
+`;
+
+exports[`validation 9`] = `
+"UglifyJs Plugin Invalid Options
+
+options.uglifyOptions.ecma should be integer
+"
+`;
+
+exports[`validation 10`] = `
+"UglifyJs Plugin Invalid Options
+
+options.uglifyOptions.ecma should be integer
+"
+`;
+
+exports[`validation 11`] = `
+"UglifyJs Plugin Invalid Options
+
+options.uglifyOptions.ecma should be >= 5
+"
+`;
+
+exports[`validation 12`] = `
+"UglifyJs Plugin Invalid Options
+
+options.uglifyOptions.ecma should be <= 8
+"
+`;
diff --git a/test/__snapshots__/warningsFilter-option.test.js.snap b/test/__snapshots__/warningsFilter-option.test.js.snap
index 5b005be..bfffb73 100644
--- a/test/__snapshots__/warningsFilter-option.test.js.snap
+++ b/test/__snapshots__/warningsFilter-option.test.js.snap
@@ -10,10 +10,10 @@ exports[`when applied with \`warningsFilter\` option matches snapshot for a \`fu
 
 exports[`when applied with \`warningsFilter\` option matches snapshot for a \`function\` value and \`sourceMap\` is \`false\`: warnings 1`] = `
 Array [
-  "Dropping unreachable code [one.d321aed3a325448435a0.js:5,41]",
-  "Dropping unused function foo [one.d321aed3a325448435a0.js:5,9]",
-  "Dropping unreachable code [two.da1b0e3de955e7df6b6e.js:6,41]",
-  "Dropping unused function foo [two.da1b0e3de955e7df6b6e.js:6,9]",
+  "UglifyJs Plugin: Dropping unreachable code [one.d321aed3a325448435a0.js:5,41]",
+  "UglifyJs Plugin: Dropping unused function foo [one.d321aed3a325448435a0.js:5,9]",
+  "UglifyJs Plugin: Dropping unreachable code [two.da1b0e3de955e7df6b6e.js:6,41]",
+  "UglifyJs Plugin: Dropping unused function foo [two.da1b0e3de955e7df6b6e.js:6,9]",
 ]
 `;
 
diff --git a/test/cache-option.test.js b/test/cache-option.test.js
index fbac018..2fc2a24 100644
--- a/test/cache-option.test.js
+++ b/test/cache-option.test.js
@@ -286,4 +286,28 @@ describe('when applied with `cache` option', () => {
         });
     });
   });
+
+  it('matches snapshot for errors into `cacheKeys` option', () => {
+    new UglifyJsPlugin({
+      cache: true,
+      cacheKeys: () => {
+        throw new Error('message');
+      },
+    }).apply(compiler);
+
+
+    return compile(compiler).then((stats) => {
+      const errors = stats.compilation.errors.map(cleanErrorStack);
+      const warnings = stats.compilation.warnings.map(cleanErrorStack);
+
+      expect(errors).toMatchSnapshot('errors');
+      expect(warnings).toMatchSnapshot('warnings');
+
+      for (const file in stats.compilation.assets) {
+        if (Object.prototype.hasOwnProperty.call(stats.compilation.assets, file)) {
+          expect(stats.compilation.assets[file].source()).toMatchSnapshot(file);
+        }
+      }
+    });
+  });
 });
diff --git a/test/cjs.test.js b/test/cjs.test.js
new file mode 100644
index 0000000..26081bc
--- /dev/null
+++ b/test/cjs.test.js
@@ -0,0 +1,8 @@
+import UglifyJsPlugin from '../src';
+import CJSUglifyJsPlugin from '../src/cjs';
+
+describe('CJS', () => {
+  it('should exported plugin', () => {
+    expect(CJSUglifyJsPlugin).toEqual(UglifyJsPlugin);
+  });
+});
diff --git a/test/extractComments-option.test.js b/test/extractComments-option.test.js
index 0f65684..cf81d97 100644
--- a/test/extractComments-option.test.js
+++ b/test/extractComments-option.test.js
@@ -1,257 +1,167 @@
 import UglifyJsPlugin from '../src/index';
-import { PluginEnvironment } from './helpers';
-
-describe('when options.extractComments', () => {
-  it('normalizes extractConmments', () => {
-    const pluginEnvironment = new PluginEnvironment();
-    const compilerEnv = pluginEnvironment.getEnvironmentStub();
-    compilerEnv.context = '';
-
-    const plugin = new UglifyJsPlugin({
-      uglifyOptions: {
-        warnings: true,
-        mangle: {
-          properties: {
-            builtins: true,
-          },
-        },
-      },
-      extractComments: true,
-    });
-    plugin.apply(compilerEnv);
+import { cleanErrorStack, compile, createCompiler } from './helpers';
 
-    const [eventBinding] = pluginEnvironment.getEventBindings();
-    const chunkPluginEnvironment = new PluginEnvironment();
+describe('when applied with `extractComments` option', () => {
+  let compiler;
 
-    const compilation = chunkPluginEnvironment.getEnvironmentStub();
-    compilation.assets = {
-      'test.js': {
-        source: () => 'var foo = 1;',
+  beforeEach(() => {
+    compiler = createCompiler({
+      entry: {
+        one: `${__dirname}/fixtures/comments.js`,
       },
-      'test1.js': {
-        source: () => 'function foo(x) { if (x) { return bar(); not_called1(); } }',
-        map: () => {
-          return {
-            version: 3,
-            sources: ['test1.js'],
-            names: ['foo', 'x', 'bar', 'not_called1'],
-            mappings: 'AAAA,QAASA,KAAIC,GACT,GAAIA,EAAG,CACH,MAAOC,MACPC',
-          };
-        },
+      output: {
+        filename: 'filename/[name].[chunkhash].js',
+        chunkFilename: 'chunks/[id].[name].[chunkhash].js',
       },
-    };
-    compilation.warnings = [];
-    compilation.errors = [];
+    });
+  });
+
+  it('matches snapshot when is not specify', () => {
+    new UglifyJsPlugin().apply(compiler);
 
-    eventBinding.handler(compilation);
-    const [compilationEventBinding] = chunkPluginEnvironment.getEventBindings();
+    return compile(compiler).then((stats) => {
+      const errors = stats.compilation.errors.map(cleanErrorStack);
+      const warnings = stats.compilation.warnings.map(cleanErrorStack);
 
-    compilationEventBinding.handler([{
-      files: ['test.js'],
-    }], () => {
-      expect(compilation.errors.length).toBe(0);
+      expect(errors).toMatchSnapshot('errors');
+      expect(warnings).toMatchSnapshot('warnings');
+
+      for (const file in stats.compilation.assets) {
+        if (Object.prototype.hasOwnProperty.call(stats.compilation.assets, file)) {
+          expect(stats.compilation.assets[file].source()).toMatchSnapshot(file);
+        }
+      }
     });
   });
 
-  it('normalizes when options.extractComments is not specify', () => {
-    const pluginEnvironment = new PluginEnvironment();
-    const compilerEnv = pluginEnvironment.getEnvironmentStub();
-    compilerEnv.context = '';
-
-    const plugin = new UglifyJsPlugin();
-    plugin.apply(compilerEnv);
-    const [eventBinding] = pluginEnvironment.getEventBindings();
-    const chunkPluginEnvironment = new PluginEnvironment();
-    const compilation = chunkPluginEnvironment.getEnvironmentStub();
-    compilation.assets = {
-      'test.js': {
-        source: () => '// Comment\nvar foo = 1;',
-      },
-      'test1.js': {
-        source: () => '/*! Legal Comment */\nvar foo = 1;',
-      },
-    };
-    compilation.warnings = [];
-    compilation.errors = [];
-
-    eventBinding.handler(compilation);
-    const [compilationEventBinding] = chunkPluginEnvironment.getEventBindings();
-
-    compilationEventBinding.handler([{
-      files: ['test.js', 'test1.js'],
-    }], () => {
-      for (const file in compilation.assets) {
-        if (Object.prototype.hasOwnProperty.call(compilation.assets, file)) {
-          expect(compilation.assets[file].source()).toMatchSnapshot(file);
+  it('matches snapshot for a `false` value', () => {
+    new UglifyJsPlugin({ extractComments: false }).apply(compiler);
+
+    return compile(compiler).then((stats) => {
+      const errors = stats.compilation.errors.map(cleanErrorStack);
+      const warnings = stats.compilation.warnings.map(cleanErrorStack);
+
+      expect(errors).toMatchSnapshot('errors');
+      expect(warnings).toMatchSnapshot('warnings');
+
+      for (const file in stats.compilation.assets) {
+        if (Object.prototype.hasOwnProperty.call(stats.compilation.assets, file)) {
+          expect(stats.compilation.assets[file].source()).toMatchSnapshot(file);
         }
       }
-      expect(compilation.errors).toMatchSnapshot('errors');
-      expect(compilation.warnings).toMatchSnapshot('warnings');
     });
   });
 
-  it('normalizes when options.extractComments is boolean - "true"', () => {
-    const pluginEnvironment = new PluginEnvironment();
-    const compilerEnv = pluginEnvironment.getEnvironmentStub();
-    compilerEnv.context = '';
+  it('matches snapshot for a `true` value', () => {
+    new UglifyJsPlugin({ extractComments: true }).apply(compiler);
 
-    const plugin = new UglifyJsPlugin({
-      extractComments: true,
-    });
-    plugin.apply(compilerEnv);
-    const [eventBinding] = pluginEnvironment.getEventBindings();
-    const chunkPluginEnvironment = new PluginEnvironment();
-    const compilation = chunkPluginEnvironment.getEnvironmentStub();
-    compilation.assets = {
-      'test.js': {
-        source: () => '// Comment\nvar foo = 1;',
-      },
-      'test1.js': {
-        source: () => '/*! Legal Comment */\nvar foo = 1;',
-      },
-    };
-    compilation.warnings = [];
-    compilation.errors = [];
-
-    eventBinding.handler(compilation);
-    const [compilationEventBinding] = chunkPluginEnvironment.getEventBindings();
-
-    compilationEventBinding.handler([{
-      files: ['test.js', 'test1.js'],
-    }], () => {
-      for (const file in compilation.assets) {
-        if (Object.prototype.hasOwnProperty.call(compilation.assets, file)) {
-          expect(compilation.assets[file].source()).toMatchSnapshot(file);
+    return compile(compiler).then((stats) => {
+      const errors = stats.compilation.errors.map(cleanErrorStack);
+      const warnings = stats.compilation.warnings.map(cleanErrorStack);
+
+      expect(errors).toMatchSnapshot('errors');
+      expect(warnings).toMatchSnapshot('warnings');
+
+      for (const file in stats.compilation.assets) {
+        if (Object.prototype.hasOwnProperty.call(stats.compilation.assets, file)) {
+          expect(stats.compilation.assets[file].source()).toMatchSnapshot(file);
         }
       }
-      expect(compilation.errors).toMatchSnapshot('errors');
-      expect(compilation.warnings).toMatchSnapshot('warnings');
     });
   });
 
-  it('normalizes when options.extractComments is regex', () => {
-    const pluginEnvironment = new PluginEnvironment();
-    const compilerEnv = pluginEnvironment.getEnvironmentStub();
-    compilerEnv.context = '';
+  it('matches snapshot for a `/Foo/` value (regexp)', () => {
+    new UglifyJsPlugin({ extractComments: /Foo/ }).apply(compiler);
 
-    const plugin = new UglifyJsPlugin({
-      extractComments: /foo/,
-    });
-    plugin.apply(compilerEnv);
-    const [eventBinding] = pluginEnvironment.getEventBindings();
-    const chunkPluginEnvironment = new PluginEnvironment();
-    const compilation = chunkPluginEnvironment.getEnvironmentStub();
-    compilation.assets = {
-      'test.js': {
-        source: () => '// Comment\nvar foo = 1;',
-      },
-      'test1.js': {
-        source: () => '// foo\nvar foo = 1;',
-      },
-    };
-    compilation.warnings = [];
-    compilation.errors = [];
-
-    eventBinding.handler(compilation);
-    const [compilationEventBinding] = chunkPluginEnvironment.getEventBindings();
-
-    compilationEventBinding.handler([{
-      files: ['test.js', 'test1.js'],
-    }], () => {
-      for (const file in compilation.assets) {
-        if (Object.prototype.hasOwnProperty.call(compilation.assets, file)) {
-          expect(compilation.assets[file].source()).toMatchSnapshot(file);
+    return compile(compiler).then((stats) => {
+      const errors = stats.compilation.errors.map(cleanErrorStack);
+      const warnings = stats.compilation.warnings.map(cleanErrorStack);
+
+      expect(errors).toMatchSnapshot('errors');
+      expect(warnings).toMatchSnapshot('warnings');
+
+      for (const file in stats.compilation.assets) {
+        if (Object.prototype.hasOwnProperty.call(stats.compilation.assets, file)) {
+          expect(stats.compilation.assets[file].source()).toMatchSnapshot(file);
         }
       }
-      expect(compilation.errors).toMatchSnapshot('errors');
-      expect(compilation.warnings).toMatchSnapshot('warnings');
     });
   });
 
-  it('normalizes when options.extractComments is string', () => {
-    const pluginEnvironment = new PluginEnvironment();
-    const compilerEnv = pluginEnvironment.getEnvironmentStub();
-    compilerEnv.context = '';
+  it('matches snapshot for a `all` value (string)', () => {
+    new UglifyJsPlugin({ extractComments: 'all' }).apply(compiler);
 
-    const plugin = new UglifyJsPlugin({
-      extractComments: 'all',
-    });
-    plugin.apply(compilerEnv);
-    const [eventBinding] = pluginEnvironment.getEventBindings();
-    const chunkPluginEnvironment = new PluginEnvironment();
-    const compilation = chunkPluginEnvironment.getEnvironmentStub();
-    compilation.assets = {
-      'test.js': {
-        source: () => '// Comment\nvar foo = 1;',
-      },
-      'test1.js': {
-        source: () => '/* Comment */\nvar foo = 1;',
-      },
-    };
-    compilation.warnings = [];
-    compilation.errors = [];
-
-    eventBinding.handler(compilation);
-    const [compilationEventBinding] = chunkPluginEnvironment.getEventBindings();
-
-    compilationEventBinding.handler([{
-      files: ['test.js', 'test1.js'],
-    }], () => {
-      for (const file in compilation.assets) {
-        if (Object.prototype.hasOwnProperty.call(compilation.assets, file)) {
-          expect(compilation.assets[file].source()).toMatchSnapshot(file);
+    return compile(compiler).then((stats) => {
+      const errors = stats.compilation.errors.map(cleanErrorStack);
+      const warnings = stats.compilation.warnings.map(cleanErrorStack);
+
+      expect(errors).toMatchSnapshot('errors');
+      expect(warnings).toMatchSnapshot('warnings');
+
+      for (const file in stats.compilation.assets) {
+        if (Object.prototype.hasOwnProperty.call(stats.compilation.assets, file)) {
+          expect(stats.compilation.assets[file].source()).toMatchSnapshot(file);
         }
       }
-      expect(compilation.errors).toMatchSnapshot('errors');
-      expect(compilation.warnings).toMatchSnapshot('warnings');
     });
   });
 
-  it('normalizes when options.extractComments is function', () => {
-    const pluginEnvironment = new PluginEnvironment();
-    const compilerEnv = pluginEnvironment.getEnvironmentStub();
-    compilerEnv.context = '';
+  it('matches snapshot for a `some` value (string)', () => {
+    new UglifyJsPlugin({ extractComments: 'some' }).apply(compiler);
+
+    return compile(compiler).then((stats) => {
+      const errors = stats.compilation.errors.map(cleanErrorStack);
+      const warnings = stats.compilation.warnings.map(cleanErrorStack);
+
+      expect(errors).toMatchSnapshot('errors');
+      expect(warnings).toMatchSnapshot('warnings');
 
-    const plugin = new UglifyJsPlugin({
-      extractComments: () => true,
+      for (const file in stats.compilation.assets) {
+        if (Object.prototype.hasOwnProperty.call(stats.compilation.assets, file)) {
+          expect(stats.compilation.assets[file].source()).toMatchSnapshot(file);
+        }
+      }
     });
-    plugin.apply(compilerEnv);
-    const [eventBinding] = pluginEnvironment.getEventBindings();
-    const chunkPluginEnvironment = new PluginEnvironment();
-    const compilation = chunkPluginEnvironment.getEnvironmentStub();
-    compilation.assets = {
-      'test.js': {
-        source: () => '// Comment\nvar foo = 1;',
-      },
-      'test1.js': {
-        source: () => '/* Comment */\nvar foo = 1;',
-      },
-    };
-    compilation.warnings = [];
-    compilation.errors = [];
-
-    eventBinding.handler(compilation);
-    const [compilationEventBinding] = chunkPluginEnvironment.getEventBindings();
-
-    compilationEventBinding.handler([{
-      files: ['test.js', 'test1.js'],
-    }], () => {
-      for (const file in compilation.assets) {
-        if (Object.prototype.hasOwnProperty.call(compilation.assets, file)) {
-          expect(compilation.assets[file].source()).toMatchSnapshot(file);
+  });
+
+  it('matches snapshot for a `Foo` value (string)', () => {
+    new UglifyJsPlugin({ extractComments: 'Foo' }).apply(compiler);
+
+    return compile(compiler).then((stats) => {
+      const errors = stats.compilation.errors.map(cleanErrorStack);
+      const warnings = stats.compilation.warnings.map(cleanErrorStack);
+
+      expect(errors).toMatchSnapshot('errors');
+      expect(warnings).toMatchSnapshot('warnings');
+
+      for (const file in stats.compilation.assets) {
+        if (Object.prototype.hasOwnProperty.call(stats.compilation.assets, file)) {
+          expect(stats.compilation.assets[file].source()).toMatchSnapshot(file);
         }
       }
-      expect(compilation.errors).toMatchSnapshot('errors');
-      expect(compilation.warnings).toMatchSnapshot('warnings');
     });
   });
 
-  it('normalizes when options.extractComments is object', () => {
-    const pluginEnvironment = new PluginEnvironment();
-    const compilerEnv = pluginEnvironment.getEnvironmentStub();
-    compilerEnv.context = '';
+  it('matches snapshot for a `function value', () => {
+    new UglifyJsPlugin({ extractComments: () => true }).apply(compiler);
+
+    return compile(compiler).then((stats) => {
+      const errors = stats.compilation.errors.map(cleanErrorStack);
+      const warnings = stats.compilation.warnings.map(cleanErrorStack);
+
+      expect(errors).toMatchSnapshot('errors');
+      expect(warnings).toMatchSnapshot('warnings');
+
+      for (const file in stats.compilation.assets) {
+        if (Object.prototype.hasOwnProperty.call(stats.compilation.assets, file)) {
+          expect(stats.compilation.assets[file].source()).toMatchSnapshot(file);
+        }
+      }
+    });
+  });
 
-    const plugin = new UglifyJsPlugin({
+  it('matches snapshot for a object value (extracts comments to multiple files)', () => {
+    new UglifyJsPlugin({
       extractComments: {
         condition: true,
         filename(file) {
@@ -261,176 +171,46 @@ describe('when options.extractComments', () => {
           return `License information can be found in ${licenseFile}`;
         },
       },
-    });
-    plugin.apply(compilerEnv);
-    const [eventBinding] = pluginEnvironment.getEventBindings();
-    const chunkPluginEnvironment = new PluginEnvironment();
-    const compilation = chunkPluginEnvironment.getEnvironmentStub();
-    compilation.assets = {
-      'test.js': {
-        source: () => '// Comment\nvar foo = 1;',
-      },
-    };
-    compilation.warnings = [];
-    compilation.errors = [];
-
-    eventBinding.handler(compilation);
-    const [compilationEventBinding] = chunkPluginEnvironment.getEventBindings();
-
-    compilationEventBinding.handler([{
-      files: ['test.js'],
-    }], () => {
-      for (const file in compilation.assets) {
-        if (Object.prototype.hasOwnProperty.call(compilation.assets, file)) {
-          expect(compilation.assets[file].source()).toMatchSnapshot(file);
-        }
-      }
-      expect(compilation.errors).toMatchSnapshot('errors');
-      expect(compilation.warnings).toMatchSnapshot('warnings');
-    });
-  });
+    }).apply(compiler);
 
-  it('normalizes when options.extractComments is string - "all" && license file should be relative source file', () => {
-    const pluginEnvironment = new PluginEnvironment();
-    const compilerEnv = pluginEnvironment.getEnvironmentStub();
-    compilerEnv.context = '';
+    return compile(compiler).then((stats) => {
+      const errors = stats.compilation.errors.map(cleanErrorStack);
+      const warnings = stats.compilation.warnings.map(cleanErrorStack);
 
-    const plugin = new UglifyJsPlugin({
-      extractComments: 'all',
-    });
-    plugin.apply(compilerEnv);
-    const [eventBinding] = pluginEnvironment.getEventBindings();
-    const chunkPluginEnvironment = new PluginEnvironment();
-    const compilation = chunkPluginEnvironment.getEnvironmentStub();
-    compilation.assets = {
-      'nested/test.js': {
-        source: () => '// Comment\nvar foo = 1;',
-      },
-      'nested/nested/test1.js': {
-        source: () => '/* Comment */\nvar foo = 1;',
-      },
-    };
-    compilation.warnings = [];
-    compilation.errors = [];
-
-    eventBinding.handler(compilation);
-    const [compilationEventBinding] = chunkPluginEnvironment.getEventBindings();
-
-    compilationEventBinding.handler([{
-      files: ['nested/test.js', 'nested/nested/test1.js'],
-    }], () => {
-      for (const file in compilation.assets) {
-        if (Object.prototype.hasOwnProperty.call(compilation.assets, file)) {
-          expect(compilation.assets[file].source()).toMatchSnapshot(file);
+      expect(errors).toMatchSnapshot('errors');
+      expect(warnings).toMatchSnapshot('warnings');
+
+      for (const file in stats.compilation.assets) {
+        if (Object.prototype.hasOwnProperty.call(stats.compilation.assets, file)) {
+          expect(stats.compilation.assets[file].source()).toMatchSnapshot(file);
         }
       }
-      expect(compilation.errors).toMatchSnapshot('errors');
-      expect(compilation.warnings).toMatchSnapshot('warnings');
     });
   });
 
-  describe('when applied with extract option set to a single file', () => {
-    let eventBindings;
-    let eventBinding;
-
-    beforeEach(() => {
-      const pluginEnvironment = new PluginEnvironment();
-      const compilerEnv = pluginEnvironment.getEnvironmentStub();
-      compilerEnv.context = '';
-
-      const plugin = new UglifyJsPlugin({
-        uglifyOptions: {
-          output: {
-            comments: 'all',
-          },
-        },
-        extractComments: {
-          condition: /.*/,
-          filename: 'extracted-comments.js',
+  it('matches snapshot for a object value (extracts comments to a single file)', () => {
+    new UglifyJsPlugin({
+      extractComments: {
+        condition: true,
+        filename: 'extracted-comments.js',
+        banner(licenseFile) {
+          return `License information can be found in ${licenseFile}`;
         },
-      });
-      plugin.apply(compilerEnv);
-      eventBindings = pluginEnvironment.getEventBindings();
-    });
+      },
+    }).apply(compiler);
 
-    it('binds one event handler', () => {
-      expect(eventBindings.length).toBe(1);
-    });
+    return compile(compiler).then((stats) => {
+      const errors = stats.compilation.errors.map(cleanErrorStack);
+      const warnings = stats.compilation.warnings.map(cleanErrorStack);
+
+      expect(errors).toMatchSnapshot('errors');
+      expect(warnings).toMatchSnapshot('warnings');
 
-    describe('compilation handler', () => {
-      beforeEach(() => {
-        [eventBinding] = eventBindings;
-      });
-
-      it('binds to compilation event', () => {
-        expect(eventBinding.name).toBe('compilation');
-      });
-
-      describe('when called', () => {
-        let chunkPluginEnvironment;
-        let compilationEventBindings;
-        let compilationEventBinding;
-        let compilation;
-
-        beforeEach(() => {
-          chunkPluginEnvironment = new PluginEnvironment();
-          compilation = chunkPluginEnvironment.getEnvironmentStub();
-          compilation.assets = {
-            'test.js': {
-              source: () => '/* This is a comment from test.js */ function foo(bar) { return bar; }',
-            },
-            'test2.js': {
-              source: () => '// This is a comment from test2.js\nfunction foo2(bar) { return bar; }',
-            },
-            'test3.js': {
-              source: () => '/* This is a comment from test3.js */ function foo3(bar) { return bar; }\n// This is another comment from test3.js\nfunction foobar3(baz) { return baz; }',
-            },
-          };
-          compilation.errors = [];
-          compilation.warnings = [];
-
-          eventBinding.handler(compilation);
-          compilationEventBindings = chunkPluginEnvironment.getEventBindings();
-        });
-
-        it('binds one event handler', () => {
-          expect(compilationEventBindings.length).toBe(1);
-        });
-
-        describe('optimize-chunk-assets handler', () => {
-          beforeEach(() => {
-            [compilationEventBinding] = compilationEventBindings;
-          });
-
-          it('binds to optimize-chunk-assets event', () => {
-            expect(compilationEventBinding.name).toEqual('optimize-chunk-assets');
-          });
-
-          it('preserves comments', () => {
-            compilationEventBinding.handler([{
-              files: ['test.js', 'test2.js', 'test3.js'],
-            }], () => {
-              expect(compilation.assets['test.js'].source()).toEqual(expect.stringContaining('/*'));
-              expect(compilation.assets['test2.js'].source()).toEqual(expect.stringContaining('//'));
-              expect(compilation.assets['test3.js'].source()).toEqual(expect.stringContaining('/*'));
-              expect(compilation.assets['test3.js'].source()).toEqual(expect.stringContaining('//'));
-            });
-          });
-
-          it('extracts comments to specified file', () => {
-            compilationEventBinding.handler([{
-              files: ['test.js', 'test2.js', 'test3.js'],
-            }], () => {
-              expect(compilation.errors.length).toBe(0);
-              expect(compilation.assets['extracted-comments.js'].source()).toEqual(expect.stringContaining('/* This is a comment from test.js */'));
-              expect(compilation.assets['extracted-comments.js'].source()).toEqual(expect.stringContaining('// This is a comment from test2.js'));
-              expect(compilation.assets['extracted-comments.js'].source()).toEqual(expect.stringContaining('/* This is a comment from test3.js */'));
-              expect(compilation.assets['extracted-comments.js'].source()).toEqual(expect.stringContaining('// This is another comment from test3.js'));
-              expect(compilation.assets['extracted-comments.js'].source()).not.toEqual(expect.stringContaining('function'));
-            });
-          });
-        });
-      });
+      for (const file in stats.compilation.assets) {
+        if (Object.prototype.hasOwnProperty.call(stats.compilation.assets, file)) {
+          expect(stats.compilation.assets[file].source()).toMatchSnapshot(file);
+        }
+      }
     });
   });
 });
diff --git a/test/fixtures/comments.js b/test/fixtures/comments.js
new file mode 100644
index 0000000..3998a18
--- /dev/null
+++ b/test/fixtures/comments.js
@@ -0,0 +1,29 @@
+import('./nested/comments.js');
+
+/*! Legal Comment */
+
+/**
+ * @preserve Copyright 2009 SomeThirdParty.
+ * Here is the full license text and copyright
+ * notice for this file. Note that the notice can span several
+ * lines and is only terminated by the closing star and slash:
+ */
+
+/**
+ * Utility functions for the foo package.
+ * @license Apache-2.0
+ */
+
+/*! Legal Foo */
+
+// Foo
+
+/*
+ Foo Bar
+ */
+
+/*
+* Foo
+*/
+
+module.exports = Math.random();
diff --git a/test/fixtures/nested/comments.js b/test/fixtures/nested/comments.js
new file mode 100644
index 0000000..daf0271
--- /dev/null
+++ b/test/fixtures/nested/comments.js
@@ -0,0 +1,27 @@
+/*! Legal Comment */
+
+/**
+ * @preserve Copyright 2009 SomeThirdParty.
+ * Here is the full license text and copyright
+ * notice for this file. Note that the notice can span several
+ * lines and is only terminated by the closing star and slash:
+ */
+
+/**
+ * Utility functions for the foo package.
+ * @license Apache-2.0
+ */
+
+/*! Legal Foo */
+
+// Foo
+
+/*
+ Foo Bar
+ */
+
+/*
+* Foo
+*/
+
+module.exports = Math.random();
diff --git a/test/minify-option.test.js b/test/minify-option.test.js
index 21444ea..951e608 100644
--- a/test/minify-option.test.js
+++ b/test/minify-option.test.js
@@ -206,4 +206,69 @@ describe('when applied with `minify` option', () => {
         }
       });
   });
+
+  it('matches snapshot for errors into `minify` option', () => {
+    const compiler = createCompiler({
+      entry: `${__dirname}/fixtures/minify/es6.js`,
+      output: {
+        path: `${__dirname}/dist-terser`,
+        filename: '[name].js',
+        chunkFilename: '[id].[name].js',
+      },
+    });
+
+    new UglifyJsPlugin({
+      minify() {
+        throw Error('Error');
+      },
+    }).apply(compiler);
+
+    return compile(compiler)
+      .then((stats) => {
+        const errors = stats.compilation.errors.map(cleanErrorStack);
+        const warnings = stats.compilation.warnings.map(cleanErrorStack);
+
+        expect(errors).toMatchSnapshot('errors');
+        expect(warnings).toMatchSnapshot('warnings');
+
+        for (const file in stats.compilation.assets) {
+          if (Object.prototype.hasOwnProperty.call(stats.compilation.assets, file)) {
+            expect(stats.compilation.assets[file].source()).toMatchSnapshot(file);
+          }
+        }
+      });
+  });
+
+  it('matches snapshot for errors into `minify` option and `parallel` is `true`', () => {
+    const compiler = createCompiler({
+      entry: `${__dirname}/fixtures/minify/es6.js`,
+      output: {
+        path: `${__dirname}/dist-terser`,
+        filename: '[name].js',
+        chunkFilename: '[id].[name].js',
+      },
+    });
+
+    new UglifyJsPlugin({
+      parallel: true,
+      minify() {
+        throw Error('Error');
+      },
+    }).apply(compiler);
+
+    return compile(compiler)
+      .then((stats) => {
+        const errors = stats.compilation.errors.map(cleanErrorStack);
+        const warnings = stats.compilation.warnings.map(cleanErrorStack);
+
+        expect(errors).toMatchSnapshot('errors');
+        expect(warnings).toMatchSnapshot('warnings');
+
+        for (const file in stats.compilation.assets) {
+          if (Object.prototype.hasOwnProperty.call(stats.compilation.assets, file)) {
+            expect(stats.compilation.assets[file].source()).toMatchSnapshot(file);
+          }
+        }
+      });
+  });
 });
diff --git a/test/sourceMap-option.test.js b/test/sourceMap-option.test.js
index 1c220f0..16dedb6 100644
--- a/test/sourceMap-option.test.js
+++ b/test/sourceMap-option.test.js
@@ -1,280 +1,148 @@
 import UglifyJsPlugin from '../src/index';
-import {
-  PluginEnvironment,
-  createCompiler,
-  compile,
-  cleanErrorStack,
-} from './helpers';
+import { createCompiler, compile, cleanErrorStack } from './helpers';
 
 describe('when options.sourceMap', () => {
-  const assets = {
-    'test.js': {
-      source: () => 'function test(foo) { foo = 1; }',
-    },
-    'test1.js': {
-      source: () => 'function test1(foo) { foo = 1; }',
-    },
-    'test2.js': {
-      source: () => 'function test2(foo) { foo = 1; }',
-    },
-    'test3.js': {
-      source: () => 'function test3(foo) { foo = 1; }',
-    },
-    'test4.js': {
-      sourceAndMap: () => {
-        return {
-          source: 'function foo(x) { if (x) { return bar(); not_called1(); } }',
-          map: null,
-        };
-      },
-    },
-  };
-
-  describe('true', () => {
-    let eventBindings;
-    let eventBinding;
-
-    beforeEach(() => {
-      const pluginEnvironment = new PluginEnvironment();
-      const compilerEnv = pluginEnvironment.getEnvironmentStub();
-      compilerEnv.context = '';
-      compilerEnv.devtool = 'source-map';
-
-      const plugin = new UglifyJsPlugin({
-        sourceMap: true,
-      });
-      plugin.apply(compilerEnv);
-      eventBindings = pluginEnvironment.getEventBindings();
-    });
-
-    it('binds one event handler', () => {
-      expect(eventBindings.length).toBe(1);
+  it('matches snapshot for a single `false` value (`devtool` is `source-map`)', () => {
+    const compiler = createCompiler({
+      entry: `${__dirname}/fixtures/entry.js`,
+      devtool: 'source-map',
     });
 
-    describe('compilation handler', () => {
-      beforeEach(() => {
-        [eventBinding] = eventBindings;
-      });
-
-      it('binds to compilation event', () => {
-        expect(eventBinding.name).toBe('compilation');
-      });
-
-      describe('when called', () => {
-        let chunkPluginEnvironment;
-        let compilationEventBindings;
-        let compilationEventBinding;
-        let compilation;
-        let callback;
-
-        beforeEach(() => {
-          chunkPluginEnvironment = new PluginEnvironment();
-          compilation = chunkPluginEnvironment.getEnvironmentStub();
-          compilation.assets = Object.assign({}, assets);
-          compilation.warnings = [];
-          compilation.errors = [];
-
-          eventBinding.handler(compilation);
-          compilationEventBindings = chunkPluginEnvironment.getEventBindings();
-        });
-
-        it('binds two event handler', () => {
-          expect(compilationEventBindings[0].name).toBe('build-module');
-          expect(compilationEventBindings[1].name).toBe('optimize-chunk-assets');
-        });
+    new UglifyJsPlugin({ sourceMap: false }).apply(compiler);
 
-        describe('build-module handler', () => {
-          beforeEach(() => {
-            [compilationEventBinding] = compilationEventBindings;
-          });
+    return compile(compiler).then((stats) => {
+      const errors = stats.compilation.errors.map(cleanErrorStack);
+      const warnings = stats.compilation.warnings.map(cleanErrorStack);
 
-          it('binds to build-module event', () => {
-            expect(compilationEventBinding.name).toEqual('build-module');
-          });
+      expect(errors).toMatchSnapshot('errors');
+      expect(warnings).toMatchSnapshot('warnings');
 
-          it('build-module handler', (done) => {
-            const moduleArgs = { useSourceMap: false };
-            const mockBuildModuleEvent = jest.fn(() => compilationEventBinding.handler(moduleArgs));
-
-            mockBuildModuleEvent();
-
-            expect(mockBuildModuleEvent.mock.calls.length).toBe(1);
-            expect(moduleArgs.useSourceMap).toBe(true);
-            done();
-          });
-        });
-
-        describe('optimize-chunk-assets handler', () => {
-          beforeEach(() => {
-            [, compilationEventBinding] = compilationEventBindings;
-          });
-
-          it('binds to optimize-chunk-assets event', () => {
-            expect(compilationEventBinding.name).toEqual('optimize-chunk-assets');
-          });
-
-          it('only calls callback once', (done) => {
-            callback = jest.fn();
-            compilationEventBinding.handler([{
-              files: ['test.js', 'test1.js', 'test2.js', 'test3.js', 'test4.js'],
-            }], () => {
-              expect(compilation.warnings).toMatchSnapshot('warnings');
-              expect(compilation.errors).toMatchSnapshot('errors');
-              callback();
-              expect(callback.mock.calls.length).toBe(1);
-              done();
-            });
-          });
-        });
-      });
+      for (const file in stats.compilation.assets) {
+        if (Object.prototype.hasOwnProperty.call(stats.compilation.assets, file)) {
+          expect(stats.compilation.assets[file].source()).toMatchSnapshot(file);
+        }
+      }
     });
+  });
 
-    it('matches snapshot', () => {
-      const compiler = createCompiler();
-      new UglifyJsPlugin({ sourceMap: true }).apply(compiler);
-
-      return compile(compiler).then((stats) => {
-        const errors = stats.compilation.errors.map(cleanErrorStack);
-        const warnings = stats.compilation.warnings.map(cleanErrorStack);
+  it('matches snapshot for a single `false` value (`devtool` is `false`)', () => {
+    const compiler = createCompiler({
+      entry: `${__dirname}/fixtures/entry.js`,
+      devtool: false,
+    });
 
-        expect(errors).toMatchSnapshot('errors');
-        expect(warnings).toMatchSnapshot('warnings');
+    new UglifyJsPlugin({ sourceMap: false }).apply(compiler);
 
-        for (const file in stats.compilation.assets) {
-          if (Object.prototype.hasOwnProperty.call(stats.compilation.assets, file)) {
-            const asset = stats.compilation.assets[file].sourceAndMap();
+    return compile(compiler).then((stats) => {
+      const errors = stats.compilation.errors.map(cleanErrorStack);
+      const warnings = stats.compilation.warnings.map(cleanErrorStack);
 
-            asset.map.sources = [];
+      expect(errors).toMatchSnapshot('errors');
+      expect(warnings).toMatchSnapshot('warnings');
 
-            expect(asset.source).toMatchSnapshot(`asset ${file}`);
-            expect(asset.map).toMatchSnapshot(`source map ${file}`);
-          }
+      for (const file in stats.compilation.assets) {
+        if (Object.prototype.hasOwnProperty.call(stats.compilation.assets, file)) {
+          expect(stats.compilation.assets[file].source()).toMatchSnapshot(file);
         }
-      });
+      }
     });
   });
 
-  describe('true and options.parallel true', () => {
-    let eventBindings;
-    let eventBinding;
-
-    beforeEach(() => {
-      const pluginEnvironment = new PluginEnvironment();
-      const compilerEnv = pluginEnvironment.getEnvironmentStub();
-      compilerEnv.context = '';
-
-      const plugin = new UglifyJsPlugin({
-        parallel: true,
-        sourceMap: true,
-      });
-      plugin.apply(compilerEnv);
-      eventBindings = pluginEnvironment.getEventBindings();
-    });
-
-    it('binds one event handler', () => {
-      expect(eventBindings.length).toBe(1);
+  it('matches snapshot for a single `true` value (`devtool` is `source-map`)', () => {
+    const compiler = createCompiler({
+      entry: `${__dirname}/fixtures/entry.js`,
+      devtool: 'source-map',
     });
 
-    describe('compilation handler', () => {
-      beforeEach(() => {
-        [eventBinding] = eventBindings;
-      });
-
-      it('binds to compilation event', () => {
-        expect(eventBinding.name).toBe('compilation');
-      });
-
-      describe('when called', () => {
-        let chunkPluginEnvironment;
-        let compilationEventBindings;
-        let compilationEventBinding;
-        let compilation;
-        let callback;
-
-        beforeEach(() => {
-          chunkPluginEnvironment = new PluginEnvironment();
-          compilation = chunkPluginEnvironment.getEnvironmentStub();
-          compilation.assets = Object.assign({}, assets);
-          compilation.warnings = [];
-          compilation.errors = [];
-
-          eventBinding.handler(compilation);
-          compilationEventBindings = chunkPluginEnvironment.getEventBindings();
-        });
+    new UglifyJsPlugin({ sourceMap: true }).apply(compiler);
 
-        it('binds two event handler', () => {
-          expect(compilationEventBindings[0].name).toBe('build-module');
-          expect(compilationEventBindings[1].name).toBe('optimize-chunk-assets');
-        });
+    return compile(compiler).then((stats) => {
+      const errors = stats.compilation.errors.map(cleanErrorStack);
+      const warnings = stats.compilation.warnings.map(cleanErrorStack);
 
-        describe('build-module handler', () => {
-          beforeEach(() => {
-            [compilationEventBinding] = compilationEventBindings;
-          });
+      expect(errors).toMatchSnapshot('errors');
+      expect(warnings).toMatchSnapshot('warnings');
 
-          it('binds to build-module event', () => {
-            expect(compilationEventBinding.name).toEqual('build-module');
-          });
+      for (const file in stats.compilation.assets) {
+        if (Object.prototype.hasOwnProperty.call(stats.compilation.assets, file)) {
+          expect(stats.compilation.assets[file].source()).toMatchSnapshot(file);
+        }
+      }
+    });
+  });
 
-          it('build-module handler', (done) => {
-            const moduleArgs = { useSourceMap: false };
-            const mockBuildModuleEvent = jest.fn(() => compilationEventBinding.handler(moduleArgs));
+  it('matches snapshot for a single `true` value (`devtool` is `false`)', () => {
+    const compiler = createCompiler({
+      entry: `${__dirname}/fixtures/entry.js`,
+      devtool: false,
+    });
 
-            mockBuildModuleEvent();
+    new UglifyJsPlugin({ sourceMap: true }).apply(compiler);
 
-            expect(mockBuildModuleEvent.mock.calls.length).toBe(1);
-            expect(moduleArgs.useSourceMap).toBe(true);
-            done();
-          });
-        });
+    return compile(compiler).then((stats) => {
+      const errors = stats.compilation.errors.map(cleanErrorStack);
+      const warnings = stats.compilation.warnings.map(cleanErrorStack);
 
-        describe('optimize-chunk-assets handler', () => {
-          beforeEach(() => {
-            [, compilationEventBinding] = compilationEventBindings;
-          });
+      expect(errors).toMatchSnapshot('errors');
+      expect(warnings).toMatchSnapshot('warnings');
 
-          it('binds to optimize-chunk-assets event', () => {
-            expect(compilationEventBinding.name).toEqual('optimize-chunk-assets');
-          });
+      for (const file in stats.compilation.assets) {
+        if (Object.prototype.hasOwnProperty.call(stats.compilation.assets, file)) {
+          expect(stats.compilation.assets[file].source()).toMatchSnapshot(file);
+        }
+      }
+    });
+  });
 
-          it('only calls callback once', (done) => {
-            callback = jest.fn();
-            compilationEventBinding.handler([{
-              files: ['test.js', 'test1.js', 'test2.js', 'test3.js', 'test4.js'],
-            }], () => {
-              expect(compilation.warnings).toMatchSnapshot('warnings');
-              expect(compilation.errors).toMatchSnapshot('errors');
-              callback();
-              expect(callback.mock.calls.length).toBe(1);
-              done();
+  it('matches snapshot for a single `true` value (`devtool` is `source-map`) and source map invalid', () => {
+    const compiler = createCompiler({
+      entry: `${__dirname}/fixtures/entry.js`,
+      devtool: 'source-map',
+      plugins: [
+        {
+          apply(pluginCompiler) {
+            pluginCompiler.plugin('compilation', (compilation) => {
+              compilation.plugin('additional-chunk-assets', () => {
+                compilation.additionalChunkAssets.push('broken-source-map.js');
+
+                const assetContent = 'var test = 1;';
+
+                // eslint-disable-next-line no-param-reassign
+                compilation.assets['broken-source-map.js'] = {
+                  size() {
+                    return assetContent.length;
+                  },
+                  source() {
+                    return assetContent;
+                  },
+                  sourceAndMap() {
+                    return {
+                      source: this.source(),
+                      map: {},
+                    };
+                  },
+                };
+              });
             });
-          });
-        });
-      });
+          },
+        },
+      ],
     });
 
-    it('matches snapshot', () => {
-      const compiler = createCompiler();
-      new UglifyJsPlugin({ parallel: true, sourceMap: true }).apply(compiler);
-
-      return compile(compiler).then((stats) => {
-        const errors = stats.compilation.errors.map(cleanErrorStack);
-        const warnings = stats.compilation.warnings.map(cleanErrorStack);
-
-        expect(errors).toMatchSnapshot('errors');
-        expect(warnings).toMatchSnapshot('warnings');
+    new UglifyJsPlugin({ sourceMap: true }).apply(compiler);
 
-        for (const file in stats.compilation.assets) {
-          if (Object.prototype.hasOwnProperty.call(stats.compilation.assets, file)) {
-            const asset = stats.compilation.assets[file].sourceAndMap();
+    return compile(compiler).then((stats) => {
+      const errors = stats.compilation.errors.map(cleanErrorStack);
+      const warnings = stats.compilation.warnings.map(cleanErrorStack);
 
-            asset.map.sources = [];
+      expect(errors).toMatchSnapshot('errors');
+      expect(warnings).toMatchSnapshot('warnings');
 
-            expect(asset.source).toMatchSnapshot(`asset ${file}`);
-            expect(asset.map).toMatchSnapshot(`source map ${file}`);
-          }
+      for (const file in stats.compilation.assets) {
+        if (Object.prototype.hasOwnProperty.call(stats.compilation.assets, file)) {
+          expect(stats.compilation.assets[file].source()).toMatchSnapshot(file);
         }
-      });
+      }
     });
   });
 });
diff --git a/test/uglifyOptions-option.test.js b/test/uglifyOptions-option.test.js
index 1532082..71f5480 100644
--- a/test/uglifyOptions-option.test.js
+++ b/test/uglifyOptions-option.test.js
@@ -129,14 +129,14 @@ describe('when applied with uglifyOptions options', () => {
     });
   });
 
-  it('matches snapshot for `warnings` option (boolean `true` value)', () => {
+  it('matches snapshot for `warnings` option (boolean `false` value)', () => {
     const compiler = createCompiler({
       entry: `${__dirname}/fixtures/unreachable-code.js`,
     });
 
     new UglifyJsPlugin({
       uglifyOptions: {
-        warnings: true,
+        warnings: false,
       },
     }).apply(compiler);
 
@@ -155,14 +155,14 @@ describe('when applied with uglifyOptions options', () => {
     });
   });
 
-  it('matches snapshot for `warnings` option (boolean `false` value)', () => {
+  it('matches snapshot for `warnings` option (boolean `true` value)', () => {
     const compiler = createCompiler({
       entry: `${__dirname}/fixtures/unreachable-code.js`,
     });
 
     new UglifyJsPlugin({
       uglifyOptions: {
-        warnings: false,
+        warnings: true,
       },
     }).apply(compiler);
 
@@ -207,12 +207,12 @@ describe('when applied with uglifyOptions options', () => {
     });
   });
 
-  it('matches snapshot for `compress` option (boolean `true` value)', () => {
+  it('matches snapshot for `compress` option (boolean `false` value)', () => {
     const compiler = createCompiler();
 
     new UglifyJsPlugin({
       uglifyOptions: {
-        compress: true,
+        compress: false,
       },
     }).apply(compiler);
 
@@ -231,12 +231,12 @@ describe('when applied with uglifyOptions options', () => {
     });
   });
 
-  it('matches snapshot for `compress` option (boolean `false` value)', () => {
+  it('matches snapshot for `compress` option (boolean `true` value)', () => {
     const compiler = createCompiler();
 
     new UglifyJsPlugin({
       uglifyOptions: {
-        compress: false,
+        compress: true,
       },
     }).apply(compiler);
 
@@ -281,12 +281,12 @@ describe('when applied with uglifyOptions options', () => {
     });
   });
 
-  it('matches snapshot for `mangle` option (boolean `true` value)', () => {
+  it('matches snapshot for `mangle` option (boolean `false` value)', () => {
     const compiler = createCompiler();
 
     new UglifyJsPlugin({
       uglifyOptions: {
-        mangle: true,
+        mangle: false,
       },
     }).apply(compiler);
 
@@ -305,12 +305,12 @@ describe('when applied with uglifyOptions options', () => {
     });
   });
 
-  it('matches snapshot for `mangle` option (boolean `false` value)', () => {
+  it('matches snapshot for `mangle` option (boolean `true` value)', () => {
     const compiler = createCompiler();
 
     new UglifyJsPlugin({
       uglifyOptions: {
-        mangle: false,
+        mangle: true,
       },
     }).apply(compiler);
 
@@ -407,12 +407,12 @@ describe('when applied with uglifyOptions options', () => {
     });
   });
 
-  it('matches snapshot for `toplevel` option (boolean `true` value)', () => {
+  it('matches snapshot for `toplevel` option (boolean `false` value)', () => {
     const compiler = createCompiler();
 
     new UglifyJsPlugin({
       uglifyOptions: {
-        toplevel: true,
+        toplevel: false,
       },
     }).apply(compiler);
 
@@ -431,12 +431,12 @@ describe('when applied with uglifyOptions options', () => {
     });
   });
 
-  it('matches snapshot for `toplevel` option (boolean `false` value)', () => {
+  it('matches snapshot for `toplevel` option (boolean `true` value)', () => {
     const compiler = createCompiler();
 
     new UglifyJsPlugin({
       uglifyOptions: {
-        toplevel: false,
+        toplevel: true,
       },
     }).apply(compiler);
 
@@ -479,6 +479,30 @@ describe('when applied with uglifyOptions options', () => {
     });
   });
 
+  it('matches snapshot for `ie8` option (boolean `false` value)', () => {
+    const compiler = createCompiler();
+
+    new UglifyJsPlugin({
+      uglifyOptions: {
+        ie8: false,
+      },
+    }).apply(compiler);
+
+    return compile(compiler).then((stats) => {
+      const errors = stats.compilation.errors.map(cleanErrorStack);
+      const warnings = stats.compilation.warnings.map(cleanErrorStack);
+
+      expect(errors).toMatchSnapshot('errors');
+      expect(warnings).toMatchSnapshot('warnings');
+
+      for (const file in stats.compilation.assets) {
+        if (Object.prototype.hasOwnProperty.call(stats.compilation.assets, file)) {
+          expect(stats.compilation.assets[file].source()).toMatchSnapshot(file);
+        }
+      }
+    });
+  });
+
   it('matches snapshot for `ie8` option (boolean `true` value)', () => {
     const compiler = createCompiler();
 
@@ -503,12 +527,12 @@ describe('when applied with uglifyOptions options', () => {
     });
   });
 
-  it('matches snapshot for `ie8` option (boolean `false` value)', () => {
+  it('matches snapshot for `keep_classnames` option (boolean `false` value)', () => {
     const compiler = createCompiler();
 
     new UglifyJsPlugin({
       uglifyOptions: {
-        ie8: false,
+        keep_classnames: false,
       },
     }).apply(compiler);
 
@@ -551,12 +575,12 @@ describe('when applied with uglifyOptions options', () => {
     });
   });
 
-  it('matches snapshot for `keep_classnames` option (boolean `false` value)', () => {
+  it('matches snapshot for `keep_fnames` option (boolean `false` value)', () => {
     const compiler = createCompiler();
 
     new UglifyJsPlugin({
       uglifyOptions: {
-        keep_classnames: false,
+        keep_fnames: false,
       },
     }).apply(compiler);
 
@@ -599,12 +623,12 @@ describe('when applied with uglifyOptions options', () => {
     });
   });
 
-  it('matches snapshot for `keep_fnames` option (boolean `false` value)', () => {
+  it('matches snapshot for `safari10` option (boolean `false` value)', () => {
     const compiler = createCompiler();
 
     new UglifyJsPlugin({
       uglifyOptions: {
-        keep_fnames: false,
+        safari10: false,
       },
     }).apply(compiler);
 
@@ -647,12 +671,13 @@ describe('when applied with uglifyOptions options', () => {
     });
   });
 
-  it('matches snapshot for `safari10` option (boolean `false` value)', () => {
+  it('matches snapshot for `unknown` option', () => {
     const compiler = createCompiler();
-
     new UglifyJsPlugin({
       uglifyOptions: {
-        safari10: false,
+        output: {
+          unknown: true,
+        },
       },
     }).apply(compiler);
 
diff --git a/test/validation.test.js b/test/validation.test.js
new file mode 100644
index 0000000..7d11830
--- /dev/null
+++ b/test/validation.test.js
@@ -0,0 +1,176 @@
+import UglifyJsPlugin from '../src';
+
+it('validation', () => {
+  /* eslint-disable no-new */
+  expect(() => {
+    new UglifyJsPlugin({ test: /foo/ });
+  }).not.toThrow('Validation Error');
+
+  expect(() => {
+    new UglifyJsPlugin({ test: [/foo/] });
+  }).not.toThrow('Validation Error');
+
+  expect(() => {
+    new UglifyJsPlugin({ include: /foo/ });
+  }).not.toThrow('Validation Error');
+
+  expect(() => {
+    new UglifyJsPlugin({ include: [/foo/] });
+  }).not.toThrow('Validation Error');
+
+  expect(() => {
+    new UglifyJsPlugin({ exclude: /foo/ });
+  }).not.toThrow('Validation Error');
+
+  expect(() => {
+    new UglifyJsPlugin({ exclude: [/foo/] });
+  }).not.toThrow('Validation Error');
+
+  expect(() => {
+    new UglifyJsPlugin({ doesntExist: true });
+  }).toThrowErrorMatchingSnapshot();
+
+  expect(() => {
+    new UglifyJsPlugin({ cache: true });
+  }).not.toThrow('Validation Error');
+
+  expect(() => {
+    new UglifyJsPlugin({ cache: false });
+  }).not.toThrow('Validation Error');
+
+  expect(() => {
+    new UglifyJsPlugin({ cache: 'path/to/cache/directory' });
+  }).not.toThrow('Validation Error');
+
+  expect(() => {
+    new UglifyJsPlugin({ cache: {} });
+  }).toThrowErrorMatchingSnapshot();
+
+  expect(() => {
+    new UglifyJsPlugin({ cacheKeys() {} });
+  }).not.toThrow('Validation Error');
+
+  expect(() => {
+    new UglifyJsPlugin({ parallel: true });
+  }).not.toThrow('Validation Error');
+
+  expect(() => {
+    new UglifyJsPlugin({ parallel: false });
+  }).not.toThrow('Validation Error');
+
+  expect(() => {
+    new UglifyJsPlugin({ parallel: 2 });
+  }).not.toThrow('Validation Error');
+
+  expect(() => {
+    new UglifyJsPlugin({ parallel: '2' });
+  }).toThrowErrorMatchingSnapshot();
+
+  expect(() => {
+    new UglifyJsPlugin({ parallel: {} });
+  }).toThrowErrorMatchingSnapshot();
+
+  expect(() => {
+    new UglifyJsPlugin({ sourceMap: true });
+  }).not.toThrow('Validation Error');
+
+  expect(() => {
+    new UglifyJsPlugin({ sourceMap: false });
+  }).not.toThrow('Validation Error');
+
+  expect(() => {
+    new UglifyJsPlugin({ sourceMap: 'true' });
+  }).toThrowErrorMatchingSnapshot();
+
+  expect(() => {
+    new UglifyJsPlugin({ minify() {} });
+  }).not.toThrow('Validation Error');
+
+  expect(() => {
+    new UglifyJsPlugin({ uglifyOptions: null });
+  }).toThrowErrorMatchingSnapshot();
+
+  expect(() => {
+    new UglifyJsPlugin({ uglifyOptions: {} });
+  }).not.toThrow('Validation Error');
+
+  expect(() => {
+    new UglifyJsPlugin({
+      uglifyOptions: {
+        ecma: 5,
+        warnings: false,
+        parse: {},
+        compress: true,
+        mangle: { inline: false },
+        output: { comments: /^\**!|@preserve|@license|@cc_on/ },
+        toplevel: false,
+        nameCache: {},
+        ie8: false,
+        keep_classnames: false,
+        keep_fnames: false,
+        safari10: false,
+      },
+    });
+  }).not.toThrow('Validation Error');
+
+  expect(() => {
+    new UglifyJsPlugin({ uglifyOptions: { ie8: false } });
+  }).not.toThrow('Validation Error');
+
+  expect(() => {
+    new UglifyJsPlugin({ uglifyOptions: { ie8: true } });
+  }).not.toThrow('Validation Error');
+
+  expect(() => {
+    new UglifyJsPlugin({ uglifyOptions: { ie8: 'false' } });
+  }).toThrowErrorMatchingSnapshot();
+
+  expect(() => {
+    new UglifyJsPlugin({ uglifyOptions: { emca: 5 } });
+  }).not.toThrow();
+
+  expect(() => {
+    new UglifyJsPlugin({ uglifyOptions: { emca: 8 } });
+  }).not.toThrow();
+
+  expect(() => {
+    new UglifyJsPlugin({ uglifyOptions: { ecma: 7.5 } });
+  }).toThrowErrorMatchingSnapshot();
+
+  expect(() => {
+    new UglifyJsPlugin({ uglifyOptions: { ecma: true } });
+  }).toThrowErrorMatchingSnapshot();
+
+  expect(() => {
+    new UglifyJsPlugin({ uglifyOptions: { ecma: '5' } });
+  }).toThrowErrorMatchingSnapshot();
+
+  expect(() => {
+    new UglifyJsPlugin({ uglifyOptions: { ecma: 3 } });
+  }).toThrowErrorMatchingSnapshot();
+
+  expect(() => {
+    new UglifyJsPlugin({ uglifyOptions: { ecma: 10 } });
+  }).toThrowErrorMatchingSnapshot();
+
+  expect(() => {
+    new UglifyJsPlugin({ extractComments: true });
+  }).not.toThrow('Validation Error');
+
+  expect(() => {
+    new UglifyJsPlugin({ extractComments: false });
+  }).not.toThrow('Validation Error');
+
+  expect(() => {
+    new UglifyJsPlugin({ extractComments: /comment/ });
+  }).not.toThrow('Validation Error');
+
+  expect(() => {
+    new UglifyJsPlugin({ extractComments() {} });
+  }).not.toThrow('Validation Error');
+
+  expect(() => {
+    new UglifyJsPlugin({ warningsFilter() {} });
+  }).not.toThrow('Validation Error');
+  /* eslint-enable no-new */
+});
diff --git a/test/warningsFilter-option.test.js b/test/warningsFilter-option.test.js
index 5514558..12b6c2b 100644
--- a/test/warningsFilter-option.test.js
+++ b/test/warningsFilter-option.test.js
@@ -17,7 +17,7 @@ describe('when applied with `warningsFilter` option', () => {
     });
   });
 
-  it('matches snapshot for a `function` value and `sourceMap` is `true`', () => {
+  it('matches snapshot for a `function` value and `sourceMap` is `false`', () => {
     new UglifyJsPlugin({
       warningsFilter(source) {
         if (/unreachable-code-2\.js/.test(source)) {
@@ -29,7 +29,7 @@ describe('when applied with `warningsFilter` option', () => {
       uglifyOptions: {
         warnings: true,
       },
-      sourceMap: true,
+      sourceMap: false,
     }).apply(compiler);
 
 
@@ -48,7 +48,7 @@ describe('when applied with `warningsFilter` option', () => {
     });
   });
 
-  it('matches snapshot for a `function` value and `sourceMap` is `false`', () => {
+  it('matches snapshot for a `function` value and `sourceMap` is `true`', () => {
     new UglifyJsPlugin({
       warningsFilter(source) {
         if (/unreachable-code-2\.js/.test(source)) {
@@ -60,7 +60,7 @@ describe('when applied with `warningsFilter` option', () => {
       uglifyOptions: {
         warnings: true,
       },
-      sourceMap: false,
+      sourceMap: true,
     }).apply(compiler);