Skip to content
This repository has been archived by the owner on Oct 27, 2020. It is now read-only.

feat: improved validation error messages #89

Merged
merged 1 commit into from Jul 18, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
8 changes: 8 additions & 0 deletions .github/CONTRIBUTING.md
Expand Up @@ -147,6 +147,14 @@ module. Thankfully, Github provides a means to do this. Add a dependency to the

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

## Contributor License Agreement

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/cache-loader).
If it is your first time, it will link you to the right place to sign it.
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.

Run `git config user.email` to see your Git email, and verify it with [your GitHub email](https://github.com/settings/emails).

## Thanks

For your interest, time, understanding, and for following this simple guide.
7 changes: 2 additions & 5 deletions lint-staged.config.js
@@ -1,7 +1,4 @@
module.exports = {
ignore: ['package-lock.json', 'CHANGELOG.md'],
linters: {
'*.js': ['prettier --write', 'eslint --fix', 'git add'],
'*.{json,md,yml,css}': ['prettier --write', 'git add'],
},
'*.js': ['prettier --write', 'eslint --fix', 'git add'],
'*.{json,md,yml,css}': ['prettier --write', 'git add'],
};
2,157 changes: 1,266 additions & 891 deletions package-lock.json

Large diffs are not rendered by default.

35 changes: 17 additions & 18 deletions package.json
Expand Up @@ -42,39 +42,38 @@
"loader-utils": "^1.2.3",
"mkdirp": "^0.5.1",
"neo-async": "^2.6.1",
"schema-utils": "^1.0.0"
"schema-utils": "^2.0.0"
},
"devDependencies": {
"@babel/cli": "^7.4.4",
"@babel/core": "^7.4.5",
"@babel/preset-env": "^7.4.5",
"@commitlint/cli": "^8.0.0",
"@commitlint/config-conventional": "^8.0.0",
"@webpack-contrib/defaults": "^5.0.0",
"@babel/cli": "^7.5.5",
"@babel/core": "^7.5.5",
"@babel/preset-env": "^7.5.5",
"@commitlint/cli": "^8.1.0",
"@commitlint/config-conventional": "^8.1.0",
"@webpack-contrib/defaults": "^5.0.2",
"@webpack-contrib/eslint-config-webpack": "^3.0.0",
"babel-jest": "^24.8.0",
"babel-loader": "^8.0.6",
"commitlint-azure-pipelines-cli": "^1.0.2",
"cross-env": "^5.2.0",
"del": "^4.1.1",
"del": "^5.0.0",
"del-cli": "^2.0.0",
"eslint": "^5.16.0",
"eslint-config-prettier": "^4.3.0",
"eslint-plugin-import": "^2.17.3",
"eslint-plugin-prettier": "^3.1.0",
"file-loader": "^4.0.0",
"husky": "^2.4.0",
"eslint": "^6.0.1",
"eslint-config-prettier": "^6.0.0",
"eslint-plugin-import": "^2.18.0",
"file-loader": "^4.1.0",
"husky": "^3.0.0",
"jest": "^24.8.0",
"jest-junit": "^6.4.0",
"lint-staged": "^8.1.7",
"lint-staged": "^9.2.0",
"memory-fs": "^0.4.1",
"normalize-path": "^3.0.0",
"npm-run-all": "^4.1.5",
"prettier": "^1.17.1",
"prettier": "^1.18.2",
"standard-version": "^6.0.1",
"uuid": "^3.3.2",
"webpack": "^4.33.0",
"webpack-cli": "^3.3.2"
"webpack": "^4.36.1",
"webpack-cli": "^3.3.6"
},
"keywords": [
"webpack"
Expand Down
11 changes: 9 additions & 2 deletions src/index.js
Expand Up @@ -59,7 +59,11 @@ function roundMs(mtime, precision) {
// to break watchpack -> chokidar watch logic over webpack@4 --watch
function loader(...args) {
const options = Object.assign({}, defaults, getOptions(this));
validateOptions(schema, options, 'Cache Loader');

validateOptions(schema, options, {
name: 'Cache Loader',
baseDataPath: 'options',
});

const { readOnly, write: writeFn } = options;

Expand Down Expand Up @@ -148,7 +152,10 @@ function loader(...args) {
function pitch(remainingRequest, prevRequest, dataInput) {
const options = Object.assign({}, defaults, getOptions(this));

validateOptions(schema, options, 'Cache Loader (Pitch)');
validateOptions(schema, options, {
name: 'Cache Loader (Pitch)',
baseDataPath: 'options',
});

const {
cacheContext,
Expand Down
9 changes: 9 additions & 0 deletions src/options.json
Expand Up @@ -2,30 +2,39 @@
"type": "object",
"properties": {
"cacheContext": {
"description": "The default cache context in order to generate the cache relatively to a path. By default it will use absolute paths.",
"type": "string"
},
"cacheKey": {
"description": "Allows you to override default cache key generator.",
"instanceof": "Function"
},
"cacheIdentifier": {
"description": "Provide a cache directory where cache items should be stored (used for default read/write implementation).",
"type": "string"
},
"cacheDirectory": {
"description": "Provide an invalidation identifier which is used to generate the hashes. You can use it for extra dependencies of loaders (used for default read/write implementation).",
"type": "string"
},
"compare": {
"description": "Allows you to override default comparison function between the cached dependency and the one is being read. Return true to use the cached resource.",
"instanceof": "Function"
},
"precision": {
"description": "Round mtime by this number of milliseconds both for stats and deps before passing those params to the comparing function.",
"type": "number"
},
"read": {
"description": "Allows you to override default read cache data from file.",
"instanceof": "Function"
},
"readOnly": {
"description": "Allows you to override default value and make the cache read only (useful for some environments where you don't want the cache to be updated, only read from it).",
"type": "boolean"
},
"write": {
"description": "Allows you to override default write cache data to file (e.g. Redis, memcached).",
"instanceof": "Function"
}
},
Expand Down
15 changes: 0 additions & 15 deletions test/__snapshots__/errors.test.js.snap

This file was deleted.

25 changes: 25 additions & 0 deletions test/__snapshots__/validate-options.test.js.snap
@@ -0,0 +1,25 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`validate options error (pitch) 1`] = `
"Invalid options object. Cache Loader (Pitch) has been initialised using an options object that does not match the API schema.
- options.cacheIdentifier should be a string.
-> Provide a cache directory where cache items should be stored (used for default read/write implementation)."
`;

exports[`validate options error 1`] = `
"Invalid options object. Cache Loader has been initialised using an options object that does not match the API schema.
- options.cacheIdentifier should be a string.
-> Provide a cache directory where cache items should be stored (used for default read/write implementation)."
`;

exports[`validate options unknown (pitch) 1`] = `
"Invalid options object. Cache Loader (Pitch) has been initialised using an options object that does not match the API schema.
- options has an unknown property 'unknown'. These properties are valid:
object { cacheContext?, cacheKey?, cacheIdentifier?, cacheDirectory?, compare?, precision?, read?, readOnly?, write? }"
`;

exports[`validate options unknown 1`] = `
"Invalid options object. Cache Loader has been initialised using an options object that does not match the API schema.
- options has an unknown property 'unknown'. These properties are valid:
object { cacheContext?, cacheKey?, cacheIdentifier?, cacheDirectory?, compare?, precision?, read?, readOnly?, write? }"
`;
21 changes: 0 additions & 21 deletions test/errors.test.js

This file was deleted.

35 changes: 35 additions & 0 deletions test/validate-options.test.js
@@ -0,0 +1,35 @@
import loader, { pitch } from '../src';

// Needed for `schema-utils` to not call
// process.exit(1) when running tests
process.env.JEST = true;

describe('validate options', () => {
test('error', () => {
const err = () => loader.call({ query: { cacheIdentifier: 1 } });

expect(err).toThrow();
expect(err).toThrowErrorMatchingSnapshot();
});

test('unknown', () => {
const err = () => loader.call({ query: { unknown: 'unknown' } });

expect(err).toThrow();
expect(err).toThrowErrorMatchingSnapshot();
});

test('error (pitch)', () => {
const err = () => pitch.call({ query: { cacheIdentifier: 1 } });

expect(err).toThrow();
expect(err).toThrowErrorMatchingSnapshot();
});

test('unknown (pitch)', () => {
const err = () => pitch.call({ query: { unknown: 'unknown' } });

expect(err).toThrow();
expect(err).toThrowErrorMatchingSnapshot();
});
});