check-types-mini
Advanced tools
Comparing version 1.5.0 to 2.0.0
@@ -7,2 +7,10 @@ # Change Log | ||
## [2.0.0] - 2017-06-12 | ||
### Changed | ||
- ✨ BREAKING API CHANGES. third argument `msg` moved to `opts.msg`. Fourth argument `optsVarName` moved to `opts.optsVarName`. That's the right thing to do. | ||
## [1.6.0] - 2017-06-11 | ||
### Added | ||
- ✨ `opts.schema` - let's you enforce any schema you want for any key. Case-insensitive, just put types. `object` means plain object, not `array`. `whatever`, and `any` are also valid values. Algorithm will check the `opts.schema` first, then if the keys does not exist there, will check its type in `defaults`. | ||
## [1.5.0] - 2017-06-11 | ||
@@ -39,1 +47,3 @@ ### Changed | ||
[1.5.0]: https://github.com/codsen/check-types-mini/compare/v1.4.0...v1.5.0 | ||
[1.6.0]: https://github.com/codsen/check-types-mini/compare/v1.5.0...v1.6.0 | ||
[2.0.0]: https://github.com/codsen/check-types-mini/compare/v1.6.0...v2.0.0 |
114
index.js
@@ -6,11 +6,14 @@ 'use strict' | ||
const clone = require('lodash.clonedeep') | ||
const isArr = Array.isArray | ||
const includes = require('lodash.includes') | ||
const pullAll = require('lodash.pullall') | ||
const isEqual = require('lodash.isequal') | ||
const intersection = require('lodash.intersection') | ||
const arrayiffyIfString = require('arrayiffy-if-string') | ||
function checkTypes (obj, ref, msg, optsVarName, opts) { | ||
function checkTypes (obj, ref, opts) { | ||
const NAMESFORANYTYPE = ['everything', 'all', 'any', 'whatever'] | ||
function existy (x) { return x != null } | ||
function isBool (something) { return type(something) === 'boolean' } | ||
function isStr (something) { return type(something) === 'string' } | ||
const isArr = Array.isArray | ||
@@ -23,15 +26,2 @@ if (arguments.length === 0) { | ||
} | ||
if (!existy(optsVarName)) { | ||
optsVarName = 'opts' | ||
} | ||
if ((typeof msg === 'string') && (msg.length > 0)) { | ||
msg = msg.trim() + ' ' | ||
} else { | ||
msg = '' | ||
} | ||
if ((typeof optsVarName === 'string') && (optsVarName.length > 0)) { | ||
optsVarName = optsVarName.trim() + '.' | ||
} else { | ||
optsVarName = '' | ||
} | ||
@@ -42,8 +32,27 @@ var defaults = { | ||
acceptArraysIgnore: [], | ||
enforceStrictKeyset: true | ||
enforceStrictKeyset: true, | ||
schema: {}, | ||
msg: '', | ||
optsVarName: 'opts.' | ||
} | ||
opts = objectAssign(clone(defaults), opts) | ||
if (!isStr(opts.msg)) { | ||
throw new Error(`check-types-mini/checkTypes(): [THROW_ID_07] opts.msg must be string! Currently it's: ${type(opts.msg)}, equal to ${JSON.stringify(opts.msg, null, 4)}`) | ||
} | ||
if (!isStr(opts.optsVarName)) { | ||
throw new Error(`check-types-mini/checkTypes(): [THROW_ID_08] opts.optsVarName must be string! Currently it's: ${type(opts.optsVarName)}, equal to ${JSON.stringify(opts.optsVarName, null, 4)}`) | ||
} | ||
opts.ignoreKeys = arrayiffyIfString(opts.ignoreKeys) | ||
opts.acceptArraysIgnore = arrayiffyIfString(opts.acceptArraysIgnore) | ||
// make every schema object key's value to be an array: | ||
Object.keys(opts.schema).forEach(function (oneKey) { | ||
if (!isArr(opts.schema[oneKey])) { | ||
opts.schema[oneKey] = [opts.schema[oneKey]] | ||
} | ||
// then turn all keys into strings and trim and lowercase them: | ||
opts.schema[oneKey] = opts.schema[oneKey].map(String).map(el => el.toLowerCase()).map(el => el.trim()) | ||
}) | ||
if (!isArr(opts.ignoreKeys)) { | ||
@@ -58,23 +67,64 @@ throw new TypeError(`check-types-mini/checkTypes(): [THROW_ID_03] opts.ignoreKeys should be an array, currently it's: ${type(opts.ignoreKeys)}`) | ||
} | ||
if (opts.enforceStrictKeyset && !isEqual(Object.keys(obj), Object.keys(ref))) { | ||
throw new TypeError(`check-types-mini/checkTypes(): [THROW_ID_06] object has some unrecongnised keys: ${pullAll(Object.keys(ref), Object.keys(obj))}`) | ||
if (!isBool(opts.enforceStrictKeyset)) { | ||
throw new TypeError(`check-types-mini/checkTypes(): [THROW_ID_06] opts.enforceStrictKeyset should be a Boolean, currently it's: ${type(opts.enforceStrictKeyset)}`) | ||
} | ||
Object.keys(obj).forEach(function (key) { | ||
if ( | ||
ref.hasOwnProperty(key) && | ||
(type(obj[key]) !== type(ref[key])) && | ||
!includes(opts.ignoreKeys, key) | ||
) { | ||
if (opts.acceptArrays && isArr(obj[key]) && !includes(opts.acceptArraysIgnore, key)) { | ||
var allMatch = obj[key].every(function (el, i) { | ||
return type(el) === type(ref[key]) | ||
}) | ||
if (!allMatch) { | ||
throw new TypeError(`${msg}${optsVarName}${key} was customised to be array, but not all of its elements are ${type(ref[key])}-type`) | ||
if (!existy(ref)) { | ||
ref = {} | ||
} | ||
if (opts.msg.length > 0) { | ||
opts.msg = opts.msg.trim() + ' ' | ||
} | ||
if (opts.enforceStrictKeyset) { | ||
if (existy(opts.schema) && (Object.keys(opts.schema).length > 0)) { | ||
if (pullAll(Object.keys(obj), clone(Object.keys(ref)).concat(Object.keys(opts.schema))).length !== 0) { | ||
throw new TypeError(`check-types-mini/checkTypes(): [THROW_ID_09] opts.enforceStrictKeyset is on and the following keys are not covered by schema and/or reference objects: ${JSON.stringify(pullAll(Object.keys(obj), clone(Object.keys(ref)).concat(Object.keys(opts.schema))), null, 4)}`) | ||
} | ||
} else { | ||
if (existy(ref) && (Object.keys(ref).length > 0)) { | ||
if (pullAll(Object.keys(obj), Object.keys(ref)).length !== 0) { | ||
throw new TypeError(`check-types-mini/checkTypes(): [THROW_ID_10] The input object has keys that are not covered by reference object: ${JSON.stringify(pullAll(Object.keys(obj), Object.keys(ref)), null, 4)}`) | ||
} else if (pullAll(Object.keys(ref), Object.keys(obj)).length !== 0) { | ||
throw new TypeError(`check-types-mini/checkTypes(): [THROW_ID_11] The reference object has keys that are not present in the input object: ${JSON.stringify(pullAll(Object.keys(ref), Object.keys(obj)), null, 4)}`) | ||
} | ||
} else { | ||
throw new TypeError(`${msg}${optsVarName}${key} was customised to ${JSON.stringify(obj[key], null, 4)} which is not ${type(ref[key])} but ${type(obj[key])}`) | ||
// it's an error because both schema and reference don't exist | ||
throw new TypeError(`check-types-mini/checkTypes(): [THROW_ID_12] Both opts.schema and reference objects are missing! We don't have anything to match the keys as you requested via opts.enforceStrictKeyset!`) | ||
} | ||
} | ||
} | ||
Object.keys(obj).forEach(function (key) { | ||
if (opts.schema.hasOwnProperty(key)) { | ||
// stage 1. check schema, if present | ||
opts.schema[key] = arrayiffyIfString(opts.schema[key]) | ||
.map(String) | ||
.map(el => el.toLowerCase()) | ||
// first check does our schema contain any blanket names, "any", "whatever" etc. | ||
if (!intersection(opts.schema[key], NAMESFORANYTYPE).length) { | ||
// because, if not, it means we need to do some work, check types: | ||
if (!includes(opts.schema[key], type(obj[key]).toLowerCase())) { | ||
throw new TypeError(`${opts.msg}${opts.optsVarName}${key} was customised to ${JSON.stringify(obj[key], null, 4)} which is not among the allowed types in schema (${opts.schema[key]}) but ${type(obj[key])}`) | ||
} | ||
} | ||
} else { | ||
// stage 2. check reference object. | ||
if ( | ||
ref.hasOwnProperty(key) && | ||
(type(obj[key]) !== type(ref[key])) && | ||
!includes(opts.ignoreKeys, key) | ||
) { | ||
if (opts.acceptArrays && isArr(obj[key]) && !includes(opts.acceptArraysIgnore, key)) { | ||
var allMatch = obj[key].every(function (el, i) { | ||
return type(el) === type(ref[key]) | ||
}) | ||
if (!allMatch) { | ||
throw new TypeError(`${opts.msg}${opts.optsVarName}${key} was customised to be array, but not all of its elements are ${type(ref[key])}-type`) | ||
} | ||
} else { | ||
throw new TypeError(`${opts.msg}${opts.optsVarName}${key} was customised to ${JSON.stringify(obj[key], null, 4)} which is not ${type(ref[key])} but ${type(obj[key])}`) | ||
} | ||
} | ||
} | ||
}) | ||
@@ -81,0 +131,0 @@ } |
{ | ||
"name": "check-types-mini", | ||
"version": "1.5.0", | ||
"version": "2.0.0", | ||
"description": "Check the types of your options object's values after user has customised them", | ||
@@ -39,7 +39,7 @@ "main": "index.js", | ||
"arrayiffy-if-string": "*", | ||
"lodash.clonedeep": "^4.5.0", | ||
"lodash.clonedeep": "*", | ||
"lodash.includes": "*", | ||
"lodash.isequal": "^4.5.0", | ||
"lodash.pullall": "^4.2.0", | ||
"object-assign": "^4.1.1", | ||
"lodash.intersection": "*", | ||
"lodash.pullall": "*", | ||
"object-assign": "*", | ||
"type-detect": "^4.0.0" | ||
@@ -46,0 +46,0 @@ }, |
@@ -26,2 +26,3 @@ # check-types-mini | ||
- [`opts.enforceStrictKeyset`](#optsenforcestrictkeyset) | ||
- [`opts.schema`](#optsschema) | ||
- [Contributing](#contributing) | ||
@@ -40,16 +41,18 @@ - [Licence](#licence) | ||
[`check-types`](https://www.npmjs.com/package/check-types) is good but it's too big. All I need is to `throw` if somebody sets my input settings to a wrong type. | ||
[`check-types`](https://www.npmjs.com/package/check-types) is good but it's too big. All I need is to `throw` if somebody sets my input settings to a wrong type: | ||
I had a working prototype of this library ages ago. Pieces of it were finding a new life (and evolving) in every new non-trivial library I created. Then I got fed up with chasing 100% code coverage each time, duplicating unit tests and decided to split it into a standalone library. | ||
```js | ||
TypeError: newLibrary/yourFunction(): [THROW_ID_01] opts.placeholder was customised to "false" which is not boolean but string | ||
``` | ||
The point of `check-types-mini` is to save your time creating new libraries. Every library that has options object will need some type checks if you let user tinker with it. | ||
Originally this library started as a function within one of my libraries. When I was about to copy-paste the thing into another library, I stopped and put that into a separate library, `check-types`. I'm glad I did this, because already 4 of my libraries depend on it, and improving `check-types` I improve my other libraries. DRY in it's best. | ||
The point of `check-types-mini` is to save your time creating new libraries. Every library that has options object will need some **type checks** if you let user tinker with it. | ||
## API | ||
**checkTypes(obj, ref\[, msg, optsVarName, opts])** | ||
**checkTypes(obj, ref\[, opts])** | ||
As a result, it _throws_ `TypeError`s for you, containing your custom message, similar to: | ||
As a result, it _throws_ `TypeError`s for you, containing your custom message which you optionally set via arguments: | ||
check-types-mini/checkTypes(): opts.mode was customised to "zzz" which is not Boolean but string | ||
Input argument | Type | Obligatory? | Description | ||
@@ -59,4 +62,2 @@ -----------------|--------------|-------------|-------------- | ||
`ref` | Plain object | yes | Default options - used to compare the types | ||
`msg` | String | no | A message to show. I like to include the name of the calling library, parent function and numeric throw ID. | ||
`optsVarName` | String | no | How is your options variable called? It does not matter much, but it's nicer to keep references consistent with your API documentation. | ||
`opts` | Plain object | no | Optional options go here. | ||
@@ -72,3 +73,6 @@ | ||
`acceptArraysIgnore` | Array of strings or String | no | `[]` (empty array) | If you want to ignore `acceptArrays` on certain keys, pass them in an array here. | ||
`enforceStrictKeyset` | Boolean | no | `true` | If it's set to `true`, your object must not have any unique keys that reference object does not have. | ||
`enforceStrictKeyset` | Boolean | no | `true` | If it's set to `true`, your object must not have any unique keys that reference object (and/or `schema`) does not have. | ||
`schema` | Plain object | no | `{}` | You can set arrays of types for each key, overriding the reference object. This allows you more precision and enforcing multiple types. | ||
`msg` | String | no | ` ` | A message to show. I like to include the name of the calling library, parent function and numeric throw ID. | ||
`optsVarName` | String | no | `opts` | How is your options variable called? It does not matter much, but it's nicer to keep references consistent with your API documentation. | ||
} | | | | | ||
@@ -85,3 +89,3 @@ | ||
// declare defaults, so we can enforce types later: | ||
var defaults = { | ||
let defaults = { | ||
placeholder: false | ||
@@ -92,7 +96,7 @@ } | ||
// the check: | ||
checkTypes(opts, defaults, 'newLibrary/yourFunction(): [THROW_ID_01]', 'opts') | ||
checkTypes(opts, defaults, {msg: 'newLibrary/yourFunction(): [THROW_ID_01]', optsVarName: 'opts'}) | ||
// ... | ||
} | ||
var res = yourFunction(1, {placeholder: 'zzz'}) | ||
let res = yourFunction(1, {placeholder: 'zzz'}) | ||
@@ -108,3 +112,3 @@ // =>> [TypeError: 'newLibrary/yourFunction(): [THROW_ID_01] opts.placeholder was customised to "false" which is not boolean but string'] | ||
const checkTypes = require('check-types-mini') | ||
var res = checkTypes( | ||
let res = checkTypes( | ||
{ // < input | ||
@@ -128,3 +132,3 @@ option1: 'setting1', | ||
const checkTypes = require('check-types-mini') | ||
var res = checkTypes( | ||
let res = checkTypes( | ||
{ | ||
@@ -140,4 +144,2 @@ option1: 'setting1', | ||
}, | ||
'check-types-mini/checkTypes(): [THROW_ID_01]', | ||
'opts', | ||
{ | ||
@@ -147,3 +149,3 @@ acceptArrays: true | ||
) | ||
// => Does not throw. | ||
// => Does not throw, because we allow arrays full of a matching type | ||
``` | ||
@@ -155,4 +157,42 @@ | ||
When I was coding a new major version of [posthtml-ast-delete-object](https://github.com/codsen/posthtml-ast-delete-object) I had to update all the unit tests too. Previously, the settings was only one argument - Boolean. I had to change it to be a plain object. I noticed that old Boolean argument was not causing problems! Then I came up with the idea to enforce the keys of the object to match the reference. This was released in `v1.4.0`. It's on by default because I can't imagine how you would end up with settings object that does not match your default settings object, key-wise, but if you don't like that, feel free to turn it off. It's `opts.enforceStrictKeyset` Boolean flag. | ||
When I was coding a new major version of [posthtml-ast-delete-object](https://github.com/codsen/posthtml-ast-delete-object) I had to update all the unit tests too. Previously, the settings were set using only one argument, Boolean-type. I had to change it to be a plain object. I noticed that when I missed updating some tests, their Booleans were `object-assign`ed into a default settings object and no alarm was being raised! That's not good. | ||
Then I came up with the idea to **enforce the keys of the object** to match the reference and/or schema keys in `options`. It's on by default because I can't imagine how you would end up with settings object that does not match your default settings object, key-wise, but if you don't like that, feel free to turn it off. It's `opts.enforceStrictKeyset` Boolean flag. | ||
### `opts.schema` | ||
Sometimes your API is more complex than a single type or array of them. Sometimes you want to allow, let's say, `string` or `array` of strings or `null`. What do you do? | ||
Enter `opts.schema`. You can define all the types for particular key, as an array: | ||
```js | ||
const checkTypes = require('check-types-mini') | ||
checkTypes( | ||
{ | ||
option1: 'setting1', | ||
option2: null | ||
}, | ||
{ | ||
option1: 'zz', | ||
option2: 'yy' // << notice, it's given as string in defaults object | ||
}, | ||
{ | ||
schema: { | ||
option2: ['stRing', null] | ||
} | ||
} | ||
) | ||
// => does not throw | ||
``` | ||
The types are case-insensitive and come from [type-detect](https://github.com/chaijs/type-detect), a Chai library: | ||
* `object` (meaning a plain object literal, nothing else) | ||
* `array` | ||
* `string` | ||
* `null` | ||
* and other usual types | ||
The type values you put into `opts.schema` are not validated, on purpose, so please don't make typos. | ||
## Contributing | ||
@@ -162,3 +202,3 @@ | ||
If you see anything incorrect whatsoever, do [raise an issue](https://github.com/codsen/check-types-mini/issues). If you file a pull request, I'll do my best to help you to get it merged as soon as possible. If you have any comments on the code, including ideas how to improve something, don't hesitate to contact me by email. | ||
If you see anything incorrect whatsoever, do [raise an issue](https://github.com/codsen/check-types-mini/issues). If you file a pull request, I'll do my best to help you to get it merged as soon as possible. If you have some advice how to improve this code, email me, I would really appreciate that. | ||
@@ -165,0 +205,0 @@ ## Licence |
382
test.js
@@ -35,3 +35,3 @@ 'use strict' | ||
test('01.04 - throws when input args are of a wrong type', t => { | ||
test('01.04 - opts.msg or opts.optsVarName args are wrong-type', t => { | ||
t.throws(function () { | ||
@@ -41,3 +41,3 @@ checkTypes( | ||
option1: 'setting1', | ||
option2: 'false', | ||
option2: 'setting2', | ||
option3: false | ||
@@ -47,7 +47,9 @@ }, | ||
option1: 'setting1', | ||
option2: false, | ||
option2: 'setting2', | ||
option3: false | ||
}, | ||
'zzz', | ||
1 | ||
{ | ||
msg: 'zzz', | ||
optsVarName: 1 | ||
} | ||
) | ||
@@ -59,3 +61,3 @@ }) | ||
option1: 'setting1', | ||
option2: 'false', | ||
option2: 'setting2', | ||
option3: false | ||
@@ -65,7 +67,9 @@ }, | ||
option1: 'setting1', | ||
option2: false, | ||
option2: 'setting2', | ||
option3: false | ||
}, | ||
1, | ||
'zzz' | ||
{ | ||
msg: 1, | ||
optsVarName: 'zzz' | ||
} | ||
) | ||
@@ -88,3 +92,5 @@ }) | ||
}, | ||
'newLibrary/index.js: [THROW_ID_01]' // << no trailing space | ||
{ | ||
msg: 'newLibrary/index.js: [THROW_ID_01]' // << no trailing space | ||
} | ||
) | ||
@@ -106,3 +112,5 @@ }, | ||
}, | ||
'newLibrary/index.js: [THROW_ID_01] ' // << trailing space | ||
{ | ||
msg: 'newLibrary/index.js: [THROW_ID_01] ' // << trailing space | ||
} | ||
) | ||
@@ -124,5 +132,6 @@ }, | ||
}, | ||
'newLibrary/index.js: [THROW_ID_01] ', | ||
null, | ||
{ ignoreKeys: ['option2'] } | ||
{ | ||
msg: 'newLibrary/index.js: [THROW_ID_01] ', | ||
ignoreKeys: ['option2'] | ||
} | ||
) | ||
@@ -134,9 +143,30 @@ }) | ||
t.throws(function () { | ||
checkTypes({a: 'a'}, {a: 'b'}, 'aa', 'bbb', { ignoreKeys: false }) | ||
}, 'check-types-mini/checkTypes(): [THROW_ID_03] opts.ignoreKeys should be an array, currently it\'s: boolean') | ||
checkTypes( | ||
{a: 'a'}, | ||
{a: 'b'}, | ||
{ | ||
msg: 'aa', | ||
optsVarName: 'bbb', | ||
ignoreKeys: false | ||
} | ||
) | ||
}, | ||
'check-types-mini/checkTypes(): [THROW_ID_03] opts.ignoreKeys should be an array, currently it\'s: boolean') | ||
t.notThrows(function () { | ||
checkTypes({a: 'a'}, {a: 'b'}, 'aa', 'bbb', { ignoreKeys: 'a' }) | ||
checkTypes({a: 'a'}, {a: 'b'}, | ||
{ | ||
msg: 'aa', | ||
optsVarName: 'bbb', | ||
ignoreKeys: 'a' | ||
} | ||
) | ||
}) | ||
t.notThrows(function () { | ||
checkTypes({a: 'a'}, {a: 'b'}, 'aa', 'bbb', { ignoreKeys: '' }) | ||
checkTypes({a: 'a'}, {a: 'b'}, | ||
{ | ||
msg: 'aa', | ||
optsVarName: 'bbb', | ||
ignoreKeys: '' | ||
} | ||
) | ||
}) | ||
@@ -176,5 +206,5 @@ }) | ||
}, | ||
'message', | ||
'varname', | ||
{ | ||
msg: 'message', | ||
optsVarName: 'varname', | ||
acceptArrays: true | ||
@@ -196,5 +226,5 @@ } | ||
}, | ||
'message', | ||
'varname', | ||
{ | ||
msg: 'message', | ||
optsVarName: 'varname', | ||
acceptArrays: true | ||
@@ -233,5 +263,5 @@ } | ||
}, | ||
'message', | ||
'varname', | ||
{ | ||
msg: 'message', | ||
optsVarName: 'varname', | ||
acceptArrays: true | ||
@@ -253,5 +283,5 @@ } | ||
}, | ||
'message', | ||
'varname', | ||
{ | ||
msg: 'message', | ||
optsVarName: 'varname', | ||
acceptArrays: true | ||
@@ -273,5 +303,5 @@ } | ||
}, | ||
'test: [THROW_ID_01]', | ||
'opts', | ||
{ | ||
msg: 'test: [THROW_ID_01]', | ||
optsVarName: 'opts', | ||
acceptArrays: 'this string will cause the throw', | ||
@@ -297,5 +327,5 @@ acceptArraysIgnore: [] | ||
}, | ||
'test: [THROW_ID_01]', | ||
'opts', | ||
{ | ||
msg: 'test: [THROW_ID_01]', | ||
optsVarName: 'opts', | ||
acceptArrays: true, | ||
@@ -318,5 +348,5 @@ acceptArraysIgnore: [] | ||
}, | ||
'test: [THROW_ID_01]', | ||
'opts', | ||
{ | ||
msg: 'test: [THROW_ID_01]', | ||
optsVarName: 'opts', | ||
acceptArrays: true, | ||
@@ -339,5 +369,5 @@ acceptArraysIgnore: ['zzz', 'option1'] | ||
}, | ||
'test: [THROW_ID_01]', | ||
'opts', | ||
{ | ||
msg: 'test: [THROW_ID_01]', | ||
optsVarName: 'opts', | ||
acceptArrays: false, | ||
@@ -360,5 +390,5 @@ acceptArraysIgnore: ['zzz', 'option1'] | ||
}, | ||
'test: [THROW_ID_01]', | ||
'opts', | ||
{ | ||
msg: 'test: [THROW_ID_01]', | ||
optsVarName: 'opts', | ||
acceptArrays: true, | ||
@@ -426,4 +456,2 @@ acceptArraysIgnore: true | ||
}, | ||
null, | ||
null, | ||
{ | ||
@@ -445,4 +473,2 @@ enforceStrictKeyset: false | ||
}, | ||
null, | ||
null, | ||
{ | ||
@@ -455,2 +481,35 @@ enforceStrictKeyset: false | ||
test('02.07 - opts.enforceStrictKeyset set to a wrong thing', t => { | ||
t.throws(function () { | ||
checkTypes( | ||
{ | ||
'key': 1, | ||
'val': null, | ||
'cleanup': true | ||
}, | ||
{ | ||
'key': null, | ||
'val': null, | ||
'cleanup': true | ||
}, | ||
{ | ||
enforceStrictKeyset: 1 | ||
} | ||
) | ||
}) | ||
}) | ||
test('02.08 - throws when reference and schema are both missing', t => { | ||
t.throws(function () { | ||
checkTypes( | ||
{ | ||
'key': 1, | ||
'val': null, | ||
'cleanup': true | ||
}, | ||
{} | ||
) | ||
}) | ||
}) | ||
// ====================== | ||
@@ -485,4 +544,2 @@ // 03. opts.enforceStrictKeyset | ||
}, | ||
null, | ||
null, | ||
{ | ||
@@ -494,1 +551,242 @@ enforceStrictKeyset: false | ||
}) | ||
// ====================== | ||
// 04. opts.schema | ||
// ====================== | ||
test('04.01 - opts.schema only', t => { | ||
t.throws(function () { | ||
checkTypes( | ||
{ | ||
option1: 'setting1', | ||
option2: null | ||
}, | ||
{ | ||
option1: 'zz', | ||
option2: 'yy' | ||
} | ||
) | ||
}) | ||
t.notThrows(function () { | ||
checkTypes( | ||
{ | ||
option1: 'setting1', | ||
option2: null | ||
}, | ||
{ | ||
option1: 'zz', | ||
option2: 'yy' | ||
}, | ||
{ | ||
schema: { | ||
option2: ['stRing', null] | ||
} | ||
} | ||
) | ||
}) | ||
t.throws(function () { | ||
checkTypes( | ||
{ | ||
option1: 'setting1', | ||
option2: null | ||
}, | ||
{ | ||
option1: 'zz', | ||
option2: 'yy' | ||
}, | ||
{ | ||
schema: { | ||
option2: ['string', 'boolean'] | ||
} | ||
} | ||
) | ||
}) | ||
t.notThrows(function () { | ||
checkTypes( | ||
{ | ||
option1: 'setting1', | ||
option2: null | ||
}, | ||
null, // << reference object is completely omitted!!! | ||
{ | ||
schema: { | ||
option1: 'String', | ||
option2: ['stRing', null] | ||
} | ||
} | ||
) | ||
}) | ||
t.throws(function () { | ||
checkTypes( | ||
{ | ||
option1: 'setting1', | ||
option2: null | ||
}, | ||
null, | ||
{ | ||
schema: { // <<< notice how option1 is missing AND also missing in reference obj | ||
option2: ['stRing', null] | ||
} | ||
} | ||
) | ||
}) | ||
}) | ||
test('04.02 - opts.schema values as strings + "whatever" keys', t => { | ||
t.throws(function () { | ||
checkTypes( | ||
{ | ||
option1: {a: 'setting1'}, | ||
option2: null | ||
}, | ||
{ | ||
option1: 'zz', | ||
option2: 'yy' | ||
} | ||
) | ||
}) | ||
t.notThrows(function () { | ||
checkTypes( | ||
{ | ||
option1: {a: 'setting1'}, | ||
option2: null | ||
}, | ||
{ | ||
option1: 'zz', | ||
option2: 'yy' | ||
}, | ||
{ | ||
schema: { | ||
option1: ['object', 'string'], | ||
option2: ['whatever'] | ||
} | ||
} | ||
) | ||
}) | ||
t.notThrows(function () { | ||
checkTypes( | ||
{ | ||
option1: {a: 'setting1'}, | ||
option2: null | ||
}, | ||
{ | ||
option1: 'zz', | ||
option2: 'yy' | ||
}, | ||
{ | ||
schema: { | ||
option1: 'object', // << observe it's a string, not an array | ||
option2: ['whatever'] | ||
} | ||
} | ||
) | ||
}) | ||
t.throws(function () { | ||
checkTypes( | ||
{ | ||
option1: {a: 'setting1'}, | ||
option2: null | ||
}, | ||
{ | ||
option1: 'zz', | ||
option2: 'yy' | ||
}, | ||
{ | ||
schema: { | ||
option1: 'string', // << will throw because this type is not followed | ||
option2: ['whatever'] | ||
} | ||
} | ||
) | ||
}) | ||
t.notThrows(function () { | ||
checkTypes( | ||
{ | ||
option1: {a: 'setting1'}, | ||
option2: null | ||
}, | ||
{ | ||
option1: 'zz', | ||
option2: 'yy' | ||
}, | ||
{ | ||
schema: { | ||
option1: ['string', 'any'], // <<< observe how "any" is among other types | ||
option2: 'whatever' // also observe that it's not an array. Should work anyway! | ||
} | ||
} | ||
) | ||
}) | ||
}) | ||
test('04.03 - opts.schema falling back to reference object', t => { | ||
// with throwing consequences: | ||
t.throws(function () { | ||
checkTypes( | ||
{ | ||
option1: {a: 'setting1'}, | ||
option2: null | ||
}, | ||
{ | ||
option1: 'zz', | ||
option2: 'yy' | ||
}, | ||
{ | ||
schema: { | ||
option1: 'number' | ||
} | ||
} | ||
) | ||
}) | ||
// without throwing consequences: | ||
t.notThrows(function () { | ||
checkTypes( | ||
{ | ||
option1: {a: 'setting1'}, | ||
option2: 'zz' | ||
}, | ||
{ | ||
option1: {ww: 'zz'}, | ||
option2: 'yy' | ||
}, | ||
{ | ||
schema: { | ||
option99: 'number' // << that's useless, so falls back to reference object | ||
} | ||
} | ||
) | ||
}) | ||
}) | ||
test('04.04 - opts.schema is set to a wrong thing - throws', t => { | ||
t.throws(function () { | ||
checkTypes( | ||
{ | ||
option1: {a: 'setting1'}, | ||
option2: null | ||
}, | ||
{ | ||
option1: 'zz', | ||
option2: 'yy' | ||
}, | ||
{ | ||
schema: 'zzz' | ||
} | ||
) | ||
}) | ||
t.throws(function () { | ||
checkTypes( | ||
{ | ||
option1: {a: 'setting1'}, | ||
option2: null | ||
}, | ||
{ | ||
option1: 'zz', | ||
option2: 'yy' | ||
}, | ||
{ | ||
schema: null | ||
} | ||
) | ||
}) | ||
}) |
Sorry, the diff of this file is not supported yet
Wildcard dependency
QualityPackage has a dependency with a floating version range. This can cause issues if the dependency publishes a new major version.
Found 4 instances in 1 package
37546
865
234
6
+ Addedlodash.intersection@*
+ Addedlodash.intersection@4.4.0(transitive)
- Removedlodash.isequal@^4.5.0
- Removedlodash.isequal@4.5.0(transitive)
Updatedlodash.clonedeep@*
Updatedlodash.pullall@*
Updatedobject-assign@*