@geekmidas/testkit 0.3.0 → 0.4.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.
- package/README.md +110 -16
- package/dist/{Factory-IdfEkOeT.d.cts → Factory-c16c27Y6.d.cts} +2 -2
- package/dist/Factory.d.cts +2 -2
- package/dist/{KyselyFactory-Dxhi_ZkA.d.cts → KyselyFactory-uZ45h7YU.d.cts} +3 -3
- package/dist/KyselyFactory.d.cts +3 -3
- package/dist/{ObjectionFactory-BRAkAByP.d.cts → ObjectionFactory-CdhzKs4f.d.cts} +3 -3
- package/dist/ObjectionFactory.d.cts +3 -3
- package/dist/better-auth.d.cts +2 -2
- package/dist/{faker-CbYiF-8_.d.cts → faker-DvxiCtxc.d.cts} +3 -3
- package/dist/faker.d.cts +1 -1
- package/dist/kysely.d.cts +3 -3
- package/dist/objection.d.cts +3 -3
- package/package.json +39 -5
package/README.md
CHANGED
|
@@ -513,28 +513,113 @@ describe('User Service', () => {
|
|
|
513
513
|
|
|
514
514
|
## Seeds
|
|
515
515
|
|
|
516
|
-
Seeds are functions that create complex test scenarios:
|
|
516
|
+
Seeds are functions that create complex test scenarios. Use `createSeed` to define type-safe seed functions that receive `{ attrs, factory, db }` as a single context object:
|
|
517
|
+
|
|
518
|
+
### Defining Seeds with Kysely
|
|
517
519
|
|
|
518
520
|
```typescript
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
521
|
+
import { KyselyFactory } from '@geekmidas/testkit/kysely';
|
|
522
|
+
|
|
523
|
+
// Define seeds using createSeed for type safety
|
|
524
|
+
const seeds = {
|
|
525
|
+
// Simple seed with typed attrs
|
|
526
|
+
adminUser: KyselyFactory.createSeed(
|
|
527
|
+
async ({ attrs, factory }: {
|
|
528
|
+
attrs: { name?: string };
|
|
529
|
+
factory: KyselyFactory<Database, typeof builders, {}>;
|
|
530
|
+
db: Kysely<Database>
|
|
531
|
+
}) => {
|
|
532
|
+
return factory.insert('user', {
|
|
533
|
+
name: attrs.name || 'Admin User',
|
|
534
|
+
role: 'admin',
|
|
535
|
+
});
|
|
536
|
+
}
|
|
537
|
+
),
|
|
538
|
+
|
|
539
|
+
// Complex seed creating related records
|
|
540
|
+
blogWithPosts: KyselyFactory.createSeed(
|
|
541
|
+
async ({ attrs, factory }) => {
|
|
542
|
+
const author = await factory.insert('user', {
|
|
543
|
+
name: attrs.authorName || 'Blog Author',
|
|
544
|
+
role: 'author',
|
|
545
|
+
});
|
|
524
546
|
|
|
525
|
-
|
|
547
|
+
const categories = await factory.insertMany(3, 'category');
|
|
526
548
|
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
549
|
+
const posts = await factory.insertMany(attrs.postCount || 5, 'post', (index) => ({
|
|
550
|
+
title: `Post ${index + 1}`,
|
|
551
|
+
authorId: author.id,
|
|
552
|
+
categoryId: categories[index % categories.length].id,
|
|
553
|
+
}));
|
|
532
554
|
|
|
533
|
-
|
|
555
|
+
return { author, categories, posts };
|
|
556
|
+
}
|
|
557
|
+
),
|
|
534
558
|
};
|
|
535
559
|
|
|
536
|
-
//
|
|
537
|
-
const
|
|
560
|
+
// Create factory with seeds
|
|
561
|
+
const factory = new KyselyFactory(builders, seeds, db);
|
|
562
|
+
|
|
563
|
+
// Use in tests - attrs are type-safe
|
|
564
|
+
const admin = await factory.seed('adminUser', { name: 'Super Admin' });
|
|
565
|
+
const blog = await factory.seed('blogWithPosts', {
|
|
566
|
+
authorName: 'Jane Doe',
|
|
567
|
+
postCount: 10
|
|
568
|
+
});
|
|
569
|
+
```
|
|
570
|
+
|
|
571
|
+
### Defining Seeds with Objection.js
|
|
572
|
+
|
|
573
|
+
```typescript
|
|
574
|
+
import { ObjectionFactory } from '@geekmidas/testkit/objection';
|
|
575
|
+
import type { Knex } from 'knex';
|
|
576
|
+
|
|
577
|
+
const seeds = {
|
|
578
|
+
userWithProfile: ObjectionFactory.createSeed(
|
|
579
|
+
async ({ attrs, factory, db }: {
|
|
580
|
+
attrs: { email?: string };
|
|
581
|
+
factory: ObjectionFactory<typeof builders, {}>;
|
|
582
|
+
db: Knex
|
|
583
|
+
}) => {
|
|
584
|
+
const user = await factory.insert('user', {
|
|
585
|
+
email: attrs.email || 'user@example.com',
|
|
586
|
+
});
|
|
587
|
+
|
|
588
|
+
await factory.insert('profile', { userId: user.id });
|
|
589
|
+
|
|
590
|
+
return user;
|
|
591
|
+
}
|
|
592
|
+
),
|
|
593
|
+
};
|
|
594
|
+
|
|
595
|
+
const factory = new ObjectionFactory(builders, seeds, knex);
|
|
596
|
+
const user = await factory.seed('userWithProfile', { email: 'custom@example.com' });
|
|
597
|
+
```
|
|
598
|
+
|
|
599
|
+
### Seed Context Object
|
|
600
|
+
|
|
601
|
+
All seed functions receive a single context object with three properties:
|
|
602
|
+
|
|
603
|
+
| Property | Description |
|
|
604
|
+
|----------|-------------|
|
|
605
|
+
| `attrs` | Configuration attributes passed to `factory.seed()` |
|
|
606
|
+
| `factory` | The factory instance for creating records |
|
|
607
|
+
| `db` | The database connection (Kysely or Knex transaction) |
|
|
608
|
+
|
|
609
|
+
This pattern allows you to destructure only what you need:
|
|
610
|
+
|
|
611
|
+
```typescript
|
|
612
|
+
// Use all three
|
|
613
|
+
KyselyFactory.createSeed(async ({ attrs, factory, db }) => {
|
|
614
|
+
// Direct db access for complex queries
|
|
615
|
+
const existing = await db.selectFrom('users').where('role', '=', 'admin').execute();
|
|
616
|
+
// ...
|
|
617
|
+
});
|
|
618
|
+
|
|
619
|
+
// Or just what you need
|
|
620
|
+
KyselyFactory.createSeed(async ({ factory }) => {
|
|
621
|
+
return factory.insert('user');
|
|
622
|
+
});
|
|
538
623
|
```
|
|
539
624
|
|
|
540
625
|
## API Reference
|
|
@@ -549,6 +634,7 @@ class KyselyFactory<DB, Builders, Seeds> {
|
|
|
549
634
|
db: Kysely<DB> | ControlledTransaction<DB>
|
|
550
635
|
);
|
|
551
636
|
|
|
637
|
+
// Create a type-safe builder for a specific table
|
|
552
638
|
static createBuilder<DB, TableName extends keyof DB & string>(
|
|
553
639
|
table: TableName,
|
|
554
640
|
defaults?: (context: {
|
|
@@ -560,20 +646,28 @@ class KyselyFactory<DB, Builders, Seeds> {
|
|
|
560
646
|
autoInsert?: boolean
|
|
561
647
|
): BuilderFunction;
|
|
562
648
|
|
|
649
|
+
// Create a type-safe seed function
|
|
650
|
+
static createSeed<Seed extends FactorySeed>(
|
|
651
|
+
seedFn: (context: { attrs: Attrs; factory: Factory; db: DB }) => Promise<Result>
|
|
652
|
+
): Seed;
|
|
653
|
+
|
|
654
|
+
// Insert a single record
|
|
563
655
|
insert<K extends keyof Builders>(
|
|
564
656
|
builderName: K,
|
|
565
657
|
attrs?: Partial<BuilderAttrs>
|
|
566
658
|
): Promise<BuilderResult>;
|
|
567
659
|
|
|
660
|
+
// Insert multiple records
|
|
568
661
|
insertMany<K extends keyof Builders>(
|
|
569
662
|
count: number,
|
|
570
663
|
builderName: K,
|
|
571
664
|
attrs?: Partial<BuilderAttrs> | ((idx: number, faker: FakerFactory) => Partial<BuilderAttrs>)
|
|
572
665
|
): Promise<BuilderResult[]>;
|
|
573
666
|
|
|
667
|
+
// Execute a seed function
|
|
574
668
|
seed<K extends keyof Seeds>(
|
|
575
669
|
seedName: K,
|
|
576
|
-
attrs?:
|
|
670
|
+
attrs?: ExtractSeedAttrs<Seeds[K]> // Attrs type is extracted from seed function
|
|
577
671
|
): Promise<SeedResult>;
|
|
578
672
|
}
|
|
579
673
|
```
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { FakerFactory } from "./faker-
|
|
1
|
+
import { FakerFactory } from "./faker-DvxiCtxc.cjs";
|
|
2
2
|
|
|
3
3
|
//#region src/Factory.d.ts
|
|
4
4
|
|
|
@@ -143,4 +143,4 @@ type ExtractSeedAttrs<T> = T extends ((context: {
|
|
|
143
143
|
}) => any) ? A : never;
|
|
144
144
|
//#endregion
|
|
145
145
|
export { ExtractSeedAttrs, Factory, FactorySeed, MixedFactoryBuilder };
|
|
146
|
-
//# sourceMappingURL=Factory-
|
|
146
|
+
//# sourceMappingURL=Factory-c16c27Y6.d.cts.map
|
package/dist/Factory.d.cts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import "./faker-
|
|
2
|
-
import { ExtractSeedAttrs, Factory, FactorySeed, MixedFactoryBuilder } from "./Factory-
|
|
1
|
+
import "./faker-DvxiCtxc.cjs";
|
|
2
|
+
import { ExtractSeedAttrs, Factory, FactorySeed, MixedFactoryBuilder } from "./Factory-c16c27Y6.cjs";
|
|
3
3
|
export { ExtractSeedAttrs, Factory, FactorySeed, MixedFactoryBuilder };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { FakerFactory } from "./faker-
|
|
2
|
-
import { ExtractSeedAttrs, Factory, FactorySeed } from "./Factory-
|
|
1
|
+
import { FakerFactory } from "./faker-DvxiCtxc.cjs";
|
|
2
|
+
import { ExtractSeedAttrs, Factory, FactorySeed } from "./Factory-c16c27Y6.cjs";
|
|
3
3
|
import { ControlledTransaction, Insertable, Kysely, Selectable } from "kysely";
|
|
4
4
|
|
|
5
5
|
//#region src/KyselyFactory.d.ts
|
|
@@ -224,4 +224,4 @@ declare class KyselyFactory<DB, Builders extends Record<string, any>, Seeds exte
|
|
|
224
224
|
}
|
|
225
225
|
//#endregion
|
|
226
226
|
export { KyselyFactory };
|
|
227
|
-
//# sourceMappingURL=KyselyFactory-
|
|
227
|
+
//# sourceMappingURL=KyselyFactory-uZ45h7YU.d.cts.map
|
package/dist/KyselyFactory.d.cts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import "./faker-
|
|
2
|
-
import "./Factory-
|
|
3
|
-
import { KyselyFactory } from "./KyselyFactory-
|
|
1
|
+
import "./faker-DvxiCtxc.cjs";
|
|
2
|
+
import "./Factory-c16c27Y6.cjs";
|
|
3
|
+
import { KyselyFactory } from "./KyselyFactory-uZ45h7YU.cjs";
|
|
4
4
|
export { KyselyFactory };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { FakerFactory } from "./faker-
|
|
2
|
-
import { ExtractSeedAttrs, Factory, FactorySeed } from "./Factory-
|
|
1
|
+
import { FakerFactory } from "./faker-DvxiCtxc.cjs";
|
|
2
|
+
import { ExtractSeedAttrs, Factory, FactorySeed } from "./Factory-c16c27Y6.cjs";
|
|
3
3
|
import { Knex } from "knex";
|
|
4
4
|
import { Model } from "objection";
|
|
5
5
|
|
|
@@ -237,4 +237,4 @@ declare class ObjectionFactory<Builders extends Record<string, any>, Seeds exten
|
|
|
237
237
|
}
|
|
238
238
|
//#endregion
|
|
239
239
|
export { ObjectionFactory };
|
|
240
|
-
//# sourceMappingURL=ObjectionFactory-
|
|
240
|
+
//# sourceMappingURL=ObjectionFactory-CdhzKs4f.d.cts.map
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import "./faker-
|
|
2
|
-
import "./Factory-
|
|
3
|
-
import { ObjectionFactory } from "./ObjectionFactory-
|
|
1
|
+
import "./faker-DvxiCtxc.cjs";
|
|
2
|
+
import "./Factory-c16c27Y6.cjs";
|
|
3
|
+
import { ObjectionFactory } from "./ObjectionFactory-CdhzKs4f.cjs";
|
|
4
4
|
export { ObjectionFactory };
|
package/dist/better-auth.d.cts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import * as
|
|
1
|
+
import * as better_auth_adapters3 from "better-auth/adapters";
|
|
2
2
|
import { DBAdapterDebugLogOption } from "better-auth/adapters";
|
|
3
3
|
|
|
4
4
|
//#region src/better-auth.d.ts
|
|
@@ -7,7 +7,7 @@ interface MemoryAdapterConfig {
|
|
|
7
7
|
usePlural?: boolean;
|
|
8
8
|
initialData?: Record<string, any[]>;
|
|
9
9
|
}
|
|
10
|
-
declare const memoryAdapter: (config?: MemoryAdapterConfig, store?: Map<any, any>) =>
|
|
10
|
+
declare const memoryAdapter: (config?: MemoryAdapterConfig, store?: Map<any, any>) => better_auth_adapters3.AdapterFactory & {
|
|
11
11
|
clear: () => void;
|
|
12
12
|
getAllData: () => Record<string, any[]>;
|
|
13
13
|
getStore: () => Map<any, any>;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import * as
|
|
1
|
+
import * as _faker_js_faker2 from "@faker-js/faker";
|
|
2
2
|
|
|
3
3
|
//#region src/faker.d.ts
|
|
4
4
|
|
|
@@ -134,7 +134,7 @@ declare function coordinateOutsideRadius(center: Coordinate, minRadiusMeters: nu
|
|
|
134
134
|
* const productPrice = faker.price();
|
|
135
135
|
* ```
|
|
136
136
|
*/
|
|
137
|
-
declare const faker: Readonly<
|
|
137
|
+
declare const faker: Readonly<_faker_js_faker2.Faker & {
|
|
138
138
|
timestamps: typeof timestamps;
|
|
139
139
|
identifier: typeof identifier;
|
|
140
140
|
sequence: typeof sequence;
|
|
@@ -163,4 +163,4 @@ type Timestamps = {
|
|
|
163
163
|
type FakerFactory = typeof faker;
|
|
164
164
|
//#endregion
|
|
165
165
|
export { FakerFactory, Timestamps, coordinateInRadius, faker, identifier, resetAllSequences, resetSequence, sequence, timestamps };
|
|
166
|
-
//# sourceMappingURL=faker-
|
|
166
|
+
//# sourceMappingURL=faker-DvxiCtxc.d.cts.map
|
package/dist/faker.d.cts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { FakerFactory, Timestamps, coordinateInRadius, faker, identifier, resetAllSequences, resetSequence, sequence, timestamps } from "./faker-
|
|
1
|
+
import { FakerFactory, Timestamps, coordinateInRadius, faker, identifier, resetAllSequences, resetSequence, sequence, timestamps } from "./faker-DvxiCtxc.cjs";
|
|
2
2
|
export { FakerFactory, Timestamps, coordinateInRadius, faker, identifier, resetAllSequences, resetSequence, sequence, timestamps };
|
package/dist/kysely.d.cts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { FakerFactory, faker } from "./faker-
|
|
2
|
-
import { ExtractSeedAttrs, FactorySeed } from "./Factory-
|
|
3
|
-
import { KyselyFactory } from "./KyselyFactory-
|
|
1
|
+
import { FakerFactory, faker } from "./faker-DvxiCtxc.cjs";
|
|
2
|
+
import { ExtractSeedAttrs, FactorySeed } from "./Factory-c16c27Y6.cjs";
|
|
3
|
+
import { KyselyFactory } from "./KyselyFactory-uZ45h7YU.cjs";
|
|
4
4
|
import "./PostgresMigrator-D5UkK1_K.cjs";
|
|
5
5
|
import { PostgresKyselyMigrator } from "./PostgresKyselyMigrator-CQ3aUoy_.cjs";
|
|
6
6
|
import { DatabaseConnection, DatabaseFixtures, ExtendedDatabaseFixtures, FixtureCreators, IsolationLevel, TestWithExtendedFixtures, TransactionWrapperOptions } from "./VitestTransactionIsolator-CwQaxZLP.cjs";
|
package/dist/objection.d.cts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { FakerFactory, faker } from "./faker-
|
|
2
|
-
import { ExtractSeedAttrs, FactorySeed } from "./Factory-
|
|
3
|
-
import { ObjectionFactory } from "./ObjectionFactory-
|
|
1
|
+
import { FakerFactory, faker } from "./faker-DvxiCtxc.cjs";
|
|
2
|
+
import { ExtractSeedAttrs, FactorySeed } from "./Factory-c16c27Y6.cjs";
|
|
3
|
+
import { ObjectionFactory } from "./ObjectionFactory-CdhzKs4f.cjs";
|
|
4
4
|
import "./PostgresMigrator-D5UkK1_K.cjs";
|
|
5
5
|
import { PostgresObjectionMigrator } from "./PostgresObjectionMigrator-CZHHcCOv.cjs";
|
|
6
6
|
import { DatabaseConnection, DatabaseFixtures, ExtendedDatabaseFixtures, FixtureCreators, IsolationLevel, TestWithExtendedFixtures, TransactionWrapperOptions } from "./VitestTransactionIsolator-CwQaxZLP.cjs";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@geekmidas/testkit",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -51,11 +51,12 @@
|
|
|
51
51
|
}
|
|
52
52
|
},
|
|
53
53
|
"dependencies": {
|
|
54
|
-
"@faker-js/faker": "~9.9.0"
|
|
55
|
-
"@geekmidas/logger": "0.1.0"
|
|
54
|
+
"@faker-js/faker": "~9.9.0"
|
|
56
55
|
},
|
|
57
56
|
"devDependencies": {
|
|
58
|
-
"@types/pg": "~8.15.4"
|
|
57
|
+
"@types/pg": "~8.15.4",
|
|
58
|
+
"@geekmidas/logger": "^0.3.0",
|
|
59
|
+
"@geekmidas/envkit": "^0.2.0"
|
|
59
60
|
},
|
|
60
61
|
"repository": {
|
|
61
62
|
"type": "git",
|
|
@@ -74,6 +75,39 @@
|
|
|
74
75
|
"vitest": "~3.2.4",
|
|
75
76
|
"@types/aws-lambda": ">=8.10.92",
|
|
76
77
|
"better-auth": ">=1.3.34",
|
|
77
|
-
"@geekmidas/envkit": "0.
|
|
78
|
+
"@geekmidas/envkit": "^0.2.0",
|
|
79
|
+
"@geekmidas/logger": "^0.3.0"
|
|
80
|
+
},
|
|
81
|
+
"peerDependenciesMeta": {
|
|
82
|
+
"@geekmidas/envkit": {
|
|
83
|
+
"optional": true
|
|
84
|
+
},
|
|
85
|
+
"@geekmidas/logger": {
|
|
86
|
+
"optional": true
|
|
87
|
+
},
|
|
88
|
+
"kysely": {
|
|
89
|
+
"optional": true
|
|
90
|
+
},
|
|
91
|
+
"pg": {
|
|
92
|
+
"optional": true
|
|
93
|
+
},
|
|
94
|
+
"knex": {
|
|
95
|
+
"optional": true
|
|
96
|
+
},
|
|
97
|
+
"objection": {
|
|
98
|
+
"optional": true
|
|
99
|
+
},
|
|
100
|
+
"db-errors": {
|
|
101
|
+
"optional": true
|
|
102
|
+
},
|
|
103
|
+
"vitest": {
|
|
104
|
+
"optional": true
|
|
105
|
+
},
|
|
106
|
+
"@types/aws-lambda": {
|
|
107
|
+
"optional": true
|
|
108
|
+
},
|
|
109
|
+
"better-auth": {
|
|
110
|
+
"optional": true
|
|
111
|
+
}
|
|
78
112
|
}
|
|
79
113
|
}
|