@reldens/storage 0.117.0 → 0.118.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.
Files changed (78) hide show
  1. package/.claude/test-architecture.md +27 -17
  2. package/CLAUDE.md +67 -11
  3. package/README.md +204 -22
  4. package/bin/reldens-storage.js +43 -10
  5. package/index.js +53 -12
  6. package/lib/drizzle/drizzle-data-server.js +123 -0
  7. package/lib/drizzle/drizzle-driver.js +228 -0
  8. package/lib/drizzle/drizzle-models-generation.js +49 -0
  9. package/lib/drizzle/drizzle-modules-loader.js +32 -0
  10. package/lib/drizzle/drizzle-modules-validator.js +74 -0
  11. package/lib/entities-generator.js +36 -7
  12. package/lib/entity-templates/drizzle-model.template +28 -0
  13. package/lib/entity-templates/query-builder-model.template +17 -0
  14. package/lib/generators/base-generator.js +13 -0
  15. package/lib/generators/entities-generation.js +0 -13
  16. package/lib/generators/models-generation.js +179 -680
  17. package/lib/generators/relations-detection.js +171 -0
  18. package/lib/knex/knex-data-server.js +128 -0
  19. package/lib/knex/knex-driver.js +157 -0
  20. package/lib/knex/knex-modules-loader.js +28 -0
  21. package/lib/knex/knex-modules-validator.js +45 -0
  22. package/lib/kysely/kysely-data-server.js +128 -0
  23. package/lib/kysely/kysely-driver.js +176 -0
  24. package/lib/kysely/kysely-modules-loader.js +28 -0
  25. package/lib/kysely/kysely-modules-validator.js +53 -0
  26. package/lib/mikro-orm/mikro-orm-data-server.js +48 -29
  27. package/lib/mikro-orm/mikro-orm-driver.js +317 -108
  28. package/lib/mikro-orm/mikro-orm-models-generation.js +178 -0
  29. package/lib/mikro-orm/mikro-orm-modules-loader.js +50 -0
  30. package/lib/mikro-orm/mikro-orm-modules-validator.js +46 -0
  31. package/lib/mysql2-connection-config.js +38 -0
  32. package/lib/objection-js/objection-js-data-server.js +71 -125
  33. package/lib/objection-js/objection-js-driver.js +4 -1
  34. package/lib/objection-js/objection-js-models-generation.js +98 -0
  35. package/lib/objection-js/objection-modules-loader.js +28 -0
  36. package/lib/objection-js/objection-modules-validator.js +31 -0
  37. package/lib/package-resolver.js +45 -0
  38. package/lib/prisma/prisma-client-loader.js +11 -1
  39. package/lib/prisma/prisma-driver.js +16 -2
  40. package/lib/prisma/prisma-filter-processor.js +5 -6
  41. package/lib/prisma/prisma-models-generation.js +236 -0
  42. package/lib/prisma/prisma-schema-generator.js +5 -1
  43. package/lib/prisma/prisma-type-caster.js +14 -0
  44. package/lib/query-builder-driver.js +210 -0
  45. package/lib/query-builder-models-generation.js +80 -0
  46. package/lib/relations-loader.js +192 -0
  47. package/lib/type-mapper.js +38 -0
  48. package/package.json +7 -7
  49. package/tests/.env.test.example +6 -0
  50. package/tests/fixtures/categories-fixtures.js +8 -0
  51. package/tests/fixtures/expected-entities/entities/test-product-details-entity.js +10 -1
  52. package/tests/fixtures/expected-entities/entities-translations.js +2 -0
  53. package/tests/fixtures/expected-entities-mikro-orm/models/mikro-orm/test-categories-model.js +13 -8
  54. package/tests/fixtures/expected-entities-mikro-orm/models/mikro-orm/test-product-details-model.js +30 -10
  55. package/tests/fixtures/expected-entities-mikro-orm/models/mikro-orm/test-products-model.js +15 -14
  56. package/tests/fixtures/expected-entities-mikro-orm/models/mikro-orm/test-reviews-model.js +13 -12
  57. package/tests/fixtures/expected-entities-prisma/models/prisma/test-product-details-model.js +3 -1
  58. package/tests/fixtures/product-details-fixtures.js +4 -1
  59. package/tests/fixtures/reviews-fixtures.js +2 -1
  60. package/tests/fixtures/sql/test-schema.sql +11 -2
  61. package/tests/fixtures/table-columns-fixtures.js +97 -0
  62. package/tests/integration/test-cross-driver-equivalence.js +286 -0
  63. package/tests/integration/test-nested-filters.js +265 -408
  64. package/tests/integration/test-relations.js +135 -0
  65. package/tests/integration/test-reldens-sample-data.js +255 -0
  66. package/tests/integration/test-reldens-shape-relations.js +292 -0
  67. package/tests/run-tests.js +111 -65
  68. package/tests/unit/test-drivers.js +7 -1
  69. package/tests/unit/test-models-generation.js +28 -18
  70. package/tests/utils/column-value-assert.js +139 -0
  71. package/tests/utils/entity-projection.js +111 -0
  72. package/tests/utils/observed-value.js +41 -0
  73. package/tests/utils/projection-difference.js +151 -0
  74. package/tests/utils/relations-shape-support.js +104 -0
  75. package/tests/utils/reldens-schema-loader.js +274 -0
  76. package/tests/utils/test-helpers.js +143 -13
  77. package/tests/utils/test-runner.js +26 -5
  78. package/tests/utils/whole-result-assert.js +243 -0
