neon-testing 2.0.1-beta.9 → 2.1.1
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 +94 -23
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/singleton.d.ts +1 -0
- package/dist/singleton.d.ts.map +1 -0
- package/dist/utils.d.ts +1 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/vite-plugin.d.ts +9 -1
- package/dist/vite-plugin.d.ts.map +1 -0
- package/dist/vite-plugin.js +10 -4
- package/dist/vite-plugin.js.map +1 -1
- package/dist/vitest-setup.d.ts +3 -0
- package/dist/vitest-setup.d.ts.map +1 -0
- package/dist/vitest-setup.js +7 -8
- package/dist/vitest-setup.js.map +1 -0
- package/package.json +8 -14
- package/vitest-setup.js +0 -11
package/README.md
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
# Neon
|
|
1
|
+
# Neon Testing
|
|
2
2
|
|
|
3
3
|
[](https://github.com/starmode-base/neon-testing/actions/workflows/test.yml)
|
|
4
|
+
[](https://www.npmjs.com/package/neon-testing)
|
|
5
|
+
[](https://github.com/starmode-base/neon-testing/releases)
|
|
4
6
|
|
|
5
|
-
A [Vitest](https://vitest.dev/) utility for seamless integration tests with [Neon Postgres](https://neon.com/).
|
|
7
|
+
A [Vitest](https://vitest.dev/) utility for seamless integration tests with [Neon Postgres](https://neon.com/). <!-- A [STΛR MODΞ](https://starmode.dev) open-source project. -->
|
|
6
8
|
|
|
7
9
|
Each test file runs against its own isolated PostgreSQL database (Neon branch), ensuring clean, parallel, and reproducible testing of code that interacts with a database. Because it uses a real, isolated clone of your production database, you can test code logic that depends on database features, such as transaction rollbacks, unique constraints, and more.
|
|
8
10
|
|
|
@@ -13,7 +15,7 @@ Each test file runs against its own isolated PostgreSQL database (Neon branch),
|
|
|
13
15
|
- 🔄 **Isolated test environments** - Each test file runs against its own Postgres database with your actual schema and constraints
|
|
14
16
|
- 🧹 **Automatic cleanup** - Neon test branches are created and destroyed automatically
|
|
15
17
|
- 🐛 **Debug friendly** - Option to preserve test branches for debugging failed tests
|
|
16
|
-
- 🛡️ **TypeScript native** -
|
|
18
|
+
- 🛡️ **TypeScript native** - With JavaScript support
|
|
17
19
|
- 🎯 **ESM only** - No CommonJS support
|
|
18
20
|
|
|
19
21
|
## How it works
|
|
@@ -41,12 +43,12 @@ If you prefer individual tests to be isolated, you can [reset the database](exam
|
|
|
41
43
|
### Install
|
|
42
44
|
|
|
43
45
|
```sh
|
|
44
|
-
bun add -d neon-testing
|
|
46
|
+
bun add -d neon-testing vitest
|
|
45
47
|
```
|
|
46
48
|
|
|
47
49
|
### Minimal example
|
|
48
50
|
|
|
49
|
-
```
|
|
51
|
+
```ts
|
|
50
52
|
// minimal.test.ts
|
|
51
53
|
import { expect, test } from "vitest";
|
|
52
54
|
import { makeNeonTesting } from "neon-testing";
|
|
@@ -73,11 +75,27 @@ test("database operations", async () => {
|
|
|
73
75
|
|
|
74
76
|
### Recommended usage
|
|
75
77
|
|
|
76
|
-
#### 1.
|
|
78
|
+
#### 1. Plugin setup
|
|
79
|
+
|
|
80
|
+
First, add the Vite plugin to clear any existing `DATABASE_URL` environment variable before tests run, ensuring tests use isolated test databases.
|
|
81
|
+
|
|
82
|
+
```ts
|
|
83
|
+
// vitest.config.ts or vite.config.ts
|
|
84
|
+
import { defineConfig } from "vitest/config";
|
|
85
|
+
import { neonTesting } from "neon-testing/utils";
|
|
86
|
+
|
|
87
|
+
export default defineConfig({
|
|
88
|
+
plugins: [neonTesting()],
|
|
89
|
+
});
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
This plugin is recommended but not required. Without it, tests might accidentally use your existing `DATABASE_URL` (from `.env` files or environment variables) instead of the isolated test databases that Neon Testing creates. This can happen if you forget to call `withNeonTestBranch()` in a test file where database writes happen.
|
|
93
|
+
|
|
94
|
+
#### 2. Configuration
|
|
77
95
|
|
|
78
96
|
Use the `makeNeonTesting` factory to generate a lifecycle function for your tests.
|
|
79
97
|
|
|
80
|
-
```
|
|
98
|
+
```ts
|
|
81
99
|
// test-setup.ts
|
|
82
100
|
import { makeNeonTesting } from "neon-testing";
|
|
83
101
|
|
|
@@ -88,11 +106,11 @@ export const withNeonTestBranch = makeNeonTesting({
|
|
|
88
106
|
});
|
|
89
107
|
```
|
|
90
108
|
|
|
91
|
-
####
|
|
109
|
+
#### 3. Enable database testing
|
|
92
110
|
|
|
93
111
|
Then call the exported test lifecycle function in the test files where you need database access.
|
|
94
112
|
|
|
95
|
-
```
|
|
113
|
+
```ts
|
|
96
114
|
// recommended.test.ts
|
|
97
115
|
import { expect, test } from "vitest";
|
|
98
116
|
import { withNeonTestBranch } from "./test-setup";
|
|
@@ -134,18 +152,66 @@ This library works with any database driver that supports Neon Postgres and Vite
|
|
|
134
152
|
|
|
135
153
|
## Configuration
|
|
136
154
|
|
|
137
|
-
You configure
|
|
155
|
+
You configure Neon Testing in two places:
|
|
138
156
|
|
|
139
157
|
- **Base settings** in `makeNeonTesting()`
|
|
140
158
|
- **Optional overrides** in `withNeonTestBranch()`
|
|
141
159
|
|
|
142
|
-
|
|
160
|
+
Configure these in `makeNeonTesting()` and optionally override per test file via `withNeonTestBranch()`.
|
|
161
|
+
|
|
162
|
+
```ts
|
|
163
|
+
export interface NeonTestingOptions {
|
|
164
|
+
/**
|
|
165
|
+
* The Neon API key, this is used to create and teardown test branches
|
|
166
|
+
*
|
|
167
|
+
* https://neon.com/docs/manage/api-keys#creating-api-keys
|
|
168
|
+
*/
|
|
169
|
+
apiKey: string;
|
|
170
|
+
/**
|
|
171
|
+
* The Neon project ID to operate on
|
|
172
|
+
*
|
|
173
|
+
* https://console.neon.tech/app/projects
|
|
174
|
+
*/
|
|
175
|
+
projectId: string;
|
|
176
|
+
/**
|
|
177
|
+
* The parent branch ID for the new branch. If omitted or empty, the branch
|
|
178
|
+
* will be created from the project's default branch.
|
|
179
|
+
*/
|
|
180
|
+
parentBranchId?: string;
|
|
181
|
+
/**
|
|
182
|
+
* Whether to create a schema-only branch (default: false)
|
|
183
|
+
*/
|
|
184
|
+
schemaOnly?: boolean;
|
|
185
|
+
/**
|
|
186
|
+
* The type of connection to create (pooler is recommended)
|
|
187
|
+
*/
|
|
188
|
+
endpoint?: "pooler" | "direct";
|
|
189
|
+
/**
|
|
190
|
+
* Delete the test branch in afterAll (default: true)
|
|
191
|
+
*
|
|
192
|
+
* Disabling this will leave each test branch in the Neon project after the
|
|
193
|
+
* test suite runs
|
|
194
|
+
*/
|
|
195
|
+
deleteBranch?: boolean;
|
|
196
|
+
/**
|
|
197
|
+
* Automatically close Neon WebSocket connections opened during tests before
|
|
198
|
+
* deleting the branch (default: false)
|
|
199
|
+
*
|
|
200
|
+
* Suppresses the specific Neon WebSocket "Connection terminated unexpectedly"
|
|
201
|
+
* error that may surface when deleting a branch with open WebSocket
|
|
202
|
+
* connections
|
|
203
|
+
*/
|
|
204
|
+
autoCloseWebSockets?: boolean;
|
|
205
|
+
}
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
See all available options in [NeonTestingOptions](index.ts#L31-L73).
|
|
143
209
|
|
|
144
210
|
### Base configuration
|
|
145
211
|
|
|
146
212
|
Configure the base settings in `makeNeonTesting()`:
|
|
147
213
|
|
|
148
|
-
```
|
|
214
|
+
```ts
|
|
149
215
|
import { makeNeonTesting } from "neon-testing";
|
|
150
216
|
|
|
151
217
|
export const withNeonTestBranch = makeNeonTesting({
|
|
@@ -158,32 +224,41 @@ export const withNeonTestBranch = makeNeonTesting({
|
|
|
158
224
|
|
|
159
225
|
Override the base configuration in specific test files with `withNeonTestBranch()`:
|
|
160
226
|
|
|
161
|
-
```
|
|
227
|
+
```ts
|
|
162
228
|
import { withNeonTestBranch } from "./test-setup";
|
|
163
229
|
|
|
164
230
|
withNeonTestBranch({ parentBranchId: "br-staging-123" });
|
|
165
231
|
```
|
|
166
232
|
|
|
233
|
+
## Continuous integration
|
|
234
|
+
|
|
235
|
+
It's easy to run Neon integration tests in CI/CD pipelines:
|
|
236
|
+
|
|
237
|
+
- **GitHub Actions** — see the [example workflow](.github/workflows/test.yml)
|
|
238
|
+
- **Vercel** — either
|
|
239
|
+
- add `vitest run` to the `build` script in [package.json](https://github.com/starmode-base/template-tanstack-start/blob/83c784e164b55fd8d59c5b57b907251e5eb03de1/app/package.json#L11), or
|
|
240
|
+
- add `vitest run` to the _Build Command_ in the Vercel dashboard
|
|
241
|
+
|
|
167
242
|
## Utilities
|
|
168
243
|
|
|
169
244
|
### deleteAllTestBranches()
|
|
170
245
|
|
|
171
246
|
The `deleteAllTestBranches()` function is a utility that deletes all test branches from your Neon project. This is useful for cleanup when tests fail unexpectedly and leave orphaned test branches.
|
|
172
247
|
|
|
173
|
-
```
|
|
248
|
+
```ts
|
|
174
249
|
import { withNeonTestBranch } from "./test-setup";
|
|
175
250
|
|
|
176
251
|
// Access the cleanup utility
|
|
177
252
|
await withNeonTestBranch.deleteAllTestBranches();
|
|
178
253
|
```
|
|
179
254
|
|
|
180
|
-
The function identifies test branches by looking for the `integration-test: true` annotation that
|
|
255
|
+
The function identifies test branches by looking for the `integration-test: true` annotation that Neon Testing automatically adds to all test branches it creates.
|
|
181
256
|
|
|
182
257
|
### lazySingleton()
|
|
183
258
|
|
|
184
259
|
The `lazySingleton()` function creates a lazy singleton from a factory function. This is useful for managing database connections efficiently:
|
|
185
260
|
|
|
186
|
-
```
|
|
261
|
+
```ts
|
|
187
262
|
import { lazySingleton } from "neon-testing/utils";
|
|
188
263
|
import { neon } from "@neondatabase/serverless";
|
|
189
264
|
|
|
@@ -219,12 +294,8 @@ bun run release
|
|
|
219
294
|
|
|
220
295
|
The command will abort if there are uncommitted changes in the working tree, or if the `version` in [package.json](package.json) has not been incremented.
|
|
221
296
|
|
|
222
|
-
##
|
|
223
|
-
|
|
224
|
-
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
|
225
|
-
|
|
226
|
-
## Need help?
|
|
297
|
+
## Author
|
|
227
298
|
|
|
228
|
-
Hi, I
|
|
299
|
+
Hi, I'm [Mikael Lirbank](https://www.lirbank.com/). I build robust, reliable, high-quality AI systems. I care deeply about quality—AI evals, robust test suites, clean data models, and clean architecture.
|
|
229
300
|
|
|
230
|
-
|
|
301
|
+
Need help building elegant systems? [I'm happy to help](https://www.lirbank.com/).
|
package/dist/index.d.ts
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AA8BA,MAAM,WAAW,kBAAkB;IACjC;;;;OAIG;IACH,MAAM,EAAE,MAAM,CAAC;IACf;;;;OAIG;IACH,SAAS,EAAE,MAAM,CAAC;IAClB;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;;OAEG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;OAEG;IACH,QAAQ,CAAC,EAAE,QAAQ,GAAG,QAAQ,CAAC;IAC/B;;;;;OAKG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB;;;;;;;OAOG;IACH,mBAAmB,CAAC,EAAE,OAAO,CAAC;CAC/B;AAED,mEAAmE;AACnE,MAAM,MAAM,oBAAoB,GAAG,IAAI,CAAC,OAAO,CAAC,kBAAkB,CAAC,EAAE,QAAQ,CAAC,CAAC;AAE/E;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,eAAe,CAAC,cAAc,EAAE,kBAAkB;iBA0BlD,oBAAoB;;EAmGnC"}
|
package/dist/singleton.d.ts
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"singleton.d.ts","sourceRoot":"","sources":["../singleton.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,wBAAgB,aAAa,CAAC,CAAC,EAAE,OAAO,EAAE,MAAM,CAAC,GAAG,MAAM,CAAC,CAM1D"}
|
package/dist/utils.d.ts
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC"}
|
package/dist/vite-plugin.d.ts
CHANGED
|
@@ -1,2 +1,10 @@
|
|
|
1
1
|
import type { Plugin } from "vite";
|
|
2
|
-
export declare function neonTesting(
|
|
2
|
+
export declare function neonTesting(options?: {
|
|
3
|
+
/**
|
|
4
|
+
* Enable debug logging.
|
|
5
|
+
*
|
|
6
|
+
* @default false
|
|
7
|
+
*/
|
|
8
|
+
debug?: boolean;
|
|
9
|
+
}): Plugin;
|
|
10
|
+
//# sourceMappingURL=vite-plugin.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vite-plugin.d.ts","sourceRoot":"","sources":["../vite-plugin.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AAEnC,wBAAgB,WAAW,CACzB,OAAO,GAAE;IACP;;;;OAIG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;CACZ,GACL,MAAM,CAyBR"}
|
package/dist/vite-plugin.js
CHANGED
|
@@ -1,14 +1,20 @@
|
|
|
1
1
|
import { fileURLToPath } from "node:url";
|
|
2
|
-
export function neonTesting() {
|
|
2
|
+
export function neonTesting(options = {}) {
|
|
3
3
|
return {
|
|
4
4
|
name: "neon-testing-plugin",
|
|
5
|
-
|
|
5
|
+
// Run as late as possible to reduce the risk of other plugins restoring
|
|
6
|
+
// DATABASE_URL after we clear it
|
|
7
|
+
enforce: "post",
|
|
6
8
|
config(user) {
|
|
7
9
|
const setupPath = fileURLToPath(new URL("./vitest-setup.js", import.meta.url));
|
|
8
|
-
const setup = new Set([...(user.test?.setupFiles ?? []), setupPath]);
|
|
9
10
|
return {
|
|
10
11
|
test: {
|
|
11
|
-
|
|
12
|
+
// Register the vitest-setup.js file to run after other setup files
|
|
13
|
+
setupFiles: Array.from(new Set([...(user.test?.setupFiles ?? []), setupPath])),
|
|
14
|
+
env: {
|
|
15
|
+
...user.test?.env,
|
|
16
|
+
NEON_TESTING_DEBUG: options.debug ? "true" : "false",
|
|
17
|
+
},
|
|
12
18
|
},
|
|
13
19
|
};
|
|
14
20
|
},
|
package/dist/vite-plugin.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vite-plugin.js","sourceRoot":"","sources":["../vite-plugin.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAGzC,MAAM,UAAU,WAAW;
|
|
1
|
+
{"version":3,"file":"vite-plugin.js","sourceRoot":"","sources":["../vite-plugin.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAGzC,MAAM,UAAU,WAAW,CACzB,UAOI,EAAE;IAEN,OAAO;QACL,IAAI,EAAE,qBAAqB;QAC3B,wEAAwE;QACxE,iCAAiC;QACjC,OAAO,EAAE,MAAM;QACf,MAAM,CAAC,IAAI;YACT,MAAM,SAAS,GAAG,aAAa,CAC7B,IAAI,GAAG,CAAC,mBAAmB,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAC9C,CAAC;YAEF,OAAO;gBACL,IAAI,EAAE;oBACJ,mEAAmE;oBACnE,UAAU,EAAE,KAAK,CAAC,IAAI,CACpB,IAAI,GAAG,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,UAAU,IAAI,EAAE,CAAC,EAAE,SAAS,CAAC,CAAC,CACvD;oBACD,GAAG,EAAE;wBACH,GAAG,IAAI,CAAC,IAAI,EAAE,GAAG;wBACjB,kBAAkB,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO;qBACrD;iBACF;aACF,CAAC;QACJ,CAAC;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vitest-setup.d.ts","sourceRoot":"","sources":["../vitest-setup.ts"],"names":[],"mappings":"AAAA,QAAA,MAAM,QAAQ,oBAAqB,CAAC;AACpC,QAAA,MAAM,OAAO,SAA4C,CAAC"}
|
package/dist/vitest-setup.js
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
1
2
|
const isVitest = process.env.VITEST;
|
|
2
|
-
|
|
3
|
+
const isDebug = process.env.NEON_TESTING_DEBUG === "true";
|
|
3
4
|
if (isVitest) {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
delete process.env.DATABASE_URL;
|
|
5
|
+
if (process.env.DATABASE_URL && isDebug) {
|
|
6
|
+
console.debug("[neon-testing] Clearing existing DATABASE_URL in test environment");
|
|
7
|
+
}
|
|
8
|
+
delete process.env.DATABASE_URL;
|
|
11
9
|
}
|
|
10
|
+
//# sourceMappingURL=vitest-setup.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vitest-setup.js","sourceRoot":"","sources":["../vitest-setup.ts"],"names":[],"mappings":";AAAA,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC;AACpC,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,kBAAkB,KAAK,MAAM,CAAC;AAE1D,IAAI,QAAQ,EAAE,CAAC;IACb,IAAI,OAAO,CAAC,GAAG,CAAC,YAAY,IAAI,OAAO,EAAE,CAAC;QACxC,OAAO,CAAC,KAAK,CACX,mEAAmE,CACpE,CAAC;IACJ,CAAC;IAED,OAAO,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC;AAClC,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "neon-testing",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.1.1",
|
|
4
4
|
"description": "A Vitest utility for seamless integration tests with Neon Postgres",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"neon",
|
|
@@ -22,26 +22,20 @@
|
|
|
22
22
|
"./utils": {
|
|
23
23
|
"types": "./dist/utils.d.ts",
|
|
24
24
|
"import": "./dist/utils.js"
|
|
25
|
-
},
|
|
26
|
-
"./vite-plugin": {
|
|
27
|
-
"types": "./dist/vite-plugin.d.ts",
|
|
28
|
-
"import": "./dist/vite-plugin.js"
|
|
29
25
|
}
|
|
30
26
|
},
|
|
31
|
-
"types": "./dist/index.d.ts",
|
|
32
27
|
"files": [
|
|
33
|
-
"dist"
|
|
34
|
-
"vitest-setup.js"
|
|
28
|
+
"dist"
|
|
35
29
|
],
|
|
36
30
|
"scripts": {
|
|
31
|
+
"build": "rm -rf dist && tsc",
|
|
37
32
|
"test": "vitest",
|
|
38
33
|
"format": "prettier --write .",
|
|
39
|
-
"
|
|
40
|
-
"release:patch": "bun pm version patch && bun publish --tag latest",
|
|
41
|
-
"release:minor": "bun pm version minor && bun publish --tag latest",
|
|
42
|
-
"release:major": "bun pm version major && bun publish --tag latest",
|
|
43
|
-
"release:beta": "bun pm version prerelease --preid=beta && bun publish --tag beta",
|
|
44
|
-
"prepublishOnly": "bun run build && vitest run && prettier --check .",
|
|
34
|
+
"check": "bun run build && bunx vitest run && bunx prettier --check .",
|
|
35
|
+
"release:patch": "bun run check && bun pm version patch && bun publish --tag latest",
|
|
36
|
+
"release:minor": "bun run check && bun pm version minor && bun publish --tag latest",
|
|
37
|
+
"release:major": "bun run check && bun pm version major && bun publish --tag latest",
|
|
38
|
+
"release:beta": "bun run check && bun pm version prerelease --preid=beta && bun publish --tag beta",
|
|
45
39
|
"postpublish": "git push --follow-tags"
|
|
46
40
|
},
|
|
47
41
|
"dependencies": {
|
package/vitest-setup.js
DELETED