diff --git a/source/index.ts b/source/index.ts index 5e52b42..e38d412 100644 --- a/source/index.ts +++ b/source/index.ts @@ -7,6 +7,7 @@ import {ArrayPredicate} from './lib/predicates/array'; import {DatePredicate} from './lib/predicates/date'; import {ErrorPredicate} from './lib/predicates/error'; import {MapPredicate} from './lib/predicates/map'; +import {WeakMapPredicate} from './lib/predicates/weak-map'; import {SetPredicate} from './lib/predicates/set'; import {WeakSetPredicate} from './lib/predicates/weak-set'; @@ -71,6 +72,10 @@ export interface Ow { * Test the value to be a Map. */ readonly map: MapPredicate; + /** + * Test the value to be a WeakMap. + */ + readonly weakMap: WeakMapPredicate; /** * Test the value to be a Set. */ @@ -198,6 +203,9 @@ Object.defineProperties(main, { map: { get: () => new MapPredicate() }, + weakMap: { + get: () => new WeakMapPredicate() + }, set: { get: () => new SetPredicate() }, diff --git a/source/lib/predicates/weak-map.ts b/source/lib/predicates/weak-map.ts new file mode 100644 index 0000000..4eac696 --- /dev/null +++ b/source/lib/predicates/weak-map.ts @@ -0,0 +1,47 @@ +import {Predicate, Context} from './predicate'; + +export class WeakMapPredicate extends Predicate> { + constructor(context?: Context) { + super('weakMap', context); + } + + /** + * Test a WeakMap to include all the provided keys. The keys are tested by identity, not structure. + * + * @param keys The keys that should be a key in the WeakMap. + */ + hasKeys(...keys: any[]) { + const missingKeys: any[] = []; + + return this.addValidator({ + message: () => `Expected WeakMap to have keys \`${JSON.stringify(missingKeys)}\``, + validator: map => { + for (const key of keys) { + if (map.has(key)) { + continue; + } + + missingKeys.push(key); + + if (missingKeys.length === 5) { + return false; + } + } + + return missingKeys.length === 0; + } + }); + } + + /** + * Test a WeakMap to include any of the provided keys. The keys are tested by identity, not structure. + * + * @param keys The keys that could be a key in the WeakMap. + */ + hasAnyKeys(...keys: any[]) { + return this.addValidator({ + message: () => `Expected WeakMap to have any key of \`${JSON.stringify(keys)}\``, + validator: map => keys.some(key => map.has(key)) + }); + } +} diff --git a/source/test/weak-map.ts b/source/test/weak-map.ts new file mode 100644 index 0000000..50bbfc8 --- /dev/null +++ b/source/test/weak-map.ts @@ -0,0 +1,30 @@ +import test from 'ava'; +import m from '..'; + +test('weakMap', t => { + t.notThrows(() => m(new WeakMap(), m.weakMap)); + t.notThrows(() => m(new WeakMap([[{foo: 'bar'}, '🦄']]), m.weakMap)); + t.throws(() => m(12 as any, m.weakMap), 'Expected argument to be of type `weakMap` but received type `number`'); +}); + +test('weakMap.hasKeys', t => { + const unicorn: any = {unicorn: true}; + const rainbow: any = {rainbow: true}; + const keys = [{x: 1}, {x: 2}, {x: 3}, {x: 4}, {x: 5}, {x: 6}, {x: 7}, {x: 8}, {x: 9}, {x: 10}]; + + t.notThrows(() => m(new WeakMap([[unicorn, '🦄']]), m.weakMap.hasKeys(unicorn))); + t.throws(() => m(new WeakMap([[{rainbow: true}, '🌈']]), m.weakMap.hasKeys({rainbow: true})), 'Expected WeakMap to have keys `[{"rainbow":true}]`'); + t.throws(() => m(new WeakMap([[unicorn, '🦄'], [rainbow, '🌈']]), m.weakMap.hasKeys(unicorn, {rainbow: true})), 'Expected WeakMap to have keys `[{"rainbow":true}]`'); + t.throws(() => m(new WeakMap([[keys[0], 1], [keys[2], 3]]), m.weakMap.hasKeys(...keys)), 'Expected WeakMap to have keys `[{"x":2},{"x":4},{"x":5},{"x":6},{"x":7}]`'); +}); + +test('weakMap.hasAnyKeys', t => { + const unicorn: any = {unicorn: true}; + const rainbow: any = {rainbow: true}; + const rocket: any = {rocket: true}; + + t.notThrows(() => m(new WeakMap([[unicorn, '🦄']]), m.weakMap.hasAnyKeys(unicorn, rainbow))); + t.notThrows(() => m(new WeakMap([[unicorn, '🦄'], [rainbow, '🌈']]), m.weakMap.hasAnyKeys(unicorn))); + t.notThrows(() => m(new WeakMap([[unicorn, '🦄'], [rainbow, '🌈']]), m.weakMap.hasAnyKeys(unicorn, rainbow, rocket))); + t.throws(() => m(new WeakMap([[unicorn, '🦄'], [rainbow, '🌈']]), m.weakMap.hasAnyKeys(rocket)), 'Expected WeakMap to have any key of `[{"rocket":true}]`'); +});