@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
package/package.json
CHANGED
|
@@ -1,18 +1,23 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@geekmidas/testkit",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.4",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
7
7
|
"./objection": {
|
|
8
|
+
"types": "./src/objection.ts",
|
|
8
9
|
"import": "./dist/objection.mjs",
|
|
9
|
-
"require": "./dist/objection.cjs"
|
|
10
|
-
"types": "./src/objection.ts"
|
|
10
|
+
"require": "./dist/objection.cjs"
|
|
11
11
|
},
|
|
12
12
|
"./kysely": {
|
|
13
|
+
"types": "./src/kysely.ts",
|
|
13
14
|
"import": "./dist/kysely.mjs",
|
|
14
|
-
"require": "./dist/kysely.cjs"
|
|
15
|
-
|
|
15
|
+
"require": "./dist/kysely.cjs"
|
|
16
|
+
},
|
|
17
|
+
"./faker": {
|
|
18
|
+
"types": "./src/faker.ts",
|
|
19
|
+
"import": "./dist/faker.mjs",
|
|
20
|
+
"require": "./dist/faker.cjs"
|
|
16
21
|
}
|
|
17
22
|
},
|
|
18
23
|
"dependencies": {
|
|
@@ -31,6 +36,6 @@
|
|
|
31
36
|
"knex": "~3.1.0",
|
|
32
37
|
"objection": "~3.1.5",
|
|
33
38
|
"db-errors": "~0.2.3",
|
|
34
|
-
"@geekmidas/envkit": "0.0.
|
|
39
|
+
"@geekmidas/envkit": "0.0.3"
|
|
35
40
|
}
|
|
36
41
|
}
|
package/src/Factory.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import type { FakerFactory } from './faker';
|
|
2
|
+
|
|
1
3
|
export abstract class Factory<
|
|
2
4
|
Builders extends Record<string, any>,
|
|
3
5
|
Seeds extends Record<string, any>,
|
|
@@ -28,7 +30,7 @@ export abstract class Factory<
|
|
|
28
30
|
builderName: K,
|
|
29
31
|
attrs?:
|
|
30
32
|
| Parameters<Builders[K]>[0]
|
|
31
|
-
| ((idx: number) => Parameters<Builders[K]>[0]),
|
|
33
|
+
| ((idx: number, faker: FakerFactory) => Parameters<Builders[K]>[0]),
|
|
32
34
|
): Promise<Awaited<ReturnType<Builders[K]>>[]>;
|
|
33
35
|
|
|
34
36
|
/**
|
package/src/KyselyFactory.ts
CHANGED
|
@@ -5,6 +5,7 @@ import type {
|
|
|
5
5
|
Selectable,
|
|
6
6
|
} from 'kysely';
|
|
7
7
|
import { Factory, type FactorySeed } from './Factory.ts';
|
|
8
|
+
import { type FakerFactory, faker } from './faker.ts';
|
|
8
9
|
|
|
9
10
|
export class KyselyFactory<
|
|
10
11
|
DB,
|
|
@@ -31,67 +32,55 @@ export class KyselyFactory<
|
|
|
31
32
|
>,
|
|
32
33
|
Factory = any,
|
|
33
34
|
Result = Selectable<DB[TableName]>,
|
|
34
|
-
>(
|
|
35
|
-
table: TableName
|
|
36
|
-
|
|
35
|
+
>(
|
|
36
|
+
table: TableName,
|
|
37
|
+
item?: (
|
|
37
38
|
attrs: Attrs,
|
|
38
39
|
factory: Factory,
|
|
39
40
|
db: Kysely<DB>,
|
|
41
|
+
faker: FakerFactory,
|
|
40
42
|
) =>
|
|
41
43
|
| Partial<Insertable<DB[TableName]>>
|
|
42
|
-
| Promise<Partial<Insertable<DB[TableName]
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
record: Result,
|
|
44
|
+
| Promise<Partial<Insertable<DB[TableName]>>>,
|
|
45
|
+
autoInsert?: boolean,
|
|
46
|
+
): (
|
|
47
|
+
attrs: Attrs,
|
|
48
|
+
factory: Factory,
|
|
49
|
+
db: Kysely<DB>,
|
|
50
|
+
faker: FakerFactory,
|
|
51
|
+
) => Promise<Result> {
|
|
52
|
+
return async (
|
|
52
53
|
attrs: Attrs,
|
|
53
54
|
factory: Factory,
|
|
54
55
|
db: Kysely<DB>,
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
}): (attrs: Attrs, factory: Factory, db: Kysely<DB>) => Promise<Result> {
|
|
58
|
-
return async (attrs: Attrs, factory: Factory, db: Kysely<DB>) => {
|
|
56
|
+
faker: FakerFactory,
|
|
57
|
+
) => {
|
|
59
58
|
// Start with attributes
|
|
60
59
|
let data: Partial<Insertable<DB[TableName]>> = { ...attrs };
|
|
61
60
|
|
|
62
61
|
// Apply defaults
|
|
63
|
-
if (
|
|
64
|
-
const defaults = await
|
|
62
|
+
if (item) {
|
|
63
|
+
const defaults = await item(attrs, factory, db, faker);
|
|
65
64
|
data = { ...defaults, ...data };
|
|
66
65
|
}
|
|
67
66
|
|
|
68
|
-
// Apply transformations
|
|
69
|
-
if (config.transform) {
|
|
70
|
-
data = await config.transform(data, factory, db);
|
|
71
|
-
}
|
|
72
|
-
|
|
73
67
|
// Handle insertion based on autoInsert flag
|
|
74
|
-
if (
|
|
68
|
+
if (autoInsert !== false) {
|
|
75
69
|
// Auto insert is enabled by default
|
|
76
70
|
const result = await db
|
|
77
|
-
.insertInto(
|
|
71
|
+
.insertInto(table)
|
|
78
72
|
.values(data as Insertable<DB[TableName]>)
|
|
79
73
|
.returningAll()
|
|
80
74
|
.executeTakeFirst();
|
|
81
75
|
|
|
82
76
|
if (!result) {
|
|
83
|
-
throw new Error(`Failed to insert into ${
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
// Handle relations if defined
|
|
87
|
-
if (config.relations) {
|
|
88
|
-
await config.relations(result as Result, attrs, factory, db);
|
|
77
|
+
throw new Error(`Failed to insert into ${table}`);
|
|
89
78
|
}
|
|
90
79
|
|
|
91
80
|
return result as Result;
|
|
92
81
|
} else {
|
|
93
82
|
// Return object for factory to handle insertion
|
|
94
|
-
return { table
|
|
83
|
+
return { table, data } as any;
|
|
95
84
|
}
|
|
96
85
|
};
|
|
97
86
|
}
|
|
@@ -108,7 +97,12 @@ export class KyselyFactory<
|
|
|
108
97
|
);
|
|
109
98
|
}
|
|
110
99
|
|
|
111
|
-
const result = await this.builders[builderName](
|
|
100
|
+
const result = await this.builders[builderName](
|
|
101
|
+
attrs || {},
|
|
102
|
+
this,
|
|
103
|
+
this.db,
|
|
104
|
+
faker,
|
|
105
|
+
);
|
|
112
106
|
|
|
113
107
|
// For Kysely, we expect the builder to return an object with table and data properties
|
|
114
108
|
// or to handle the insertion itself and return the inserted record
|
|
@@ -141,7 +135,7 @@ export class KyselyFactory<
|
|
|
141
135
|
async insertMany<K extends keyof Builders>(
|
|
142
136
|
count: number,
|
|
143
137
|
builderName: K,
|
|
144
|
-
attrs: (idx: number) => Parameters<Builders[K]>[0],
|
|
138
|
+
attrs: (idx: number, faker: FakerFactory) => Parameters<Builders[K]>[0],
|
|
145
139
|
): Promise<Awaited<ReturnType<Builders[K]>>[]>;
|
|
146
140
|
async insertMany<K extends keyof Builders>(
|
|
147
141
|
count: number,
|
|
@@ -159,7 +153,7 @@ export class KyselyFactory<
|
|
|
159
153
|
const promises: Promise<any>[] = [];
|
|
160
154
|
|
|
161
155
|
for (let i = 0; i < count; i++) {
|
|
162
|
-
const newAttrs = typeof attrs === 'function' ? attrs(i) : attrs;
|
|
156
|
+
const newAttrs = typeof attrs === 'function' ? attrs(i, faker) : attrs;
|
|
163
157
|
promises.push(this.insert(builderName, newAttrs));
|
|
164
158
|
}
|
|
165
159
|
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { Kysely, Transaction } from 'kysely';
|
|
2
|
+
import {
|
|
3
|
+
type IsolationLevel,
|
|
4
|
+
VitestPostgresTransactionIsolator,
|
|
5
|
+
} from './VitestTransactionIsolator';
|
|
6
|
+
|
|
7
|
+
export class VitestKyselyTransactionIsolator<
|
|
8
|
+
Database,
|
|
9
|
+
> extends VitestPostgresTransactionIsolator<
|
|
10
|
+
Kysely<Database>,
|
|
11
|
+
Transaction<Database>
|
|
12
|
+
> {
|
|
13
|
+
async transact(
|
|
14
|
+
conn: Kysely<Database>,
|
|
15
|
+
level: IsolationLevel,
|
|
16
|
+
fn: (trx: Transaction<Database>) => Promise<void>,
|
|
17
|
+
): Promise<void> {
|
|
18
|
+
const isolationLevel =
|
|
19
|
+
level.toLocaleLowerCase() as Lowercase<IsolationLevel>;
|
|
20
|
+
await conn.transaction().setIsolationLevel(isolationLevel).execute(fn);
|
|
21
|
+
}
|
|
22
|
+
// Implement any Kysely-specific transaction logic here
|
|
23
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { test as base } from 'vitest';
|
|
2
|
+
|
|
3
|
+
export interface DatabaseFixtures<Transaction> {
|
|
4
|
+
trx: Transaction;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export enum IsolationLevel {
|
|
8
|
+
READ_UNCOMMITTED = 'READ UNCOMMITTED',
|
|
9
|
+
READ_COMMITTED = 'READ COMMITTED',
|
|
10
|
+
REPEATABLE_READ = 'REPEATABLE READ',
|
|
11
|
+
SERIALIZABLE = 'SERIALIZABLE',
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export abstract class VitestPostgresTransactionIsolator<
|
|
15
|
+
Connection,
|
|
16
|
+
Transaction,
|
|
17
|
+
> {
|
|
18
|
+
abstract transact(
|
|
19
|
+
conn: Connection,
|
|
20
|
+
isolationLevel: IsolationLevel,
|
|
21
|
+
fn: (trx: Transaction) => Promise<void>,
|
|
22
|
+
): Promise<void>;
|
|
23
|
+
|
|
24
|
+
wrapVitestWithTransaction(
|
|
25
|
+
conn: Connection,
|
|
26
|
+
setup?: (trx: Transaction) => Promise<void>,
|
|
27
|
+
level: IsolationLevel = IsolationLevel.REPEATABLE_READ,
|
|
28
|
+
) {
|
|
29
|
+
return base.extend<DatabaseFixtures<Transaction>>({
|
|
30
|
+
// This fixture automatically provides a transaction to each test
|
|
31
|
+
trx: async ({}, use) => {
|
|
32
|
+
// Create a custom error class for rollback
|
|
33
|
+
class TestRollback extends Error {
|
|
34
|
+
constructor() {
|
|
35
|
+
super('Test rollback');
|
|
36
|
+
this.name = 'TestRollback';
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
let testError: Error | undefined;
|
|
41
|
+
|
|
42
|
+
try {
|
|
43
|
+
await this.transact(conn, level, async (transaction) => {
|
|
44
|
+
try {
|
|
45
|
+
// Provide the transaction to the test
|
|
46
|
+
await setup?.(transaction);
|
|
47
|
+
await use(transaction);
|
|
48
|
+
} catch (error) {
|
|
49
|
+
// Capture any test errors
|
|
50
|
+
testError = error as Error;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// Always throw to trigger rollback
|
|
54
|
+
throw new TestRollback();
|
|
55
|
+
});
|
|
56
|
+
} catch (error) {
|
|
57
|
+
// Only rethrow if it's not our rollback error
|
|
58
|
+
if (!(error instanceof TestRollback)) {
|
|
59
|
+
throw error;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// If the test had an error, throw it now
|
|
63
|
+
if (testError) {
|
|
64
|
+
throw testError;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
},
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
}
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
import { beforeEach, describe, expect, it } from 'vitest';
|
|
2
|
+
import {
|
|
3
|
+
Factory,
|
|
4
|
+
type FactorySeed,
|
|
5
|
+
type MixedFactoryBuilder,
|
|
6
|
+
} from '../Factory';
|
|
7
|
+
|
|
8
|
+
// Create a concrete implementation for testing
|
|
9
|
+
class TestFactory extends Factory<
|
|
10
|
+
{ testBuilder: (attrs: any) => any },
|
|
11
|
+
{ testSeed: (attrs: any, factory: any, db: any) => any }
|
|
12
|
+
> {
|
|
13
|
+
async insert(builderName: any, attrs?: any) {
|
|
14
|
+
return Promise.resolve({ id: 1, ...attrs });
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
async insertMany(count: number, builderName: any, attrs?: any) {
|
|
18
|
+
const results: any[] = [];
|
|
19
|
+
for (let i = 0; i < count; i++) {
|
|
20
|
+
const newAttrs = typeof attrs === 'function' ? attrs(i) : attrs;
|
|
21
|
+
results.push(await this.insert(builderName, newAttrs));
|
|
22
|
+
}
|
|
23
|
+
return results;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
seed(seedName: any, attrs?: any): any {
|
|
27
|
+
return Promise.resolve({ seedResult: true, ...attrs });
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
describe('Factory', () => {
|
|
32
|
+
describe('abstract class functionality', () => {
|
|
33
|
+
it('should be instantiable through concrete implementation', () => {
|
|
34
|
+
const factory = new TestFactory();
|
|
35
|
+
expect(factory).toBeInstanceOf(Factory);
|
|
36
|
+
expect(factory).toBeInstanceOf(TestFactory);
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
it('should have abstract methods defined', () => {
|
|
40
|
+
const factory = new TestFactory();
|
|
41
|
+
expect(typeof factory.insert).toBe('function');
|
|
42
|
+
expect(typeof factory.insertMany).toBe('function');
|
|
43
|
+
expect(typeof factory.seed).toBe('function');
|
|
44
|
+
});
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
describe('createSeed static method', () => {
|
|
48
|
+
it('should return the seed function unchanged', () => {
|
|
49
|
+
const seedFn = async (attrs: any, factory: any, db: any) => {
|
|
50
|
+
return { id: 1, name: 'test' };
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
const result = Factory.createSeed(seedFn);
|
|
54
|
+
|
|
55
|
+
expect(result).toBe(seedFn);
|
|
56
|
+
expect(typeof result).toBe('function');
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
it('should work with different seed function signatures', () => {
|
|
60
|
+
const simpleSeed = () => Promise.resolve({ simple: true });
|
|
61
|
+
const complexSeed = async (
|
|
62
|
+
attrs: { name: string },
|
|
63
|
+
factory: any,
|
|
64
|
+
db: any,
|
|
65
|
+
) => {
|
|
66
|
+
return { name: attrs.name, created: true };
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
const result1 = Factory.createSeed(simpleSeed);
|
|
70
|
+
const result2 = Factory.createSeed(complexSeed);
|
|
71
|
+
|
|
72
|
+
expect(result1).toBe(simpleSeed);
|
|
73
|
+
expect(result2).toBe(complexSeed);
|
|
74
|
+
});
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
describe('concrete implementation behavior', () => {
|
|
78
|
+
let factory: TestFactory;
|
|
79
|
+
|
|
80
|
+
beforeEach(() => {
|
|
81
|
+
factory = new TestFactory();
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
it('should implement insert method', async () => {
|
|
85
|
+
const result = await factory.insert('testBuilder', { name: 'test' });
|
|
86
|
+
expect(result).toEqual({ id: 1, name: 'test' });
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
it('should implement insertMany method', async () => {
|
|
90
|
+
const results = await factory.insertMany(3, 'testBuilder', {
|
|
91
|
+
name: 'test',
|
|
92
|
+
});
|
|
93
|
+
expect(results).toHaveLength(3);
|
|
94
|
+
expect(results[0]).toEqual({ id: 1, name: 'test' });
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
it('should implement insertMany with function attributes', async () => {
|
|
98
|
+
const results = await factory.insertMany(2, 'testBuilder', (idx) => ({
|
|
99
|
+
name: `test${idx}`,
|
|
100
|
+
}));
|
|
101
|
+
expect(results).toHaveLength(2);
|
|
102
|
+
expect(results[0]).toEqual({ id: 1, name: 'test0' });
|
|
103
|
+
expect(results[1]).toEqual({ id: 1, name: 'test1' });
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
it('should implement seed method', async () => {
|
|
107
|
+
const result = await factory.seed('testSeed', { custom: 'value' });
|
|
108
|
+
expect(result).toEqual({ seedResult: true, custom: 'value' });
|
|
109
|
+
});
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
describe('type definitions', () => {
|
|
113
|
+
it('should properly type MixedFactoryBuilder', () => {
|
|
114
|
+
// Test that the type allows both sync and async returns
|
|
115
|
+
const syncBuilder: MixedFactoryBuilder = (attrs, factory, db) => ({
|
|
116
|
+
sync: true,
|
|
117
|
+
});
|
|
118
|
+
const asyncBuilder: MixedFactoryBuilder = async (attrs, factory, db) => ({
|
|
119
|
+
async: true,
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
expect(typeof syncBuilder).toBe('function');
|
|
123
|
+
expect(typeof asyncBuilder).toBe('function');
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
it('should properly type FactorySeed', () => {
|
|
127
|
+
// Test that FactorySeed requires async return
|
|
128
|
+
const seed: FactorySeed = async (attrs, factory, db) => ({
|
|
129
|
+
seeded: true,
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
expect(typeof seed).toBe('function');
|
|
133
|
+
});
|
|
134
|
+
});
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
// Test the type exports
|
|
138
|
+
describe('Factory types', () => {
|
|
139
|
+
it('should export MixedFactoryBuilder type', () => {
|
|
140
|
+
const builder: MixedFactoryBuilder<
|
|
141
|
+
{ name: string },
|
|
142
|
+
TestFactory,
|
|
143
|
+
{ id: number; name: string },
|
|
144
|
+
any
|
|
145
|
+
> = (attrs, factory, db) => {
|
|
146
|
+
return { id: 1, name: attrs.name };
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
expect(typeof builder).toBe('function');
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
it('should export FactorySeed type', () => {
|
|
153
|
+
const seed: FactorySeed<
|
|
154
|
+
{ count: number },
|
|
155
|
+
TestFactory,
|
|
156
|
+
{ created: number },
|
|
157
|
+
any
|
|
158
|
+
> = async (attrs, factory, db) => {
|
|
159
|
+
return { created: attrs.count };
|
|
160
|
+
};
|
|
161
|
+
|
|
162
|
+
expect(typeof seed).toBe('function');
|
|
163
|
+
});
|
|
164
|
+
});
|