webpack/test/Validation.test.js

478 lines
16 KiB
JavaScript
Raw Normal View History

2017-02-02 19:56:41 +08:00
/* globals describe, it */
"use strict";
2019-05-21 16:38:16 +08:00
const webpack = require("..");
2017-01-18 23:29:47 +08:00
describe("Validation", () => {
2019-05-21 16:38:16 +08:00
const createTestCase = (name, config, fn) => {
it("should fail validation for " + name, () => {
try {
webpack(config);
} catch (err) {
if (err.name !== "WebpackOptionsValidationError") throw err;
expect(err.message).toMatch(/^Invalid configuration object./);
fn(err.message);
return;
}
throw new Error("Validation didn't fail");
});
};
createTestCase("undefined configuration", undefined, msg =>
expect(msg).toMatchInlineSnapshot(`
"Invalid configuration object. Webpack has been initialised using a configuration object that does not match the API schema.
- configuration should be an object."
`)
);
createTestCase("null configuration", null, msg =>
expect(msg).toMatchInlineSnapshot(`
"Invalid configuration object. Webpack has been initialised using a configuration object that does not match the API schema.
- configuration should be an object."
`)
);
createTestCase(
"empty entry string",
2018-02-25 18:46:17 +08:00
{
2019-05-21 16:38:16 +08:00
entry: ""
},
2019-05-21 16:38:16 +08:00
msg =>
expect(msg).toMatchInlineSnapshot(`
"Invalid configuration object. Webpack has been initialised using a configuration object that does not match the API schema.
- configuration.entry should be one of these:
function | object { <key>: non-empty string | [non-empty string] } | non-empty string | [non-empty string]
-> The entry point(s) of the compilation.
Details:
* configuration.entry should be an instance of function
-> A Function returning an entry object, an entry string, an entry array or a promise to these things.
* configuration.entry should be an object.
-> Multiple entry bundles are created. The key is the chunk name. The value can be a string or an array.
* configuration.entry should not be empty.
-> An entry point without name. The string is resolved to a module which is loaded upon startup.
* configuration.entry should be an array:
[non-empty string]"
`)
);
createTestCase(
"empty entry bundle array",
2018-02-25 18:46:17 +08:00
{
2019-05-21 16:38:16 +08:00
entry: {
bundle: []
}
},
2019-05-21 16:38:16 +08:00
msg =>
expect(msg).toMatchInlineSnapshot(`
"Invalid configuration object. Webpack has been initialised using a configuration object that does not match the API schema.
- configuration.entry should be one of these:
function | object { <key>: non-empty string | [non-empty string] } | non-empty string | [non-empty string]
-> The entry point(s) of the compilation.
Details:
* configuration.entry should be an instance of function
-> A Function returning an entry object, an entry string, an entry array or a promise to these things.
* configuration.entry['bundle'] should be a string.
-> The string is resolved to a module which is loaded upon startup.
* configuration.entry['bundle'] should not be empty.
* configuration.entry should be a string.
-> An entry point without name. The string is resolved to a module which is loaded upon startup.
* configuration.entry should be an array:
[non-empty string]"
`)
);
createTestCase(
"invalid instanceof",
2018-02-25 18:46:17 +08:00
{
2019-05-21 16:38:16 +08:00
entry: "a",
module: {
wrappedContextRegExp: 1337
}
},
2019-05-21 16:38:16 +08:00
msg =>
expect(msg).toMatchInlineSnapshot(`
"Invalid configuration object. Webpack has been initialised using a configuration object that does not match the API schema.
- configuration.module.wrappedContextRegExp should be an instance of RegExp
-> Set the inner regular expression for partial dynamic dependencies"
`)
);
createTestCase(
"invalid minimum",
2018-02-25 18:46:17 +08:00
{
2019-05-21 16:38:16 +08:00
entry: "a",
parallelism: 0
},
2019-05-21 16:38:16 +08:00
msg =>
expect(msg).toMatchInlineSnapshot(`
"Invalid configuration object. Webpack has been initialised using a configuration object that does not match the API schema.
- configuration.parallelism should be >= 1.
-> The number of parallel processed modules in the compilation."
`)
);
createTestCase(
"repeated value",
2018-02-25 18:46:17 +08:00
{
2019-05-21 16:38:16 +08:00
entry: ["abc", "def", "abc"]
},
2019-05-21 16:38:16 +08:00
msg =>
expect(msg).toMatchInlineSnapshot(`
"Invalid configuration object. Webpack has been initialised using a configuration object that does not match the API schema.
- configuration.entry should be one of these:
function | object { <key>: non-empty string | [non-empty string] } | non-empty string | [non-empty string]
-> The entry point(s) of the compilation.
Details:
* configuration.entry should be an instance of function
-> A Function returning an entry object, an entry string, an entry array or a promise to these things.
* configuration.entry should be an object.
-> Multiple entry bundles are created. The key is the chunk name. The value can be a string or an array.
* configuration.entry should be a string.
-> An entry point without name. The string is resolved to a module which is loaded upon startup.
* configuration.entry should not contain the item 'abc' twice."
`)
);
createTestCase(
"multiple errors",
2018-02-25 18:46:17 +08:00
{
2019-05-21 16:38:16 +08:00
entry: [/a/],
output: {
filename: /a/
}
},
2019-05-21 16:38:16 +08:00
msg =>
expect(msg).toMatchInlineSnapshot(`
"Invalid configuration object. Webpack has been initialised using a configuration object that does not match the API schema.
- configuration.entry should be one of these:
function | object { <key>: non-empty string | [non-empty string] } | non-empty string | [non-empty string]
-> The entry point(s) of the compilation.
Details:
* configuration.entry should be an instance of function
-> A Function returning an entry object, an entry string, an entry array or a promise to these things.
* configuration.entry should be an object.
-> Multiple entry bundles are created. The key is the chunk name. The value can be a string or an array.
* configuration.entry should be a string.
-> An entry point without name. The string is resolved to a module which is loaded upon startup.
* configuration.entry[0] should be a string.
-> A non-empty string
- configuration.output.filename should be one of these:
string | function
-> Specifies the name of each output file on disk. You must **not** specify an absolute path here! The \`output.path\` option determines the location on disk the files are written to, filename is used solely for naming the individual files.
Details:
* configuration.output.filename should be a string.
* configuration.output.filename should be an instance of function"
`)
);
createTestCase(
"multiple configurations",
[
{
entry: [/a/]
2018-02-25 18:46:17 +08:00
},
2019-05-21 16:38:16 +08:00
{
entry: "a",
2018-02-25 18:46:17 +08:00
output: {
filename: /a/
}
2019-05-21 16:38:16 +08:00
}
],
msg =>
expect(msg).toMatchInlineSnapshot(`
"Invalid configuration object. Webpack has been initialised using a configuration object that does not match the API schema.
- configuration[0].entry should be one of these:
function | object { <key>: non-empty string | [non-empty string] } | non-empty string | [non-empty string]
-> The entry point(s) of the compilation.
Details:
* configuration[0].entry should be an instance of function
-> A Function returning an entry object, an entry string, an entry array or a promise to these things.
* configuration[0].entry should be an object.
-> Multiple entry bundles are created. The key is the chunk name. The value can be a string or an array.
* configuration[0].entry should be a string.
-> An entry point without name. The string is resolved to a module which is loaded upon startup.
* configuration[0].entry[0] should be a string.
-> A non-empty string
- configuration[1].output.filename should be one of these:
string | function
-> Specifies the name of each output file on disk. You must **not** specify an absolute path here! The \`output.path\` option determines the location on disk the files are written to, filename is used solely for naming the individual files.
Details:
* configuration[1].output.filename should be a string.
* configuration[1].output.filename should be an instance of function"
`)
);
createTestCase(
"deep error",
2018-02-25 18:46:17 +08:00
{
2019-05-21 16:38:16 +08:00
entry: "a",
module: {
rules: [
{
oneOf: [
{
test: "/a",
passer: {
amd: false
2018-02-25 18:46:17 +08:00
}
2019-05-21 16:38:16 +08:00
}
]
}
]
}
},
2019-05-21 16:38:16 +08:00
msg =>
expect(msg).toMatchInlineSnapshot(`
"Invalid configuration object. Webpack has been initialised using a configuration object that does not match the API schema.
- configuration.module.rules[0].oneOf[0] has an unknown property 'passer'. These properties are valid:
object { compiler?, enforce?, exclude?, include?, issuer?, loader?, loaders?, oneOf?, options?, parser?, query?, resolve?, resource?, resourceQuery?, rules?, sideEffects?, test?, type?, use? }
-> A rule"
`)
);
createTestCase(
"additional key on root",
2018-02-25 18:46:17 +08:00
{
2019-05-21 16:38:16 +08:00
entry: "a",
postcss: () => {}
},
2019-05-21 16:38:16 +08:00
msg =>
expect(msg).toMatchInlineSnapshot(`
"Invalid configuration object. Webpack has been initialised using a configuration object that does not match the API schema.
- configuration has an unknown property 'postcss'. These properties are valid:
object { amd?, bail?, cache?, context?, dependencies?, devServer?, devtool?, entry?, externals?, loader?, mode?, module?, name?, node?, optimization?, output?, parallelism?, performance?, plugins?, profile?, recordsInputPath?, recordsOutputPath?, recordsPath?, resolve?, resolveLoader?, serve?, stats?, target?, watch?, watchOptions? }
For typos: please correct them.
For loader options: webpack >= v2.0.0 no longer allows custom properties in configuration.
Loaders should be updated to allow passing options via loader options in module.rules.
Until loaders are updated one can use the LoaderOptionsPlugin to pass these options to the loader:
plugins: [
new webpack.LoaderOptionsPlugin({
// test: /\\\\.xxx$/, // may apply this only for some modules
options: {
postcss:
}
})
]"
`)
);
createTestCase(
"enum",
2018-02-25 18:46:17 +08:00
{
2019-05-21 16:38:16 +08:00
entry: "a",
devtool: true
2016-12-14 19:03:24 +08:00
},
2019-05-21 16:38:16 +08:00
msg =>
expect(msg).toMatchInlineSnapshot(`
"Invalid configuration object. Webpack has been initialised using a configuration object that does not match the API schema.
- configuration.devtool should be one of these:
string | false
-> A developer tool to enhance debugging.
Details:
* configuration.devtool should be a string.
* configuration.devtool should be false"
`)
);
createTestCase(
"! in path",
{
2019-05-21 16:38:16 +08:00
entry: "foo.js",
output: {
path: "/somepath/!test",
filename: "bar"
}
},
2019-05-21 16:38:16 +08:00
msg =>
expect(msg).toMatchInlineSnapshot(`
"Invalid configuration object. Webpack has been initialised using a configuration object that does not match the API schema.
- configuration.output.path: The provided value \\"/somepath/!test\\" contains exclamation mark (!) which is not allowed because it's reserved for loader syntax.
-> The output directory as **absolute path** (required)."
`)
);
createTestCase(
"relative path",
2018-02-25 18:46:17 +08:00
{
2019-05-21 16:38:16 +08:00
entry: "foo.js",
output: {
filename: "/bar"
}
},
2019-05-21 16:38:16 +08:00
msg =>
expect(msg).toMatchInlineSnapshot(`
"Invalid configuration object. Webpack has been initialised using a configuration object that does not match the API schema.
- configuration.output.filename should be one of these:
string | function
-> Specifies the name of each output file on disk. You must **not** specify an absolute path here! The \`output.path\` option determines the location on disk the files are written to, filename is used solely for naming the individual files.
Details:
* configuration.output.filename: A relative path is expected. However, the provided value \\"/bar\\" is an absolute path!
Please use output.path to specify absolute path and output.filename for the file name.
* configuration.output.filename should be an instance of function"
`)
);
createTestCase(
"absolute path",
2018-02-25 18:46:17 +08:00
{
2019-05-21 16:38:16 +08:00
entry: "foo.js",
output: {
filename: "bar"
},
2019-05-21 16:38:16 +08:00
context: "baz"
},
2019-05-21 16:38:16 +08:00
msg =>
expect(msg).toMatchInlineSnapshot(`
"Invalid configuration object. Webpack has been initialised using a configuration object that does not match the API schema.
- configuration.context: The provided value \\"baz\\" is not an absolute path!
-> The base directory (absolute path!) for resolving the \`entry\` option. If \`output.pathinfo\` is set, the included pathinfo is shortened to this directory."
`)
);
createTestCase(
"missing stats option",
2018-02-25 18:46:17 +08:00
{
2019-05-21 16:38:16 +08:00
entry: "foo.js",
stats: {
foobar: true
}
},
2019-05-21 16:38:16 +08:00
msg => {
expect(
msg
.replace(/object \{ .* \}/g, "object {...}")
.replace(/"none" \| .+/g, '"none" | ...')
).toMatchInlineSnapshot(`
"Invalid configuration object. Webpack has been initialised using a configuration object that does not match the API schema.
- configuration.stats should be one of these:
object {...} | boolean | \\"none\\" | ...
-> Used by the webpack CLI program to pass stats options.
Details:
* configuration.stats has an unknown property 'foobar'. These properties are valid:
object {...}
* configuration.stats should be a boolean.
* configuration.stats should be one of these:
\\"none\\" | ..."
`);
}
);
createTestCase(
"Invalid plugin provided: bool",
2018-02-25 18:46:17 +08:00
{
2019-05-21 16:38:16 +08:00
entry: "foo.js",
plugins: [false]
},
2019-05-21 16:38:16 +08:00
msg =>
expect(msg).toMatchInlineSnapshot(`
"Invalid configuration object. Webpack has been initialised using a configuration object that does not match the API schema.
- configuration.plugins[0] should be one of these:
object { apply, } | function
-> Plugin of type object or instanceof Function
Details:
* configuration.plugins[0] should be an object.
-> Plugin instance
* configuration.plugins[0] should be an instance of function
-> Function acting as plugin"
`)
);
createTestCase(
"Invalid plugin provided: array",
2018-02-25 18:46:17 +08:00
{
2019-05-21 16:38:16 +08:00
entry: "foo.js",
plugins: [[]]
},
2019-05-21 16:38:16 +08:00
msg =>
expect(msg).toMatchInlineSnapshot(`
"Invalid configuration object. Webpack has been initialised using a configuration object that does not match the API schema.
- configuration.plugins[0] should be one of these:
object { apply, } | function
-> Plugin of type object or instanceof Function
Details:
* configuration.plugins[0] should be an object.
-> Plugin instance
* configuration.plugins[0] should be an instance of function
-> Function acting as plugin"
`)
);
createTestCase(
"Invalid plugin provided: string",
2018-02-25 18:46:17 +08:00
{
2019-05-21 16:38:16 +08:00
entry: "foo.js",
plugins: ["abc123"]
},
2019-05-21 16:38:16 +08:00
msg =>
expect(msg).toMatchInlineSnapshot(`
"Invalid configuration object. Webpack has been initialised using a configuration object that does not match the API schema.
- configuration.plugins[0] should be one of these:
object { apply, } | function
-> Plugin of type object or instanceof Function
Details:
* configuration.plugins[0] should be an object.
-> Plugin instance
* configuration.plugins[0] should be an instance of function
-> Function acting as plugin"
`)
);
createTestCase(
"Invalid plugin provided: int",
2018-02-25 18:46:17 +08:00
{
2019-05-21 16:38:16 +08:00
entry: "foo.js",
plugins: [12]
},
2019-05-21 16:38:16 +08:00
msg =>
expect(msg).toMatchInlineSnapshot(`
"Invalid configuration object. Webpack has been initialised using a configuration object that does not match the API schema.
- configuration.plugins[0] should be one of these:
object { apply, } | function
-> Plugin of type object or instanceof Function
Details:
* configuration.plugins[0] should be an object.
-> Plugin instance
* configuration.plugins[0] should be an instance of function
-> Function acting as plugin"
`)
);
2019-05-21 16:38:16 +08:00
createTestCase(
"Invalid plugin provided: object without apply function",
{
entry: "foo.js",
plugins: [{}]
},
msg =>
expect(msg).toMatchInlineSnapshot(`
"Invalid configuration object. Webpack has been initialised using a configuration object that does not match the API schema.
- configuration.plugins[0] should be one of these:
object { apply, } | function
-> Plugin of type object or instanceof Function
Details:
* configuration.plugins[0] misses the property 'apply'.
function
-> The run point of the plugin, required method.
* configuration.plugins[0] should be an instance of function
-> Function acting as plugin"
2019-05-21 16:38:37 +08:00
`)
);
createTestCase(
"invalid mode",
{
mode: "protuction"
},
msg =>
expect(msg).toMatchInlineSnapshot(`
"Invalid configuration object. Webpack has been initialised using a configuration object that does not match the API schema.
- configuration.mode should be one of these:
\\"development\\" | \\"production\\" | \\"none\\"
-> Enable production optimizations or development hints."
2019-05-21 16:38:16 +08:00
`)
);
});