functional-models 1.0.9 → 1.0.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +39 -21
- package/features/stepDefinitions/steps.js +5 -5
- package/package.json +2 -1
- package/src/fields.js +5 -3
- package/src/models.js +22 -16
- package/src/serialization.js +4 -4
- package/src/utils.js +2 -2
- package/src/validation.js +35 -22
- package/test/src/fields.test.js +7 -7
- package/test/src/models.test.js +40 -11
- package/test/src/serialization.test.js +15 -15
- package/test/src/validation.test.js +14 -0
package/README.md
CHANGED
|
@@ -10,29 +10,36 @@ This library empowers the creation of pure JavaScript function based models that
|
|
|
10
10
|
## Example Usage
|
|
11
11
|
|
|
12
12
|
const {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
13
|
+
field,
|
|
14
|
+
constantValueField,
|
|
15
|
+
textField,
|
|
16
|
+
dateField,
|
|
17
|
+
integerField,
|
|
16
18
|
uniqueId,
|
|
19
|
+
createModel,
|
|
20
|
+
validation,
|
|
17
21
|
}= require('functional-models')
|
|
18
22
|
|
|
19
|
-
const Truck = ({
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
23
|
+
const Truck = createModel({
|
|
24
|
+
type: constantValueField('truck'),
|
|
25
|
+
id: uniqueId({required: true}),
|
|
26
|
+
make: textField({ maxLength: 20, minLength: 3, required: true}),
|
|
27
|
+
model: textField({ maxLength: 20, minLength: 3, required: true}),
|
|
28
|
+
color: textField({ maxLength: 10, minLength: 3, validators: [
|
|
29
|
+
validation.meetsRegex(/Red/),
|
|
30
|
+
]}),
|
|
31
|
+
year: integerField({ maxValue: 2500, minValue: 1900}),
|
|
32
|
+
lastModified: dateField({ autoNow: true}),
|
|
33
|
+
})
|
|
27
34
|
|
|
28
35
|
|
|
29
36
|
const myTruck = Truck({ make: 'Ford', model: 'F-150', color: 'White', year: 2013})
|
|
30
37
|
|
|
31
|
-
console.log(myTruck.getId()) // a random uuid
|
|
32
|
-
console.log(myTruck.getMake()) // 'Ford'
|
|
33
|
-
console.log(myTruck.getModel()) // 'F-150'
|
|
34
|
-
console.log(myTruck.getColor()) // 'White'
|
|
35
|
-
console.log(myTruck.getYear()) // 2013
|
|
38
|
+
console.log(await myTruck.getId()) // a random uuid
|
|
39
|
+
console.log(await myTruck.getMake()) // 'Ford'
|
|
40
|
+
console.log(await myTruck.getModel()) // 'F-150'
|
|
41
|
+
console.log(await myTruck.getColor()) // 'White'
|
|
42
|
+
console.log(await myTruck.getYear()) // 2013
|
|
36
43
|
|
|
37
44
|
const asJson = await myTruck.functions.toJson()
|
|
38
45
|
console.log(asJson)
|
|
@@ -47,8 +54,19 @@ This library empowers the creation of pure JavaScript function based models that
|
|
|
47
54
|
*/
|
|
48
55
|
|
|
49
56
|
const sameTruck = Truck(asJson)
|
|
50
|
-
console.log(sameTruck.getId()) // same uuid as above
|
|
51
|
-
console.log(sameTruck.getMake()) // 'Ford'
|
|
52
|
-
console.log(sameTruck.getModel()) // 'F-150'
|
|
53
|
-
console.log(sameTruck.getColor()) // 'White'
|
|
54
|
-
console.log(sameTruck.getYear()) // 2013
|
|
57
|
+
console.log(await sameTruck.getId()) // same uuid as above
|
|
58
|
+
console.log(await sameTruck.getMake()) // 'Ford'
|
|
59
|
+
console.log(await sameTruck.getModel()) // 'F-150'
|
|
60
|
+
console.log(await sameTruck.getColor()) // 'White'
|
|
61
|
+
console.log(await sameTruck.getYear()) // 2013
|
|
62
|
+
|
|
63
|
+
// Validation
|
|
64
|
+
const errors = await sameTruck.functions.validate.model() // {}
|
|
65
|
+
|
|
66
|
+
const newTruck = Truck({ make: 'Ford', model: 'F-150', color: 'White', year: 20130})
|
|
67
|
+
const errors2 = await newTruck.functions.validate.model()
|
|
68
|
+
console.log(errors2)
|
|
69
|
+
// {"year": 'Value is too long'}
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
|
|
@@ -4,24 +4,24 @@ const { Given, When, Then } = require('@cucumber/cucumber')
|
|
|
4
4
|
const { createModel, field, arrayField, validation } = require('../../index')
|
|
5
5
|
|
|
6
6
|
const MODEL_DEFINITIONS = {
|
|
7
|
-
TestModel1: createModel({
|
|
7
|
+
TestModel1: createModel("TestModel1", {
|
|
8
8
|
name: field({ required: true }),
|
|
9
9
|
type: field({ required: true, isString: true }),
|
|
10
10
|
flag: field({ required: true, isNumber: true }),
|
|
11
11
|
}),
|
|
12
|
-
ArrayModel1: createModel({
|
|
12
|
+
ArrayModel1: createModel("ArrayModel1", {
|
|
13
13
|
arrayField: field({
|
|
14
14
|
isArray: true,
|
|
15
15
|
validators: [validation.arrayType(validation.TYPE_PRIMATIVES.integer)],
|
|
16
16
|
}),
|
|
17
17
|
}),
|
|
18
|
-
ArrayModel2: createModel({
|
|
18
|
+
ArrayModel2: createModel("ArrayModel2", {
|
|
19
19
|
arrayField: field({ isArray: true }),
|
|
20
20
|
}),
|
|
21
|
-
ArrayModel3: createModel({
|
|
21
|
+
ArrayModel3: createModel("ArrayModel3", {
|
|
22
22
|
arrayField: arrayField({}),
|
|
23
23
|
}),
|
|
24
|
-
ArrayModel4: createModel({
|
|
24
|
+
ArrayModel4: createModel("ArrayModel4", {
|
|
25
25
|
arrayField: arrayField({
|
|
26
26
|
choices: [4, 5, 6],
|
|
27
27
|
validators: [validation.arrayType(validation.TYPE_PRIMATIVES.integer)],
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "functional-models",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.10",
|
|
4
4
|
"description": "A library for creating JavaScript function based models.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -29,6 +29,7 @@
|
|
|
29
29
|
"nyc": {
|
|
30
30
|
"all": true,
|
|
31
31
|
"exclude": [
|
|
32
|
+
"coverage/",
|
|
32
33
|
"features/stepDefinitions/*",
|
|
33
34
|
"test/*"
|
|
34
35
|
]
|
package/src/fields.js
CHANGED
|
@@ -53,9 +53,11 @@ const field = (config = {}) => {
|
|
|
53
53
|
}
|
|
54
54
|
},
|
|
55
55
|
getValidator: valueGetter => {
|
|
56
|
-
|
|
57
|
-
|
|
56
|
+
const validator = createFieldValidator(config)
|
|
57
|
+
const _fieldValidatorWrapper = async () => {
|
|
58
|
+
return validator(await valueGetter())
|
|
58
59
|
}
|
|
60
|
+
return _fieldValidatorWrapper
|
|
59
61
|
},
|
|
60
62
|
}
|
|
61
63
|
}
|
|
@@ -101,7 +103,7 @@ const referenceField = config => {
|
|
|
101
103
|
...objToUse,
|
|
102
104
|
functions: {
|
|
103
105
|
...(objToUse.functions ? objToUse.functions : {}),
|
|
104
|
-
|
|
106
|
+
toObj: _getId,
|
|
105
107
|
},
|
|
106
108
|
}
|
|
107
109
|
}
|
package/src/models.js
CHANGED
|
@@ -1,29 +1,36 @@
|
|
|
1
1
|
const merge = require('lodash/merge')
|
|
2
|
-
const
|
|
3
|
-
const {
|
|
2
|
+
const pickBy = require('lodash/pickBy')
|
|
3
|
+
const { toObj } = require('./serialization')
|
|
4
4
|
const { createPropertyTitle } = require('./utils')
|
|
5
5
|
const { createModelValidator } = require('./validation')
|
|
6
6
|
|
|
7
|
-
const
|
|
8
|
-
|
|
7
|
+
const MODEL_DEF_KEYS = ['meta', 'functions']
|
|
9
8
|
const PROTECTED_KEYS = ['model']
|
|
10
9
|
|
|
11
|
-
const createModel = keyToField => {
|
|
10
|
+
const createModel = (modelName, keyToField) => {
|
|
12
11
|
PROTECTED_KEYS.forEach(key => {
|
|
13
12
|
if (key in keyToField) {
|
|
14
13
|
throw new Error(`Cannot use ${key}. This is a protected value.`)
|
|
15
14
|
}
|
|
16
15
|
})
|
|
17
|
-
const
|
|
18
|
-
|
|
19
|
-
|
|
16
|
+
const fieldProperties = Object.entries(keyToField).filter(
|
|
17
|
+
([key, _]) => !(key in MODEL_DEF_KEYS)
|
|
18
|
+
)
|
|
19
|
+
const fields = fieldProperties.reduce((acc, [key, field]) => {
|
|
20
|
+
return { ...acc, [key]: field }
|
|
20
21
|
}, {})
|
|
21
|
-
const
|
|
22
|
-
(
|
|
22
|
+
const modelDefProperties = merge(
|
|
23
|
+
pickBy(keyToField, (value, key) => MODEL_DEF_KEYS.includes(key)),
|
|
24
|
+
{
|
|
25
|
+
meta: {
|
|
26
|
+
fields,
|
|
27
|
+
modelName,
|
|
28
|
+
},
|
|
29
|
+
}
|
|
23
30
|
)
|
|
24
31
|
|
|
25
|
-
return (instanceValues={}) => {
|
|
26
|
-
const loadedInternals =
|
|
32
|
+
return (instanceValues = {}) => {
|
|
33
|
+
const loadedInternals = fieldProperties.reduce((acc, [key, field]) => {
|
|
27
34
|
const fieldGetter = field.createGetter(instanceValues[key])
|
|
28
35
|
const fieldValidator = field.getValidator(fieldGetter)
|
|
29
36
|
const getFieldKey = createPropertyTitle(key)
|
|
@@ -37,16 +44,15 @@ const createModel = keyToField => {
|
|
|
37
44
|
}
|
|
38
45
|
return merge(acc, fleshedOutField)
|
|
39
46
|
}, {})
|
|
40
|
-
const
|
|
41
|
-
const internalFunctions = {
|
|
47
|
+
const frameworkProperties = {
|
|
42
48
|
functions: {
|
|
43
|
-
|
|
49
|
+
toObj: toObj(loadedInternals),
|
|
44
50
|
validate: {
|
|
45
51
|
model: createModelValidator(loadedInternals),
|
|
46
52
|
},
|
|
47
53
|
},
|
|
48
54
|
}
|
|
49
|
-
return merge(
|
|
55
|
+
return merge(loadedInternals, modelDefProperties, frameworkProperties)
|
|
50
56
|
}
|
|
51
57
|
}
|
|
52
58
|
|
package/src/serialization.js
CHANGED
|
@@ -12,8 +12,8 @@ const _getValue = async value => {
|
|
|
12
12
|
return _getValue(await value())
|
|
13
13
|
}
|
|
14
14
|
// Nested Json
|
|
15
|
-
if (type === 'object' && value.functions && value.functions.
|
|
16
|
-
return _getValue(await value.functions.
|
|
15
|
+
if (type === 'object' && value.functions && value.functions.toObj) {
|
|
16
|
+
return _getValue(await value.functions.toObj())
|
|
17
17
|
}
|
|
18
18
|
// Dates
|
|
19
19
|
if (type === 'object' && value.toISOString) {
|
|
@@ -30,7 +30,7 @@ const _shouldIgnoreKey = key => {
|
|
|
30
30
|
return IGNORABLE_KEYS.includes(key)
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
-
const
|
|
33
|
+
const toObj = keyToFunc => async () => {
|
|
34
34
|
return Object.entries(keyToFunc).reduce(async (acc, [key, value]) => {
|
|
35
35
|
const realAcc = await acc
|
|
36
36
|
if (_shouldIgnoreKey(key)) {
|
|
@@ -43,5 +43,5 @@ const toJson = keyToFunc => async () => {
|
|
|
43
43
|
}
|
|
44
44
|
|
|
45
45
|
module.exports = {
|
|
46
|
-
|
|
46
|
+
toObj,
|
|
47
47
|
}
|
package/src/utils.js
CHANGED
|
@@ -6,7 +6,7 @@ const toTitleCase = string => {
|
|
|
6
6
|
return `${string.slice(0, 1).toUpperCase()}${string.slice(1)}`
|
|
7
7
|
}
|
|
8
8
|
|
|
9
|
-
const
|
|
9
|
+
const createFieldTitle = key => {
|
|
10
10
|
const goodName = toTitleCase(key)
|
|
11
11
|
return `get${goodName}`
|
|
12
12
|
}
|
|
@@ -37,6 +37,6 @@ const loweredTitleCase = string => {
|
|
|
37
37
|
module.exports = {
|
|
38
38
|
createUuid,
|
|
39
39
|
loweredTitleCase,
|
|
40
|
-
createPropertyTitle,
|
|
40
|
+
createPropertyTitle: createFieldTitle,
|
|
41
41
|
toTitleCase,
|
|
42
42
|
}
|
package/src/validation.js
CHANGED
|
@@ -130,16 +130,20 @@ const minTextLength = min => value => {
|
|
|
130
130
|
return undefined
|
|
131
131
|
}
|
|
132
132
|
|
|
133
|
-
const aggregateValidator = methodOrMethods =>
|
|
133
|
+
const aggregateValidator = methodOrMethods => {
|
|
134
134
|
const toDo = Array.isArray(methodOrMethods)
|
|
135
135
|
? methodOrMethods
|
|
136
136
|
: [methodOrMethods]
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
137
|
+
|
|
138
|
+
const _aggregativeValidator = async value => {
|
|
139
|
+
const values = await Promise.all(
|
|
140
|
+
toDo.map(method => {
|
|
141
|
+
return method(value)
|
|
142
|
+
})
|
|
143
|
+
)
|
|
144
|
+
return values.filter(x => x)
|
|
145
|
+
}
|
|
146
|
+
return _aggregativeValidator
|
|
143
147
|
}
|
|
144
148
|
|
|
145
149
|
const emptyValidator = () => []
|
|
@@ -166,24 +170,33 @@ const createFieldValidator = config => {
|
|
|
166
170
|
].filter(x => x)
|
|
167
171
|
const validator =
|
|
168
172
|
validators.length > 0 ? aggregateValidator(validators) : emptyValidator
|
|
169
|
-
|
|
173
|
+
const _fieldValidator = async value => {
|
|
170
174
|
const errors = await validator(value)
|
|
171
175
|
return [...new Set(flatMap(errors))]
|
|
172
176
|
}
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
const
|
|
178
|
-
keysAndFunctions.
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
177
|
+
return _fieldValidator
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
const createModelValidator = fields => {
|
|
181
|
+
const _modelValidator = async () => {
|
|
182
|
+
const keysAndFunctions = Object.entries(
|
|
183
|
+
get(fields, 'functions.validate', {})
|
|
184
|
+
)
|
|
185
|
+
const data = await Promise.all(
|
|
186
|
+
keysAndFunctions.map(async ([key, validator]) => {
|
|
187
|
+
if (key === 'model') {
|
|
188
|
+
return [key, []]
|
|
189
|
+
}
|
|
190
|
+
return [key, await validator()]
|
|
191
|
+
})
|
|
192
|
+
)
|
|
193
|
+
return data
|
|
194
|
+
.filter(([_, errors]) => Boolean(errors) && errors.length > 0)
|
|
195
|
+
.reduce((acc, [key, errors]) => {
|
|
196
|
+
return { ...acc, [key]: errors }
|
|
197
|
+
}, {})
|
|
198
|
+
}
|
|
199
|
+
return _modelValidator
|
|
187
200
|
}
|
|
188
201
|
|
|
189
202
|
module.exports = {
|
package/test/src/fields.test.js
CHANGED
|
@@ -481,7 +481,7 @@ describe('/src/fields.js', () => {
|
|
|
481
481
|
assert.deepEqual(actual, expected)
|
|
482
482
|
})
|
|
483
483
|
it('should take the smartObject as a value', async () => {
|
|
484
|
-
const proto = createModel({
|
|
484
|
+
const proto = createModel('name', {
|
|
485
485
|
id: uniqueId({ value: 'obj-id' }),
|
|
486
486
|
})
|
|
487
487
|
const input = [proto({ id: 'obj-id' })]
|
|
@@ -490,23 +490,23 @@ describe('/src/fields.js', () => {
|
|
|
490
490
|
const expected = 'obj-id'
|
|
491
491
|
assert.deepEqual(actual, expected)
|
|
492
492
|
})
|
|
493
|
-
describe('#functions.
|
|
494
|
-
it('should use the getId of the smartObject passed in when
|
|
495
|
-
const proto = createModel({
|
|
493
|
+
describe('#functions.toObj()', () => {
|
|
494
|
+
it('should use the getId of the smartObject passed in when toObj is called', async () => {
|
|
495
|
+
const proto = createModel('name', {
|
|
496
496
|
id: uniqueId({ value: 'obj-id' }),
|
|
497
497
|
})
|
|
498
498
|
const input = [proto({ id: 'obj-id' })]
|
|
499
499
|
const instance = await referenceField({}).createGetter(...input)()
|
|
500
|
-
const actual = await instance.functions.
|
|
500
|
+
const actual = await instance.functions.toObj()
|
|
501
501
|
const expected = 'obj-id'
|
|
502
502
|
assert.deepEqual(actual, expected)
|
|
503
503
|
})
|
|
504
|
-
it('should return "obj-id" when switch-a-roo fetcher is used and
|
|
504
|
+
it('should return "obj-id" when switch-a-roo fetcher is used and toObj is called', async () => {
|
|
505
505
|
const input = ['obj-id']
|
|
506
506
|
const instance = await referenceField({
|
|
507
507
|
fetcher: () => ({ id: 'obj-id', prop: 'switch-a-roo' }),
|
|
508
508
|
}).createGetter(...input)()
|
|
509
|
-
const actual = await instance.functions.
|
|
509
|
+
const actual = await instance.functions.toObj()
|
|
510
510
|
const expected = 'obj-id'
|
|
511
511
|
assert.deepEqual(actual, expected)
|
|
512
512
|
})
|
package/test/src/models.test.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
const _ = require('lodash')
|
|
1
2
|
const assert = require('chai').assert
|
|
2
3
|
const { createModel } = require('../../src/models')
|
|
3
4
|
const { field } = require('../../src/fields')
|
|
@@ -5,7 +6,7 @@ const { field } = require('../../src/fields')
|
|
|
5
6
|
describe('/src/models.js', () => {
|
|
6
7
|
describe('#createModel()', () => {
|
|
7
8
|
it('should return a function when called once with valid data', () => {
|
|
8
|
-
const actual = createModel({})
|
|
9
|
+
const actual = createModel('name', {})
|
|
9
10
|
const expected = 'function'
|
|
10
11
|
assert.isFunction(actual)
|
|
11
12
|
})
|
|
@@ -14,16 +15,44 @@ describe('/src/models.js', () => {
|
|
|
14
15
|
const input = {
|
|
15
16
|
myField: field({ required: true }),
|
|
16
17
|
}
|
|
17
|
-
const model = createModel(input)
|
|
18
|
+
const model = createModel('name', input)
|
|
18
19
|
assert.doesNotThrow(() => {
|
|
19
20
|
model()
|
|
20
21
|
})
|
|
21
22
|
})
|
|
23
|
+
it('should return an object that contains meta.fields.myField', () => {
|
|
24
|
+
const input = {
|
|
25
|
+
myField: field({ required: true }),
|
|
26
|
+
}
|
|
27
|
+
const model = createModel('name', input)
|
|
28
|
+
const instance = model({ myField: 'value' })
|
|
29
|
+
const actual = _.get(instance, 'meta.fields.myField')
|
|
30
|
+
assert.isOk(actual)
|
|
31
|
+
})
|
|
32
|
+
it('should return an object that contains meta.modelName===test-the-name', () => {
|
|
33
|
+
const input = {
|
|
34
|
+
myField: field({ required: true }),
|
|
35
|
+
}
|
|
36
|
+
const model = createModel('test-the-name', input)
|
|
37
|
+
const instance = model({ myField: 'value' })
|
|
38
|
+
const actual = _.get(instance, 'meta.modelName')
|
|
39
|
+
const expected = 'test-the-name'
|
|
40
|
+
assert.deepEqual(actual, expected)
|
|
41
|
+
})
|
|
42
|
+
it('should return an object that contains meta.fields.myField', () => {
|
|
43
|
+
const input = {
|
|
44
|
+
myField: field({ required: true }),
|
|
45
|
+
}
|
|
46
|
+
const model = createModel('name', input)
|
|
47
|
+
const instance = model({ myField: 'value' })
|
|
48
|
+
const actual = _.get(instance, 'meta.fields.myField')
|
|
49
|
+
assert.isOk(actual)
|
|
50
|
+
})
|
|
22
51
|
it('should use the value passed in when field.defaultValue and field.value are not set', async () => {
|
|
23
52
|
const input = {
|
|
24
53
|
myField: field({ required: true }),
|
|
25
54
|
}
|
|
26
|
-
const model = createModel(input)
|
|
55
|
+
const model = createModel('name', input)
|
|
27
56
|
const instance = model({ myField: 'passed-in' })
|
|
28
57
|
const actual = await instance.getMyField()
|
|
29
58
|
const expected = 'passed-in'
|
|
@@ -33,7 +62,7 @@ describe('/src/models.js', () => {
|
|
|
33
62
|
const input = {
|
|
34
63
|
myField: field({ value: 'value', defaultValue: 'default-value' }),
|
|
35
64
|
}
|
|
36
|
-
const model = createModel(input)
|
|
65
|
+
const model = createModel('name', input)
|
|
37
66
|
const instance = model({ myField: 'passed-in' })
|
|
38
67
|
const actual = await instance.getMyField()
|
|
39
68
|
const expected = 'value'
|
|
@@ -43,7 +72,7 @@ describe('/src/models.js', () => {
|
|
|
43
72
|
const input = {
|
|
44
73
|
myField: field({ value: 'value' }),
|
|
45
74
|
}
|
|
46
|
-
const model = createModel(input)
|
|
75
|
+
const model = createModel('name', input)
|
|
47
76
|
const instance = model({ myField: 'passed-in' })
|
|
48
77
|
const actual = await instance.getMyField()
|
|
49
78
|
const expected = 'value'
|
|
@@ -53,7 +82,7 @@ describe('/src/models.js', () => {
|
|
|
53
82
|
const input = {
|
|
54
83
|
myField: field({ defaultValue: 'defaultValue' }),
|
|
55
84
|
}
|
|
56
|
-
const model = createModel(input)
|
|
85
|
+
const model = createModel('name', input)
|
|
57
86
|
const instance = model({})
|
|
58
87
|
const actual = await instance.getMyField()
|
|
59
88
|
const expected = 'defaultValue'
|
|
@@ -63,7 +92,7 @@ describe('/src/models.js', () => {
|
|
|
63
92
|
const input = {
|
|
64
93
|
myField: field({ defaultValue: 'defaultValue' }),
|
|
65
94
|
}
|
|
66
|
-
const model = createModel(input)
|
|
95
|
+
const model = createModel('name', input)
|
|
67
96
|
const instance = model({ myField: null })
|
|
68
97
|
const actual = await instance.getMyField()
|
|
69
98
|
const expected = 'defaultValue'
|
|
@@ -74,7 +103,7 @@ describe('/src/models.js', () => {
|
|
|
74
103
|
id: field({ required: true }),
|
|
75
104
|
type: field(),
|
|
76
105
|
}
|
|
77
|
-
const model = createModel(input)
|
|
106
|
+
const model = createModel('name', input)
|
|
78
107
|
const actual = model({ id: 'my-id', type: 'my-type' })
|
|
79
108
|
assert.isOk(actual.getId)
|
|
80
109
|
assert.isOk(actual.getType)
|
|
@@ -84,7 +113,7 @@ describe('/src/models.js', () => {
|
|
|
84
113
|
id: field({ required: true }),
|
|
85
114
|
type: field(),
|
|
86
115
|
}
|
|
87
|
-
const model = createModel(input)
|
|
116
|
+
const model = createModel('name', input)
|
|
88
117
|
const instance = model({ type: 'my-type' })
|
|
89
118
|
const actual = await instance.functions.validate.model()
|
|
90
119
|
const expected = 1
|
|
@@ -92,12 +121,12 @@ describe('/src/models.js', () => {
|
|
|
92
121
|
})
|
|
93
122
|
})
|
|
94
123
|
it('should return a function when called once with valid data', () => {
|
|
95
|
-
const actual = createModel({})
|
|
124
|
+
const actual = createModel('name', {})
|
|
96
125
|
assert.isFunction(actual)
|
|
97
126
|
})
|
|
98
127
|
it('should throw an exception if a key "model" is passed in', () => {
|
|
99
128
|
assert.throws(() => {
|
|
100
|
-
createModel({ model: 'weeee' })
|
|
129
|
+
createModel('name', { model: 'weeee' })
|
|
101
130
|
})
|
|
102
131
|
})
|
|
103
132
|
})
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
const assert = require('chai').assert
|
|
2
|
-
const {
|
|
2
|
+
const { toObj } = require('../../src/serialization')
|
|
3
3
|
|
|
4
4
|
describe('/src/serialization.js', () => {
|
|
5
|
-
describe('#
|
|
5
|
+
describe('#toObj()', () => {
|
|
6
6
|
it('serialize a very basic input of key-value', async () => {
|
|
7
|
-
const actual = await
|
|
7
|
+
const actual = await toObj({
|
|
8
8
|
key: 'value',
|
|
9
9
|
key2: 'value2',
|
|
10
10
|
})()
|
|
@@ -15,7 +15,7 @@ describe('/src/serialization.js', () => {
|
|
|
15
15
|
assert.deepEqual(actual, expected)
|
|
16
16
|
})
|
|
17
17
|
it('should ignore "meta" properties', async () => {
|
|
18
|
-
const actual = await
|
|
18
|
+
const actual = await toObj({
|
|
19
19
|
key: 'value',
|
|
20
20
|
key2: 'value2',
|
|
21
21
|
meta: {
|
|
@@ -29,7 +29,7 @@ describe('/src/serialization.js', () => {
|
|
|
29
29
|
assert.deepEqual(actual, expected)
|
|
30
30
|
})
|
|
31
31
|
it('should ignore "functions" properties', async () => {
|
|
32
|
-
const actual = await
|
|
32
|
+
const actual = await toObj({
|
|
33
33
|
key: 'value',
|
|
34
34
|
key2: 'value2',
|
|
35
35
|
functions: {
|
|
@@ -44,13 +44,13 @@ describe('/src/serialization.js', () => {
|
|
|
44
44
|
}
|
|
45
45
|
assert.deepEqual(actual, expected)
|
|
46
46
|
})
|
|
47
|
-
it('should call "functions.
|
|
48
|
-
const actual = await
|
|
47
|
+
it('should call "functions.toObj" on nested objects', async () => {
|
|
48
|
+
const actual = await toObj({
|
|
49
49
|
key: 'value',
|
|
50
50
|
key2: {
|
|
51
51
|
complex: () => ({ func: 'func' }),
|
|
52
52
|
functions: {
|
|
53
|
-
|
|
53
|
+
toObj: () => ({ func: 'value' }),
|
|
54
54
|
},
|
|
55
55
|
},
|
|
56
56
|
})()
|
|
@@ -62,12 +62,12 @@ describe('/src/serialization.js', () => {
|
|
|
62
62
|
}
|
|
63
63
|
assert.deepEqual(actual, expected)
|
|
64
64
|
})
|
|
65
|
-
it('should call "
|
|
66
|
-
const actual = await
|
|
65
|
+
it('should call "toObj" on very nested objects', async () => {
|
|
66
|
+
const actual = await toObj({
|
|
67
67
|
key: 'value',
|
|
68
68
|
key2: {
|
|
69
69
|
functions: {
|
|
70
|
-
|
|
70
|
+
toObj: () => ({ func: 'value' }),
|
|
71
71
|
},
|
|
72
72
|
},
|
|
73
73
|
})()
|
|
@@ -80,7 +80,7 @@ describe('/src/serialization.js', () => {
|
|
|
80
80
|
assert.deepEqual(actual, expected)
|
|
81
81
|
})
|
|
82
82
|
it('should set an undefined property to null', async () => {
|
|
83
|
-
const actual = await
|
|
83
|
+
const actual = await toObj({
|
|
84
84
|
key: 'value',
|
|
85
85
|
key2: undefined,
|
|
86
86
|
})()
|
|
@@ -91,7 +91,7 @@ describe('/src/serialization.js', () => {
|
|
|
91
91
|
assert.deepEqual(actual, expected)
|
|
92
92
|
})
|
|
93
93
|
it('should get the value of a function', async () => {
|
|
94
|
-
const actual = await
|
|
94
|
+
const actual = await toObj({
|
|
95
95
|
key: 'value',
|
|
96
96
|
key2: () => {
|
|
97
97
|
return 'funcvalue'
|
|
@@ -104,7 +104,7 @@ describe('/src/serialization.js', () => {
|
|
|
104
104
|
assert.deepEqual(actual, expected)
|
|
105
105
|
})
|
|
106
106
|
it('should change property getTheValue to "theValue"', async () => {
|
|
107
|
-
const actual = await
|
|
107
|
+
const actual = await toObj({
|
|
108
108
|
key: 'value',
|
|
109
109
|
getTheValue: () => 'funcvalue',
|
|
110
110
|
})()
|
|
@@ -115,7 +115,7 @@ describe('/src/serialization.js', () => {
|
|
|
115
115
|
assert.deepEqual(actual, expected)
|
|
116
116
|
})
|
|
117
117
|
it('should return "2021-09-16T21:51:56.039Z" for the set date.', async () => {
|
|
118
|
-
const actual = await
|
|
118
|
+
const actual = await toObj({
|
|
119
119
|
myDate: new Date('2021-09-16T21:51:56.039Z'),
|
|
120
120
|
})()
|
|
121
121
|
const expected = {
|
|
@@ -258,6 +258,20 @@ describe('/src/validation.js', () => {
|
|
|
258
258
|
sinon.assert.calledOnce(fields.functions.validate.id)
|
|
259
259
|
sinon.assert.calledOnce(fields.functions.validate.type)
|
|
260
260
|
})
|
|
261
|
+
it('should not run a validate.model function', async () => {
|
|
262
|
+
const fields = {
|
|
263
|
+
functions: {
|
|
264
|
+
validate: {
|
|
265
|
+
id: sinon.stub().returns(undefined),
|
|
266
|
+
type: sinon.stub().returns(undefined),
|
|
267
|
+
model: sinon.stub().returns(undefined),
|
|
268
|
+
},
|
|
269
|
+
},
|
|
270
|
+
}
|
|
271
|
+
const validator = createModelValidator(fields)
|
|
272
|
+
await validator()
|
|
273
|
+
sinon.assert.notCalled(fields.functions.validate.model)
|
|
274
|
+
})
|
|
261
275
|
it('should combine results for both functions.validate for two objects that error', async () => {
|
|
262
276
|
const fields = {
|
|
263
277
|
functions: {
|