|
1 |
| -import { isNumber, isString } from "lodash"; |
| 1 | +import { isNumber, isString } from 'lodash' |
2 | 2 |
|
3 |
| -import { be, beArray, beTrue, decode } from "./index"; |
| 3 | +import {be, decodeArray, decode, makeDecoder} from './index' |
4 | 4 |
|
5 |
| -test("be", () => { |
6 |
| - const numError = "Not a number!"; |
| 5 | +test('be', () => { |
| 6 | + const numError = 'Not a number!' |
7 | 7 |
|
8 |
| - expect(be(20, isNumber, numError)).toBe(20); |
9 |
| - expect(() => be("20", isNumber, numError)).toThrow(numError); |
10 |
| -}); |
| 8 | + expect(be(20, isNumber, numError)).toBe(20) |
| 9 | + expect(() => be('20', isNumber, numError)).toThrow(numError) |
| 10 | +}) |
11 | 11 |
|
12 |
| -test("beTrue", () => { |
13 |
| - const fiverError = "Not equals to 5.5!"; |
14 |
| - const eq = (m: number) => (n: number) => n === m; |
| 12 | +test('beArray: happy path', () => { |
| 13 | + expect(decodeArray([1, false, 'Bob'], el => el)).toStrictEqual([1, false, 'Bob']) |
| 14 | +}) |
15 | 15 |
|
16 |
| - expect(beTrue(5.5, eq(5.5), fiverError)).toBe(5.5); |
17 |
| - expect(() => beTrue(5.7, eq(5.5), fiverError)).toThrow(fiverError); |
18 |
| -}); |
19 |
| - |
20 |
| -test("decode: validation ok", () => { |
21 |
| - expect( |
22 |
| - decode( |
23 |
| - ["foo", "bar"], |
24 |
| - ([foo, bar]) => ({ |
25 |
| - foo: be(foo, isString, "Failed"), |
26 |
| - bar: beTrue(bar, s => s === "bar", "Failed") |
27 |
| - }), |
28 |
| - null |
29 |
| - ) |
30 |
| - ).toStrictEqual({ |
31 |
| - foo: "foo", |
32 |
| - bar: "bar" |
33 |
| - }); |
34 |
| -}); |
35 |
| - |
36 |
| -test("decode: falling back", () => { |
37 |
| - const logger = jest.fn(); |
38 |
| - |
39 |
| - expect( |
40 |
| - decode( |
41 |
| - void 0, |
42 |
| - () => ({ |
43 |
| - foo: be("foo", isString, "Failed"), |
44 |
| - bar: beTrue("bar", s => s === "foo", "Failed") |
45 |
| - }), |
46 |
| - null, |
47 |
| - { logger } |
48 |
| - ) |
49 |
| - ).toBe(null); |
50 |
| - |
51 |
| - expect(logger).toBeCalledWith(expect.objectContaining({ message: "Failed" })); |
52 |
| -}); |
53 |
| - |
54 |
| -test("beArray: happy path", () => { |
55 |
| - expect(beArray([1, false, "Bob"], el => el)).toStrictEqual([1, false, "Bob"]); |
56 |
| -}); |
57 |
| - |
58 |
| -test("beArray: filtering", () => { |
| 16 | +test('beArray: filtering', () => { |
59 | 17 | expect(
|
60 |
| - beArray(["a", 0, "b", 1, "c"], s => { |
61 |
| - if (typeof s !== "string") throw Error("!"); |
62 |
| - return { s }; |
| 18 | + decodeArray(['a', 0, 'b', 1, 'c'], s => { |
| 19 | + if (typeof s !== 'string') throw Error('!') |
| 20 | + return { s } |
63 | 21 | })
|
64 |
| - ).toStrictEqual([{ s: "a" }, { s: "b" }, { s: "c" }]); |
65 |
| -}); |
| 22 | + ).toStrictEqual([{ s: 'a' }, { s: 'b' }, { s: 'c' }]) |
| 23 | +}) |
66 | 24 |
|
67 |
| -test("beArray: invalidate all", () => { |
| 25 | +test('beArray: invalidate all', () => { |
68 | 26 | expect(() =>
|
69 |
| - beArray( |
70 |
| - ["a", 0, "b", 1, "c"], |
| 27 | + decodeArray( |
| 28 | + ['a', 0, 'b', 1, 'c'], |
71 | 29 | x => {
|
72 |
| - if (typeof x !== "string") throw Error("!!!"); |
73 |
| - return x; |
| 30 | + if (typeof x !== 'string') throw Error('!!!') |
| 31 | + return x |
74 | 32 | },
|
75 | 33 | { invalidateAll: true }
|
76 | 34 | )
|
77 |
| - ).toThrow("!!!"); |
78 |
| -}); |
| 35 | + ).toThrow('!!!') |
| 36 | +}) |
79 | 37 |
|
80 |
| -test("beArray: not an array", () => { |
| 38 | +test('beArray: not an array', () => { |
81 | 39 | expect(() => {
|
82 |
| - beArray("[]", x => x); |
83 |
| - }).toThrow("“[]” (string) is not an array"); |
| 40 | + decodeArray('[]', x => x) |
| 41 | + }).toThrow('“[]” (string) is not an array') |
84 | 42 |
|
85 | 43 | expect(() => {
|
86 |
| - beArray(3.14, x => x); |
87 |
| - }).toThrow("3.14 (number) is not an array"); |
| 44 | + decodeArray(3.14, x => x) |
| 45 | + }).toThrow('3.14 (number) is not an array') |
88 | 46 |
|
89 | 47 | expect(() => {
|
90 |
| - beArray("[]", x => x, { |
91 |
| - notAnArrayError: "Not quite an array one would expect" |
92 |
| - }); |
93 |
| - }).toThrow("Not quite an array one would expect"); |
94 |
| -}); |
| 48 | + decodeArray('[]', x => x, { |
| 49 | + notAnArrayError: 'Not quite an array one would expect' |
| 50 | + }) |
| 51 | + }).toThrow('Not quite an array one would expect') |
| 52 | +}) |
95 | 53 |
|
96 |
| -test("beArray: checkLength", () => { |
| 54 | +test('beArray: checkLength', () => { |
97 | 55 | expect(() =>
|
98 |
| - beArray( |
| 56 | + decodeArray( |
99 | 57 | [false, false, false, false, true],
|
100 | 58 | x => {
|
101 |
| - if (!x) throw Error("!!!"); |
102 |
| - return x; |
| 59 | + if (!x) throw Error('!!!') |
| 60 | + return x |
103 | 61 | },
|
104 |
| - { minLength: 2, minLengthError: "Way too short!" } |
| 62 | + { minLength: 2, minLengthError: 'Way too short!' } |
105 | 63 | )
|
106 |
| - ).toThrow("Way too short!"); |
| 64 | + ).toThrow('Way too short!') |
107 | 65 |
|
108 | 66 | expect(() =>
|
109 |
| - beArray( |
| 67 | + decodeArray( |
110 | 68 | [false, false, false, false, true],
|
111 | 69 | x => {
|
112 |
| - if (!x) throw Error("!!!"); |
113 |
| - return x; |
| 70 | + if (!x) throw Error('!!!') |
| 71 | + return x |
114 | 72 | },
|
115 | 73 | { minLength: 2 }
|
116 | 74 | )
|
117 |
| - ).toThrow("Array length (1) less than specified (2)"); |
118 |
| -}); |
| 75 | + ).toThrow('Array length (1) less than specified (2)') |
| 76 | +}) |
| 77 | + |
| 78 | +test('decode: validation ok', () => { |
| 79 | + expect( |
| 80 | + decode( |
| 81 | + ['foo', 'bar'], |
| 82 | + ([foo, bar]) => ({ |
| 83 | + foo: be(foo, isString, 'Failed'), |
| 84 | + bar: be(bar, isString, 'Failed') |
| 85 | + }), |
| 86 | + null |
| 87 | + ) |
| 88 | + ).toStrictEqual({ |
| 89 | + foo: 'foo', |
| 90 | + bar: 'bar' |
| 91 | + }) |
| 92 | +}) |
| 93 | + |
| 94 | +test('decode: falling back', () => { |
| 95 | + const logger = jest.fn() |
| 96 | + |
| 97 | + expect( |
| 98 | + decode( |
| 99 | + void 0, |
| 100 | + () => ({ |
| 101 | + foo: be('foo', isString, 'Failed'), |
| 102 | + bar: be('bar', isNumber, 'Failed') |
| 103 | + }), |
| 104 | + null, |
| 105 | + { logger } |
| 106 | + ) |
| 107 | + ).toBe(null) |
| 108 | + |
| 109 | + expect(logger).toBeCalledWith(expect.objectContaining({ message: 'Failed' })) |
| 110 | +}) |
| 111 | + |
| 112 | +test('decode: successful nested array', () => { |
| 113 | + expect( |
| 114 | + decode( |
| 115 | + { id: 3, animals: ['Cat', 'Dog', 'Siren'] }, |
| 116 | + input => ({ |
| 117 | + id: be(input.id, isNumber, 'Id should be a number'), |
| 118 | + animalNames: decodeArray( |
| 119 | + input.animals, |
| 120 | + makeDecoder( |
| 121 | + isString, |
| 122 | + 'animal should have strings of characters as their names' |
| 123 | + ) |
| 124 | + // fixme: maybe we should add a fallback parameter after all |
| 125 | + // I mean, the only way to catch array validation errors here |
| 126 | + // is `decode`, and wrapping `decodeArray` (a catching point in its |
| 127 | + // own right) in `decode` eels rather weird |
| 128 | + // |
| 129 | + // maybe we should have `invalidate: 'element' | 'array' | 'parent' |
| 130 | + ) |
| 131 | + }), |
| 132 | + null |
| 133 | + ) |
| 134 | + ).toStrictEqual({ id: 3, animalNames: ['Cat', 'Dog', 'Siren'] }) |
| 135 | +}) |
0 commit comments