@@ -39,9 +39,89 @@ class RelationsTest
39
39
  await this.testNestedRelations();
40
40
  await this.testRelationStringParsing();
41
41
  await this.testOneToOneRelations();
42
+ await this.testCamelCaseColumns();
42
43
  return this.runner.getResults();
43
44
  }
44
45
 
46
+ async testCamelCaseColumns()
47
+ {
48
+ this.runner.group('CamelCase Columns');
49
+ await TestHelpers.cleanDatabase(this.dataServer);
50
+ await TestHelpers.insertFixturesViaRawSQL(this.dataServer, 'test_categories', [
51
+ CategoriesFixtures.category_relations_1
52
+ ]);
53
+ await TestHelpers.insertFixturesViaRawSQL(this.dataServer, 'test_products', [
54
+ ProductsFixtures.product_relations_1
55
+ ]);
56
+ await TestHelpers.insertFixturesViaRawSQL(this.dataServer, 'test_product_details', [
57
+ ProductDetailsFixtures.product_details_relations_1
58
+ ]);
59
+ await this.runner.test('should read a camelCase column with the exact database column name', async () => {
60
+ let record = await this.productDetailsRepo.loadById(4600);
61
+ assert.ok(record);
62
+ assert.strictEqual(record.customData, ProductDetailsFixtures.product_details_relations_1.customData);
63
+ assert.strictEqual(record.useTimeOut, ProductDetailsFixtures.product_details_relations_1.useTimeOut);
64
+ });
65
+ await this.runner.test('should read a bigint column as a number', async () => {
66
+ let record = await this.productDetailsRepo.loadById(4600);
67
+ assert.strictEqual(typeof record.total_views, 'number');
68
+ assert.strictEqual(record.total_views, ProductDetailsFixtures.product_details_relations_1.total_views);
69
+ assert.strictEqual(record.total_views + 1, ProductDetailsFixtures.product_details_relations_1.total_views + 1);
70
+ });
71
+ await this.runner.test('should filter by a camelCase column', async () => {
72
+ let records = await this.productDetailsRepo.loadBy('useTimeOut', 45);
73
+ assert.strictEqual(records.length, 1);
74
+ assert.strictEqual(records[0].id, 4600);
75
+ });
76
+ await this.runner.test('should write a camelCase column', async () => {
77
+ await this.productDetailsRepo.updateById(4600, {useTimeOut: 90});
78
+ let updated = await this.productDetailsRepo.loadById(4600);
79
+ assert.strictEqual(updated.useTimeOut, 90);
80
+ });
81
+ await this.runner.test('should populate a relation whose target has camelCase columns', async () => {
82
+ let results = await this.productsRepo.loadWithRelations({id: 2600}, ['related_test_product_details']);
83
+ assert.strictEqual(results.length, 1);
84
+ assert.strictEqual(
85
+ results[0].related_test_product_details.customData,
86
+ ProductDetailsFixtures.product_details_relations_1.customData
87
+ );
88
+ });
89
+ await this.runner.test('should return an explicit null for an empty nullable foreign key', async () => {
90
+ let record = await this.productDetailsRepo.loadById(4600);
91
+ assert.strictEqual(record.category_id, null);
92
+ });
93
+ await this.runner.test('should keep the foreign key column value on a nested populated relation', async () => {
94
+ let results = await this.categoriesRepo.loadWithRelations(
95
+ {id: 1600},
96
+ ['related_test_products.related_test_product_details']
97
+ );
98
+ let product = results[0].related_test_products[0];
99
+ assert.strictEqual(product.category_id, 1600);
100
+ assert.strictEqual(product.related_test_product_details.product_id, 2600);
101
+ });
102
+ await this.runner.test('should keep a nullable foreign key on the leaf of a nested populate', async () => {
103
+ let results = await this.categoriesRepo.loadWithRelations(
104
+ {id: 1600},
105
+ ['related_test_products.related_test_product_details']
106
+ );
107
+ let details = results[0].related_test_products[0].related_test_product_details;
108
+ assert.strictEqual(details.category_id, null);
109
+ });
110
+ await this.runner.test('should keep the foreign key column value on a load without relations', async () => {
111
+ let record = await this.productDetailsRepo.loadById(4600);
112
+ assert.strictEqual(record.product_id, 2600);
113
+ });
114
+ await this.runner.test('should keep the foreign key column value on loadBy without relations', async () => {
115
+ let records = await this.productDetailsRepo.loadBy('id', 4600);
116
+ assert.strictEqual(records[0].product_id, 2600);
117
+ });
118
+ await this.runner.test('should accept an object written into a text column', async () => {
119
+ await this.productDetailsRepo.updateById(4600, {customData: {onlyCurrentPlayer: true}});
120
+ let updated = await this.productDetailsRepo.loadById(4600);
121
+ assert.ok(updated.customData);
122
+ });
123
+ }
124
+
45
125
  async testOneToOneRelations()
