mirror of https://github.com/lukechilds/ow.git
Sam Verschueren
7 years ago
committed by
Sindre Sorhus
3 changed files with 310 additions and 0 deletions
@ -0,0 +1,215 @@ |
|||||
|
import * as isEqual from 'lodash.isequal'; |
||||
|
import ow from '../..'; |
||||
|
import {Predicate, Context} from './predicate'; |
||||
|
|
||||
|
export class MapPredicate extends Predicate<Map<any, any>> { |
||||
|
constructor(context?: Context) { |
||||
|
super('map', context); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Test a Map to have a specific size. |
||||
|
* |
||||
|
* @param size The size of the Map. |
||||
|
*/ |
||||
|
size(size: number) { |
||||
|
return this.addValidator({ |
||||
|
message: map => `Expected Map to have size \`${size}\`, got \`${map.size}\``, |
||||
|
validator: map => map.size === size |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Test an Map to have a minimum size. |
||||
|
* |
||||
|
* @param size The minimum size of the Map. |
||||
|
*/ |
||||
|
minSize(size: number) { |
||||
|
return this.addValidator({ |
||||
|
message: map => `Expected Map to have a minimum size of \`${size}\`, got \`${map.size}\``, |
||||
|
validator: map => map.size >= size |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Test an Map to have a maximum size. |
||||
|
* |
||||
|
* @param size The maximum size of the Map. |
||||
|
*/ |
||||
|
maxSize(size: number) { |
||||
|
return this.addValidator({ |
||||
|
message: map => `Expected Map to have a maximum size of \`${size}\`, got \`${map.size}\``, |
||||
|
validator: map => map.size <= size |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Test a Map 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 Map. |
||||
|
*/ |
||||
|
hasKeys(...keys: any[]) { |
||||
|
const missingKeys: any[] = []; |
||||
|
|
||||
|
return this.addValidator({ |
||||
|
message: () => `Expected Map 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 Map 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 Map. |
||||
|
*/ |
||||
|
hasAnyKeys(...keys: any[]) { |
||||
|
return this.addValidator({ |
||||
|
message: () => `Expected Map to have any key of \`${JSON.stringify(keys)}\``, |
||||
|
validator: map => keys.some(key => map.has(key)) |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Test a Map to include all the provided values. The values are tested by identity, not structure. |
||||
|
* |
||||
|
* @param values The values that should be a value in the Map. |
||||
|
*/ |
||||
|
hasValues(...values: any[]) { |
||||
|
const missingValues: any[] = []; |
||||
|
|
||||
|
return this.addValidator({ |
||||
|
message: () => `Expected Map to have values \`${JSON.stringify(missingValues)}\``, |
||||
|
validator: map => { |
||||
|
const valueSet = new Set(map.values()); |
||||
|
|
||||
|
for (const value of values) { |
||||
|
if (valueSet.has(value)) { |
||||
|
continue; |
||||
|
} |
||||
|
|
||||
|
missingValues.push(value); |
||||
|
|
||||
|
if (missingValues.length === 5) { |
||||
|
return false; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return missingValues.length === 0; |
||||
|
} |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Test a Map to include any of the provided values. The values are tested by identity, not structure. |
||||
|
* |
||||
|
* @param values The values that could be a value in the Map. |
||||
|
*/ |
||||
|
hasAnyValues(...values: any[]) { |
||||
|
return this.addValidator({ |
||||
|
message: () => `Expected Map to have any value of \`${JSON.stringify(values)}\``, |
||||
|
validator: map => { |
||||
|
const valueSet = new Set(map.values()); |
||||
|
|
||||
|
return values.some(key => valueSet.has(key)); |
||||
|
} |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Test all the keys in the Map to match the provided predicate. |
||||
|
* |
||||
|
* @param predicate The predicate that should be applied against every key in the Map. |
||||
|
*/ |
||||
|
keysOfType<T>(predicate: Predicate<T>) { |
||||
|
let error: string; |
||||
|
|
||||
|
return this.addValidator({ |
||||
|
message: () => error, |
||||
|
validator: map => { |
||||
|
try { |
||||
|
for (const item of map.keys()) { |
||||
|
ow(item, predicate); |
||||
|
} |
||||
|
|
||||
|
return true; |
||||
|
} catch (err) { |
||||
|
error = err.message; |
||||
|
|
||||
|
return false; |
||||
|
} |
||||
|
} |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Test all the values in the Map to match the provided predicate. |
||||
|
* |
||||
|
* @param predicate The predicate that should be applied against every value in the Map. |
||||
|
*/ |
||||
|
valuesOfType<T>(predicate: Predicate<T>) { |
||||
|
let error: string; |
||||
|
|
||||
|
return this.addValidator({ |
||||
|
message: () => error, |
||||
|
validator: map => { |
||||
|
try { |
||||
|
for (const item of map.values()) { |
||||
|
ow(item, predicate); |
||||
|
} |
||||
|
|
||||
|
return true; |
||||
|
} catch (err) { |
||||
|
error = err.message; |
||||
|
|
||||
|
return false; |
||||
|
} |
||||
|
} |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Test a Map to be empty. |
||||
|
*/ |
||||
|
get empty() { |
||||
|
return this.addValidator({ |
||||
|
message: map => `Expected Map to be empty, got \`${JSON.stringify(Array.from(map))}\``, |
||||
|
validator: map => map.size === 0 |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Test a Map to be not empty. |
||||
|
*/ |
||||
|
get nonEmpty() { |
||||
|
return this.addValidator({ |
||||
|
message: () => 'Expected Map to not be empty', |
||||
|
validator: map => map.size > 0 |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Test a Map to be deeply equal to the provided Map. |
||||
|
* |
||||
|
* @param expected Expected Map to match. |
||||
|
*/ |
||||
|
deepEqual(expected: Map<any, any>) { |
||||
|
return this.addValidator({ |
||||
|
message: map => `Expected Map to be deeply equal to \`${JSON.stringify(Array.from(expected))}\`, got \`${JSON.stringify(Array.from(map))}\``, |
||||
|
validator: map => isEqual(map, expected) |
||||
|
}); |
||||
|
} |
||||
|
} |
@ -0,0 +1,87 @@ |
|||||
|
import test from 'ava'; |
||||
|
import m from '..'; |
||||
|
|
||||
|
test('map', t => { |
||||
|
t.notThrows(() => m(new Map(), m.map)); |
||||
|
t.notThrows(() => m(new Map([['unicorn', '🦄']]), m.map)); |
||||
|
t.throws(() => m(12 as any, m.map), 'Expected argument to be of type `map` but received type `number`'); |
||||
|
}); |
||||
|
|
||||
|
test('map.size', t => { |
||||
|
t.notThrows(() => m(new Map(), m.map.size(0))); |
||||
|
t.notThrows(() => m(new Map([['unicorn', '🦄']]), m.map.size(1))); |
||||
|
t.throws(() => m(new Map([['unicorn', '🦄']]), m.map.size(0)), 'Expected Map to have size `0`, got `1`'); |
||||
|
}); |
||||
|
|
||||
|
test('map.minSize', t => { |
||||
|
t.notThrows(() => m(new Map([['unicorn', '🦄']]), m.map.minSize(1))); |
||||
|
t.notThrows(() => m(new Map([['unicorn', '🦄'], ['rainbow', '🌈']]), m.map.minSize(1))); |
||||
|
t.throws(() => m(new Map([['unicorn', '🦄']]), m.map.minSize(2)), 'Expected Map to have a minimum size of `2`, got `1`'); |
||||
|
}); |
||||
|
|
||||
|
test('map.maxSize', t => { |
||||
|
t.notThrows(() => m(new Map([['unicorn', '🦄']]), m.map.maxSize(1))); |
||||
|
t.notThrows(() => m(new Map([['unicorn', '🦄'], ['rainbow', '🌈']]), m.map.maxSize(4))); |
||||
|
t.throws(() => m(new Map([['unicorn', '🦄'], ['rainbow', '🌈']]), m.map.maxSize(1)), 'Expected Map to have a maximum size of `1`, got `2`'); |
||||
|
}); |
||||
|
|
||||
|
test('map.hasKeys', t => { |
||||
|
t.notThrows(() => m(new Map([['unicorn', '🦄']]), m.map.hasKeys('unicorn'))); |
||||
|
t.notThrows(() => m(new Map([['unicorn', '🦄'], ['rainbow', '🌈']]), m.map.hasKeys('unicorn', 'rainbow'))); |
||||
|
t.notThrows(() => m(new Map([[1, '🦄'], [2, '🌈']]), m.map.hasKeys(1, 2))); |
||||
|
t.throws(() => m(new Map([['unicorn', '🦄'], ['rainbow', '🌈']]), m.map.hasKeys('foo')), 'Expected Map to have keys `["foo"]`'); |
||||
|
t.throws(() => m(new Map([['unicorn', '🦄'], ['foo', '🌈']]), m.map.hasKeys('foo', 'bar')), 'Expected Map to have keys `["bar"]`'); |
||||
|
t.throws(() => m(new Map([[2, '🦄'], [4, '🌈']]), m.map.hasKeys(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)), 'Expected Map to have keys `[1,3,5,6,7]`'); |
||||
|
}); |
||||
|
|
||||
|
test('map.hasAnyKeys', t => { |
||||
|
t.notThrows(() => m(new Map([['unicorn', '🦄']]), m.map.hasAnyKeys('unicorn', 'rainbow'))); |
||||
|
t.notThrows(() => m(new Map([['unicorn', '🦄'], ['rainbow', '🌈']]), m.map.hasAnyKeys('unicorn'))); |
||||
|
t.notThrows(() => m(new Map([[1, '🦄'], [2, '🌈']]), m.map.hasAnyKeys(1, 2, 3, 4))); |
||||
|
t.throws(() => m(new Map([['unicorn', '🦄'], ['rainbow', '🌈']]), m.map.hasAnyKeys('foo')), 'Expected Map to have any key of `["foo"]`'); |
||||
|
}); |
||||
|
|
||||
|
test('map.hasValues', t => { |
||||
|
t.notThrows(() => m(new Map([['unicorn', '🦄']]), m.map.hasValues('🦄'))); |
||||
|
t.notThrows(() => m(new Map([['unicorn', '🦄'], ['rainbow', '🌈']]), m.map.hasValues('🦄', '🌈'))); |
||||
|
t.throws(() => m(new Map([['unicorn', '🦄'], ['rainbow', '🌈']]), m.map.hasValues('🦄', '🌦️')), 'Expected Map to have values `["🌦️"]`'); |
||||
|
t.throws(() => m(new Map([['unicorn', '🦄'], ['rainbow', '🌈']]), m.map.hasValues('🌈', '⚡', '👓', '🐬', '🎃', '🎶', '❤', '️🐳', '🍀', '👽')), 'Expected Map to have values `["⚡","👓","🐬","🎃","🎶"]`'); |
||||
|
}); |
||||
|
|
||||
|
test('map.hasAnyValues', t => { |
||||
|
t.notThrows(() => m(new Map([['unicorn', '🦄']]), m.map.hasAnyValues('🦄', '🌈'))); |
||||
|
t.notThrows(() => m(new Map([['unicorn', '🦄'], ['rainbow', '🌈']]), m.map.hasAnyValues('🦄'))); |
||||
|
t.throws(() => m(new Map([['unicorn', '🦄'], ['rainbow', '🌈']]), m.map.hasAnyValues('🌦️')), 'Expected Map to have any value of `["🌦️"]`'); |
||||
|
}); |
||||
|
|
||||
|
test('map.keysOfType', t => { |
||||
|
t.notThrows(() => m(new Map([['unicorn', '🦄']]), m.map.keysOfType(m.string))); |
||||
|
t.notThrows(() => m(new Map([['unicorn', '🦄'], ['rainbow', '🌈']]), m.map.keysOfType(m.string.minLength(3)))); |
||||
|
t.notThrows(() => m(new Map([[1, '🦄']]), m.map.keysOfType(m.number))); |
||||
|
t.throws(() => m(new Map([['unicorn', '🦄']]), m.map.keysOfType(m.number)), 'Expected argument to be of type `number` but received type `string`'); |
||||
|
}); |
||||
|
|
||||
|
test('map.valuesOfType', t => { |
||||
|
t.notThrows(() => m(new Map([['unicorn', 1]]), m.map.valuesOfType(m.number))); |
||||
|
t.notThrows(() => m(new Map([['unicorn', 10], ['rainbow', 11]]), m.map.valuesOfType(m.number.greaterThanOrEqual(10)))); |
||||
|
t.notThrows(() => m(new Map([['unicorn', '🦄']]), m.map.valuesOfType(m.string))); |
||||
|
t.throws(() => m(new Map([['unicorn', '🦄']]), m.map.valuesOfType(m.number)), 'Expected argument to be of type `number` but received type `string`'); |
||||
|
}); |
||||
|
|
||||
|
test('map.empty', t => { |
||||
|
t.notThrows(() => m(new Map(), m.map.empty)); |
||||
|
t.notThrows(() => m(new Map([]), m.map.empty)); |
||||
|
t.throws(() => m(new Map([['unicorn', '🦄']]), m.map.empty), 'Expected Map to be empty, got `[["unicorn","🦄"]]`'); |
||||
|
}); |
||||
|
|
||||
|
test('map.notEmpty', t => { |
||||
|
t.notThrows(() => m(new Map([['unicorn', '🦄']]), m.map.nonEmpty)); |
||||
|
t.throws(() => m(new Map(), m.map.nonEmpty), 'Expected Map to not be empty'); |
||||
|
}); |
||||
|
|
||||
|
test('map.deepEqual', t => { |
||||
|
t.notThrows(() => m(new Map([['unicorn', '🦄']]), m.map.deepEqual(new Map([['unicorn', '🦄']])))); |
||||
|
t.notThrows(() => m(new Map([['foo', {foo: 'bar'}]]), m.map.deepEqual(new Map([['foo', {foo: 'bar'}]])))); |
||||
|
t.throws(() => m(new Map([['unicorn', '🦄']]), m.map.deepEqual(new Map([['rainbow', '🌈']]))), 'Expected Map to be deeply equal to `[["rainbow","🌈"]]`, got `[["unicorn","🦄"]]`'); |
||||
|
t.throws(() => m(new Map([['foo', {foo: 'bar'}]]), m.map.deepEqual(new Map([['foo', {foo: 'baz'}]]))), 'Expected Map to be deeply equal to `[["foo",{"foo":"baz"}]]`, got `[["foo",{"foo":"bar"}]]`'); |
||||
|
}); |
Loading…
Reference in new issue