functional-models 1.0.27 → 1.1.2
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/.eslintignore +1 -0
- package/.eslintrc +9 -15
- package/cucumber.js +10 -0
- package/dist/src/constants.d.ts +14 -0
- package/dist/src/constants.js +19 -0
- package/dist/src/constants.js.map +1 -0
- package/dist/src/errors.d.ts +9 -0
- package/dist/src/errors.js +15 -0
- package/dist/src/errors.js.map +1 -0
- package/dist/src/index.d.ts +9 -0
- package/dist/src/index.js +39 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/interfaces.d.ts +145 -0
- package/dist/src/interfaces.js +5 -0
- package/dist/src/interfaces.js.map +1 -0
- package/dist/src/lazy.d.ts +2 -0
- package/dist/src/lazy.js +37 -0
- package/dist/src/lazy.js.map +1 -0
- package/dist/src/methods.d.ts +4 -0
- package/dist/src/methods.js +18 -0
- package/dist/src/methods.js.map +1 -0
- package/dist/src/models.d.ts +3 -0
- package/dist/src/models.js +128 -0
- package/dist/src/models.js.map +1 -0
- package/dist/src/properties.d.ts +16 -0
- package/dist/src/properties.js +208 -0
- package/dist/src/properties.js.map +1 -0
- package/dist/src/serialization.d.ts +3 -0
- package/dist/src/serialization.js +49 -0
- package/dist/src/serialization.js.map +1 -0
- package/dist/src/utils.d.ts +4 -0
- package/dist/src/utils.js +44 -0
- package/dist/src/utils.js.map +1 -0
- package/dist/src/validation.d.ts +29 -0
- package/dist/src/validation.js +286 -0
- package/dist/src/validation.js.map +1 -0
- package/dist/stepDefinitions/oldSteps.d.ts +1 -0
- package/dist/stepDefinitions/oldSteps.js +191 -0
- package/dist/stepDefinitions/oldSteps.js.map +1 -0
- package/dist/stepDefinitions/tssteps.d.ts +1 -0
- package/dist/stepDefinitions/tssteps.js +96 -0
- package/dist/stepDefinitions/tssteps.js.map +1 -0
- package/dist/test/src/errors.test.d.ts +1 -0
- package/dist/test/src/errors.test.js +33 -0
- package/dist/test/src/errors.test.js.map +1 -0
- package/dist/test/src/lazy.test.d.ts +1 -0
- package/dist/test/src/lazy.test.js +28 -0
- package/dist/test/src/lazy.test.js.map +1 -0
- package/dist/test/src/methods.test.d.ts +1 -0
- package/dist/test/src/methods.test.js +48 -0
- package/dist/test/src/methods.test.js.map +1 -0
- package/dist/test/src/models.test.d.ts +1 -0
- package/dist/test/src/models.test.js +395 -0
- package/dist/test/src/models.test.js.map +1 -0
- package/dist/test/src/properties.test.d.ts +1 -0
- package/dist/test/src/properties.test.js +724 -0
- package/dist/test/src/properties.test.js.map +1 -0
- package/dist/test/src/serialization.test.d.ts +1 -0
- package/dist/test/src/serialization.test.js +91 -0
- package/dist/test/src/serialization.test.js.map +1 -0
- package/dist/test/src/utils.test.d.ts +1 -0
- package/dist/test/src/utils.test.js +81 -0
- package/dist/test/src/utils.test.js.map +1 -0
- package/dist/test/src/validation.test.d.ts +1 -0
- package/dist/test/src/validation.test.js +612 -0
- package/dist/test/src/validation.test.js.map +1 -0
- package/features/arrayFields.feature +7 -7
- package/features/basic-ts.feature +13 -0
- package/features/functions.feature +2 -3
- package/package.json +35 -10
- package/src/constants.ts +15 -0
- package/src/{errors.js → errors.ts} +6 -4
- package/src/index.ts +12 -0
- package/src/interfaces.ts +323 -0
- package/src/lazy.ts +24 -0
- package/src/methods.ts +30 -0
- package/src/models.ts +183 -0
- package/src/properties.ts +375 -0
- package/src/serialization.ts +39 -0
- package/src/{utils.js → utils.ts} +16 -26
- package/src/validation.ts +390 -0
- package/{features/stepDefinitions/steps.js → stepDefinitions/oldSteps.ts} +76 -53
- package/stepDefinitions/tssteps.ts +107 -0
- package/test/src/errors.test.ts +31 -0
- package/test/src/{lazy.test.js → lazy.test.ts} +4 -4
- package/test/src/methods.test.ts +45 -0
- package/test/src/models.test.ts +417 -0
- package/test/src/{properties.test.js → properties.test.ts} +251 -58
- package/test/src/serialization.test.ts +80 -0
- package/test/src/{utils.test.js → utils.test.ts} +29 -7
- package/test/src/{validation.test.js → validation.test.ts} +278 -210
- package/tsconfig.json +100 -0
- package/src/constants.js +0 -19
- package/src/functions.js +0 -7
- package/src/index.js +0 -10
- package/src/lazy.js +0 -19
- package/src/models.js +0 -152
- package/src/properties.js +0 -313
- package/src/serialization.js +0 -50
- package/src/validation.js +0 -285
- package/test/base/index.test.js +0 -5
- package/test/src/functions.test.js +0 -45
- package/test/src/index.test.js +0 -5
- package/test/src/models.test.js +0 -380
- package/test/src/serialization.test.js +0 -127
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { Given, When, Then } from '@cucumber/cucumber'
|
|
2
|
+
import { assert } from 'chai'
|
|
3
|
+
import { BaseModel } from '../src/models'
|
|
4
|
+
import { WrapperInstanceMethod, WrapperModelMethod } from '../src/methods'
|
|
5
|
+
import {
|
|
6
|
+
Model,
|
|
7
|
+
FunctionalModel,
|
|
8
|
+
ModelInstanceMethodTyped,
|
|
9
|
+
ModelMethodTyped,
|
|
10
|
+
ModelInstanceInputData,
|
|
11
|
+
Nullable,
|
|
12
|
+
} from '../src/interfaces'
|
|
13
|
+
import { ObjectProperty, TextProperty, UniqueId } from '../src/properties'
|
|
14
|
+
|
|
15
|
+
type MyTSType = {
|
|
16
|
+
name: string
|
|
17
|
+
data: FunctionalModel
|
|
18
|
+
notRequired?: Nullable<string>
|
|
19
|
+
myMethod: ModelInstanceMethodTyped<MyTSType>
|
|
20
|
+
myModelMethod: ModelMethodTyped<MyTSType>
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const TE_FULL_TEST = () => {
|
|
24
|
+
const m = BaseModel<MyTSType>('TSFullTests', {
|
|
25
|
+
properties: {
|
|
26
|
+
id: UniqueId({ value: 'my-unique-id' }),
|
|
27
|
+
name: TextProperty({ required: true }),
|
|
28
|
+
data: ObjectProperty({}),
|
|
29
|
+
notRequired: TextProperty({}),
|
|
30
|
+
},
|
|
31
|
+
instanceMethods: {
|
|
32
|
+
myMethod: WrapperInstanceMethod<MyTSType>((instance, args) => {
|
|
33
|
+
return 'InstanceMethod'
|
|
34
|
+
}),
|
|
35
|
+
},
|
|
36
|
+
modelMethods: {
|
|
37
|
+
myModelMethod: WrapperModelMethod<MyTSType>((model, args) => {
|
|
38
|
+
return 'ModelMethod'
|
|
39
|
+
}),
|
|
40
|
+
},
|
|
41
|
+
})
|
|
42
|
+
return m
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const TE_FULL_TEST_1 = () => {
|
|
46
|
+
return {
|
|
47
|
+
id: 'my-unique-id',
|
|
48
|
+
name: 'My name',
|
|
49
|
+
data: { my: 'data' },
|
|
50
|
+
notRequired: null,
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const DATA_SET: { [s: string]: () => ModelInstanceInputData<MyTSType> } = {
|
|
55
|
+
TE_FULL_TEST_1,
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const MODEL_SET: { [s: string]: () => Model<MyTSType> } = {
|
|
59
|
+
TE_FULL_TEST,
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
Given('model {word} is used', function (modelName: string) {
|
|
63
|
+
this.theModel = MODEL_SET[modelName]()
|
|
64
|
+
})
|
|
65
|
+
|
|
66
|
+
When(
|
|
67
|
+
'a model instanced is created is called on model with {word}',
|
|
68
|
+
async function (dataName: string) {
|
|
69
|
+
this.theModelInstance = this.theModel.create(DATA_SET[dataName]())
|
|
70
|
+
}
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
When('toObj is called on the model instance', async function () {
|
|
74
|
+
this.results = await this.theModelInstance.toObj()
|
|
75
|
+
})
|
|
76
|
+
|
|
77
|
+
Then('the results match {word} obj data', function (dataName) {
|
|
78
|
+
const data = DATA_SET[dataName]()
|
|
79
|
+
assert.deepEqual(data, this.results)
|
|
80
|
+
})
|
|
81
|
+
|
|
82
|
+
When('instance method {word} is called', async function (methodName) {
|
|
83
|
+
this.instanceMethodActual = await this.theModelInstance.methods[methodName]()
|
|
84
|
+
})
|
|
85
|
+
|
|
86
|
+
Then('the result of instance method is {word}', function (expected) {
|
|
87
|
+
const actual = this.instanceMethodActual
|
|
88
|
+
assert.equal(actual, expected)
|
|
89
|
+
})
|
|
90
|
+
|
|
91
|
+
When('model method {word} is called', async function (methodName) {
|
|
92
|
+
this.modelMethodActual = await this.theModel.methods[methodName]()
|
|
93
|
+
})
|
|
94
|
+
|
|
95
|
+
Then('the result of model method is {word}', function (expected) {
|
|
96
|
+
const actual = this.modelMethodActual
|
|
97
|
+
assert.equal(actual, expected)
|
|
98
|
+
})
|
|
99
|
+
|
|
100
|
+
When('validate is called on model instance', async function () {
|
|
101
|
+
this.validationActual = await this.theModelInstance.validate()
|
|
102
|
+
})
|
|
103
|
+
|
|
104
|
+
Then('the model instance validated successfully', function () {
|
|
105
|
+
const expected = {}
|
|
106
|
+
assert.deepEqual(this.validationActual, expected)
|
|
107
|
+
})
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { assert } from 'chai'
|
|
2
|
+
import { ValidationError } from '../../src/errors'
|
|
3
|
+
|
|
4
|
+
describe('/src/errors.ts', () => {
|
|
5
|
+
describe('ValidationError', () => {
|
|
6
|
+
it('should have the correct modelName', () => {
|
|
7
|
+
const instance = new ValidationError('modelName', {
|
|
8
|
+
name: ['error1', 'error2'],
|
|
9
|
+
})
|
|
10
|
+
const actual = instance.modelName
|
|
11
|
+
const expected = 'modelName'
|
|
12
|
+
assert.equal(actual, expected)
|
|
13
|
+
})
|
|
14
|
+
it('should have the correct keysToErrors', () => {
|
|
15
|
+
const instance = new ValidationError('modelName', {
|
|
16
|
+
name: ['error1', 'error2'],
|
|
17
|
+
})
|
|
18
|
+
const actual = instance.keysToErrors
|
|
19
|
+
const expected = { name: ['error1', 'error2'] }
|
|
20
|
+
assert.deepEqual(actual, expected)
|
|
21
|
+
})
|
|
22
|
+
it('should have the correct name', () => {
|
|
23
|
+
const instance = new ValidationError('modelName', {
|
|
24
|
+
name: ['error1', 'error2'],
|
|
25
|
+
})
|
|
26
|
+
const actual = instance.name
|
|
27
|
+
const expected = 'ValidationError'
|
|
28
|
+
assert.equal(actual, expected)
|
|
29
|
+
})
|
|
30
|
+
})
|
|
31
|
+
})
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import { assert } from 'chai'
|
|
2
|
+
import sinon from 'sinon'
|
|
3
|
+
import { lazyValue } from '../../src/lazy'
|
|
4
4
|
|
|
5
|
-
describe('/src/lazy.
|
|
5
|
+
describe('/src/lazy.ts', () => {
|
|
6
6
|
describe('#lazyValue()', () => {
|
|
7
7
|
it('should only call the method passed in once even after two calls', async () => {
|
|
8
8
|
const method = sinon.stub().returns('hello-world')
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { assert } from 'chai'
|
|
2
|
+
import sinon from 'sinon'
|
|
3
|
+
import { BaseModel } from '../../src/models'
|
|
4
|
+
import { TextProperty, Property } from '../../src/properties'
|
|
5
|
+
import { WrapperInstanceMethod } from '../../src/methods'
|
|
6
|
+
|
|
7
|
+
type TEST_MODEL_TYPE = { text: string }
|
|
8
|
+
|
|
9
|
+
describe('/src/methods.js', () => {
|
|
10
|
+
describe('#InstanceMethod()', () => {
|
|
11
|
+
it('should return "Hello-world" when passed in', () => {
|
|
12
|
+
const method = sinon.stub().callsFake(input => {
|
|
13
|
+
return `${input.get.text()}-world`
|
|
14
|
+
})
|
|
15
|
+
const myInstanceMethod = WrapperInstanceMethod<TEST_MODEL_TYPE>(method)
|
|
16
|
+
const wrappedObj = 'Hello'
|
|
17
|
+
const model = BaseModel<TEST_MODEL_TYPE>('Test', {
|
|
18
|
+
properties: { text: TextProperty() },
|
|
19
|
+
})
|
|
20
|
+
const modelInstance = model.create({ text: 'Hello' })
|
|
21
|
+
const actual = myInstanceMethod(modelInstance)
|
|
22
|
+
const expected = 'Hello-world'
|
|
23
|
+
assert.equal(actual, expected)
|
|
24
|
+
})
|
|
25
|
+
it('should call the method when InstanceMethod()() called', () => {
|
|
26
|
+
const method = sinon.stub().callsFake(input => {
|
|
27
|
+
return `${input}-world`
|
|
28
|
+
})
|
|
29
|
+
const myInstanceMethod = WrapperInstanceMethod<TEST_MODEL_TYPE>(method)
|
|
30
|
+
const model = BaseModel<TEST_MODEL_TYPE>('Test', {
|
|
31
|
+
properties: { text: TextProperty() },
|
|
32
|
+
})
|
|
33
|
+
const modelInstance = model.create({ text: 'Hello' })
|
|
34
|
+
const actual = myInstanceMethod(modelInstance)
|
|
35
|
+
sinon.assert.calledOnce(method)
|
|
36
|
+
})
|
|
37
|
+
it('should not call the method when InstanceMethod() called', () => {
|
|
38
|
+
const method = sinon.stub().callsFake(input => {
|
|
39
|
+
return `${input}-world`
|
|
40
|
+
})
|
|
41
|
+
const myInstanceMethod = WrapperInstanceMethod<TEST_MODEL_TYPE>(method)
|
|
42
|
+
sinon.assert.notCalled(method)
|
|
43
|
+
})
|
|
44
|
+
})
|
|
45
|
+
})
|
|
@@ -0,0 +1,417 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ModelDefinition,
|
|
3
|
+
ReferenceValueType,
|
|
4
|
+
ModelMethod,
|
|
5
|
+
ModelInstanceMethod,
|
|
6
|
+
ModelInstance,
|
|
7
|
+
} from '../../src/interfaces'
|
|
8
|
+
|
|
9
|
+
import _ from 'lodash'
|
|
10
|
+
import sinon from 'sinon'
|
|
11
|
+
import { assert } from 'chai'
|
|
12
|
+
import { BaseModel } from '../../src/models'
|
|
13
|
+
import { Property, TextProperty, ReferenceProperty } from '../../src/properties'
|
|
14
|
+
import { WrapperInstanceMethod, WrapperModelMethod } from '../../src/methods'
|
|
15
|
+
import { UniqueId } from '../../src/properties'
|
|
16
|
+
|
|
17
|
+
type TEST_MODEL_TYPE = {
|
|
18
|
+
name: string
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const TEST_MODEL_1 = BaseModel<TEST_MODEL_TYPE>('MyModel', {
|
|
22
|
+
properties: {
|
|
23
|
+
name: TextProperty(),
|
|
24
|
+
},
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
describe('/src/models.ts', () => {
|
|
28
|
+
describe('#Model()', () => {
|
|
29
|
+
it('should pass a functional instance to the instanceMethods by the time the function is called by a client', () => {
|
|
30
|
+
const model = BaseModel<{
|
|
31
|
+
name: string
|
|
32
|
+
func1: ModelInstanceMethod
|
|
33
|
+
func2: ModelInstanceMethod
|
|
34
|
+
}>('ModelName', {
|
|
35
|
+
properties: {
|
|
36
|
+
name: TextProperty(),
|
|
37
|
+
},
|
|
38
|
+
instanceMethods: {
|
|
39
|
+
func1: WrapperInstanceMethod((instance: ModelInstance<any>) => {
|
|
40
|
+
// @ts-ignore
|
|
41
|
+
return instance.methods.func2()
|
|
42
|
+
}),
|
|
43
|
+
func2: (instance: ModelInstance<any>) => {
|
|
44
|
+
return 'from instance func2'
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
})
|
|
48
|
+
const instance = model.create({ name: 'name' })
|
|
49
|
+
const actual = instance.methods.func1()
|
|
50
|
+
const expected = 'from instance func2'
|
|
51
|
+
assert.deepEqual(actual, expected)
|
|
52
|
+
})
|
|
53
|
+
it('should pass the clients arguments before the model is passed', () => {
|
|
54
|
+
const model = BaseModel<{ func1: ModelMethod; func2: ModelMethod }>(
|
|
55
|
+
'ModelName',
|
|
56
|
+
{
|
|
57
|
+
properties: {},
|
|
58
|
+
modelMethods: {
|
|
59
|
+
func1: WrapperModelMethod((model, input) => {
|
|
60
|
+
return `${input} ${model.methods.func2()}`
|
|
61
|
+
}),
|
|
62
|
+
func2: WrapperModelMethod(model => {
|
|
63
|
+
return 'from func2'
|
|
64
|
+
}),
|
|
65
|
+
},
|
|
66
|
+
}
|
|
67
|
+
)
|
|
68
|
+
const actual = model.methods.func1('hello')
|
|
69
|
+
const expected = 'hello from func2'
|
|
70
|
+
assert.deepEqual(actual, expected)
|
|
71
|
+
})
|
|
72
|
+
it('should pass a functional model to the modelFunction by the time the function is called by a client', () => {
|
|
73
|
+
const model = BaseModel<{ func1: ModelMethod; func2: ModelMethod }>(
|
|
74
|
+
'ModelName',
|
|
75
|
+
{
|
|
76
|
+
properties: {},
|
|
77
|
+
modelMethods: {
|
|
78
|
+
func1: model => {
|
|
79
|
+
return model.methods.func2()
|
|
80
|
+
},
|
|
81
|
+
func2: model => {
|
|
82
|
+
return 'from func2'
|
|
83
|
+
},
|
|
84
|
+
},
|
|
85
|
+
}
|
|
86
|
+
)
|
|
87
|
+
const actual = model.methods.func1()
|
|
88
|
+
const expected = 'from func2'
|
|
89
|
+
assert.deepEqual(actual, expected)
|
|
90
|
+
})
|
|
91
|
+
it('should find model.myString when modelExtension has myString function in it', () => {
|
|
92
|
+
const model = BaseModel<{ myString: ModelMethod }>('ModelName', {
|
|
93
|
+
properties: {},
|
|
94
|
+
modelMethods: {
|
|
95
|
+
myString: model => {
|
|
96
|
+
return 'To String'
|
|
97
|
+
},
|
|
98
|
+
},
|
|
99
|
+
})
|
|
100
|
+
assert.isFunction(model.methods.myString)
|
|
101
|
+
})
|
|
102
|
+
describe('#getPrimaryKeyName()', () => {
|
|
103
|
+
it('should return "primaryKey" when this value is passed in as the primaryKey', () => {
|
|
104
|
+
const expected = 'primaryKey'
|
|
105
|
+
const model = BaseModel<{ myString: ModelMethod }>('ModelName', {
|
|
106
|
+
getPrimaryKeyName: () => expected,
|
|
107
|
+
properties: {},
|
|
108
|
+
modelMethods: {
|
|
109
|
+
myString: model => {
|
|
110
|
+
return 'To String'
|
|
111
|
+
},
|
|
112
|
+
},
|
|
113
|
+
})
|
|
114
|
+
const actual = model.getPrimaryKeyName()
|
|
115
|
+
assert.equal(actual, expected)
|
|
116
|
+
})
|
|
117
|
+
})
|
|
118
|
+
describe('#create()', () => {
|
|
119
|
+
it('should have a references.theReference when properties has a ReferenceProperty named "theReference"', () => {
|
|
120
|
+
const model = BaseModel<{
|
|
121
|
+
theReference?: ReferenceValueType<TEST_MODEL_TYPE>
|
|
122
|
+
}>('ModelName', {
|
|
123
|
+
properties: {
|
|
124
|
+
theReference: ReferenceProperty(TEST_MODEL_1),
|
|
125
|
+
},
|
|
126
|
+
})
|
|
127
|
+
const instance = model.create({})
|
|
128
|
+
assert.isFunction(instance.references.theReference)
|
|
129
|
+
})
|
|
130
|
+
it('should have an "get.id" field when no primaryKey is passed', () => {
|
|
131
|
+
const model = BaseModel<{}>('ModelName', {
|
|
132
|
+
properties: {},
|
|
133
|
+
})
|
|
134
|
+
const instance = model.create({})
|
|
135
|
+
assert.isFunction(instance.get.id)
|
|
136
|
+
})
|
|
137
|
+
it('should have an "getMyPrimaryKeyId" field when "myPrimaryKeyId" is passed as the "getPrimaryKey" is passed', () => {
|
|
138
|
+
const model = BaseModel<{ myPrimaryKeyId: string }>('ModelName', {
|
|
139
|
+
getPrimaryKeyName: () => 'myPrimaryKeyId',
|
|
140
|
+
properties: {
|
|
141
|
+
myPrimaryKeyId: UniqueId(),
|
|
142
|
+
},
|
|
143
|
+
})
|
|
144
|
+
const instance = model.create({ myPrimaryKeyId: 'blah' })
|
|
145
|
+
assert.isFunction(instance.get.myPrimaryKeyId)
|
|
146
|
+
})
|
|
147
|
+
it('should find instance.methods.toString when in instanceMethods', () => {
|
|
148
|
+
const model = BaseModel<{ toString: ModelInstanceMethod }>(
|
|
149
|
+
'ModelName',
|
|
150
|
+
{
|
|
151
|
+
properties: {},
|
|
152
|
+
instanceMethods: {
|
|
153
|
+
toString: instance => {
|
|
154
|
+
return 'An instance'
|
|
155
|
+
},
|
|
156
|
+
},
|
|
157
|
+
}
|
|
158
|
+
)
|
|
159
|
+
const instance = model.create({})
|
|
160
|
+
assert.isFunction(instance.methods.toString)
|
|
161
|
+
})
|
|
162
|
+
it('should call all the instanceCreatedCallback functions when create() is called', () => {
|
|
163
|
+
const input = {
|
|
164
|
+
properties: {
|
|
165
|
+
myProperty: TextProperty({ required: true }),
|
|
166
|
+
},
|
|
167
|
+
}
|
|
168
|
+
const callbacks = [sinon.stub(), sinon.stub()]
|
|
169
|
+
const model = BaseModel('name', input, {
|
|
170
|
+
instanceCreatedCallback: callbacks,
|
|
171
|
+
})
|
|
172
|
+
model.create({ myProperty: 'value' })
|
|
173
|
+
callbacks.forEach(x => {
|
|
174
|
+
sinon.assert.calledOnce(x)
|
|
175
|
+
})
|
|
176
|
+
})
|
|
177
|
+
it('should call the instanceCreatedCallback function when create() is called', () => {
|
|
178
|
+
const input = {
|
|
179
|
+
properties: {
|
|
180
|
+
myProperty: TextProperty({ required: true }),
|
|
181
|
+
},
|
|
182
|
+
}
|
|
183
|
+
const callback = sinon.stub()
|
|
184
|
+
const model = BaseModel('name', input, {
|
|
185
|
+
instanceCreatedCallback: callback,
|
|
186
|
+
})
|
|
187
|
+
model.create({ myProperty: 'value' })
|
|
188
|
+
sinon.assert.calledOnce(callback)
|
|
189
|
+
})
|
|
190
|
+
it('should not throw an exception if nothing is passed into function', () => {
|
|
191
|
+
const input = {
|
|
192
|
+
properties: {
|
|
193
|
+
myProperty: TextProperty({ required: true }),
|
|
194
|
+
},
|
|
195
|
+
}
|
|
196
|
+
const model = BaseModel('name', input)
|
|
197
|
+
assert.doesNotThrow(() => {
|
|
198
|
+
model.create({})
|
|
199
|
+
})
|
|
200
|
+
})
|
|
201
|
+
it('should return an object that contains getModel().getModelDefinition().properties.myProperty', () => {
|
|
202
|
+
type MyType = { myProperty: string }
|
|
203
|
+
const input: ModelDefinition<MyType> = {
|
|
204
|
+
properties: {
|
|
205
|
+
myProperty: TextProperty({ required: true }),
|
|
206
|
+
},
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
const model = BaseModel<MyType>('name', input)
|
|
210
|
+
const instance = model.create({ myProperty: 'value' })
|
|
211
|
+
const actual = instance.getModel().getModelDefinition()
|
|
212
|
+
.properties.myProperty
|
|
213
|
+
assert.isOk(actual)
|
|
214
|
+
})
|
|
215
|
+
it('should flow through the additional special functions within the keyValues', () => {
|
|
216
|
+
const input = {
|
|
217
|
+
properties: {
|
|
218
|
+
myProperty: TextProperty({ required: true }),
|
|
219
|
+
},
|
|
220
|
+
instanceMethods: {
|
|
221
|
+
custom: () => 'works',
|
|
222
|
+
},
|
|
223
|
+
}
|
|
224
|
+
const model = BaseModel<{
|
|
225
|
+
myProperty: string
|
|
226
|
+
custom: ModelInstanceMethod
|
|
227
|
+
}>('name', input)
|
|
228
|
+
const instance = model.create({ myProperty: 'value' })
|
|
229
|
+
const actual = instance.methods.custom()
|
|
230
|
+
const expected = 'works'
|
|
231
|
+
assert.equal(actual, expected)
|
|
232
|
+
})
|
|
233
|
+
it('should return an object that contains .getModel().getName()===test-the-name', () => {
|
|
234
|
+
const input = {
|
|
235
|
+
properties: {
|
|
236
|
+
myProperty: TextProperty({ required: true }),
|
|
237
|
+
},
|
|
238
|
+
}
|
|
239
|
+
const model = BaseModel('test-the-name', input)
|
|
240
|
+
const instance = model.create({ myProperty: 'value' })
|
|
241
|
+
const actual = instance.getModel().getName()
|
|
242
|
+
const expected = 'test-the-name'
|
|
243
|
+
assert.deepEqual(actual, expected)
|
|
244
|
+
})
|
|
245
|
+
it('should use the value passed in when Property.defaultValue and Property.value are not set', () => {
|
|
246
|
+
const input = {
|
|
247
|
+
properties: {
|
|
248
|
+
myProperty: TextProperty({ required: true }),
|
|
249
|
+
},
|
|
250
|
+
}
|
|
251
|
+
const model = BaseModel<{ myProperty: string }>('name', input)
|
|
252
|
+
const instance = model.create({ myProperty: 'passed-in' })
|
|
253
|
+
const actual = instance.get.myProperty()
|
|
254
|
+
const expected = 'passed-in'
|
|
255
|
+
assert.deepEqual(actual, expected)
|
|
256
|
+
})
|
|
257
|
+
it('should use the value for Property.value when even if Property.defaultValue is set and a value is passed in', () => {
|
|
258
|
+
const input = {
|
|
259
|
+
properties: {
|
|
260
|
+
myProperty: Property('MyProperty', {
|
|
261
|
+
value: 'value',
|
|
262
|
+
defaultValue: 'default-value',
|
|
263
|
+
}),
|
|
264
|
+
},
|
|
265
|
+
}
|
|
266
|
+
const model = BaseModel<{ myProperty: string }>('name', input)
|
|
267
|
+
const instance = model.create({ myProperty: 'passed-in' })
|
|
268
|
+
const actual = instance.get.myProperty()
|
|
269
|
+
const expected = 'value'
|
|
270
|
+
assert.deepEqual(actual, expected)
|
|
271
|
+
})
|
|
272
|
+
it('should use the value for Property.value when even if Property.defaultValue is not set and a value is passed in', async () => {
|
|
273
|
+
const input = {
|
|
274
|
+
properties: {
|
|
275
|
+
myProperty: Property('MyProperty', { value: 'value' }),
|
|
276
|
+
},
|
|
277
|
+
}
|
|
278
|
+
const model = BaseModel<{ myProperty: string }>('name', input)
|
|
279
|
+
const instance = model.create({ myProperty: 'passed-in' })
|
|
280
|
+
const actual = instance.get.myProperty()
|
|
281
|
+
const expected = 'value'
|
|
282
|
+
assert.deepEqual(actual, expected)
|
|
283
|
+
})
|
|
284
|
+
it('should use the value for Property.defaultValue when Property.value is not set and no value is passed in', async () => {
|
|
285
|
+
const input = {
|
|
286
|
+
properties: {
|
|
287
|
+
myProperty: Property('MyProperty', {
|
|
288
|
+
defaultValue: 'defaultValue',
|
|
289
|
+
}),
|
|
290
|
+
},
|
|
291
|
+
}
|
|
292
|
+
const model = BaseModel<{ myProperty: string }>('name', input)
|
|
293
|
+
// @ts-ignore
|
|
294
|
+
const instance = model.create({})
|
|
295
|
+
const actual = instance.get.myProperty()
|
|
296
|
+
const expected = 'defaultValue'
|
|
297
|
+
assert.deepEqual(actual, expected)
|
|
298
|
+
})
|
|
299
|
+
it('should use the value for Property.defaultValue when Property.value is not set and null is passed as a value', async () => {
|
|
300
|
+
const input = {
|
|
301
|
+
properties: {
|
|
302
|
+
myProperty: Property('MyProperty', {
|
|
303
|
+
defaultValue: 'defaultValue',
|
|
304
|
+
}),
|
|
305
|
+
},
|
|
306
|
+
}
|
|
307
|
+
const model = BaseModel<{ myProperty: string | null }>('name', input)
|
|
308
|
+
const instance = model.create({ myProperty: null })
|
|
309
|
+
const actual = instance.get.myProperty()
|
|
310
|
+
const expected = 'defaultValue'
|
|
311
|
+
assert.deepEqual(actual, expected)
|
|
312
|
+
})
|
|
313
|
+
it('should return a model with get.id and get.type for the provided valid keyToProperty', () => {
|
|
314
|
+
const input = {
|
|
315
|
+
properties: {
|
|
316
|
+
id: UniqueId({ required: true }),
|
|
317
|
+
type: Property('MyProperty', {}),
|
|
318
|
+
},
|
|
319
|
+
}
|
|
320
|
+
const model = BaseModel<{ type: string }>('name', input)
|
|
321
|
+
const actual = model.create({ id: 'my-id', type: 'my-type' })
|
|
322
|
+
assert.isOk(actual.get.id)
|
|
323
|
+
assert.isOk(actual.get.type)
|
|
324
|
+
})
|
|
325
|
+
it('should return the id when get.id() is called', () => {
|
|
326
|
+
const expected = 'my-id'
|
|
327
|
+
const input = {
|
|
328
|
+
properties: {
|
|
329
|
+
id: Property<string>('myid', {}),
|
|
330
|
+
type: Property('MyProperty', {}),
|
|
331
|
+
},
|
|
332
|
+
}
|
|
333
|
+
const model = BaseModel('name', input)
|
|
334
|
+
const instance = model.create({ id: expected, type: 'my-type' })
|
|
335
|
+
const actual = instance.get.id()
|
|
336
|
+
assert.equal(actual, expected)
|
|
337
|
+
})
|
|
338
|
+
it('should have a Promise for the default get.id()', () => {
|
|
339
|
+
const expected = 'my-id'
|
|
340
|
+
const input = {
|
|
341
|
+
properties: {
|
|
342
|
+
type: Property('MyProperty', {}),
|
|
343
|
+
},
|
|
344
|
+
}
|
|
345
|
+
const model = BaseModel('name', input)
|
|
346
|
+
const instance = model.create({ id: expected, type: 'my-type' })
|
|
347
|
+
const actual = instance.get.id()
|
|
348
|
+
// @ts-ignore
|
|
349
|
+
assert.isOk(actual.then)
|
|
350
|
+
})
|
|
351
|
+
it('should return a model where validate returns one error for id', async () => {
|
|
352
|
+
const input = {
|
|
353
|
+
properties: {
|
|
354
|
+
id: Property<string>('MyId', { required: true }),
|
|
355
|
+
type: Property('MyProperty', {}),
|
|
356
|
+
},
|
|
357
|
+
}
|
|
358
|
+
const model = BaseModel('name', input)
|
|
359
|
+
const instance = model.create({ type: 'my-type' })
|
|
360
|
+
const actual = await instance.validate()
|
|
361
|
+
const expected = 1
|
|
362
|
+
assert.equal(Object.values(actual).length, expected)
|
|
363
|
+
})
|
|
364
|
+
it('should return a model where validate returns one error for the missing text property', async () => {
|
|
365
|
+
const input = {
|
|
366
|
+
properties: {
|
|
367
|
+
id: Property<string>('MyProperty', { required: true }),
|
|
368
|
+
text: TextProperty({ required: true }),
|
|
369
|
+
},
|
|
370
|
+
}
|
|
371
|
+
const model = BaseModel('name', input)
|
|
372
|
+
const instance = model.create({ id: 'my-id' })
|
|
373
|
+
const actual = await instance.validate()
|
|
374
|
+
const expected = 1
|
|
375
|
+
assert.equal(Object.values(actual).length, expected)
|
|
376
|
+
})
|
|
377
|
+
})
|
|
378
|
+
it('should return an object with a function "create" when called once with valid data', () => {
|
|
379
|
+
const actual = BaseModel<{}>('name', { properties: {} })
|
|
380
|
+
assert.isFunction(actual.create)
|
|
381
|
+
})
|
|
382
|
+
describe('#references.getMyReferencedId()', () => {
|
|
383
|
+
it('should return the id from the ReferenceProperty', () => {
|
|
384
|
+
const model = BaseModel<{
|
|
385
|
+
myReference: ReferenceValueType<TEST_MODEL_TYPE>
|
|
386
|
+
}>('ModelName', {
|
|
387
|
+
properties: {
|
|
388
|
+
myReference: ReferenceProperty(TEST_MODEL_1),
|
|
389
|
+
},
|
|
390
|
+
})
|
|
391
|
+
const instance = model.create({ myReference: 'unit-test-id' })
|
|
392
|
+
const actual = instance.references.myReference()
|
|
393
|
+
const expected = 'unit-test-id'
|
|
394
|
+
assert.deepEqual(actual, expected)
|
|
395
|
+
})
|
|
396
|
+
})
|
|
397
|
+
describe('#getPrimaryKey()', () => {
|
|
398
|
+
it('should return the id field when no primaryKey is passed', async () => {
|
|
399
|
+
const model = BaseModel('ModelName', { properties: {} })
|
|
400
|
+
const expected = 'my-primary-key'
|
|
401
|
+
const instance = model.create({ id: expected })
|
|
402
|
+
const actual = await instance.getPrimaryKey()
|
|
403
|
+
assert.equal(actual, expected)
|
|
404
|
+
})
|
|
405
|
+
it('should return the primaryKey field when "primaryKey" is passed as primaryKey', async () => {
|
|
406
|
+
const model = BaseModel('ModelName', {
|
|
407
|
+
getPrimaryKeyName: () => 'primaryKey',
|
|
408
|
+
properties: {},
|
|
409
|
+
})
|
|
410
|
+
const expected = 'my-primary-key'
|
|
411
|
+
const instance = model.create({ primaryKey: expected })
|
|
412
|
+
const actual = await instance.getPrimaryKey()
|
|
413
|
+
assert.equal(actual, expected)
|
|
414
|
+
})
|
|
415
|
+
})
|
|
416
|
+
})
|
|
417
|
+
})
|