46
126
  {
47
127
  this.runner.group('One To One Relations');
@@ -134,6 +214,10 @@ class RelationsTest
134
214
  assert.ok(results.length > 0);
135
215
  let product = results[0];
136
216
  assert.ok(product.related_test_categories);
217
+ assert.strictEqual(
218
+ product.related_test_categories.name,
219
+ CategoriesFixtures.category_relations_1.name
220
+ );
137
221
  assert.ok(product.related_test_reviews);
138
222
  assert.ok(Array.isArray(product.related_test_reviews));
139
223
  });
@@ -364,6 +448,9 @@ class RelationsTest
364
448
  await TestHelpers.insertFixturesViaRawSQL(this.dataServer, 'test_reviews', [
365
449
  ReviewsFixtures.review_relations_1
366
450
  ]);
451
+ await TestHelpers.insertFixturesViaRawSQL(this.dataServer, 'test_product_details', [
452
+ ProductDetailsFixtures.product_details_relations_1
453
+ ]);
367
454
  await this.runner.test('should load nested relations (category > products > reviews)', async () => {
368
455
  let results = await this.categoriesRepo.loadWithRelations(
369
456
  {id: 1600},
@@ -377,6 +464,50 @@ class RelationsTest
377
464
  let product = category.related_test_products[0];
378
465
  assert.ok(product.related_test_reviews);
379
466
  });
467
+ await this.runner.test('should load a relation whose foreign key references a non primary column', async () => {
468
+ let results = await this.categoriesRepo.loadWithRelations(
469
+ {id: 1600},
470
+ ['related_test_reviews']
471
+ );
472
+ let related = results[0].related_test_reviews;
473
+ assert.ok(Array.isArray(related));
474
+ assert.strictEqual(related.length, 1);
475
+ assert.strictEqual(related[0].reviewer_name, ReviewsFixtures.review_relations_1.reviewer_name);
476
+ });
477
+ await this.runner.test('should load a collection nested under an owning relation', async () => {
478
+ let results = await this.productDetailsRepo.loadAllWithRelations([
479
+ 'related_test_products.related_test_reviews'
480
+ ]);
481
+ let product = results[0].related_test_products;
482
+ assert.strictEqual(typeof product, 'object');
483
+ assert.strictEqual(product.name, ProductsFixtures.product_relations_1.name);
484
+ assert.ok(Array.isArray(product.related_test_reviews));
485
+ assert.strictEqual(
486
+ product.related_test_reviews[0].reviewer_name,
487
+ ReviewsFixtures.review_relations_1.reviewer_name
488
+ );
489
+ });
490
+ await this.runner.test('should load a nested relation through an owning relation as an entity', async () => {
491
+ let results = await this.productDetailsRepo.loadWithRelations(
492
+ {id: 4600},
493
+ ['related_test_products.related_test_categories']
494
+ );
495
+ let product = results[0].related_test_products;
496
+ assert.strictEqual(product.name, ProductsFixtures.product_relations_1.name);
497
+ assert.strictEqual(
498
+ product.related_test_categories.name,
499
+ CategoriesFixtures.category_relations_1.name
500
+ );
501
+ });
502
+ await this.runner.test('should return the nested collection as an array on the deepest level', async () => {
503
+ let results = await this.categoriesRepo.loadWithRelations(
504
+ {id: 1600},
505
+ ['related_test_products.related_test_reviews']
506
+ );
507
+ let product = results[0].related_test_products[0];
508
+ assert.ok(Array.isArray(product.related_test_reviews));
509
+ assert.strictEqual(product.related_test_reviews.length, 1);
510
+ });
380
511
  }
