@e22m4u/js-repository 0.1.9 → 0.1.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +46 -4
- package/docs/assets/navigation.js +1 -1
- package/docs/assets/search.js +1 -1
- package/docs/classes/Adapter.html +1 -1
- package/docs/classes/AdapterLoader.html +1 -1
- package/docs/classes/AdapterRegistry.html +1 -1
- package/docs/classes/BelongsToResolver.html +1 -1
- package/docs/classes/DatasourceDefinitionValidator.html +1 -1
- package/docs/classes/DefinitionRegistry.html +1 -1
- package/docs/classes/EmptyValuesDefiner.html +18 -0
- package/docs/classes/FieldsClauseTool.html +1 -1
- package/docs/classes/HasManyResolver.html +1 -1
- package/docs/classes/HasOneResolver.html +1 -1
- package/docs/classes/IncludeClauseTool.html +1 -1
- package/docs/classes/InvalidArgumentError.html +1 -1
- package/docs/classes/InvalidOperatorValueError.html +1 -1
- package/docs/classes/ModelDataSanitizer.html +1 -1
- package/docs/classes/ModelDataTransformer.html +1 -1
- package/docs/classes/ModelDataValidator.html +1 -1
- package/docs/classes/ModelDefinitionUtils.html +20 -18
- package/docs/classes/ModelDefinitionValidator.html +1 -1
- package/docs/classes/NotImplementedError.html +1 -1
- package/docs/classes/OperatorClauseTool.html +1 -1
- package/docs/classes/OrderClauseTool.html +1 -1
- package/docs/classes/PrimaryKeysDefinitionValidator.html +1 -1
- package/docs/classes/PropertiesDefinitionValidator.html +1 -1
- package/docs/classes/PropertyTransformerRegistry.html +1 -1
- package/docs/classes/PropertyUniquenessValidator.html +1 -1
- package/docs/classes/PropertyValidatorRegistry.html +1 -1
- package/docs/classes/ReferencesManyResolver.html +1 -1
- package/docs/classes/RelationsDefinitionValidator.html +1 -1
- package/docs/classes/Repository.html +1 -1
- package/docs/classes/RepositoryRegistry.html +1 -1
- package/docs/classes/Schema.html +1 -1
- package/docs/classes/SliceClauseTool.html +1 -1
- package/docs/classes/WhereClauseTool.html +1 -1
- package/docs/enums/DataType.html +1 -1
- package/docs/enums/DecoratorTargetType.html +1 -1
- package/docs/enums/RelationType.html +1 -1
- package/docs/functions/capitalize.html +1 -1
- package/docs/functions/cloneDeep.html +1 -1
- package/docs/functions/excludeObjectKeys.html +1 -1
- package/docs/functions/getCtorName.html +1 -1
- package/docs/functions/getDecoratorTargetType.html +1 -1
- package/docs/functions/getValueByPath.html +1 -1
- package/docs/functions/isCtor.html +1 -1
- package/docs/functions/isDeepEqual.html +2 -0
- package/docs/functions/isPureObject.html +1 -1
- package/docs/functions/selectObjectKeys.html +1 -1
- package/docs/functions/singularize.html +1 -1
- package/docs/functions/stringToRegexp.html +1 -1
- package/docs/index.html +62 -6
- package/docs/interfaces/AndClause.html +1 -1
- package/docs/interfaces/Constructor.html +1 -1
- package/docs/interfaces/OrClause.html +1 -1
- package/docs/modules.html +4 -1
- package/docs/types/AnyObject.html +1 -1
- package/docs/types/BelongsToDefinition.html +1 -1
- package/docs/types/CountMethod.html +1 -1
- package/docs/types/DEFAULT_PRIMARY_KEY_PROPERTY_NAME.html +1 -1
- package/docs/types/DatasourceDefinition.html +1 -1
- package/docs/types/FieldsClause.html +1 -1
- package/docs/types/FilterClause.html +1 -1
- package/docs/types/Flatten.html +1 -1
- package/docs/types/FullPropertyDefinition.html +1 -1
- package/docs/types/HasManyDefinition.html +1 -1
- package/docs/types/HasOneDefinition.html +1 -1
- package/docs/types/Identity.html +1 -1
- package/docs/types/IncludeClause.html +1 -1
- package/docs/types/ItemFilterClause.html +1 -1
- package/docs/types/ModelData.html +1 -1
- package/docs/types/ModelDefinition.html +1 -1
- package/docs/types/ModelId.html +1 -1
- package/docs/types/NestedIncludeClause.html +1 -1
- package/docs/types/NormalizedFieldsClause.html +1 -1
- package/docs/types/NormalizedIncludeClause.html +1 -1
- package/docs/types/OperatorClause.html +1 -1
- package/docs/types/OptionalUnlessRequiredId.html +1 -1
- package/docs/types/OrderClause.html +1 -1
- package/docs/types/PartialBy.html +1 -1
- package/docs/types/PartialWithoutId.html +1 -1
- package/docs/types/PolyBelongsToDefinition.html +1 -1
- package/docs/types/PolyHasManyDefinitionWithTargetKeys.html +1 -1
- package/docs/types/PolyHasManyDefinitionWithTargetRelationName.html +1 -1
- package/docs/types/PolyHasOneDefinitionWithTargetKeys.html +1 -1
- package/docs/types/PolyHasOneDefinitionWithTargetRelationName.html +1 -1
- package/docs/types/PropertiesClause.html +1 -1
- package/docs/types/PropertyDefinition.html +1 -1
- package/docs/types/PropertyDefinitionMap.html +1 -1
- package/docs/types/PropertyTransformOptions.html +1 -1
- package/docs/types/PropertyTransformer.html +1 -1
- package/docs/types/PropertyTransformerContext.html +1 -1
- package/docs/types/PropertyUniqueness.html +2 -0
- package/docs/types/PropertyValidateOptions.html +1 -1
- package/docs/types/PropertyValidator.html +1 -1
- package/docs/types/PropertyValidatorContext.html +1 -1
- package/docs/types/ReferencesManyDefinition.html +1 -1
- package/docs/types/RelationDefinition.html +1 -1
- package/docs/types/RelationDefinitionMap.html +1 -1
- package/docs/types/WhereClause.html +1 -1
- package/docs/types/WithoutId.html +1 -1
- package/package.json +1 -1
- package/src/definition/model/model-data-transformer.js +16 -9
- package/src/definition/model/model-data-transformer.spec.js +21 -27
- package/src/definition/model/model-data-validator.js +21 -8
- package/src/definition/model/model-data-validator.spec.js +97 -50
- package/src/definition/model/model-definition-utils.d.ts +8 -0
- package/src/definition/model/model-definition-utils.js +38 -2
- package/src/definition/model/model-definition-utils.spec.js +82 -0
- package/src/definition/model/properties/empty-values-definer.d.ts +23 -0
- package/src/definition/model/properties/empty-values-definer.js +66 -0
- package/src/definition/model/properties/empty-values-definer.spec.js +96 -0
- package/src/definition/model/properties/index.d.ts +2 -0
- package/src/definition/model/properties/index.js +2 -0
- package/src/definition/model/properties/properties-definition-validator.js +8 -2
- package/src/definition/model/properties/properties-definition-validator.spec.js +10 -6
- package/src/definition/model/properties/property-uniqueness-validator.js +10 -0
- package/src/definition/model/properties/property-uniqueness-validator.spec.js +44 -0
- package/src/definition/model/properties/property-uniqueness.d.ts +8 -0
- package/src/definition/model/properties/property-uniqueness.js +8 -0
- package/src/utils/index.d.ts +1 -0
- package/src/utils/index.js +1 -0
- package/src/utils/is-deep-equal.d.ts +10 -0
- package/src/utils/is-deep-equal.js +71 -0
- package/src/utils/is-deep-equal.spec.js +238 -0
|
@@ -2,6 +2,7 @@ import chai from 'chai';
|
|
|
2
2
|
import {expect} from 'chai';
|
|
3
3
|
import {DataType} from './data-type.js';
|
|
4
4
|
import {format} from '@e22m4u/js-format';
|
|
5
|
+
import {PropertyUniqueness} from './property-uniqueness.js';
|
|
5
6
|
import {PropertyValidatorRegistry} from './property-validator/index.js';
|
|
6
7
|
import {PropertyTransformerRegistry} from './property-transformer/index.js';
|
|
7
8
|
import {PropertiesDefinitionValidator} from './properties-definition-validator.js';
|
|
@@ -490,7 +491,7 @@ describe('PropertiesDefinitionValidator', function () {
|
|
|
490
491
|
validate({myTransformer: true})();
|
|
491
492
|
});
|
|
492
493
|
|
|
493
|
-
it('expects provided the option "unique" to be
|
|
494
|
+
it('expects provided the option "unique" to be the PropertyUniqueness', function () {
|
|
494
495
|
const validate = v => {
|
|
495
496
|
const foo = {
|
|
496
497
|
type: DataType.STRING,
|
|
@@ -501,18 +502,20 @@ describe('PropertiesDefinitionValidator', function () {
|
|
|
501
502
|
const error = v =>
|
|
502
503
|
format(
|
|
503
504
|
'The provided option "unique" of the property "foo" in the model "model" ' +
|
|
504
|
-
'should be
|
|
505
|
+
'should be one of values: %l, but %s given.',
|
|
506
|
+
Object.values(PropertyUniqueness),
|
|
505
507
|
v,
|
|
506
508
|
);
|
|
507
509
|
expect(validate('str')).to.throw(error('"str"'));
|
|
508
510
|
expect(validate(10)).to.throw(error('10'));
|
|
509
511
|
expect(validate([])).to.throw(error('Array'));
|
|
510
512
|
expect(validate({})).to.throw(error('Object'));
|
|
511
|
-
validate(
|
|
512
|
-
validate(
|
|
513
|
+
validate(PropertyUniqueness.UNIQUE)();
|
|
514
|
+
validate(PropertyUniqueness.SPARSE)();
|
|
515
|
+
validate(PropertyUniqueness.NON_UNIQUE)();
|
|
513
516
|
});
|
|
514
517
|
|
|
515
|
-
it('expects the primary key should not have the option "unique"
|
|
518
|
+
it('expects the primary key should not have the option "unique"', function () {
|
|
516
519
|
const validate = v => () => {
|
|
517
520
|
const foo = {
|
|
518
521
|
type: DataType.ANY,
|
|
@@ -525,7 +528,8 @@ describe('PropertiesDefinitionValidator', function () {
|
|
|
525
528
|
'The property "foo" of the model "model" is a primary key, ' +
|
|
526
529
|
'so it should not have the option "unique" to be provided.',
|
|
527
530
|
);
|
|
528
|
-
expect(validate(
|
|
531
|
+
expect(validate(PropertyUniqueness.UNIQUE)).to.throw(error);
|
|
532
|
+
expect(validate(PropertyUniqueness.SPARSE)).to.throw(error);
|
|
529
533
|
validate(false)();
|
|
530
534
|
validate(undefined)();
|
|
531
535
|
});
|
|
@@ -1,5 +1,8 @@
|
|
|
1
|
+
import {DataType} from './data-type.js';
|
|
1
2
|
import {Service} from '@e22m4u/js-service';
|
|
2
3
|
import {isPureObject} from '../../../utils/index.js';
|
|
4
|
+
import {PropertyUniqueness} from './property-uniqueness.js';
|
|
5
|
+
import {EmptyValuesDefiner} from './empty-values-definer.js';
|
|
3
6
|
import {InvalidArgumentError} from '../../../errors/index.js';
|
|
4
7
|
import {ModelDefinitionUtils} from '../model-definition-utils.js';
|
|
5
8
|
|
|
@@ -67,10 +70,17 @@ export class PropertyUniquenessValidator extends Service {
|
|
|
67
70
|
propValue,
|
|
68
71
|
);
|
|
69
72
|
let willBeReplaced = undefined;
|
|
73
|
+
const emptyValuesDefiner = this.getService(EmptyValuesDefiner);
|
|
70
74
|
for (const propName of propNames) {
|
|
71
75
|
const propDef = propDefs[propName];
|
|
72
76
|
if (!propDef || typeof propDef === 'string' || !propDef.unique) continue;
|
|
77
|
+
// sparse
|
|
73
78
|
const propValue = modelData[propName];
|
|
79
|
+
if (propDef.unique === PropertyUniqueness.SPARSE) {
|
|
80
|
+
const propType = propDef.type || DataType.ANY;
|
|
81
|
+
const isEmpty = emptyValuesDefiner.isEmpty(propType, propValue);
|
|
82
|
+
if (isEmpty) continue;
|
|
83
|
+
}
|
|
74
84
|
// create
|
|
75
85
|
if (methodName === 'create') {
|
|
76
86
|
const count = await countMethod({[propName]: propValue});
|
|
@@ -2,6 +2,8 @@ import {expect} from 'chai';
|
|
|
2
2
|
import {DataType} from './data-type.js';
|
|
3
3
|
import {format} from '@e22m4u/js-format';
|
|
4
4
|
import {Schema} from '../../../schema.js';
|
|
5
|
+
import {PropertyUniqueness} from './property-uniqueness.js';
|
|
6
|
+
import {EmptyValuesDefiner} from './empty-values-definer.js';
|
|
5
7
|
import {PropertyUniquenessValidator} from './property-uniqueness-validator.js';
|
|
6
8
|
import {DEFAULT_PRIMARY_KEY_PROPERTY_NAME as DEF_PK} from '../model-definition-utils.js';
|
|
7
9
|
|
|
@@ -185,6 +187,48 @@ describe('PropertyUniquenessValidator', function () {
|
|
|
185
187
|
);
|
|
186
188
|
});
|
|
187
189
|
|
|
190
|
+
it('skips uniqueness checking for an empty value for "sparse" mode', async function () {
|
|
191
|
+
const schema = new Schema();
|
|
192
|
+
schema.defineModel({
|
|
193
|
+
name: 'model',
|
|
194
|
+
properties: {
|
|
195
|
+
foo: {
|
|
196
|
+
type: DataType.STRING,
|
|
197
|
+
unique: true,
|
|
198
|
+
},
|
|
199
|
+
bar: {
|
|
200
|
+
type: DataType.STRING,
|
|
201
|
+
unique: PropertyUniqueness.SPARSE,
|
|
202
|
+
},
|
|
203
|
+
baz: {
|
|
204
|
+
type: DataType.STRING,
|
|
205
|
+
unique: true,
|
|
206
|
+
},
|
|
207
|
+
},
|
|
208
|
+
});
|
|
209
|
+
const S = schema.getService(PropertyUniquenessValidator);
|
|
210
|
+
let invoked = 0;
|
|
211
|
+
schema
|
|
212
|
+
.getService(EmptyValuesDefiner)
|
|
213
|
+
.setEmptyValuesOf(DataType.STRING, ['val2']);
|
|
214
|
+
const modelData = {
|
|
215
|
+
foo: 'val1',
|
|
216
|
+
bar: 'val2',
|
|
217
|
+
baz: 'val3',
|
|
218
|
+
};
|
|
219
|
+
const countMethod = where => {
|
|
220
|
+
invoked++;
|
|
221
|
+
if (invoked === 1) {
|
|
222
|
+
expect(where).to.be.eql({foo: 'val1'});
|
|
223
|
+
} else if (invoked === 2) {
|
|
224
|
+
expect(where).to.be.eql({baz: 'val3'});
|
|
225
|
+
}
|
|
226
|
+
return 0;
|
|
227
|
+
};
|
|
228
|
+
await S.validate(countMethod, 'create', 'model', modelData);
|
|
229
|
+
expect(invoked).to.be.eql(2);
|
|
230
|
+
});
|
|
231
|
+
|
|
188
232
|
describe('create', function () {
|
|
189
233
|
it('throws an error if the "countMethod" returns a positive number', async function () {
|
|
190
234
|
const schema = new Schema();
|
package/src/utils/index.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ export * from './is-ctor.js';
|
|
|
2
2
|
export * from './capitalize.js';
|
|
3
3
|
export * from './clone-deep.js';
|
|
4
4
|
export * from './singularize.js';
|
|
5
|
+
export * from './is-deep-equal.js';
|
|
5
6
|
export * from './get-ctor-name.js';
|
|
6
7
|
export * from './is-pure-object.js';
|
|
7
8
|
export * from './string-to-regexp.js';
|
package/src/utils/index.js
CHANGED
|
@@ -2,6 +2,7 @@ export * from './is-ctor.js';
|
|
|
2
2
|
export * from './capitalize.js';
|
|
3
3
|
export * from './clone-deep.js';
|
|
4
4
|
export * from './singularize.js';
|
|
5
|
+
export * from './is-deep-equal.js';
|
|
5
6
|
export * from './get-ctor-name.js';
|
|
6
7
|
export * from './is-pure-object.js';
|
|
7
8
|
export * from './string-to-regexp.js';
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Is deep equal.
|
|
3
|
+
* https://github.com/pinglu85/BFEdevSolutions/blob/main/Coding-Problems/69.implement-deep-equal-isEqual.md
|
|
4
|
+
*
|
|
5
|
+
* @param {*} firstValue
|
|
6
|
+
* @param {*} secondValue
|
|
7
|
+
* @returns {boolean}
|
|
8
|
+
*/
|
|
9
|
+
export function isDeepEqual(firstValue, secondValue) {
|
|
10
|
+
const cached = new WeakMap();
|
|
11
|
+
const compare = (a, b) => {
|
|
12
|
+
// Check if one of the two inputs is primitive by using typeof
|
|
13
|
+
// operator; since the typeof primitive null is object, check
|
|
14
|
+
// if one of the inputs is equal to null. If one of the two
|
|
15
|
+
// inputs is primitive, then I can compare them by reference.
|
|
16
|
+
if (a === null || b === null) return a === b;
|
|
17
|
+
if (typeof a !== 'object' || typeof b !== 'object') return a === b;
|
|
18
|
+
// Check if the data type of the two inputs are the same,
|
|
19
|
+
// both are arrays or objects. If they are not, return false.
|
|
20
|
+
const dataTypeA = Array.isArray(a) ? 'array' : 'object';
|
|
21
|
+
const dataTypeB = Array.isArray(b) ? 'array' : 'object';
|
|
22
|
+
if (dataTypeA !== dataTypeB) return false;
|
|
23
|
+
// Use Object.keys and Object.getOwnPropertySymbols to get
|
|
24
|
+
// all of enumerable and not-inherited properties of the two
|
|
25
|
+
// inputs. Compare their size respectively, if one of them
|
|
26
|
+
// is not equal, return false.
|
|
27
|
+
const keysA = Object.keys(a);
|
|
28
|
+
const keysB = Object.keys(b);
|
|
29
|
+
if (keysA.length !== keysB.length) return false;
|
|
30
|
+
const symbolsA = Object.getOwnPropertySymbols(a);
|
|
31
|
+
const symbolsB = Object.getOwnPropertySymbols(b);
|
|
32
|
+
if (symbolsA.length !== symbolsB.length) return false;
|
|
33
|
+
// To handle the circular reference, initialize a WeakMap
|
|
34
|
+
// that is going to keep track of the objects or arrays
|
|
35
|
+
// that have been seen, in which each key is an object
|
|
36
|
+
// or an array and each value is a set of objects or arrays,
|
|
37
|
+
// that have been compared to that object or array.
|
|
38
|
+
let setForA = cached.get(a);
|
|
39
|
+
if (setForA == null) {
|
|
40
|
+
setForA = new Set();
|
|
41
|
+
cached.set(a, setForA);
|
|
42
|
+
} else if (setForA.has(b)) {
|
|
43
|
+
return true;
|
|
44
|
+
}
|
|
45
|
+
setForA.add(b);
|
|
46
|
+
let setForB = cached.get(b);
|
|
47
|
+
if (setForB == null) {
|
|
48
|
+
setForB = new Set();
|
|
49
|
+
cached.set(b, setForB);
|
|
50
|
+
} else if (setForB.has(a)) {
|
|
51
|
+
return true;
|
|
52
|
+
}
|
|
53
|
+
setForB.add(a);
|
|
54
|
+
// Compare the property names and the values. Loop through
|
|
55
|
+
// all the properties of the first input data, check if
|
|
56
|
+
// the property name also exist in the second input data,
|
|
57
|
+
// if not, return false; otherwise recursively compare
|
|
58
|
+
// the property value.
|
|
59
|
+
const propertyNamesA = [...keysA, ...symbolsA];
|
|
60
|
+
for (const propertyNameA of propertyNamesA) {
|
|
61
|
+
if (!b.hasOwnProperty(propertyNameA)) return false;
|
|
62
|
+
const propertyValueA = a[propertyNameA];
|
|
63
|
+
const propertyValueB = b[propertyNameA];
|
|
64
|
+
if (!compare(propertyValueA, propertyValueB)) return false;
|
|
65
|
+
}
|
|
66
|
+
// If we get out of the loop without
|
|
67
|
+
// returning false, return true.
|
|
68
|
+
return true;
|
|
69
|
+
};
|
|
70
|
+
return compare(firstValue, secondValue);
|
|
71
|
+
}
|
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
import {expect} from 'chai';
|
|
2
|
+
import {isDeepEqual} from './is-deep-equal.js';
|
|
3
|
+
|
|
4
|
+
const check = (a, b, expected) => {
|
|
5
|
+
expect(isDeepEqual(a, b)).to.be.eq(expected);
|
|
6
|
+
expect(isDeepEqual(b, a)).to.be.eq(expected);
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
describe('isDeepEqual', function () {
|
|
10
|
+
describe('string', function () {
|
|
11
|
+
it('a non-empty string', function () {
|
|
12
|
+
check('str', 'str', true);
|
|
13
|
+
check('str', '', false);
|
|
14
|
+
check('str', 10, false);
|
|
15
|
+
check('str', 0, false);
|
|
16
|
+
check('str', -10, false);
|
|
17
|
+
check('str', true, false);
|
|
18
|
+
check('str', false, false);
|
|
19
|
+
check('str', undefined, false);
|
|
20
|
+
check('str', null, false);
|
|
21
|
+
check('str', {foo: 'bar'}, false);
|
|
22
|
+
check('str', {}, false);
|
|
23
|
+
check('str', [1, 2, 3], false);
|
|
24
|
+
check('str', [], false);
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
it('an empty string', function () {
|
|
28
|
+
check('', 'str', false);
|
|
29
|
+
check('', '', true);
|
|
30
|
+
check('', 10, false);
|
|
31
|
+
check('', 0, false);
|
|
32
|
+
check('', -10, false);
|
|
33
|
+
check('', true, false);
|
|
34
|
+
check('', false, false);
|
|
35
|
+
check('', undefined, false);
|
|
36
|
+
check('', null, false);
|
|
37
|
+
check('', {foo: 'bar'}, false);
|
|
38
|
+
check('', {}, false);
|
|
39
|
+
check('', [1, 2, 3], false);
|
|
40
|
+
check('', [], false);
|
|
41
|
+
});
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
describe('number', function () {
|
|
45
|
+
it('a positive number', function () {
|
|
46
|
+
check(10, 'str', false);
|
|
47
|
+
check(10, '', false);
|
|
48
|
+
check(10, 10, true);
|
|
49
|
+
check(10, 0, false);
|
|
50
|
+
check(10, -10, false);
|
|
51
|
+
check(10, true, false);
|
|
52
|
+
check(10, false, false);
|
|
53
|
+
check(10, undefined, false);
|
|
54
|
+
check(10, null, false);
|
|
55
|
+
check(10, {foo: 'bar'}, false);
|
|
56
|
+
check(10, {}, false);
|
|
57
|
+
check(10, [1, 2, 3], false);
|
|
58
|
+
check(10, [], false);
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
it('zero', function () {
|
|
62
|
+
check(0, 'str', false);
|
|
63
|
+
check(0, '', false);
|
|
64
|
+
check(0, 10, false);
|
|
65
|
+
check(0, 0, true);
|
|
66
|
+
check(0, -10, false);
|
|
67
|
+
check(0, true, false);
|
|
68
|
+
check(0, false, false);
|
|
69
|
+
check(0, undefined, false);
|
|
70
|
+
check(0, null, false);
|
|
71
|
+
check(0, {foo: 'bar'}, false);
|
|
72
|
+
check(0, {}, false);
|
|
73
|
+
check(0, [1, 2, 3], false);
|
|
74
|
+
check(0, [], false);
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
it('a negative number', function () {
|
|
78
|
+
check(-10, 'str', false);
|
|
79
|
+
check(-10, '', false);
|
|
80
|
+
check(-10, 10, false);
|
|
81
|
+
check(-10, 0, false);
|
|
82
|
+
check(-10, -10, true);
|
|
83
|
+
check(-10, true, false);
|
|
84
|
+
check(-10, false, false);
|
|
85
|
+
check(-10, undefined, false);
|
|
86
|
+
check(-10, null, false);
|
|
87
|
+
check(-10, {foo: 'bar'}, false);
|
|
88
|
+
check(-10, {}, false);
|
|
89
|
+
check(-10, [1, 2, 3], false);
|
|
90
|
+
check(-10, [], false);
|
|
91
|
+
});
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
describe('boolean', function () {
|
|
95
|
+
it('true', function () {
|
|
96
|
+
check(true, 'str', false);
|
|
97
|
+
check(true, '', false);
|
|
98
|
+
check(true, 10, false);
|
|
99
|
+
check(true, 0, false);
|
|
100
|
+
check(true, -10, false);
|
|
101
|
+
check(true, true, true);
|
|
102
|
+
check(true, false, false);
|
|
103
|
+
check(true, undefined, false);
|
|
104
|
+
check(true, null, false);
|
|
105
|
+
check(true, {foo: 'bar'}, false);
|
|
106
|
+
check(true, {}, false);
|
|
107
|
+
check(true, [1, 2, 3], false);
|
|
108
|
+
check(true, [], false);
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
it('false', function () {
|
|
112
|
+
check(false, 'str', false);
|
|
113
|
+
check(false, '', false);
|
|
114
|
+
check(false, 10, false);
|
|
115
|
+
check(false, 0, false);
|
|
116
|
+
check(false, -10, false);
|
|
117
|
+
check(false, true, false);
|
|
118
|
+
check(false, false, true);
|
|
119
|
+
check(false, undefined, false);
|
|
120
|
+
check(false, null, false);
|
|
121
|
+
check(false, {foo: 'bar'}, false);
|
|
122
|
+
check(false, {}, false);
|
|
123
|
+
check(false, [1, 2, 3], false);
|
|
124
|
+
check(false, [], false);
|
|
125
|
+
});
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
describe('array', function () {
|
|
129
|
+
it('an array of numbers', function () {
|
|
130
|
+
check([1, 2, 3], 'str', false);
|
|
131
|
+
check([1, 2, 3], '', false);
|
|
132
|
+
check([1, 2, 3], 10, false);
|
|
133
|
+
check([1, 2, 3], 0, false);
|
|
134
|
+
check([1, 2, 3], -10, false);
|
|
135
|
+
check([1, 2, 3], true, false);
|
|
136
|
+
check([1, 2, 3], false, false);
|
|
137
|
+
check([1, 2, 3], undefined, false);
|
|
138
|
+
check([1, 2, 3], null, false);
|
|
139
|
+
check([1, 2, 3], {foo: 'bar'}, false);
|
|
140
|
+
check([1, 2, 3], {}, false);
|
|
141
|
+
check([1, 2, 3], [1, 2, 3], true);
|
|
142
|
+
check([1, 2, 3], [], false);
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
it('an empty array', function () {
|
|
146
|
+
check([], 'str', false);
|
|
147
|
+
check([], '', false);
|
|
148
|
+
check([], 10, false);
|
|
149
|
+
check([], 0, false);
|
|
150
|
+
check([], -10, false);
|
|
151
|
+
check([], true, false);
|
|
152
|
+
check([], false, false);
|
|
153
|
+
check([], undefined, false);
|
|
154
|
+
check([], null, false);
|
|
155
|
+
check([], {foo: 'bar'}, false);
|
|
156
|
+
check([], {}, false);
|
|
157
|
+
check([], [1, 2, 3], false);
|
|
158
|
+
check([], [], true);
|
|
159
|
+
});
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
describe('object', function () {
|
|
163
|
+
it('string key and string value', function () {
|
|
164
|
+
check({foo: 'bar'}, 'str', false);
|
|
165
|
+
check({foo: 'bar'}, '', false);
|
|
166
|
+
check({foo: 'bar'}, 10, false);
|
|
167
|
+
check({foo: 'bar'}, 0, false);
|
|
168
|
+
check({foo: 'bar'}, -10, false);
|
|
169
|
+
check({foo: 'bar'}, true, false);
|
|
170
|
+
check({foo: 'bar'}, false, false);
|
|
171
|
+
check({foo: 'bar'}, undefined, false);
|
|
172
|
+
check({foo: 'bar'}, null, false);
|
|
173
|
+
check({foo: 'bar'}, {foo: 'bar'}, true);
|
|
174
|
+
check({foo: 'bar'}, {}, false);
|
|
175
|
+
check({foo: 'bar'}, [1, 2, 3], false);
|
|
176
|
+
check({foo: 'bar'}, [], false);
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
it('an empty object', function () {
|
|
180
|
+
check({}, 'str', false);
|
|
181
|
+
check({}, '', false);
|
|
182
|
+
check({}, 10, false);
|
|
183
|
+
check({}, 0, false);
|
|
184
|
+
check({}, -10, false);
|
|
185
|
+
check({}, true, false);
|
|
186
|
+
check({}, false, false);
|
|
187
|
+
check({}, undefined, false);
|
|
188
|
+
check({}, null, false);
|
|
189
|
+
check({}, {foo: 'bar'}, false);
|
|
190
|
+
check({}, {}, true);
|
|
191
|
+
check({}, [1, 2, 3], false);
|
|
192
|
+
check({}, [], false);
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
it('null', function () {
|
|
196
|
+
check(null, 'str', false);
|
|
197
|
+
check(null, '', false);
|
|
198
|
+
check(null, 10, false);
|
|
199
|
+
check(null, 0, false);
|
|
200
|
+
check(null, -10, false);
|
|
201
|
+
check(null, true, false);
|
|
202
|
+
check(null, false, false);
|
|
203
|
+
check(null, undefined, false);
|
|
204
|
+
check(null, null, true);
|
|
205
|
+
check(null, {foo: 'bar'}, false);
|
|
206
|
+
check(null, {}, false);
|
|
207
|
+
check(null, [1, 2, 3], false);
|
|
208
|
+
check(null, [], false);
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
it('circular reference to itself', function () {
|
|
212
|
+
const a = {foo: 'bar'};
|
|
213
|
+
const b = {baz: 'qux'};
|
|
214
|
+
const c = {foo: 'bar'};
|
|
215
|
+
a.itself = a;
|
|
216
|
+
b.itself = b;
|
|
217
|
+
c.itself = c;
|
|
218
|
+
check(a, b, false);
|
|
219
|
+
check(a, c, true);
|
|
220
|
+
});
|
|
221
|
+
});
|
|
222
|
+
|
|
223
|
+
it('undefined', function () {
|
|
224
|
+
check(undefined, 'str', false);
|
|
225
|
+
check(undefined, '', false);
|
|
226
|
+
check(undefined, 10, false);
|
|
227
|
+
check(undefined, 0, false);
|
|
228
|
+
check(undefined, -10, false);
|
|
229
|
+
check(undefined, true, false);
|
|
230
|
+
check(undefined, false, false);
|
|
231
|
+
check(undefined, undefined, true);
|
|
232
|
+
check(undefined, null, false);
|
|
233
|
+
check(undefined, {foo: 'bar'}, false);
|
|
234
|
+
check(undefined, {}, false);
|
|
235
|
+
check(undefined, [1, 2, 3], false);
|
|
236
|
+
check(undefined, [], false);
|
|
237
|
+
});
|
|
238
|
+
});
|