@geekmidas/testkit 0.4.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (209) hide show
  1. package/dist/Factory-BFVnMMCC.mjs.map +1 -1
  2. package/dist/Factory-BhjUOBWN.cjs.map +1 -1
  3. package/dist/{Factory-c16c27Y6.d.cts → Factory-Bx0AJXZB.d.cts} +3 -2
  4. package/dist/Factory-Bx0AJXZB.d.cts.map +1 -0
  5. package/dist/{Factory-BcGJjLc8.d.mts → Factory-SFupxRC2.d.mts} +2 -1
  6. package/dist/Factory-SFupxRC2.d.mts.map +1 -0
  7. package/dist/Factory.d.cts +2 -2
  8. package/dist/Factory.d.mts +1 -1
  9. package/dist/KyselyFactory-BFqVIn_0.cjs.map +1 -1
  10. package/dist/KyselyFactory-DMswpwji.mjs.map +1 -1
  11. package/dist/{KyselyFactory-uZ45h7YU.d.cts → KyselyFactory-KLeKH43i.d.cts} +4 -3
  12. package/dist/KyselyFactory-KLeKH43i.d.cts.map +1 -0
  13. package/dist/{KyselyFactory-Cj-EultY.d.mts → KyselyFactory-vAxYodck.d.mts} +3 -2
  14. package/dist/KyselyFactory-vAxYodck.d.mts.map +1 -0
  15. package/dist/KyselyFactory.d.cts +3 -3
  16. package/dist/KyselyFactory.d.mts +2 -2
  17. package/dist/{ObjectionFactory-DL4qkuF1.d.mts → ObjectionFactory-BWjB49-i.d.mts} +3 -2
  18. package/dist/ObjectionFactory-BWjB49-i.d.mts.map +1 -0
  19. package/dist/ObjectionFactory-BeFBYcan.cjs.map +1 -1
  20. package/dist/ObjectionFactory-QCJ7u0Ql.mjs.map +1 -1
  21. package/dist/{ObjectionFactory-CdhzKs4f.d.cts → ObjectionFactory-aMGvAKt9.d.cts} +4 -3
  22. package/dist/ObjectionFactory-aMGvAKt9.d.cts.map +1 -0
  23. package/dist/ObjectionFactory.d.cts +3 -3
  24. package/dist/ObjectionFactory.d.mts +2 -2
  25. package/dist/{PostgresKyselyMigrator-upT-hmrz.mjs → PostgresKyselyMigrator-6sE1KOni.mjs} +2 -2
  26. package/dist/PostgresKyselyMigrator-6sE1KOni.mjs.map +1 -0
  27. package/dist/{PostgresKyselyMigrator-CIx3AFSR.d.mts → PostgresKyselyMigrator-CBltSOq5.d.cts} +3 -2
  28. package/dist/PostgresKyselyMigrator-CBltSOq5.d.cts.map +1 -0
  29. package/dist/{PostgresKyselyMigrator-CfytARcA.cjs → PostgresKyselyMigrator-D6IbPq8t.cjs} +2 -2
  30. package/dist/PostgresKyselyMigrator-D6IbPq8t.cjs.map +1 -0
  31. package/dist/{PostgresKyselyMigrator-CQ3aUoy_.d.cts → PostgresKyselyMigrator-DrVWncqd.d.mts} +3 -2
  32. package/dist/PostgresKyselyMigrator-DrVWncqd.d.mts.map +1 -0
  33. package/dist/PostgresKyselyMigrator.cjs +2 -2
  34. package/dist/PostgresKyselyMigrator.d.cts +2 -2
  35. package/dist/PostgresKyselyMigrator.d.mts +2 -2
  36. package/dist/PostgresKyselyMigrator.mjs +2 -2
  37. package/dist/{PostgresMigrator-DbuJGAVy.mjs → PostgresMigrator-BjjenqSd.mjs} +2 -2
  38. package/dist/PostgresMigrator-BjjenqSd.mjs.map +1 -0
  39. package/dist/{PostgresMigrator-D5UkK1_K.d.cts → PostgresMigrator-Bres0U6E.d.cts} +2 -1
  40. package/dist/PostgresMigrator-Bres0U6E.d.cts.map +1 -0
  41. package/dist/{PostgresMigrator-DFcNdCvD.cjs → PostgresMigrator-D6dQn0x2.cjs} +2 -2
  42. package/dist/PostgresMigrator-D6dQn0x2.cjs.map +1 -0
  43. package/dist/{PostgresMigrator-DQaRxoaY.d.mts → PostgresMigrator-S-YYosAC.d.mts} +2 -1
  44. package/dist/PostgresMigrator-S-YYosAC.d.mts.map +1 -0
  45. package/dist/PostgresMigrator.cjs +1 -1
  46. package/dist/PostgresMigrator.d.cts +1 -1
  47. package/dist/PostgresMigrator.d.mts +1 -1
  48. package/dist/PostgresMigrator.mjs +1 -1
  49. package/dist/{PostgresObjectionMigrator-CZHHcCOv.d.cts → PostgresObjectionMigrator-CPfBAP7r.d.cts} +3 -2
  50. package/dist/PostgresObjectionMigrator-CPfBAP7r.d.cts.map +1 -0
  51. package/dist/{PostgresObjectionMigrator-BG6ymgnt.cjs → PostgresObjectionMigrator-DK8ODIHQ.cjs} +2 -2
  52. package/dist/PostgresObjectionMigrator-DK8ODIHQ.cjs.map +1 -0
  53. package/dist/{PostgresObjectionMigrator-D_hCcrQu.d.mts → PostgresObjectionMigrator-DVEqB5tp.d.mts} +3 -2
  54. package/dist/PostgresObjectionMigrator-DVEqB5tp.d.mts.map +1 -0
  55. package/dist/{PostgresObjectionMigrator-DPj2pOpX.mjs → PostgresObjectionMigrator-D_QxXbIN.mjs} +2 -2
  56. package/dist/PostgresObjectionMigrator-D_QxXbIN.mjs.map +1 -0
  57. package/dist/PostgresObjectionMigrator.cjs +2 -2
  58. package/dist/PostgresObjectionMigrator.d.cts +2 -2
  59. package/dist/PostgresObjectionMigrator.d.mts +2 -2
  60. package/dist/PostgresObjectionMigrator.mjs +2 -2
  61. package/dist/{VitestKyselyTransactionIsolator-D3EZZhjZ.d.cts → VitestKyselyTransactionIsolator-CduJlHoT.d.cts} +4 -3
  62. package/dist/VitestKyselyTransactionIsolator-CduJlHoT.d.cts.map +1 -0
  63. package/dist/{VitestKyselyTransactionIsolator-Dxlp1u0f.d.mts → VitestKyselyTransactionIsolator-Cswnnj0k.d.mts} +4 -3
  64. package/dist/VitestKyselyTransactionIsolator-Cswnnj0k.d.mts.map +1 -0
  65. package/dist/{VitestKyselyTransactionIsolator-EvDLk5zg.cjs → VitestKyselyTransactionIsolator-D7RRXOBa.cjs} +2 -2
  66. package/dist/VitestKyselyTransactionIsolator-D7RRXOBa.cjs.map +1 -0
  67. package/dist/{VitestKyselyTransactionIsolator-CNURW8y6.mjs → VitestKyselyTransactionIsolator-DceyIqr4.mjs} +2 -2
  68. package/dist/VitestKyselyTransactionIsolator-DceyIqr4.mjs.map +1 -0
  69. package/dist/VitestKyselyTransactionIsolator.cjs +1 -1
  70. package/dist/VitestKyselyTransactionIsolator.d.cts +2 -2
  71. package/dist/VitestKyselyTransactionIsolator.d.mts +2 -2
  72. package/dist/VitestKyselyTransactionIsolator.mjs +1 -1
  73. package/dist/{VitestObjectionTransactionIsolator-1TpsPqfG.d.cts → VitestObjectionTransactionIsolator-BXoR6xdG.d.cts} +4 -3
  74. package/dist/VitestObjectionTransactionIsolator-BXoR6xdG.d.cts.map +1 -0
  75. package/dist/{VitestObjectionTransactionIsolator-CM5KTAFA.cjs → VitestObjectionTransactionIsolator-CdLRrzNf.cjs} +2 -2
  76. package/dist/VitestObjectionTransactionIsolator-CdLRrzNf.cjs.map +1 -0
  77. package/dist/{VitestObjectionTransactionIsolator-jQFaCz0u.mjs → VitestObjectionTransactionIsolator-OF2osYY5.mjs} +2 -2
  78. package/dist/VitestObjectionTransactionIsolator-OF2osYY5.mjs.map +1 -0
  79. package/dist/{VitestObjectionTransactionIsolator-i9jIgU8Q.d.mts → VitestObjectionTransactionIsolator-x6hY5j4u.d.mts} +4 -3
  80. package/dist/VitestObjectionTransactionIsolator-x6hY5j4u.d.mts.map +1 -0
  81. package/dist/VitestObjectionTransactionIsolator.cjs +1 -1
  82. package/dist/VitestObjectionTransactionIsolator.d.cts +2 -2
  83. package/dist/VitestObjectionTransactionIsolator.d.mts +2 -2
  84. package/dist/VitestObjectionTransactionIsolator.mjs +1 -1
  85. package/dist/{VitestTransactionIsolator-BvR19bYn.d.mts → VitestTransactionIsolator-BNWJqh9f.d.mts} +3 -2
  86. package/dist/VitestTransactionIsolator-BNWJqh9f.d.mts.map +1 -0
  87. package/dist/VitestTransactionIsolator-CMfJXZP8.cjs.map +1 -1
  88. package/dist/{VitestTransactionIsolator-CwQaxZLP.d.cts → VitestTransactionIsolator-CSroc7Df.d.cts} +3 -2
  89. package/dist/VitestTransactionIsolator-CSroc7Df.d.cts.map +1 -0
  90. package/dist/VitestTransactionIsolator-DQ7tLqgV.mjs.map +1 -1
  91. package/dist/VitestTransactionIsolator.d.cts +1 -1
  92. package/dist/VitestTransactionIsolator.d.mts +1 -1
  93. package/dist/aws.cjs.map +1 -1
  94. package/dist/aws.d.cts +2 -0
  95. package/dist/aws.d.cts.map +1 -0
  96. package/dist/aws.d.mts +2 -0
  97. package/dist/aws.d.mts.map +1 -0
  98. package/dist/aws.mjs.map +1 -1
  99. package/dist/benchmark.cjs.map +1 -1
  100. package/dist/benchmark.d.cts +1 -0
  101. package/dist/benchmark.d.cts.map +1 -0
  102. package/dist/benchmark.d.mts +1 -0
  103. package/dist/benchmark.d.mts.map +1 -0
  104. package/dist/benchmark.mjs.map +1 -1
  105. package/dist/better-auth.cjs +29 -30
  106. package/dist/better-auth.cjs.map +1 -1
  107. package/dist/better-auth.d.cts +2 -2
  108. package/dist/better-auth.d.cts.map +1 -0
  109. package/dist/better-auth.d.mts.map +1 -0
  110. package/dist/better-auth.mjs +29 -30
  111. package/dist/better-auth.mjs.map +1 -1
  112. package/dist/directory-B-Ozljzk.mjs.map +1 -1
  113. package/dist/directory-BVC8g7cX.cjs.map +1 -1
  114. package/dist/{directory-BXavAeJZ.d.mts → directory-CVrfTq1I.d.mts} +2 -1
  115. package/dist/directory-CVrfTq1I.d.mts.map +1 -0
  116. package/dist/directory-Cys9g76X.d.cts +13 -0
  117. package/dist/directory-Cys9g76X.d.cts.map +1 -0
  118. package/dist/faker-B14IEMIN.cjs.map +1 -1
  119. package/dist/faker-BGKYFoCT.mjs.map +1 -1
  120. package/dist/{faker-DvxiCtxc.d.cts → faker-BSH1EMtg.d.cts} +3 -3
  121. package/dist/faker-BSH1EMtg.d.cts.map +1 -0
  122. package/dist/faker-DHh7xs4u.d.mts.map +1 -0
  123. package/dist/faker.d.cts +1 -1
  124. package/dist/helpers.cjs.map +1 -1
  125. package/dist/helpers.d.cts +1 -0
  126. package/dist/helpers.d.cts.map +1 -0
  127. package/dist/helpers.d.mts +1 -0
  128. package/dist/helpers.d.mts.map +1 -0
  129. package/dist/helpers.mjs.map +1 -1
  130. package/dist/kysely.cjs +3 -3
  131. package/dist/kysely.cjs.map +1 -1
  132. package/dist/kysely.d.cts +8 -7
  133. package/dist/kysely.d.cts.map +1 -0
  134. package/dist/kysely.d.mts +7 -6
  135. package/dist/kysely.d.mts.map +1 -0
  136. package/dist/kysely.mjs +3 -3
  137. package/dist/kysely.mjs.map +1 -1
  138. package/dist/logger.cjs.map +1 -1
  139. package/dist/logger.d.cts +1 -0
  140. package/dist/logger.d.cts.map +1 -0
  141. package/dist/logger.d.mts +1 -0
  142. package/dist/logger.d.mts.map +1 -0
  143. package/dist/logger.mjs.map +1 -1
  144. package/dist/objection.cjs +3 -3
  145. package/dist/objection.cjs.map +1 -1
  146. package/dist/objection.d.cts +8 -7
  147. package/dist/objection.d.cts.map +1 -0
  148. package/dist/objection.d.mts +7 -6
  149. package/dist/objection.d.mts.map +1 -0
  150. package/dist/objection.mjs +3 -3
  151. package/dist/objection.mjs.map +1 -1
  152. package/dist/os/directory.d.cts +1 -1
  153. package/dist/os/directory.d.mts +1 -1
  154. package/dist/os/index.d.cts +1 -1
  155. package/dist/os/index.d.mts +1 -1
  156. package/dist/timer.cjs.map +1 -1
  157. package/dist/timer.d.cts +2 -0
  158. package/dist/timer.d.cts.map +1 -0
  159. package/dist/timer.d.mts +2 -0
  160. package/dist/timer.d.mts.map +1 -0
  161. package/dist/timer.mjs.map +1 -1
  162. package/package.json +5 -5
  163. package/src/Factory.ts +72 -72
  164. package/src/KyselyFactory.ts +330 -330
  165. package/src/ObjectionFactory.ts +354 -355
  166. package/src/PostgresKyselyMigrator.ts +37 -37
  167. package/src/PostgresMigrator.ts +107 -107
  168. package/src/PostgresObjectionMigrator.ts +91 -91
  169. package/src/VitestKyselyTransactionIsolator.ts +27 -27
  170. package/src/VitestObjectionTransactionIsolator.ts +39 -39
  171. package/src/VitestTransactionIsolator.ts +196 -195
  172. package/src/__tests__/Factory.spec.ts +163 -155
  173. package/src/__tests__/KyselyFactory.spec.ts +443 -439
  174. package/src/__tests__/ObjectionFactory.spec.ts +563 -557
  175. package/src/__tests__/PostgresKyselyMigrator.spec.ts +641 -641
  176. package/src/__tests__/PostgresMigrator.spec.ts +341 -341
  177. package/src/__tests__/PostgresObjectionMigrator.spec.ts +578 -578
  178. package/src/__tests__/VitestObjectionTransactionIsolator.spec.ts +114 -114
  179. package/src/__tests__/benchmark.spec.ts +140 -0
  180. package/src/__tests__/better-auth.spec.ts +15 -15
  181. package/src/__tests__/faker.spec.ts +226 -137
  182. package/src/__tests__/integration.spec.ts +597 -597
  183. package/src/__tests__/utilities.spec.ts +211 -0
  184. package/src/aws.ts +104 -104
  185. package/src/benchmark.ts +12 -12
  186. package/src/better-auth.ts +286 -301
  187. package/src/faker.ts +153 -153
  188. package/src/helpers.ts +6 -6
  189. package/src/kysely.ts +33 -33
  190. package/src/logger.ts +10 -10
  191. package/src/objection.ts +31 -31
  192. package/src/os/directory.ts +11 -10
  193. package/src/timer.ts +1 -1
  194. package/test/globalSetup.ts +45 -45
  195. package/test/helpers.ts +189 -189
  196. package/test/migrations/1749664623372_user.ts +13 -13
  197. package/tsconfig.json +9 -0
  198. package/vitest.config.ts +4 -4
  199. package/dist/PostgresKyselyMigrator-CfytARcA.cjs.map +0 -1
  200. package/dist/PostgresKyselyMigrator-upT-hmrz.mjs.map +0 -1
  201. package/dist/PostgresMigrator-DFcNdCvD.cjs.map +0 -1
  202. package/dist/PostgresMigrator-DbuJGAVy.mjs.map +0 -1
  203. package/dist/PostgresObjectionMigrator-BG6ymgnt.cjs.map +0 -1
  204. package/dist/PostgresObjectionMigrator-DPj2pOpX.mjs.map +0 -1
  205. package/dist/VitestKyselyTransactionIsolator-CNURW8y6.mjs.map +0 -1
  206. package/dist/VitestKyselyTransactionIsolator-EvDLk5zg.cjs.map +0 -1
  207. package/dist/VitestObjectionTransactionIsolator-CM5KTAFA.cjs.map +0 -1
  208. package/dist/VitestObjectionTransactionIsolator-jQFaCz0u.mjs.map +0 -1
  209. package/dist/directory-Mi7tdOuD.d.cts +0 -12
