@geekmidas/testkit 0.0.7 → 0.0.9
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/PostgresObjectionMigrator-B88aTT0m.cjs +122 -0
- package/dist/PostgresObjectionMigrator-DydSgYFv.mjs +117 -0
- package/dist/PostgresObjectionMigrator.cjs +4 -0
- package/dist/PostgresObjectionMigrator.mjs +4 -0
- package/dist/{VitestKyselyTransactionIsolator-AfxPJEwR.mjs → VitestKyselyTransactionIsolator-BKGT9nEG.mjs} +1 -1
- package/dist/{VitestKyselyTransactionIsolator-YWnSJiIH.cjs → VitestKyselyTransactionIsolator-CIlpIO78.cjs} +1 -1
- package/dist/VitestKyselyTransactionIsolator.cjs +2 -2
- package/dist/VitestKyselyTransactionIsolator.mjs +2 -2
- package/dist/{VitestObjectionTransactionIsolator-BZRYy8iW.mjs → VitestObjectionTransactionIsolator-BPoLUFop.mjs} +2 -2
- package/dist/{VitestObjectionTransactionIsolator-0uX6DW5G.cjs → VitestObjectionTransactionIsolator-DyqLp_in.cjs} +2 -2
- package/dist/VitestObjectionTransactionIsolator.cjs +2 -2
- package/dist/VitestObjectionTransactionIsolator.mjs +2 -2
- package/dist/VitestTransactionIsolator.cjs +1 -1
- package/dist/VitestTransactionIsolator.mjs +1 -1
- package/dist/__tests__/KyselyFactory.spec.cjs +5 -5
- package/dist/__tests__/KyselyFactory.spec.mjs +5 -5
- package/dist/__tests__/ObjectionFactory.spec.cjs +1 -1
- package/dist/__tests__/ObjectionFactory.spec.mjs +1 -1
- package/dist/__tests__/PostgresMigrator.spec.cjs +1 -1
- package/dist/__tests__/PostgresMigrator.spec.mjs +1 -1
- package/dist/__tests__/PostgresObjectionMigrator.spec.cjs +432 -0
- package/dist/__tests__/PostgresObjectionMigrator.spec.mjs +431 -0
- package/dist/__tests__/VitestObjectionTransactionIsolator.spec.cjs +130 -0
- package/dist/__tests__/VitestObjectionTransactionIsolator.spec.mjs +129 -0
- package/dist/__tests__/integration.spec.cjs +5 -5
- package/dist/__tests__/integration.spec.mjs +5 -5
- package/dist/{helpers-CukcFAU9.mjs → helpers-BEmjyUVE.mjs} +1 -1
- package/dist/{helpers-Bnm3Jy9X.cjs → helpers-CNMBePuj.cjs} +12 -0
- package/dist/helpers.cjs +1 -1
- package/dist/helpers.mjs +1 -1
- package/dist/{kysely-B-GOhABm.cjs → kysely-CBfCXxUn.cjs} +2 -2
- package/dist/{kysely-CqfoKVXs.mjs → kysely-Cx_1pZYc.mjs} +2 -2
- package/dist/kysely.cjs +3 -3
- package/dist/kysely.mjs +3 -3
- package/dist/objection-CCD8fMLj.cjs +87 -0
- package/dist/objection-lsMgM5gP.mjs +82 -0
- package/dist/objection.cjs +7 -81
- package/dist/objection.mjs +6 -81
- package/package.json +1 -1
- package/src/PostgresObjectionMigrator.ts +138 -0
- package/src/VitestObjectionTransactionIsolator.ts +2 -1
- package/src/__tests__/PostgresObjectionMigrator.spec.ts +634 -0
- package/src/__tests__/VitestObjectionTransactionIsolator.spec.ts +144 -0
- package/src/objection.ts +1 -0
- package/test/helpers.ts +3 -1
- /package/dist/{VitestTransactionIsolator-kFL36T8x.mjs → VitestTransactionIsolator-BWwK-ca6.mjs} +0 -0
- /package/dist/{VitestTransactionIsolator-DcOz0LZF.cjs → VitestTransactionIsolator-CruLTRRi.cjs} +0 -0
- /package/dist/{helpers-CKMlwSYT.mjs → helpers-BuPmgzyQ.mjs} +0 -0
- /package/dist/{helpers-H4hO5SZR.cjs → helpers-nEUtQ7eo.cjs} +0 -0
|
@@ -3,11 +3,11 @@ import "../faker-CxKkEeYi.mjs";
|
|
|
3
3
|
import { KyselyFactory } from "../KyselyFactory-ELiHgHVv.mjs";
|
|
4
4
|
import "../PostgresMigrator-BzqksJcW.mjs";
|
|
5
5
|
import "../PostgresKyselyMigrator-ChIpZFYB.mjs";
|
|
6
|
-
import "../VitestTransactionIsolator-
|
|
7
|
-
import "../VitestKyselyTransactionIsolator-
|
|
8
|
-
import { createKyselyDb } from "../helpers-
|
|
9
|
-
import { wrapVitestKyselyTransaction } from "../kysely-
|
|
10
|
-
import { TEST_DATABASE_CONFIG, createTestTables } from "../helpers-
|
|
6
|
+
import "../VitestTransactionIsolator-BWwK-ca6.mjs";
|
|
7
|
+
import "../VitestKyselyTransactionIsolator-BKGT9nEG.mjs";
|
|
8
|
+
import { createKyselyDb } from "../helpers-BuPmgzyQ.mjs";
|
|
9
|
+
import { wrapVitestKyselyTransaction } from "../kysely-Cx_1pZYc.mjs";
|
|
10
|
+
import { TEST_DATABASE_CONFIG, createTestTables } from "../helpers-BEmjyUVE.mjs";
|
|
11
11
|
import { beforeAll, describe, expect, it } from "vitest";
|
|
12
12
|
|
|
13
13
|
//#region src/__tests__/integration.spec.ts
|
|
@@ -108,4 +108,4 @@ async function createTestDatabase(dbName) {
|
|
|
108
108
|
}
|
|
109
109
|
|
|
110
110
|
//#endregion
|
|
111
|
-
export { TEST_DATABASE_CONFIG, createTestDatabase, createTestTables, setupKnexTest };
|
|
111
|
+
export { TEST_DATABASE_CONFIG, createKnexDb, createTestDatabase, createTestTables, createTestTablesKnex, setupKnexTest };
|
|
@@ -115,6 +115,12 @@ Object.defineProperty(exports, 'TEST_DATABASE_CONFIG', {
|
|
|
115
115
|
return TEST_DATABASE_CONFIG;
|
|
116
116
|
}
|
|
117
117
|
});
|
|
118
|
+
Object.defineProperty(exports, 'createKnexDb', {
|
|
119
|
+
enumerable: true,
|
|
120
|
+
get: function () {
|
|
121
|
+
return createKnexDb;
|
|
122
|
+
}
|
|
123
|
+
});
|
|
118
124
|
Object.defineProperty(exports, 'createTestDatabase', {
|
|
119
125
|
enumerable: true,
|
|
120
126
|
get: function () {
|
|
@@ -127,6 +133,12 @@ Object.defineProperty(exports, 'createTestTables', {
|
|
|
127
133
|
return createTestTables;
|
|
128
134
|
}
|
|
129
135
|
});
|
|
136
|
+
Object.defineProperty(exports, 'createTestTablesKnex', {
|
|
137
|
+
enumerable: true,
|
|
138
|
+
get: function () {
|
|
139
|
+
return createTestTablesKnex;
|
|
140
|
+
}
|
|
141
|
+
});
|
|
130
142
|
Object.defineProperty(exports, 'setupKnexTest', {
|
|
131
143
|
enumerable: true,
|
|
132
144
|
get: function () {
|
package/dist/helpers.cjs
CHANGED
package/dist/helpers.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
const require_VitestTransactionIsolator = require('./VitestTransactionIsolator-
|
|
2
|
-
const require_VitestKyselyTransactionIsolator = require('./VitestKyselyTransactionIsolator-
|
|
1
|
+
const require_VitestTransactionIsolator = require('./VitestTransactionIsolator-CruLTRRi.cjs');
|
|
2
|
+
const require_VitestKyselyTransactionIsolator = require('./VitestKyselyTransactionIsolator-CIlpIO78.cjs');
|
|
3
3
|
|
|
4
4
|
//#region src/kysely.ts
|
|
5
5
|
/**
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { IsolationLevel } from "./VitestTransactionIsolator-
|
|
2
|
-
import { VitestKyselyTransactionIsolator } from "./VitestKyselyTransactionIsolator-
|
|
1
|
+
import { IsolationLevel } from "./VitestTransactionIsolator-BWwK-ca6.mjs";
|
|
2
|
+
import { VitestKyselyTransactionIsolator } from "./VitestKyselyTransactionIsolator-BKGT9nEG.mjs";
|
|
3
3
|
|
|
4
4
|
//#region src/kysely.ts
|
|
5
5
|
/**
|
package/dist/kysely.cjs
CHANGED
|
@@ -3,9 +3,9 @@ require('./faker-SMN4ira4.cjs');
|
|
|
3
3
|
const require_KyselyFactory = require('./KyselyFactory-Bdq1s1Go.cjs');
|
|
4
4
|
require('./PostgresMigrator-BtAWdLss.cjs');
|
|
5
5
|
const require_PostgresKyselyMigrator = require('./PostgresKyselyMigrator-Bs31emFd.cjs');
|
|
6
|
-
const require_VitestTransactionIsolator = require('./VitestTransactionIsolator-
|
|
7
|
-
const require_VitestKyselyTransactionIsolator = require('./VitestKyselyTransactionIsolator-
|
|
8
|
-
const require_kysely = require('./kysely-
|
|
6
|
+
const require_VitestTransactionIsolator = require('./VitestTransactionIsolator-CruLTRRi.cjs');
|
|
7
|
+
const require_VitestKyselyTransactionIsolator = require('./VitestKyselyTransactionIsolator-CIlpIO78.cjs');
|
|
8
|
+
const require_kysely = require('./kysely-CBfCXxUn.cjs');
|
|
9
9
|
|
|
10
10
|
exports.IsolationLevel = require_VitestTransactionIsolator.IsolationLevel;
|
|
11
11
|
exports.KyselyFactory = require_KyselyFactory.KyselyFactory;
|
package/dist/kysely.mjs
CHANGED
|
@@ -3,8 +3,8 @@ import "./faker-CxKkEeYi.mjs";
|
|
|
3
3
|
import { KyselyFactory } from "./KyselyFactory-ELiHgHVv.mjs";
|
|
4
4
|
import "./PostgresMigrator-BzqksJcW.mjs";
|
|
5
5
|
import { PostgresKyselyMigrator } from "./PostgresKyselyMigrator-ChIpZFYB.mjs";
|
|
6
|
-
import { IsolationLevel } from "./VitestTransactionIsolator-
|
|
7
|
-
import { VitestKyselyTransactionIsolator } from "./VitestKyselyTransactionIsolator-
|
|
8
|
-
import { wrapVitestKyselyTransaction } from "./kysely-
|
|
6
|
+
import { IsolationLevel } from "./VitestTransactionIsolator-BWwK-ca6.mjs";
|
|
7
|
+
import { VitestKyselyTransactionIsolator } from "./VitestKyselyTransactionIsolator-BKGT9nEG.mjs";
|
|
8
|
+
import { wrapVitestKyselyTransaction } from "./kysely-Cx_1pZYc.mjs";
|
|
9
9
|
|
|
10
10
|
export { IsolationLevel, KyselyFactory, PostgresKyselyMigrator, VitestKyselyTransactionIsolator, wrapVitestKyselyTransaction };
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
const require_VitestTransactionIsolator = require('./VitestTransactionIsolator-CruLTRRi.cjs');
|
|
2
|
+
const require_VitestObjectionTransactionIsolator = require('./VitestObjectionTransactionIsolator-DyqLp_in.cjs');
|
|
3
|
+
|
|
4
|
+
//#region src/objection.ts
|
|
5
|
+
/**
|
|
6
|
+
* Creates a wrapped Vitest test API with automatic transaction rollback for Objection.js.
|
|
7
|
+
* Each test runs in an isolated database transaction that is rolled back after completion.
|
|
8
|
+
* This ensures tests don't affect each other's data and run faster than truncating tables.
|
|
9
|
+
*
|
|
10
|
+
* @param api - The Vitest test API (usually `test` from vitest)
|
|
11
|
+
* @param knex - The Knex database connection instance
|
|
12
|
+
* @param setup - Optional setup function to run before each test in the transaction
|
|
13
|
+
* @param level - Transaction isolation level (defaults to REPEATABLE_READ)
|
|
14
|
+
* @returns A wrapped test API that provides transaction isolation
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```typescript
|
|
18
|
+
* import { test } from 'vitest';
|
|
19
|
+
* import { wrapVitestObjectionTransaction } from '@geekmidas/testkit/objection';
|
|
20
|
+
* import { knex } from './database';
|
|
21
|
+
* import { User, Post } from './models';
|
|
22
|
+
*
|
|
23
|
+
* // Create isolated test with automatic rollback
|
|
24
|
+
* const isolatedTest = wrapVitestObjectionTransaction(test, knex);
|
|
25
|
+
*
|
|
26
|
+
* // Use in tests - each test gets its own transaction
|
|
27
|
+
* isolatedTest('should create user', async ({ trx }) => {
|
|
28
|
+
* const user = await User.query(trx)
|
|
29
|
+
* .insert({ name: 'Test User', email: 'test@example.com' });
|
|
30
|
+
*
|
|
31
|
+
* expect(user).toBeDefined();
|
|
32
|
+
* // User is automatically rolled back after test
|
|
33
|
+
* });
|
|
34
|
+
*
|
|
35
|
+
* // With setup function for common test data
|
|
36
|
+
* const testWithSetup = wrapVitestObjectionTransaction(
|
|
37
|
+
* test,
|
|
38
|
+
* knex,
|
|
39
|
+
* async (trx) => {
|
|
40
|
+
* // Create common test data
|
|
41
|
+
* await knex('settings')
|
|
42
|
+
* .transacting(trx)
|
|
43
|
+
* .insert({ key: 'test_mode', value: 'true' });
|
|
44
|
+
* }
|
|
45
|
+
* );
|
|
46
|
+
*
|
|
47
|
+
* testWithSetup('should have test settings', async ({ trx }) => {
|
|
48
|
+
* const setting = await knex('settings')
|
|
49
|
+
* .transacting(trx)
|
|
50
|
+
* .where('key', 'test_mode')
|
|
51
|
+
* .first();
|
|
52
|
+
*
|
|
53
|
+
* expect(setting?.value).toBe('true');
|
|
54
|
+
* });
|
|
55
|
+
*
|
|
56
|
+
* // Example with factory and transaction
|
|
57
|
+
* const isolatedTest = wrapVitestObjectionTransaction(test, knex);
|
|
58
|
+
* const factory = new ObjectionFactory(builders, seeds, knex);
|
|
59
|
+
*
|
|
60
|
+
* isolatedTest('creates related data', async ({ trx }) => {
|
|
61
|
+
* // Factory can use the transaction
|
|
62
|
+
* const user = await User.query(trx).insert({ name: 'Author' });
|
|
63
|
+
* const posts = await Post.query(trx).insert([
|
|
64
|
+
* { title: 'Post 1', userId: user.id },
|
|
65
|
+
* { title: 'Post 2', userId: user.id }
|
|
66
|
+
* ]);
|
|
67
|
+
*
|
|
68
|
+
* const userWithPosts = await User.query(trx)
|
|
69
|
+
* .findById(user.id)
|
|
70
|
+
* .withGraphFetched('posts');
|
|
71
|
+
*
|
|
72
|
+
* expect(userWithPosts.posts).toHaveLength(2);
|
|
73
|
+
* });
|
|
74
|
+
* ```
|
|
75
|
+
*/
|
|
76
|
+
function wrapVitestObjectionTransaction(api, knex, setup, level = require_VitestTransactionIsolator.IsolationLevel.REPEATABLE_READ) {
|
|
77
|
+
const wrapper = new require_VitestObjectionTransactionIsolator.VitestObjectionTransactionIsolator(api);
|
|
78
|
+
return wrapper.wrapVitestWithTransaction(knex, setup, level);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
//#endregion
|
|
82
|
+
Object.defineProperty(exports, 'wrapVitestObjectionTransaction', {
|
|
83
|
+
enumerable: true,
|
|
84
|
+
get: function () {
|
|
85
|
+
return wrapVitestObjectionTransaction;
|
|
86
|
+
}
|
|
87
|
+
});
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { IsolationLevel } from "./VitestTransactionIsolator-BWwK-ca6.mjs";
|
|
2
|
+
import { VitestObjectionTransactionIsolator } from "./VitestObjectionTransactionIsolator-BPoLUFop.mjs";
|
|
3
|
+
|
|
4
|
+
//#region src/objection.ts
|
|
5
|
+
/**
|
|
6
|
+
* Creates a wrapped Vitest test API with automatic transaction rollback for Objection.js.
|
|
7
|
+
* Each test runs in an isolated database transaction that is rolled back after completion.
|
|
8
|
+
* This ensures tests don't affect each other's data and run faster than truncating tables.
|
|
9
|
+
*
|
|
10
|
+
* @param api - The Vitest test API (usually `test` from vitest)
|
|
11
|
+
* @param knex - The Knex database connection instance
|
|
12
|
+
* @param setup - Optional setup function to run before each test in the transaction
|
|
13
|
+
* @param level - Transaction isolation level (defaults to REPEATABLE_READ)
|
|
14
|
+
* @returns A wrapped test API that provides transaction isolation
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```typescript
|
|
18
|
+
* import { test } from 'vitest';
|
|
19
|
+
* import { wrapVitestObjectionTransaction } from '@geekmidas/testkit/objection';
|
|
20
|
+
* import { knex } from './database';
|
|
21
|
+
* import { User, Post } from './models';
|
|
22
|
+
*
|
|
23
|
+
* // Create isolated test with automatic rollback
|
|
24
|
+
* const isolatedTest = wrapVitestObjectionTransaction(test, knex);
|
|
25
|
+
*
|
|
26
|
+
* // Use in tests - each test gets its own transaction
|
|
27
|
+
* isolatedTest('should create user', async ({ trx }) => {
|
|
28
|
+
* const user = await User.query(trx)
|
|
29
|
+
* .insert({ name: 'Test User', email: 'test@example.com' });
|
|
30
|
+
*
|
|
31
|
+
* expect(user).toBeDefined();
|
|
32
|
+
* // User is automatically rolled back after test
|
|
33
|
+
* });
|
|
34
|
+
*
|
|
35
|
+
* // With setup function for common test data
|
|
36
|
+
* const testWithSetup = wrapVitestObjectionTransaction(
|
|
37
|
+
* test,
|
|
38
|
+
* knex,
|
|
39
|
+
* async (trx) => {
|
|
40
|
+
* // Create common test data
|
|
41
|
+
* await knex('settings')
|
|
42
|
+
* .transacting(trx)
|
|
43
|
+
* .insert({ key: 'test_mode', value: 'true' });
|
|
44
|
+
* }
|
|
45
|
+
* );
|
|
46
|
+
*
|
|
47
|
+
* testWithSetup('should have test settings', async ({ trx }) => {
|
|
48
|
+
* const setting = await knex('settings')
|
|
49
|
+
* .transacting(trx)
|
|
50
|
+
* .where('key', 'test_mode')
|
|
51
|
+
* .first();
|
|
52
|
+
*
|
|
53
|
+
* expect(setting?.value).toBe('true');
|
|
54
|
+
* });
|
|
55
|
+
*
|
|
56
|
+
* // Example with factory and transaction
|
|
57
|
+
* const isolatedTest = wrapVitestObjectionTransaction(test, knex);
|
|
58
|
+
* const factory = new ObjectionFactory(builders, seeds, knex);
|
|
59
|
+
*
|
|
60
|
+
* isolatedTest('creates related data', async ({ trx }) => {
|
|
61
|
+
* // Factory can use the transaction
|
|
62
|
+
* const user = await User.query(trx).insert({ name: 'Author' });
|
|
63
|
+
* const posts = await Post.query(trx).insert([
|
|
64
|
+
* { title: 'Post 1', userId: user.id },
|
|
65
|
+
* { title: 'Post 2', userId: user.id }
|
|
66
|
+
* ]);
|
|
67
|
+
*
|
|
68
|
+
* const userWithPosts = await User.query(trx)
|
|
69
|
+
* .findById(user.id)
|
|
70
|
+
* .withGraphFetched('posts');
|
|
71
|
+
*
|
|
72
|
+
* expect(userWithPosts.posts).toHaveLength(2);
|
|
73
|
+
* });
|
|
74
|
+
* ```
|
|
75
|
+
*/
|
|
76
|
+
function wrapVitestObjectionTransaction(api, knex, setup, level = IsolationLevel.REPEATABLE_READ) {
|
|
77
|
+
const wrapper = new VitestObjectionTransactionIsolator(api);
|
|
78
|
+
return wrapper.wrapVitestWithTransaction(knex, setup, level);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
//#endregion
|
|
82
|
+
export { wrapVitestObjectionTransaction };
|
package/dist/objection.cjs
CHANGED
|
@@ -1,87 +1,13 @@
|
|
|
1
1
|
require('./Factory-WMhTNZ9S.cjs');
|
|
2
2
|
const require_ObjectionFactory = require('./ObjectionFactory-C47B03Ot.cjs');
|
|
3
|
-
|
|
4
|
-
const
|
|
3
|
+
require('./PostgresMigrator-BtAWdLss.cjs');
|
|
4
|
+
const require_PostgresObjectionMigrator = require('./PostgresObjectionMigrator-B88aTT0m.cjs');
|
|
5
|
+
const require_VitestTransactionIsolator = require('./VitestTransactionIsolator-CruLTRRi.cjs');
|
|
6
|
+
const require_VitestObjectionTransactionIsolator = require('./VitestObjectionTransactionIsolator-DyqLp_in.cjs');
|
|
7
|
+
const require_objection = require('./objection-CCD8fMLj.cjs');
|
|
5
8
|
|
|
6
|
-
//#region src/objection.ts
|
|
7
|
-
/**
|
|
8
|
-
* Creates a wrapped Vitest test API with automatic transaction rollback for Objection.js.
|
|
9
|
-
* Each test runs in an isolated database transaction that is rolled back after completion.
|
|
10
|
-
* This ensures tests don't affect each other's data and run faster than truncating tables.
|
|
11
|
-
*
|
|
12
|
-
* @param api - The Vitest test API (usually `test` from vitest)
|
|
13
|
-
* @param knex - The Knex database connection instance
|
|
14
|
-
* @param setup - Optional setup function to run before each test in the transaction
|
|
15
|
-
* @param level - Transaction isolation level (defaults to REPEATABLE_READ)
|
|
16
|
-
* @returns A wrapped test API that provides transaction isolation
|
|
17
|
-
*
|
|
18
|
-
* @example
|
|
19
|
-
* ```typescript
|
|
20
|
-
* import { test } from 'vitest';
|
|
21
|
-
* import { wrapVitestObjectionTransaction } from '@geekmidas/testkit/objection';
|
|
22
|
-
* import { knex } from './database';
|
|
23
|
-
* import { User, Post } from './models';
|
|
24
|
-
*
|
|
25
|
-
* // Create isolated test with automatic rollback
|
|
26
|
-
* const isolatedTest = wrapVitestObjectionTransaction(test, knex);
|
|
27
|
-
*
|
|
28
|
-
* // Use in tests - each test gets its own transaction
|
|
29
|
-
* isolatedTest('should create user', async ({ trx }) => {
|
|
30
|
-
* const user = await User.query(trx)
|
|
31
|
-
* .insert({ name: 'Test User', email: 'test@example.com' });
|
|
32
|
-
*
|
|
33
|
-
* expect(user).toBeDefined();
|
|
34
|
-
* // User is automatically rolled back after test
|
|
35
|
-
* });
|
|
36
|
-
*
|
|
37
|
-
* // With setup function for common test data
|
|
38
|
-
* const testWithSetup = wrapVitestObjectionTransaction(
|
|
39
|
-
* test,
|
|
40
|
-
* knex,
|
|
41
|
-
* async (trx) => {
|
|
42
|
-
* // Create common test data
|
|
43
|
-
* await knex('settings')
|
|
44
|
-
* .transacting(trx)
|
|
45
|
-
* .insert({ key: 'test_mode', value: 'true' });
|
|
46
|
-
* }
|
|
47
|
-
* );
|
|
48
|
-
*
|
|
49
|
-
* testWithSetup('should have test settings', async ({ trx }) => {
|
|
50
|
-
* const setting = await knex('settings')
|
|
51
|
-
* .transacting(trx)
|
|
52
|
-
* .where('key', 'test_mode')
|
|
53
|
-
* .first();
|
|
54
|
-
*
|
|
55
|
-
* expect(setting?.value).toBe('true');
|
|
56
|
-
* });
|
|
57
|
-
*
|
|
58
|
-
* // Example with factory and transaction
|
|
59
|
-
* const isolatedTest = wrapVitestObjectionTransaction(test, knex);
|
|
60
|
-
* const factory = new ObjectionFactory(builders, seeds, knex);
|
|
61
|
-
*
|
|
62
|
-
* isolatedTest('creates related data', async ({ trx }) => {
|
|
63
|
-
* // Factory can use the transaction
|
|
64
|
-
* const user = await User.query(trx).insert({ name: 'Author' });
|
|
65
|
-
* const posts = await Post.query(trx).insert([
|
|
66
|
-
* { title: 'Post 1', userId: user.id },
|
|
67
|
-
* { title: 'Post 2', userId: user.id }
|
|
68
|
-
* ]);
|
|
69
|
-
*
|
|
70
|
-
* const userWithPosts = await User.query(trx)
|
|
71
|
-
* .findById(user.id)
|
|
72
|
-
* .withGraphFetched('posts');
|
|
73
|
-
*
|
|
74
|
-
* expect(userWithPosts.posts).toHaveLength(2);
|
|
75
|
-
* });
|
|
76
|
-
* ```
|
|
77
|
-
*/
|
|
78
|
-
function wrapVitestObjectionTransaction(api, knex, setup, level = require_VitestTransactionIsolator.IsolationLevel.REPEATABLE_READ) {
|
|
79
|
-
const wrapper = new require_VitestObjectionTransactionIsolator.VitestObjectionTransactionIsolator(api);
|
|
80
|
-
return wrapper.wrapVitestWithTransaction(knex, setup, level);
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
//#endregion
|
|
84
9
|
exports.IsolationLevel = require_VitestTransactionIsolator.IsolationLevel;
|
|
85
10
|
exports.ObjectionFactory = require_ObjectionFactory.ObjectionFactory;
|
|
11
|
+
exports.PostgresObjectionMigrator = require_PostgresObjectionMigrator.PostgresObjectionMigrator;
|
|
86
12
|
exports.VitestObjectionTransactionIsolator = require_VitestObjectionTransactionIsolator.VitestObjectionTransactionIsolator;
|
|
87
|
-
exports.wrapVitestObjectionTransaction = wrapVitestObjectionTransaction;
|
|
13
|
+
exports.wrapVitestObjectionTransaction = require_objection.wrapVitestObjectionTransaction;
|
package/dist/objection.mjs
CHANGED
|
@@ -1,84 +1,9 @@
|
|
|
1
1
|
import "./Factory-z2m01hMj.mjs";
|
|
2
2
|
import { ObjectionFactory } from "./ObjectionFactory-89p-FFEw.mjs";
|
|
3
|
-
import
|
|
4
|
-
import {
|
|
3
|
+
import "./PostgresMigrator-BzqksJcW.mjs";
|
|
4
|
+
import { PostgresObjectionMigrator } from "./PostgresObjectionMigrator-DydSgYFv.mjs";
|
|
5
|
+
import { IsolationLevel } from "./VitestTransactionIsolator-BWwK-ca6.mjs";
|
|
6
|
+
import { VitestObjectionTransactionIsolator } from "./VitestObjectionTransactionIsolator-BPoLUFop.mjs";
|
|
7
|
+
import { wrapVitestObjectionTransaction } from "./objection-lsMgM5gP.mjs";
|
|
5
8
|
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* Creates a wrapped Vitest test API with automatic transaction rollback for Objection.js.
|
|
9
|
-
* Each test runs in an isolated database transaction that is rolled back after completion.
|
|
10
|
-
* This ensures tests don't affect each other's data and run faster than truncating tables.
|
|
11
|
-
*
|
|
12
|
-
* @param api - The Vitest test API (usually `test` from vitest)
|
|
13
|
-
* @param knex - The Knex database connection instance
|
|
14
|
-
* @param setup - Optional setup function to run before each test in the transaction
|
|
15
|
-
* @param level - Transaction isolation level (defaults to REPEATABLE_READ)
|
|
16
|
-
* @returns A wrapped test API that provides transaction isolation
|
|
17
|
-
*
|
|
18
|
-
* @example
|
|
19
|
-
* ```typescript
|
|
20
|
-
* import { test } from 'vitest';
|
|
21
|
-
* import { wrapVitestObjectionTransaction } from '@geekmidas/testkit/objection';
|
|
22
|
-
* import { knex } from './database';
|
|
23
|
-
* import { User, Post } from './models';
|
|
24
|
-
*
|
|
25
|
-
* // Create isolated test with automatic rollback
|
|
26
|
-
* const isolatedTest = wrapVitestObjectionTransaction(test, knex);
|
|
27
|
-
*
|
|
28
|
-
* // Use in tests - each test gets its own transaction
|
|
29
|
-
* isolatedTest('should create user', async ({ trx }) => {
|
|
30
|
-
* const user = await User.query(trx)
|
|
31
|
-
* .insert({ name: 'Test User', email: 'test@example.com' });
|
|
32
|
-
*
|
|
33
|
-
* expect(user).toBeDefined();
|
|
34
|
-
* // User is automatically rolled back after test
|
|
35
|
-
* });
|
|
36
|
-
*
|
|
37
|
-
* // With setup function for common test data
|
|
38
|
-
* const testWithSetup = wrapVitestObjectionTransaction(
|
|
39
|
-
* test,
|
|
40
|
-
* knex,
|
|
41
|
-
* async (trx) => {
|
|
42
|
-
* // Create common test data
|
|
43
|
-
* await knex('settings')
|
|
44
|
-
* .transacting(trx)
|
|
45
|
-
* .insert({ key: 'test_mode', value: 'true' });
|
|
46
|
-
* }
|
|
47
|
-
* );
|
|
48
|
-
*
|
|
49
|
-
* testWithSetup('should have test settings', async ({ trx }) => {
|
|
50
|
-
* const setting = await knex('settings')
|
|
51
|
-
* .transacting(trx)
|
|
52
|
-
* .where('key', 'test_mode')
|
|
53
|
-
* .first();
|
|
54
|
-
*
|
|
55
|
-
* expect(setting?.value).toBe('true');
|
|
56
|
-
* });
|
|
57
|
-
*
|
|
58
|
-
* // Example with factory and transaction
|
|
59
|
-
* const isolatedTest = wrapVitestObjectionTransaction(test, knex);
|
|
60
|
-
* const factory = new ObjectionFactory(builders, seeds, knex);
|
|
61
|
-
*
|
|
62
|
-
* isolatedTest('creates related data', async ({ trx }) => {
|
|
63
|
-
* // Factory can use the transaction
|
|
64
|
-
* const user = await User.query(trx).insert({ name: 'Author' });
|
|
65
|
-
* const posts = await Post.query(trx).insert([
|
|
66
|
-
* { title: 'Post 1', userId: user.id },
|
|
67
|
-
* { title: 'Post 2', userId: user.id }
|
|
68
|
-
* ]);
|
|
69
|
-
*
|
|
70
|
-
* const userWithPosts = await User.query(trx)
|
|
71
|
-
* .findById(user.id)
|
|
72
|
-
* .withGraphFetched('posts');
|
|
73
|
-
*
|
|
74
|
-
* expect(userWithPosts.posts).toHaveLength(2);
|
|
75
|
-
* });
|
|
76
|
-
* ```
|
|
77
|
-
*/
|
|
78
|
-
function wrapVitestObjectionTransaction(api, knex, setup, level = IsolationLevel.REPEATABLE_READ) {
|
|
79
|
-
const wrapper = new VitestObjectionTransactionIsolator(api);
|
|
80
|
-
return wrapper.wrapVitestWithTransaction(knex, setup, level);
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
//#endregion
|
|
84
|
-
export { IsolationLevel, ObjectionFactory, VitestObjectionTransactionIsolator, wrapVitestObjectionTransaction };
|
|
9
|
+
export { IsolationLevel, ObjectionFactory, PostgresObjectionMigrator, VitestObjectionTransactionIsolator, wrapVitestObjectionTransaction };
|
package/package.json
CHANGED
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import type { Knex } from 'knex';
|
|
2
|
+
import { PostgresMigrator } from './PostgresMigrator';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Default logger instance for migration operations.
|
|
6
|
+
*/
|
|
7
|
+
const logger = console;
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* PostgreSQL migrator implementation for Objection.js ORM with Knex.
|
|
11
|
+
* Extends PostgresMigrator to provide Knex-specific migration functionality.
|
|
12
|
+
* Automatically creates test databases and applies migrations for testing environments.
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```typescript
|
|
16
|
+
* import knex from 'knex';
|
|
17
|
+
* import { PostgresObjectionMigrator } from '@geekmidas/testkit';
|
|
18
|
+
*
|
|
19
|
+
* // Create Knex instance
|
|
20
|
+
* const db = knex({
|
|
21
|
+
* client: 'pg',
|
|
22
|
+
* connection: uri,
|
|
23
|
+
* migrations: {
|
|
24
|
+
* directory: path.join(__dirname, 'migrations'),
|
|
25
|
+
* extension: 'ts'
|
|
26
|
+
* }
|
|
27
|
+
* });
|
|
28
|
+
*
|
|
29
|
+
* // Create and use migrator
|
|
30
|
+
* const migrator = new PostgresObjectionMigrator({
|
|
31
|
+
* uri: 'postgresql://localhost:5432/test_db',
|
|
32
|
+
* knex: db
|
|
33
|
+
* });
|
|
34
|
+
*
|
|
35
|
+
* const cleanup = await migrator.start();
|
|
36
|
+
* // Run tests...
|
|
37
|
+
* await cleanup();
|
|
38
|
+
* ```
|
|
39
|
+
*/
|
|
40
|
+
export class PostgresObjectionMigrator extends PostgresMigrator {
|
|
41
|
+
/**
|
|
42
|
+
* Creates a new PostgresObjectionMigrator instance.
|
|
43
|
+
*
|
|
44
|
+
* @param options - Configuration options
|
|
45
|
+
* @param options.uri - PostgreSQL connection URI
|
|
46
|
+
* @param options.knex - Knex database instance configured with migrations
|
|
47
|
+
*/
|
|
48
|
+
constructor(
|
|
49
|
+
private options: {
|
|
50
|
+
uri: string;
|
|
51
|
+
knex: Knex;
|
|
52
|
+
},
|
|
53
|
+
) {
|
|
54
|
+
super(options.uri);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Executes Knex migrations to the latest version.
|
|
59
|
+
* Implements the abstract migrate() method from PostgresMigrator.
|
|
60
|
+
*
|
|
61
|
+
* @throws Error if migrations fail to apply
|
|
62
|
+
* @returns Promise that resolves when all migrations are applied
|
|
63
|
+
*/
|
|
64
|
+
async migrate(): Promise<void> {
|
|
65
|
+
try {
|
|
66
|
+
// Run migrations to latest
|
|
67
|
+
const [batchNo, migrations] = await this.options.knex.migrate.latest();
|
|
68
|
+
|
|
69
|
+
if (migrations.length > 0) {
|
|
70
|
+
logger.log(
|
|
71
|
+
`Applied batch ${batchNo} with ${migrations.length} migrations:`,
|
|
72
|
+
);
|
|
73
|
+
migrations.forEach((migration: string) => {
|
|
74
|
+
logger.log(` - ${migration}`);
|
|
75
|
+
});
|
|
76
|
+
} else {
|
|
77
|
+
logger.log('No pending migrations to apply');
|
|
78
|
+
}
|
|
79
|
+
} catch (error) {
|
|
80
|
+
logger.error('Failed to apply migrations:', error);
|
|
81
|
+
throw error;
|
|
82
|
+
} finally {
|
|
83
|
+
// Always destroy the connection pool
|
|
84
|
+
await this.options.knex.destroy();
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Rolls back the last batch of migrations.
|
|
90
|
+
* Useful for testing migration rollback scenarios.
|
|
91
|
+
*
|
|
92
|
+
* @returns Promise that resolves when rollback is complete
|
|
93
|
+
*/
|
|
94
|
+
async rollback(): Promise<void> {
|
|
95
|
+
try {
|
|
96
|
+
const [batchNo, migrations] = await this.options.knex.migrate.rollback();
|
|
97
|
+
|
|
98
|
+
if (migrations.length > 0) {
|
|
99
|
+
logger.log(
|
|
100
|
+
`Rolled back batch ${batchNo} with ${migrations.length} migrations:`,
|
|
101
|
+
);
|
|
102
|
+
migrations.forEach((migration: string) => {
|
|
103
|
+
logger.log(` - ${migration}`);
|
|
104
|
+
});
|
|
105
|
+
} else {
|
|
106
|
+
logger.log('No migrations to rollback');
|
|
107
|
+
}
|
|
108
|
+
} catch (error) {
|
|
109
|
+
logger.error('Failed to rollback migrations:', error);
|
|
110
|
+
throw error;
|
|
111
|
+
} finally {
|
|
112
|
+
await this.options.knex.destroy();
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Gets the current migration status.
|
|
118
|
+
* Returns information about completed and pending migrations.
|
|
119
|
+
*
|
|
120
|
+
* @returns Promise with migration status information
|
|
121
|
+
*/
|
|
122
|
+
async status(): Promise<{
|
|
123
|
+
completed: string[];
|
|
124
|
+
pending: string[];
|
|
125
|
+
}> {
|
|
126
|
+
try {
|
|
127
|
+
const completed = await this.options.knex.migrate.list();
|
|
128
|
+
const [, pending] = await this.options.knex.migrate.currentVersion();
|
|
129
|
+
|
|
130
|
+
return {
|
|
131
|
+
completed: Array.isArray(completed[0]) ? completed[0] : [],
|
|
132
|
+
pending: Array.isArray(pending) ? pending : [],
|
|
133
|
+
};
|
|
134
|
+
} finally {
|
|
135
|
+
await this.options.knex.destroy();
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|
|
@@ -60,7 +60,8 @@ export class VitestObjectionTransactionIsolator extends VitestPostgresTransactio
|
|
|
60
60
|
level: IsolationLevel,
|
|
61
61
|
fn: (trx: Knex.Transaction) => Promise<void>,
|
|
62
62
|
): Promise<void> {
|
|
63
|
-
const isolationLevel = level.
|
|
63
|
+
const isolationLevel = level.toLowerCase() as Lowercase<IsolationLevel>;
|
|
64
|
+
|
|
64
65
|
await conn.transaction(
|
|
65
66
|
async (trx) => {
|
|
66
67
|
await fn(trx);
|