neon-testing 2.7.0 → 3.0.0-beta.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 +58 -41
- package/package.json +49 -39
- package/src/bun.ts +13 -0
- package/src/core.ts +372 -0
- package/src/lib/barrier.ts +22 -0
- package/src/lib/expires-in.ts +24 -0
- package/src/lib/singleton.ts +10 -0
- package/src/lib/ssl.ts +24 -0
- package/src/lib/with-retry.ts +55 -0
- package/src/lib/ws-error.ts +17 -0
- package/src/setup.ts +8 -0
- package/src/utils.ts +2 -0
- package/src/vitest.ts +12 -0
- package/dist/barrier.d.ts +0 -6
- package/dist/barrier.d.ts.map +0 -1
- package/dist/barrier.js +0 -19
- package/dist/barrier.js.map +0 -1
- package/dist/browser-empty.d.ts +0 -2
- package/dist/browser-empty.d.ts.map +0 -1
- package/dist/browser-empty.js +0 -4
- package/dist/browser-empty.js.map +0 -1
- package/dist/index.d.ts +0 -128
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js +0 -292
- package/dist/index.js.map +0 -1
- package/dist/singleton.d.ts +0 -5
- package/dist/singleton.d.ts.map +0 -1
- package/dist/singleton.js +0 -11
- package/dist/singleton.js.map +0 -1
- package/dist/utils.d.ts +0 -9
- package/dist/utils.d.ts.map +0 -1
- package/dist/utils.js +0 -9
- package/dist/utils.js.map +0 -1
- package/dist/vite-plugin.d.ts +0 -13
- package/dist/vite-plugin.d.ts.map +0 -1
- package/dist/vite-plugin.js +0 -26
- package/dist/vite-plugin.js.map +0 -1
- package/dist/vitest-setup.d.ts +0 -3
- package/dist/vitest-setup.d.ts.map +0 -1
- package/dist/vitest-setup.js +0 -10
- package/dist/vitest-setup.js.map +0 -1
package/README.md
CHANGED
|
@@ -5,7 +5,9 @@
|
|
|
5
5
|
[](https://github.com/starmode-base/neon-testing/releases)
|
|
6
6
|
[](LICENSE)
|
|
7
7
|
|
|
8
|
-
A
|
|
8
|
+
A testing utility for seamless integration tests with [Neon Postgres](https://neon.com/), for [Vitest](https://vitest.dev/) and [Bun Test](https://bun.com/docs/cli/test).
|
|
9
|
+
|
|
10
|
+
<!-- A [STΛR MODΞ](https://starmode.dev) open-source project. -->
|
|
9
11
|
|
|
10
12
|
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.
|
|
11
13
|
|
|
@@ -29,7 +31,7 @@ Each test file runs against its own isolated PostgreSQL database (Neon branch),
|
|
|
29
31
|
- 🔄 **Isolated test environments** - Each test file runs against its own Postgres database with your actual schema and constraints
|
|
30
32
|
- 🧹 **Automatic cleanup** - Neon test branches are created and destroyed automatically
|
|
31
33
|
- 🐛 **Debug friendly** - Option to preserve test branches for debugging failed tests
|
|
32
|
-
- 🛡️ **TypeScript
|
|
34
|
+
- 🛡️ **TypeScript only** - Ships TypeScript source files
|
|
33
35
|
- 🎯 **ESM only** - No CommonJS support
|
|
34
36
|
|
|
35
37
|
## How it works
|
|
@@ -41,7 +43,9 @@ Each test file runs against its own isolated PostgreSQL database (Neon branch),
|
|
|
41
43
|
|
|
42
44
|
### Test isolation
|
|
43
45
|
|
|
44
|
-
|
|
46
|
+
Each test file runs against its own database instance (Neon branch), so test files are fully isolated from each other. Tests within a single file share that branch and run sequentially — individual tests within a file are intentionally not isolated.
|
|
47
|
+
|
|
48
|
+
Vitest and Bun differ in how they execute files. Vitest runs each file in its own process, [in parallel](https://vitest.dev/guide/parallelism.html), while Bun runs every file in [a single shared process](https://bun.com/docs/test), one after another by default. File-level isolation is the same on both — each file gets its own branch — but Vitest creates those branches concurrently whereas Bun creates them one at a time.
|
|
45
49
|
|
|
46
50
|
If you prefer individual tests to be isolated, you can [reset the database](examples/isolated.test.ts) in a `beforeEach` lifecycle hook.
|
|
47
51
|
|
|
@@ -59,7 +63,11 @@ Test branches are automatically deleted after your tests complete. As a safety n
|
|
|
59
63
|
### Install
|
|
60
64
|
|
|
61
65
|
```sh
|
|
66
|
+
# Vitest
|
|
62
67
|
bun add -d neon-testing vitest
|
|
68
|
+
|
|
69
|
+
# Bun Test
|
|
70
|
+
bun add -d neon-testing
|
|
63
71
|
```
|
|
64
72
|
|
|
65
73
|
### Minimal example
|
|
@@ -67,7 +75,7 @@ bun add -d neon-testing vitest
|
|
|
67
75
|
```ts
|
|
68
76
|
// minimal.test.ts
|
|
69
77
|
import { expect, test } from "vitest";
|
|
70
|
-
import { makeNeonTesting } from "neon-testing";
|
|
78
|
+
import { makeNeonTesting } from "neon-testing/vitest";
|
|
71
79
|
import { Pool } from "@neondatabase/serverless";
|
|
72
80
|
|
|
73
81
|
// Enable Neon test branch for this test file
|
|
@@ -75,6 +83,7 @@ makeNeonTesting({
|
|
|
75
83
|
apiKey: process.env.NEON_API_KEY!,
|
|
76
84
|
projectId: process.env.NEON_PROJECT_ID!,
|
|
77
85
|
// Recommended for Neon WebSocket drivers to automatically close connections
|
|
86
|
+
// (Vitest only)
|
|
78
87
|
autoCloseWebSockets: true,
|
|
79
88
|
})();
|
|
80
89
|
|
|
@@ -93,21 +102,29 @@ Source: [`examples/minimal.test.ts`](examples/minimal.test.ts)
|
|
|
93
102
|
|
|
94
103
|
### Recommended usage
|
|
95
104
|
|
|
96
|
-
#### 1.
|
|
105
|
+
#### 1. Setup
|
|
97
106
|
|
|
98
|
-
|
|
107
|
+
Register `neon-testing/setup` so any existing `DATABASE_URL` is cleared before tests run. A test file that forgets to enable branching then fails loudly instead of silently writing to a real database.
|
|
99
108
|
|
|
100
109
|
```ts
|
|
101
110
|
// vitest.config.ts
|
|
102
111
|
import { defineConfig } from "vitest/config";
|
|
103
|
-
import { neonTesting } from "neon-testing/vite";
|
|
104
112
|
|
|
105
113
|
export default defineConfig({
|
|
106
|
-
|
|
114
|
+
test: {
|
|
115
|
+
setupFiles: ["neon-testing/setup"],
|
|
116
|
+
},
|
|
107
117
|
});
|
|
108
118
|
```
|
|
109
119
|
|
|
110
|
-
|
|
120
|
+
For Bun, add it to `bunfig.toml` instead:
|
|
121
|
+
|
|
122
|
+
```toml
|
|
123
|
+
[test]
|
|
124
|
+
preload = ["neon-testing/setup"]
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
Recommended but not required. Without it, a test file that forgets to call `neonTesting()` could fall back to your real `DATABASE_URL` (from `.env` or the environment) instead of an isolated test branch.
|
|
111
128
|
|
|
112
129
|
#### 2. Configuration
|
|
113
130
|
|
|
@@ -115,7 +132,7 @@ Use the `makeNeonTesting` factory to generate a lifecycle function for your test
|
|
|
115
132
|
|
|
116
133
|
```ts
|
|
117
134
|
// neon-testing.ts
|
|
118
|
-
import { makeNeonTesting } from "neon-testing";
|
|
135
|
+
import { makeNeonTesting } from "neon-testing/vitest"; // or "neon-testing/bun"
|
|
119
136
|
|
|
120
137
|
// Export a configured lifecycle function to use in test files
|
|
121
138
|
export const neonTesting = makeNeonTesting({
|
|
@@ -139,6 +156,7 @@ import { Pool } from "@neondatabase/serverless";
|
|
|
139
156
|
// Enable Neon test branch for this test file
|
|
140
157
|
neonTesting({
|
|
141
158
|
// Recommended for Neon WebSocket drivers to automatically close connections
|
|
159
|
+
// (Vitest only)
|
|
142
160
|
autoCloseWebSockets: true,
|
|
143
161
|
});
|
|
144
162
|
|
|
@@ -157,20 +175,28 @@ Source: [`examples/recommended.test.ts`](examples/recommended.test.ts)
|
|
|
157
175
|
|
|
158
176
|
## Drivers
|
|
159
177
|
|
|
160
|
-
This library works with any database driver that supports Neon Postgres
|
|
178
|
+
This library works with any database driver that supports Neon Postgres.
|
|
179
|
+
|
|
180
|
+
### Closing connections
|
|
181
|
+
|
|
182
|
+
Some drivers keep a connection open after a test finishes — [Neon's WebSocket driver](https://neon.com/docs/serverless/serverless-driver#use-the-driver-over-websockets) and [node-postgres](https://www.npmjs.com/package/pg). If the test branch is deleted while a connection is still open, the driver errors. Avoid it in one of three ways:
|
|
161
183
|
|
|
162
|
-
|
|
184
|
+
- close the connection yourself (e.g. `await pool.end()`)
|
|
185
|
+
- enable `autoCloseWebSockets` (WebSocket driver only, Vitest only)
|
|
186
|
+
- keep the branch with `deleteBranch: false`
|
|
187
|
+
|
|
188
|
+
[Neon's HTTP driver](https://neon.com/docs/serverless/serverless-driver#use-the-driver-over-http) and [Postgres.js](https://www.npmjs.com/package/postgres) close their own connections, so they need none of this.
|
|
163
189
|
|
|
164
190
|
### Examples
|
|
165
191
|
|
|
166
|
-
- [Neon serverless WebSocket](
|
|
167
|
-
- [Neon serverless WebSocket + Drizzle](
|
|
168
|
-
- [Neon serverless HTTP](
|
|
169
|
-
- [Neon serverless HTTP + Drizzle](
|
|
170
|
-
- [node-postgres](
|
|
171
|
-
- [node-postgres + Drizzle](
|
|
172
|
-
- [Postgres.js](
|
|
173
|
-
- [Postgres.js + Drizzle](
|
|
192
|
+
- [Neon serverless WebSocket](tests-vitest/drivers/ws-neon.test.ts)
|
|
193
|
+
- [Neon serverless WebSocket + Drizzle](tests-vitest/drivers/ws-neon-drizzle.test.ts)
|
|
194
|
+
- [Neon serverless HTTP](tests-vitest/drivers/http-neon.test.ts)
|
|
195
|
+
- [Neon serverless HTTP + Drizzle](tests-vitest/drivers/http-neon-drizzle.test.ts)
|
|
196
|
+
- [node-postgres](tests-vitest/drivers/tcp-pg.test.ts)
|
|
197
|
+
- [node-postgres + Drizzle](tests-vitest/drivers/tcp-pg-drizzle.test.ts)
|
|
198
|
+
- [Postgres.js](tests-vitest/drivers/tcp-postgres.test.ts)
|
|
199
|
+
- [Postgres.js + Drizzle](tests-vitest/drivers/tcp-postgres-drizzle.test.ts)
|
|
174
200
|
|
|
175
201
|
## Configuration
|
|
176
202
|
|
|
@@ -179,10 +205,10 @@ You configure Neon Testing in two places:
|
|
|
179
205
|
- **Base settings** in `makeNeonTesting()`
|
|
180
206
|
- **Optional overrides** when calling the returned function (e.g., `neonTesting()`)
|
|
181
207
|
|
|
182
|
-
Configure these in `makeNeonTesting()`
|
|
208
|
+
Configure these in `makeNeonTesting()`; every option except `apiKey` can also be overridden per test file when calling the returned function.
|
|
183
209
|
|
|
184
210
|
```ts
|
|
185
|
-
export interface
|
|
211
|
+
export interface MakeNeonTestingOptions {
|
|
186
212
|
/**
|
|
187
213
|
* The Neon API key, this is used to create and teardown test branches (required)
|
|
188
214
|
*
|
|
@@ -224,6 +250,8 @@ export interface NeonTestingOptions {
|
|
|
224
250
|
* Suppresses the specific Neon WebSocket "Connection terminated unexpectedly"
|
|
225
251
|
* error that may surface when deleting a branch with open WebSocket
|
|
226
252
|
* connections
|
|
253
|
+
*
|
|
254
|
+
* Vitest only.
|
|
227
255
|
*/
|
|
228
256
|
autoCloseWebSockets?: boolean;
|
|
229
257
|
/**
|
|
@@ -273,7 +301,7 @@ Configure the base settings in `makeNeonTesting()`:
|
|
|
273
301
|
|
|
274
302
|
```ts
|
|
275
303
|
// neon-testing.ts
|
|
276
|
-
import { makeNeonTesting } from "neon-testing";
|
|
304
|
+
import { makeNeonTesting } from "neon-testing/vitest";
|
|
277
305
|
|
|
278
306
|
export const neonTesting = makeNeonTesting({
|
|
279
307
|
apiKey: process.env.NEON_API_KEY!,
|
|
@@ -373,7 +401,9 @@ It's easy to run Neon integration tests in CI/CD pipelines:
|
|
|
373
401
|
|
|
374
402
|
## API Reference
|
|
375
403
|
|
|
376
|
-
###
|
|
404
|
+
### Runner entry (`neon-testing/vitest` or `neon-testing/bun`)
|
|
405
|
+
|
|
406
|
+
Both entries export the same `makeNeonTesting`; they differ only in which runner's `beforeAll`/`afterAll` hooks they wire up. (For other runners, `neon-testing/core` takes the hooks directly.)
|
|
377
407
|
|
|
378
408
|
#### makeNeonTesting(options)
|
|
379
409
|
|
|
@@ -381,7 +411,7 @@ The factory function that creates a configured lifecycle function for your tests
|
|
|
381
411
|
|
|
382
412
|
```ts
|
|
383
413
|
// neon-testing.ts
|
|
384
|
-
import { makeNeonTesting } from "neon-testing";
|
|
414
|
+
import { makeNeonTesting } from "neon-testing/vitest";
|
|
385
415
|
|
|
386
416
|
export const neonTesting = makeNeonTesting({
|
|
387
417
|
apiKey: process.env.NEON_API_KEY!,
|
|
@@ -434,24 +464,11 @@ test("access branch information", () => {
|
|
|
434
464
|
|
|
435
465
|
See the [Neon Branch API documentation](https://api-docs.neon.tech/reference/getprojectbranch) for all available properties.
|
|
436
466
|
|
|
437
|
-
###
|
|
438
|
-
|
|
439
|
-
The Vite plugin clears any existing `DATABASE_URL` environment variable before tests run, ensuring tests use isolated test databases.
|
|
440
|
-
|
|
441
|
-
```ts
|
|
442
|
-
import { defineConfig } from "vitest/config";
|
|
443
|
-
import { neonTesting } from "neon-testing/vite";
|
|
444
|
-
|
|
445
|
-
export default defineConfig({
|
|
446
|
-
plugins: [neonTesting()],
|
|
447
|
-
});
|
|
448
|
-
```
|
|
449
|
-
|
|
450
|
-
**Options:**
|
|
467
|
+
### Setup (`neon-testing/setup`)
|
|
451
468
|
|
|
452
|
-
- `
|
|
469
|
+
A zero-config preload that clears `DATABASE_URL` before tests run, so a file that forgets to call `neonTesting()` can't reach a real database. Register it with your runner — Vitest `setupFiles` or Bun `bunfig` `preload` (see [Recommended usage](#recommended-usage)).
|
|
453
470
|
|
|
454
|
-
|
|
471
|
+
Set `NEON_TESTING_DEBUG=true` to log when it clears a value.
|
|
455
472
|
|
|
456
473
|
### Utilities (`neon-testing/utils`)
|
|
457
474
|
|
package/package.json
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "neon-testing",
|
|
3
|
-
"version": "
|
|
4
|
-
"description": "A
|
|
3
|
+
"version": "3.0.0-beta.0",
|
|
4
|
+
"description": "A testing utility for seamless integration tests with Neon Postgres, for Vitest and Bun Test.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"neon",
|
|
7
7
|
"postgres",
|
|
8
8
|
"postgresql",
|
|
9
|
-
"vitest"
|
|
9
|
+
"vitest",
|
|
10
|
+
"bun",
|
|
11
|
+
"testing"
|
|
10
12
|
],
|
|
11
13
|
"author": "Mikael Lirbank",
|
|
12
14
|
"license": "MIT",
|
|
@@ -15,60 +17,68 @@
|
|
|
15
17
|
"bugs": "https://github.com/starmode-base/neon-testing/issues",
|
|
16
18
|
"type": "module",
|
|
17
19
|
"exports": {
|
|
18
|
-
"
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
"./
|
|
23
|
-
"types": "./dist/utils.d.ts",
|
|
24
|
-
"import": "./dist/utils.js"
|
|
25
|
-
},
|
|
26
|
-
"./vite": {
|
|
27
|
-
"types": "./dist/vite-plugin.d.ts",
|
|
28
|
-
"import": "./dist/vite-plugin.js"
|
|
29
|
-
}
|
|
20
|
+
"./core": "./src/core.ts",
|
|
21
|
+
"./vitest": "./src/vitest.ts",
|
|
22
|
+
"./bun": "./src/bun.ts",
|
|
23
|
+
"./utils": "./src/utils.ts",
|
|
24
|
+
"./setup": "./src/setup.ts"
|
|
30
25
|
},
|
|
31
26
|
"files": [
|
|
32
|
-
"
|
|
27
|
+
"src",
|
|
28
|
+
"!src/**/*.test.ts"
|
|
33
29
|
],
|
|
30
|
+
"engines": {
|
|
31
|
+
"node": ">=22"
|
|
32
|
+
},
|
|
34
33
|
"scripts": {
|
|
35
|
-
"dev": "tsc
|
|
36
|
-
"
|
|
34
|
+
"dev": "tsc --watch",
|
|
35
|
+
"check": "prettier --check . && tsc && bun run check:drift && bun run test",
|
|
36
|
+
"check:drift": "diff -r -x neon-testing.ts tests-bun tests-vitest",
|
|
37
37
|
"format": "prettier --write .",
|
|
38
|
-
"test": "vitest",
|
|
38
|
+
"test": "vitest run && bun test",
|
|
39
|
+
"test:unit": "vitest run src",
|
|
40
|
+
"test:unit:watch": "vitest src",
|
|
41
|
+
"test:examples": "vitest run examples",
|
|
42
|
+
"test:examples:watch": "vitest examples",
|
|
43
|
+
"test:vitest": "vitest run tests-vitest",
|
|
44
|
+
"test:vitest:watch": "vitest tests-vitest",
|
|
45
|
+
"test:bun": "bun test",
|
|
46
|
+
"test:bun:watch": "bun test --watch",
|
|
39
47
|
"skills:update": "bunx skills add neondatabase/agent-skills",
|
|
40
|
-
"clean:soft": "rm -rf node_modules
|
|
41
|
-
"clean:hard": "rm -rf node_modules
|
|
42
|
-
"release:patch": "bun pm version patch",
|
|
43
|
-
"release:minor": "bun pm version minor",
|
|
44
|
-
"release:major": "bun pm version major",
|
|
45
|
-
"release:beta": "bun pm version prerelease --preid=beta",
|
|
46
|
-
"release:beta:patch": "bun pm version prepatch --preid=beta",
|
|
47
|
-
"release:beta:minor": "bun pm version preminor --preid=beta",
|
|
48
|
-
"release:beta:major": "bun pm version premajor --preid=beta",
|
|
48
|
+
"clean:soft": "rm -rf node_modules && bun install",
|
|
49
|
+
"clean:hard": "rm -rf node_modules bun.lock && bun install",
|
|
50
|
+
"release:patch": "bun pm version patch --message 'release: v%s'",
|
|
51
|
+
"release:minor": "bun pm version minor --message 'release: v%s'",
|
|
52
|
+
"release:major": "bun pm version major --message 'release: v%s'",
|
|
53
|
+
"release:beta": "bun pm version prerelease --preid=beta --message 'release: v%s'",
|
|
54
|
+
"release:beta:patch": "bun pm version prepatch --preid=beta --message 'release: v%s'",
|
|
55
|
+
"release:beta:minor": "bun pm version preminor --preid=beta --message 'release: v%s'",
|
|
56
|
+
"release:beta:major": "bun pm version premajor --preid=beta --message 'release: v%s'",
|
|
57
|
+
"preversion": "test \"$(git branch --show-current)\" = main && git pull --ff-only",
|
|
49
58
|
"postversion": "git push --follow-tags"
|
|
50
59
|
},
|
|
51
60
|
"dependencies": {
|
|
52
|
-
"@neondatabase/api-client": "
|
|
61
|
+
"@neondatabase/api-client": "2.7.1"
|
|
53
62
|
},
|
|
54
63
|
"peerDependencies": {
|
|
55
|
-
"vite": "^7",
|
|
56
64
|
"vitest": "^3 || ^4"
|
|
57
65
|
},
|
|
66
|
+
"peerDependenciesMeta": {
|
|
67
|
+
"vitest": {
|
|
68
|
+
"optional": true
|
|
69
|
+
}
|
|
70
|
+
},
|
|
58
71
|
"devDependencies": {
|
|
59
|
-
"@neondatabase/serverless": "^1.0
|
|
72
|
+
"@neondatabase/serverless": "^1.1.0",
|
|
73
|
+
"@types/bun": "^1.3.14",
|
|
60
74
|
"@types/pg": "^8.20.0",
|
|
61
75
|
"dotenv": "^17.4.2",
|
|
62
76
|
"drizzle-orm": "^0.45.2",
|
|
63
|
-
"pg": "^8.
|
|
77
|
+
"pg": "^8.21.0",
|
|
64
78
|
"postgres": "^3.4.9",
|
|
65
|
-
"prettier": "^3.8.
|
|
79
|
+
"prettier": "^3.8.4",
|
|
66
80
|
"tiny-invariant": "^1.3.3",
|
|
67
|
-
"typescript": "^
|
|
68
|
-
"
|
|
69
|
-
"vitest": "^4.1.4"
|
|
70
|
-
},
|
|
71
|
-
"browser": {
|
|
72
|
-
"./dist/vite-plugin.js": "./dist/browser-empty.js"
|
|
81
|
+
"typescript": "^6.0.3",
|
|
82
|
+
"vitest": "^4.1.9"
|
|
73
83
|
}
|
|
74
84
|
}
|
package/src/bun.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/// <reference types="bun" />
|
|
2
|
+
import { beforeAll, afterAll } from "bun:test";
|
|
3
|
+
import { makeNeonTestingCore } from "./core";
|
|
4
|
+
import type { MakeNeonTestingOptions } from "./core";
|
|
5
|
+
|
|
6
|
+
export type { MakeNeonTestingOptions, NeonTestingOptions } from "./core";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Create a Neon test-branch factory wired to Bun's lifecycle hooks.
|
|
10
|
+
*/
|
|
11
|
+
export function makeNeonTesting(options: MakeNeonTestingOptions) {
|
|
12
|
+
return makeNeonTestingCore({ ...options, hooks: { beforeAll, afterAll } });
|
|
13
|
+
}
|