entropic-bond 1.48.1 → 1.50.0
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/.github/workflows/release.yml +26 -0
- package/CHANGELOG.md +1151 -0
- package/docs/.nojekyll +1 -0
- package/docs/README.md +94 -0
- package/docs/classes/Auth.md +391 -0
- package/docs/classes/AuthMock.md +278 -0
- package/docs/classes/AuthService.md +188 -0
- package/docs/classes/CloudFunctions.md +123 -0
- package/docs/classes/CloudFunctionsMock.md +97 -0
- package/docs/classes/CloudStorage.md +215 -0
- package/docs/classes/DataSource.md +248 -0
- package/docs/classes/EntropicComponent.md +666 -0
- package/docs/classes/JsonDataSource.md +328 -0
- package/docs/classes/MockCloudStorage.md +279 -0
- package/docs/classes/Model.md +274 -0
- package/docs/classes/Observable.md +120 -0
- package/docs/classes/Persistent.md +420 -0
- package/docs/classes/ServerAuth.md +211 -0
- package/docs/classes/ServerAuthMock.md +176 -0
- package/docs/classes/ServerAuthService.md +130 -0
- package/docs/classes/Store.md +218 -0
- package/docs/classes/StoredFile.md +636 -0
- package/docs/enums/StoredFileEvent.md +41 -0
- package/docs/interfaces/AuthError.md +30 -0
- package/docs/interfaces/CloudFunctionsService.md +69 -0
- package/docs/interfaces/Collection.md +13 -0
- package/docs/interfaces/CustomCredentials.md +7 -0
- package/docs/interfaces/DocumentReference.md +49 -0
- package/docs/interfaces/JsonRawData.md +7 -0
- package/docs/interfaces/SignData.md +63 -0
- package/docs/interfaces/StoreParams.md +52 -0
- package/docs/interfaces/StoredFileChange.md +41 -0
- package/docs/interfaces/UploadControl.md +90 -0
- package/docs/interfaces/UserCredentials.md +113 -0
- package/docs/interfaces/Values.md +17 -0
- package/docs/modules.md +1273 -0
- package/package.json +23 -19
- package/src/auth/auth-mock.spec.ts +168 -0
- package/src/auth/auth-mock.ts +129 -0
- package/src/auth/auth.ts +185 -0
- package/src/auth/user-auth-types.ts +21 -0
- package/src/cloud-functions/cloud-functions-mock.spec.ts +136 -0
- package/src/cloud-functions/cloud-functions-mock.ts +23 -0
- package/src/cloud-functions/cloud-functions.ts +83 -0
- package/src/cloud-storage/cloud-storage.spec.ts +207 -0
- package/src/cloud-storage/cloud-storage.ts +60 -0
- package/src/cloud-storage/mock-cloud-storage.ts +72 -0
- package/src/cloud-storage/stored-file.ts +102 -0
- package/src/index.ts +19 -0
- package/src/observable/observable.spec.ts +105 -0
- package/src/observable/observable.ts +67 -0
- package/src/persistent/entropic-component.spec.ts +143 -0
- package/src/persistent/entropic-component.ts +135 -0
- package/src/persistent/persistent.spec.ts +828 -0
- package/src/persistent/persistent.ts +650 -0
- package/src/server-auth/server-auth-mock.spec.ts +53 -0
- package/src/server-auth/server-auth-mock.ts +45 -0
- package/src/server-auth/server-auth.ts +49 -0
- package/src/store/data-source.ts +186 -0
- package/src/store/json-data-source.spec.ts +100 -0
- package/src/store/json-data-source.ts +256 -0
- package/src/store/mocks/mock-data.json +155 -0
- package/src/store/mocks/test-user.ts +122 -0
- package/src/store/model.spec.ts +659 -0
- package/src/store/model.ts +462 -0
- package/src/store/store.spec.ts +30 -0
- package/src/store/store.ts +113 -0
- package/src/types/utility-types.spec.ts +117 -0
- package/src/types/utility-types.ts +116 -0
- package/src/utils/test-utils/test-person.ts +44 -0
- package/src/utils/utils.spec.ts +95 -0
- package/{lib/utils/utils.d.ts → src/utils/utils.ts} +34 -10
- package/tsconfig-build.json +7 -0
- package/tsconfig-cjs.json +9 -0
- package/tsconfig.json +33 -0
- package/vite.config.ts +22 -0
- package/lib/auth/auth-mock.d.ts +0 -21
- package/lib/auth/auth-mock.js +0 -108
- package/lib/auth/auth-mock.js.map +0 -1
- package/lib/auth/auth.d.ts +0 -129
- package/lib/auth/auth.js +0 -146
- package/lib/auth/auth.js.map +0 -1
- package/lib/auth/user-auth-types.d.ts +0 -19
- package/lib/auth/user-auth-types.js +0 -3
- package/lib/auth/user-auth-types.js.map +0 -1
- package/lib/cloud-functions/cloud-functions-mock.d.ts +0 -11
- package/lib/cloud-functions/cloud-functions-mock.js +0 -19
- package/lib/cloud-functions/cloud-functions-mock.js.map +0 -1
- package/lib/cloud-functions/cloud-functions.d.ts +0 -19
- package/lib/cloud-functions/cloud-functions.js +0 -64
- package/lib/cloud-functions/cloud-functions.js.map +0 -1
- package/lib/cloud-storage/cloud-storage.d.ts +0 -24
- package/lib/cloud-storage/cloud-storage.js +0 -37
- package/lib/cloud-storage/cloud-storage.js.map +0 -1
- package/lib/cloud-storage/mock-cloud-storage.d.ts +0 -20
- package/lib/cloud-storage/mock-cloud-storage.js +0 -68
- package/lib/cloud-storage/mock-cloud-storage.js.map +0 -1
- package/lib/cloud-storage/stored-file.d.ts +0 -39
- package/lib/cloud-storage/stored-file.js +0 -106
- package/lib/cloud-storage/stored-file.js.map +0 -1
- package/lib/index.d.ts +0 -19
- package/lib/index.js +0 -36
- package/lib/index.js.map +0 -1
- package/lib/observable/observable.d.ts +0 -52
- package/lib/observable/observable.js +0 -66
- package/lib/observable/observable.js.map +0 -1
- package/lib/persistent/entropic-component.d.ts +0 -76
- package/lib/persistent/entropic-component.js +0 -109
- package/lib/persistent/entropic-component.js.map +0 -1
- package/lib/persistent/persistent.d.ts +0 -281
- package/lib/persistent/persistent.js +0 -539
- package/lib/persistent/persistent.js.map +0 -1
- package/lib/server-auth/server-auth-mock.d.ts +0 -12
- package/lib/server-auth/server-auth-mock.js +0 -39
- package/lib/server-auth/server-auth-mock.js.map +0 -1
- package/lib/server-auth/server-auth.d.ts +0 -24
- package/lib/server-auth/server-auth.js +0 -36
- package/lib/server-auth/server-auth.js.map +0 -1
- package/lib/store/data-source.d.ts +0 -137
- package/lib/store/data-source.js +0 -62
- package/lib/store/data-source.js.map +0 -1
- package/lib/store/json-data-source.d.ts +0 -68
- package/lib/store/json-data-source.js +0 -199
- package/lib/store/json-data-source.js.map +0 -1
- package/lib/store/mocks/test-user.d.ts +0 -49
- package/lib/store/mocks/test-user.js +0 -135
- package/lib/store/mocks/test-user.js.map +0 -1
- package/lib/store/model.d.ts +0 -238
- package/lib/store/model.js +0 -417
- package/lib/store/model.js.map +0 -1
- package/lib/store/store.d.ts +0 -62
- package/lib/store/store.js +0 -102
- package/lib/store/store.js.map +0 -1
- package/lib/types/utility-types.d.ts +0 -45
- package/lib/types/utility-types.js +0 -3
- package/lib/types/utility-types.js.map +0 -1
- package/lib/utils/test-utils/test-person.d.ts +0 -33
- package/lib/utils/test-utils/test-person.js +0 -25
- package/lib/utils/test-utils/test-person.js.map +0 -1
- package/lib/utils/utils.js +0 -76
- package/lib/utils/utils.js.map +0 -1
|
@@ -0,0 +1,828 @@
|
|
|
1
|
+
import { Persistent, persistent, persistentReference, persistentReferenceAt, registerPersistentClass, persistentPureReferenceWithPersistentProps, persistentReferenceWithPersistentProps, registerLegacyClassName, searchableArray, required, requiredWithValidator } from './persistent'
|
|
2
|
+
|
|
3
|
+
interface InnerObject {
|
|
4
|
+
nonPersistedReferences: PersistentClass[]
|
|
5
|
+
}
|
|
6
|
+
const beforeSerialize = vi.fn()
|
|
7
|
+
const afterDeserialize = vi.fn()
|
|
8
|
+
|
|
9
|
+
@registerLegacyClassName( 'LegacyClassName' )
|
|
10
|
+
@registerPersistentClass( 'PersistentClass' )
|
|
11
|
+
class PersistentClass extends Persistent {
|
|
12
|
+
protected override beforeSerialize(): void { beforeSerialize() }
|
|
13
|
+
protected override afterDeserialize(): void { afterDeserialize() }
|
|
14
|
+
set persistentProp( val: number | undefined ) { this._persistentProp = val }
|
|
15
|
+
get persistentProp() { return this._persistentProp }
|
|
16
|
+
set personPureRef( value: Person | undefined ) { this._personPureRef = value }
|
|
17
|
+
get personPureRef() { return this._personPureRef }
|
|
18
|
+
set persistentArray( value: PersistentClass[] | undefined ) { this._persistentArray = value }
|
|
19
|
+
get persistentArray() { return this._persistentArray }
|
|
20
|
+
@persistent _persistentProp: number | undefined
|
|
21
|
+
@persistent @searchableArray _persistentArray: PersistentClass[] | undefined
|
|
22
|
+
@persistentPureReferenceWithPersistentProps<Person>([ 'name', 'salary' ]) _personPureRef: Person | undefined
|
|
23
|
+
_nonPersistentProp: number | undefined
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
class NotRegistered extends Persistent {}
|
|
27
|
+
|
|
28
|
+
@registerPersistentClass( 'Person' )
|
|
29
|
+
class Person extends Persistent {
|
|
30
|
+
protected override beforeSerialize(): void {
|
|
31
|
+
beforeSerialize()
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
protected override afterDeserialize(): void {
|
|
35
|
+
afterDeserialize()
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
set name( value: string | undefined ) {
|
|
39
|
+
this._name = value
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
get name() {
|
|
43
|
+
return this._name
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
set salary( value: number | undefined ) {
|
|
47
|
+
this._salary = value
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
get salary() {
|
|
51
|
+
return this._salary
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
set doNotPersist( value: number | undefined ) {
|
|
55
|
+
this._doNotPersist = value
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
get doNotPersist() {
|
|
59
|
+
return this._doNotPersist
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
set anObjectProperty( value: PersistentClass ) {
|
|
63
|
+
this._anObjectProperty = value
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
get anObjectProperty() {
|
|
67
|
+
return this._anObjectProperty
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
set skills( value: string[] | undefined ) {
|
|
71
|
+
this._skills = value
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
get skills() {
|
|
75
|
+
return this._skills
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
set arrayOfPersistent( value: PersistentClass[] | undefined ) {
|
|
79
|
+
this._arrayOfPersistent = value
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
get arrayOfPersistent() {
|
|
83
|
+
return this._arrayOfPersistent
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
set document( value: PersistentClass | undefined ) {
|
|
87
|
+
this._document = value
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
get document() {
|
|
91
|
+
return this._document
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
set arrayOfRefs(value: PersistentClass[]) {
|
|
95
|
+
this._arrayOfRefs = value
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
get arrayOfRefs(): PersistentClass[] {
|
|
99
|
+
return this._arrayOfRefs
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
set persistentObject( value: InnerObject | undefined ) {
|
|
103
|
+
this._persistentObject = value
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
get persistentObject() {
|
|
107
|
+
return this._persistentObject
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
@required @persistent private _name?: string
|
|
111
|
+
@persistent private _salary?: number
|
|
112
|
+
@requiredWithValidator(
|
|
113
|
+
( val, propInfo, instace ) => !!val && val.length > 0 && propInfo.name === 'skills' && instace.id === 'person9'
|
|
114
|
+
) @persistent private _skills: string[] | undefined
|
|
115
|
+
@persistent private _anObjectProperty: PersistentClass = new PersistentClass()
|
|
116
|
+
@persistent private _arrayOfPersistent: PersistentClass[] | undefined
|
|
117
|
+
@persistent _notRegistered: NotRegistered | undefined
|
|
118
|
+
@persistent _arrayOfArray: number[][] | undefined
|
|
119
|
+
@persistent _arrayOfPersistentArray: PersistentClass[][] | undefined
|
|
120
|
+
@persistent _plainObject: { [ key: string ]: unknown } | undefined
|
|
121
|
+
@persistentReference _document: PersistentClass | undefined
|
|
122
|
+
@persistentReferenceAt('ArbitraryCollectionName') _docAtArbitraryCollection: PersistentClass | undefined
|
|
123
|
+
@persistentReferenceAt(( value, prop ) => `ArbitraryCollectionName/${ value.className }/${ prop.name }` ) _docAtArbitraryCollectionRefFunc: PersistentClass | undefined
|
|
124
|
+
@persistentReference private _arrayOfRefs: PersistentClass[] = []
|
|
125
|
+
@persistent private _persistentObject: InnerObject | undefined
|
|
126
|
+
@persistentReferenceWithPersistentProps<PersistentClass>([ 'persistentProp' ], value => `ArbitraryCollectionName/${ value.className }` ) _referenceWithStoredValues: PersistentClass | undefined
|
|
127
|
+
private _doNotPersist: number | undefined
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
interface CustomAnnotation {
|
|
132
|
+
menu: string
|
|
133
|
+
subType: string
|
|
134
|
+
showInDashboard: boolean
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
@registerPersistentClass( 'WithAnnotations', {
|
|
138
|
+
menu: 'main',
|
|
139
|
+
subType: 'NiceClass',
|
|
140
|
+
showInDashboard: false
|
|
141
|
+
} as CustomAnnotation )
|
|
142
|
+
export class WithAnnotations extends PersistentClass {}
|
|
143
|
+
|
|
144
|
+
@registerPersistentClass( 'WithAnnotations2', {
|
|
145
|
+
menu: 'main',
|
|
146
|
+
subType: 'UglyClass',
|
|
147
|
+
showInDashboard: false
|
|
148
|
+
}as CustomAnnotation)
|
|
149
|
+
export class WithAnnotations2 extends PersistentClass {}
|
|
150
|
+
|
|
151
|
+
@registerPersistentClass( 'WithAnnotations3', {
|
|
152
|
+
menu: 'subMenu',
|
|
153
|
+
showInDashboard: true
|
|
154
|
+
}as CustomAnnotation)
|
|
155
|
+
export class WithAnnotations3 extends PersistentClass {}
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
abstract class AbstractClass extends Persistent {
|
|
159
|
+
abstract pp(): any
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
@registerPersistentClass( 'ConcreteClass' )
|
|
163
|
+
class ConcreteClass extends AbstractClass {
|
|
164
|
+
pp(){}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
describe( 'Persistent', ()=>{
|
|
168
|
+
let person: Person
|
|
169
|
+
let newPerson: Person
|
|
170
|
+
let obj = {
|
|
171
|
+
__className: 'Person',
|
|
172
|
+
name: 'Lisa',
|
|
173
|
+
salary: 2500,
|
|
174
|
+
skills: [ 'lazy', 'messy' ],
|
|
175
|
+
arrayOfArray: [ [ 5, 6 ], [ 7, 8 ] ],
|
|
176
|
+
plainObject: {
|
|
177
|
+
prop1: 'prop1',
|
|
178
|
+
prop2: 3
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
beforeEach(()=>{
|
|
183
|
+
person = new Person( 'person1' )
|
|
184
|
+
person.name = 'Maria'
|
|
185
|
+
person.salary = 3000
|
|
186
|
+
person.skills = [ 'diligent', 'smart' ]
|
|
187
|
+
person._arrayOfArray = [ [ 1, 2 ], [ 3, 4 ] ]
|
|
188
|
+
person._plainObject = {
|
|
189
|
+
prop1: 'aProp1',
|
|
190
|
+
prop2: 1034
|
|
191
|
+
}
|
|
192
|
+
newPerson = Persistent.createInstance<Person>( obj )
|
|
193
|
+
})
|
|
194
|
+
|
|
195
|
+
it( 'should keep a persistent properties list for each class', ()=>{
|
|
196
|
+
const a = new Person( 'person2' )
|
|
197
|
+
const b = new PersistentClass()
|
|
198
|
+
|
|
199
|
+
// we are testing a decorator that manipulates the class definition.
|
|
200
|
+
// Therefore we need to access the decorator created private properties
|
|
201
|
+
// in order to test the behaviour of the decorator
|
|
202
|
+
expect( a[ '_persistentProperties' ] ).toEqual( expect.arrayContaining([
|
|
203
|
+
{ name: '_name', validator: expect.any( Function ) },
|
|
204
|
+
{ name: '_skills', validator: expect.any( Function ) }
|
|
205
|
+
]))
|
|
206
|
+
expect( b[ '_persistentProperties' ] ).not.toEqual( expect.arrayContaining( [ expect.objectContaining({
|
|
207
|
+
name: '_name'
|
|
208
|
+
})]))
|
|
209
|
+
expect( a[ '_persistentProperties' ] ).not.toEqual( expect.arrayContaining([ expect.objectContaining({
|
|
210
|
+
name: '_persistentProp'
|
|
211
|
+
})]))
|
|
212
|
+
expect( b[ '_persistentProperties' ] ).toEqual( expect.arrayContaining( [ {
|
|
213
|
+
name: '_persistentProp'
|
|
214
|
+
} ] ) )
|
|
215
|
+
})
|
|
216
|
+
|
|
217
|
+
it( 'should provide a flat object with persistent properties', ()=>{
|
|
218
|
+
expect( person.name ).toEqual( 'Maria' )
|
|
219
|
+
expect( person.toObject().name ).toEqual( 'Maria' )
|
|
220
|
+
})
|
|
221
|
+
|
|
222
|
+
it( 'should set persistent properties from a flat object', ()=>{
|
|
223
|
+
person.fromObject( obj )
|
|
224
|
+
|
|
225
|
+
expect( person.name ).toEqual( 'Lisa' )
|
|
226
|
+
expect( person.salary ).toBe( 2500 )
|
|
227
|
+
})
|
|
228
|
+
|
|
229
|
+
it( 'should process number object even when undefined', ()=>{
|
|
230
|
+
person.salary = undefined
|
|
231
|
+
expect( person.salary ).toBeUndefined()
|
|
232
|
+
|
|
233
|
+
person.fromObject( obj )
|
|
234
|
+
expect( person.salary ).toBe( 2500 )
|
|
235
|
+
})
|
|
236
|
+
|
|
237
|
+
it( 'should fill properties from arbitrary object', ()=>{
|
|
238
|
+
person.name = 'meganito'
|
|
239
|
+
person.salary = 32
|
|
240
|
+
person.fromObject({
|
|
241
|
+
name: 'fulanito changed',
|
|
242
|
+
salary: 4839,
|
|
243
|
+
foo: 'bar'
|
|
244
|
+
})
|
|
245
|
+
|
|
246
|
+
expect( person.name ).toBe( 'fulanito changed' )
|
|
247
|
+
expect( person.salary ).toBe( 4839 )
|
|
248
|
+
expect( (person as any).foo ).not.toBeDefined()
|
|
249
|
+
})
|
|
250
|
+
|
|
251
|
+
it( 'should persist number with value of 0', ()=>{
|
|
252
|
+
person.salary = 0
|
|
253
|
+
const object = person.toObject()
|
|
254
|
+
|
|
255
|
+
expect( object.salary ).toBe( 0 )
|
|
256
|
+
|
|
257
|
+
const newPerson = new Person( 'person3' )
|
|
258
|
+
newPerson.fromObject( object )
|
|
259
|
+
expect( newPerson.salary ).toBe( 0 )
|
|
260
|
+
})
|
|
261
|
+
|
|
262
|
+
it( 'should deal with undefined strings', ()=>{
|
|
263
|
+
person.name = undefined
|
|
264
|
+
expect( person.name ).toBeUndefined()
|
|
265
|
+
|
|
266
|
+
expect( person.toObject().name ).toBeUndefined()
|
|
267
|
+
|
|
268
|
+
delete (obj as any).name
|
|
269
|
+
person.fromObject( obj )
|
|
270
|
+
expect( person.name ).toBeUndefined()
|
|
271
|
+
})
|
|
272
|
+
|
|
273
|
+
it( 'should persist array properties', ()=>{
|
|
274
|
+
expect( person.toObject().skills ).toEqual( [ 'diligent', 'smart' ] )
|
|
275
|
+
})
|
|
276
|
+
|
|
277
|
+
it( 'should read arrays from stream', ()=>{
|
|
278
|
+
expect( newPerson.skills ).toEqual( [ 'lazy', 'messy' ] )
|
|
279
|
+
})
|
|
280
|
+
|
|
281
|
+
it( 'should persist array of array properties', ()=>{
|
|
282
|
+
const obj: any = person.toObject()
|
|
283
|
+
expect( obj.arrayOfArray ).toEqual( [ [ 1, 2 ], [ 3, 4 ] ] )
|
|
284
|
+
})
|
|
285
|
+
|
|
286
|
+
it( 'should read arrays of array from stream', ()=>{
|
|
287
|
+
expect( newPerson._arrayOfArray ).toEqual( [ [ 5, 6 ], [ 7, 8 ] ] )
|
|
288
|
+
})
|
|
289
|
+
|
|
290
|
+
it( 'should persist plain object properties', ()=>{
|
|
291
|
+
const obj: any = person.toObject()
|
|
292
|
+
expect( obj.plainObject ).toEqual( {
|
|
293
|
+
prop1: 'aProp1',
|
|
294
|
+
prop2: 1034
|
|
295
|
+
})
|
|
296
|
+
})
|
|
297
|
+
|
|
298
|
+
it( 'should read plain objects from stream', ()=>{
|
|
299
|
+
expect( newPerson._plainObject ).toEqual( {
|
|
300
|
+
prop1: 'prop1',
|
|
301
|
+
prop2: 3
|
|
302
|
+
})
|
|
303
|
+
})
|
|
304
|
+
|
|
305
|
+
it( 'should deal with undefined values', ()=>{
|
|
306
|
+
obj.plainObject.prop1 = undefined as any
|
|
307
|
+
obj.plainObject.prop2 = null as any
|
|
308
|
+
let aPerson: Person
|
|
309
|
+
|
|
310
|
+
expect( ()=>{ aPerson = new Person( 'person4' ).fromObject( obj ) } ).not.toThrow()
|
|
311
|
+
aPerson = new Person( 'person4' ).fromObject( obj )
|
|
312
|
+
expect( aPerson._plainObject!.prop1 ).toBeUndefined()
|
|
313
|
+
expect( aPerson._plainObject!.prop2 ).toBeNull()
|
|
314
|
+
})
|
|
315
|
+
|
|
316
|
+
it( 'should not throw on null property when toObject', ()=>{
|
|
317
|
+
newPerson._plainObject!.prop1 = null
|
|
318
|
+
|
|
319
|
+
expect( ()=>{
|
|
320
|
+
newPerson.toObject()
|
|
321
|
+
}).not.toThrow()
|
|
322
|
+
})
|
|
323
|
+
|
|
324
|
+
it( 'should not throw on null property when toObject', ()=>{
|
|
325
|
+
newPerson._plainObject!.prop1 = undefined
|
|
326
|
+
|
|
327
|
+
expect( ()=>{
|
|
328
|
+
newPerson.toObject()
|
|
329
|
+
}).not.toThrow()
|
|
330
|
+
})
|
|
331
|
+
|
|
332
|
+
it( 'should throw with object info if not available on creating a persistent instance', ()=>{
|
|
333
|
+
expect(()=>{
|
|
334
|
+
Persistent.createInstance({ id: 'id' } as any )
|
|
335
|
+
}).toThrow( 'You should provide a class name.' )
|
|
336
|
+
})
|
|
337
|
+
|
|
338
|
+
it( 'should clone persistent properties of an instance into this instance', ()=>{
|
|
339
|
+
const instace = new Person( 'personId' )
|
|
340
|
+
instace.clone( person )
|
|
341
|
+
|
|
342
|
+
expect( instace.id ).toBe( 'personId' )
|
|
343
|
+
expect( instace.name ).toBe( 'Maria')
|
|
344
|
+
})
|
|
345
|
+
|
|
346
|
+
|
|
347
|
+
describe( 'Properties instance of Persistent type', ()=>{
|
|
348
|
+
beforeEach(()=>{
|
|
349
|
+
const subObject = new PersistentClass()
|
|
350
|
+
subObject._persistentProp = 23
|
|
351
|
+
const subObject2 = new PersistentClass()
|
|
352
|
+
subObject._persistentProp = 103
|
|
353
|
+
|
|
354
|
+
const a = new PersistentClass(), b = new PersistentClass()
|
|
355
|
+
a._persistentProp = 205
|
|
356
|
+
b._persistentProp = 206
|
|
357
|
+
subObject._persistentArray = [ a, b ]
|
|
358
|
+
|
|
359
|
+
person.anObjectProperty = subObject
|
|
360
|
+
person.arrayOfPersistent = [ subObject, subObject2 ]
|
|
361
|
+
person._arrayOfPersistentArray = [ [ subObject, subObject2 ], [ subObject2, subObject ] ]
|
|
362
|
+
person._plainObject = {
|
|
363
|
+
prop1: subObject,
|
|
364
|
+
prop2: subObject2
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
const obj = JSON.stringify( person.toObject() )
|
|
368
|
+
newPerson = Persistent.createInstance<Person>( JSON.parse( obj ) )
|
|
369
|
+
})
|
|
370
|
+
|
|
371
|
+
it( 'should return compound objects as instance of object class', ()=>{
|
|
372
|
+
expect( newPerson.anObjectProperty ).toBeInstanceOf( PersistentClass )
|
|
373
|
+
})
|
|
374
|
+
|
|
375
|
+
it( 'should throw if class not registered on writing to a stream', ()=>{
|
|
376
|
+
person._notRegistered = new NotRegistered()
|
|
377
|
+
|
|
378
|
+
expect(()=>{
|
|
379
|
+
person.toObject()
|
|
380
|
+
}).toThrow( 'You should register this class prior to streaming it.' )
|
|
381
|
+
})
|
|
382
|
+
|
|
383
|
+
it( 'should throw if class not registered on reading from stream', ()=>{
|
|
384
|
+
const obj: any = {
|
|
385
|
+
id: 'id',
|
|
386
|
+
anObjectProperty: { __className: 'NotRegistered' }
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
expect(()=>{
|
|
390
|
+
new Person( 'person5' ).fromObject( obj )
|
|
391
|
+
}).toThrow( 'You should register class NotRegistered prior to use.' )
|
|
392
|
+
})
|
|
393
|
+
|
|
394
|
+
it( 'should persist array of Persistent type properties', ()=>{
|
|
395
|
+
expect( newPerson.arrayOfPersistent?.[ 0 ] ).toBeInstanceOf( PersistentClass )
|
|
396
|
+
})
|
|
397
|
+
|
|
398
|
+
it( 'should persist persistent array of array of Persistent type properties', ()=>{
|
|
399
|
+
expect( newPerson.arrayOfPersistent?.[ 0 ]?._persistentArray?.[ 0 ] ).toBeInstanceOf( PersistentClass )
|
|
400
|
+
})
|
|
401
|
+
|
|
402
|
+
it( 'should persist array of array of Persistent type properties', ()=>{
|
|
403
|
+
expect( newPerson._arrayOfPersistentArray?.[ 0 ]?.[ 0 ] ).toBeInstanceOf( PersistentClass )
|
|
404
|
+
})
|
|
405
|
+
|
|
406
|
+
it( 'should persist properties of type Persistent in plain object', ()=>{
|
|
407
|
+
expect( newPerson._plainObject?.prop1 ).toBeInstanceOf( PersistentClass )
|
|
408
|
+
})
|
|
409
|
+
|
|
410
|
+
it( 'should return registered properties', ()=>{
|
|
411
|
+
expect( new PersistentClass().getPersistentProperties() ).toEqual([
|
|
412
|
+
{ name: 'id' },
|
|
413
|
+
{ name: 'persistentProp' },
|
|
414
|
+
{ name: 'persistentArray', searchableArray: true },
|
|
415
|
+
{ name: 'personPureRef', isReference: true, isPureReference: true, forcedPersistentProps: [ 'name', 'salary' ] }
|
|
416
|
+
])
|
|
417
|
+
|
|
418
|
+
expect( new Person( 'person6' ).getPersistentProperties() ).toEqual( expect.arrayContaining([
|
|
419
|
+
{ name: 'name', validator: expect.any( Function ) },
|
|
420
|
+
{ name: 'document', isReference: true },
|
|
421
|
+
{ name: 'docAtArbitraryCollection', isReference: true, storeInCollection: 'ArbitraryCollectionName' }
|
|
422
|
+
]))
|
|
423
|
+
})
|
|
424
|
+
|
|
425
|
+
})
|
|
426
|
+
|
|
427
|
+
describe( 'Document as reference', ()=>{
|
|
428
|
+
let ref1: PersistentClass, ref2: PersistentClass
|
|
429
|
+
|
|
430
|
+
beforeEach(()=>{
|
|
431
|
+
person.document = new PersistentClass()
|
|
432
|
+
person.document._persistentProp = 345
|
|
433
|
+
person._docAtArbitraryCollection = new PersistentClass()
|
|
434
|
+
person._docAtArbitraryCollection._persistentProp = 3989
|
|
435
|
+
person._docAtArbitraryCollectionRefFunc = person._docAtArbitraryCollection
|
|
436
|
+
ref1 = new PersistentClass(); ref1._persistentProp = 2091
|
|
437
|
+
ref2 = new PersistentClass(); ref2._persistentProp = 2092
|
|
438
|
+
person.arrayOfRefs.push( ref1 )
|
|
439
|
+
person.arrayOfRefs.push( ref2 )
|
|
440
|
+
person._referenceWithStoredValues = new PersistentClass(); person._referenceWithStoredValues._persistentProp = 2093
|
|
441
|
+
const obj = JSON.stringify( person.toObject() )
|
|
442
|
+
newPerson = Persistent.createInstance<Person>( JSON.parse( obj ) )
|
|
443
|
+
})
|
|
444
|
+
|
|
445
|
+
it( 'should create an object at root level', ()=>{
|
|
446
|
+
const persistentClassDocs = person.toObject().__rootCollections?.[ 'PersistentClass' ]
|
|
447
|
+
|
|
448
|
+
expect( persistentClassDocs ).toEqual( expect.arrayContaining([
|
|
449
|
+
expect.objectContaining({ persistentProp: 345 })
|
|
450
|
+
]))
|
|
451
|
+
expect( newPerson.document ).toBeInstanceOf( PersistentClass )
|
|
452
|
+
expect( newPerson.document?.persistentProp ).toBeUndefined()
|
|
453
|
+
})
|
|
454
|
+
|
|
455
|
+
it( 'should create root reference collection with arbitrary name', ()=>{
|
|
456
|
+
const collectionDocs = person.toObject().__rootCollections?.[ 'ArbitraryCollectionName' ]
|
|
457
|
+
|
|
458
|
+
expect( collectionDocs ).toEqual( expect.arrayContaining([
|
|
459
|
+
expect.objectContaining({ persistentProp: 3989 })
|
|
460
|
+
]))
|
|
461
|
+
expect( newPerson._docAtArbitraryCollection ).toBeInstanceOf( PersistentClass )
|
|
462
|
+
expect( newPerson._docAtArbitraryCollection?.persistentProp ).toBeUndefined()
|
|
463
|
+
})
|
|
464
|
+
|
|
465
|
+
it( 'should create root reference collection with arbitrary name based on function call', ()=>{
|
|
466
|
+
const collectionDocs = person.toObject().__rootCollections?.[ 'ArbitraryCollectionName/PersistentClass/_docAtArbitraryCollectionRefFunc' ]
|
|
467
|
+
expect( collectionDocs ).toBeDefined()
|
|
468
|
+
|
|
469
|
+
expect( collectionDocs ).toEqual( expect.arrayContaining([
|
|
470
|
+
expect.objectContaining({ persistentProp: 3989 })
|
|
471
|
+
]))
|
|
472
|
+
expect( newPerson._docAtArbitraryCollection ).toBeInstanceOf( PersistentClass )
|
|
473
|
+
expect( newPerson._docAtArbitraryCollection?.persistentProp ).toBeUndefined()
|
|
474
|
+
})
|
|
475
|
+
|
|
476
|
+
|
|
477
|
+
it( 'should not create root reference for existing references', ()=>{
|
|
478
|
+
expect( Object.values(
|
|
479
|
+
newPerson.toObject().__rootCollections as any
|
|
480
|
+
)).toHaveLength( 1 )
|
|
481
|
+
})
|
|
482
|
+
|
|
483
|
+
it( 'should read swallow object document as reference', ()=>{
|
|
484
|
+
expect( newPerson.document ).toBeInstanceOf( PersistentClass )
|
|
485
|
+
expect( newPerson.document?.id ).toEqual( person.document?.id )
|
|
486
|
+
expect( newPerson.document?.['__documentReference'] ).toEqual({
|
|
487
|
+
storedInCollection: 'PersistentClass'
|
|
488
|
+
})
|
|
489
|
+
expect( newPerson.document?.persistentProp ).toBeUndefined()
|
|
490
|
+
})
|
|
491
|
+
|
|
492
|
+
it( 'should save existing refs properly', ()=>{
|
|
493
|
+
const res = newPerson.toObject()
|
|
494
|
+
|
|
495
|
+
expect( res.document ).not.toBeInstanceOf( PersistentClass )
|
|
496
|
+
expect( res.document ).toEqual({
|
|
497
|
+
__className: 'PersistentClass',
|
|
498
|
+
id: newPerson.document?.id,
|
|
499
|
+
__documentReference: { storedInCollection: 'PersistentClass' },
|
|
500
|
+
})
|
|
501
|
+
})
|
|
502
|
+
|
|
503
|
+
it( 'should not store pure references', ()=>{
|
|
504
|
+
person.anObjectProperty.personPureRef = new Person( 'person7' )
|
|
505
|
+
const obj = person.toObject()
|
|
506
|
+
|
|
507
|
+
expect( obj.__rootCollections?.['Person'] ).toHaveLength( 1 )
|
|
508
|
+
expect( obj.__rootCollections?.['Person']?.[0]?.id ).not.toEqual( 'person7' )
|
|
509
|
+
})
|
|
510
|
+
|
|
511
|
+
it( 'should fill reference object when store pure reference', ()=>{
|
|
512
|
+
const personPureRef =new Person( 'person7' )
|
|
513
|
+
personPureRef.name = 'James'
|
|
514
|
+
personPureRef.salary = 5643
|
|
515
|
+
person.anObjectProperty.personPureRef = personPureRef
|
|
516
|
+
const obj = person.toObject()
|
|
517
|
+
|
|
518
|
+
expect( obj.anObjectProperty?.personPureRef ).toEqual({
|
|
519
|
+
__className: 'Person',
|
|
520
|
+
id: personPureRef.id,
|
|
521
|
+
__documentReference: { storedInCollection: 'Person' },
|
|
522
|
+
name: 'James',
|
|
523
|
+
salary: 5643
|
|
524
|
+
})
|
|
525
|
+
|
|
526
|
+
expect( obj.__rootCollections?.Person?.[ 0 ]?.['anObjectProperty'].personPureRef ).toEqual({
|
|
527
|
+
__className: 'Person',
|
|
528
|
+
id: personPureRef.id,
|
|
529
|
+
__documentReference: { storedInCollection: 'Person' },
|
|
530
|
+
name: 'James',
|
|
531
|
+
salary: 5643
|
|
532
|
+
})
|
|
533
|
+
})
|
|
534
|
+
|
|
535
|
+
it( 'should NOT fill reference object when store pure reference and value is undefined', ()=>{
|
|
536
|
+
const personPureRef =new Person( 'person7' )
|
|
537
|
+
personPureRef.name = undefined
|
|
538
|
+
personPureRef.salary = 5643
|
|
539
|
+
person.anObjectProperty.personPureRef = personPureRef
|
|
540
|
+
const obj = person.toObject()
|
|
541
|
+
|
|
542
|
+
expect( obj.anObjectProperty?.personPureRef ).toEqual({
|
|
543
|
+
__className: 'Person',
|
|
544
|
+
id: personPureRef.id,
|
|
545
|
+
__documentReference: { storedInCollection: 'Person' },
|
|
546
|
+
salary: 5643
|
|
547
|
+
})
|
|
548
|
+
expect( obj.anObjectProperty?.personPureRef ).not.toHaveProperty( 'name' )
|
|
549
|
+
})
|
|
550
|
+
|
|
551
|
+
it( 'should create an instance from pure reference with the referenced persistent props', ()=>{
|
|
552
|
+
const personPureRef =new Person( 'person7' )
|
|
553
|
+
personPureRef.name = 'James'
|
|
554
|
+
personPureRef.salary = 5643
|
|
555
|
+
person.anObjectProperty.personPureRef = personPureRef
|
|
556
|
+
const obj = person.toObject()
|
|
557
|
+
const instance = Persistent.createInstance( obj )
|
|
558
|
+
|
|
559
|
+
expect( instance.anObjectProperty.personPureRef ).toBeInstanceOf( Person )
|
|
560
|
+
expect( instance.anObjectProperty.personPureRef?.name ).toEqual( 'James' )
|
|
561
|
+
expect( instance.anObjectProperty.personPureRef?.salary ).toBe( 5643 )
|
|
562
|
+
})
|
|
563
|
+
|
|
564
|
+
|
|
565
|
+
it( 'should store values of persistentReferenceWithPersistentProps', ()=>{
|
|
566
|
+
const obj = person.toObject()
|
|
567
|
+
|
|
568
|
+
expect( obj.__rootCollections?.Person?.[0]?.id ).toEqual( person.id )
|
|
569
|
+
expect( obj['referenceWithStoredValues'] ).toEqual({
|
|
570
|
+
__className: 'PersistentClass',
|
|
571
|
+
id: person._referenceWithStoredValues?.id,
|
|
572
|
+
__documentReference: { storedInCollection: 'ArbitraryCollectionName/PersistentClass' },
|
|
573
|
+
persistentProp: 2093
|
|
574
|
+
})
|
|
575
|
+
|
|
576
|
+
const referenceWithValuesInRootCollections = obj.__rootCollections?.['ArbitraryCollectionName/PersistentClass']?.find(
|
|
577
|
+
persistent => persistent.id === person._referenceWithStoredValues?.id
|
|
578
|
+
)
|
|
579
|
+
|
|
580
|
+
expect( referenceWithValuesInRootCollections ).toEqual({
|
|
581
|
+
__className: 'PersistentClass',
|
|
582
|
+
id: person._referenceWithStoredValues?.id,
|
|
583
|
+
persistentProp: 2093
|
|
584
|
+
})
|
|
585
|
+
})
|
|
586
|
+
|
|
587
|
+
it( 'should not store values of persistentReferenceWithPersistentProps if value is undefined', ()=>{
|
|
588
|
+
person._referenceWithStoredValues!.persistentProp = undefined as any
|
|
589
|
+
const obj = person.toObject()
|
|
590
|
+
|
|
591
|
+
expect( obj['referenceWithStoredValues'] ).toEqual({
|
|
592
|
+
__className: 'PersistentClass',
|
|
593
|
+
id: person._referenceWithStoredValues?.id,
|
|
594
|
+
__documentReference: { storedInCollection: 'ArbitraryCollectionName/PersistentClass' },
|
|
595
|
+
})
|
|
596
|
+
expect( obj['referenceWithStoredValues'] ).not.toHaveProperty( 'persistentProp' )
|
|
597
|
+
})
|
|
598
|
+
|
|
599
|
+
it( 'should create an instance from reference with the referenced persistent props', ()=>{
|
|
600
|
+
const obj = person.toObject()
|
|
601
|
+
const instance = Persistent.createInstance( obj )
|
|
602
|
+
|
|
603
|
+
expect( instance._referenceWithStoredValues ).toBeInstanceOf( PersistentClass )
|
|
604
|
+
expect( instance._referenceWithStoredValues?.persistentProp ).toBe( 2093 )
|
|
605
|
+
})
|
|
606
|
+
|
|
607
|
+
describe( 'Array of references', ()=>{
|
|
608
|
+
|
|
609
|
+
it( 'should create an object with array of refs', ()=>{
|
|
610
|
+
const obj = person.toObject()
|
|
611
|
+
|
|
612
|
+
expect( obj.arrayOfRefs ).toHaveLength( 2 )
|
|
613
|
+
expect( obj.arrayOfRefs?.[0] ).toEqual({
|
|
614
|
+
id: ref1.id,
|
|
615
|
+
__className: 'PersistentClass',
|
|
616
|
+
__documentReference: {
|
|
617
|
+
storedInCollection: 'PersistentClass'
|
|
618
|
+
}
|
|
619
|
+
})
|
|
620
|
+
})
|
|
621
|
+
|
|
622
|
+
it( 'should create root reference collection with references in array of references', ()=>{
|
|
623
|
+
const persistentClassDocs = person.toObject().__rootCollections?.[ 'PersistentClass' ]
|
|
624
|
+
|
|
625
|
+
expect( persistentClassDocs ).toEqual( expect.arrayContaining([
|
|
626
|
+
expect.objectContaining({ id: ref1.id }),
|
|
627
|
+
expect.objectContaining({ id: ref2.id }),
|
|
628
|
+
]))
|
|
629
|
+
})
|
|
630
|
+
|
|
631
|
+
it( 'should deal with arrays of refs', ()=>{
|
|
632
|
+
expect( newPerson.arrayOfRefs ).toHaveLength( 2 )
|
|
633
|
+
expect( newPerson.arrayOfRefs[0]?.persistentProp ).toBeUndefined()
|
|
634
|
+
expect( newPerson.arrayOfRefs ).toEqual( expect.arrayContaining([
|
|
635
|
+
expect.objectContaining({
|
|
636
|
+
id: ref1.id,
|
|
637
|
+
__className: 'PersistentClass',
|
|
638
|
+
__documentReference: {
|
|
639
|
+
storedInCollection: 'PersistentClass'
|
|
640
|
+
}
|
|
641
|
+
}),
|
|
642
|
+
expect.objectContaining({
|
|
643
|
+
id: ref2.id,
|
|
644
|
+
__className: 'PersistentClass',
|
|
645
|
+
__documentReference: {
|
|
646
|
+
storedInCollection: 'PersistentClass'
|
|
647
|
+
}
|
|
648
|
+
})
|
|
649
|
+
]))
|
|
650
|
+
})
|
|
651
|
+
|
|
652
|
+
it( 'should produce proper formed references from object', ()=>{
|
|
653
|
+
const personObj = person.toObject()
|
|
654
|
+
|
|
655
|
+
personObj.persistentObject = {
|
|
656
|
+
nonPersistedReferences: [{
|
|
657
|
+
id: ref1.id,
|
|
658
|
+
__className: 'PersistentClass',
|
|
659
|
+
__documentReference: {
|
|
660
|
+
storedInCollection: 'PersistentClass'
|
|
661
|
+
}
|
|
662
|
+
} as any ]
|
|
663
|
+
}
|
|
664
|
+
|
|
665
|
+
const newPerson = Persistent.createInstance<Person>( personObj )
|
|
666
|
+
|
|
667
|
+
const obj = newPerson.toObject()
|
|
668
|
+
expect( obj.persistentObject?.nonPersistedReferences ).toHaveLength( 1 )
|
|
669
|
+
expect( obj.persistentObject?.nonPersistedReferences[0]?.id ).toBeDefined()
|
|
670
|
+
expect( obj.persistentObject?.nonPersistedReferences[0]?.['__className'] ).toBeDefined()
|
|
671
|
+
expect( obj.persistentObject?.nonPersistedReferences[0]?.['__documentReference'] ).toBeDefined()
|
|
672
|
+
expect( obj.persistentObject?.nonPersistedReferences[0]?.persistentProp ).not.toBeDefined()
|
|
673
|
+
})
|
|
674
|
+
})
|
|
675
|
+
|
|
676
|
+
})
|
|
677
|
+
|
|
678
|
+
describe( 'Annotations', ()=>{
|
|
679
|
+
|
|
680
|
+
it( 'should allow register persistent class with arbitrary annotations', ()=>{
|
|
681
|
+
expect( Persistent.annotations( WithAnnotations ) ).toEqual({
|
|
682
|
+
menu: 'main',
|
|
683
|
+
subType: 'NiceClass',
|
|
684
|
+
showInDashboard: false
|
|
685
|
+
})
|
|
686
|
+
})
|
|
687
|
+
|
|
688
|
+
it( 'should check if a property is required', ()=>{
|
|
689
|
+
const person = new Person( 'person8' )
|
|
690
|
+
expect( person.isRequired( 'name' ) ).toBe( true )
|
|
691
|
+
expect( person.isRequired( 'salary' ) ).toBe( false )
|
|
692
|
+
})
|
|
693
|
+
|
|
694
|
+
it( 'should validate non required properties', ()=>{
|
|
695
|
+
const person = new Person( 'person9' )
|
|
696
|
+
expect( person.isPropValueValid('salary') ).toBeTruthy()
|
|
697
|
+
})
|
|
698
|
+
|
|
699
|
+
it( 'should validate a required properties', ()=>{
|
|
700
|
+
const person = new Person( 'person9' )
|
|
701
|
+
person.name = 'A test name'
|
|
702
|
+
expect( person.isPropValueValid('name') ).toBeTruthy()
|
|
703
|
+
})
|
|
704
|
+
|
|
705
|
+
it( 'should fail validation of an empty required properties', ()=>{
|
|
706
|
+
const person = new Person( 'person9' )
|
|
707
|
+
expect( person.isPropValueValid('name') ).toBeFalsy()
|
|
708
|
+
})
|
|
709
|
+
|
|
710
|
+
it( 'should fail validation of an empty required with validator properties', ()=>{
|
|
711
|
+
const person = new Person( 'person9' )
|
|
712
|
+
expect( person.isPropValueValid('skills') ).toBeFalsy()
|
|
713
|
+
})
|
|
714
|
+
|
|
715
|
+
it( 'should fail validation of an non passing validator properties', ()=>{
|
|
716
|
+
const person = new Person( 'person9' )
|
|
717
|
+
person.skills = []
|
|
718
|
+
expect( person.isPropValueValid('skills') ).toBeFalsy()
|
|
719
|
+
})
|
|
720
|
+
|
|
721
|
+
it( 'should pass validation of a filled required with validator properties', ()=>{
|
|
722
|
+
const person = new Person( 'person9' )
|
|
723
|
+
person.skills = [ 'a skill' ]
|
|
724
|
+
expect( person.isPropValueValid('skills') ).toBeTruthy()
|
|
725
|
+
})
|
|
726
|
+
})
|
|
727
|
+
|
|
728
|
+
describe( 'Persistent Class collection retrieval', ()=>{
|
|
729
|
+
|
|
730
|
+
it( 'should retrieve all registered classes by class name', ()=>{
|
|
731
|
+
expect( Persistent.registeredClasses() ).toHaveLength( 7 )
|
|
732
|
+
expect( Persistent.registeredClasses() ).toContain( 'Person' )
|
|
733
|
+
expect( Persistent.registeredClasses() ).toContain( 'PersistentClass' )
|
|
734
|
+
expect( Persistent.registeredClasses() ).toContain( 'LegacyClassName' )
|
|
735
|
+
})
|
|
736
|
+
|
|
737
|
+
it( 'should retrieve classes by type', ()=>{
|
|
738
|
+
expect( Persistent.classesExtending( PersistentClass ) ).toHaveLength( 5 )
|
|
739
|
+
expect( Persistent.classesExtending( PersistentClass ) ).toContain( 'PersistentClass' )
|
|
740
|
+
expect( Persistent.classesExtending( PersistentClass ) ).toContain( 'LegacyClassName' )
|
|
741
|
+
expect( Persistent.classesExtending( PersistentClass ) ).toContain( 'WithAnnotations' )
|
|
742
|
+
expect( Persistent.classesExtending( PersistentClass ) ).toContain( 'WithAnnotations3' )
|
|
743
|
+
})
|
|
744
|
+
|
|
745
|
+
it( 'should retrieve classes by abstract class', ()=>{
|
|
746
|
+
expect( Persistent.classesExtending( AbstractClass ) ).toHaveLength( 1 )
|
|
747
|
+
expect( Persistent.classesExtending( AbstractClass ) ).toContain( 'ConcreteClass' )
|
|
748
|
+
})
|
|
749
|
+
|
|
750
|
+
it( 'should retrieve property info', ()=>{
|
|
751
|
+
expect( Persistent.propInfo<Person>( 'Person', 'name' ) ).toEqual({
|
|
752
|
+
name: 'name', validator: expect.any( Function )
|
|
753
|
+
})
|
|
754
|
+
})
|
|
755
|
+
})
|
|
756
|
+
|
|
757
|
+
describe( 'Persistent instantation', ()=>{
|
|
758
|
+
|
|
759
|
+
it( 'should create an instance of a registered class', ()=>{
|
|
760
|
+
const instance = Persistent.createInstance({ __className: 'PersistentClass', id: 'testPersistent' } )
|
|
761
|
+
expect( instance ).toBeInstanceOf( PersistentClass )
|
|
762
|
+
expect( instance.id ).toEqual( 'testPersistent' )
|
|
763
|
+
})
|
|
764
|
+
|
|
765
|
+
it( 'should create an instance of a registered legacy class', ()=>{
|
|
766
|
+
const instance = Persistent.createInstance({ __className: 'LegacyClassName', id: 'testPersistent' } )
|
|
767
|
+
expect( instance ).toBeInstanceOf( PersistentClass )
|
|
768
|
+
expect( instance.id ).toEqual( 'testPersistent' )
|
|
769
|
+
})
|
|
770
|
+
|
|
771
|
+
it( 'should not create persistent objects with legacy name', ()=>{
|
|
772
|
+
const instance = new PersistentClass( 'testPersistent' )
|
|
773
|
+
|
|
774
|
+
expect( instance.toObject().__className ).toBe( 'PersistentClass' )
|
|
775
|
+
})
|
|
776
|
+
|
|
777
|
+
it( 'should create a reference from a plain object', ()=>{
|
|
778
|
+
const instance = Persistent.createReference({ __className: 'PersistentClass', id: 'testPersistent', __documentReference:{ storedInCollection: 'PersistentClass' } } )
|
|
779
|
+
expect( instance ).toBeInstanceOf( PersistentClass )
|
|
780
|
+
expect( instance.id ).toEqual( 'testPersistent' )
|
|
781
|
+
expect( instance['__documentReference'] ).toEqual({ storedInCollection: 'PersistentClass' })
|
|
782
|
+
})
|
|
783
|
+
|
|
784
|
+
it( 'should create a reference from a plain object without explicit __documentReference object', ()=>{
|
|
785
|
+
const instance = Persistent.createReference({ __className: 'PersistentClass', id: 'testPersistent' } )
|
|
786
|
+
expect( instance ).toBeInstanceOf( PersistentClass )
|
|
787
|
+
expect( instance.id ).toEqual( 'testPersistent' )
|
|
788
|
+
expect( instance['__documentReference'] ).toEqual({ storedInCollection: 'PersistentClass' })
|
|
789
|
+
})
|
|
790
|
+
|
|
791
|
+
})
|
|
792
|
+
|
|
793
|
+
describe( 'Before and after serialize hooks', ()=>{
|
|
794
|
+
beforeEach(()=>{
|
|
795
|
+
beforeSerialize.mockReset()
|
|
796
|
+
afterDeserialize.mockReset()
|
|
797
|
+
})
|
|
798
|
+
|
|
799
|
+
it( 'should call beforeSerialize hook', ()=>{
|
|
800
|
+
person.toObject()
|
|
801
|
+
expect( beforeSerialize ).toHaveBeenCalledTimes( 2 )
|
|
802
|
+
})
|
|
803
|
+
|
|
804
|
+
it( 'should call afterDeserialize hook', ()=>{
|
|
805
|
+
const obj = person.toObject()
|
|
806
|
+
Persistent.createInstance<Person>( obj )
|
|
807
|
+
expect( afterDeserialize ).toHaveBeenCalledTimes( 2 )
|
|
808
|
+
})
|
|
809
|
+
})
|
|
810
|
+
|
|
811
|
+
describe( 'Make array field searchable by property', ()=>{
|
|
812
|
+
it( 'should create a searchable array field', ()=>{
|
|
813
|
+
const instance = new PersistentClass( 'testPersistent' )
|
|
814
|
+
instance.persistentArray = [
|
|
815
|
+
new PersistentClass( 'testPersistent0' ),
|
|
816
|
+
new PersistentClass( 'testPersistent1' ),
|
|
817
|
+
new PersistentClass( 'testPersistent2' ),
|
|
818
|
+
]
|
|
819
|
+
const obj = instance.toObject()
|
|
820
|
+
|
|
821
|
+
expect( obj[Persistent.searchableArrayNameFor( 'persistentArray' )] ).toEqual([
|
|
822
|
+
'testPersistent0',
|
|
823
|
+
'testPersistent1',
|
|
824
|
+
'testPersistent2',
|
|
825
|
+
])
|
|
826
|
+
})
|
|
827
|
+
})
|
|
828
|
+
})
|