@reldens/storage 0.87.0 → 0.89.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/.claude/driver-methods-complete-analysis.md +1978 -0
- package/.claude/test-architecture.md +973 -0
- package/CLAUDE.md +141 -7
- package/README.md +14 -2
- package/bin/reldens-storage.js +1 -1
- package/lib/base-driver.js +8 -0
- package/lib/entities-generator.js +1 -3
- package/lib/entity-templates/mikro-orm-model.template +2 -1
- package/lib/generators/models-generation.js +126 -5
- package/lib/mikro-orm/mikro-orm-data-server.js +24 -10
- package/lib/mikro-orm/mikro-orm-driver.js +184 -116
- package/lib/objection-js/objection-js-driver.js +111 -19
- package/lib/prisma/prisma-client-loader.js +4 -0
- package/lib/prisma/prisma-data-server.js +3 -2
- package/lib/prisma/prisma-driver.js +12 -10
- package/lib/prisma/prisma-filter-processor.js +193 -146
- package/lib/prisma/prisma-metadata-loader.js +0 -4
- package/lib/prisma/prisma-relation-resolver.js +292 -267
- package/lib/prisma/prisma-type-caster.js +280 -260
- package/package.json +15 -6
- package/tests/.env.test.example +7 -0
- package/tests/fixtures/categories-fixtures.js +164 -0
- package/tests/fixtures/expected-entities-mikro-orm/entities/test-categories-entity.js +70 -0
- package/tests/fixtures/expected-entities-mikro-orm/entities/test-products-entity.js +95 -0
- package/tests/fixtures/expected-entities-mikro-orm/entities/test-reviews-entity.js +84 -0
- package/tests/fixtures/expected-entities-mikro-orm/entities-config.js +17 -0
- package/tests/fixtures/expected-entities-mikro-orm/entities-translations.js +13 -0
- package/tests/fixtures/expected-entities-mikro-orm/models/mikro-orm/registered-models-mikro-orm.js +23 -0
- package/tests/fixtures/expected-entities-mikro-orm/models/mikro-orm/test-categories-model.js +57 -0
- package/tests/fixtures/expected-entities-mikro-orm/models/mikro-orm/test-products-model.js +79 -0
- package/tests/fixtures/expected-entities-mikro-orm/models/mikro-orm/test-reviews-model.js +70 -0
- package/tests/fixtures/expected-entities-objection-js/entities/test-categories-entity.js +70 -0
- package/tests/fixtures/expected-entities-objection-js/entities/test-products-entity.js +95 -0
- package/tests/fixtures/expected-entities-objection-js/entities/test-reviews-entity.js +84 -0
- package/tests/fixtures/expected-entities-objection-js/entities-config.js +17 -0
- package/tests/fixtures/expected-entities-objection-js/entities-translations.js +13 -0
- package/tests/fixtures/expected-entities-objection-js/models/objection-js/registered-models-objection-js.js +23 -0
- package/tests/fixtures/expected-entities-objection-js/models/objection-js/test-categories-model.js +33 -0
- package/tests/fixtures/expected-entities-objection-js/models/objection-js/test-products-model.js +42 -0
- package/tests/fixtures/expected-entities-objection-js/models/objection-js/test-reviews-model.js +33 -0
- package/tests/fixtures/expected-entities-prisma/entities/test-categories-entity.js +70 -0
- package/tests/fixtures/expected-entities-prisma/entities/test-products-entity.js +95 -0
- package/tests/fixtures/expected-entities-prisma/entities/test-reviews-entity.js +84 -0
- package/tests/fixtures/expected-entities-prisma/entities-config.js +17 -0
- package/tests/fixtures/expected-entities-prisma/entities-translations.js +13 -0
- package/tests/fixtures/expected-entities-prisma/models/prisma/registered-models-prisma.js +23 -0
- package/tests/fixtures/expected-entities-prisma/models/prisma/test-categories-model.js +43 -0
- package/tests/fixtures/expected-entities-prisma/models/prisma/test-products-model.js +50 -0
- package/tests/fixtures/expected-entities-prisma/models/prisma/test-reviews-model.js +46 -0
- package/tests/fixtures/products-fixtures.js +119 -0
- package/tests/fixtures/reviews-fixtures.js +42 -0
- package/tests/fixtures/sql/test-schema.sql +59 -0
- package/tests/integration/test-drivers.js +257 -0
- package/tests/integration/test-nested-filters.js +408 -0
- package/tests/integration/test-relations.js +349 -0
- package/tests/run-tests.js +213 -0
- package/tests/unit/test-drivers.js +89 -0
- package/tests/unit/test-entities-generator.js +533 -0
- package/tests/unit/test-entity-manager.js +128 -0
- package/tests/unit/test-type-mapper.js +232 -0
- package/tests/utils/custom-reporter.js +73 -0
- package/tests/utils/driver-registry.js +144 -0
- package/tests/utils/prisma-subprocess-worker.js +150 -0
- package/tests/utils/test-helpers.js +726 -0
- package/tests/utils/test-runner.js +63 -0
|
@@ -0,0 +1,533 @@
|
|
|
1
|
+
/**
|
|
2
|
+
*
|
|
3
|
+
* Reldens - EntitiesGenerator Test
|
|
4
|
+
*
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const { describe, it, beforeEach } = require('node:test');
|
|
8
|
+
const assert = require('node:assert');
|
|
9
|
+
const { EntitiesGenerator } = require('../../lib/entities-generator');
|
|
10
|
+
const { FileHandler } = require('@reldens/server-utils');
|
|
11
|
+
|
|
12
|
+
class EntitiesGeneratorTest
|
|
13
|
+
{
|
|
14
|
+
|
|
15
|
+
run()
|
|
16
|
+
{
|
|
17
|
+
let counter = 0;
|
|
18
|
+
let errors = 0;
|
|
19
|
+
describe('EntitiesGenerator', () => {
|
|
20
|
+
describe('constructor', () => {
|
|
21
|
+
it('should initialize with default props', () => {
|
|
22
|
+
try {
|
|
23
|
+
let generator = new EntitiesGenerator({});
|
|
24
|
+
assert.ok(generator.templatesFolderPath);
|
|
25
|
+
assert.ok(generator.templates);
|
|
26
|
+
assert.ok(generator.projectPath);
|
|
27
|
+
assert.ok(generator.generationFolder);
|
|
28
|
+
assert.ok(generator.entitiesFolder);
|
|
29
|
+
assert.ok(generator.modelsFolder);
|
|
30
|
+
assert.ok(generator.driverMap);
|
|
31
|
+
assert.ok(generator.driversClassMap);
|
|
32
|
+
counter++;
|
|
33
|
+
} catch(error) {
|
|
34
|
+
errors++;
|
|
35
|
+
throw error;
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
it('should initialize with custom projectPath', () => {
|
|
39
|
+
try {
|
|
40
|
+
let customPath = FileHandler.joinPaths(__dirname, 'custom-project');
|
|
41
|
+
let generator = new EntitiesGenerator({projectPath: customPath});
|
|
42
|
+
assert.strictEqual(generator.projectPath, customPath);
|
|
43
|
+
counter++;
|
|
44
|
+
} catch(error) {
|
|
45
|
+
errors++;
|
|
46
|
+
throw error;
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
it('should initialize with override flag', () => {
|
|
50
|
+
try {
|
|
51
|
+
let generator = new EntitiesGenerator({isOverride: true});
|
|
52
|
+
assert.strictEqual(generator.isOverride, true);
|
|
53
|
+
counter++;
|
|
54
|
+
} catch(error) {
|
|
55
|
+
errors++;
|
|
56
|
+
throw error;
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
it('should initialize empty generated entities map', () => {
|
|
60
|
+
try {
|
|
61
|
+
let generator = new EntitiesGenerator({});
|
|
62
|
+
assert.deepStrictEqual(generator.generatedEntities, {});
|
|
63
|
+
counter++;
|
|
64
|
+
} catch(error) {
|
|
65
|
+
errors++;
|
|
66
|
+
throw error;
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
it('should initialize empty existing entities map', () => {
|
|
70
|
+
try {
|
|
71
|
+
let generator = new EntitiesGenerator({});
|
|
72
|
+
assert.deepStrictEqual(generator.existingEntities, {});
|
|
73
|
+
counter++;
|
|
74
|
+
} catch(error) {
|
|
75
|
+
errors++;
|
|
76
|
+
throw error;
|
|
77
|
+
}
|
|
78
|
+
});
|
|
79
|
+
it('should initialize empty existing entity fields map', () => {
|
|
80
|
+
try {
|
|
81
|
+
let generator = new EntitiesGenerator({});
|
|
82
|
+
assert.deepStrictEqual(generator.existingEntityFields, {});
|
|
83
|
+
counter++;
|
|
84
|
+
} catch(error) {
|
|
85
|
+
errors++;
|
|
86
|
+
throw error;
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
it('should initialize empty existing models map', () => {
|
|
90
|
+
try {
|
|
91
|
+
let generator = new EntitiesGenerator({});
|
|
92
|
+
assert.deepStrictEqual(generator.existingModels, {});
|
|
93
|
+
counter++;
|
|
94
|
+
} catch(error) {
|
|
95
|
+
errors++;
|
|
96
|
+
throw error;
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
});
|
|
100
|
+
describe('detectExistingEntities', () => {
|
|
101
|
+
it('should return early when entities folder does not exist', () => {
|
|
102
|
+
try {
|
|
103
|
+
let generator = new EntitiesGenerator({});
|
|
104
|
+
generator.entitiesFolder = FileHandler.joinPaths(__dirname, 'nonexistent-folder');
|
|
105
|
+
generator.detectExistingEntities();
|
|
106
|
+
assert.deepStrictEqual(generator.existingEntities, {});
|
|
107
|
+
counter++;
|
|
108
|
+
} catch(error) {
|
|
109
|
+
errors++;
|
|
110
|
+
throw error;
|
|
111
|
+
}
|
|
112
|
+
});
|
|
113
|
+
it('should detect entity files with -entity.js suffix', () => {
|
|
114
|
+
try {
|
|
115
|
+
let generator = new EntitiesGenerator({});
|
|
116
|
+
generator.entitiesFolder = FileHandler.joinPaths(__dirname, '..', 'fixtures', 'mock-entities');
|
|
117
|
+
if(!FileHandler.exists(generator.entitiesFolder)){
|
|
118
|
+
assert.ok(true);
|
|
119
|
+
counter++;
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
generator.detectExistingEntities();
|
|
123
|
+
assert.ok(generator.existingEntities);
|
|
124
|
+
counter++;
|
|
125
|
+
} catch(error) {
|
|
126
|
+
errors++;
|
|
127
|
+
throw error;
|
|
128
|
+
}
|
|
129
|
+
});
|
|
130
|
+
it('should skip files without -entity.js suffix', () => {
|
|
131
|
+
try {
|
|
132
|
+
let generator = new EntitiesGenerator({});
|
|
133
|
+
generator.entitiesFolder = FileHandler.joinPaths(__dirname, '..', 'fixtures');
|
|
134
|
+
if(!FileHandler.exists(generator.entitiesFolder)){
|
|
135
|
+
assert.ok(true);
|
|
136
|
+
counter++;
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
generator.detectExistingEntities();
|
|
140
|
+
let entityFiles = Object.values(generator.existingEntities);
|
|
141
|
+
for(let entity of entityFiles){
|
|
142
|
+
assert.ok(entity.entityFileName.endsWith('-entity.js'));
|
|
143
|
+
}
|
|
144
|
+
counter++;
|
|
145
|
+
} catch(error) {
|
|
146
|
+
errors++;
|
|
147
|
+
throw error;
|
|
148
|
+
}
|
|
149
|
+
});
|
|
150
|
+
it('should convert kebab-case filenames to snake_case table names', () => {
|
|
151
|
+
try {
|
|
152
|
+
let generator = new EntitiesGenerator({});
|
|
153
|
+
generator.entitiesFolder = FileHandler.joinPaths(__dirname, '..', 'fixtures', 'mock-entities');
|
|
154
|
+
if(!FileHandler.exists(generator.entitiesFolder)){
|
|
155
|
+
assert.ok(true);
|
|
156
|
+
counter++;
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
generator.detectExistingEntities();
|
|
160
|
+
for(let tableName of Object.keys(generator.existingEntities)){
|
|
161
|
+
assert.ok(!tableName.includes('-'));
|
|
162
|
+
}
|
|
163
|
+
counter++;
|
|
164
|
+
} catch(error) {
|
|
165
|
+
errors++;
|
|
166
|
+
throw error;
|
|
167
|
+
}
|
|
168
|
+
});
|
|
169
|
+
});
|
|
170
|
+
describe('detectExistingModels', () => {
|
|
171
|
+
it('should return early when models folder does not exist', () => {
|
|
172
|
+
try {
|
|
173
|
+
let generator = new EntitiesGenerator({});
|
|
174
|
+
generator.modelsFolder = FileHandler.joinPaths(__dirname, 'nonexistent-folder');
|
|
175
|
+
generator.detectExistingModels();
|
|
176
|
+
assert.deepStrictEqual(generator.existingModels, {});
|
|
177
|
+
counter++;
|
|
178
|
+
} catch(error) {
|
|
179
|
+
errors++;
|
|
180
|
+
throw error;
|
|
181
|
+
}
|
|
182
|
+
});
|
|
183
|
+
it('should detect model files in driver subfolders', () => {
|
|
184
|
+
try {
|
|
185
|
+
let generator = new EntitiesGenerator({});
|
|
186
|
+
generator.modelsFolder = FileHandler.joinPaths(__dirname, '..', 'fixtures', 'mock-models');
|
|
187
|
+
if(!FileHandler.exists(generator.modelsFolder)){
|
|
188
|
+
assert.ok(true);
|
|
189
|
+
counter++;
|
|
190
|
+
return;
|
|
191
|
+
}
|
|
192
|
+
generator.detectExistingModels();
|
|
193
|
+
assert.ok(generator.existingModels);
|
|
194
|
+
counter++;
|
|
195
|
+
} catch(error) {
|
|
196
|
+
errors++;
|
|
197
|
+
throw error;
|
|
198
|
+
}
|
|
199
|
+
});
|
|
200
|
+
it('should skip files without -model.js suffix', () => {
|
|
201
|
+
try {
|
|
202
|
+
let generator = new EntitiesGenerator({});
|
|
203
|
+
generator.modelsFolder = FileHandler.joinPaths(__dirname, '..', 'fixtures', 'mock-models');
|
|
204
|
+
if(!FileHandler.exists(generator.modelsFolder)){
|
|
205
|
+
assert.ok(true);
|
|
206
|
+
counter++;
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
209
|
+
generator.detectExistingModels();
|
|
210
|
+
for(let tableName of Object.keys(generator.existingModels)){
|
|
211
|
+
for(let driverKey of Object.keys(generator.existingModels[tableName])){
|
|
212
|
+
assert.ok(generator.existingModels[tableName][driverKey].modelFileName.endsWith('-model.js'));
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
counter++;
|
|
216
|
+
} catch(error) {
|
|
217
|
+
errors++;
|
|
218
|
+
throw error;
|
|
219
|
+
}
|
|
220
|
+
});
|
|
221
|
+
it('should group models by table name and driver', () => {
|
|
222
|
+
try {
|
|
223
|
+
let generator = new EntitiesGenerator({});
|
|
224
|
+
generator.modelsFolder = FileHandler.joinPaths(__dirname, '..', 'fixtures', 'mock-models');
|
|
225
|
+
if(!FileHandler.exists(generator.modelsFolder)){
|
|
226
|
+
assert.ok(true);
|
|
227
|
+
counter++;
|
|
228
|
+
return;
|
|
229
|
+
}
|
|
230
|
+
generator.detectExistingModels();
|
|
231
|
+
for(let tableName of Object.keys(generator.existingModels)){
|
|
232
|
+
assert.ok('object' === typeof generator.existingModels[tableName]);
|
|
233
|
+
for(let driverKey of Object.keys(generator.existingModels[tableName])){
|
|
234
|
+
assert.ok(generator.existingModels[tableName][driverKey].driverKey);
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
counter++;
|
|
238
|
+
} catch(error) {
|
|
239
|
+
errors++;
|
|
240
|
+
throw error;
|
|
241
|
+
}
|
|
242
|
+
});
|
|
243
|
+
});
|
|
244
|
+
describe('detectExistingEntityFields', () => {
|
|
245
|
+
it('should return early when file does not exist', () => {
|
|
246
|
+
try {
|
|
247
|
+
let generator = new EntitiesGenerator({});
|
|
248
|
+
generator.entitiesFolder = FileHandler.joinPaths(__dirname, 'nonexistent-folder');
|
|
249
|
+
generator.detectExistingEntityFields('test_table', 'test-entity.js');
|
|
250
|
+
assert.ok(!generator.existingEntityFields['test_table']);
|
|
251
|
+
counter++;
|
|
252
|
+
} catch(error) {
|
|
253
|
+
errors++;
|
|
254
|
+
throw error;
|
|
255
|
+
}
|
|
256
|
+
});
|
|
257
|
+
it('should extract property names from entity file', () => {
|
|
258
|
+
try {
|
|
259
|
+
let generator = new EntitiesGenerator({});
|
|
260
|
+
let mockEntityPath = FileHandler.joinPaths(__dirname, '..', 'fixtures', 'mock-entities', 'test-users-entity.js');
|
|
261
|
+
if(!FileHandler.exists(mockEntityPath)){
|
|
262
|
+
assert.ok(true);
|
|
263
|
+
counter++;
|
|
264
|
+
return;
|
|
265
|
+
}
|
|
266
|
+
generator.entitiesFolder = FileHandler.joinPaths(__dirname, '..', 'fixtures', 'mock-entities');
|
|
267
|
+
generator.detectExistingEntityFields('test_users', 'test-users-entity.js');
|
|
268
|
+
assert.ok(generator.existingEntityFields['test_users']);
|
|
269
|
+
assert.ok(Array.isArray(generator.existingEntityFields['test_users']));
|
|
270
|
+
counter++;
|
|
271
|
+
} catch(error) {
|
|
272
|
+
errors++;
|
|
273
|
+
throw error;
|
|
274
|
+
}
|
|
275
|
+
});
|
|
276
|
+
});
|
|
277
|
+
describe('entityNeedsUpdate', () => {
|
|
278
|
+
it('should return true when no existing fields', () => {
|
|
279
|
+
try {
|
|
280
|
+
let generator = new EntitiesGenerator({});
|
|
281
|
+
let tableData = {columns: {id: {}, name: {}, email: {}}};
|
|
282
|
+
let needsUpdate = generator.entityNeedsUpdate('new_table', tableData);
|
|
283
|
+
assert.strictEqual(needsUpdate, true);
|
|
284
|
+
counter++;
|
|
285
|
+
} catch(error) {
|
|
286
|
+
errors++;
|
|
287
|
+
throw error;
|
|
288
|
+
}
|
|
289
|
+
});
|
|
290
|
+
it('should return true when database has new field', () => {
|
|
291
|
+
try {
|
|
292
|
+
let generator = new EntitiesGenerator({});
|
|
293
|
+
generator.existingEntityFields['test_table'] = ['id', 'name'];
|
|
294
|
+
let tableData = {columns: {id: {}, name: {}, email: {}}};
|
|
295
|
+
let needsUpdate = generator.entityNeedsUpdate('test_table', tableData);
|
|
296
|
+
assert.strictEqual(needsUpdate, true);
|
|
297
|
+
counter++;
|
|
298
|
+
} catch(error) {
|
|
299
|
+
errors++;
|
|
300
|
+
throw error;
|
|
301
|
+
}
|
|
302
|
+
});
|
|
303
|
+
it('should return true when entity has removed field', () => {
|
|
304
|
+
try {
|
|
305
|
+
let generator = new EntitiesGenerator({});
|
|
306
|
+
generator.existingEntityFields['test_table'] = ['id', 'name', 'email', 'phone'];
|
|
307
|
+
let tableData = {columns: {id: {}, name: {}, email: {}}};
|
|
308
|
+
let needsUpdate = generator.entityNeedsUpdate('test_table', tableData);
|
|
309
|
+
assert.strictEqual(needsUpdate, true);
|
|
310
|
+
counter++;
|
|
311
|
+
} catch(error) {
|
|
312
|
+
errors++;
|
|
313
|
+
throw error;
|
|
314
|
+
}
|
|
315
|
+
});
|
|
316
|
+
it('should return false when fields match exactly', () => {
|
|
317
|
+
try {
|
|
318
|
+
let generator = new EntitiesGenerator({});
|
|
319
|
+
generator.existingEntityFields['test_table'] = ['id', 'name', 'email'];
|
|
320
|
+
let tableData = {columns: {id: {}, name: {}, email: {}}};
|
|
321
|
+
let needsUpdate = generator.entityNeedsUpdate('test_table', tableData);
|
|
322
|
+
assert.strictEqual(needsUpdate, false);
|
|
323
|
+
counter++;
|
|
324
|
+
} catch(error) {
|
|
325
|
+
errors++;
|
|
326
|
+
throw error;
|
|
327
|
+
}
|
|
328
|
+
});
|
|
329
|
+
it('should ignore id field when checking for removed fields', () => {
|
|
330
|
+
try {
|
|
331
|
+
let generator = new EntitiesGenerator({});
|
|
332
|
+
generator.existingEntityFields['test_table'] = ['id', 'name'];
|
|
333
|
+
let tableData = {columns: {id: {}, name: {}}};
|
|
334
|
+
let needsUpdate = generator.entityNeedsUpdate('test_table', tableData);
|
|
335
|
+
assert.strictEqual(needsUpdate, false);
|
|
336
|
+
counter++;
|
|
337
|
+
} catch(error) {
|
|
338
|
+
errors++;
|
|
339
|
+
throw error;
|
|
340
|
+
}
|
|
341
|
+
});
|
|
342
|
+
});
|
|
343
|
+
describe('filterTablesToGenerate', () => {
|
|
344
|
+
let generator;
|
|
345
|
+
beforeEach(() => {
|
|
346
|
+
generator = new EntitiesGenerator({});
|
|
347
|
+
generator.existingEntities = {};
|
|
348
|
+
generator.existingModels = {};
|
|
349
|
+
generator.existingEntityFields = {};
|
|
350
|
+
generator.entitiesConfigPath = FileHandler.joinPaths(__dirname, 'nonexistent-config.js');
|
|
351
|
+
});
|
|
352
|
+
it('should include new tables', () => {
|
|
353
|
+
try {
|
|
354
|
+
let tables = {
|
|
355
|
+
new_table: {columns: {id: {}, name: {}}}
|
|
356
|
+
};
|
|
357
|
+
let filtered = generator.filterTablesToGenerate(tables, 'objection-js');
|
|
358
|
+
assert.ok(filtered['new_table']);
|
|
359
|
+
counter++;
|
|
360
|
+
} catch(error) {
|
|
361
|
+
errors++;
|
|
362
|
+
throw error;
|
|
363
|
+
}
|
|
364
|
+
});
|
|
365
|
+
it('should include tables with field changes', () => {
|
|
366
|
+
try {
|
|
367
|
+
generator.existingEntities['test_table'] = {entityFileName: 'test-table-entity.js'};
|
|
368
|
+
generator.existingEntityFields['test_table'] = ['id', 'name'];
|
|
369
|
+
generator.entityExistsInConfig = () => true;
|
|
370
|
+
generator.modelExistsInRegistered = () => true;
|
|
371
|
+
let tables = {
|
|
372
|
+
test_table: {columns: {id: {}, name: {}, email: {}}}
|
|
373
|
+
};
|
|
374
|
+
let filtered = generator.filterTablesToGenerate(tables, 'objection-js');
|
|
375
|
+
assert.ok(filtered['test_table']);
|
|
376
|
+
counter++;
|
|
377
|
+
} catch(error) {
|
|
378
|
+
errors++;
|
|
379
|
+
throw error;
|
|
380
|
+
}
|
|
381
|
+
});
|
|
382
|
+
it('should include tables missing models', () => {
|
|
383
|
+
try {
|
|
384
|
+
generator.existingEntities['test_table'] = {entityFileName: 'test-table-entity.js'};
|
|
385
|
+
generator.existingEntityFields['test_table'] = ['id', 'name'];
|
|
386
|
+
generator.entityExistsInConfig = () => true;
|
|
387
|
+
let tables = {
|
|
388
|
+
test_table: {columns: {id: {}, name: {}}}
|
|
389
|
+
};
|
|
390
|
+
let filtered = generator.filterTablesToGenerate(tables, 'objection-js');
|
|
391
|
+
assert.ok(filtered['test_table']);
|
|
392
|
+
counter++;
|
|
393
|
+
} catch(error) {
|
|
394
|
+
errors++;
|
|
395
|
+
throw error;
|
|
396
|
+
}
|
|
397
|
+
});
|
|
398
|
+
it('should exclude tables that are fully configured and up to date', () => {
|
|
399
|
+
try {
|
|
400
|
+
generator.existingEntities['test_table'] = {entityFileName: 'test-table-entity.js'};
|
|
401
|
+
generator.existingEntityFields['test_table'] = ['id', 'name'];
|
|
402
|
+
generator.existingModels['test_table'] = {
|
|
403
|
+
'objection-js': {modelFileName: 'test-table-model.js'}
|
|
404
|
+
};
|
|
405
|
+
generator.modelExistsInRegistered = () => true;
|
|
406
|
+
generator.entityExistsInConfig = () => true;
|
|
407
|
+
let tables = {
|
|
408
|
+
test_table: {columns: {id: {}, name: {}}}
|
|
409
|
+
};
|
|
410
|
+
let filtered = generator.filterTablesToGenerate(tables, 'objection-js');
|
|
411
|
+
assert.ok(!filtered['test_table']);
|
|
412
|
+
counter++;
|
|
413
|
+
} catch(error) {
|
|
414
|
+
errors++;
|
|
415
|
+
throw error;
|
|
416
|
+
}
|
|
417
|
+
});
|
|
418
|
+
it('should include all tables when override flag is set', () => {
|
|
419
|
+
try {
|
|
420
|
+
generator.isOverride = true;
|
|
421
|
+
generator.existingEntities['test_table'] = {entityFileName: 'test-table-entity.js'};
|
|
422
|
+
generator.existingEntityFields['test_table'] = ['id', 'name'];
|
|
423
|
+
generator.existingModels['test_table'] = {
|
|
424
|
+
'objection-js': {modelFileName: 'test-table-model.js'}
|
|
425
|
+
};
|
|
426
|
+
generator.modelExistsInRegistered = () => true;
|
|
427
|
+
generator.entityExistsInConfig = () => true;
|
|
428
|
+
let tables = {
|
|
429
|
+
test_table: {columns: {id: {}, name: {}}}
|
|
430
|
+
};
|
|
431
|
+
let filtered = generator.filterTablesToGenerate(tables, 'objection-js');
|
|
432
|
+
assert.ok(filtered['test_table']);
|
|
433
|
+
counter++;
|
|
434
|
+
} catch(error) {
|
|
435
|
+
errors++;
|
|
436
|
+
throw error;
|
|
437
|
+
}
|
|
438
|
+
});
|
|
439
|
+
it('should return empty object when no tables need generation', () => {
|
|
440
|
+
try {
|
|
441
|
+
generator.existingEntities['test_table'] = {entityFileName: 'test-table-entity.js'};
|
|
442
|
+
generator.existingEntityFields['test_table'] = ['id', 'name'];
|
|
443
|
+
generator.existingModels['test_table'] = {
|
|
444
|
+
'objection-js': {modelFileName: 'test-table-model.js'}
|
|
445
|
+
};
|
|
446
|
+
generator.modelExistsInRegistered = () => true;
|
|
447
|
+
generator.entityExistsInConfig = () => true;
|
|
448
|
+
let tables = {
|
|
449
|
+
test_table: {columns: {id: {}, name: {}}}
|
|
450
|
+
};
|
|
451
|
+
let filtered = generator.filterTablesToGenerate(tables, 'objection-js');
|
|
452
|
+
assert.strictEqual(Object.keys(filtered).length, 0);
|
|
453
|
+
counter++;
|
|
454
|
+
} catch(error) {
|
|
455
|
+
errors++;
|
|
456
|
+
throw error;
|
|
457
|
+
}
|
|
458
|
+
});
|
|
459
|
+
});
|
|
460
|
+
describe('entityExistsInConfig', () => {
|
|
461
|
+
it('should delegate to entitiesConfigGeneration', () => {
|
|
462
|
+
try {
|
|
463
|
+
let generator = new EntitiesGenerator({});
|
|
464
|
+
generator.entitiesConfigPath = FileHandler.joinPaths(__dirname, 'nonexistent-config.js');
|
|
465
|
+
let called = false;
|
|
466
|
+
generator.entitiesConfigGeneration.entityExistsInConfig = () => {
|
|
467
|
+
called = true;
|
|
468
|
+
return true;
|
|
469
|
+
};
|
|
470
|
+
generator.entityExistsInConfig('test_table');
|
|
471
|
+
assert.strictEqual(called, true);
|
|
472
|
+
counter++;
|
|
473
|
+
} catch(error) {
|
|
474
|
+
errors++;
|
|
475
|
+
throw error;
|
|
476
|
+
}
|
|
477
|
+
});
|
|
478
|
+
});
|
|
479
|
+
describe('modelExistsInRegistered', () => {
|
|
480
|
+
it('should return false when registered models file does not exist', () => {
|
|
481
|
+
try {
|
|
482
|
+
let generator = new EntitiesGenerator({});
|
|
483
|
+
generator.modelsFolder = FileHandler.joinPaths(__dirname, 'nonexistent-folder');
|
|
484
|
+
let exists = generator.modelExistsInRegistered('test_table', 'objection-js');
|
|
485
|
+
assert.strictEqual(exists, false);
|
|
486
|
+
counter++;
|
|
487
|
+
} catch(error) {
|
|
488
|
+
errors++;
|
|
489
|
+
throw error;
|
|
490
|
+
}
|
|
491
|
+
});
|
|
492
|
+
it('should return false when model not found in registered file', () => {
|
|
493
|
+
try {
|
|
494
|
+
let generator = new EntitiesGenerator({});
|
|
495
|
+
generator.modelsFolder = FileHandler.joinPaths(__dirname, '..', 'fixtures', 'mock-models');
|
|
496
|
+
let registeredPath = FileHandler.joinPaths(generator.modelsFolder, 'objection-js', 'registered-models-objection-js.js');
|
|
497
|
+
if(!FileHandler.exists(registeredPath)){
|
|
498
|
+
assert.ok(true);
|
|
499
|
+
counter++;
|
|
500
|
+
return;
|
|
501
|
+
}
|
|
502
|
+
let exists = generator.modelExistsInRegistered('nonexistent_table', 'objection-js');
|
|
503
|
+
assert.strictEqual(exists, false);
|
|
504
|
+
counter++;
|
|
505
|
+
} catch(error) {
|
|
506
|
+
errors++;
|
|
507
|
+
throw error;
|
|
508
|
+
}
|
|
509
|
+
});
|
|
510
|
+
});
|
|
511
|
+
describe('ensureFoldersExist', () => {
|
|
512
|
+
it('should return true when all folders created successfully', () => {
|
|
513
|
+
try {
|
|
514
|
+
let generator = new EntitiesGenerator({});
|
|
515
|
+
generator.generationFolder = FileHandler.joinPaths(__dirname, 'temp-generation');
|
|
516
|
+
generator.entitiesFolder = FileHandler.joinPaths(generator.generationFolder, 'entities');
|
|
517
|
+
generator.modelsFolder = FileHandler.joinPaths(generator.generationFolder, 'models');
|
|
518
|
+
let result = generator.ensureFoldersExist();
|
|
519
|
+
assert.ok(result);
|
|
520
|
+
counter++;
|
|
521
|
+
} catch(error) {
|
|
522
|
+
errors++;
|
|
523
|
+
throw error;
|
|
524
|
+
}
|
|
525
|
+
});
|
|
526
|
+
});
|
|
527
|
+
});
|
|
528
|
+
return {counter, errors};
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
module.exports = EntitiesGeneratorTest;
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
/**
|
|
2
|
+
*
|
|
3
|
+
* Reldens - EntityManager Test
|
|
4
|
+
*
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const { TestRunner, assert } = require('../utils/test-runner');
|
|
8
|
+
const { EntityManager } = require('../../lib/entity-manager');
|
|
9
|
+
|
|
10
|
+
class EntityManagerTest
|
|
11
|
+
{
|
|
12
|
+
|
|
13
|
+
constructor()
|
|
14
|
+
{
|
|
15
|
+
this.runner = new TestRunner();
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
async run()
|
|
19
|
+
{
|
|
20
|
+
this.runner.suite('EntityManager');
|
|
21
|
+
await this.testConstructor();
|
|
22
|
+
await this.testSetEntities();
|
|
23
|
+
await this.testGet();
|
|
24
|
+
await this.testAdd();
|
|
25
|
+
await this.testRemove();
|
|
26
|
+
await this.testClear();
|
|
27
|
+
return this.runner.getResults();
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
async testConstructor()
|
|
31
|
+
{
|
|
32
|
+
this.runner.group('constructor');
|
|
33
|
+
await this.runner.test('should initialize with empty entities object', async () => {
|
|
34
|
+
let emptyManager = new EntityManager({});
|
|
35
|
+
assert.deepStrictEqual(emptyManager.entities, {});
|
|
36
|
+
});
|
|
37
|
+
await this.runner.test('should initialize with provided entities', async () => {
|
|
38
|
+
let initialEntities = {users: {}, posts: {}};
|
|
39
|
+
let preloadedManager = new EntityManager({entities: initialEntities});
|
|
40
|
+
assert.deepStrictEqual(preloadedManager.entities, initialEntities);
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
async testSetEntities()
|
|
45
|
+
{
|
|
46
|
+
this.runner.group('setEntities');
|
|
47
|
+
await this.runner.test('should set entities object', async () => {
|
|
48
|
+
let manager = new EntityManager({});
|
|
49
|
+
let newEntities = {categories: {}, products: {}};
|
|
50
|
+
manager.setEntities(newEntities);
|
|
51
|
+
assert.deepStrictEqual(manager.entities, newEntities);
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
async testGet()
|
|
56
|
+
{
|
|
57
|
+
this.runner.group('get');
|
|
58
|
+
await this.runner.test('should retrieve entity by key', async () => {
|
|
59
|
+
let manager = new EntityManager({});
|
|
60
|
+
let mockEntity = {name: 'users'};
|
|
61
|
+
manager.entities = {users: mockEntity};
|
|
62
|
+
let result = manager.get('users');
|
|
63
|
+
assert.strictEqual(result, mockEntity);
|
|
64
|
+
});
|
|
65
|
+
await this.runner.test('should return undefined for non-existent key', async () => {
|
|
66
|
+
let manager = new EntityManager({});
|
|
67
|
+
let result = manager.get('nonexistent');
|
|
68
|
+
assert.strictEqual(result, undefined);
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
async testAdd()
|
|
73
|
+
{
|
|
74
|
+
this.runner.group('add');
|
|
75
|
+
await this.runner.test('should add entity with key', async () => {
|
|
76
|
+
let manager = new EntityManager({});
|
|
77
|
+
let mockEntity = {name: 'posts'};
|
|
78
|
+
manager.add('posts', mockEntity);
|
|
79
|
+
assert.strictEqual(manager.entities.posts, mockEntity);
|
|
80
|
+
});
|
|
81
|
+
await this.runner.test('should return the added entity', async () => {
|
|
82
|
+
let manager = new EntityManager({});
|
|
83
|
+
let mockEntity = {name: 'comments'};
|
|
84
|
+
let result = manager.add('comments', mockEntity);
|
|
85
|
+
assert.strictEqual(result, mockEntity);
|
|
86
|
+
});
|
|
87
|
+
await this.runner.test('should overwrite existing entity with same key', async () => {
|
|
88
|
+
let manager = new EntityManager({});
|
|
89
|
+
let firstEntity = {name: 'first'};
|
|
90
|
+
let secondEntity = {name: 'second'};
|
|
91
|
+
manager.add('test', firstEntity);
|
|
92
|
+
manager.add('test', secondEntity);
|
|
93
|
+
assert.strictEqual(manager.entities.test, secondEntity);
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
async testRemove()
|
|
98
|
+
{
|
|
99
|
+
this.runner.group('remove');
|
|
100
|
+
await this.runner.test('should remove entity by key', async () => {
|
|
101
|
+
let manager = new EntityManager({});
|
|
102
|
+
manager.entities = {users: {}, posts: {}};
|
|
103
|
+
manager.remove('users');
|
|
104
|
+
assert.strictEqual(manager.entities.users, undefined);
|
|
105
|
+
assert.ok(manager.entities.posts);
|
|
106
|
+
});
|
|
107
|
+
await this.runner.test('should not throw error when removing non-existent key', async () => {
|
|
108
|
+
let manager = new EntityManager({});
|
|
109
|
+
assert.doesNotThrow(() => {
|
|
110
|
+
manager.remove('nonexistent');
|
|
111
|
+
});
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
async testClear()
|
|
116
|
+
{
|
|
117
|
+
this.runner.group('clear');
|
|
118
|
+
await this.runner.test('should remove all entities', async () => {
|
|
119
|
+
let manager = new EntityManager({});
|
|
120
|
+
manager.entities = {users: {}, posts: {}, comments: {}};
|
|
121
|
+
manager.clear();
|
|
122
|
+
assert.deepStrictEqual(manager.entities, {});
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
module.exports = EntityManagerTest;
|