Skip to content

Commit 8adc130

Browse files
authored
fix: we are sure about type if parent checked it (#177)
* fix: we are sure about type if parent checked it Type delta calculation here is needed for discriminator to be sure that we can compile. * test: add a regression test for #177
1 parent 9f565db commit 8adc130

File tree

2 files changed

+82
-1
lines changed

2 files changed

+82
-1
lines changed

src/compile.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1284,7 +1284,10 @@ const compileSchema = (schema, root, opts, scope, basePathRoot = '') => {
12841284
evaluateDelta({ type: [current.type] })
12851285
return null
12861286
}
1287-
if (parentCheckedType(...typearr)) return null
1287+
if (parentCheckedType(...typearr)) {
1288+
evaluateDelta({ type: typearr })
1289+
return null
1290+
}
12881291
const filteredTypes = typearr.filter((t) => typeApplicable(t))
12891292
if (filteredTypes.length === 0) fail('No valid types possible')
12901293
evaluateDelta({ type: typearr }) // can be safely done here, filteredTypes already prepared

test/regressions/177.js

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
'use strict'
2+
3+
const tape = require('tape')
4+
const { validator } = require('../../')
5+
6+
tape('regression #177', (t) => {
7+
const variants = [{ type: 'object' }, {}]
8+
9+
for (const l0 of variants) {
10+
for (const l1a of variants) {
11+
for (const l1b of variants) {
12+
for (const l2a of variants) {
13+
for (const l2b of variants) {
14+
if (!l0.type && !l1a.type) continue
15+
if (!l0.type && !l1b.type && !l2a.type) continue
16+
if (!l0.type && !l1b.type && !l2b.type) continue
17+
18+
if (l0.type && (!l2a.type || !l2b.type)) continue // Bug, fixed by #179
19+
20+
t.doesNotThrow(() => {
21+
const validate = validator({
22+
required: ['type'],
23+
discriminator: { propertyName: 'type' },
24+
...l0,
25+
properties: {
26+
type: {
27+
enum: ['noop', 'foo'],
28+
},
29+
},
30+
oneOf: [
31+
{
32+
...l1a,
33+
properties: { type: { const: 'noop' } },
34+
},
35+
{
36+
...l1b,
37+
required: ['method'],
38+
discriminator: { propertyName: 'method' },
39+
properties: {
40+
type: { const: 'foo' },
41+
method: {
42+
enum: ['bar', 'buzz'],
43+
},
44+
},
45+
oneOf: [
46+
{
47+
...l2a,
48+
properties: {
49+
method: { const: 'bar' },
50+
},
51+
},
52+
{
53+
...l2b,
54+
properties: {
55+
method: { const: 'buzz' },
56+
},
57+
},
58+
],
59+
},
60+
],
61+
})
62+
63+
t.notOk(validate({}), '{}')
64+
t.ok(validate({ type: 'noop' }), "{ type: 'noop' }")
65+
t.notOk(validate({ type: 'no' }), "{ type: 'no' }")
66+
t.notOk(validate({ type: 'bar' }), "{ type: 'bar' }")
67+
t.notOk(validate({ type: 'foo' }), "{ type: 'foo' }")
68+
t.ok(validate({ type: 'foo', method: 'bar' }), "{ type: 'foo', method: 'bar' }")
69+
t.notOk(validate({ type: 'foo', method: 'fuzz' }), "{ type: 'foo', method: 'fuzz' }")
70+
}, JSON.stringify([l0, l1a, l1b, l2a, l2b]))
71+
}
72+
}
73+
}
74+
}
75+
}
76+
77+
t.end()
78+
})

0 commit comments

Comments
 (0)