Comparing version 0.2.3 to 0.2.4
@@ -120,2 +120,8 @@ class Masker { | ||
if (isLayered && sourceItems.length > destinationItems.length) { | ||
for (let index = destinationItems.length; index < sourceItems.length; index++) { | ||
destinationItems[index] = {}; // allocate missings, so array items can be updated by reference | ||
} | ||
} | ||
const settled = {touched: []}; | ||
@@ -122,0 +128,0 @@ let untouched = true; |
{ | ||
"name": "carnaval", | ||
"version": "0.2.3", | ||
"version": "0.2.4", | ||
"repository": { | ||
@@ -5,0 +5,0 @@ "type": "git", |
@@ -41,3 +41,5 @@ const Ajv = require('ajv').default; | ||
schema.properties[prop] = propSchema; | ||
if (propSchema.required) { | ||
const required = this._isPropRequired(rule); | ||
if ((propSchema.required && propSchema.required.length) || required) { | ||
schema.required.push(prop); | ||
@@ -106,2 +108,10 @@ } | ||
} | ||
static _isPropRequired(rule) { | ||
for (const prop in rule) { | ||
if (rule[prop].required) { | ||
return true; | ||
} | ||
} | ||
return false; | ||
} | ||
static _props(Type) { | ||
@@ -108,0 +118,0 @@ return Domain.match(Type) ? Type.prototype.props : Type; |
@@ -97,2 +97,59 @@ const test = require('ava'); | ||
class EmptyBox extends Domain { | ||
get props() { | ||
return { | ||
size: String, | ||
thing: Thing | ||
}; | ||
} | ||
get rules() { | ||
return { | ||
thing: { | ||
name: { | ||
value: {enum: ['valued']} | ||
} | ||
} | ||
}; | ||
} | ||
} | ||
test('validate deep (two levels) optionnal', t => { | ||
const json = {}; | ||
const mapping = Mapping.map(EmptyBox).afterDecode(object => validate(object)); | ||
return mapping.decode(json) | ||
.then(emptyBox => { | ||
t.true(emptyBox instanceof EmptyBox); | ||
t.is(emptyBox.thing, undefined); | ||
}); | ||
}); | ||
class NotEmptyBox extends Domain { | ||
get props() { | ||
return { | ||
size: String, | ||
thing: Thing | ||
}; | ||
} | ||
get rules() { | ||
return { | ||
thing: { | ||
name: { | ||
value: {required: true, enum: ['valued']} | ||
} | ||
} | ||
}; | ||
} | ||
} | ||
test('validate deep (two levels) error', t => { | ||
const json = {}; | ||
const mapping = Mapping.map(NotEmptyBox).afterDecode(object => validate(object)); | ||
return mapping.decode(json) | ||
.catch(error => { | ||
t.is(error.message, 'should have required property \'thing\''); | ||
}); | ||
}); | ||
class Gift extends Domain { | ||
@@ -99,0 +156,0 @@ get props() { |
@@ -162,37 +162,37 @@ const test = require('ava'); | ||
class UnreferencedBoxesWithin extends Domain { | ||
get props() { | ||
return { | ||
size: Number, | ||
things: [{ | ||
details: [String] | ||
}] | ||
}; | ||
} | ||
} | ||
// class UnreferencedBoxesWithin extends Domain { | ||
// get props() { | ||
// return { | ||
// size: Number, | ||
// things: [{ | ||
// details: [String] | ||
// }] | ||
// }; | ||
// } | ||
// } | ||
test.only('decode deeply and deeply through untyped mapping', t => { | ||
const mapping = Mapping.map(UnreferencedBoxesWithin); | ||
const json = {size: 40, things: [{details: ['Shoes', 'Small']}, {details: ['Shirt', 'Large']}]}; | ||
// test('decode deeply and deeply through untyped mapping', t => { | ||
// const mapping = Mapping.map(UnreferencedBoxesWithin); | ||
// const json = {size: 40, things: [{details: ['Shoes', 'Small']}, {details: ['Shirt', 'Large']}]}; | ||
return mapping.decode(json).then(box => { | ||
t.true(box instanceof UnreferencedBoxesWithin); | ||
t.is(box.size, json.size); | ||
t.true(box.things instanceof Array); | ||
t.is(box.things[0].details[0], json.things[0].details[0]); | ||
t.is(box.things[1].details[1], json.things[1].details[1]); | ||
}); | ||
}); | ||
// return mapping.decode(json).then(box => { | ||
// t.true(box instanceof UnreferencedBoxesWithin); | ||
// t.is(box.size, json.size); | ||
// t.true(box.things instanceof Array); | ||
// t.is(box.things[0].details[0], json.things[0].details[0]); | ||
// t.is(box.things[1].details[1], json.things[1].details[1]); | ||
// }); | ||
// }); | ||
test('encode deeply and deeply through untyped mapping', t => { | ||
const mapping = Mapping.map(UnreferencedBoxesWithin); | ||
const box = new UnreferencedBoxes({size: 40, things: [{details: ['Shoes', 'Small']}, {details: ['Shirt', 'Large']}]}); | ||
// test('encode deeply and deeply through untyped mapping', t => { | ||
// const mapping = Mapping.map(UnreferencedBoxesWithin); | ||
// const box = new UnreferencedBoxes({size: 40, things: [{details: ['Shoes', 'Small']}, {details: ['Shirt', 'Large']}]}); | ||
return mapping.encode(box).then(json => { | ||
t.is(json.size, box.size); | ||
t.true(json.things instanceof Array); | ||
t.is(json.things[0].details[0], box.things[0].details[0]); | ||
t.is(json.things[1].details[1], box.things[1].details[1]); | ||
}); | ||
}); | ||
// return mapping.encode(box).then(json => { | ||
// t.is(json.size, box.size); | ||
// t.true(json.things instanceof Array); | ||
// t.is(json.things[0].details[0], box.things[0].details[0]); | ||
// t.is(json.things[1].details[1], box.things[1].details[1]); | ||
// }); | ||
// }); | ||
@@ -609,2 +609,38 @@ class UnknownBox extends Domain { | ||
test('decode array class tree through mapping & transform', t => { | ||
const mapping = Mapping.map(UnreferencedBoxes).with({ | ||
things: [Mapping.map(Thing).with({ | ||
name: { | ||
set: value => value.toUpperCase() | ||
} | ||
})] | ||
}); | ||
const json = {size: 40, things: [{name: 'Shoes'}]}; | ||
return mapping.decode(json).then(boxes => { | ||
t.true(boxes instanceof UnreferencedBoxes); | ||
t.is(boxes.size, json.size); | ||
t.true(boxes.things instanceof Array); | ||
t.is(boxes.things[0].name, json.things[0].name.toUpperCase()); | ||
}); | ||
}); | ||
test('encode array class tree through mapping & transform', t => { | ||
const mapping = Mapping.map(UnreferencedBoxes).with({ | ||
things: [Mapping.map(Thing).with({ | ||
name: { | ||
get: value => value.toLowerCase() | ||
} | ||
})] | ||
}); | ||
const boxes = new UnreferencedBoxes({size: 40, things: [new Thing({name: 'Shoes'})]}); | ||
return mapping.encode(boxes).then(json => { | ||
t.is(json.size, boxes.size); | ||
t.true(json.things instanceof Array); | ||
t.is(json.size, 40); | ||
t.is(json.things[0].name, boxes.things[0].name.toLowerCase()); | ||
}); | ||
}); | ||
test('decode class tree through mapping & visibility transform', t => { | ||
@@ -611,0 +647,0 @@ const mapping = Mapping.map(Box).with({ |
@@ -97,2 +97,19 @@ const test = require('ava'); | ||
test('assign array, untouched', t => { | ||
const mask = Mask.cover(Gift).with({ | ||
names: true | ||
}); | ||
const names = []; | ||
const gift = new Gift({names}); | ||
const touched = mask.settle( | ||
gift, | ||
new Gift({names: ['Jeans', 'Shirt', 'Jeans']}) | ||
); | ||
t.deepEqual(gift.names, ['Jeans', 'Shirt', 'Jeans']); | ||
t.deepEqual(touched.names, undefined); | ||
}); | ||
test('assign array, touched & schema', t => { | ||
@@ -312,2 +329,27 @@ const mask = Mask.cover(Gift).with({ | ||
test('assign deep array, untouched', t => { | ||
const mask = Mask.cover(Boxes).with({ | ||
things: true | ||
}); | ||
const name = 'Shoes'; | ||
const description = 'Adventure Playground'; | ||
const physical = true; | ||
const boxes = new Boxes({things: []}); | ||
const touched = mask.settle( | ||
boxes, | ||
new Boxes({things: [{name, description, physical}, {name, description, physical}]}) | ||
); | ||
for (let i = 0; i < 2; i++) { | ||
t.is(boxes.things[i].name, name); | ||
t.is(boxes.things[i].description, description); | ||
t.is(boxes.things[i].size, undefined); | ||
t.is(boxes.things[i].physical, physical); | ||
} | ||
t.is(touched.thing, undefined); | ||
}); | ||
class Cart extends Domain { | ||
@@ -314,0 +356,0 @@ get props() { |
112903
2767