@geekmidas/testkit 0.0.9 → 0.0.11
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/dist/Factory-B9LP1L18.d.cts +131 -0
- package/dist/Factory-DiZSNxC0.d.mts +131 -0
- package/dist/Factory.d.cts +3 -0
- package/dist/Factory.d.mts +3 -0
- package/dist/KyselyFactory-B-zlLbov.d.mts +200 -0
- package/dist/KyselyFactory-CrLWxJW4.d.cts +200 -0
- package/dist/KyselyFactory.d.cts +4 -0
- package/dist/KyselyFactory.d.mts +4 -0
- package/dist/ObjectionFactory-CJCpvwts.d.mts +213 -0
- package/dist/{ObjectionFactory-C47B03Ot.cjs → ObjectionFactory-Wq80ypMM.cjs} +82 -40
- package/dist/{ObjectionFactory-89p-FFEw.mjs → ObjectionFactory-aqM0dDW7.mjs} +82 -40
- package/dist/ObjectionFactory-vME-wNlq.d.cts +213 -0
- package/dist/ObjectionFactory.cjs +2 -1
- package/dist/ObjectionFactory.d.cts +4 -0
- package/dist/ObjectionFactory.d.mts +4 -0
- package/dist/ObjectionFactory.mjs +2 -1
- package/dist/{PostgresKyselyMigrator-ChIpZFYB.mjs → PostgresKyselyMigrator-Bdhl251C.mjs} +1 -1
- package/dist/PostgresKyselyMigrator-CQ3aUoy_.d.cts +67 -0
- package/dist/{PostgresKyselyMigrator-Bs31emFd.cjs → PostgresKyselyMigrator-CfytARcA.cjs} +1 -1
- package/dist/PostgresKyselyMigrator-_6yHZigp.d.mts +67 -0
- package/dist/PostgresKyselyMigrator.cjs +2 -2
- package/dist/PostgresKyselyMigrator.d.cts +3 -0
- package/dist/PostgresKyselyMigrator.d.mts +3 -0
- package/dist/PostgresKyselyMigrator.mjs +2 -2
- package/dist/PostgresMigrator-BlvuQl7d.d.mts +84 -0
- package/dist/PostgresMigrator-D5UkK1_K.d.cts +84 -0
- package/dist/{PostgresMigrator-BtAWdLss.cjs → PostgresMigrator-DFcNdCvD.cjs} +2 -1
- package/dist/{PostgresMigrator-BzqksJcW.mjs → PostgresMigrator-DxPC_gGu.mjs} +3 -2
- package/dist/PostgresMigrator.cjs +1 -1
- package/dist/PostgresMigrator.d.cts +2 -0
- package/dist/PostgresMigrator.d.mts +2 -0
- package/dist/PostgresMigrator.mjs +1 -1
- package/dist/{PostgresObjectionMigrator-B88aTT0m.cjs → PostgresObjectionMigrator-BG6ymgnt.cjs} +1 -1
- package/dist/PostgresObjectionMigrator-C69n7vzr.d.mts +77 -0
- package/dist/PostgresObjectionMigrator-CZHHcCOv.d.cts +77 -0
- package/dist/{PostgresObjectionMigrator-DydSgYFv.mjs → PostgresObjectionMigrator-G4h5FLvU.mjs} +1 -1
- package/dist/PostgresObjectionMigrator.cjs +2 -2
- package/dist/PostgresObjectionMigrator.d.cts +3 -0
- package/dist/PostgresObjectionMigrator.d.mts +3 -0
- package/dist/PostgresObjectionMigrator.mjs +2 -2
- package/dist/VitestKyselyTransactionIsolator-ClCazkBO.d.mts +56 -0
- package/dist/VitestKyselyTransactionIsolator-UE1J-UoP.d.cts +56 -0
- package/dist/VitestKyselyTransactionIsolator.d.cts +3 -0
- package/dist/VitestKyselyTransactionIsolator.d.mts +3 -0
- package/dist/VitestObjectionTransactionIsolator-CO2nTi9r.d.cts +57 -0
- package/dist/VitestObjectionTransactionIsolator-D264iuPy.d.mts +57 -0
- package/dist/VitestObjectionTransactionIsolator.d.cts +3 -0
- package/dist/VitestObjectionTransactionIsolator.d.mts +3 -0
- package/dist/VitestTransactionIsolator-DHf2MxmC.d.cts +118 -0
- package/dist/VitestTransactionIsolator-Xqyjlmw6.d.mts +118 -0
- package/dist/VitestTransactionIsolator.d.cts +2 -0
- package/dist/VitestTransactionIsolator.d.mts +2 -0
- package/dist/__tests__/Factory.spec.d.cts +1 -0
- package/dist/__tests__/Factory.spec.d.mts +1 -0
- package/dist/__tests__/KyselyFactory.spec.cjs +2 -2
- package/dist/__tests__/KyselyFactory.spec.d.cts +1 -0
- package/dist/__tests__/KyselyFactory.spec.d.mts +1 -0
- package/dist/__tests__/KyselyFactory.spec.mjs +2 -2
- package/dist/__tests__/ObjectionFactory.spec.cjs +117 -1
- package/dist/__tests__/ObjectionFactory.spec.d.cts +1 -0
- package/dist/__tests__/ObjectionFactory.spec.d.mts +1 -0
- package/dist/__tests__/ObjectionFactory.spec.mjs +117 -1
- package/dist/__tests__/PostgresMigrator.spec.cjs +1 -1
- package/dist/__tests__/PostgresMigrator.spec.d.cts +1 -0
- package/dist/__tests__/PostgresMigrator.spec.d.mts +1 -0
- package/dist/__tests__/PostgresMigrator.spec.mjs +1 -1
- package/dist/__tests__/PostgresObjectionMigrator.spec.cjs +2 -2
- package/dist/__tests__/PostgresObjectionMigrator.spec.d.cts +1 -0
- package/dist/__tests__/PostgresObjectionMigrator.spec.d.mts +1 -0
- package/dist/__tests__/PostgresObjectionMigrator.spec.mjs +2 -2
- package/dist/__tests__/VitestObjectionTransactionIsolator.spec.cjs +4 -3
- package/dist/__tests__/VitestObjectionTransactionIsolator.spec.d.cts +1 -0
- package/dist/__tests__/VitestObjectionTransactionIsolator.spec.d.mts +1 -0
- package/dist/__tests__/VitestObjectionTransactionIsolator.spec.mjs +4 -3
- package/dist/__tests__/faker.spec.d.cts +1 -0
- package/dist/__tests__/faker.spec.d.mts +1 -0
- package/dist/__tests__/integration.spec.cjs +2 -2
- package/dist/__tests__/integration.spec.d.cts +1 -0
- package/dist/__tests__/integration.spec.d.mts +1 -0
- package/dist/__tests__/integration.spec.mjs +2 -2
- package/dist/example.d.cts +26 -0
- package/dist/example.d.mts +26 -0
- package/dist/faker-DAiFK3T3.d.cts +155 -0
- package/dist/faker-nN9Ki6fn.d.mts +155 -0
- package/dist/faker.d.cts +2 -0
- package/dist/faker.d.mts +2 -0
- package/dist/helpers.d.cts +41 -0
- package/dist/helpers.d.mts +41 -0
- package/dist/kysely.cjs +2 -2
- package/dist/kysely.d.cts +73 -0
- package/dist/kysely.d.mts +73 -0
- package/dist/kysely.mjs +2 -2
- package/dist/objection.cjs +4 -3
- package/dist/objection.d.cts +88 -0
- package/dist/objection.d.mts +88 -0
- package/dist/objection.mjs +4 -3
- package/package.json +5 -5
- package/src/ObjectionFactory.ts +156 -13
- package/src/PostgresMigrator.ts +3 -1
- package/src/__tests__/ObjectionFactory.spec.ts +162 -0
- package/PostgresKyselyMigrator.spec +0 -471
package/src/ObjectionFactory.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import type { Knex } from 'knex';
|
|
2
|
+
import type { Model } from 'objection';
|
|
2
3
|
import { Factory, type FactorySeed } from './Factory.ts';
|
|
4
|
+
import { type FakerFactory, faker } from './faker.ts';
|
|
3
5
|
|
|
4
6
|
/**
|
|
5
7
|
* Factory implementation for Objection.js ORM, providing test data creation utilities.
|
|
@@ -53,6 +55,105 @@ export class ObjectionFactory<
|
|
|
53
55
|
return Factory.createSeed(seedFn);
|
|
54
56
|
}
|
|
55
57
|
|
|
58
|
+
/**
|
|
59
|
+
* Creates a typed builder function for Objection.js models.
|
|
60
|
+
* This is a utility method that helps create builders with proper type inference.
|
|
61
|
+
*
|
|
62
|
+
* @template TModel - The Objection.js Model class type
|
|
63
|
+
* @template Attrs - The attributes type for the builder (defaults to Partial of model)
|
|
64
|
+
* @template Factory - The factory instance type
|
|
65
|
+
* @template Result - The result type (defaults to the model instance)
|
|
66
|
+
*
|
|
67
|
+
* @param ModelClass - The Objection.js Model class
|
|
68
|
+
* @param item - Optional function to provide default values and transformations
|
|
69
|
+
* @param autoInsert - Whether to automatically insert the record (default: true)
|
|
70
|
+
* @returns A builder function that creates and optionally inserts records
|
|
71
|
+
*
|
|
72
|
+
* @example
|
|
73
|
+
* ```typescript
|
|
74
|
+
* // Create a simple builder with defaults
|
|
75
|
+
* const userBuilder = ObjectionFactory.createBuilder(User,
|
|
76
|
+
* (attrs, factory, db, faker) => ({
|
|
77
|
+
* id: faker.string.uuid(),
|
|
78
|
+
* name: faker.person.fullName(),
|
|
79
|
+
* email: faker.internet.email(),
|
|
80
|
+
* createdAt: new Date(),
|
|
81
|
+
* ...attrs
|
|
82
|
+
* })
|
|
83
|
+
* );
|
|
84
|
+
*
|
|
85
|
+
* // Create a builder that doesn't auto-insert (useful for nested inserts)
|
|
86
|
+
* const addressBuilder = ObjectionFactory.createBuilder(Address,
|
|
87
|
+
* (attrs) => ({
|
|
88
|
+
* street: '123 Main St',
|
|
89
|
+
* city: 'Anytown',
|
|
90
|
+
* ...attrs
|
|
91
|
+
* }),
|
|
92
|
+
* false // Don't auto-insert
|
|
93
|
+
* );
|
|
94
|
+
*
|
|
95
|
+
* // Use with relations
|
|
96
|
+
* const postBuilder = ObjectionFactory.createBuilder(Post,
|
|
97
|
+
* async (attrs, factory) => ({
|
|
98
|
+
* title: faker.lorem.sentence(),
|
|
99
|
+
* content: faker.lorem.paragraphs(),
|
|
100
|
+
* authorId: attrs.authorId || (await factory.insert('user')).id,
|
|
101
|
+
* ...attrs
|
|
102
|
+
* })
|
|
103
|
+
* );
|
|
104
|
+
* ```
|
|
105
|
+
*/
|
|
106
|
+
static createBuilder<
|
|
107
|
+
TModel extends typeof Model,
|
|
108
|
+
Attrs extends Partial<InstanceType<TModel>> = Partial<InstanceType<TModel>>,
|
|
109
|
+
Factory = any,
|
|
110
|
+
Result = InstanceType<TModel>,
|
|
111
|
+
>(
|
|
112
|
+
ModelClass: TModel,
|
|
113
|
+
item?: (
|
|
114
|
+
attrs: Attrs,
|
|
115
|
+
factory: Factory,
|
|
116
|
+
db: Knex,
|
|
117
|
+
faker: FakerFactory,
|
|
118
|
+
) => Partial<InstanceType<TModel>> | Promise<Partial<InstanceType<TModel>>>,
|
|
119
|
+
autoInsert?: boolean,
|
|
120
|
+
): (
|
|
121
|
+
attrs: Attrs,
|
|
122
|
+
factory: Factory,
|
|
123
|
+
db: Knex,
|
|
124
|
+
faker: FakerFactory,
|
|
125
|
+
) => Promise<Result> {
|
|
126
|
+
return async (
|
|
127
|
+
attrs: Attrs,
|
|
128
|
+
factory: Factory,
|
|
129
|
+
db: Knex,
|
|
130
|
+
faker: FakerFactory,
|
|
131
|
+
) => {
|
|
132
|
+
// Start with attributes
|
|
133
|
+
let data: Partial<InstanceType<TModel>> = { ...attrs };
|
|
134
|
+
|
|
135
|
+
// Apply defaults
|
|
136
|
+
if (item) {
|
|
137
|
+
const defaults = await item(attrs, factory, db, faker);
|
|
138
|
+
data = { ...defaults, ...data };
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// Create model instance
|
|
142
|
+
const model = ModelClass.fromJson(data) as InstanceType<TModel>;
|
|
143
|
+
|
|
144
|
+
// Handle insertion based on autoInsert flag
|
|
145
|
+
if (autoInsert !== false) {
|
|
146
|
+
// Auto insert is enabled by default
|
|
147
|
+
// @ts-ignore
|
|
148
|
+
const result = await model.$query(db).insertGraph(model).execute();
|
|
149
|
+
return result as Result;
|
|
150
|
+
} else {
|
|
151
|
+
// Return model for factory to handle insertion
|
|
152
|
+
return model as Result;
|
|
153
|
+
}
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
|
|
56
157
|
/**
|
|
57
158
|
* Creates a new ObjectionFactory instance.
|
|
58
159
|
*
|
|
@@ -72,7 +173,8 @@ export class ObjectionFactory<
|
|
|
72
173
|
* Inserts a single record into the database using the specified builder.
|
|
73
174
|
* Uses Objection.js's insertGraph method to handle nested relations.
|
|
74
175
|
*
|
|
75
|
-
* @
|
|
176
|
+
* @template K - The builder name (must be a key of Builders)
|
|
177
|
+
* @param builderName - The name of the builder to use
|
|
76
178
|
* @param attrs - Optional attributes to override builder defaults
|
|
77
179
|
* @returns A promise resolving to the inserted record with all relations
|
|
78
180
|
* @throws Error if the specified builder doesn't exist
|
|
@@ -98,18 +200,32 @@ export class ObjectionFactory<
|
|
|
98
200
|
* });
|
|
99
201
|
* ```
|
|
100
202
|
*/
|
|
101
|
-
insert
|
|
102
|
-
|
|
203
|
+
async insert<K extends keyof Builders>(
|
|
204
|
+
builderName: K,
|
|
205
|
+
attrs?: Parameters<Builders[K]>[0],
|
|
206
|
+
): Promise<Awaited<ReturnType<Builders[K]>>> {
|
|
207
|
+
if (!(builderName in this.builders)) {
|
|
103
208
|
throw new Error(
|
|
104
209
|
`Factory "${
|
|
105
|
-
|
|
210
|
+
builderName as string
|
|
106
211
|
}" does not exist. Make sure it is correct and registered in src/test/setup.ts`,
|
|
107
212
|
);
|
|
108
213
|
}
|
|
109
214
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
215
|
+
const result = await this.builders[builderName](
|
|
216
|
+
attrs || {},
|
|
217
|
+
this,
|
|
218
|
+
this.db,
|
|
219
|
+
faker,
|
|
220
|
+
);
|
|
221
|
+
|
|
222
|
+
// If the builder returns a model instance, insert it
|
|
223
|
+
if (result && typeof result.$query === 'function') {
|
|
224
|
+
return await result.$query(this.db).insertGraph(result).execute();
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
// Otherwise, assume the builder handled insertion itself
|
|
228
|
+
return result;
|
|
113
229
|
}
|
|
114
230
|
/**
|
|
115
231
|
* Inserts multiple records into the database using the specified builder.
|
|
@@ -140,7 +256,22 @@ export class ObjectionFactory<
|
|
|
140
256
|
* }));
|
|
141
257
|
* ```
|
|
142
258
|
*/
|
|
143
|
-
|
|
259
|
+
// Method overloads for better type inference
|
|
260
|
+
async insertMany<K extends keyof Builders>(
|
|
261
|
+
count: number,
|
|
262
|
+
builderName: K,
|
|
263
|
+
attrs?: Parameters<Builders[K]>[0],
|
|
264
|
+
): Promise<Awaited<ReturnType<Builders[K]>>[]>;
|
|
265
|
+
async insertMany<K extends keyof Builders>(
|
|
266
|
+
count: number,
|
|
267
|
+
builderName: K,
|
|
268
|
+
attrs: (idx: number, faker: FakerFactory) => Parameters<Builders[K]>[0],
|
|
269
|
+
): Promise<Awaited<ReturnType<Builders[K]>>[]>;
|
|
270
|
+
async insertMany<K extends keyof Builders>(
|
|
271
|
+
count: number,
|
|
272
|
+
builderName: K,
|
|
273
|
+
attrs?: any,
|
|
274
|
+
): Promise<Awaited<ReturnType<Builders[K]>>[]> {
|
|
144
275
|
if (!(builderName in this.builders)) {
|
|
145
276
|
throw new Error(
|
|
146
277
|
`Builder "${
|
|
@@ -151,11 +282,19 @@ export class ObjectionFactory<
|
|
|
151
282
|
|
|
152
283
|
const records: any[] = [];
|
|
153
284
|
for (let i = 0; i < count; i++) {
|
|
154
|
-
const newAttrs =
|
|
285
|
+
const newAttrs =
|
|
286
|
+
typeof attrs === 'function' ? (attrs as any)(i, faker) : attrs;
|
|
155
287
|
|
|
156
288
|
records.push(
|
|
157
|
-
this.builders[builderName](newAttrs,
|
|
158
|
-
|
|
289
|
+
this.builders[builderName](newAttrs, this, this.db, faker).then(
|
|
290
|
+
(record: any) => {
|
|
291
|
+
// If the builder returns a model instance, insert it
|
|
292
|
+
if (record && typeof record.$query === 'function') {
|
|
293
|
+
return record.$query(this.db).insertGraph(record).execute();
|
|
294
|
+
}
|
|
295
|
+
// Otherwise, assume the builder handled insertion itself
|
|
296
|
+
return record;
|
|
297
|
+
},
|
|
159
298
|
),
|
|
160
299
|
);
|
|
161
300
|
}
|
|
@@ -166,6 +305,7 @@ export class ObjectionFactory<
|
|
|
166
305
|
* Executes a seed function to create complex test scenarios with multiple related records.
|
|
167
306
|
* Seeds are useful for setting up complete test environments with realistic data relationships.
|
|
168
307
|
*
|
|
308
|
+
* @template K - The seed name (must be a key of Seeds)
|
|
169
309
|
* @param seedName - The name of the seed to execute
|
|
170
310
|
* @param attrs - Optional configuration attributes for the seed
|
|
171
311
|
* @returns The result of the seed function (typically the primary record created)
|
|
@@ -194,7 +334,10 @@ export class ObjectionFactory<
|
|
|
194
334
|
* .withGraphFetched('[departments.employees]');
|
|
195
335
|
* ```
|
|
196
336
|
*/
|
|
197
|
-
seed
|
|
337
|
+
seed<K extends keyof Seeds>(
|
|
338
|
+
seedName: K,
|
|
339
|
+
attrs?: Parameters<Seeds[K]>[0],
|
|
340
|
+
): ReturnType<Seeds[K]> {
|
|
198
341
|
if (!(seedName in this.seeds)) {
|
|
199
342
|
throw new Error(
|
|
200
343
|
`Seed "${
|
|
@@ -203,6 +346,6 @@ export class ObjectionFactory<
|
|
|
203
346
|
);
|
|
204
347
|
}
|
|
205
348
|
|
|
206
|
-
return this.seeds[seedName](attrs, this, this.db);
|
|
349
|
+
return this.seeds[seedName](attrs || {}, this, this.db);
|
|
207
350
|
}
|
|
208
351
|
}
|
package/src/PostgresMigrator.ts
CHANGED
|
@@ -3,6 +3,7 @@ import { Model } from 'objection';
|
|
|
3
3
|
import { afterAll, beforeAll, describe, expect, it } from 'vitest';
|
|
4
4
|
import { setupKnexTest } from '../../test/helpers';
|
|
5
5
|
import { ObjectionFactory } from '../ObjectionFactory';
|
|
6
|
+
import { faker } from '../faker';
|
|
6
7
|
|
|
7
8
|
// Define real Objection models for testing
|
|
8
9
|
class User extends Model {
|
|
@@ -386,6 +387,167 @@ describe.skip('ObjectionFactory', () => {
|
|
|
386
387
|
});
|
|
387
388
|
});
|
|
388
389
|
|
|
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(),
|
|
400
|
+
...attrs,
|
|
401
|
+
}),
|
|
402
|
+
);
|
|
403
|
+
|
|
404
|
+
const builders = { user: userBuilder };
|
|
405
|
+
factory = new ObjectionFactory(builders, {}, trx);
|
|
406
|
+
|
|
407
|
+
const result = await factory.insert('user', { name: 'Test User' });
|
|
408
|
+
|
|
409
|
+
expect(result).toBeInstanceOf(User);
|
|
410
|
+
expect(result.name).toBe('Test User');
|
|
411
|
+
expect(result.email).toMatch(/@/);
|
|
412
|
+
expect(result.id).toBeDefined();
|
|
413
|
+
});
|
|
414
|
+
|
|
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(),
|
|
424
|
+
...attrs,
|
|
425
|
+
}),
|
|
426
|
+
false, // Don't auto-insert
|
|
427
|
+
);
|
|
428
|
+
|
|
429
|
+
const builders = { user: userBuilder };
|
|
430
|
+
factory = new ObjectionFactory(builders, {}, trx);
|
|
431
|
+
|
|
432
|
+
const result = await factory.insert('user');
|
|
433
|
+
|
|
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
|
+
});
|
|
439
|
+
|
|
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
|
+
});
|
|
472
|
+
|
|
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');
|
|
495
|
+
|
|
496
|
+
expect(result).toBeInstanceOf(User);
|
|
497
|
+
expect(result.name).toBe('Async User');
|
|
498
|
+
expect(result.id).toBeDefined();
|
|
499
|
+
});
|
|
500
|
+
|
|
501
|
+
it('should work without item function', async () => {
|
|
502
|
+
const userBuilder = ObjectionFactory.createBuilder(User);
|
|
503
|
+
|
|
504
|
+
const builders = { user: userBuilder };
|
|
505
|
+
factory = new ObjectionFactory(builders, {}, trx);
|
|
506
|
+
|
|
507
|
+
const attrs = {
|
|
508
|
+
name: 'Manual User',
|
|
509
|
+
email: 'manual@example.com',
|
|
510
|
+
role: 'user',
|
|
511
|
+
createdAt: new Date(),
|
|
512
|
+
updatedAt: new Date(),
|
|
513
|
+
};
|
|
514
|
+
|
|
515
|
+
const result = await factory.insert('user', attrs);
|
|
516
|
+
|
|
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();
|
|
521
|
+
});
|
|
522
|
+
|
|
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
|
+
});
|
|
549
|
+
});
|
|
550
|
+
|
|
389
551
|
describe('error handling', () => {
|
|
390
552
|
it('should handle builder errors gracefully', async () => {
|
|
391
553
|
const userBuilder = async (attrs: any, factory: any, db: Knex) => {
|