@geekmidas/testkit 0.0.12 → 0.0.13

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 (64) hide show
  1. package/README.md +1 -1
  2. package/dist/{Factory-Bm44VKa-.d.cts → Factory-D7P3bKKb.d.mts} +2 -2
  3. package/dist/{Factory-tjCDNgUK.d.mts → Factory-pNV7ZQ7-.d.cts} +2 -2
  4. package/dist/Factory.d.cts +2 -2
  5. package/dist/Factory.d.mts +2 -2
  6. package/dist/{KyselyFactory-C3Bc3p4L.mjs → KyselyFactory-BcYkC0t2.mjs} +1 -1
  7. package/dist/{KyselyFactory-BoPDDitt.d.cts → KyselyFactory-BrWADI77.d.mts} +3 -3
  8. package/dist/{KyselyFactory-CXtfmMfK.cjs → KyselyFactory-Cf0o2YxO.cjs} +1 -1
  9. package/dist/{KyselyFactory-D82j74t9.d.mts → KyselyFactory-DM2dnUXU.d.cts} +3 -3
  10. package/dist/KyselyFactory.cjs +1 -1
  11. package/dist/KyselyFactory.d.cts +3 -3
  12. package/dist/KyselyFactory.d.mts +3 -3
  13. package/dist/KyselyFactory.mjs +1 -1
  14. package/dist/{ObjectionFactory-qIICOph3.mjs → ObjectionFactory-8hebmnai.mjs} +20 -4
  15. package/dist/{ObjectionFactory-BWMTXsxH.d.cts → ObjectionFactory-B40NQWSe.d.mts} +2 -2
  16. package/dist/{ObjectionFactory-DxIxJagq.cjs → ObjectionFactory-CDriunkS.cjs} +20 -4
  17. package/dist/{ObjectionFactory-CEG5qUrm.d.mts → ObjectionFactory-D3l1VuyX.d.cts} +2 -2
  18. package/dist/ObjectionFactory.cjs +1 -1
  19. package/dist/ObjectionFactory.d.cts +3 -3
  20. package/dist/ObjectionFactory.d.mts +3 -3
  21. package/dist/ObjectionFactory.mjs +1 -1
  22. package/dist/__tests__/KyselyFactory.spec.cjs +2 -2
  23. package/dist/__tests__/KyselyFactory.spec.mjs +2 -2
  24. package/dist/__tests__/ObjectionFactory.spec.cjs +288 -450
  25. package/dist/__tests__/ObjectionFactory.spec.mjs +289 -451
  26. package/dist/__tests__/PostgresKyselyMigrator.spec.cjs +397 -0
  27. package/dist/__tests__/PostgresKyselyMigrator.spec.d.cts +1 -0
  28. package/dist/__tests__/PostgresKyselyMigrator.spec.d.mts +1 -0
  29. package/dist/__tests__/PostgresKyselyMigrator.spec.mjs +396 -0
  30. package/dist/__tests__/PostgresMigrator.spec.cjs +1 -1
  31. package/dist/__tests__/PostgresMigrator.spec.mjs +1 -1
  32. package/dist/__tests__/PostgresObjectionMigrator.spec.cjs +1 -1
  33. package/dist/__tests__/PostgresObjectionMigrator.spec.mjs +1 -1
  34. package/dist/__tests__/VitestObjectionTransactionIsolator.spec.cjs +3 -11
  35. package/dist/__tests__/VitestObjectionTransactionIsolator.spec.mjs +3 -11
  36. package/dist/__tests__/integration.spec.cjs +2 -2
  37. package/dist/__tests__/integration.spec.mjs +2 -2
  38. package/dist/{faker-km9UhOS6.d.cts → faker-BSH1EMtg.d.cts} +2 -2
  39. package/dist/{faker-ChuHaYMR.d.mts → faker-C-Iuk_R1.d.mts} +2 -2
  40. package/dist/faker.d.cts +1 -1
  41. package/dist/faker.d.mts +1 -1
  42. package/dist/{helpers-BEmjyUVE.mjs → helpers-B4TXg3Wp.mjs} +11 -36
  43. package/dist/{helpers-CNMBePuj.cjs → helpers-Bf0nXhbu.cjs} +10 -41
  44. package/dist/kysely.cjs +1 -1
  45. package/dist/kysely.d.cts +3 -3
  46. package/dist/kysely.d.mts +3 -3
  47. package/dist/kysely.mjs +1 -1
  48. package/dist/objection.cjs +1 -1
  49. package/dist/objection.d.cts +3 -3
  50. package/dist/objection.d.mts +3 -3
  51. package/dist/objection.mjs +1 -1
  52. package/package.json +2 -2
  53. package/src/Factory.ts +4 -1
  54. package/src/KyselyFactory.ts +6 -2
  55. package/src/ObjectionFactory.ts +31 -4
  56. package/src/__tests__/ObjectionFactory.spec.ts +423 -542
  57. package/src/__tests__/PostgresKyselyMigrator.spec.ts +690 -0
  58. package/src/__tests__/VitestObjectionTransactionIsolator.spec.ts +0 -8
  59. package/test/helpers.ts +13 -21
  60. package/dist/example.cjs +0 -22
  61. package/dist/example.d.cts +0 -26
  62. package/dist/example.d.mts +0 -26
  63. package/dist/example.mjs +0 -22
  64. package/src/example.ts +0 -45
@@ -1,22 +1,19 @@
1
1
  import type { Knex } from 'knex';
2
2
  import { Model } from 'objection';
3
- import { afterAll, beforeAll, describe, expect, it } from 'vitest';
4
- import { setupKnexTest } from '../../test/helpers';
3
+ import { describe, expect, test } from 'vitest';
4
+ import { createKnexDb, createTestTablesKnex } from '../../test/helpers';
5
5
  import { ObjectionFactory } from '../ObjectionFactory';
