Skip to content

Commit ff905c0

Browse files
committed
Define and.json, add additional checks to if.json
1 parent 950bdd9 commit ff905c0

File tree

3 files changed

+184
-4
lines changed

3 files changed

+184
-4
lines changed

defaultMethods.js

+9-3
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,7 @@ const defaultMethods = {
228228
[Sync]: (data, buildState) => isSyncDeep(data, buildState.engine, buildState),
229229
method: (arr, context, above, engine) => {
230230
if (!Array.isArray(arr)) throw INVALID_ARGUMENTS
231+
if (!arr.length) return false
231232

232233
let item
233234
for (let i = 0; i < arr.length; i++) {
@@ -239,6 +240,7 @@ const defaultMethods = {
239240
},
240241
asyncMethod: async (arr, _1, _2, engine) => {
241242
if (!Array.isArray(arr)) throw INVALID_ARGUMENTS
243+
if (!arr.length) return false
242244

243245
let item
244246
for (let i = 0; i < arr.length; i++) {
@@ -251,7 +253,8 @@ const defaultMethods = {
251253
deterministic: (data, buildState) => isDeterministic(data, buildState.engine, buildState),
252254
compile: (data, buildState) => {
253255
let res = buildState.compile``
254-
if (Array.isArray(data) && data.length) {
256+
if (Array.isArray(data)) {
257+
if (!data.length) return buildState.compile`false`
255258
for (let i = 0; i < data.length; i++) res = buildState.compile`${res} engine.truthy(prev = ${data[i]}) ? prev : `
256259
res = buildState.compile`${res} prev`
257260
return res
@@ -383,6 +386,7 @@ const defaultMethods = {
383386
[Sync]: (data, buildState) => isSyncDeep(data, buildState.engine, buildState),
384387
method: (arr, context, above, engine) => {
385388
if (!Array.isArray(arr)) throw INVALID_ARGUMENTS
389+
if (!arr.length) return false
386390

387391
let item
388392
for (let i = 0; i < arr.length; i++) {
@@ -393,7 +397,7 @@ const defaultMethods = {
393397
},
394398
asyncMethod: async (arr, _1, _2, engine) => {
395399
if (!Array.isArray(arr)) throw INVALID_ARGUMENTS
396-
400+
if (!arr.length) return false
397401
let item
398402
for (let i = 0; i < arr.length; i++) {
399403
item = await engine.run(arr[i], _1, { above: _2 })
@@ -405,11 +409,13 @@ const defaultMethods = {
405409
deterministic: (data, buildState) => isDeterministic(data, buildState.engine, buildState),
406410
compile: (data, buildState) => {
407411
let res = buildState.compile``
408-
if (Array.isArray(data) && data.length) {
412+
if (Array.isArray(data)) {
413+
if (!data.length) return buildState.compile`false`
409414
for (let i = 0; i < data.length; i++) res = buildState.compile`${res} !engine.truthy(prev = ${data[i]}) ? prev : `
410415
res = buildState.compile`${res} prev`
411416
return res
412417
}
418+
413419
return false
414420
}
415421
},

suites/control/and.json

+143-1
Original file line numberDiff line numberDiff line change
@@ -1 +1,143 @@
1-
[]
1+
[
2+
"Basic Checks",
3+
{
4+
"description": "Two true values should be true",
5+
"rule": { "and": [true, true] },
6+
"data": null,
7+
"result": true
8+
},
9+
{
10+
"description": "false and true should be false",
11+
"rule": { "and": [false, true] },
12+
"data": null,
13+
"result": false
14+
},
15+
{
16+
"description": "true and false should be false",
17+
"rule": { "and": [true, false] },
18+
"data": null,
19+
"result": false
20+
},
21+
{
22+
"description": "Two false values should be false",
23+
"rule": { "and": [false, false] },
24+
"data": null,
25+
"result": false
26+
},
27+
{
28+
"description": "All true values should be true",
29+
"rule": { "and": [true, true, true] },
30+
"data": null,
31+
"result": true
32+
},
33+
{
34+
"description": "Any false value should be false",
35+
"rule": { "and": [true, true, false] },
36+
"data": null,
37+
"result": false
38+
},
39+
{
40+
"description": "And with a single false value should be false",
41+
"rule": { "and": [false] },
42+
"data": null,
43+
"result": false
44+
},
45+
{
46+
"description": "And with a single falsey value should be return the falsy value",
47+
"rule": { "and": [[]] },
48+
"data": null,
49+
"result": []
50+
},
51+
{
52+
"description": "And with a single falsey value should be return the falsy value (2)",
53+
"rule": { "and": [0] },
54+
"data": null,
55+
"result": 0
56+
},
57+
{
58+
"description": "And with a single falsey value should be return the falsy value (3)",
59+
"rule": { "and": [""] },
60+
"data": null,
61+
"result": ""
62+
},
63+
{
64+
"description": "And with a single true value should be true",
65+
"rule": { "and": [true] },
66+
"data": null,
67+
"result": true
68+
},
69+
{
70+
"description": "And with 2 truthy values should return the last truthy value",
71+
"rule": { "and": [1, 3] },
72+
"data": null,
73+
"result": 3
74+
},
75+
{
76+
"description": "And with a truthy value and a false value should return the false value",
77+
"rule": { "and": [3, false] },
78+
"data": null,
79+
"result": false
80+
},
81+
{
82+
"description": "And with a truthy value and a false value should return the false value (2)",
83+
"rule": { "and": [false, 3] },
84+
"data": null,
85+
"result": false
86+
},
87+
{
88+
"description": "Empty array is falsy, so it is returned",
89+
"rule": { "and": [[], true] },
90+
"data": null,
91+
"result": []
92+
},
93+
{
94+
"description": "0 is falsy, so it is returned",
95+
"rule": { "and": [0, true] },
96+
"data": null,
97+
"result": 0
98+
},
99+
{
100+
"description": "Empty string is falsy, so it is returned",
101+
"rule": { "and": ["", true] },
102+
"data": null,
103+
"result": ""
104+
},
105+
{
106+
"description": "0 as a string is truthy, so the last truthy value is returned",
107+
"rule": { "and": ["0", true] },
108+
"data": null,
109+
"result": true
110+
},
111+
{
112+
"description": "And with no arguments should return false",
113+
"rule": { "and": [] },
114+
"data": null,
115+
"result": false
116+
},
117+
"Valid Arguments Checks",
118+
{
119+
"description": "And with non-array arguments should throw",
120+
"rule": { "and": true },
121+
"data": null,
122+
"error": { "type": "Invalid Arguments" }
123+
},
124+
"Short Circuiting Checks",
125+
{
126+
"description": "And will not interpret the second argument if the first is false",
127+
"rule": { "and": [false, { "throw": "Not Lazy" }] },
128+
"data": null,
129+
"result": false
130+
},
131+
{
132+
"description": "And will not interpret the second argument if the first is falsy",
133+
"rule": { "and": [0, { "throw": "Not Lazy" }] },
134+
"data": null,
135+
"result": 0
136+
},
137+
{
138+
"description": "And will not interpret the nth argument if any value before it is false",
139+
"rule": { "and": [true, 1, 2, 3, 4, [], { "throw": "Not Lazy" }] },
140+
"data": null,
141+
"result": []
142+
}
143+
]

suites/control/if.json

+32
Original file line numberDiff line numberDiff line change
@@ -241,5 +241,37 @@
241241
"rule": { "if": [{}, "apple", 0, "banana", 7, "carrot", "date"] },
242242
"data": null,
243243
"result": "apple"
244+
},
245+
"Bad Arguments",
246+
{
247+
"description": "If with non-array arguments throws",
248+
"rule": { "if": "apple" },
249+
"data": null,
250+
"error": { "type": "Invalid Arguments" }
251+
},
252+
"Short circuiting check",
253+
{
254+
"description": "If will not evaluate then branch if the condition is false",
255+
"rule": { "if": [false, { "throw": "Not Lazy" }, "banana"] },
256+
"data": null,
257+
"result": "banana"
258+
},
259+
{
260+
"description": "If will not evaluate fallback branch if the condition is true",
261+
"rule": { "if": [true, "apple", { "throw": "Not Lazy" }] },
262+
"data": null,
263+
"result": "apple"
264+
},
265+
{
266+
"description": "If will not evaluate other branches or checks if a prior condition is true",
267+
"rule": { "if": [false, { "throw": "Not Lazy" }, true, "apple", { "throw": "Not Lazy" }, { "throw": "Not Lazy" }, { "throw": "Not Lazy" }] },
268+
"data": null,
269+
"result": "apple"
270+
},
271+
{
272+
"description": "No branches except the fallback check will be evaluated if the condition is false",
273+
"rule": { "if": [false, { "throw": "Not Lazy" }, false, { "throw": "Not Lazy" }, false, { "throw": "Not Lazy" }, "carrot"] },
274+
"data": null,
275+
"result": "carrot"
244276
}
245277
]

0 commit comments

Comments
 (0)