@@ -2,579 +2,585 @@ import type { Knex } from 'knex';
2
2
  import { Model } from 'objection';
3
3
  import { describe, expect, test } from 'vitest';
4
4
  import { createKnexDb, createTestTablesKnex } from '../../test/helpers';
5
- import { ObjectionFactory } from '../ObjectionFactory';
6
5
  import { faker } from '../faker';
6
+ import { ObjectionFactory } from '../ObjectionFactory';
7
7
  import { wrapVitestObjectionTransaction } from '../objection';
8
8
 
9
9
  // Define simple Objection models for testing
10
10
  class User extends Model {
11
- static get tableName() {
12
- return 'users';
13
- }
11
+ static get tableName() {
12
+ return 'users';
13
+ }
14
14
 
15
- id!: string;
16
- name!: string;
15
+ id!: string;
16
+ name!: string;
17
17
  }
18
18
 
19
19
  class Post extends Model {
20
- static get tableName() {
21
- return 'posts';
22
- }
20
+ static get tableName() {
21
+ return 'posts';
22
+ }
23
23
 
24
- id!: string;
25
- title!: string;
26
- user_id!: string;
24
+ id!: string;
25
+ title!: string;
26
+ user_id!: string;
27
27
  }
28
28
 
29
29
  class Comment extends Model {
30
- static get tableName() {
31
- return 'comments';
32
- }
33
-
34
- id!: string;
35
- content!: string;
36
- post_id!: string;
37
- user_id!: string;
30
+ static get tableName() {
31
+ return 'comments';
32
+ }
33
+
34
+ id!: string;
35
+ content!: string;
36
+ post_id!: string;
37
+ user_id!: string;
38
38
  }