6
6
  import { faker } from '../faker';
7
+ import { wrapVitestObjectionTransaction } from '../objection';
7
8
 
8
- // Define real Objection models for testing
9
+ // Define simple Objection models for testing
9
10
  class User extends Model {
10
11
  static get tableName() {
11
12
  return 'users';
12
13
  }
13
14
 
14
- id!: number;
15
+ id!: string;
15
16
  name!: string;
16
- email!: string;
17
- role?: string;
18
- createdAt!: Date;
19
- updatedAt?: Date;
20
17
  }
21
18
 
22
19
  class Post extends Model {
@@ -24,13 +21,9 @@ class Post extends Model {
24
21
  return 'posts';
25
22
  }
26
23
 
27
- id!: number;
24
+ id!: string;
28
25
  title!: string;
29
- content!: string;
30
- userId!: number;
31
- published?: boolean;
32
- createdAt!: Date;
33
- updatedAt?: Date;
26
+ user_id!: string;
34
27
  }
35
28
 
36
29
  class Comment extends Model {
@@ -38,657 +31,545 @@ class Comment extends Model {
38
31
  return 'comments';
39
32
  }
40
33
 
41
- id!: number;
34
+ id!: string;
42
35
  content!: string;
43
- postId!: number;
44
- userId!: number;
45
- createdAt!: Date;
36
+ post_id!: string;
37
+ user_id!: string;
46
38
  }
47
39
 
