Skip to content

Commit c7b40fe

Browse files
Chore: Add documentation
1 parent 651be30 commit c7b40fe

File tree

5 files changed

+659
-2
lines changed

5 files changed

+659
-2
lines changed

.vscode/extensions.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"recommendations": ["biomejs.biome", "DavidAnson.vscode-markdownlint"]
3+
}

.vscode/settings.json

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
"editor.defaultFormatter": "biomejs.biome"
1414
},
1515
"[markdown]": {
16-
"editor.defaultFormatter": "biomejs.biome"
16+
"editor.defaultFormatter": "DavidAnson.vscode-markdownlint"
1717
},
1818
"[typescript]": {
1919
"editor.defaultFormatter": "biomejs.biome"
@@ -22,5 +22,12 @@
2222
"**/.DS_Store": true,
2323
"**/.turbo": true,
2424
"**/node_modules": true
25+
},
26+
"markdownlint.config": {
27+
"MD010": {
28+
"spaces_per_tab": 4
29+
},
30+
"MD036": false,
31+
"MD041": false
2532
}
2633
}

packages/core/readme.md

Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
# `@kysely-vitest/core`
2+
3+
`@kysely-vitest/core` provides helper functions to create you custom adapter for `kysely-vitest`. An adapter consists in 3 functions:
4+
5+
- A `kysely` [dialect factory](#create-the-dialect-factory)
6+
- A `vitest` [plugin function](#create-the-plugin-function)
7+
- A `test` [function factory](#create-the-test-function-factory)
8+
9+
## Create the Dialect Factory
10+
11+
The dialect factory will be used to initialize the connection to the database when running migrations, seeding the database and running tests.
12+
13+
Here is an example on how to create you dialect factory function:
14+
15+
```ts
16+
// in src/tests/dialect.ts
17+
import type { DialectFactory } from "@kysely-vitest/core/types.js";
18+
import { MyDialect } from 'kysely/my-dialect';
19+
20+
export const MY_DIALECT_CONFIG_KEY = "myDialectConfig" as const;
21+
22+
export const myDialectFactory: DialectFactory<
23+
typeof MY_DIALECT_CONFIG_KEY
24+
> = (config) => {
25+
return new MyDialect({
26+
// Dialect configuration
27+
})
28+
};
29+
30+
// Extend vitest types
31+
declare module "vitest" {
32+
export type MyDialectConfig = {
33+
// Dialect options
34+
};
35+
36+
export interface ProvidedContext {
37+
myDialectConfig: MyDialectConfig;
38+
}
39+
}
40+
```
41+
42+
## Create the Plugin Function
43+
44+
Once your dialect function has been created, you can create the plugin function that will be used by `vitest` to run migrations, seed the database and configure your `test` function.
45+
46+
Here is an example on how to create your plugin:
47+
48+
```ts
49+
// in src/tests/plugin.ts
50+
import { createPlugin } from "@kysely-vitest/core/plugin.js";
51+
import { MY_DIALECT_CONFIG_KEY, myDialectFactory } from "./dialect.js";
52+
53+
export const kyselyPlugin = createPlugin({
54+
name: "plugin",
55+
configKey: MY_DIALECT_CONFIG_KEY,
56+
dialectFactory: myDialectFactory,
57+
});
58+
```
59+
60+
Then, you can use your plugin in the `vitest.config.ts` file:
61+
62+
```ts
63+
// in vitest.config.ts
64+
import path from "node:path";
65+
import { defineConfig } from "vitest/config";
66+
import type { DB } from "./src/db.js";
67+
import { kyselyPlugin } from "./src/tests/plugin.js";
68+
69+
export default defineConfig({
70+
plugins: [
71+
// Other plugins
72+
kyselyPlugin<DB>({
73+
config: {
74+
// Your dialect configuration
75+
},
76+
migrationFolder: path.resolve(__dirname, "migrations"),
77+
}),
78+
],
79+
test: {
80+
// Test configuration
81+
},
82+
});
83+
```
84+
85+
Note: You can use also use a [`seed`](#seeding) function with your plugin.
86+
87+
## Create the Test Function Factory
88+
89+
Once your plugin has been configured, you can create your `test` function. Here is an example of a `dbTest` function:
90+
91+
```ts
92+
// in src/tests/dbTest.ts
93+
import { createTestFunction } from "@kysely-vitest/core/test.js";
94+
import { MY_DIALECT_CONFIG_KEY, myDialectFactory } from "./dialect.js";
95+
import type { DB } from "../db.js";
96+
97+
export const dbTest = createTestFunction<typeof MY_DIALECT_CONFIG_KEY, DB>({
98+
configKey: MY_DIALECT_CONFIG_KEY,
99+
dialectFactory: myDialectFactory,
100+
});
101+
```
102+
103+
Then you can use your test function inside your test suites:
104+
105+
```ts
106+
// in src/myTestSuite.spec.ts
107+
import { describe, expect } from "vitest";
108+
import { dbTest } from "./tests/dbTest.js";
109+
110+
describe("myTestSuite", () => {
111+
dbTest("my test", async ({ db }) => {
112+
// ...
113+
});
114+
});
115+
```
116+
117+
Note: The `db` parameter is a transaction that is rolled back after the test to ensure that each test runs in isolation.
118+
119+
## Seeding
120+
121+
You can provide a seeding function to your adapter to seed your database before running the tests. Here is an example with your custom adapter:
122+
123+
First create your `seed` function in `src/tests/seed.js`:
124+
125+
```ts
126+
// in src/tests/seed.js
127+
import type { SeedFunction } from "@kysely-vitest/core/types.js";
128+
import { sql } from "kysely";
129+
import type { DB } from "../db.js";
130+
131+
export const seed: SeedFunction<DB> = async (db) => {
132+
await sql<void>`TRUNCATE TABLE "users" RESTART IDENTITY CASCADE`.execute(db);
133+
134+
await db
135+
.insertInto("users")
136+
.values([{ username: "alice" }, { username: "bob" }])
137+
.execute();
138+
};
139+
```
140+
141+
Then configure the plugin in `vitest.config.ts` to use your `seed` function:
142+
143+
```ts
144+
// in vitest.config.ts
145+
import path from "node:path";
146+
import { defineConfig } from "vitest/config";
147+
import type { DB } from "./src/db.js";
148+
import { kyselyPlugin } from "./src/tests/plugin.js";
149+
import { seed } from "./src/tests/seed.js";
150+
151+
export default defineConfig({
152+
plugins: [
153+
// Other plugins
154+
kyselyPlugin<DB>({
155+
// Configure the plugin
156+
seed,
157+
}),
158+
],
159+
test: {
160+
// Test configuration
161+
},
162+
});
163+
```
164+
165+
Note: The seeding function will be run once before running your tests suite and will not run on test reload.

packages/postgres/readme.md

Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
# `@kysely-vitest/postgres`
2+
3+
`@kysely-vitest/postgres` provides helpers to test your modules that depends on [`kysely`](https://kysely.dev/) to query your PostgreSQL database.
4+
5+
## Install
6+
7+
`kysely-vitest` depends on `kysely@^0.28.0`, `kysely-postgres-js` and `vitest@^4.0.0` as peer dependencies. Run one of the following commands to install the dependencies:
8+
9+
```shell
10+
npm install kysely kysely-postgres-js && npm install -D vitest @kysely-vitest/postgres
11+
# or
12+
yarn add kysely kysely-postgres-js && yarn add -D vitest @kysely-vitest/postgres
13+
# or
14+
pnpm add kysely kysely-postgres-js && pnpm add -D vitest @kysely-vitest/postgres
15+
```
16+
17+
Then, you can define your [database types](https://kysely.dev/docs/getting-started#types) in `src/db.ts`:
18+
19+
```ts
20+
// in src/db.ts
21+
export type DB = {
22+
// ...
23+
};
24+
```
25+
26+
## Configure the Plugin
27+
28+
First, we will register the `kyselyPostgres` plugin in `vitest.config.ts`:
29+
30+
```ts
31+
// in vitest.config.ts
32+
import path from "node:path";
33+
import { kyselyPostgres } from "@kysely-vitest/postgres/plugin.js";
34+
import { defineConfig } from "vitest/config";
35+
import type { DB } from "./src/db.js";
36+
37+
export default defineConfig({
38+
plugins: [
39+
// Other plugins
40+
kyselyPostgres<DB>({
41+
config: {
42+
database: "testdb",
43+
username: "test",
44+
password: "test",
45+
},
46+
migrationFolder: path.resolve(__dirname, "migrations"),
47+
}),
48+
],
49+
test: {
50+
// Test configuration
51+
},
52+
});
53+
```
54+
55+
Then we can create the `pgTest` function in `src/tests/pgTest.ts` that will be used in our test suite:
56+
57+
```ts
58+
// in src/tests/pgTest.ts
59+
import { createPostgresTestFunction } from "@kysely-vitest/postgres/test.js";
60+
import type { DB } from "../db.js";
61+
62+
export const pgTest = createPostgresTestFunction<DB>();
63+
```
64+
65+
Note: The test function will create a database client by worker.
66+
67+
## Create a Test
68+
69+
To run a test on your database, use the `pgTest` function instead of the `it/test` function provided by `vitest`. Note that `pgTest` is an extension of `it/test` and can be used exactly as the base function.
70+
71+
```ts
72+
// in src/myTestSuite.spec.ts
73+
import { describe, expect } from "vitest";
74+
import { pgTest } from "./tests/pgTest.js";
75+
76+
describe("myTestSuite", () => {
77+
pgTest("my test", async ({ db }) => {
78+
// ...
79+
});
80+
});
81+
```
82+
83+
Note: The `db` parameter is a transaction that is rolled back after the test to ensure that each test runs in isolation.
84+
85+
## Run your Test Suite
86+
87+
To run you test suite, you will need to start a PostgreSQL database. The `@kysely-vitest/postgres` plugin will automatically run your migrations on that database.
88+
89+
You use the following `docker-compose.yml` file to run your test database:
90+
91+
```yml
92+
# in docker-compose.yml
93+
services:
94+
postgres:
95+
image: postgres:18-alpine
96+
environment:
97+
POSTGRES_DB: testdb
98+
POSTGRES_USER: test
99+
POSTGRES_PASSWORD: test
100+
ports:
101+
- "5432:5432"
102+
healthcheck:
103+
test: ["CMD-SHELL", "pg_isready -U test"]
104+
interval: 10s
105+
timeout: 5s
106+
retries: 5
107+
```
108+
109+
Then run your test suite with the following commands:
110+
111+
```shell
112+
# Start test database
113+
docker compose up --wait
114+
115+
# Run you tests
116+
npx vitest
117+
# or
118+
yarn vitest
119+
# or
120+
pnpm vitest
121+
122+
# Stop test database an cleanup volumes
123+
docker compose down --volumes
124+
```
125+
126+
## Seeding
127+
128+
You can provide a seeding function to the `@kysely-vitest/postgres` adapter to seed your database before running the tests.
129+
130+
First create your `seed` function in `src/tests/seed.js`:
131+
132+
```ts
133+
// in src/tests/seed.js
134+
import type { SeedFunction } from "@kysely-vitest/postgres/types.js";
135+
import { sql } from "kysely";
136+
import type { DB } from "../db.js";
137+
138+
export const seed: SeedFunction<DB> = async (db) => {
139+
await sql<void>`TRUNCATE TABLE "users" RESTART IDENTITY CASCADE`.execute(db);
140+
141+
await db
142+
.insertInto("users")
143+
.values([{ username: "alice" }, { username: "bob" }])
144+
.execute();
145+
};
146+
```
147+
148+
Then configure the `kyselyPostgres` plugin in `vitest.config.ts` to use your `seed` function:
149+
150+
```ts
151+
// in vitest.config.ts
152+
import path from "node:path";
153+
import { kyselyPostgres } from "@kysely-vitest/postgres/plugin.js";
154+
import { defineConfig } from "vitest/config";
155+
import type { DB } from "./src/db.js";
156+
import { seed } from "./src/tests/seed.js";
157+
158+
export default defineConfig({
159+
plugins: [
160+
// Other plugins
161+
kyselyPostgres<DB>({
162+
// Configure the plugin
163+
seed,
164+
}),
165+
],
166+
test: {
167+
// Test configuration
168+
},
169+
});
170+
```
171+
172+
Note: The seeding function will be run once before running your tests suite and will not run on test reload.

0 commit comments

Comments
 (0)