39
39
 
40
40
  const it = wrapVitestObjectionTransaction(test, {
41
- connection: createKnexDb,
42
- setup: createTestTablesKnex,
41
+ connection: createKnexDb,
42
+ setup: createTestTablesKnex,
43
43
  });
44
44
  describe('ObjectionFactory', () => {
45
- it('should create an ObjectionFactory instance', ({ trx }) => {
46
- const builders = {};
47
- const seeds = {};
48
-
49
- const factory = new ObjectionFactory(builders, seeds, trx);
50
-
51
- expect(factory).toBeInstanceOf(ObjectionFactory);
52
- });
53
-
54
- it('should call builder and insert the record', async ({ trx }) => {
55
- const userBuilder = async (attrs: any, factory: any, db: Knex) => {
56
- return User.fromJson({
57
- name: attrs.name || 'Default Name',
58
- });
59
- };
60
-
61
- const builders = {
62
- user: userBuilder,
63
- };
64
-
65
- const factory = new ObjectionFactory(builders, {}, trx);
66
-
67
- const attrs = { name: 'John Doe', email: 'john@example.com' };
68
- const result = await factory.insert('user', attrs);
69
-
70
- expect(result).toBeInstanceOf(User);
71
- expect(result.name).toBe('John Doe');
72
- expect(result.id).toBeDefined();
73
- });
74
-
75
- it('should use empty object as default attributes', async ({ trx }) => {
76
- const userBuilder = async (attrs: any, factory: any, db: Knex) => {
77
- return User.fromJson({
78
- name: 'Default Name',
79
- });
80
- };
81
-
82
- const builders = {
83
- user: userBuilder,
84
- };
85
-
86
- const factory = new ObjectionFactory(builders, {}, trx);
87
-
88
- const result = await factory.insert('user');
89
-
90
- expect(result).toBeInstanceOf(User);
91
- expect(result.name).toBe('Default Name');
92
- expect(result.id).toBeDefined();
93
- });
94
-
95
- it('should throw error for non-existent factory', async ({ trx }) => {
96
- const factory = new ObjectionFactory({}, {}, trx);
97
- // @ts-ignore
98
- await expect(factory.insert('nonExistent')).rejects.toThrow(
99
- 'Factory "nonExistent" does not exist',
100
- );
101
- });
102
-
103
- it('should handle builder that returns a promise', async ({ trx }) => {
104
- const userBuilder = async (attrs: any, factory: any, db: Knex) => {
105
- // Simulate async operation
106
- await new Promise((resolve) => setTimeout(resolve, 10));
107
- return User.fromJson({
108
- name: attrs.name || 'Default Name',
109
- });
110
- };
111
-
112
- const builders = {
113
- user: userBuilder,
114
- };
115
-
116
- const factory = new ObjectionFactory(builders, {}, trx);
117
-
118
- const result = await factory.insert('user', { name: 'Jane' });
119
-
120
- expect(result).toBeInstanceOf(User);
121
- expect(result.name).toBe('Jane');
122
- });
123
-
124
- it('should insert multiple records with same attributes', async ({ trx }) => {
125
- const userBuilder = async (attrs: any, factory: any, db: Knex) => {
126
- return User.fromJson({
127
- name: attrs.name || 'Default Name',
128
- });
129
- };
130
-
131
- const builders = {
132
- user: userBuilder,
133
- };
134
-
135
- const factory = new ObjectionFactory(builders, {}, trx);
136
-
137
- const attrs = { name: 'User' };
138
- const results = await factory.insertMany(3, 'user', attrs);
139
-
140
- expect(results).toHaveLength(3);
141
- results.forEach((result) => {
142
- expect(result).toBeInstanceOf(User);
143
- expect(result.name).toBe('User');
144
- expect(result.id).toBeDefined();
145
- });
146
- });
147
-
148
- it('should insert multiple records with dynamic attributes', async ({
149
- trx,
150
- }) => {
151
- const userBuilder = async (attrs: any, factory: any, db: Knex) => {
152
- return User.fromJson({
153
- name: attrs.name || 'Default Name',
154
- });
155
- };
156
-
157
- const builders = {
158
- user: userBuilder,
159
- };
160
-
161
- const factory = new ObjectionFactory(builders, {}, trx);
162
-
163
- const attrsFn = (idx: number) => ({ name: `User ${idx}` });
164
- const results = await factory.insertMany(2, 'user', attrsFn);
165
-
166
- expect(results).toHaveLength(2);
167
- expect(results[0].name).toBe('User 0');
168
- expect(results[1].name).toBe('User 1');
169
- results.forEach((result) => {
170
- expect(result).toBeInstanceOf(User);
171
- expect(result.id).toBeDefined();
172
- });
173
- });
174
-
175
- it('should use empty object as default attributes for insertMany', async ({
176
- trx,
177
- }) => {
178
- const userBuilder = async (attrs: any, factory: any, db: Knex) => {
179
- return User.fromJson({
180
- name: 'Default Name',
181
- });
182
- };
183
-
184
- const builders = {
185
- user: userBuilder,
186
- };
187
-
188
- const factory = new ObjectionFactory(builders, {}, trx);
189
-
190
- const results = await factory.insertMany(2, 'user');
191
-
192
- expect(results).toHaveLength(2);
193
- results.forEach((result) => {
194
- expect(result).toBeInstanceOf(User);
195
- expect(result.name).toBe('Default Name');
196
- expect(result.id).toBeDefined();
197
- });
198
- });
199
-
200
- it('should throw error for non-existent builder in insertMany', async ({
201
- trx,
202
- }) => {
203
- const factory = new ObjectionFactory({}, {}, trx);
204
- // @ts-ignore
205
- await expect(factory.insertMany(2, 'nonExistent')).rejects.toThrow(
206
- 'Builder "nonExistent" is not registered',
207
- );
208
- });
209
-
210
- it('should execute seed function', async ({ trx }) => {
211
- const userBuilder = async (attrs: any, factory: any, db: Knex) => {
212
- return User.fromJson({
213
- name: attrs.name || 'Default Name',
214
- });
215
- };
216
-
217
- const builders = { user: userBuilder };
218
-
219
- const seeds = {
220
- createAdmin: ObjectionFactory.createSeed(
221
- async ({
222
- attrs,
223
- factory,
224
- }: { attrs: { name?: string }; factory: any; db: Knex }) => {
225
- return await factory.insert('user', {
226
- name: attrs.name || 'Admin User',
227
- });
228
- },
229
- ),
230
- };
231
-
232
- const factory = new ObjectionFactory(builders, seeds, trx);
233
-
234
- const result = await factory.seed('createAdmin', { name: 'Super Admin' });
235
-
236
- expect(result).toBeInstanceOf(User);
237
- expect(result.name).toBe('Super Admin');
238
- expect(result.id).toBeDefined();
239
- });
240
-
241
- it('should use empty object as default attributes for seed', async ({
242
- trx,
243
- }) => {
244
- const userBuilder = async (attrs: any, factory: any, db: Knex) => {
245
- return User.fromJson({
246
- name: 'Default Admin',
247
- });
248
- };
249
-
250
- const builders = { user: userBuilder };
251
-
252
- const seeds = {
253
- createAdmin: ObjectionFactory.createSeed(
254
- async ({ factory }: { attrs: any; factory: any; db: Knex }) => {
255
- return await factory.insert('user', {
256
- name: 'Default Admin',
257
- role: 'admin',
258
- });
259
- },
260
- ),
261
- };
262
-
263
- const factory = new ObjectionFactory(builders, seeds, trx);
264
-
265
- const result = await factory.seed('createAdmin');
266
-
267
- expect(result).toBeInstanceOf(User);
268
- expect(result.name).toBe('Default Admin');
269
- });
270
-
271
- it('should throw error for non-existent seed', ({ trx }) => {
272
- const factory = new ObjectionFactory({}, {}, trx);
273
- // @ts-ignore
274
- expect(() => factory.seed('nonExistent')).toThrow(
275
- 'Seed "nonExistent" is not registered',
276
- );
277
- });
278
-
279
- it('should pass factory and db to seed function', async ({ trx }) => {
280
- const userBuilder = async (attrs: any, factory: any, db: Knex) => {
281
- return User.fromJson({
282
- name: attrs.name || 'Test User',
283
- });
284
- };
285
-
286
- const builders = { user: userBuilder };
287
-
288
- let factoryRef: any;
289
-
290
- const seeds = {
291
- complexSeed: ObjectionFactory.createSeed(
292
- async ({
293
- attrs,
294
- factory: passedFactory,
295
- db: passedDb,
296
- }: { attrs: { data: string }; factory: any; db: Knex }) => {
297
- // Verify that factory and db are passed correctly
298
- expect(passedFactory).toBe(factoryRef);
299
- expect(passedDb).toBe(trx);
300
-
301
- return await passedFactory.insert('user', {
302
- name: `Complex ${attrs.data}`,
303
- });
304
- },
305
- ),
306
- };
307
-
308
- const factory = new ObjectionFactory(builders, seeds, trx);
309
- factoryRef = factory;
310
-
311
- const result = await factory.seed('complexSeed', { data: 'test' });
312
-
313
- expect(result).toBeInstanceOf(User);
314
- expect(result.name).toBe('Complex test');
315
- });
316
-
317
- it('should return the seed function unchanged', () => {
318
- const seedFn = async ({ attrs }: { attrs: any; factory: any; db: any }) => {
319
- return { id: 1, name: 'test' };
320
- };
321
-
322
- const result = ObjectionFactory.createSeed(seedFn);
323
-
324
- expect(result).toBe(seedFn);
325
- });
326
-
327
- it('should create a builder function with auto-insert', async ({ trx }) => {
328
- const userBuilder = ObjectionFactory.createBuilder(
329
- User,
330
- ({ attrs, faker }) => ({
331
- name: faker.person.fullName(),
332
- ...attrs,
333
- }),
334
- );
335
-
336
- const builders = { user: userBuilder };
337
- const factory = new ObjectionFactory(builders, {}, trx);
338
-
339
- const result = await factory.insert('user', { name: 'Test User' });
340
-
341
- expect(result).toBeInstanceOf(User);
342
- expect(result.name).toBe('Test User');
343
- expect(result.id).toBeDefined();
344
- });
345
-
346
- it('should create a builder function without auto-insert', async ({
347
- trx,
348
- }) => {
349
- const userBuilder = ObjectionFactory.createBuilder(
350
- User,
351
- ({ attrs }) => ({
352
- name: 'No Insert User',
353
- ...attrs,
354
- }),
355
- false, // Don't auto-insert
356
- );
357
-
358
- const builders = { user: userBuilder };
359
- const factory = new ObjectionFactory(builders, {}, trx);
360
-
361
- const result = await factory.insert('user');
362
-
363
- // The factory's insert method should handle the insertion
364
- expect(result).toBeInstanceOf(User);
365
- expect(result.name).toBe('No Insert User');
366
- expect(result.id).toBeDefined();
367
- });
368
-
369
- it('should pass all parameters to the item function', async ({ trx }) => {
370
- let capturedFactory: any;
371
- let capturedDb: any;
372
- let capturedFaker: any;
373
-
374
- const userBuilder = ObjectionFactory.createBuilder(
375
- User,
376
- ({ attrs, factory: passedFactory, db, faker: fakerInstance }) => {
377
- capturedFactory = passedFactory;
378
- capturedDb = db;
379
- capturedFaker = fakerInstance;
380
-
381
- return {
382
- name: 'Test User',
383
- ...attrs,
384
- };
385
- },
386
- );
387
-
388
- const builders = { user: userBuilder };
389
- const factory = new ObjectionFactory(builders, {}, trx);
390
-
391
- await factory.insert('user');
392
-
393
- expect(capturedFactory).toBe(factory);
394
- expect(capturedDb).toBe(trx);
395
- expect(capturedFaker).toBe(faker);
396
- });
397
-
398
- it('should handle async item functions', async ({ trx }) => {
399
- const userBuilder = ObjectionFactory.createBuilder(
400
- User,
401
- async ({ attrs }) => {
402
- // Simulate async operation
403
- await new Promise((resolve) => setTimeout(resolve, 10));
404
-
405
- return {
406
- name: 'Async User',
407
- ...attrs,
408
- };
409
- },
410
- );
411
-
412
- const builders = { user: userBuilder };
413
- const factory = new ObjectionFactory(builders, {}, trx);
414
-
415
- const result = await factory.insert('user');
416
-
417
- expect(result).toBeInstanceOf(User);
418
- expect(result.name).toBe('Async User');
419
- expect(result.id).toBeDefined();
420
- });
421
-
422
- it('should work without item function', async ({ trx }) => {
423
- const userBuilder = ObjectionFactory.createBuilder(User);
424
-
425
- const builders = { user: userBuilder };
426
- const factory = new ObjectionFactory(builders, {}, trx);
427
-
428
- const attrs = {
429
- name: 'Manual User',
430
- };
431
-
432
- const result = await factory.insert('user', attrs);
433
-
434
- expect(result).toBeInstanceOf(User);
435
- expect(result.name).toBe('Manual User');
436
- expect(result.id).toBeDefined();
437
- });
438
-
439
- it('should allow overriding default values', async ({ trx }) => {
440
- const userBuilder = ObjectionFactory.createBuilder(User, ({ attrs }) => ({
441
- name: 'Default Name',
442
- ...attrs,
443
- }));
444
-
445
- const builders = { user: userBuilder };
446
- const factory = new ObjectionFactory(builders, {}, trx);
447
-
448
- const result = await factory.insert('user', {
449
- name: 'Override Name',
450
- });
451
-
452
- expect(result).toBeInstanceOf(User);
453
- expect(result.name).toBe('Override Name');
454
- });
455
-
456
- it('should handle builder errors gracefully', async ({ trx }) => {
457
- const userBuilder = async (attrs: any, factory: any, db: Knex) => {
458
- throw new Error('Builder failed');
459
- };
460
-
461
- const builders = {
462
- user: userBuilder,
463
- };
464
-
465
- const factory = new ObjectionFactory(builders, {}, trx);
466
-
467
- await expect(factory.insert('user')).rejects.toThrow('Builder failed');
468
- });
469
-
470
- it('should handle invalid model data gracefully', async ({ trx }) => {
471
- const userBuilder = async (attrs: any, factory: any, db: Knex) => {
472
- // Return invalid model data that will fail validation
473
- return User.fromJson({
474
- // Missing required fields
475
- invalidField: 'invalid',
476
- } as any);
477
- };
478
-
479
- const builders = {
480
- user: userBuilder,
481
- };
482
-
483
- const factory = new ObjectionFactory(builders, {}, trx);
484
-
485
- await expect(factory.insert('user')).rejects.toThrow();
486
- });
487
-
488
- it('should handle seed function errors gracefully', async ({ trx }) => {
489
- const seeds = {
490
- failingSeed: ObjectionFactory.createSeed(
491
- async ({}: { attrs: any; factory: any; db: Knex }) => {
492
- throw new Error('Seed failed');
493
- },
494
- ),
495
- };
496
-
497
- const factory = new ObjectionFactory({}, seeds, trx);
498
-
499
- await expect(factory.seed('failingSeed')).rejects.toThrow('Seed failed');
500
- });
501
-
502
- it('should work with typed builders and seeds', async ({ trx }) => {
503
- interface UserInterface {
504
- id: string;
505
- name: string;
506
- }
507
-
508
- type UserAttrs = Partial<Pick<UserInterface, 'name'>>;
509
-
510
- const userBuilder = async (attrs: UserAttrs, factory: any, db: Knex) => {
511
- return User.fromJson({
512
- name: attrs.name || 'Default User',
513
- });
514
- };
515
-
516
- const builders = { user: userBuilder };
517
- const seeds = {
518
- admin: ObjectionFactory.createSeed(
519
- async ({
520
- factory,
521
- }: {
522
- attrs: { isSuper?: boolean };
523
- factory: any;
524
- db: Knex;
525
- }) => {
526
- return factory.insert('user', {
527
- name: 'Admin',
528
- });
529
- },
530
- ),
531
- };
532
-
533
- // This should compile without type errors
534
- const factory = new ObjectionFactory(builders, seeds, trx);
535
-
536
- expect(factory).toBeInstanceOf(ObjectionFactory);
537
-
538
- // Test actual functionality
539
- const admin = await factory.seed('admin', { isSuper: true });
540
- expect(admin).toBeInstanceOf(User);
541
- expect(admin.name).toBe('Admin');
542
- });
543
-
544
- it('should handle complex builder scenarios', async ({ trx }) => {
545
- const userBuilder = async (attrs: any, factory: any, db: Knex) => {
546
- return User.fromJson({
547
- name: attrs.name || 'Default User',
548
- });
549
- };
550
-
551
- const postBuilder = async (attrs: any, factory: any, db: Knex) => {
552
- // If no user_id provided, create a user
553
- if (!attrs.user_id) {
554
- const user = await factory.insert('user');
555
- return Post.fromJson({
556
- title: attrs.title || 'Default Post',
557
- user_id: user.id,
558
- });
559
- }
560
- return Post.fromJson({
561
- title: attrs.title || 'Default Post',
562
- user_id: attrs.user_id,
563
- });
564
- };
565
-
566
- const builders = {
567
- user: userBuilder,
568
- post: postBuilder,
569
- };
570
-
571
- const factory = new ObjectionFactory(builders, {}, trx);
572
-
573
- const post = await factory.insert('post', { title: 'Test Post' });
574
-
575
- expect(post).toBeInstanceOf(Post);
576
- expect(post.title).toBe('Test Post');
577
- expect(post.user_id).toBeDefined();
578
- expect(typeof post.user_id).toBe('string'); // PostgreSQL returns bigint as string
579
- });
45
+ it('should create an ObjectionFactory instance', ({ trx }) => {
46
+ const builders = {};
47
+ const seeds = {};
48
+
49
+ const factory = new ObjectionFactory(builders, seeds, trx);
50
+
51
+ expect(factory).toBeInstanceOf(ObjectionFactory);
52
+ });
53
+
54
+ it('should call builder and insert the record', async ({ trx }) => {
55
+ const userBuilder = async (attrs: any, _factory: any, _db: Knex) => {
56
+ return User.fromJson({
57
+ name: attrs.name || 'Default Name',
58
+ });
59
+ };
60
+
61
+ const builders = {
62
+ user: userBuilder,
63
+ };
64
+
65
+ const factory = new ObjectionFactory(builders, {}, trx);
66
+
67
+ const attrs = { name: 'John Doe', email: 'john@example.com' };
68
+ const result = await factory.insert('user', attrs);
69
+
70
+ expect(result).toBeInstanceOf(User);
71
+ expect(result.name).toBe('John Doe');
72
+ expect(result.id).toBeDefined();
73
+ });
74
+
75
+ it('should use empty object as default attributes', async ({ trx }) => {
76
+ const userBuilder = async (_attrs: any, _factory: any, _db: Knex) => {
77
+ return User.fromJson({
78
+ name: 'Default Name',
79
+ });
80
+ };
81
+
82
+ const builders = {
83
+ user: userBuilder,
84
+ };
85
+
86
+ const factory = new ObjectionFactory(builders, {}, trx);
87
+
88
+ const result = await factory.insert('user');
89
+
90
+ expect(result).toBeInstanceOf(User);
91
+ expect(result.name).toBe('Default Name');
92
+ expect(result.id).toBeDefined();
93
+ });
94
+
95
+ it('should throw error for non-existent factory', async ({ trx }) => {
96
+ const factory = new ObjectionFactory({}, {}, trx);
97
+ // @ts-expect-error
98
+ await expect(factory.insert('nonExistent')).rejects.toThrow(
99
+ 'Factory "nonExistent" does not exist',
100
+ );
101
+ });
102
+
103
+ it('should handle builder that returns a promise', async ({ trx }) => {
104
+ const userBuilder = async (attrs: any, _factory: any, _db: Knex) => {
105
+ // Simulate async operation
106
+ await new Promise((resolve) => setTimeout(resolve, 10));
107
+ return User.fromJson({
108
+ name: attrs.name || 'Default Name',
109
+ });
110
+ };
111
+
112
+ const builders = {
113
+ user: userBuilder,
114
+ };
115
+
116
+ const factory = new ObjectionFactory(builders, {}, trx);
117
+
118
+ const result = await factory.insert('user', { name: 'Jane' });
119
+
120
+ expect(result).toBeInstanceOf(User);
121
+ expect(result.name).toBe('Jane');
122
+ });
123
+
124
+ it('should insert multiple records with same attributes', async ({ trx }) => {
125
+ const userBuilder = async (attrs: any, _factory: any, _db: Knex) => {
126
+ return User.fromJson({
127
+ name: attrs.name || 'Default Name',
128
+ });
129
+ };
130
+
131
+ const builders = {
132
+ user: userBuilder,
133
+ };
134
+
135
+ const factory = new ObjectionFactory(builders, {}, trx);
136
+
137
+ const attrs = { name: 'User' };
138
+ const results = await factory.insertMany(3, 'user', attrs);
139
+
140
+ expect(results).toHaveLength(3);
141
+ results.forEach((result) => {
142
+ expect(result).toBeInstanceOf(User);
143
+ expect(result.name).toBe('User');
144
+ expect(result.id).toBeDefined();
145
+ });
146
+ });
147
+
148
+ it('should insert multiple records with dynamic attributes', async ({
149
+ trx,
150
+ }) => {
151
+ const userBuilder = async (attrs: any, _factory: any, _db: Knex) => {
152
+ return User.fromJson({
153
+ name: attrs.name || 'Default Name',
154
+ });
155
+ };
156
+
157
+ const builders = {
158
+ user: userBuilder,
159
+ };
160
+
161
+ const factory = new ObjectionFactory(builders, {}, trx);
162
+
163
+ const attrsFn = (idx: number) => ({ name: `User ${idx}` });
164
+ const results = await factory.insertMany(2, 'user', attrsFn);
165
+
166
+ expect(results).toHaveLength(2);
167
+ expect(results[0].name).toBe('User 0');
168
+ expect(results[1].name).toBe('User 1');
169
+ results.forEach((result) => {
170
+ expect(result).toBeInstanceOf(User);
171
+ expect(result.id).toBeDefined();
172
+ });
173
+ });
174
+
175
+ it('should use empty object as default attributes for insertMany', async ({
176
+ trx,
177
+ }) => {
178
+ const userBuilder = async (_attrs: any, _factory: any, _db: Knex) => {
179
+ return User.fromJson({
180
+ name: 'Default Name',
181
+ });
182
+ };
183
+
184
+ const builders = {
185
+ user: userBuilder,
186
+ };
187
+
188
+ const factory = new ObjectionFactory(builders, {}, trx);
189
+
190
+ const results = await factory.insertMany(2, 'user');
191
+
192
+ expect(results).toHaveLength(2);
193
+ results.forEach((result) => {
194
+ expect(result).toBeInstanceOf(User);
195
+ expect(result.name).toBe('Default Name');
196
+ expect(result.id).toBeDefined();
197
+ });
198
+ });
199
+
200
+ it('should throw error for non-existent builder in insertMany', async ({
201
+ trx,
202
+ }) => {
203
+ const factory = new ObjectionFactory({}, {}, trx);
204
+ // @ts-expect-error
205
+ await expect(factory.insertMany(2, 'nonExistent')).rejects.toThrow(
206
+ 'Builder "nonExistent" is not registered',
207
+ );
208
+ });
209
+
210
+ it('should execute seed function', async ({ trx }) => {
211
+ const userBuilder = async (attrs: any, _factory: any, _db: Knex) => {
212
+ return User.fromJson({
213
+ name: attrs.name || 'Default Name',
214
+ });
215
+ };
216
+
217
+ const builders = { user: userBuilder };
218
+
219
+ const seeds = {
220
+ createAdmin: ObjectionFactory.createSeed(
221
+ async ({
222
+ attrs,
223
+ factory,
224
+ }: {
225
+ attrs: { name?: string };
226
+ factory: any;
227
+ db: Knex;
228
+ }) => {
229
+ return await factory.insert('user', {
230
+ name: attrs.name || 'Admin User',
231
+ });
232
+ },
233
+ ),
234
+ };
235
+
236
+ const factory = new ObjectionFactory(builders, seeds, trx);
237
+
238
+ const result = await factory.seed('createAdmin', { name: 'Super Admin' });
239
+
240
+ expect(result).toBeInstanceOf(User);
241
+ expect(result.name).toBe('Super Admin');
242
+ expect(result.id).toBeDefined();
243
+ });
244
+
245
+ it('should use empty object as default attributes for seed', async ({
246
+ trx,
247
+ }) => {
248
+ const userBuilder = async (_attrs: any, _factory: any, _db: Knex) => {
249
+ return User.fromJson({
250
+ name: 'Default Admin',
251
+ });
252
+ };
253
+
254
+ const builders = { user: userBuilder };
255
+
256
+ const seeds = {
257
+ createAdmin: ObjectionFactory.createSeed(
258
+ async ({ factory }: { attrs: any; factory: any; db: Knex }) => {
259
+ return await factory.insert('user', {
260
+ name: 'Default Admin',
261
+ role: 'admin',
262
+ });
263
+ },
264
+ ),
265
+ };
266
+
267
+ const factory = new ObjectionFactory(builders, seeds, trx);
268
+
269
+ const result = await factory.seed('createAdmin');
270
+
271
+ expect(result).toBeInstanceOf(User);
272
+ expect(result.name).toBe('Default Admin');
273
+ });
274
+
275
+ it('should throw error for non-existent seed', ({ trx }) => {
276
+ const factory = new ObjectionFactory({}, {}, trx);
277
+ // @ts-expect-error
278
+ expect(() => factory.seed('nonExistent')).toThrow(
279
+ 'Seed "nonExistent" is not registered',
280
+ );
281
+ });
282
+
283
+ it('should pass factory and db to seed function', async ({ trx }) => {
284
+ const userBuilder = async (attrs: any, _factory: any, _db: Knex) => {
285
+ return User.fromJson({
286
+ name: attrs.name || 'Test User',
287
+ });
288
+ };
289
+
290
+ const builders = { user: userBuilder };
291
+
292
+ let factoryRef: any;
293
+
294
+ const seeds = {
295
+ complexSeed: ObjectionFactory.createSeed(
296
+ async ({
297
+ attrs,
298
+ factory: passedFactory,
299
+ db: passedDb,
300
+ }: {
301
+ attrs: { data: string };
302
+ factory: any;
303
+ db: Knex;
304
+ }) => {
305
+ // Verify that factory and db are passed correctly
306
+ expect(passedFactory).toBe(factoryRef);
307
+ expect(passedDb).toBe(trx);
308
+
309
+ return await passedFactory.insert('user', {
310
+ name: `Complex ${attrs.data}`,
311
+ });
312
+ },
313
+ ),
314
+ };
315
+
316
+ const factory = new ObjectionFactory(builders, seeds, trx);
317
+ factoryRef = factory;
318
+
319
+ const result = await factory.seed('complexSeed', { data: 'test' });
320
+
321
+ expect(result).toBeInstanceOf(User);
322
+ expect(result.name).toBe('Complex test');
323
+ });
324
+
325
+ it('should return the seed function unchanged', () => {
326
+ const seedFn = async ({ attrs }: { attrs: any; factory: any; db: any }) => {
327
+ return { id: 1, name: 'test' };
328
+ };
329
+
330
+ const result = ObjectionFactory.createSeed(seedFn);
331
+
332
+ expect(result).toBe(seedFn);
333
+ });
334
+
335
+ it('should create a builder function with auto-insert', async ({ trx }) => {
336
+ const userBuilder = ObjectionFactory.createBuilder(
337
+ User,
338
+ ({ attrs, faker }) => ({
339
+ name: faker.person.fullName(),
340
+ ...attrs,
341
+ }),
342
+ );
343
+
344
+ const builders = { user: userBuilder };
345
+ const factory = new ObjectionFactory(builders, {}, trx);
346
+
347
+ const result = await factory.insert('user', { name: 'Test User' });
348
+
349
+ expect(result).toBeInstanceOf(User);
350
+ expect(result.name).toBe('Test User');
351
+ expect(result.id).toBeDefined();
352
+ });
353
+
354
+ it('should create a builder function without auto-insert', async ({
355
+ trx,
356
+ }) => {
357
+ const userBuilder = ObjectionFactory.createBuilder(
358
+ User,
359
+ ({ attrs }) => ({
360
+ name: 'No Insert User',
361
+ ...attrs,
362
+ }),
363
+ false, // Don't auto-insert
364
+ );
365
+
366
+ const builders = { user: userBuilder };
367
+ const factory = new ObjectionFactory(builders, {}, trx);
368
+
369
+ const result = await factory.insert('user');
370
+
371
+ // The factory's insert method should handle the insertion
372
+ expect(result).toBeInstanceOf(User);
373
+ expect(result.name).toBe('No Insert User');
374
+ expect(result.id).toBeDefined();
375
+ });
376
+
377
+ it('should pass all parameters to the item function', async ({ trx }) => {
378
+ let capturedFactory: any;
379
+ let capturedDb: any;
380
+ let capturedFaker: any;
381
+
382
+ const userBuilder = ObjectionFactory.createBuilder(
383
+ User,
384
+ ({ attrs, factory: passedFactory, db, faker: fakerInstance }) => {
385
+ capturedFactory = passedFactory;
386
+ capturedDb = db;
387
+ capturedFaker = fakerInstance;
388
+
389
+ return {
390
+ name: 'Test User',
391
+ ...attrs,
392
+ };
393
+ },
394
+ );
395
+
396
+ const builders = { user: userBuilder };
397
+ const factory = new ObjectionFactory(builders, {}, trx);
398
+
399
+ await factory.insert('user');
400
+
401
+ expect(capturedFactory).toBe(factory);
402
+ expect(capturedDb).toBe(trx);
403
+ expect(capturedFaker).toBe(faker);
404
+ });
405
+
406
+ it('should handle async item functions', async ({ trx }) => {
407
+ const userBuilder = ObjectionFactory.createBuilder(
408
+ User,
409
+ async ({ attrs }) => {
410
+ // Simulate async operation
411
+ await new Promise((resolve) => setTimeout(resolve, 10));
412
+
413
+ return {
414
+ name: 'Async User',
415
+ ...attrs,
416
+ };
417
+ },
418
+ );
419
+
420
+ const builders = { user: userBuilder };
421
+ const factory = new ObjectionFactory(builders, {}, trx);
422
+
423
+ const result = await factory.insert('user');
424
+
425
+ expect(result).toBeInstanceOf(User);
426
+ expect(result.name).toBe('Async User');
427
+ expect(result.id).toBeDefined();
428
+ });
429
+
430
+ it('should work without item function', async ({ trx }) => {
431
+ const userBuilder = ObjectionFactory.createBuilder(User);
432
+
433
+ const builders = { user: userBuilder };
434
+ const factory = new ObjectionFactory(builders, {}, trx);
435
+
436
+ const attrs = {
437
+ name: 'Manual User',
438
+ };
439
+
440
+ const result = await factory.insert('user', attrs);
441
+
442
+ expect(result).toBeInstanceOf(User);
443
+ expect(result.name).toBe('Manual User');
444
+ expect(result.id).toBeDefined();
445
+ });
446
+
447
+ it('should allow overriding default values', async ({ trx }) => {
448
+ const userBuilder = ObjectionFactory.createBuilder(User, ({ attrs }) => ({
449
+ name: 'Default Name',
450
+ ...attrs,
451
+ }));
452
+
453
+ const builders = { user: userBuilder };
454
+ const factory = new ObjectionFactory(builders, {}, trx);
455
+
456
+ const result = await factory.insert('user', {
457
+ name: 'Override Name',
458
+ });
459
+
460
+ expect(result).toBeInstanceOf(User);
461
+ expect(result.name).toBe('Override Name');
462
+ });
463
+
464
+ it('should handle builder errors gracefully', async ({ trx }) => {
465
+ const userBuilder = async (_attrs: any, _factory: any, _db: Knex) => {
466
+ throw new Error('Builder failed');
467
+ };
468
+
469
+ const builders = {
470
+ user: userBuilder,
471
+ };
472
+
473
+ const factory = new ObjectionFactory(builders, {}, trx);
474
+
475
+ await expect(factory.insert('user')).rejects.toThrow('Builder failed');
476
+ });
477
+
478
+ it('should handle invalid model data gracefully', async ({ trx }) => {
479
+ const userBuilder = async (_attrs: any, _factory: any, _db: Knex) => {
480
+ // Return invalid model data that will fail validation
481
+ return User.fromJson({
482
+ // Missing required fields
483
+ invalidField: 'invalid',
484
+ } as any);
485
+ };
486
+
487
+ const builders = {
488
+ user: userBuilder,
489
+ };
490
+
491
+ const factory = new ObjectionFactory(builders, {}, trx);
492
+
493
+ await expect(factory.insert('user')).rejects.toThrow();
494
+ });
495
+
496
+ it('should handle seed function errors gracefully', async ({ trx }) => {
497
+ const seeds = {
498
+ failingSeed: ObjectionFactory.createSeed(async () => {
499
+ throw new Error('Seed failed');
500
+ }),
501
+ };
502
+
503
+ const factory = new ObjectionFactory({}, seeds, trx);
504
+
505
+ await expect(factory.seed('failingSeed')).rejects.toThrow('Seed failed');
506
+ });
507
+
508
+ it('should work with typed builders and seeds', async ({ trx }) => {
509
+ interface UserInterface {
510
+ id: string;
511
+ name: string;
512
+ }
513
+
514
+ type UserAttrs = Partial<Pick<UserInterface, 'name'>>;
515
+
516
+ const userBuilder = async (attrs: UserAttrs, _factory: any, _db: Knex) => {
517
+ return User.fromJson({
518
+ name: attrs.name || 'Default User',
519
+ });
520
+ };
521
+
522
+ const builders = { user: userBuilder };
523
+ const seeds = {
524
+ admin: ObjectionFactory.createSeed(
525
+ async ({
526
+ factory,
527
+ }: {
528
+ attrs: { isSuper?: boolean };
529
+ factory: any;
530
+ db: Knex;
531
+ }) => {
532
+ return factory.insert('user', {
533
+ name: 'Admin',
534
+ });
535
+ },
536
+ ),
537
+ };
538
+
539
+ // This should compile without type errors
540
+ const factory = new ObjectionFactory(builders, seeds, trx);
541
+
542
+ expect(factory).toBeInstanceOf(ObjectionFactory);
543
+
544
+ // Test actual functionality
545
+ const admin = await factory.seed('admin', { isSuper: true });
546
+ expect(admin).toBeInstanceOf(User);
547
+ expect(admin.name).toBe('Admin');
548
+ });
549
+
550
+ it('should handle complex builder scenarios', async ({ trx }) => {
551
+ const userBuilder = async (attrs: any, _factory: any, _db: Knex) => {
552
+ return User.fromJson({
553
+ name: attrs.name || 'Default User',
554
+ });
555
+ };
556
+
557
+ const postBuilder = async (attrs: any, factory: any, _db: Knex) => {
558
+ // If no user_id provided, create a user
559
+ if (!attrs.user_id) {
560
+ const user = await factory.insert('user');
561
+ return Post.fromJson({
562
+ title: attrs.title || 'Default Post',
563
+ user_id: user.id,
564
+ });
565
+ }
566
+ return Post.fromJson({
567
+ title: attrs.title || 'Default Post',
568
+ user_id: attrs.user_id,
569
+ });
570
+ };
571
+
572
+ const builders = {
573
+ user: userBuilder,
574
+ post: postBuilder,
575
+ };
576
+
577
+ const factory = new ObjectionFactory(builders, {}, trx);
578
+
579
+ const post = await factory.insert('post', { title: 'Test Post' });
580
+
581
+ expect(post).toBeInstanceOf(Post);
582
+ expect(post.title).toBe('Test Post');
583
+ expect(post.user_id).toBeDefined();
584
+ expect(typeof post.user_id).toBe('string'); // PostgreSQL returns bigint as string
585
+ });
580
586
  });