@geekmidas/testkit 0.0.5 → 0.0.7
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-WMhTNZ9S.cjs +56 -0
- package/dist/Factory-z2m01hMj.mjs +50 -0
- package/dist/Factory.cjs +1 -1
- package/dist/Factory.mjs +1 -1
- package/dist/KyselyFactory-Bdq1s1Go.cjs +215 -0
- package/dist/KyselyFactory-ELiHgHVv.mjs +210 -0
- package/dist/KyselyFactory.cjs +3 -3
- package/dist/KyselyFactory.mjs +3 -3
- package/dist/ObjectionFactory-89p-FFEw.mjs +178 -0
- package/dist/ObjectionFactory-C47B03Ot.cjs +183 -0
- package/dist/ObjectionFactory.cjs +2 -2
- package/dist/ObjectionFactory.mjs +2 -2
- package/dist/PostgresKyselyMigrator-Bs31emFd.cjs +87 -0
- package/dist/PostgresKyselyMigrator-ChIpZFYB.mjs +81 -0
- package/dist/PostgresKyselyMigrator.cjs +2 -2
- package/dist/PostgresKyselyMigrator.mjs +2 -2
- package/dist/PostgresMigrator-BtAWdLss.cjs +151 -0
- package/dist/PostgresMigrator-BzqksJcW.mjs +145 -0
- package/dist/PostgresMigrator.cjs +1 -1
- package/dist/PostgresMigrator.mjs +1 -1
- package/dist/VitestKyselyTransactionIsolator-AfxPJEwR.mjs +58 -0
- package/dist/VitestKyselyTransactionIsolator-YWnSJiIH.cjs +63 -0
- package/dist/VitestKyselyTransactionIsolator.cjs +2 -2
- package/dist/VitestKyselyTransactionIsolator.mjs +2 -2
- package/dist/VitestObjectionTransactionIsolator-0uX6DW5G.cjs +66 -0
- package/dist/VitestObjectionTransactionIsolator-BZRYy8iW.mjs +61 -0
- package/dist/VitestObjectionTransactionIsolator.cjs +4 -0
- package/dist/VitestObjectionTransactionIsolator.mjs +4 -0
- package/dist/VitestTransactionIsolator-DcOz0LZF.cjs +129 -0
- package/dist/VitestTransactionIsolator-kFL36T8x.mjs +117 -0
- package/dist/VitestTransactionIsolator.cjs +1 -1
- package/dist/VitestTransactionIsolator.mjs +1 -1
- package/dist/__tests__/Factory.spec.cjs +1 -1
- package/dist/__tests__/Factory.spec.mjs +1 -1
- package/dist/__tests__/KyselyFactory.spec.cjs +41 -40
- package/dist/__tests__/KyselyFactory.spec.mjs +42 -41
- package/dist/__tests__/ObjectionFactory.spec.cjs +3 -3
- package/dist/__tests__/ObjectionFactory.spec.mjs +3 -3
- package/dist/__tests__/PostgresMigrator.spec.cjs +2 -2
- package/dist/__tests__/PostgresMigrator.spec.mjs +2 -2
- package/dist/__tests__/faker.spec.cjs +1 -1
- package/dist/__tests__/faker.spec.mjs +1 -1
- package/dist/__tests__/integration.spec.cjs +11 -8
- package/dist/__tests__/integration.spec.mjs +12 -9
- package/dist/example.cjs +3 -3
- package/dist/example.mjs +3 -3
- package/dist/faker-CxKkEeYi.mjs +227 -0
- package/dist/faker-SMN4ira4.cjs +263 -0
- package/dist/faker.cjs +1 -1
- package/dist/faker.mjs +1 -1
- package/dist/helpers-CKMlwSYT.mjs +47 -0
- package/dist/helpers-H4hO5SZR.cjs +53 -0
- package/dist/helpers.cjs +2 -5
- package/dist/helpers.mjs +2 -4
- package/dist/kysely-B-GOhABm.cjs +72 -0
- package/dist/kysely-CqfoKVXs.mjs +67 -0
- package/dist/kysely.cjs +11 -15
- package/dist/kysely.mjs +9 -15
- package/dist/objection.cjs +86 -3
- package/dist/objection.mjs +83 -3
- package/package.json +2 -2
- package/src/Factory.ts +97 -0
- package/src/KyselyFactory.ts +180 -0
- package/src/ObjectionFactory.ts +145 -3
- package/src/PostgresKyselyMigrator.ts +54 -0
- package/src/PostgresMigrator.ts +90 -0
- package/src/VitestKyselyTransactionIsolator.ts +46 -0
- package/src/VitestObjectionTransactionIsolator.ts +73 -0
- package/src/VitestTransactionIsolator.ts +99 -2
- package/src/__tests__/KyselyFactory.spec.ts +4 -6
- package/src/__tests__/integration.spec.ts +8 -3
- package/src/faker.ts +158 -7
- package/src/helpers.ts +35 -18
- package/src/kysely.ts +66 -1
- package/src/objection.ts +95 -0
- package/dist/Factory-DREHoms3.cjs +0 -15
- package/dist/Factory-DlzMkMzb.mjs +0 -9
- package/dist/KyselyFactory-BX7Kv2uP.cjs +0 -65
- package/dist/KyselyFactory-pOMOFQWE.mjs +0 -60
- package/dist/ObjectionFactory-BlkzSEqo.cjs +0 -41
- package/dist/ObjectionFactory-ChuX8sZN.mjs +0 -36
- package/dist/PostgresKyselyMigrator-D8fm35-s.mjs +0 -27
- package/dist/PostgresKyselyMigrator-JTY2LfwD.cjs +0 -33
- package/dist/PostgresMigrator-Bz-tnjB6.cjs +0 -67
- package/dist/PostgresMigrator-CEoRKTdq.mjs +0 -61
- package/dist/VitestKyselyTransactionIsolator-BS3R-V0I.mjs +0 -12
- package/dist/VitestKyselyTransactionIsolator-DWSTKIe3.cjs +0 -17
- package/dist/VitestTransactionIsolator-BjVXqFs6.mjs +0 -40
- package/dist/VitestTransactionIsolator-Bx2c4OzK.cjs +0 -52
- package/dist/faker-BwaXA_RF.mjs +0 -85
- package/dist/faker-caz-8zt8.cjs +0 -121
- package/dist/helpers-B9Jdk_C7.cjs +0 -31
- package/dist/helpers-DOiGIkaU.mjs +0 -19
- /package/dist/{helpers-DKEBHABj.cjs → helpers-Bnm3Jy9X.cjs} +0 -0
- /package/dist/{helpers-BfuX-cjN.mjs → helpers-CukcFAU9.mjs} +0 -0
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
|
|
2
|
+
//#region src/Factory.ts
|
|
3
|
+
/**
|
|
4
|
+
* Abstract base class for database factories used in testing.
|
|
5
|
+
* Provides a standardized interface for creating test data using builder and seed patterns.
|
|
6
|
+
*
|
|
7
|
+
* @template Builders - Record of builder functions for creating individual entities
|
|
8
|
+
* @template Seeds - Record of seed functions for creating complex test scenarios
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```typescript
|
|
12
|
+
* // Define builders for creating individual records
|
|
13
|
+
* const builders = {
|
|
14
|
+
* user: (attrs) => ({ name: 'Test User', email: 'test@example.com', ...attrs }),
|
|
15
|
+
* post: (attrs) => ({ title: 'Test Post', content: 'Content', ...attrs })
|
|
16
|
+
* };
|
|
17
|
+
*
|
|
18
|
+
* // Define seeds for complex scenarios
|
|
19
|
+
* const seeds = {
|
|
20
|
+
* userWithPosts: async (attrs, factory) => {
|
|
21
|
+
* const user = await factory.insert('user', attrs);
|
|
22
|
+
* await factory.insertMany(3, 'post', { userId: user.id });
|
|
23
|
+
* return user;
|
|
24
|
+
* }
|
|
25
|
+
* };
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
var Factory = class {
|
|
29
|
+
/**
|
|
30
|
+
* Creates a typed seed function with proper type inference.
|
|
31
|
+
* This is a utility method to help with TypeScript type checking when defining seeds.
|
|
32
|
+
*
|
|
33
|
+
* @template Seed - The seed function type
|
|
34
|
+
* @param seedFn - The seed function to wrap
|
|
35
|
+
* @returns The same seed function with proper typing
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* ```typescript
|
|
39
|
+
* const userWithPostsSeed = Factory.createSeed(async (attrs, factory, db) => {
|
|
40
|
+
* const user = await factory.insert('user', attrs);
|
|
41
|
+
* return user;
|
|
42
|
+
* });
|
|
43
|
+
* ```
|
|
44
|
+
*/
|
|
45
|
+
static createSeed(seedFn) {
|
|
46
|
+
return seedFn;
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
//#endregion
|
|
51
|
+
Object.defineProperty(exports, 'Factory', {
|
|
52
|
+
enumerable: true,
|
|
53
|
+
get: function () {
|
|
54
|
+
return Factory;
|
|
55
|
+
}
|
|
56
|
+
});
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
//#region src/Factory.ts
|
|
2
|
+
/**
|
|
3
|
+
* Abstract base class for database factories used in testing.
|
|
4
|
+
* Provides a standardized interface for creating test data using builder and seed patterns.
|
|
5
|
+
*
|
|
6
|
+
* @template Builders - Record of builder functions for creating individual entities
|
|
7
|
+
* @template Seeds - Record of seed functions for creating complex test scenarios
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```typescript
|
|
11
|
+
* // Define builders for creating individual records
|
|
12
|
+
* const builders = {
|
|
13
|
+
* user: (attrs) => ({ name: 'Test User', email: 'test@example.com', ...attrs }),
|
|
14
|
+
* post: (attrs) => ({ title: 'Test Post', content: 'Content', ...attrs })
|
|
15
|
+
* };
|
|
16
|
+
*
|
|
17
|
+
* // Define seeds for complex scenarios
|
|
18
|
+
* const seeds = {
|
|
19
|
+
* userWithPosts: async (attrs, factory) => {
|
|
20
|
+
* const user = await factory.insert('user', attrs);
|
|
21
|
+
* await factory.insertMany(3, 'post', { userId: user.id });
|
|
22
|
+
* return user;
|
|
23
|
+
* }
|
|
24
|
+
* };
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
var Factory = class {
|
|
28
|
+
/**
|
|
29
|
+
* Creates a typed seed function with proper type inference.
|
|
30
|
+
* This is a utility method to help with TypeScript type checking when defining seeds.
|
|
31
|
+
*
|
|
32
|
+
* @template Seed - The seed function type
|
|
33
|
+
* @param seedFn - The seed function to wrap
|
|
34
|
+
* @returns The same seed function with proper typing
|
|
35
|
+
*
|
|
36
|
+
* @example
|
|
37
|
+
* ```typescript
|
|
38
|
+
* const userWithPostsSeed = Factory.createSeed(async (attrs, factory, db) => {
|
|
39
|
+
* const user = await factory.insert('user', attrs);
|
|
40
|
+
* return user;
|
|
41
|
+
* });
|
|
42
|
+
* ```
|
|
43
|
+
*/
|
|
44
|
+
static createSeed(seedFn) {
|
|
45
|
+
return seedFn;
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
//#endregion
|
|
50
|
+
export { Factory };
|
package/dist/Factory.cjs
CHANGED
package/dist/Factory.mjs
CHANGED
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
const require_Factory = require('./Factory-WMhTNZ9S.cjs');
|
|
2
|
+
const require_faker = require('./faker-SMN4ira4.cjs');
|
|
3
|
+
|
|
4
|
+
//#region src/KyselyFactory.ts
|
|
5
|
+
/**
|
|
6
|
+
* Factory implementation for Kysely ORM, providing test data creation utilities.
|
|
7
|
+
* Extends the base Factory class with Kysely-specific database operations.
|
|
8
|
+
*
|
|
9
|
+
* @template DB - The database schema type
|
|
10
|
+
* @template Builders - Record of builder functions for creating entities
|
|
11
|
+
* @template Seeds - Record of seed functions for complex test scenarios
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```typescript
|
|
15
|
+
* // Define your database schema
|
|
16
|
+
* interface Database {
|
|
17
|
+
* users: UsersTable;
|
|
18
|
+
* posts: PostsTable;
|
|
19
|
+
* }
|
|
20
|
+
*
|
|
21
|
+
* // Create builders
|
|
22
|
+
* const builders = {
|
|
23
|
+
* user: KyselyFactory.createBuilder<Database, 'users'>('users', (attrs, factory, db, faker) => ({
|
|
24
|
+
* id: faker.string.uuid(),
|
|
25
|
+
* name: faker.person.fullName(),
|
|
26
|
+
* email: faker.internet.email(),
|
|
27
|
+
* ...attrs
|
|
28
|
+
* })),
|
|
29
|
+
* post: KyselyFactory.createBuilder<Database, 'posts'>('posts', (attrs) => ({
|
|
30
|
+
* title: 'Test Post',
|
|
31
|
+
* content: 'Test content',
|
|
32
|
+
* ...attrs
|
|
33
|
+
* }))
|
|
34
|
+
* };
|
|
35
|
+
*
|
|
36
|
+
* // Create factory instance
|
|
37
|
+
* const factory = new KyselyFactory(builders, seeds, db);
|
|
38
|
+
*
|
|
39
|
+
* // Use in tests
|
|
40
|
+
* const user = await factory.insert('user', { name: 'John Doe' });
|
|
41
|
+
* ```
|
|
42
|
+
*/
|
|
43
|
+
var KyselyFactory = class extends require_Factory.Factory {
|
|
44
|
+
/**
|
|
45
|
+
* Creates a typed seed function with proper type inference.
|
|
46
|
+
* Inherits from the base Factory class implementation.
|
|
47
|
+
*
|
|
48
|
+
* @template Seed - The seed function type
|
|
49
|
+
* @param seedFn - The seed function to wrap
|
|
50
|
+
* @returns The same seed function with proper typing
|
|
51
|
+
*/
|
|
52
|
+
static createSeed(seedFn) {
|
|
53
|
+
return require_Factory.Factory.createSeed(seedFn);
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Creates a new KyselyFactory instance.
|
|
57
|
+
*
|
|
58
|
+
* @param builders - Record of builder functions for creating individual entities
|
|
59
|
+
* @param seeds - Record of seed functions for creating complex test scenarios
|
|
60
|
+
* @param db - Kysely database instance or controlled transaction
|
|
61
|
+
*/
|
|
62
|
+
constructor(builders, seeds, db) {
|
|
63
|
+
super();
|
|
64
|
+
this.builders = builders;
|
|
65
|
+
this.seeds = seeds;
|
|
66
|
+
this.db = db;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Creates a typed builder function for a specific database table.
|
|
70
|
+
* This is a utility method that helps create builders with proper type inference for Kysely.
|
|
71
|
+
*
|
|
72
|
+
* @template DB - The database schema type
|
|
73
|
+
* @template TableName - The name of the table (must be a key of DB)
|
|
74
|
+
* @template Attrs - The attributes type for the builder (defaults to Partial<Insertable>)
|
|
75
|
+
* @template Factory - The factory instance type
|
|
76
|
+
* @template Result - The result type (defaults to Selectable of the table)
|
|
77
|
+
*
|
|
78
|
+
* @param table - The name of the database table
|
|
79
|
+
* @param item - Optional function to provide default values and transformations
|
|
80
|
+
* @param autoInsert - Whether to automatically insert the record (default: true)
|
|
81
|
+
* @returns A builder function that creates and optionally inserts records
|
|
82
|
+
*
|
|
83
|
+
* @example
|
|
84
|
+
* ```typescript
|
|
85
|
+
* // Create a simple builder with defaults
|
|
86
|
+
* const userBuilder = KyselyFactory.createBuilder<DB, 'users'>('users',
|
|
87
|
+
* (attrs, factory, db, faker) => ({
|
|
88
|
+
* id: faker.string.uuid(),
|
|
89
|
+
* name: faker.person.fullName(),
|
|
90
|
+
* email: faker.internet.email(),
|
|
91
|
+
* createdAt: new Date(),
|
|
92
|
+
* ...attrs
|
|
93
|
+
* })
|
|
94
|
+
* );
|
|
95
|
+
*
|
|
96
|
+
* // Create a builder that doesn't auto-insert (useful for nested inserts)
|
|
97
|
+
* const addressBuilder = KyselyFactory.createBuilder<DB, 'addresses'>('addresses',
|
|
98
|
+
* (attrs) => ({
|
|
99
|
+
* street: '123 Main St',
|
|
100
|
+
* city: 'Anytown',
|
|
101
|
+
* ...attrs
|
|
102
|
+
* }),
|
|
103
|
+
* false // Don't auto-insert
|
|
104
|
+
* );
|
|
105
|
+
* ```
|
|
106
|
+
*/
|
|
107
|
+
static createBuilder(table, item, autoInsert) {
|
|
108
|
+
return async (attrs, factory, db, faker$1) => {
|
|
109
|
+
let data = { ...attrs };
|
|
110
|
+
if (item) {
|
|
111
|
+
const defaults = await item(attrs, factory, db, faker$1);
|
|
112
|
+
data = {
|
|
113
|
+
...defaults,
|
|
114
|
+
...data
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
if (autoInsert !== false) {
|
|
118
|
+
const result = await db.insertInto(table).values(data).returningAll().executeTakeFirst();
|
|
119
|
+
if (!result) throw new Error(`Failed to insert into ${table}`);
|
|
120
|
+
return result;
|
|
121
|
+
} else return {
|
|
122
|
+
table,
|
|
123
|
+
data
|
|
124
|
+
};
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Inserts a single record into the database using the specified builder.
|
|
129
|
+
* The builder function is responsible for generating the record data with defaults
|
|
130
|
+
* and the factory handles the actual database insertion.
|
|
131
|
+
*
|
|
132
|
+
* @template K - The builder name (must be a key of Builders)
|
|
133
|
+
* @param builderName - The name of the builder to use
|
|
134
|
+
* @param attrs - Optional attributes to override builder defaults
|
|
135
|
+
* @returns A promise resolving to the inserted record
|
|
136
|
+
* @throws Error if the specified builder doesn't exist
|
|
137
|
+
*
|
|
138
|
+
* @example
|
|
139
|
+
* ```typescript
|
|
140
|
+
* // Insert with defaults
|
|
141
|
+
* const user = await factory.insert('user');
|
|
142
|
+
*
|
|
143
|
+
* // Insert with overrides
|
|
144
|
+
* const adminUser = await factory.insert('user', {
|
|
145
|
+
* email: 'admin@example.com',
|
|
146
|
+
* role: 'admin'
|
|
147
|
+
* });
|
|
148
|
+
*
|
|
149
|
+
* // Use the inserted record
|
|
150
|
+
* const post = await factory.insert('post', {
|
|
151
|
+
* userId: user.id,
|
|
152
|
+
* title: 'My First Post'
|
|
153
|
+
* });
|
|
154
|
+
* ```
|
|
155
|
+
*/
|
|
156
|
+
async insert(builderName, attrs) {
|
|
157
|
+
if (!(builderName in this.builders)) throw new Error(`Factory "${builderName}" does not exist. Make sure it is correct and registered in src/test/setup.ts`);
|
|
158
|
+
const result = await this.builders[builderName](attrs || {}, this, this.db, require_faker.faker);
|
|
159
|
+
if (result && typeof result === "object" && "table" in result && "data" in result) {
|
|
160
|
+
const inserted = await this.db.insertInto(result.table).values(result.data).returningAll().executeTakeFirst();
|
|
161
|
+
return inserted;
|
|
162
|
+
}
|
|
163
|
+
return result;
|
|
164
|
+
}
|
|
165
|
+
async insertMany(count, builderName, attrs) {
|
|
166
|
+
if (!(builderName in this.builders)) throw new Error(`Builder "${builderName}" is not registered in this factory. Make sure it is correct and registered in src/test/setup.ts`);
|
|
167
|
+
const promises = [];
|
|
168
|
+
for (let i = 0; i < count; i++) {
|
|
169
|
+
const newAttrs = typeof attrs === "function" ? attrs(i, require_faker.faker) : attrs;
|
|
170
|
+
promises.push(this.insert(builderName, newAttrs));
|
|
171
|
+
}
|
|
172
|
+
return Promise.all(promises);
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Executes a seed function to create complex test scenarios with multiple related records.
|
|
176
|
+
* Seeds are useful for setting up complete test environments with realistic data relationships.
|
|
177
|
+
*
|
|
178
|
+
* @template K - The seed name (must be a key of Seeds)
|
|
179
|
+
* @param seedName - The name of the seed to execute
|
|
180
|
+
* @param attrs - Optional configuration attributes for the seed
|
|
181
|
+
* @returns The result of the seed function (typically the primary record created)
|
|
182
|
+
* @throws Error if the specified seed doesn't exist
|
|
183
|
+
*
|
|
184
|
+
* @example
|
|
185
|
+
* ```typescript
|
|
186
|
+
* // Execute a simple seed
|
|
187
|
+
* const user = await factory.seed('userWithProfile');
|
|
188
|
+
*
|
|
189
|
+
* // Execute a seed with configuration
|
|
190
|
+
* const author = await factory.seed('authorWithBooks', {
|
|
191
|
+
* bookCount: 5,
|
|
192
|
+
* includeReviews: true
|
|
193
|
+
* });
|
|
194
|
+
*
|
|
195
|
+
* // Use seed result in tests
|
|
196
|
+
* const company = await factory.seed('companyWithDepartments', {
|
|
197
|
+
* departmentCount: 3,
|
|
198
|
+
* employeesPerDepartment: 10
|
|
199
|
+
* });
|
|
200
|
+
* expect(company.departments).toHaveLength(3);
|
|
201
|
+
* ```
|
|
202
|
+
*/
|
|
203
|
+
seed(seedName, attrs) {
|
|
204
|
+
if (!(seedName in this.seeds)) throw new Error(`Seed "${seedName}" is not registered in this factory. Make sure it is correct and registered in src/test/setup.ts`);
|
|
205
|
+
return this.seeds[seedName](attrs || {}, this, this.db);
|
|
206
|
+
}
|
|
207
|
+
};
|
|
208
|
+
|
|
209
|
+
//#endregion
|
|
210
|
+
Object.defineProperty(exports, 'KyselyFactory', {
|
|
211
|
+
enumerable: true,
|
|
212
|
+
get: function () {
|
|
213
|
+
return KyselyFactory;
|
|
214
|
+
}
|
|
215
|
+
});
|
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
import { Factory } from "./Factory-z2m01hMj.mjs";
|
|
2
|
+
import { faker } from "./faker-CxKkEeYi.mjs";
|
|
3
|
+
|
|
4
|
+
//#region src/KyselyFactory.ts
|
|
5
|
+
/**
|
|
6
|
+
* Factory implementation for Kysely ORM, providing test data creation utilities.
|
|
7
|
+
* Extends the base Factory class with Kysely-specific database operations.
|
|
8
|
+
*
|
|
9
|
+
* @template DB - The database schema type
|
|
10
|
+
* @template Builders - Record of builder functions for creating entities
|
|
11
|
+
* @template Seeds - Record of seed functions for complex test scenarios
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```typescript
|
|
15
|
+
* // Define your database schema
|
|
16
|
+
* interface Database {
|
|
17
|
+
* users: UsersTable;
|
|
18
|
+
* posts: PostsTable;
|
|
19
|
+
* }
|
|
20
|
+
*
|
|
21
|
+
* // Create builders
|
|
22
|
+
* const builders = {
|
|
23
|
+
* user: KyselyFactory.createBuilder<Database, 'users'>('users', (attrs, factory, db, faker) => ({
|
|
24
|
+
* id: faker.string.uuid(),
|
|
25
|
+
* name: faker.person.fullName(),
|
|
26
|
+
* email: faker.internet.email(),
|
|
27
|
+
* ...attrs
|
|
28
|
+
* })),
|
|
29
|
+
* post: KyselyFactory.createBuilder<Database, 'posts'>('posts', (attrs) => ({
|
|
30
|
+
* title: 'Test Post',
|
|
31
|
+
* content: 'Test content',
|
|
32
|
+
* ...attrs
|
|
33
|
+
* }))
|
|
34
|
+
* };
|
|
35
|
+
*
|
|
36
|
+
* // Create factory instance
|
|
37
|
+
* const factory = new KyselyFactory(builders, seeds, db);
|
|
38
|
+
*
|
|
39
|
+
* // Use in tests
|
|
40
|
+
* const user = await factory.insert('user', { name: 'John Doe' });
|
|
41
|
+
* ```
|
|
42
|
+
*/
|
|
43
|
+
var KyselyFactory = class extends Factory {
|
|
44
|
+
/**
|
|
45
|
+
* Creates a typed seed function with proper type inference.
|
|
46
|
+
* Inherits from the base Factory class implementation.
|
|
47
|
+
*
|
|
48
|
+
* @template Seed - The seed function type
|
|
49
|
+
* @param seedFn - The seed function to wrap
|
|
50
|
+
* @returns The same seed function with proper typing
|
|
51
|
+
*/
|
|
52
|
+
static createSeed(seedFn) {
|
|
53
|
+
return Factory.createSeed(seedFn);
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Creates a new KyselyFactory instance.
|
|
57
|
+
*
|
|
58
|
+
* @param builders - Record of builder functions for creating individual entities
|
|
59
|
+
* @param seeds - Record of seed functions for creating complex test scenarios
|
|
60
|
+
* @param db - Kysely database instance or controlled transaction
|
|
61
|
+
*/
|
|
62
|
+
constructor(builders, seeds, db) {
|
|
63
|
+
super();
|
|
64
|
+
this.builders = builders;
|
|
65
|
+
this.seeds = seeds;
|
|
66
|
+
this.db = db;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Creates a typed builder function for a specific database table.
|
|
70
|
+
* This is a utility method that helps create builders with proper type inference for Kysely.
|
|
71
|
+
*
|
|
72
|
+
* @template DB - The database schema type
|
|
73
|
+
* @template TableName - The name of the table (must be a key of DB)
|
|
74
|
+
* @template Attrs - The attributes type for the builder (defaults to Partial<Insertable>)
|
|
75
|
+
* @template Factory - The factory instance type
|
|
76
|
+
* @template Result - The result type (defaults to Selectable of the table)
|
|
77
|
+
*
|
|
78
|
+
* @param table - The name of the database table
|
|
79
|
+
* @param item - Optional function to provide default values and transformations
|
|
80
|
+
* @param autoInsert - Whether to automatically insert the record (default: true)
|
|
81
|
+
* @returns A builder function that creates and optionally inserts records
|
|
82
|
+
*
|
|
83
|
+
* @example
|
|
84
|
+
* ```typescript
|
|
85
|
+
* // Create a simple builder with defaults
|
|
86
|
+
* const userBuilder = KyselyFactory.createBuilder<DB, 'users'>('users',
|
|
87
|
+
* (attrs, factory, db, faker) => ({
|
|
88
|
+
* id: faker.string.uuid(),
|
|
89
|
+
* name: faker.person.fullName(),
|
|
90
|
+
* email: faker.internet.email(),
|
|
91
|
+
* createdAt: new Date(),
|
|
92
|
+
* ...attrs
|
|
93
|
+
* })
|
|
94
|
+
* );
|
|
95
|
+
*
|
|
96
|
+
* // Create a builder that doesn't auto-insert (useful for nested inserts)
|
|
97
|
+
* const addressBuilder = KyselyFactory.createBuilder<DB, 'addresses'>('addresses',
|
|
98
|
+
* (attrs) => ({
|
|
99
|
+
* street: '123 Main St',
|
|
100
|
+
* city: 'Anytown',
|
|
101
|
+
* ...attrs
|
|
102
|
+
* }),
|
|
103
|
+
* false // Don't auto-insert
|
|
104
|
+
* );
|
|
105
|
+
* ```
|
|
106
|
+
*/
|
|
107
|
+
static createBuilder(table, item, autoInsert) {
|
|
108
|
+
return async (attrs, factory, db, faker$1) => {
|
|
109
|
+
let data = { ...attrs };
|
|
110
|
+
if (item) {
|
|
111
|
+
const defaults = await item(attrs, factory, db, faker$1);
|
|
112
|
+
data = {
|
|
113
|
+
...defaults,
|
|
114
|
+
...data
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
if (autoInsert !== false) {
|
|
118
|
+
const result = await db.insertInto(table).values(data).returningAll().executeTakeFirst();
|
|
119
|
+
if (!result) throw new Error(`Failed to insert into ${table}`);
|
|
120
|
+
return result;
|
|
121
|
+
} else return {
|
|
122
|
+
table,
|
|
123
|
+
data
|
|
124
|
+
};
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Inserts a single record into the database using the specified builder.
|
|
129
|
+
* The builder function is responsible for generating the record data with defaults
|
|
130
|
+
* and the factory handles the actual database insertion.
|
|
131
|
+
*
|
|
132
|
+
* @template K - The builder name (must be a key of Builders)
|
|
133
|
+
* @param builderName - The name of the builder to use
|
|
134
|
+
* @param attrs - Optional attributes to override builder defaults
|
|
135
|
+
* @returns A promise resolving to the inserted record
|
|
136
|
+
* @throws Error if the specified builder doesn't exist
|
|
137
|
+
*
|
|
138
|
+
* @example
|
|
139
|
+
* ```typescript
|
|
140
|
+
* // Insert with defaults
|
|
141
|
+
* const user = await factory.insert('user');
|
|
142
|
+
*
|
|
143
|
+
* // Insert with overrides
|
|
144
|
+
* const adminUser = await factory.insert('user', {
|
|
145
|
+
* email: 'admin@example.com',
|
|
146
|
+
* role: 'admin'
|
|
147
|
+
* });
|
|
148
|
+
*
|
|
149
|
+
* // Use the inserted record
|
|
150
|
+
* const post = await factory.insert('post', {
|
|
151
|
+
* userId: user.id,
|
|
152
|
+
* title: 'My First Post'
|
|
153
|
+
* });
|
|
154
|
+
* ```
|
|
155
|
+
*/
|
|
156
|
+
async insert(builderName, attrs) {
|
|
157
|
+
if (!(builderName in this.builders)) throw new Error(`Factory "${builderName}" does not exist. Make sure it is correct and registered in src/test/setup.ts`);
|
|
158
|
+
const result = await this.builders[builderName](attrs || {}, this, this.db, faker);
|
|
159
|
+
if (result && typeof result === "object" && "table" in result && "data" in result) {
|
|
160
|
+
const inserted = await this.db.insertInto(result.table).values(result.data).returningAll().executeTakeFirst();
|
|
161
|
+
return inserted;
|
|
162
|
+
}
|
|
163
|
+
return result;
|
|
164
|
+
}
|
|
165
|
+
async insertMany(count, builderName, attrs) {
|
|
166
|
+
if (!(builderName in this.builders)) throw new Error(`Builder "${builderName}" is not registered in this factory. Make sure it is correct and registered in src/test/setup.ts`);
|
|
167
|
+
const promises = [];
|
|
168
|
+
for (let i = 0; i < count; i++) {
|
|
169
|
+
const newAttrs = typeof attrs === "function" ? attrs(i, faker) : attrs;
|
|
170
|
+
promises.push(this.insert(builderName, newAttrs));
|
|
171
|
+
}
|
|
172
|
+
return Promise.all(promises);
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Executes a seed function to create complex test scenarios with multiple related records.
|
|
176
|
+
* Seeds are useful for setting up complete test environments with realistic data relationships.
|
|
177
|
+
*
|
|
178
|
+
* @template K - The seed name (must be a key of Seeds)
|
|
179
|
+
* @param seedName - The name of the seed to execute
|
|
180
|
+
* @param attrs - Optional configuration attributes for the seed
|
|
181
|
+
* @returns The result of the seed function (typically the primary record created)
|
|
182
|
+
* @throws Error if the specified seed doesn't exist
|
|
183
|
+
*
|
|
184
|
+
* @example
|
|
185
|
+
* ```typescript
|
|
186
|
+
* // Execute a simple seed
|
|
187
|
+
* const user = await factory.seed('userWithProfile');
|
|
188
|
+
*
|
|
189
|
+
* // Execute a seed with configuration
|
|
190
|
+
* const author = await factory.seed('authorWithBooks', {
|
|
191
|
+
* bookCount: 5,
|
|
192
|
+
* includeReviews: true
|
|
193
|
+
* });
|
|
194
|
+
*
|
|
195
|
+
* // Use seed result in tests
|
|
196
|
+
* const company = await factory.seed('companyWithDepartments', {
|
|
197
|
+
* departmentCount: 3,
|
|
198
|
+
* employeesPerDepartment: 10
|
|
199
|
+
* });
|
|
200
|
+
* expect(company.departments).toHaveLength(3);
|
|
201
|
+
* ```
|
|
202
|
+
*/
|
|
203
|
+
seed(seedName, attrs) {
|
|
204
|
+
if (!(seedName in this.seeds)) throw new Error(`Seed "${seedName}" is not registered in this factory. Make sure it is correct and registered in src/test/setup.ts`);
|
|
205
|
+
return this.seeds[seedName](attrs || {}, this, this.db);
|
|
206
|
+
}
|
|
207
|
+
};
|
|
208
|
+
|
|
209
|
+
//#endregion
|
|
210
|
+
export { KyselyFactory };
|
package/dist/KyselyFactory.cjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
require('./Factory-
|
|
2
|
-
require('./faker-
|
|
3
|
-
const require_KyselyFactory = require('./KyselyFactory-
|
|
1
|
+
require('./Factory-WMhTNZ9S.cjs');
|
|
2
|
+
require('./faker-SMN4ira4.cjs');
|
|
3
|
+
const require_KyselyFactory = require('./KyselyFactory-Bdq1s1Go.cjs');
|
|
4
4
|
|
|
5
5
|
exports.KyselyFactory = require_KyselyFactory.KyselyFactory;
|
package/dist/KyselyFactory.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import "./Factory-
|
|
2
|
-
import "./faker-
|
|
3
|
-
import { KyselyFactory } from "./KyselyFactory-
|
|
1
|
+
import "./Factory-z2m01hMj.mjs";
|
|
2
|
+
import "./faker-CxKkEeYi.mjs";
|
|
3
|
+
import { KyselyFactory } from "./KyselyFactory-ELiHgHVv.mjs";
|
|
4
4
|
|
|
5
5
|
export { KyselyFactory };
|