@geekmidas/testkit 0.0.2 → 0.0.4
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/PostgresKyselyMigrator.spec +471 -0
- package/dist/Factory.mjs +1 -1
- package/dist/{KyselyFactory-DiiWtMYe.cjs → KyselyFactory-BGvSMLtd.cjs} +11 -12
- package/dist/{KyselyFactory-DZewtWtJ.mjs → KyselyFactory-ionH4gvk.mjs} +12 -13
- package/dist/KyselyFactory.cjs +2 -1
- package/dist/KyselyFactory.mjs +3 -2
- package/dist/{ObjectionFactory-MAf2m8LI.mjs → ObjectionFactory-CFrtXe7i.mjs} +1 -1
- package/dist/ObjectionFactory.cjs +1 -1
- package/dist/ObjectionFactory.mjs +2 -2
- package/dist/{PostgresKyselyMigrator-ChMJpPrQ.mjs → PostgresKyselyMigrator-CbtiZgfI.mjs} +1 -1
- package/dist/{PostgresKyselyMigrator-rY3hO_-1.cjs → PostgresKyselyMigrator-Cxf2Dp9y.cjs} +3 -2
- package/dist/PostgresKyselyMigrator.cjs +2 -2
- package/dist/PostgresKyselyMigrator.mjs +2 -2
- package/dist/{PostgresMigrator-BJ2-5A_b.cjs → PostgresMigrator-eqyAFSf-.cjs} +2 -39
- package/dist/PostgresMigrator.cjs +1 -1
- package/dist/PostgresMigrator.mjs +1 -1
- package/dist/VitestKyselyTransactionIsolator-DXjWQtDN.mjs +12 -0
- package/dist/VitestKyselyTransactionIsolator-Dh2AgJDd.cjs +17 -0
- package/dist/VitestKyselyTransactionIsolator.cjs +5 -0
- package/dist/VitestKyselyTransactionIsolator.mjs +5 -0
- package/dist/VitestTransactionIsolator-pLwsDo_A.mjs +40 -0
- package/dist/VitestTransactionIsolator-zK5NJ7DQ.cjs +51 -0
- package/dist/VitestTransactionIsolator.cjs +5 -0
- package/dist/VitestTransactionIsolator.mjs +4 -0
- package/dist/__tests__/Factory.spec.cjs +139 -0
- package/dist/__tests__/Factory.spec.mjs +139 -0
- package/dist/__tests__/KyselyFactory.spec.cjs +221 -15008
- package/dist/__tests__/KyselyFactory.spec.mjs +220 -15034
- package/dist/__tests__/ObjectionFactory.spec.cjs +387 -0
- package/dist/__tests__/ObjectionFactory.spec.mjs +386 -0
- package/dist/__tests__/PostgresMigrator.spec.cjs +257 -0
- package/dist/__tests__/PostgresMigrator.spec.mjs +256 -0
- package/dist/__tests__/faker.spec.cjs +115 -0
- package/dist/__tests__/faker.spec.mjs +115 -0
- package/dist/__tests__/integration.spec.cjs +279 -0
- package/dist/__tests__/integration.spec.mjs +279 -0
- package/dist/chunk-DWy1uDak.cjs +39 -0
- package/dist/dist-BM2KvLG1.mjs +5618 -0
- package/dist/dist-DE3gAxQI.cjs +5736 -0
- package/dist/example.cjs +2 -1
- package/dist/example.mjs +3 -2
- package/dist/faker-cGCFcrj2.mjs +85 -0
- package/dist/faker-h6CkRloU.cjs +121 -0
- package/dist/faker.cjs +8 -0
- package/dist/faker.mjs +3 -0
- package/dist/helpers-BnARb5Ap.mjs +19 -0
- package/dist/helpers-C2NH7xcz.cjs +135 -0
- package/dist/helpers-C_RZk04R.cjs +31 -0
- package/dist/helpers-CukcFAU9.mjs +111 -0
- package/dist/helpers.cjs +7 -0
- package/dist/helpers.mjs +6 -0
- package/dist/kysely.cjs +16 -4
- package/dist/kysely.mjs +16 -5
- package/dist/objection.cjs +1 -1
- package/dist/objection.mjs +2 -2
- package/dist/vi.bdSIJ99Y-BgRxGeO2.mjs +9382 -0
- package/dist/vi.bdSIJ99Y-CFuzUeY6.cjs +9393 -0
- package/package.json +11 -6
- package/src/Factory.ts +3 -1
- package/src/KyselyFactory.ts +30 -36
- package/src/VitestKyselyTransactionIsolator.ts +23 -0
- package/src/VitestTransactionIsolator.ts +70 -0
- package/src/__tests__/Factory.spec.ts +164 -0
- package/src/__tests__/KyselyFactory.spec.ts +432 -64
- package/src/__tests__/ObjectionFactory.spec.ts +532 -0
- package/src/__tests__/PostgresMigrator.spec.ts +366 -0
- package/src/__tests__/faker.spec.ts +142 -0
- package/src/__tests__/integration.spec.ts +442 -0
- package/src/faker.ts +112 -0
- package/src/helpers.ts +28 -0
- package/src/kysely.ts +14 -0
- package/test/globalSetup.ts +41 -40
- package/test/helpers.ts +273 -0
- /package/dist/{Factory-DlzMkMzb.mjs → Factory-D52Lsc6Z.mjs} +0 -0
- /package/dist/{ObjectionFactory-DeFYWbzt.cjs → ObjectionFactory-BlkzSEqo.cjs} +0 -0
- /package/dist/{PostgresMigrator-BKaNTth5.mjs → PostgresMigrator-DqeuPy-e.mjs} +0 -0
- /package/dist/{magic-string.es-CxbtJGk_.mjs → magic-string.es-C6yzoryu.mjs} +0 -0
- /package/dist/{magic-string.es-KiPEzMtt.cjs → magic-string.es-jdtJrR0A.cjs} +0 -0
|
@@ -0,0 +1,386 @@
|
|
|
1
|
+
import { afterAll, beforeAll, describe, it } from "../dist-BM2KvLG1.mjs";
|
|
2
|
+
import "../Factory-D52Lsc6Z.mjs";
|
|
3
|
+
import { ObjectionFactory } from "../ObjectionFactory-CFrtXe7i.mjs";
|
|
4
|
+
import { globalExpect } from "../vi.bdSIJ99Y-BgRxGeO2.mjs";
|
|
5
|
+
import { setupKnexTest } from "../helpers-CukcFAU9.mjs";
|
|
6
|
+
import { Model } from "objection";
|
|
7
|
+
|
|
8
|
+
//#region src/__tests__/ObjectionFactory.spec.ts
|
|
9
|
+
var User = class extends Model {
|
|
10
|
+
static get tableName() {
|
|
11
|
+
return "users";
|
|
12
|
+
}
|
|
13
|
+
id;
|
|
14
|
+
name;
|
|
15
|
+
email;
|
|
16
|
+
role;
|
|
17
|
+
createdAt;
|
|
18
|
+
updatedAt;
|
|
19
|
+
};
|
|
20
|
+
var Post = class extends Model {
|
|
21
|
+
static get tableName() {
|
|
22
|
+
return "posts";
|
|
23
|
+
}
|
|
24
|
+
id;
|
|
25
|
+
title;
|
|
26
|
+
content;
|
|
27
|
+
userId;
|
|
28
|
+
published;
|
|
29
|
+
createdAt;
|
|
30
|
+
updatedAt;
|
|
31
|
+
};
|
|
32
|
+
var Comment = class extends Model {
|
|
33
|
+
static get tableName() {
|
|
34
|
+
return "comments";
|
|
35
|
+
}
|
|
36
|
+
id;
|
|
37
|
+
content;
|
|
38
|
+
postId;
|
|
39
|
+
userId;
|
|
40
|
+
createdAt;
|
|
41
|
+
};
|
|
42
|
+
describe.skip("ObjectionFactory", () => {
|
|
43
|
+
let factory;
|
|
44
|
+
let db;
|
|
45
|
+
let trx;
|
|
46
|
+
let cleanup;
|
|
47
|
+
beforeAll(async () => {
|
|
48
|
+
const setup = await setupKnexTest();
|
|
49
|
+
db = setup.db;
|
|
50
|
+
trx = setup.trx;
|
|
51
|
+
cleanup = setup.cleanup;
|
|
52
|
+
User.knex(trx);
|
|
53
|
+
Post.knex(trx);
|
|
54
|
+
Comment.knex(trx);
|
|
55
|
+
});
|
|
56
|
+
afterAll(async () => {
|
|
57
|
+
await cleanup();
|
|
58
|
+
});
|
|
59
|
+
describe("constructor", () => {
|
|
60
|
+
it("should create an ObjectionFactory instance", () => {
|
|
61
|
+
const builders = {};
|
|
62
|
+
const seeds = {};
|
|
63
|
+
factory = new ObjectionFactory(builders, seeds, trx);
|
|
64
|
+
globalExpect(factory).toBeInstanceOf(ObjectionFactory);
|
|
65
|
+
});
|
|
66
|
+
});
|
|
67
|
+
describe("insert method", () => {
|
|
68
|
+
it("should call builder and insert the record", async () => {
|
|
69
|
+
const userBuilder = async (attrs$1, factory$1, db$1) => {
|
|
70
|
+
return User.fromJson({
|
|
71
|
+
name: attrs$1.name || "Default Name",
|
|
72
|
+
email: attrs$1.email || `user${Date.now()}@example.com`,
|
|
73
|
+
role: attrs$1.role || "user",
|
|
74
|
+
createdAt: /* @__PURE__ */ new Date(),
|
|
75
|
+
updatedAt: /* @__PURE__ */ new Date()
|
|
76
|
+
});
|
|
77
|
+
};
|
|
78
|
+
const builders = { user: userBuilder };
|
|
79
|
+
factory = new ObjectionFactory(builders, {}, trx);
|
|
80
|
+
const attrs = {
|
|
81
|
+
name: "John Doe",
|
|
82
|
+
email: "john@example.com"
|
|
83
|
+
};
|
|
84
|
+
const result = await factory.insert("user", attrs);
|
|
85
|
+
globalExpect(result).toBeInstanceOf(User);
|
|
86
|
+
globalExpect(result.name).toBe("John Doe");
|
|
87
|
+
globalExpect(result.email).toBe("john@example.com");
|
|
88
|
+
globalExpect(result.id).toBeDefined();
|
|
89
|
+
});
|
|
90
|
+
it("should use empty object as default attributes", async () => {
|
|
91
|
+
const userBuilder = async (attrs, factory$1, db$1) => {
|
|
92
|
+
return User.fromJson({
|
|
93
|
+
name: "Default Name",
|
|
94
|
+
email: `user${Date.now()}@example.com`,
|
|
95
|
+
role: "user",
|
|
96
|
+
createdAt: /* @__PURE__ */ new Date(),
|
|
97
|
+
updatedAt: /* @__PURE__ */ new Date()
|
|
98
|
+
});
|
|
99
|
+
};
|
|
100
|
+
const builders = { user: userBuilder };
|
|
101
|
+
factory = new ObjectionFactory(builders, {}, trx);
|
|
102
|
+
const result = await factory.insert("user");
|
|
103
|
+
globalExpect(result).toBeInstanceOf(User);
|
|
104
|
+
globalExpect(result.name).toBe("Default Name");
|
|
105
|
+
globalExpect(result.id).toBeDefined();
|
|
106
|
+
});
|
|
107
|
+
it("should throw error for non-existent factory", async () => {
|
|
108
|
+
factory = new ObjectionFactory({}, {}, trx);
|
|
109
|
+
await globalExpect(factory.insert("nonExistent")).rejects.toThrow("Factory \"nonExistent\" does not exist");
|
|
110
|
+
});
|
|
111
|
+
it("should handle builder that returns a promise", async () => {
|
|
112
|
+
const userBuilder = async (attrs, factory$1, db$1) => {
|
|
113
|
+
await new Promise((resolve) => setTimeout(resolve, 10));
|
|
114
|
+
return User.fromJson({
|
|
115
|
+
name: attrs.name || "Default Name",
|
|
116
|
+
email: `async${Date.now()}@example.com`,
|
|
117
|
+
role: "user",
|
|
118
|
+
createdAt: /* @__PURE__ */ new Date(),
|
|
119
|
+
updatedAt: /* @__PURE__ */ new Date()
|
|
120
|
+
});
|
|
121
|
+
};
|
|
122
|
+
const builders = { user: userBuilder };
|
|
123
|
+
factory = new ObjectionFactory(builders, {}, trx);
|
|
124
|
+
const result = await factory.insert("user", { name: "Jane" });
|
|
125
|
+
globalExpect(result).toBeInstanceOf(User);
|
|
126
|
+
globalExpect(result.name).toBe("Jane");
|
|
127
|
+
});
|
|
128
|
+
});
|
|
129
|
+
describe("insertMany method", () => {
|
|
130
|
+
it("should insert multiple records with same attributes", async () => {
|
|
131
|
+
const userBuilder = async (attrs$1, factory$1, db$1) => {
|
|
132
|
+
return User.fromJson({
|
|
133
|
+
name: attrs$1.name || "Default Name",
|
|
134
|
+
email: `user${Date.now()}-${Math.random()}@example.com`,
|
|
135
|
+
role: "user",
|
|
136
|
+
createdAt: /* @__PURE__ */ new Date(),
|
|
137
|
+
updatedAt: /* @__PURE__ */ new Date()
|
|
138
|
+
});
|
|
139
|
+
};
|
|
140
|
+
const builders = { user: userBuilder };
|
|
141
|
+
factory = new ObjectionFactory(builders, {}, trx);
|
|
142
|
+
const attrs = { name: "User" };
|
|
143
|
+
const results = await factory.insertMany(3, "user", attrs);
|
|
144
|
+
globalExpect(results).toHaveLength(3);
|
|
145
|
+
results.forEach((result) => {
|
|
146
|
+
globalExpect(result).toBeInstanceOf(User);
|
|
147
|
+
globalExpect(result.name).toBe("User");
|
|
148
|
+
globalExpect(result.id).toBeDefined();
|
|
149
|
+
});
|
|
150
|
+
});
|
|
151
|
+
it("should insert multiple records with dynamic attributes", async () => {
|
|
152
|
+
const userBuilder = async (attrs, factory$1, db$1) => {
|
|
153
|
+
return User.fromJson({
|
|
154
|
+
name: attrs.name || "Default Name",
|
|
155
|
+
email: `user${Date.now()}-${Math.random()}@example.com`,
|
|
156
|
+
role: "user",
|
|
157
|
+
createdAt: /* @__PURE__ */ new Date(),
|
|
158
|
+
updatedAt: /* @__PURE__ */ new Date()
|
|
159
|
+
});
|
|
160
|
+
};
|
|
161
|
+
const builders = { user: userBuilder };
|
|
162
|
+
factory = new ObjectionFactory(builders, {}, trx);
|
|
163
|
+
const attrsFn = (idx) => ({ name: `User ${idx}` });
|
|
164
|
+
const results = await factory.insertMany(2, "user", attrsFn);
|
|
165
|
+
globalExpect(results).toHaveLength(2);
|
|
166
|
+
globalExpect(results[0].name).toBe("User 0");
|
|
167
|
+
globalExpect(results[1].name).toBe("User 1");
|
|
168
|
+
results.forEach((result) => {
|
|
169
|
+
globalExpect(result).toBeInstanceOf(User);
|
|
170
|
+
globalExpect(result.id).toBeDefined();
|
|
171
|
+
});
|
|
172
|
+
});
|
|
173
|
+
it("should use empty object as default attributes for insertMany", async () => {
|
|
174
|
+
const userBuilder = async (attrs, factory$1, db$1) => {
|
|
175
|
+
return User.fromJson({
|
|
176
|
+
name: "Default Name",
|
|
177
|
+
email: `user${Date.now()}-${Math.random()}@example.com`,
|
|
178
|
+
role: "user",
|
|
179
|
+
createdAt: /* @__PURE__ */ new Date(),
|
|
180
|
+
updatedAt: /* @__PURE__ */ new Date()
|
|
181
|
+
});
|
|
182
|
+
};
|
|
183
|
+
const builders = { user: userBuilder };
|
|
184
|
+
factory = new ObjectionFactory(builders, {}, trx);
|
|
185
|
+
const results = await factory.insertMany(2, "user");
|
|
186
|
+
globalExpect(results).toHaveLength(2);
|
|
187
|
+
results.forEach((result) => {
|
|
188
|
+
globalExpect(result).toBeInstanceOf(User);
|
|
189
|
+
globalExpect(result.name).toBe("Default Name");
|
|
190
|
+
globalExpect(result.id).toBeDefined();
|
|
191
|
+
});
|
|
192
|
+
});
|
|
193
|
+
it("should throw error for non-existent builder in insertMany", async () => {
|
|
194
|
+
factory = new ObjectionFactory({}, {}, trx);
|
|
195
|
+
await globalExpect(factory.insertMany(2, "nonExistent")).rejects.toThrow("Builder \"nonExistent\" is not registered");
|
|
196
|
+
});
|
|
197
|
+
});
|
|
198
|
+
describe("seed method", () => {
|
|
199
|
+
it("should execute seed function", async () => {
|
|
200
|
+
const userBuilder = async (attrs$1, factory$1, db$1) => {
|
|
201
|
+
return User.fromJson({
|
|
202
|
+
name: attrs$1.name || "Default Name",
|
|
203
|
+
email: attrs$1.email || `admin${Date.now()}@example.com`,
|
|
204
|
+
role: "admin",
|
|
205
|
+
createdAt: /* @__PURE__ */ new Date(),
|
|
206
|
+
updatedAt: /* @__PURE__ */ new Date()
|
|
207
|
+
});
|
|
208
|
+
};
|
|
209
|
+
const builders = { user: userBuilder };
|
|
210
|
+
const createAdminSeed = async (attrs$1, factory$1, db$1) => {
|
|
211
|
+
return await factory$1.insert("user", {
|
|
212
|
+
name: attrs$1.name || "Admin User",
|
|
213
|
+
email: "admin@example.com",
|
|
214
|
+
role: "admin"
|
|
215
|
+
});
|
|
216
|
+
};
|
|
217
|
+
const seeds = { createAdmin: createAdminSeed };
|
|
218
|
+
factory = new ObjectionFactory(builders, seeds, trx);
|
|
219
|
+
const attrs = { name: "Super Admin" };
|
|
220
|
+
const result = await factory.seed("createAdmin", attrs);
|
|
221
|
+
globalExpect(result).toBeInstanceOf(User);
|
|
222
|
+
globalExpect(result.name).toBe("Super Admin");
|
|
223
|
+
globalExpect(result.role).toBe("admin");
|
|
224
|
+
globalExpect(result.id).toBeDefined();
|
|
225
|
+
});
|
|
226
|
+
it("should use empty object as default attributes for seed", async () => {
|
|
227
|
+
const userBuilder = async (attrs, factory$1, db$1) => {
|
|
228
|
+
return User.fromJson({
|
|
229
|
+
name: "Default Admin",
|
|
230
|
+
email: `admin${Date.now()}@example.com`,
|
|
231
|
+
role: "admin",
|
|
232
|
+
createdAt: /* @__PURE__ */ new Date(),
|
|
233
|
+
updatedAt: /* @__PURE__ */ new Date()
|
|
234
|
+
});
|
|
235
|
+
};
|
|
236
|
+
const builders = { user: userBuilder };
|
|
237
|
+
const createAdminSeed = async (attrs, factory$1, db$1) => {
|
|
238
|
+
return await factory$1.insert("user", {
|
|
239
|
+
name: "Default Admin",
|
|
240
|
+
role: "admin"
|
|
241
|
+
});
|
|
242
|
+
};
|
|
243
|
+
const seeds = { createAdmin: createAdminSeed };
|
|
244
|
+
factory = new ObjectionFactory(builders, seeds, trx);
|
|
245
|
+
const result = await factory.seed("createAdmin");
|
|
246
|
+
globalExpect(result).toBeInstanceOf(User);
|
|
247
|
+
globalExpect(result.name).toBe("Default Admin");
|
|
248
|
+
globalExpect(result.role).toBe("admin");
|
|
249
|
+
});
|
|
250
|
+
it("should throw error for non-existent seed", () => {
|
|
251
|
+
factory = new ObjectionFactory({}, {}, trx);
|
|
252
|
+
globalExpect(() => factory.seed("nonExistent")).toThrow("Seed \"nonExistent\" is not registered");
|
|
253
|
+
});
|
|
254
|
+
it("should pass factory and db to seed function", async () => {
|
|
255
|
+
const userBuilder = async (attrs, factory$1, db$1) => {
|
|
256
|
+
return User.fromJson({
|
|
257
|
+
name: attrs.name || "Test User",
|
|
258
|
+
email: `test${Date.now()}@example.com`,
|
|
259
|
+
role: "user",
|
|
260
|
+
createdAt: /* @__PURE__ */ new Date(),
|
|
261
|
+
updatedAt: /* @__PURE__ */ new Date()
|
|
262
|
+
});
|
|
263
|
+
};
|
|
264
|
+
const builders = { user: userBuilder };
|
|
265
|
+
const complexSeed = async (attrs, passedFactory, passedDb) => {
|
|
266
|
+
globalExpect(passedFactory).toBe(factory);
|
|
267
|
+
globalExpect(passedDb).toBe(trx);
|
|
268
|
+
return await passedFactory.insert("user", { name: `Complex ${attrs.data}` });
|
|
269
|
+
};
|
|
270
|
+
const seeds = { complexSeed };
|
|
271
|
+
factory = new ObjectionFactory(builders, seeds, trx);
|
|
272
|
+
const result = await factory.seed("complexSeed", { data: "test" });
|
|
273
|
+
globalExpect(result).toBeInstanceOf(User);
|
|
274
|
+
globalExpect(result.name).toBe("Complex test");
|
|
275
|
+
});
|
|
276
|
+
});
|
|
277
|
+
describe("createSeed static method", () => {
|
|
278
|
+
it("should return the seed function unchanged", () => {
|
|
279
|
+
const seedFn = async (attrs, factory$1, db$1) => {
|
|
280
|
+
return {
|
|
281
|
+
id: 1,
|
|
282
|
+
name: "test"
|
|
283
|
+
};
|
|
284
|
+
};
|
|
285
|
+
const result = ObjectionFactory.createSeed(seedFn);
|
|
286
|
+
globalExpect(result).toBe(seedFn);
|
|
287
|
+
});
|
|
288
|
+
});
|
|
289
|
+
describe("error handling", () => {
|
|
290
|
+
it("should handle builder errors gracefully", async () => {
|
|
291
|
+
const userBuilder = async (attrs, factory$1, db$1) => {
|
|
292
|
+
throw new Error("Builder failed");
|
|
293
|
+
};
|
|
294
|
+
const builders = { user: userBuilder };
|
|
295
|
+
factory = new ObjectionFactory(builders, {}, trx);
|
|
296
|
+
await globalExpect(factory.insert("user")).rejects.toThrow("Builder failed");
|
|
297
|
+
});
|
|
298
|
+
it("should handle invalid model data gracefully", async () => {
|
|
299
|
+
const userBuilder = async (attrs, factory$1, db$1) => {
|
|
300
|
+
return User.fromJson({ invalidField: "invalid" });
|
|
301
|
+
};
|
|
302
|
+
const builders = { user: userBuilder };
|
|
303
|
+
factory = new ObjectionFactory(builders, {}, trx);
|
|
304
|
+
await globalExpect(factory.insert("user")).rejects.toThrow();
|
|
305
|
+
});
|
|
306
|
+
it("should handle seed function errors gracefully", async () => {
|
|
307
|
+
const failingSeed = async (attrs, factory$1, db$1) => {
|
|
308
|
+
throw new Error("Seed failed");
|
|
309
|
+
};
|
|
310
|
+
const seeds = { failingSeed };
|
|
311
|
+
factory = new ObjectionFactory({}, seeds, trx);
|
|
312
|
+
await globalExpect(factory.seed("failingSeed")).rejects.toThrow("Seed failed");
|
|
313
|
+
});
|
|
314
|
+
});
|
|
315
|
+
describe("type safety and integration", () => {
|
|
316
|
+
it("should work with typed builders and seeds", async () => {
|
|
317
|
+
const userBuilder = async (attrs, factory$1, db$1) => {
|
|
318
|
+
return User.fromJson({
|
|
319
|
+
name: attrs.name || "Default User",
|
|
320
|
+
email: attrs.email || `user${Date.now()}@example.com`,
|
|
321
|
+
role: "user",
|
|
322
|
+
createdAt: /* @__PURE__ */ new Date(),
|
|
323
|
+
updatedAt: /* @__PURE__ */ new Date()
|
|
324
|
+
});
|
|
325
|
+
};
|
|
326
|
+
const adminSeed = async (attrs, factory$1, db$1) => {
|
|
327
|
+
return factory$1.insert("user", {
|
|
328
|
+
name: "Admin",
|
|
329
|
+
email: "admin@example.com",
|
|
330
|
+
role: "admin"
|
|
331
|
+
});
|
|
332
|
+
};
|
|
333
|
+
const builders = { user: userBuilder };
|
|
334
|
+
const seeds = { admin: adminSeed };
|
|
335
|
+
factory = new ObjectionFactory(builders, seeds, trx);
|
|
336
|
+
globalExpect(factory).toBeInstanceOf(ObjectionFactory);
|
|
337
|
+
const admin = await factory.seed("admin", { isSuper: true });
|
|
338
|
+
globalExpect(admin).toBeInstanceOf(User);
|
|
339
|
+
globalExpect(admin.name).toBe("Admin");
|
|
340
|
+
});
|
|
341
|
+
it("should handle complex builder scenarios", async () => {
|
|
342
|
+
const userBuilder = async (attrs, factory$1, db$1) => {
|
|
343
|
+
return User.fromJson({
|
|
344
|
+
name: attrs.name || "Default User",
|
|
345
|
+
email: attrs.email || `user${Date.now()}@example.com`,
|
|
346
|
+
role: "user",
|
|
347
|
+
createdAt: /* @__PURE__ */ new Date(),
|
|
348
|
+
updatedAt: /* @__PURE__ */ new Date()
|
|
349
|
+
});
|
|
350
|
+
};
|
|
351
|
+
const postBuilder = async (attrs, factory$1, db$1) => {
|
|
352
|
+
if (!attrs.userId) {
|
|
353
|
+
const user = await factory$1.insert("user");
|
|
354
|
+
return Post.fromJson({
|
|
355
|
+
title: attrs.title || "Default Post",
|
|
356
|
+
content: attrs.content || "Default content",
|
|
357
|
+
userId: user.id,
|
|
358
|
+
published: attrs.published || false,
|
|
359
|
+
createdAt: /* @__PURE__ */ new Date(),
|
|
360
|
+
updatedAt: /* @__PURE__ */ new Date()
|
|
361
|
+
});
|
|
362
|
+
}
|
|
363
|
+
return Post.fromJson({
|
|
364
|
+
title: attrs.title || "Default Post",
|
|
365
|
+
content: attrs.content || "Default content",
|
|
366
|
+
userId: attrs.userId,
|
|
367
|
+
published: attrs.published || false,
|
|
368
|
+
createdAt: /* @__PURE__ */ new Date(),
|
|
369
|
+
updatedAt: /* @__PURE__ */ new Date()
|
|
370
|
+
});
|
|
371
|
+
};
|
|
372
|
+
const builders = {
|
|
373
|
+
user: userBuilder,
|
|
374
|
+
post: postBuilder
|
|
375
|
+
};
|
|
376
|
+
factory = new ObjectionFactory(builders, {}, trx);
|
|
377
|
+
const post = await factory.insert("post", { title: "Test Post" });
|
|
378
|
+
globalExpect(post).toBeInstanceOf(Post);
|
|
379
|
+
globalExpect(post.title).toBe("Test Post");
|
|
380
|
+
globalExpect(post.userId).toBeDefined();
|
|
381
|
+
globalExpect(typeof post.userId).toBe("number");
|
|
382
|
+
});
|
|
383
|
+
});
|
|
384
|
+
});
|
|
385
|
+
|
|
386
|
+
//#endregion
|
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
const require_chunk = require('../chunk-DWy1uDak.cjs');
|
|
2
|
+
const require_PostgresMigrator = require('../PostgresMigrator-eqyAFSf-.cjs');
|
|
3
|
+
const require_dist = require('../dist-DE3gAxQI.cjs');
|
|
4
|
+
const require_vi_bdSIJ99Y = require('../vi.bdSIJ99Y-CFuzUeY6.cjs');
|
|
5
|
+
const require_helpers = require('../helpers-C2NH7xcz.cjs');
|
|
6
|
+
const pg = require_chunk.__toESM(require("pg"));
|
|
7
|
+
|
|
8
|
+
//#region src/__tests__/PostgresMigrator.spec.ts
|
|
9
|
+
var TestPostgresMigrator = class extends require_PostgresMigrator.PostgresMigrator {
|
|
10
|
+
migrateCalled = false;
|
|
11
|
+
migrateError;
|
|
12
|
+
customMigrations = [];
|
|
13
|
+
async migrate() {
|
|
14
|
+
this.migrateCalled = true;
|
|
15
|
+
if (this.migrateError) throw this.migrateError;
|
|
16
|
+
for (const migration of this.customMigrations) await migration();
|
|
17
|
+
}
|
|
18
|
+
addMigration(migration) {
|
|
19
|
+
this.customMigrations.push(migration);
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
require_dist.describe("PostgresMigrator", () => {
|
|
23
|
+
let testDbName;
|
|
24
|
+
let cleanupDb;
|
|
25
|
+
let consoleSpy;
|
|
26
|
+
require_dist.beforeAll(async () => {
|
|
27
|
+
testDbName = `test_postgres_migrator_${Date.now()}`;
|
|
28
|
+
cleanupDb = await require_helpers.createTestDatabase(testDbName);
|
|
29
|
+
});
|
|
30
|
+
require_dist.beforeEach(() => {
|
|
31
|
+
consoleSpy = require_vi_bdSIJ99Y.vi.spyOn(console, "log").mockImplementation(() => {});
|
|
32
|
+
});
|
|
33
|
+
require_dist.afterEach(() => {
|
|
34
|
+
consoleSpy.mockRestore();
|
|
35
|
+
});
|
|
36
|
+
require_dist.afterAll(async () => {
|
|
37
|
+
await cleanupDb();
|
|
38
|
+
});
|
|
39
|
+
require_dist.describe("constructor", () => {
|
|
40
|
+
require_dist.it("should create a PostgresMigrator instance", () => {
|
|
41
|
+
const migrator = new TestPostgresMigrator(`postgresql://geekmidas:geekmidas@localhost:5432/${testDbName}`);
|
|
42
|
+
require_vi_bdSIJ99Y.globalExpect(migrator).toBeInstanceOf(require_PostgresMigrator.PostgresMigrator);
|
|
43
|
+
});
|
|
44
|
+
});
|
|
45
|
+
require_dist.describe("start method", () => {
|
|
46
|
+
require_dist.it("should create database, migrate, and return cleanup function", async () => {
|
|
47
|
+
const newDbName = `test_start_${Date.now()}`;
|
|
48
|
+
const uri = `postgresql://geekmidas:geekmidas@localhost:5432/${newDbName}`;
|
|
49
|
+
const migrator = new TestPostgresMigrator(uri);
|
|
50
|
+
let migrationRan = false;
|
|
51
|
+
migrator.addMigration(async () => {
|
|
52
|
+
migrationRan = true;
|
|
53
|
+
});
|
|
54
|
+
const cleanup = await migrator.start();
|
|
55
|
+
require_vi_bdSIJ99Y.globalExpect(migrator.migrateCalled).toBe(true);
|
|
56
|
+
require_vi_bdSIJ99Y.globalExpect(migrationRan).toBe(true);
|
|
57
|
+
require_vi_bdSIJ99Y.globalExpect(consoleSpy).toHaveBeenCalledWith(`Migrating database: ${newDbName}`);
|
|
58
|
+
require_vi_bdSIJ99Y.globalExpect(typeof cleanup).toBe("function");
|
|
59
|
+
await cleanup();
|
|
60
|
+
});
|
|
61
|
+
require_dist.it("should handle existing database", async () => {
|
|
62
|
+
const uri = `postgresql://geekmidas:geekmidas@localhost:5432/${testDbName}`;
|
|
63
|
+
const migrator = new TestPostgresMigrator(uri);
|
|
64
|
+
let migrationRan = false;
|
|
65
|
+
migrator.addMigration(async () => {
|
|
66
|
+
migrationRan = true;
|
|
67
|
+
});
|
|
68
|
+
const cleanup = await migrator.start();
|
|
69
|
+
require_vi_bdSIJ99Y.globalExpect(migrator.migrateCalled).toBe(true);
|
|
70
|
+
require_vi_bdSIJ99Y.globalExpect(migrationRan).toBe(true);
|
|
71
|
+
require_vi_bdSIJ99Y.globalExpect(typeof cleanup).toBe("function");
|
|
72
|
+
});
|
|
73
|
+
require_dist.it("should handle URI with query parameters", async () => {
|
|
74
|
+
const queryDbName = `test_query_params_${Date.now()}`;
|
|
75
|
+
const uri = `postgresql://geekmidas:geekmidas@localhost:5432/${queryDbName}?ssl=false&timeout=30`;
|
|
76
|
+
const migrator = new TestPostgresMigrator(uri);
|
|
77
|
+
const cleanup = await migrator.start();
|
|
78
|
+
require_vi_bdSIJ99Y.globalExpect(migrator.migrateCalled).toBe(true);
|
|
79
|
+
require_vi_bdSIJ99Y.globalExpect(typeof cleanup).toBe("function");
|
|
80
|
+
await cleanup();
|
|
81
|
+
});
|
|
82
|
+
require_dist.it("should clean up connections even if migration fails", async () => {
|
|
83
|
+
const failDbName = `test_fail_${Date.now()}`;
|
|
84
|
+
const uri = `postgresql://geekmidas:geekmidas@localhost:5432/${failDbName}`;
|
|
85
|
+
const migrator = new TestPostgresMigrator(uri);
|
|
86
|
+
migrator.migrateError = new Error("Migration failed");
|
|
87
|
+
await require_vi_bdSIJ99Y.globalExpect(migrator.start()).rejects.toThrow("Migration failed");
|
|
88
|
+
require_vi_bdSIJ99Y.globalExpect(migrator.migrateCalled).toBe(true);
|
|
89
|
+
const cleanupClient = new pg.Client({
|
|
90
|
+
host: "localhost",
|
|
91
|
+
port: 5432,
|
|
92
|
+
user: "geekmidas",
|
|
93
|
+
password: "geekmidas",
|
|
94
|
+
database: "postgres"
|
|
95
|
+
});
|
|
96
|
+
try {
|
|
97
|
+
await cleanupClient.connect();
|
|
98
|
+
await cleanupClient.query(`DROP DATABASE IF EXISTS "${failDbName}"`);
|
|
99
|
+
} finally {
|
|
100
|
+
await cleanupClient.end();
|
|
101
|
+
}
|
|
102
|
+
});
|
|
103
|
+
require_dist.it("should return cleanup function that drops database", async () => {
|
|
104
|
+
const cleanupDbName = `test_cleanup_${Date.now()}`;
|
|
105
|
+
const uri = `postgresql://geekmidas:geekmidas@localhost:5432/${cleanupDbName}`;
|
|
106
|
+
const migrator = new TestPostgresMigrator(uri);
|
|
107
|
+
const cleanup = await migrator.start();
|
|
108
|
+
require_vi_bdSIJ99Y.globalExpect(migrator.migrateCalled).toBe(true);
|
|
109
|
+
require_vi_bdSIJ99Y.globalExpect(typeof cleanup).toBe("function");
|
|
110
|
+
const checkClient = new pg.Client({
|
|
111
|
+
host: "localhost",
|
|
112
|
+
port: 5432,
|
|
113
|
+
user: "geekmidas",
|
|
114
|
+
password: "geekmidas",
|
|
115
|
+
database: "postgres"
|
|
116
|
+
});
|
|
117
|
+
await checkClient.connect();
|
|
118
|
+
const beforeResult = await checkClient.query(`SELECT * FROM pg_catalog.pg_database WHERE datname = $1`, [cleanupDbName]);
|
|
119
|
+
require_vi_bdSIJ99Y.globalExpect(beforeResult.rowCount).toBe(1);
|
|
120
|
+
await checkClient.end();
|
|
121
|
+
await cleanup();
|
|
122
|
+
const checkClient2 = new pg.Client({
|
|
123
|
+
host: "localhost",
|
|
124
|
+
port: 5432,
|
|
125
|
+
user: "geekmidas",
|
|
126
|
+
password: "geekmidas",
|
|
127
|
+
database: "postgres"
|
|
128
|
+
});
|
|
129
|
+
await checkClient2.connect();
|
|
130
|
+
const afterResult = await checkClient2.query(`SELECT * FROM pg_catalog.pg_database WHERE datname = $1`, [cleanupDbName]);
|
|
131
|
+
require_vi_bdSIJ99Y.globalExpect(afterResult.rowCount).toBe(0);
|
|
132
|
+
await checkClient2.end();
|
|
133
|
+
});
|
|
134
|
+
});
|
|
135
|
+
require_dist.describe("database creation", () => {
|
|
136
|
+
require_dist.it("should handle connection errors gracefully", async () => {
|
|
137
|
+
const badDbName = `test_bad_connection_${Date.now()}`;
|
|
138
|
+
const uri = `postgresql://invalid_user:invalid_pass@localhost:5432/${badDbName}`;
|
|
139
|
+
const migrator = new TestPostgresMigrator(uri);
|
|
140
|
+
await require_vi_bdSIJ99Y.globalExpect(migrator.start()).rejects.toThrow();
|
|
141
|
+
});
|
|
142
|
+
require_dist.it("should handle invalid database names", async () => {
|
|
143
|
+
const invalidDbName = "test-invalid-db-name!";
|
|
144
|
+
const uri = `postgresql://geekmidas:geekmidas@localhost:5432/${invalidDbName}`;
|
|
145
|
+
const migrator = new TestPostgresMigrator(uri);
|
|
146
|
+
await require_vi_bdSIJ99Y.globalExpect(migrator.start).rejects.toThrow();
|
|
147
|
+
});
|
|
148
|
+
});
|
|
149
|
+
require_dist.describe("URI parsing", () => {
|
|
150
|
+
require_dist.it("should parse different URI formats correctly", async () => {
|
|
151
|
+
const testDbName$1 = `test_uri_parsing_${Date.now()}`;
|
|
152
|
+
const uri = `postgresql://geekmidas:geekmidas@localhost:5432/${testDbName$1}`;
|
|
153
|
+
const migrator = new TestPostgresMigrator(uri);
|
|
154
|
+
const cleanup = await migrator.start();
|
|
155
|
+
require_vi_bdSIJ99Y.globalExpect(migrator.migrateCalled).toBe(true);
|
|
156
|
+
require_vi_bdSIJ99Y.globalExpect(typeof cleanup).toBe("function");
|
|
157
|
+
await cleanup();
|
|
158
|
+
});
|
|
159
|
+
});
|
|
160
|
+
require_dist.describe("error handling", () => {
|
|
161
|
+
require_dist.it("should propagate migration errors", async () => {
|
|
162
|
+
const errorDbName = `test_migration_error_${Date.now()}`;
|
|
163
|
+
const uri = `postgresql://geekmidas:geekmidas@localhost:5432/${errorDbName}`;
|
|
164
|
+
const migrator = new TestPostgresMigrator(uri);
|
|
165
|
+
const migrationError = new Error("Custom migration error");
|
|
166
|
+
migrator.migrateError = migrationError;
|
|
167
|
+
await require_vi_bdSIJ99Y.globalExpect(migrator.start()).rejects.toThrow("Custom migration error");
|
|
168
|
+
const cleanupClient = new pg.Client({
|
|
169
|
+
host: "localhost",
|
|
170
|
+
port: 5432,
|
|
171
|
+
user: "geekmidas",
|
|
172
|
+
password: "geekmidas",
|
|
173
|
+
database: "postgres"
|
|
174
|
+
});
|
|
175
|
+
try {
|
|
176
|
+
await cleanupClient.connect();
|
|
177
|
+
await cleanupClient.query(`DROP DATABASE IF EXISTS "${errorDbName}"`);
|
|
178
|
+
} finally {
|
|
179
|
+
await cleanupClient.end();
|
|
180
|
+
}
|
|
181
|
+
});
|
|
182
|
+
require_dist.it("should handle cleanup errors gracefully", async () => {
|
|
183
|
+
const cleanupErrorDbName = `test_cleanup_error_${Date.now()}`;
|
|
184
|
+
const uri = `postgresql://geekmidas:geekmidas@localhost:5432/${cleanupErrorDbName}`;
|
|
185
|
+
const migrator = new TestPostgresMigrator(uri);
|
|
186
|
+
const cleanup = await migrator.start();
|
|
187
|
+
const adminClient = new pg.Client({
|
|
188
|
+
host: "localhost",
|
|
189
|
+
port: 5432,
|
|
190
|
+
user: "geekmidas",
|
|
191
|
+
password: "geekmidas",
|
|
192
|
+
database: "postgres"
|
|
193
|
+
});
|
|
194
|
+
await adminClient.connect();
|
|
195
|
+
await adminClient.query(`DROP DATABASE IF EXISTS "${cleanupErrorDbName}"`);
|
|
196
|
+
await adminClient.end();
|
|
197
|
+
await require_vi_bdSIJ99Y.globalExpect(cleanup()).rejects.toThrow();
|
|
198
|
+
});
|
|
199
|
+
});
|
|
200
|
+
require_dist.describe("abstract method", () => {
|
|
201
|
+
require_dist.it("should require concrete implementation of migrate method", () => {
|
|
202
|
+
const migrator = new TestPostgresMigrator(`postgresql://geekmidas:geekmidas@localhost:5432/${testDbName}`);
|
|
203
|
+
require_vi_bdSIJ99Y.globalExpect(typeof migrator.migrate).toBe("function");
|
|
204
|
+
});
|
|
205
|
+
});
|
|
206
|
+
require_dist.describe("integration scenarios", () => {
|
|
207
|
+
require_dist.it("should handle complete workflow", async () => {
|
|
208
|
+
const integrationDbName = `test_integration_${Date.now()}`;
|
|
209
|
+
const uri = `postgresql://geekmidas:geekmidas@localhost:5432/${integrationDbName}`;
|
|
210
|
+
const migrator = new TestPostgresMigrator(uri);
|
|
211
|
+
migrator.addMigration(async () => {
|
|
212
|
+
const client = new pg.Client({
|
|
213
|
+
host: "localhost",
|
|
214
|
+
port: 5432,
|
|
215
|
+
user: "geekmidas",
|
|
216
|
+
password: "geekmidas",
|
|
217
|
+
database: integrationDbName
|
|
218
|
+
});
|
|
219
|
+
await client.connect();
|
|
220
|
+
await client.query(`
|
|
221
|
+
CREATE TABLE IF NOT EXISTS test_table (
|
|
222
|
+
id SERIAL PRIMARY KEY,
|
|
223
|
+
name VARCHAR(255) NOT NULL
|
|
224
|
+
)
|
|
225
|
+
`);
|
|
226
|
+
await client.end();
|
|
227
|
+
});
|
|
228
|
+
const cleanup = await migrator.start();
|
|
229
|
+
require_vi_bdSIJ99Y.globalExpect(migrator.migrateCalled).toBe(true);
|
|
230
|
+
require_vi_bdSIJ99Y.globalExpect(consoleSpy).toHaveBeenCalledWith(`Migrating database: ${integrationDbName}`);
|
|
231
|
+
const verifyClient = new pg.Client({
|
|
232
|
+
host: "localhost",
|
|
233
|
+
port: 5432,
|
|
234
|
+
user: "geekmidas",
|
|
235
|
+
password: "geekmidas",
|
|
236
|
+
database: integrationDbName
|
|
237
|
+
});
|
|
238
|
+
await verifyClient.connect();
|
|
239
|
+
const tableResult = await verifyClient.query(`
|
|
240
|
+
SELECT table_name FROM information_schema.tables
|
|
241
|
+
WHERE table_schema = 'public' AND table_name = 'test_table'
|
|
242
|
+
`);
|
|
243
|
+
require_vi_bdSIJ99Y.globalExpect(tableResult.rowCount).toBe(1);
|
|
244
|
+
await verifyClient.end();
|
|
245
|
+
await cleanup();
|
|
246
|
+
});
|
|
247
|
+
require_dist.it("should handle database that already exists and cleanup", async () => {
|
|
248
|
+
const uri = `postgresql://geekmidas:geekmidas@localhost:5432/${testDbName}`;
|
|
249
|
+
const migrator = new TestPostgresMigrator(uri);
|
|
250
|
+
const cleanup = await migrator.start();
|
|
251
|
+
require_vi_bdSIJ99Y.globalExpect(migrator.migrateCalled).toBe(true);
|
|
252
|
+
require_vi_bdSIJ99Y.globalExpect(typeof cleanup).toBe("function");
|
|
253
|
+
});
|
|
254
|
+
});
|
|
255
|
+
});
|
|
256
|
+
|
|
257
|
+
//#endregion
|