Skip to content
This repository was archived by the owner on Apr 4, 2023. It is now read-only.

Commit 7089936

Browse files
authored
Merge pull request #7 from OsomePteLtd/failing-anyOf-test
Failing-anyOf-test
2 parents 2c3338c + b6b1ae8 commit 7089936

File tree

3 files changed

+117
-41
lines changed

3 files changed

+117
-41
lines changed

lib/index.js

+16-14
Original file line numberDiff line numberDiff line change
@@ -34,28 +34,18 @@ function serialize(resource, schema, options = {}) {
3434
}
3535

3636
function findObjectDef(propertyDef) {
37-
const { type, anyOf, properties } = propertyDef;
37+
const { type, anyOf } = propertyDef;
3838

39-
if (type === 'object' && properties) {
39+
if (type === 'object') {
4040
return propertyDef;
4141
}
4242

4343
if (type === 'array') {
4444
return findObjectDef(propertyDef.items);
4545
}
4646

47-
if (anyOf) {
48-
const props = anyOf
49-
.map(findObjectDef)
50-
.filter(Boolean)
51-
.map(item => item.properties)
52-
.reduce((acc, curr) => ({ ...acc, ...curr }), {});
53-
if (Object.keys(props).length > 0) {
54-
return {
55-
type: 'object',
56-
properties: props,
57-
};
58-
}
47+
if (anyOf && isNullableType(propertyDef)) {
48+
return anyOf.map(findObjectDef).find(def => def && def.type === 'object');
5949
}
6050

6151
return null;
@@ -66,7 +56,19 @@ function isObjectLike(value) {
6656
}
6757

6858
function toJSON(value) {
59+
if (Array.isArray(value)) {
60+
return value.map(toJSON);
61+
}
6962
return value && typeof value.toJSON === 'function' ? value.toJSON() : value;
7063
}
7164

65+
function isNullType(schema = {}) {
66+
return schema.type === 'null';
67+
}
68+
69+
function isNullableType(schema = {}) {
70+
const { anyOf = [] } = schema;
71+
return Boolean(anyOf.length === 2 && anyOf.find(isNullType) && anyOf.find(item => !isNullType(item)));
72+
}
73+
7274
module.exports = serialize;

tests/all.test.js

+96-17
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1+
const Sequelize = require('sequelize');
12
const { createModel, DUMMY_VALUES } = require('./init');
3+
24
const serialize = require('../lib/index');
35

46
describe('Serializers', () => {
@@ -67,18 +69,25 @@ describe('Serializers', () => {
6769
type: 'string',
6870
},
6971
modelsB: {
70-
type: 'array',
71-
items: {
72-
type: 'object',
73-
properties: {
74-
b: {
75-
type: 'integer',
76-
},
77-
c: {
78-
type: 'boolean',
72+
anyOf: [
73+
{
74+
type: 'array',
75+
items: {
76+
type: 'object',
77+
properties: {
78+
b: {
79+
type: 'integer',
80+
},
81+
c: {
82+
type: 'boolean',
83+
},
84+
},
7985
},
8086
},
81-
},
87+
{
88+
type: 'null',
89+
},
90+
],
8291
},
8392
},
8493
};
@@ -130,7 +139,9 @@ describe('Serializers', () => {
130139

131140
expect(serialize(instanceB, schema)).toEqual({
132141
a: 'x',
133-
modelA: { b: 777, c: true },
142+
modelA: {
143+
a: 'x', b: 777, c: true, id: null,
144+
},
134145
});
135146
});
136147

@@ -180,21 +191,25 @@ describe('Serializers', () => {
180191
};
181192

182193
const instanceA = new ModelA(DUMMY_VALUES);
183-
const instanceB1 = new ModelB(DUMMY_VALUES);
194+
const instanceB1 = new ModelB({ a: 'x' });
184195
const instanceB2 = new ModelB(DUMMY_VALUES);
185196
instanceA.modelsB = [instanceB1, instanceB2];
186197

187198
expect(serialize(instanceA, schema)).toEqual({
188199
a: 'x',
189200
modelsB: [
190-
{ b: 777, c: true },
191-
{ b: 777, c: true },
201+
{
202+
a: 'x', id: null,
203+
},
204+
{
205+
a: 'x', b: 777, c: true, id: null,
206+
},
192207
],
193208
});
194209
});
195210

196211
it('Object schema without properties', () => {
197-
const TestModel = createModel();
212+
const TestModel = createModel('TestModel', { a: Sequelize.DataTypes.JSONB });
198213

199214
const schema = {
200215
type: 'object',
@@ -213,8 +228,14 @@ describe('Serializers', () => {
213228
additionalProperties: false,
214229
};
215230

216-
const instance = new TestModel({ ...DUMMY_VALUES, a: {} });
217-
expect(serialize(instance, schema)).toEqual({ a: {} });
231+
const instance = new TestModel({ ...DUMMY_VALUES, a: DUMMY_VALUES });
232+
expect(serialize(instance, schema)).toEqual({
233+
a: {
234+
a: 'x',
235+
b: 777,
236+
c: true,
237+
},
238+
});
218239
});
219240

220241
it('Resource as empty array', () => {
@@ -238,4 +259,62 @@ describe('Serializers', () => {
238259
id: null,
239260
});
240261
});
262+
263+
it('anyOf with conflicting nested properties', () => {
264+
const ModelA = createModel('ModelA', { a: Sequelize.DataTypes.JSONB });
265+
266+
const schema = {
267+
type: 'object',
268+
properties: {
269+
a: {
270+
anyOf: [
271+
{
272+
type: 'object',
273+
properties: {
274+
arr: {
275+
type: 'array',
276+
items: {
277+
type: 'object',
278+
properties: {
279+
foo: {
280+
type: 'boolean',
281+
},
282+
},
283+
},
284+
},
285+
},
286+
},
287+
{
288+
type: 'object',
289+
properties: {
290+
arr: {
291+
type: 'array',
292+
items: {
293+
type: 'object',
294+
properties: {
295+
bar: {
296+
type: 'boolean',
297+
},
298+
},
299+
},
300+
},
301+
},
302+
},
303+
],
304+
},
305+
},
306+
};
307+
308+
const instanceA = new ModelA({
309+
a: {
310+
arr: [{ foo: true }],
311+
},
312+
});
313+
314+
expect(serialize(instanceA, schema)).toEqual({
315+
a: {
316+
arr: [{ foo: true }],
317+
},
318+
});
319+
});
241320
});

tests/init.js

+5-10
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,21 @@
11
const Sequelize = require('sequelize');
22

3-
const sequelize = new Sequelize('sqlite::memory:');
3+
const sequelize = new Sequelize('sqlite::memory:', { logging: false });
44

55
const DUMMY_VALUES = {
66
a: 'x',
77
b: 777,
88
c: true,
99
};
1010

11-
function createModel() {
12-
class TestModel extends Sequelize.Model {}
13-
14-
TestModel.init(
11+
function createModel(modelName = 'TestModel', props = {}) {
12+
return sequelize.define(modelName,
1513
{
1614
a: Sequelize.DataTypes.STRING,
1715
b: Sequelize.DataTypes.INTEGER,
1816
c: Sequelize.DataTypes.BOOLEAN,
19-
},
20-
{ sequelize },
21-
);
22-
23-
return TestModel;
17+
...props,
18+
});
2419
}
2520

2621
module.exports = {

0 commit comments

Comments
 (0)