Skip to content
This repository was archived by the owner on Mar 17, 2021. It is now read-only.

Commit 705eed4

Browse files
feat: improved validation error messages (#339)
1 parent d016daa commit 705eed4

File tree

10 files changed

+1201
-891
lines changed

10 files changed

+1201
-891
lines changed

.github/CONTRIBUTING.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,14 @@ module. Thankfully, Github provides a means to do this. Add a dependency to the
147147

148148
Where `{id}` is the # ID of your Pull Request.
149149

150+
## Contributor License Agreement
151+
152+
When submitting your contribution, a CLA (Contributor License Agreement) bot will come by to verify that you signed the [CLA](https://cla.js.foundation/webpack-contrib/file-loader).
153+
If it is your first time, it will link you to the right place to sign it.
154+
However, if you have committed your contributions using an email that is not the same as your email used on GitHub, the CLA bot can't accept your contribution.
155+
156+
Run `git config user.email` to see your Git email, and verify it with [your GitHub email](https://github.com/settings/emails).
157+
150158
## Thanks
151159

152160
For your interest, time, understanding, and for following this simple guide.

lint-staged.config.js

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,4 @@
11
module.exports = {
2-
ignore: ['package-lock.json', 'CHANGELOG.md'],
3-
linters: {
4-
'*.js': ['prettier --write', 'eslint --fix', 'git add'],
5-
'*.{json,md,yml,css}': ['prettier --write', 'git add'],
6-
},
2+
'*.js': ['prettier --write', 'eslint --fix', 'git add'],
3+
'*.{json,md,yml,css}': ['prettier --write', 'git add'],
74
};

package-lock.json

Lines changed: 1052 additions & 752 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -37,35 +37,35 @@
3737
"webpack": "^4.0.0"
3838
},
3939
"dependencies": {
40-
"loader-utils": "^1.2.2",
41-
"schema-utils": "^1.0.0"
40+
"loader-utils": "^1.2.3",
41+
"schema-utils": "^2.0.0"
4242
},
4343
"devDependencies": {
44-
"@babel/cli": "^7.2.0",
45-
"@babel/core": "^7.2.2",
46-
"@babel/preset-env": "^7.2.0",
47-
"@commitlint/cli": "^8.0.0",
48-
"@commitlint/config-conventional": "^8.0.0",
49-
"@webpack-contrib/defaults": "^5.0.0",
44+
"@babel/cli": "^7.5.5",
45+
"@babel/core": "^7.5.5",
46+
"@babel/preset-env": "^7.5.5",
47+
"@commitlint/cli": "^8.1.0",
48+
"@commitlint/config-conventional": "^8.1.0",
49+
"@webpack-contrib/defaults": "^5.0.2",
5050
"@webpack-contrib/eslint-config-webpack": "^3.0.0",
5151
"babel-jest": "^24.8.0",
5252
"commitlint-azure-pipelines-cli": "^1.0.2",
5353
"cross-env": "^5.2.0",
54-
"del": "^4.1.1",
54+
"del": "^5.0.0",
5555
"del-cli": "^2.0.0",
56-
"eslint": "^5.16.0",
57-
"eslint-config-prettier": "^4.3.0",
58-
"eslint-plugin-import": "^2.17.3",
59-
"husky": "^2.3.0",
56+
"eslint": "^6.0.1",
57+
"eslint-config-prettier": "^6.0.0",
58+
"eslint-plugin-import": "^2.18.0",
59+
"husky": "^3.0.0",
6060
"jest": "^24.8.0",
6161
"jest-junit": "^6.4.0",
62-
"lint-staged": "^8.1.7",
62+
"lint-staged": "^9.2.0",
6363
"memory-fs": "^0.4.1",
6464
"npm-run-all": "^4.1.5",
65-
"prettier": "^1.17.1",
65+
"prettier": "^1.18.2",
6666
"standard-version": "^6.0.1",
67-
"url-loader": "^1.1.2",
68-
"webpack": "^4.33.0"
67+
"url-loader": "^2.0.1",
68+
"webpack": "^4.36.1"
6969
},
7070
"keywords": [
7171
"webpack"

src/index.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,10 @@ import schema from './options.json';
88
export default function loader(content) {
99
const options = loaderUtils.getOptions(this) || {};
1010

11-
validateOptions(schema, options, 'File Loader');
11+
validateOptions(schema, options, {
12+
name: 'File Loader',
13+
baseDataPath: 'options',
14+
});
1215

1316
const context = options.context || this.rootContext;
1417

src/options.json

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
"additionalProperties": true,
33
"properties": {
44
"name": {
5+
"description": "The filename template for the target file(s) (https://github.com/webpack-contrib/file-loader#name).",
56
"anyOf": [
67
{
78
"type": "string"
@@ -12,6 +13,7 @@
1213
]
1314
},
1415
"outputPath": {
16+
"description": "A filesystem path where the target file(s) will be placed (https://github.com/webpack-contrib/file-loader#outputpath).",
1517
"anyOf": [
1618
{
1719
"type": "string"
@@ -22,6 +24,7 @@
2224
]
2325
},
2426
"publicPath": {
27+
"description": "A custom public path for the target file(s) (https://github.com/webpack-contrib/file-loader#publicpath).",
2528
"anyOf": [
2629
{
2730
"type": "string"
@@ -32,12 +35,15 @@
3235
]
3336
},
3437
"context": {
38+
"description": "A custom file context (https://github.com/webpack-contrib/file-loader#context).",
3539
"type": "string"
3640
},
3741
"emitFile": {
42+
"description": "Enables/Disables emit files (https://github.com/webpack-contrib/file-loader#emitfile).",
3843
"type": "boolean"
3944
},
4045
"regExp": {
46+
"description": "A Regular Expression to one or many parts of the target file path. The capture groups can be reused in the name property using [N] placeholder (https://github.com/webpack-contrib/file-loader#regexp).",
4147
"anyOf": [
4248
{
4349
"type": "string"
@@ -48,13 +54,5 @@
4854
]
4955
}
5056
},
51-
"errorMessages": {
52-
"name": "should be {String} or {Function} (https://github.com/webpack-contrib/file-loader#name)",
53-
"outputPath": "should be {String} or {Function} (https://github.com/webpack-contrib/file-loader#outputpath)",
54-
"publicPath": "should be {String} or {Function} (https://github.com/webpack-contrib/file-loader#publicpath)",
55-
"context": "should be {String} (https://github.com/webpack-contrib/file-loader#context)",
56-
"emitFile": "should be {Boolean} (https://github.com/webpack-contrib/file-loader#emitfile)",
57-
"regExp": "should be {String} or {RegExp} (https://github.com/webpack-contrib/file-loader#regexp)"
58-
},
5957
"type": "object"
6058
}

test/__snapshots__/errors.test.js.snap

Lines changed: 0 additions & 51 deletions
This file was deleted.
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
// Jest Snapshot v1, https://goo.gl/fbAQLP
2+
3+
exports[`validate options 1`] = `
4+
"Invalid options object. File Loader has been initialised using an options object that does not match the API schema.
5+
- options.name should be one of these:
6+
string | function
7+
-> The filename template for the target file(s) (https://github.com/webpack-contrib/file-loader#name).
8+
Details:
9+
* options.name should be a string.
10+
* options.name should be an instance of function."
11+
`;
12+
13+
exports[`validate options 2`] = `
14+
"Invalid options object. File Loader has been initialised using an options object that does not match the API schema.
15+
- options.outputPath should be one of these:
16+
string | function
17+
-> A filesystem path where the target file(s) will be placed (https://github.com/webpack-contrib/file-loader#outputpath).
18+
Details:
19+
* options.outputPath should be a string.
20+
* options.outputPath should be an instance of function."
21+
`;
22+
23+
exports[`validate options 3`] = `
24+
"Invalid options object. File Loader has been initialised using an options object that does not match the API schema.
25+
- options.publicPath should be one of these:
26+
string | function
27+
-> A custom public path for the target file(s) (https://github.com/webpack-contrib/file-loader#publicpath).
28+
Details:
29+
* options.publicPath should be a string.
30+
* options.publicPath should be an instance of function."
31+
`;
32+
33+
exports[`validate options 4`] = `
34+
"Invalid options object. File Loader has been initialised using an options object that does not match the API schema.
35+
- options.context should be a string.
36+
-> A custom file context (https://github.com/webpack-contrib/file-loader#context)."
37+
`;
38+
39+
exports[`validate options 5`] = `
40+
"Invalid options object. File Loader has been initialised using an options object that does not match the API schema.
41+
- options.emitFile should be a boolean.
42+
-> Enables/Disables emit files (https://github.com/webpack-contrib/file-loader#emitfile)."
43+
`;
44+
45+
exports[`validate options 6`] = `
46+
"Invalid options object. File Loader has been initialised using an options object that does not match the API schema.
47+
- options.regExp should be one of these:
48+
string | RegExp
49+
-> A Regular Expression to one or many parts of the target file path. The capture groups can be reused in the name property using [N] placeholder (https://github.com/webpack-contrib/file-loader#regexp).
50+
Details:
51+
* options.regExp should be a string.
52+
* options.regExp should be an instance of RegExp."
53+
`;

test/errors.test.js

Lines changed: 0 additions & 57 deletions
This file was deleted.

test/validate-options.test.js

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import loader from '../src';
2+
3+
it('validate options', () => {
4+
const validate = (options) =>
5+
loader.call(
6+
Object.assign(
7+
{},
8+
{
9+
resourcePath: 'image.png',
10+
query: options,
11+
emitFile: () => {},
12+
}
13+
),
14+
'a { color: red; }'
15+
);
16+
17+
expect(() => validate()).not.toThrow();
18+
19+
// The `file-loader` loader can be used as `fallback` loader and options can contain not only `file-loader` options
20+
// so we use `additionalProperties: false` to avoid problems.
21+
expect(() => validate({ limit: 8192 })).not.toThrow();
22+
23+
expect(() => validate({ name: '[path][name].[ext]' })).not.toThrow();
24+
expect(() =>
25+
validate({
26+
name: () => '[hash].[ext]',
27+
})
28+
).not.toThrow();
29+
expect(() => validate({ name: true })).toThrowErrorMatchingSnapshot();
30+
31+
expect(() => validate({ outputPath: 'assets' })).not.toThrow();
32+
expect(() =>
33+
validate({
34+
outputPath: () => 'assets',
35+
})
36+
).not.toThrow();
37+
expect(() => validate({ outputPath: true })).toThrowErrorMatchingSnapshot();
38+
39+
expect(() => validate({ publicPath: 'assets' })).not.toThrow();
40+
expect(() =>
41+
validate({
42+
publicPath: () => 'assets',
43+
})
44+
).not.toThrow();
45+
expect(() => validate({ publicPath: true })).toThrowErrorMatchingSnapshot();
46+
47+
expect(() => validate({ context: 'assets' })).not.toThrow();
48+
expect(() => validate({ context: true })).toThrowErrorMatchingSnapshot();
49+
50+
expect(() => validate({ emitFile: true })).not.toThrow();
51+
expect(() => validate({ emitFile: false })).not.toThrow();
52+
expect(() => validate({ emitFile: 'true' })).toThrowErrorMatchingSnapshot();
53+
54+
expect(() => validate({ regExp: /image\.png/ })).not.toThrow();
55+
expect(() => validate({ regExp: 'image\\.png' })).not.toThrow();
56+
expect(() => validate({ regExp: true })).toThrowErrorMatchingSnapshot();
57+
58+
expect(() => validate({ unknown: 'unknown' })).not.toThrow();
59+
});

0 commit comments

Comments
 (0)