48
- describe.skip('ObjectionFactory', () => {
49
- let factory: ObjectionFactory<any, any>;
50
- let db: Knex;
51
- let trx: Knex.Transaction;
52
- let cleanup: () => Promise<void>;
53
-
54
- beforeAll(async () => {
55
- const setup = await setupKnexTest();
56
- db = setup.db;
57
- trx = setup.trx;
58
- cleanup = setup.cleanup;
59
-
60
- // Bind models to the transaction
61
- User.knex(trx);
62
- Post.knex(trx);
63
- Comment.knex(trx);
64
- });
40
+ const it = wrapVitestObjectionTransaction(
41
+ test,
42
+ createKnexDb(),
43
+ createTestTablesKnex,
44
+ );
45
+ describe('ObjectionFactory', () => {
46
+ it('should create an ObjectionFactory instance', ({ trx }) => {
47
+ const builders = {};
48
+ const seeds = {};
65
49
 
66
- afterAll(async () => {
67
- await cleanup();
50
+ const factory = new ObjectionFactory(builders, seeds, trx);
51
+
52
+ expect(factory).toBeInstanceOf(ObjectionFactory);
68
53
  });
69
54
 
70
- describe('constructor', () => {
71
- it('should create an ObjectionFactory instance', () => {
72
- const builders = {};
73
- const seeds = {};
55
+ it('should call builder and insert the record', async ({ trx }) => {
56
+ const userBuilder = async (attrs: any, factory: any, db: Knex) => {
57
+ return User.fromJson({
58
+ name: attrs.name || 'Default Name',
59
+ });
60
+ };
74
61
 
75
- factory = new ObjectionFactory(builders, seeds, trx);
62
+ const builders = {
63
+ user: userBuilder,
64
+ };
76
65
 
77
- expect(factory).toBeInstanceOf(ObjectionFactory);
78
- });
79
- });
66
+ const factory = new ObjectionFactory(builders, {}, trx);
80
67
 
81
- describe('insert method', () => {
82
- it('should call builder and insert the record', async () => {
83
- const userBuilder = async (attrs: any, factory: any, db: Knex) => {
84
- return User.fromJson({
85
- name: attrs.name || 'Default Name',
86
- email: attrs.email || `user${Date.now()}@example.com`,
87
- role: attrs.role || 'user',
88
- createdAt: new Date(),
89
- updatedAt: new Date(),
90
- });
91
- };
68
+ const attrs = { name: 'John Doe', email: 'john@example.com' };
69
+ const result = await factory.insert('user', attrs);
92
70
 
93
- const builders = {
94
- user: userBuilder,
95
- };
71
+ expect(result).toBeInstanceOf(User);
72
+ expect(result.name).toBe('John Doe');
73
+ expect(result.id).toBeDefined();
74
+ });
96
75
 
97
- factory = new ObjectionFactory(builders, {}, trx);
76
+ it('should use empty object as default attributes', async ({ trx }) => {
77
+ const userBuilder = async (attrs: any, factory: any, db: Knex) => {
78
+ return User.fromJson({
79
+ name: 'Default Name',
80
+ });
81
+ };
98
82
 
99
- const attrs = { name: 'John Doe', email: 'john@example.com' };
100
- const result = await factory.insert('user', attrs);
83
+ const builders = {
84
+ user: userBuilder,
85
+ };
101
86
 
102
- expect(result).toBeInstanceOf(User);
103
- expect(result.name).toBe('John Doe');
104
- expect(result.email).toBe('john@example.com');
105
- expect(result.id).toBeDefined();
106
- });
87
+ const factory = new ObjectionFactory(builders, {}, trx);
107
88
 
108
- it('should use empty object as default attributes', async () => {
109
- const userBuilder = async (attrs: any, factory: any, db: Knex) => {
110
- return User.fromJson({
111
- name: 'Default Name',
112
- email: `user${Date.now()}@example.com`,
113
- role: 'user',
114
- createdAt: new Date(),
115
- updatedAt: new Date(),
116
- });
117
- };
89
+ const result = await factory.insert('user');
90
+
91
+ expect(result).toBeInstanceOf(User);
92
+ expect(result.name).toBe('Default Name');
93
+ expect(result.id).toBeDefined();
94
+ });
118
95
 
119
- const builders = {
120
- user: userBuilder,
121
- };
96
+ it('should throw error for non-existent factory', async ({ trx }) => {
97
+ const factory = new ObjectionFactory({}, {}, trx);
98
+ // @ts-ignore
99
+ await expect(factory.insert('nonExistent')).rejects.toThrow(
100
+ 'Factory "nonExistent" does not exist',
101
+ );
102
+ });
122
103
 
123
- factory = new ObjectionFactory(builders, {}, trx);
104
+ it('should handle builder that returns a promise', async ({ trx }) => {
105
+ const userBuilder = async (attrs: any, factory: any, db: Knex) => {
106
+ // Simulate async operation
107
+ await new Promise((resolve) => setTimeout(resolve, 10));
108
+ return User.fromJson({
109
+ name: attrs.name || 'Default Name',
110
+ });
111
+ };
124
112
 
125
- const result = await factory.insert('user');
113
+ const builders = {
114
+ user: userBuilder,
115
+ };
126
116
 
127
- expect(result).toBeInstanceOf(User);
128
- expect(result.name).toBe('Default Name');
129
- expect(result.id).toBeDefined();
130
- });
117
+ const factory = new ObjectionFactory(builders, {}, trx);
131
118
 
132
- it('should throw error for non-existent factory', async () => {
133
- factory = new ObjectionFactory({}, {}, trx);
119
+ const result = await factory.insert('user', { name: 'Jane' });
134
120
 
135
- await expect(factory.insert('nonExistent')).rejects.toThrow(
136
- 'Factory "nonExistent" does not exist',
137
- );
138
- });
121
+ expect(result).toBeInstanceOf(User);
122
+ expect(result.name).toBe('Jane');
123
+ });
139
124
 
140
- it('should handle builder that returns a promise', async () => {
141
- const userBuilder = async (attrs: any, factory: any, db: Knex) => {
142
- // Simulate async operation
143
- await new Promise((resolve) => setTimeout(resolve, 10));
144
- return User.fromJson({
145
- name: attrs.name || 'Default Name',
146
- email: `async${Date.now()}@example.com`,
147
- role: 'user',
148
- createdAt: new Date(),
149
- updatedAt: new Date(),
150
- });
151
- };
125
+ it('should insert multiple records with same attributes', async ({ trx }) => {
126
+ const userBuilder = async (attrs: any, factory: any, db: Knex) => {
127
+ return User.fromJson({
128
+ name: attrs.name || 'Default Name',
129
+ });
130
+ };
152
131
 
153
- const builders = {
154
- user: userBuilder,
155
- };
132
+ const builders = {
133
+ user: userBuilder,
134
+ };
156
135
 
157
- factory = new ObjectionFactory(builders, {}, trx);
136
+ const factory = new ObjectionFactory(builders, {}, trx);
158
137
 
159
- const result = await factory.insert('user', { name: 'Jane' });
138
+ const attrs = { name: 'User' };
139
+ const results = await factory.insertMany(3, 'user', attrs);
160
140
 
141
+ expect(results).toHaveLength(3);
142
+ results.forEach((result) => {
161
143
  expect(result).toBeInstanceOf(User);
162
- expect(result.name).toBe('Jane');
144
+ expect(result.name).toBe('User');
145
+ expect(result.id).toBeDefined();
163
146
  });
164
147
  });
165
148
 
166
- describe('insertMany method', () => {
167
- it('should insert multiple records with same attributes', async () => {
168
- const userBuilder = async (attrs: any, factory: any, db: Knex) => {
169
- return User.fromJson({
170
- name: attrs.name || 'Default Name',
171
- email: `user${Date.now()}-${Math.random()}@example.com`,
172
- role: 'user',
173
- createdAt: new Date(),
174
- updatedAt: new Date(),
175
- });
176
- };
149
+ it('should insert multiple records with dynamic attributes', async ({
150
+ trx,
151
+ }) => {
152
+ const userBuilder = async (attrs: any, factory: any, db: Knex) => {
153
+ return User.fromJson({
154
+ name: attrs.name || 'Default Name',
155
+ });
156
+ };
177
157
 
178
- const builders = {
179
- user: userBuilder,
180
- };
158
+ const builders = {
159
+ user: userBuilder,
160
+ };
181
161
 
182
- factory = new ObjectionFactory(builders, {}, trx);
162
+ const factory = new ObjectionFactory(builders, {}, trx);
183
163
 
184
- const attrs = { name: 'User' };
185
- const results = await factory.insertMany(3, 'user', attrs);
164
+ const attrsFn = (idx: number) => ({ name: `User ${idx}` });
165
+ const results = await factory.insertMany(2, 'user', attrsFn);
186
166
 
187
- expect(results).toHaveLength(3);
188
- results.forEach((result) => {
189
- expect(result).toBeInstanceOf(User);
190
- expect(result.name).toBe('User');
191
- expect(result.id).toBeDefined();
192
- });
167
+ expect(results).toHaveLength(2);
168
+ expect(results[0].name).toBe('User 0');
169
+ expect(results[1].name).toBe('User 1');
170
+ results.forEach((result) => {
171
+ expect(result).toBeInstanceOf(User);
172
+ expect(result.id).toBeDefined();
193
173
  });
174
+ });
194
175
 
195
- it('should insert multiple records with dynamic attributes', async () => {
196
- const userBuilder = async (attrs: any, factory: any, db: Knex) => {
197
- return User.fromJson({
198
- name: attrs.name || 'Default Name',
199
- email: `user${Date.now()}-${Math.random()}@example.com`,
200
- role: 'user',
201
- createdAt: new Date(),
202
- updatedAt: new Date(),
203
- });
204
- };
176
+ it('should use empty object as default attributes for insertMany', async ({
177
+ trx,
178
+ }) => {
179
+ const userBuilder = async (attrs: any, factory: any, db: Knex) => {
180
+ return User.fromJson({
181
+ name: 'Default Name',
182
+ });
183
+ };
205
184
 
206
- const builders = {
207
- user: userBuilder,
208
- };
185
+ const builders = {
186
+ user: userBuilder,
187
+ };
209
188
 
210
- factory = new ObjectionFactory(builders, {}, trx);
189
+ const factory = new ObjectionFactory(builders, {}, trx);
211
190
 
212
- const attrsFn = (idx: number) => ({ name: `User ${idx}` });
213
- const results = await factory.insertMany(2, 'user', attrsFn);
191
+ const results = await factory.insertMany(2, 'user');
214
192
 
215
- expect(results).toHaveLength(2);
216
- expect(results[0].name).toBe('User 0');
217
- expect(results[1].name).toBe('User 1');
218
- results.forEach((result) => {
219
- expect(result).toBeInstanceOf(User);
220
- expect(result.id).toBeDefined();
221
- });
193
+ expect(results).toHaveLength(2);
194
+ results.forEach((result) => {
195
+ expect(result).toBeInstanceOf(User);
196
+ expect(result.name).toBe('Default Name');
197
+ expect(result.id).toBeDefined();
222
198
  });
199
+ });
223
200
 
224
- it('should use empty object as default attributes for insertMany', async () => {
225
- const userBuilder = async (attrs: any, factory: any, db: Knex) => {
226
- return User.fromJson({
227
- name: 'Default Name',
228
- email: `user${Date.now()}-${Math.random()}@example.com`,
229
- role: 'user',
230
- createdAt: new Date(),
231
- updatedAt: new Date(),
232
- });
233
- };
234
-
235
- const builders = {
236
- user: userBuilder,
237
- };
201
+ it('should throw error for non-existent builder in insertMany', async ({
202
+ trx,
203
+ }) => {
204
+ const factory = new ObjectionFactory({}, {}, trx);
205
+ // @ts-ignore
206
+ await expect(factory.insertMany(2, 'nonExistent')).rejects.toThrow(
207
+ 'Builder "nonExistent" is not registered',
208
+ );
209
+ });
238
210
 
239
- factory = new ObjectionFactory(builders, {}, trx);
211
+ it('should execute seed function', async ({ trx }) => {
212
+ const userBuilder = async (attrs: any, factory: any, db: Knex) => {
213
+ return User.fromJson({
214
+ name: attrs.name || 'Default Name',
215
+ });
216
+ };
240
217
 
241
- const results = await factory.insertMany(2, 'user');
218
+ const builders = { user: userBuilder };
242
219
 
243
- expect(results).toHaveLength(2);
244
- results.forEach((result) => {
245
- expect(result).toBeInstanceOf(User);
246
- expect(result.name).toBe('Default Name');
247
- expect(result.id).toBeDefined();
220
+ const createAdminSeed = async (attrs: any, factory: any, db: Knex) => {
221
+ return await factory.insert('user', {
222
+ name: attrs.name || 'Admin User',
248
223
  });
249
- });
224
+ };
250
225
 
251
- it('should throw error for non-existent builder in insertMany', async () => {
252
- factory = new ObjectionFactory({}, {}, trx);
226
+ const seeds = {
227
+ createAdmin: createAdminSeed,
228
+ };
253
229
 
254
- await expect(factory.insertMany(2, 'nonExistent')).rejects.toThrow(
255
- 'Builder "nonExistent" is not registered',
256
- );
257
- });
258
- });
230
+ const factory = new ObjectionFactory(builders, seeds, trx);
259
231
 
260
- describe('seed method', () => {
261
- it('should execute seed function', async () => {
262
- const userBuilder = async (attrs: any, factory: any, db: Knex) => {
263
- return User.fromJson({
264
- name: attrs.name || 'Default Name',
265
- email: attrs.email || `admin${Date.now()}@example.com`,
266
- role: 'admin',
267
- createdAt: new Date(),
268
- updatedAt: new Date(),
269
- });
270
- };
232
+ const attrs = { name: 'Super Admin' };
233
+ const result = await factory.seed('createAdmin', attrs);
271
234
 
272
- const builders = { user: userBuilder };
235
+ expect(result).toBeInstanceOf(User);
236
+ expect(result.name).toBe('Super Admin');
237
+ expect(result.id).toBeDefined();
238
+ });
273
239
 
274
- const createAdminSeed = async (attrs: any, factory: any, db: Knex) => {
275
- return await factory.insert('user', {
276
- name: attrs.name || 'Admin User',
277
- email: 'admin@example.com',
278
- role: 'admin',
279
- });
280
- };
240
+ it('should use empty object as default attributes for seed', async ({
241
+ trx,
242
+ }) => {
243
+ const userBuilder = async (attrs: any, factory: any, db: Knex) => {
244
+ return User.fromJson({
245
+ name: 'Default Admin',
246
+ });
247
+ };
281
248
 
282
- const seeds = {
283
- createAdmin: createAdminSeed,
284
- };
249
+ const builders = { user: userBuilder };
285
250
 
286
- factory = new ObjectionFactory(builders, seeds, trx);
251
+ const createAdminSeed = async (attrs: any, factory: any, db: Knex) => {
252
+ return await factory.insert('user', {
253
+ name: 'Default Admin',
254
+ role: 'admin',
255
+ });
256
+ };
287
257
 
288
- const attrs = { name: 'Super Admin' };
289
- const result = await factory.seed('createAdmin', attrs);
258
+ const seeds = {
259
+ createAdmin: createAdminSeed,
260
+ };
290
261
 
291
- expect(result).toBeInstanceOf(User);
292
- expect(result.name).toBe('Super Admin');
293
- expect(result.role).toBe('admin');
294
- expect(result.id).toBeDefined();
295
- });
262
+ const factory = new ObjectionFactory(builders, seeds, trx);
296
263
 
297
- it('should use empty object as default attributes for seed', async () => {
298
- const userBuilder = async (attrs: any, factory: any, db: Knex) => {
299
- return User.fromJson({
300
- name: 'Default Admin',
301
- email: `admin${Date.now()}@example.com`,
302
- role: 'admin',
303
- createdAt: new Date(),
304
- updatedAt: new Date(),
305
- });
306
- };
264
+ const result = await factory.seed('createAdmin');
307
265
 
308
- const builders = { user: userBuilder };
266
+ expect(result).toBeInstanceOf(User);
267
+ expect(result.name).toBe('Default Admin');
268
+ });
309
269
 
310
- const createAdminSeed = async (attrs: any, factory: any, db: Knex) => {
311
- return await factory.insert('user', {
312
- name: 'Default Admin',
313
- role: 'admin',
314
- });
315
- };
270
+ it('should throw error for non-existent seed', ({ trx }) => {
271
+ const factory = new ObjectionFactory({}, {}, trx);
272
+ // @ts-ignore
273
+ expect(() => factory.seed('nonExistent')).toThrow(
274
+ 'Seed "nonExistent" is not registered',
275
+ );
276
+ });
316
277
 
317
- const seeds = {
318
- createAdmin: createAdminSeed,
319
- };
278
+ it('should pass factory and db to seed function', async ({ trx }) => {
279
+ const userBuilder = async (attrs: any, factory: any, db: Knex) => {
280
+ return User.fromJson({
281
+ name: attrs.name || 'Test User',
282
+ });
283
+ };
320
284
 
321
- factory = new ObjectionFactory(builders, seeds, trx);
285
+ const builders = { user: userBuilder };
322
286
 
323
- const result = await factory.seed('createAdmin');
287
+ const complexSeed = async (
288
+ attrs: any,
289
+ passedFactory: any,
290
+ passedDb: Knex,
291
+ ) => {
292
+ // Verify that factory and db are passed correctly
293
+ expect(passedFactory).toBe(factory);
294
+ expect(passedDb).toBe(trx);
324
295
 
325
- expect(result).toBeInstanceOf(User);
326
- expect(result.name).toBe('Default Admin');
327
- expect(result.role).toBe('admin');
328
- });
296
+ return await passedFactory.insert('user', {
297
+ name: `Complex ${attrs.data}`,
298
+ });
299
+ };
329
300
 
330
- it('should throw error for non-existent seed', () => {
331
- factory = new ObjectionFactory({}, {}, trx);
301
+ const seeds = {
302
+ complexSeed,
303
+ };
332
304
 
333
- expect(() => factory.seed('nonExistent')).toThrow(
334
- 'Seed "nonExistent" is not registered',
335
- );
336
- });
305
+ const factory = new ObjectionFactory(builders, seeds, trx);
337
306
 
338
- it('should pass factory and db to seed function', async () => {
339
- const userBuilder = async (attrs: any, factory: any, db: Knex) => {
340
- return User.fromJson({
341
- name: attrs.name || 'Test User',
342
- email: `test${Date.now()}@example.com`,
343
- role: 'user',
344
- createdAt: new Date(),
345
- updatedAt: new Date(),
346
- });
347
- };
307
+ const result = await factory.seed('complexSeed', { data: 'test' });
348
308
 
349
- const builders = { user: userBuilder };
309
+ expect(result).toBeInstanceOf(User);
310
+ expect(result.name).toBe('Complex test');
311
+ });
350
312
 
351
- const complexSeed = async (
352
- attrs: any,
353
- passedFactory: any,
354
- passedDb: Knex,
355
- ) => {
356
- // Verify that factory and db are passed correctly
357
- expect(passedFactory).toBe(factory);
358
- expect(passedDb).toBe(trx);
313
+ it('should return the seed function unchanged', () => {
314
+ const seedFn = async (attrs: any, factory: any, db: any) => {
315
+ return { id: 1, name: 'test' };
316
+ };
359
317
 
360
- return await passedFactory.insert('user', {
361
- name: `Complex ${attrs.data}`,
362
- });
363
- };
318
+ const result = ObjectionFactory.createSeed(seedFn);
364
319
 
365
- const seeds = {
366
- complexSeed,
367
- };
320
+ expect(result).toBe(seedFn);
321
+ });
368
322
 
369
- factory = new ObjectionFactory(builders, seeds, trx);
323
+ it('should create a builder function with auto-insert', async ({ trx }) => {
324
+ const userBuilder = ObjectionFactory.createBuilder(
325
+ User,
326
+ (attrs, factory, db, faker) => ({
327
+ name: faker.person.fullName(),
328
+ ...attrs,
329
+ }),
330
+ );
370
331
 
371
- const result = await factory.seed('complexSeed', { data: 'test' });
332
+ const builders = { user: userBuilder };
333
+ const factory = new ObjectionFactory(builders, {}, trx);
372
334
 
373
- expect(result).toBeInstanceOf(User);
374
- expect(result.name).toBe('Complex test');
375
- });
335
+ const result = await factory.insert('user', { name: 'Test User' });
336
+
337
+ expect(result).toBeInstanceOf(User);
338
+ expect(result.name).toBe('Test User');
339
+ expect(result.id).toBeDefined();
376
340
  });
377
341
 
378
- describe('createSeed static method', () => {
379
- it('should return the seed function unchanged', () => {
380
- const seedFn = async (attrs: any, factory: any, db: any) => {
381
- return { id: 1, name: 'test' };
382
- };
342
+ it('should create a builder function without auto-insert', async ({
343
+ trx,
344
+ }) => {
345
+ const userBuilder = ObjectionFactory.createBuilder(
346
+ User,
347
+ (attrs) => ({
348
+ name: 'No Insert User',
349
+ ...attrs,
350
+ }),
351
+ false, // Don't auto-insert
352
+ );
353
+
354
+ const builders = { user: userBuilder };
355
+ const factory = new ObjectionFactory(builders, {}, trx);
356
+
357
+ const result = await factory.insert('user');
358
+
359
+ // The factory's insert method should handle the insertion
360
+ expect(result).toBeInstanceOf(User);
361
+ expect(result.name).toBe('No Insert User');
362
+ expect(result.id).toBeDefined();
363
+ });
383
364
 
384
- const result = ObjectionFactory.createSeed(seedFn);
365
+ it('should pass all parameters to the item function', async ({ trx }) => {
366
+ let capturedFactory: any;
367
+ let capturedDb: any;
368
+ let capturedFaker: any;
385
369
 
386
- expect(result).toBe(seedFn);
387
- });
388
- });
370
+ const userBuilder = ObjectionFactory.createBuilder(
371
+ User,
372
+ (attrs, factory, db, fakerInstance) => {
373
+ capturedFactory = factory;
374
+ capturedDb = db;
375
+ capturedFaker = fakerInstance;
389
376
 
390
- describe('createBuilder static method', () => {
391
- it('should create a builder function with auto-insert', async () => {
392
- const userBuilder = ObjectionFactory.createBuilder(
393
- User,
394
- (attrs, factory, db, faker) => ({
395
- name: faker.person.fullName(),
396
- email: faker.internet.email(),
397
- role: 'user',
398
- createdAt: new Date(),
399
- updatedAt: new Date(),
377
+ return {
378
+ name: 'Test User',
400
379
  ...attrs,
401
- }),
402
- );
380
+ };
381
+ },
382
+ );
403
383
 
404
- const builders = { user: userBuilder };
405
- factory = new ObjectionFactory(builders, {}, trx);
384
+ const builders = { user: userBuilder };
385
+ const factory = new ObjectionFactory(builders, {}, trx);
406
386
 
407
- const result = await factory.insert('user', { name: 'Test User' });
387
+ await factory.insert('user');
408
388
 
409
- expect(result).toBeInstanceOf(User);
410
- expect(result.name).toBe('Test User');
411
- expect(result.email).toMatch(/@/);
412
- expect(result.id).toBeDefined();
413
- });
389
+ expect(capturedFactory).toBe(factory);
390
+ expect(capturedDb).toBe(trx);
391
+ expect(capturedFaker).toBe(faker);
392
+ });
393
+
394
+ it('should handle async item functions', async ({ trx }) => {
395
+ const userBuilder = ObjectionFactory.createBuilder(
396
+ User,
397
+ async (attrs, factory, db, faker) => {
398
+ // Simulate async operation
399
+ await new Promise((resolve) => setTimeout(resolve, 10));
414
400
 
415
- it('should create a builder function without auto-insert', async () => {
416
- const userBuilder = ObjectionFactory.createBuilder(
417
- User,
418
- (attrs) => ({
419
- name: 'No Insert User',
420
- email: 'noinsert@example.com',
421
- role: 'user',
422
- createdAt: new Date(),
423
- updatedAt: new Date(),
401
+ return {
402
+ name: 'Async User',
424
403
  ...attrs,
425
- }),
426
- false, // Don't auto-insert
427
- );
404
+ };
405
+ },
406
+ );
428
407
 
429
- const builders = { user: userBuilder };
430
- factory = new ObjectionFactory(builders, {}, trx);
408
+ const builders = { user: userBuilder };
409
+ const factory = new ObjectionFactory(builders, {}, trx);
431
410
 
432
- const result = await factory.insert('user');
411
+ const result = await factory.insert('user');
433
412
 
434
- // The factory's insert method should handle the insertion
435
- expect(result).toBeInstanceOf(User);
436
- expect(result.name).toBe('No Insert User');
437
- expect(result.id).toBeDefined();
438
- });
413
+ expect(result).toBeInstanceOf(User);
414
+ expect(result.name).toBe('Async User');
415
+ expect(result.id).toBeDefined();
416
+ });
439
417
 
440
- it('should pass all parameters to the item function', async () => {
441
- let capturedFactory: any;
442
- let capturedDb: any;
443
- let capturedFaker: any;
444
-
445
- const userBuilder = ObjectionFactory.createBuilder(
446
- User,
447
- (attrs, factory, db, fakerInstance) => {
448
- capturedFactory = factory;
449
- capturedDb = db;
450
- capturedFaker = fakerInstance;
451
-
452
- return {
453
- name: 'Test User',
454
- email: 'test@example.com',
455
- role: 'user',
456
- createdAt: new Date(),
457
- updatedAt: new Date(),
458
- ...attrs,
459
- };
460
- },
461
- );
462
-
463
- const builders = { user: userBuilder };
464
- factory = new ObjectionFactory(builders, {}, trx);
465
-
466
- await factory.insert('user');
467
-
468
- expect(capturedFactory).toBe(factory);
469
- expect(capturedDb).toBe(trx);
470
- expect(capturedFaker).toBe(faker);
471
- });
418
+ it('should work without item function', async ({ trx }) => {
419
+ const userBuilder = ObjectionFactory.createBuilder(User);
472
420
 
473
- it('should handle async item functions', async () => {
474
- const userBuilder = ObjectionFactory.createBuilder(
475
- User,
476
- async (attrs, factory, db, faker) => {
477
- // Simulate async operation
478
- await new Promise((resolve) => setTimeout(resolve, 10));
479
-
480
- return {
481
- name: 'Async User',
482
- email: faker.internet.email(),
483
- role: 'user',
484
- createdAt: new Date(),
485
- updatedAt: new Date(),
486
- ...attrs,
487
- };
488
- },
489
- );
490
-
491
- const builders = { user: userBuilder };
492
- factory = new ObjectionFactory(builders, {}, trx);
493
-
494
- const result = await factory.insert('user');
421
+ const builders = { user: userBuilder };
422
+ const factory = new ObjectionFactory(builders, {}, trx);
495
423
 
496
- expect(result).toBeInstanceOf(User);
497
- expect(result.name).toBe('Async User');
498
- expect(result.id).toBeDefined();
499
- });
424
+ const attrs = {
425
+ name: 'Manual User',
426
+ };
500
427
 
501
- it('should work without item function', async () => {
502
- const userBuilder = ObjectionFactory.createBuilder(User);
428
+ const result = await factory.insert('user', attrs);
503
429
 
504
- const builders = { user: userBuilder };
505
- factory = new ObjectionFactory(builders, {}, trx);
430
+ expect(result).toBeInstanceOf(User);
431
+ expect(result.name).toBe('Manual User');
432
+ expect(result.id).toBeDefined();
433
+ });
506
434
 
507
- const attrs = {
508
- name: 'Manual User',
509
- email: 'manual@example.com',
510
- role: 'user',
511
- createdAt: new Date(),
512
- updatedAt: new Date(),
513
- };
435
+ it('should allow overriding default values', async ({ trx }) => {
436
+ const userBuilder = ObjectionFactory.createBuilder(
437
+ User,
438
+ (attrs, factory, db, faker) => ({
439
+ name: 'Default Name',
440
+ ...attrs,
441
+ }),
442
+ );
514
443
 
515
- const result = await factory.insert('user', attrs);
444
+ const builders = { user: userBuilder };
445
+ const factory = new ObjectionFactory(builders, {}, trx);
516
446
 
517
- expect(result).toBeInstanceOf(User);
518
- expect(result.name).toBe('Manual User');
519
- expect(result.email).toBe('manual@example.com');
520
- expect(result.id).toBeDefined();
447
+ const result = await factory.insert('user', {
448
+ name: 'Override Name',
521
449
  });
522
450
 
523
- it('should allow overriding default values', async () => {
524
- const userBuilder = ObjectionFactory.createBuilder(
525
- User,
526
- (attrs, factory, db, faker) => ({
527
- name: 'Default Name',
528
- email: 'default@example.com',
529
- role: 'user',
530
- createdAt: new Date(),
531
- updatedAt: new Date(),
532
- ...attrs,
533
- }),
534
- );
535
-
536
- const builders = { user: userBuilder };
537
- factory = new ObjectionFactory(builders, {}, trx);
538
-
539
- const result = await factory.insert('user', {
540
- name: 'Override Name',
541
- email: 'override@example.com',
542
- });
543
-
544
- expect(result).toBeInstanceOf(User);
545
- expect(result.name).toBe('Override Name');
546
- expect(result.email).toBe('override@example.com');
547
- expect(result.role).toBe('user'); // Default not overridden
548
- });
451
+ expect(result).toBeInstanceOf(User);
452
+ expect(result.name).toBe('Override Name');
549
453
  });
550
454
 
551
- describe('error handling', () => {
552
- it('should handle builder errors gracefully', async () => {
553
- const userBuilder = async (attrs: any, factory: any, db: Knex) => {
554
- throw new Error('Builder failed');
555
- };
455
+ it('should handle builder errors gracefully', async ({ trx }) => {
456
+ const userBuilder = async (attrs: any, factory: any, db: Knex) => {
457
+ throw new Error('Builder failed');
458
+ };
556
459
 
557
- const builders = {
558
- user: userBuilder,
559
- };
460
+ const builders = {
461
+ user: userBuilder,
462
+ };
560
463
 
561
- factory = new ObjectionFactory(builders, {}, trx);
464
+ const factory = new ObjectionFactory(builders, {}, trx);
562
465
 
563
- await expect(factory.insert('user')).rejects.toThrow('Builder failed');
564
- });
466
+ await expect(factory.insert('user')).rejects.toThrow('Builder failed');
467
+ });
565
468
 
566
- it('should handle invalid model data gracefully', async () => {
567
- const userBuilder = async (attrs: any, factory: any, db: Knex) => {
568
- // Return invalid model data that will fail validation
569
- return User.fromJson({
570
- // Missing required fields
571
- invalidField: 'invalid',
572
- } as any);
573
- };
469
+ it('should handle invalid model data gracefully', async ({ trx }) => {
470
+ const userBuilder = async (attrs: any, factory: any, db: Knex) => {
471
+ // Return invalid model data that will fail validation
472
+ return User.fromJson({
473
+ // Missing required fields
474
+ invalidField: 'invalid',
475
+ } as any);
476
+ };
574
477
 
575
- const builders = {
576
- user: userBuilder,
577
- };
478
+ const builders = {
479
+ user: userBuilder,
480
+ };
578
481
 
579
- factory = new ObjectionFactory(builders, {}, trx);
482
+ const factory = new ObjectionFactory(builders, {}, trx);
580
483
 
581
- await expect(factory.insert('user')).rejects.toThrow();
582
- });
484
+ await expect(factory.insert('user')).rejects.toThrow();
485
+ });
583
486
 
584
- it('should handle seed function errors gracefully', async () => {
585
- const failingSeed = async (attrs: any, factory: any, db: Knex) => {
586
- throw new Error('Seed failed');
587
- };
487
+ it('should handle seed function errors gracefully', async ({ trx }) => {
488
+ const failingSeed = async (attrs: any, factory: any, db: Knex) => {
489
+ throw new Error('Seed failed');
490
+ };
588
491
 
589
- const seeds = {
590
- failingSeed,
591
- };
492
+ const seeds = {
493
+ failingSeed,
494
+ };
592
495
 
593
- factory = new ObjectionFactory({}, seeds, trx);
496
+ const factory = new ObjectionFactory({}, seeds, trx);
594
497
 
595
- await expect(factory.seed('failingSeed')).rejects.toThrow('Seed failed');
596
- });
498
+ await expect(factory.seed('failingSeed')).rejects.toThrow('Seed failed');
597
499
  });
598
500
 
599
- describe('type safety and integration', () => {
600
- it('should work with typed builders and seeds', async () => {
601
- interface UserInterface {
602
- id: number;
603
- name: string;
604
- email: string;
605
- }
501
+ it('should work with typed builders and seeds', async ({ trx }) => {
502
+ interface UserInterface {
503
+ id: string;
504
+ name: string;
505
+ }
606
506
 
607
- type UserAttrs = Partial<Pick<UserInterface, 'name' | 'email'>>;
507
+ type UserAttrs = Partial<Pick<UserInterface, 'name'>>;
608
508
 
609
- const userBuilder = async (attrs: UserAttrs, factory: any, db: Knex) => {
610
- return User.fromJson({
611
- name: attrs.name || 'Default User',
612
- email: attrs.email || `user${Date.now()}@example.com`,
613
- role: 'user',
614
- createdAt: new Date(),
615
- updatedAt: new Date(),
616
- });
617
- };
618
-
619
- const adminSeed = async (
620
- attrs: { isSuper?: boolean },
621
- factory: any,
622
- db: Knex,
623
- ) => {
624
- return factory.insert('user', {
625
- name: 'Admin',
626
- email: 'admin@example.com',
627
- role: 'admin',
628
- });
629
- };
509
+ const userBuilder = async (attrs: UserAttrs, factory: any, db: Knex) => {
510
+ return User.fromJson({
511
+ name: attrs.name || 'Default User',
512
+ });
513
+ };
514
+
515
+ const adminSeed = async (
516
+ attrs: { isSuper?: boolean },
517
+ factory: any,
518
+ db: Knex,
519
+ ) => {
520
+ return factory.insert('user', {
521
+ name: 'Admin',
522
+ });
523
+ };
630
524
 
631
- const builders = { user: userBuilder };
632
- const seeds = { admin: adminSeed };
525
+ const builders = { user: userBuilder };
526
+ const seeds = { admin: adminSeed };
633
527
 
634
- // This should compile without type errors
635
- factory = new ObjectionFactory(builders, seeds, trx);
528
+ // This should compile without type errors
529
+ const factory = new ObjectionFactory(builders, seeds, trx);
636
530
 
637
- expect(factory).toBeInstanceOf(ObjectionFactory);
531
+ expect(factory).toBeInstanceOf(ObjectionFactory);
638
532
 
639
- // Test actual functionality
640
- const admin = await factory.seed('admin', { isSuper: true });
641
- expect(admin).toBeInstanceOf(User);
642
- expect(admin.name).toBe('Admin');
643
- });
533
+ // Test actual functionality
534
+ const admin = await factory.seed('admin', { isSuper: true });
535
+ expect(admin).toBeInstanceOf(User);
536
+ expect(admin.name).toBe('Admin');
537
+ });
644
538
 
645
- it('should handle complex builder scenarios', async () => {
646
- const userBuilder = async (attrs: any, factory: any, db: Knex) => {
647
- return User.fromJson({
648
- name: attrs.name || 'Default User',
649
- email: attrs.email || `user${Date.now()}@example.com`,
650
- role: 'user',
651
- createdAt: new Date(),
652
- updatedAt: new Date(),
653
- });
654
- };
655
-
656
- const postBuilder = async (attrs: any, factory: any, db: Knex) => {
657
- // If no userId provided, create a user
658
- if (!attrs.userId) {
659
- const user = await factory.insert('user');
660
- return Post.fromJson({
661
- title: attrs.title || 'Default Post',
662
- content: attrs.content || 'Default content',
663
- userId: user.id,
664
- published: attrs.published || false,
665
- createdAt: new Date(),
666
- updatedAt: new Date(),
667
- });
668
- }
539
+ it('should handle complex builder scenarios', async ({ trx }) => {
540
+ const userBuilder = async (attrs: any, factory: any, db: Knex) => {
541
+ return User.fromJson({
542
+ name: attrs.name || 'Default User',
543
+ });
544
+ };
545
+
546
+ const postBuilder = async (attrs: any, factory: any, db: Knex) => {
547
+ // If no user_id provided, create a user
548
+ if (!attrs.user_id) {
549
+ const user = await factory.insert('user');
669
550
  return Post.fromJson({
670
551
  title: attrs.title || 'Default Post',
671
- content: attrs.content || 'Default content',
672
- userId: attrs.userId,
673
- published: attrs.published || false,
674
- createdAt: new Date(),
675
- updatedAt: new Date(),
552
+ user_id: user.id,
676
553
  });
677
- };
554
+ }
555
+ return Post.fromJson({
556
+ title: attrs.title || 'Default Post',
557
+ user_id: attrs.user_id,
558
+ });
559
+ };
678
560
 
679
- const builders = {
680
- user: userBuilder,
681
- post: postBuilder,
682
- };
561
+ const builders = {
562
+ user: userBuilder,
563
+ post: postBuilder,
564
+ };
683
565
 
684
- factory = new ObjectionFactory(builders, {}, trx);
566
+ const factory = new ObjectionFactory(builders, {}, trx);
685
567
 
686
- const post = await factory.insert('post', { title: 'Test Post' });
568
+ const post = await factory.insert('post', { title: 'Test Post' });
687
569
 
688
- expect(post).toBeInstanceOf(Post);
689
- expect(post.title).toBe('Test Post');
690
- expect(post.userId).toBeDefined();
691
- expect(typeof post.userId).toBe('number');
692
- });
570
+ expect(post).toBeInstanceOf(Post);
571
+ expect(post.title).toBe('Test Post');
572
+ expect(post.user_id).toBeDefined();
573
+ expect(typeof post.user_id).toBe('string'); // PostgreSQL returns bigint as string
693
574
  });
694
575
  });