381
512
 
382
513
  async testRelationStringParsing()
@@ -405,6 +536,10 @@ class RelationsTest
405
536
  assert.ok(results);
406
537
  assert.ok(results.length > 0);
407
538
  assert.ok(results[0].related_test_categories);
539
+ assert.strictEqual(
540
+ results[0].related_test_categories.name,
541
+ CategoriesFixtures.category_relations_1.name
542
+ );
408
543
  });
409
544
  }
410
545
 
@@ -0,0 +1,255 @@
1
+ /**
2
+ *
3
+ * Reldens - Reldens Sample Data Test
4
+ * Runs the relation assertions against the real Reldens database: the schema from reldens-install-v4.0.0.sql
5
+ * and the rows inserted by reldens-basic-config-v4.0.0.sql and reldens-sample-data-v4.0.0.sql. Every expected
6
+ * count below is the amount of rows those files insert, so the assertions describe the shipped sample data.
7
+ *
8
+ */
9
+
10
+ const { TestRunner, assert } = require('../utils/test-runner');
11
+ const { ReldensSchemaLoader } = require('../utils/reldens-schema-loader');
12
+ const { ObservedValue } = require('../utils/observed-value');
13
+
14
+ class ReldensSampleDataTest
15
+ {
16
+
17
+ constructor(dataServer, repos, driverName)
18
+ {
19
+ this.driverName = driverName;
20
+ this.runner = new TestRunner();
21
+ this.dataServer = false;
22
+ this.repos = {};
23
+ this.entityNames = ['itemsItem', 'skillsClassPath', 'rooms', 'playersState'];
24
+ this.itemRelationCases = {
25
+ 'the coins requirements from the required item foreign key':
26
+ {itemId: 1, relationKey: 'related_objects_items_requirements_required_item_key', expectedRows: 4},
27
+ 'the coins rewards from the reward item foreign key':
28
+ {itemId: 1, relationKey: 'related_objects_items_rewards_reward_item_key', expectedRows: 5},
29
+ 'no coins requirement from the item foreign key':
30
+ {itemId: 1, relationKey: 'related_objects_items_requirements_item_key', expectedRows: 0},
31
+ 'the axe requirement from the item foreign key':
32
+ {itemId: 4, relationKey: 'related_objects_items_requirements_item_key', expectedRows: 1},
33
+ 'no axe requirement from the required item foreign key':
34
+ {itemId: 4, relationKey: 'related_objects_items_requirements_required_item_key', expectedRows: 0},
35
+ 'the axe reward from the item foreign key':
36
+ {itemId: 4, relationKey: 'related_objects_items_rewards_item_key', expectedRows: 1}
37
+ };
38
+ this.levelsSetKey = 'related_skills_levels_set';
39
+ this.levelsKey = 'related_skills_levels';
40
+ this.levelsModifiersKey = 'related_skills_levels_modifiers';
41
+ this.changePointsKey = 'related_rooms_change_points_room';
42
+ this.nextRoomKey = 'related_rooms_next_room';
43
+ this.skillsLevelsChain = this.levelsSetKey+'.'+this.levelsKey+'.'+this.levelsModifiersKey;
44
+ this.changePointsChain = this.changePointsKey+'.'+this.nextRoomKey;
45
+ this.journeymanClassPathId = 1;
46
+ this.journeymanLevelsSetId = 1;
47
+ this.journeymanLevelsRows = 4;
48
+ this.journeymanModifiersByLevelId = {1: 0, 2: 8, 3: 8, 4: 8};
49
+ this.botsForestRoomId = 9;
50
+ this.botsForestChangePointsRows = 1;
51
+ this.botsForestNextRoomId = 10;
52
+ this.botsForestNextRoomName = 'reldens-bots-forest-house-01-n0';
53
+ this.playersStateId = 1;
54
+ this.playersStatePlayerId = 1;
55
+ this.playersStateRoomId = 5;
56
+ }
57
+
58
+ async run()
59
+ {
60
+ this.runner.suite('Reldens Sample Data - Driver: '+this.driverName);
61
+ if(!ReldensSchemaLoader.isAvailable()){
62
+ return this.runner.fail(
63
+ 'reldens migrations must be available for '+this.driverName,
64
+ 'RELDENS_TEST_MIGRATIONS_PATH does not point to a folder containing the reldens migrations.'
65
+ );
66
+ }
67
+ this.dataServer = await ReldensSchemaLoader.setup(this.driverName);
68
+ if(!this.dataServer){
69
+ return this.runner.fail(
70
+ 'reldens sample data server must connect for '+this.driverName,
71
+ 'The '+this.driverName+' data server could not be set up.'
72
+ );
73
+ }
74
+ for(let entityName of this.entityNames){
75
+ this.repos[entityName] = this.dataServer.getEntity(entityName);
76
+ }
77
+ try {
78
+ await this.testGeneratedRepositories();
79
+ await this.testItemsItemSameTableForeignKeys();
80
+ await this.testSkillsClassPathLevelsChain();
81
+ await this.testRoomsChangePointsNestedRoom();
82
+ await this.testForeignKeyScalarWithoutRelations();
83
+ } finally {
84
+ await ReldensSchemaLoader.teardown(this.dataServer);
85
+ }
86
+ return this.runner.getResults();
87
+ }
88
+
89
+ clearedRepo(entityName)
90
+ {
91
+ if(this.dataServer.orm && this.dataServer.orm.em){
92
+ this.dataServer.orm.em.clear();
93
+ }
94
+ return this.repos[entityName];
95
+ }
96
+
97
+ assertRelationRows(record, relationKey, expectedRows, label)
98
+ {
99
+ let related = record[relationKey];
100
+ ObservedValue.log(label+'.'+relationKey, related);
101
+ assert.ok(
102
+ Array.isArray(related),
103
+ label+'.'+relationKey+' is not an array, observed: '+ObservedValue.describe(related)
104
+ );
105
+ assert.strictEqual(
106
+ related.length,
107
+ expectedRows,
108
+ label+'.'+relationKey+' rows observed: '+related.length+' - expected: '+expectedRows
109
+ );
110
+ return related;
111
+ }
112
+
113
+ async testGeneratedRepositories()
114
+ {
115
+ this.runner.group('Reldens Schema Repositories');
116
+ await this.runner.test('should expose a repository for every asserted entity', async () => {
117
+ for(let entityName of this.entityNames){
118
+ assert.ok(this.repos[entityName], 'entity "'+entityName+'" missing from the reldens schema');
119
+ }
120
+ });
121
+ }
122
+
123
+ async testItemsItemSameTableForeignKeys()
124
+ {
125
+ this.runner.group('Items Item Two Foreign Keys To The Same Table');
126
+ for(let caseName of Object.keys(this.itemRelationCases)){
127
+ let testCase = this.itemRelationCases[caseName];
128
+ await this.runner.test('should return '+caseName, async () => {
129
+ let record = await this.clearedRepo('itemsItem').loadByIdWithRelations(
130
+ testCase.itemId,
131
+ [testCase.relationKey]
132
+ );
133
+ assert.ok(record, 'items_item '+testCase.itemId+' not loaded: '+ObservedValue.describe(record));
134
+ this.assertRelationRows(record, testCase.relationKey, testCase.expectedRows, caseName);
135
+ });
136
+ }
137
+ }
138
+
139
+ async testSkillsClassPathLevelsChain()
140
+ {
141
+ this.runner.group('Skills Class Path Levels Chain');
142
+ await this.runner.test('should load the levels set with every level of the journeyman path', async () => {
143
+ let record = await this.clearedRepo('skillsClassPath').loadByIdWithRelations(
144
+ this.journeymanClassPathId,
145
+ [this.skillsLevelsChain]
146
+ );
147
+ assert.ok(record, 'journeyman class path not loaded: '+ObservedValue.describe(record));
148
+ let levelsSet = record[this.levelsSetKey];
149
+ ObservedValue.log('journeyman.'+this.levelsSetKey, levelsSet);
150
+ assert.strictEqual(
151
+ 'object',
152
+ typeof levelsSet,
153
+ 'the levels set was not populated, observed: '+ObservedValue.describe(levelsSet)
154
+ );
155
+ assert.strictEqual(
156
+ Number(levelsSet.id),
157
+ this.journeymanLevelsSetId,
158
+ 'the levels set id observed: '+ObservedValue.describe(levelsSet.id)
159
+ );
160
+ this.assertRelationRows(levelsSet, this.levelsKey, this.journeymanLevelsRows, 'journeyman levels set');
161
+ });
162
+ await this.runner.test('should load the modifiers of every journeyman level', async () => {
163
+ let record = await this.clearedRepo('skillsClassPath').loadByIdWithRelations(
164
+ this.journeymanClassPathId,
165
+ [this.skillsLevelsChain]
166
+ );
167
+ assert.ok(record, 'journeyman class path not loaded: '+ObservedValue.describe(record));
168
+ let levels = this.assertRelationRows(
169
+ record[this.levelsSetKey],
170
+ this.levelsKey,
171
+ this.journeymanLevelsRows,
172
+ 'journeyman levels set'
173
+ );
174
+ for(let level of levels){
175
+ this.assertRelationRows(
176
+ level,
177
+ this.levelsModifiersKey,
178
+ this.journeymanModifiersByLevelId[level.id],
179
+ 'journeyman level '+level.id
180
+ );
181
+ }
182
+ });
183
+ }
184
+
185
+ async testRoomsChangePointsNestedRoom()
186
+ {
187
+ this.runner.group('Rooms Change Points Nested Room');
188
+ await this.runner.test('should load the change points of the bots forest room', async () => {
189
+ let record = await this.clearedRepo('rooms').loadByIdWithRelations(
190
+ this.botsForestRoomId,
191
+ [this.changePointsChain]
192
+ );
193
+ assert.ok(record, 'bots forest room not loaded: '+ObservedValue.describe(record));
194
+ this.assertRelationRows(record, this.changePointsKey, this.botsForestChangePointsRows, 'bots forest');
195
+ });
196
+ await this.runner.test('should load the change point next room as an entity', async () => {
197
+ let record = await this.clearedRepo('rooms').loadByIdWithRelations(
198
+ this.botsForestRoomId,
199
+ [this.changePointsChain]
200
+ );
201
+ assert.ok(record, 'bots forest room not loaded: '+ObservedValue.describe(record));
202
+ let changePoints = this.assertRelationRows(
203
+ record,
204
+ this.changePointsKey,
205
+ this.botsForestChangePointsRows,
206
+ 'bots forest'
207
+ );
208
+ let nextRoom = [...changePoints].shift()[this.nextRoomKey];
209
+ ObservedValue.log('bots forest change point.'+this.nextRoomKey, nextRoom);
210
+ assert.strictEqual(
211
+ 'object',
212
+ typeof nextRoom,
213
+ 'the next room was not populated, observed: '+ObservedValue.describe(nextRoom)
214
+ );
215
+ assert.strictEqual(
216
+ Number(nextRoom.id),
217
+ this.botsForestNextRoomId,
218
+ 'the next room id observed: '+ObservedValue.describe(nextRoom.id)
219
+ );
220
+ assert.strictEqual(
221
+ nextRoom.name,
222
+ this.botsForestNextRoomName,
223
+ 'the next room name observed: '+ObservedValue.describe(nextRoom.name)
224
+ );
225
+ });
226
+ }
227
+
228
+ async testForeignKeyScalarWithoutRelations()
229
+ {
230
+ this.runner.group('Foreign Key Scalar Without Relations');
231
+ await this.runner.test('should return the players state room id as a scalar', async () => {
232
+ let record = await this.clearedRepo('playersState').loadById(this.playersStateId);
233
+ assert.ok(record, 'players state row not loaded: '+ObservedValue.describe(record));
234
+ ObservedValue.log('players state room_id', record.room_id);
235
+ assert.notStrictEqual(
236
+ 'object',
237
+ typeof record.room_id,
238
+ 'the room_id was hydrated as an entity, observed: '+ObservedValue.describe(record.room_id)
239
+ );
240
+ assert.strictEqual(
241
+ Number(record.room_id),
242
+ this.playersStateRoomId,
243
+ 'the room_id observed: '+ObservedValue.describe(record.room_id)
244
+ );
245
+ assert.strictEqual(
246
+ Number(record.player_id),
247
+ this.playersStatePlayerId,
248
+ 'the player_id observed: '+ObservedValue.describe(record.player_id)
249
+ );
250
+ });
251
+ }
252
+
253
+ }
254
+
255
+ module.exports = ReldensSampleDataTest;