neon-testing 2.2.0 → 2.2.1-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 +121 -31
- package/dist/examples/branch-expiration.test.d.ts +2 -0
- package/dist/examples/branch-expiration.test.d.ts.map +1 -0
- package/dist/examples/branch-expiration.test.js +60 -0
- package/dist/examples/branch-expiration.test.js.map +1 -0
- package/dist/examples/drivers/http-neon-drizzle.test.d.ts +2 -0
- package/dist/examples/drivers/http-neon-drizzle.test.d.ts.map +1 -0
- package/dist/examples/drivers/http-neon-drizzle.test.js +80 -0
- package/dist/examples/drivers/http-neon-drizzle.test.js.map +1 -0
- package/dist/examples/drivers/http-neon.test.d.ts +2 -0
- package/dist/examples/drivers/http-neon.test.d.ts.map +1 -0
- package/dist/examples/drivers/http-neon.test.js +71 -0
- package/dist/examples/drivers/http-neon.test.js.map +1 -0
- package/dist/examples/drivers/tcp-pg-drizzle.test.d.ts +2 -0
- package/dist/examples/drivers/tcp-pg-drizzle.test.d.ts.map +1 -0
- package/dist/examples/drivers/tcp-pg-drizzle.test.js +90 -0
- package/dist/examples/drivers/tcp-pg-drizzle.test.js.map +1 -0
- package/dist/examples/drivers/tcp-pg.test.d.ts +2 -0
- package/dist/examples/drivers/tcp-pg.test.d.ts.map +1 -0
- package/dist/examples/drivers/tcp-pg.test.js +76 -0
- package/dist/examples/drivers/tcp-pg.test.js.map +1 -0
- package/dist/examples/drivers/tcp-postgres-drizzle.test.d.ts +2 -0
- package/dist/examples/drivers/tcp-postgres-drizzle.test.d.ts.map +1 -0
- package/dist/examples/drivers/tcp-postgres-drizzle.test.js +77 -0
- package/dist/examples/drivers/tcp-postgres-drizzle.test.js.map +1 -0
- package/dist/examples/drivers/tcp-postgres.test.d.ts +2 -0
- package/dist/examples/drivers/tcp-postgres.test.d.ts.map +1 -0
- package/dist/examples/drivers/tcp-postgres.test.js +69 -0
- package/dist/examples/drivers/tcp-postgres.test.js.map +1 -0
- package/dist/examples/drivers/ws-neon-drizzle.test.d.ts +2 -0
- package/dist/examples/drivers/ws-neon-drizzle.test.d.ts.map +1 -0
- package/dist/examples/drivers/ws-neon-drizzle.test.js +121 -0
- package/dist/examples/drivers/ws-neon-drizzle.test.js.map +1 -0
- package/dist/examples/drivers/ws-neon.test.d.ts +2 -0
- package/dist/examples/drivers/ws-neon.test.d.ts.map +1 -0
- package/dist/examples/drivers/ws-neon.test.js +97 -0
- package/dist/examples/drivers/ws-neon.test.js.map +1 -0
- package/dist/examples/isolated.test.d.ts +2 -0
- package/dist/examples/isolated.test.d.ts.map +1 -0
- package/dist/examples/isolated.test.js +114 -0
- package/dist/examples/isolated.test.js.map +1 -0
- package/dist/examples/minimal.test.d.ts +2 -0
- package/dist/examples/minimal.test.d.ts.map +1 -0
- package/dist/examples/minimal.test.js +19 -0
- package/dist/examples/minimal.test.js.map +1 -0
- package/dist/examples/neon-testing.d.ts +6 -0
- package/dist/examples/neon-testing.d.ts.map +1 -0
- package/dist/examples/neon-testing.js +8 -0
- package/dist/examples/neon-testing.js.map +1 -0
- package/dist/examples/options-validation.test.d.ts +2 -0
- package/dist/examples/options-validation.test.d.ts.map +1 -0
- package/dist/examples/options-validation.test.js +99 -0
- package/dist/examples/options-validation.test.js.map +1 -0
- package/dist/examples/recommended.test.d.ts +2 -0
- package/dist/examples/recommended.test.d.ts.map +1 -0
- package/dist/examples/recommended.test.js +17 -0
- package/dist/examples/recommended.test.js.map +1 -0
- package/dist/index.d.ts +45 -12
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +85 -22
- package/dist/index.js.map +1 -1
- package/dist/vitest.config.d.ts +3 -0
- package/dist/vitest.config.d.ts.map +1 -0
- package/dist/vitest.config.js +16 -0
- package/dist/vitest.config.js.map +1 -0
- package/package.json +6 -4
package/README.md
CHANGED
|
@@ -28,12 +28,14 @@ Each test file runs against its own isolated PostgreSQL database (Neon branch),
|
|
|
28
28
|
|
|
29
29
|
### Test isolation
|
|
30
30
|
|
|
31
|
-
Tests in the same file share a single database instance (Neon branch). This means test files are fully isolated from each other, but individual tests within a file are intentionally not isolated.
|
|
32
|
-
|
|
33
|
-
This works because Vitest runs test files in [parallel](https://vitest.dev/guide/parallelism.html), while tests within each file run sequentially.
|
|
31
|
+
Tests in the same file share a single database instance (Neon branch). This means test files are fully isolated from each other, but individual tests within a file are intentionally not isolated. This works because Vitest runs test files in [parallel](https://vitest.dev/guide/parallelism.html), while tests within each file run sequentially.
|
|
34
32
|
|
|
35
33
|
If you prefer individual tests to be isolated, you can [reset the database](examples/isolated.test.ts) in a `beforeEach` lifecycle hook.
|
|
36
34
|
|
|
35
|
+
### Automatic cleanup
|
|
36
|
+
|
|
37
|
+
Test branches are automatically deleted after your tests complete. As a safety net, branches also expire after 10 minutes by default to handle interrupted or failed test runs. This dual approach minimizes costs while protecting against edge cases like crashed processes or CI failures. Both behaviors can be customized through the `deleteBranch` and `expiresIn` options.
|
|
38
|
+
|
|
37
39
|
## Quick start
|
|
38
40
|
|
|
39
41
|
### Prerequisites
|
|
@@ -57,8 +59,8 @@ import { Pool } from "@neondatabase/serverless";
|
|
|
57
59
|
|
|
58
60
|
// Enable Neon test branch for this test file
|
|
59
61
|
makeNeonTesting({
|
|
60
|
-
apiKey:
|
|
61
|
-
projectId:
|
|
62
|
+
apiKey: process.env.NEON_API_KEY!,
|
|
63
|
+
projectId: process.env.NEON_PROJECT_ID!,
|
|
62
64
|
// Recommended for Neon WebSocket drivers to automatically close connections
|
|
63
65
|
autoCloseWebSockets: true,
|
|
64
66
|
})();
|
|
@@ -74,6 +76,8 @@ test("database operations", async () => {
|
|
|
74
76
|
});
|
|
75
77
|
```
|
|
76
78
|
|
|
79
|
+
Source: [`examples/minimal.test.ts`](examples/minimal.test.ts)
|
|
80
|
+
|
|
77
81
|
### Recommended usage
|
|
78
82
|
|
|
79
83
|
#### 1. Plugin setup
|
|
@@ -90,23 +94,25 @@ export default defineConfig({
|
|
|
90
94
|
});
|
|
91
95
|
```
|
|
92
96
|
|
|
93
|
-
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 `
|
|
97
|
+
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 `neonTesting()` in a test file where database writes happen.
|
|
94
98
|
|
|
95
99
|
#### 2. Configuration
|
|
96
100
|
|
|
97
101
|
Use the `makeNeonTesting` factory to generate a lifecycle function for your tests.
|
|
98
102
|
|
|
99
103
|
```ts
|
|
100
|
-
//
|
|
104
|
+
// neon-testing.ts
|
|
101
105
|
import { makeNeonTesting } from "neon-testing";
|
|
102
106
|
|
|
103
107
|
// Export a configured lifecycle function to use in test files
|
|
104
|
-
export const
|
|
105
|
-
apiKey:
|
|
106
|
-
projectId:
|
|
108
|
+
export const neonTesting = makeNeonTesting({
|
|
109
|
+
apiKey: process.env.NEON_API_KEY!,
|
|
110
|
+
projectId: process.env.NEON_PROJECT_ID!,
|
|
107
111
|
});
|
|
108
112
|
```
|
|
109
113
|
|
|
114
|
+
Source: [`examples/neon-testing.ts`](examples/neon-testing.ts)
|
|
115
|
+
|
|
110
116
|
#### 3. Enable database testing
|
|
111
117
|
|
|
112
118
|
Then call the exported test lifecycle function in the test files where you need database access.
|
|
@@ -114,11 +120,11 @@ Then call the exported test lifecycle function in the test files where you need
|
|
|
114
120
|
```ts
|
|
115
121
|
// recommended.test.ts
|
|
116
122
|
import { expect, test } from "vitest";
|
|
117
|
-
import {
|
|
123
|
+
import { neonTesting } from "./neon-testing";
|
|
118
124
|
import { Pool } from "@neondatabase/serverless";
|
|
119
125
|
|
|
120
126
|
// Enable Neon test branch for this test file
|
|
121
|
-
|
|
127
|
+
neonTesting({
|
|
122
128
|
// Recommended for Neon WebSocket drivers to automatically close connections
|
|
123
129
|
autoCloseWebSockets: true,
|
|
124
130
|
});
|
|
@@ -134,11 +140,13 @@ test("database operations", async () => {
|
|
|
134
140
|
});
|
|
135
141
|
```
|
|
136
142
|
|
|
143
|
+
Source: [`examples/recommended.test.ts`](examples/recommended.test.ts)
|
|
144
|
+
|
|
137
145
|
## Drivers
|
|
138
146
|
|
|
139
147
|
This library works with any database driver that supports Neon Postgres and Vitest. The examples below demonstrate connection management, transaction support, and test isolation patterns for some popular drivers.
|
|
140
148
|
|
|
141
|
-
**IMPORTANT:** For [Neon WebSocket drivers](https://neon.com/docs/serverless/serverless-driver), enable `autoCloseWebSockets` in your `makeNeonTesting()` or `
|
|
149
|
+
**IMPORTANT:** For [Neon WebSocket drivers](https://neon.com/docs/serverless/serverless-driver), enable `autoCloseWebSockets` in your `makeNeonTesting()` or `neonTesting()` configuration. This automatically closes WebSocket connections when deleting test branches, preventing connection termination errors.
|
|
142
150
|
|
|
143
151
|
### Examples
|
|
144
152
|
|
|
@@ -156,9 +164,9 @@ This library works with any database driver that supports Neon Postgres and Vite
|
|
|
156
164
|
You configure Neon Testing in two places:
|
|
157
165
|
|
|
158
166
|
- **Base settings** in `makeNeonTesting()`
|
|
159
|
-
- **Optional overrides**
|
|
167
|
+
- **Optional overrides** when calling the returned function (e.g., `neonTesting()`)
|
|
160
168
|
|
|
161
|
-
Configure these in `makeNeonTesting()` and optionally override per test file
|
|
169
|
+
Configure these in `makeNeonTesting()` and optionally override per test file when calling the returned function.
|
|
162
170
|
|
|
163
171
|
```ts
|
|
164
172
|
export interface NeonTestingOptions {
|
|
@@ -203,32 +211,45 @@ export interface NeonTestingOptions {
|
|
|
203
211
|
* connections
|
|
204
212
|
*/
|
|
205
213
|
autoCloseWebSockets?: boolean;
|
|
214
|
+
/**
|
|
215
|
+
* Time in seconds until the branch expires and is automatically deleted
|
|
216
|
+
* (default: 600 = 10 minutes)
|
|
217
|
+
*
|
|
218
|
+
* This provides automatic cleanup for dangling branches from interrupted or
|
|
219
|
+
* failed test runs. Set to `null` to disable automatic expiration.
|
|
220
|
+
*
|
|
221
|
+
* Must be a positive integer. Maximum 30 days (2,592,000 seconds).
|
|
222
|
+
*
|
|
223
|
+
* https://neon.com/docs/guides/branch-expiration
|
|
224
|
+
*/
|
|
225
|
+
expiresIn?: number | null;
|
|
206
226
|
}
|
|
207
227
|
```
|
|
208
228
|
|
|
209
|
-
See all available options in [NeonTestingOptions](index.ts#L31-L73).
|
|
210
|
-
|
|
211
229
|
### Base configuration
|
|
212
230
|
|
|
213
231
|
Configure the base settings in `makeNeonTesting()`:
|
|
214
232
|
|
|
215
233
|
```ts
|
|
234
|
+
// neon-testing.ts
|
|
216
235
|
import { makeNeonTesting } from "neon-testing";
|
|
217
236
|
|
|
218
|
-
export const
|
|
219
|
-
apiKey:
|
|
220
|
-
projectId:
|
|
237
|
+
export const neonTesting = makeNeonTesting({
|
|
238
|
+
apiKey: process.env.NEON_API_KEY!,
|
|
239
|
+
projectId: process.env.NEON_PROJECT_ID!,
|
|
221
240
|
});
|
|
222
241
|
```
|
|
223
242
|
|
|
224
243
|
### Override configuration
|
|
225
244
|
|
|
226
|
-
Override the base configuration in specific test files
|
|
245
|
+
Override the base configuration in specific test files when calling the function:
|
|
227
246
|
|
|
228
247
|
```ts
|
|
229
|
-
import {
|
|
248
|
+
import { neonTesting } from "./neon-testing";
|
|
230
249
|
|
|
231
|
-
|
|
250
|
+
neonTesting({
|
|
251
|
+
parentBranchId: "br-staging-123",
|
|
252
|
+
});
|
|
232
253
|
```
|
|
233
254
|
|
|
234
255
|
## Continuous integration
|
|
@@ -240,24 +261,93 @@ It's easy to run Neon integration tests in CI/CD pipelines:
|
|
|
240
261
|
- 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
|
|
241
262
|
- add `vitest run` to the _Build Command_ in the Vercel dashboard
|
|
242
263
|
|
|
243
|
-
##
|
|
264
|
+
## API Reference
|
|
265
|
+
|
|
266
|
+
### Main exports (`neon-testing`)
|
|
267
|
+
|
|
268
|
+
#### makeNeonTesting(options)
|
|
269
|
+
|
|
270
|
+
The factory function that creates a configured lifecycle function for your tests. See [Configuration](#configuration) for available options.
|
|
271
|
+
|
|
272
|
+
```ts
|
|
273
|
+
// neon-testing.ts
|
|
274
|
+
import { makeNeonTesting } from "neon-testing";
|
|
275
|
+
|
|
276
|
+
export const neonTesting = makeNeonTesting({
|
|
277
|
+
apiKey: process.env.NEON_API_KEY!,
|
|
278
|
+
projectId: process.env.NEON_PROJECT_ID!,
|
|
279
|
+
});
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
The configured function has the following properties:
|
|
283
|
+
|
|
284
|
+
##### `.api`
|
|
285
|
+
|
|
286
|
+
Access the Neon API client to make additional API calls:
|
|
287
|
+
|
|
288
|
+
```ts
|
|
289
|
+
import { neonTesting } from "./neon-testing";
|
|
290
|
+
|
|
291
|
+
const { data } = await neonTesting.api.getProjectBranch(projectId, branchId);
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
See the [Neon API client documentation](https://neon.com/docs/reference/typescript-sdk) for all available methods.
|
|
244
295
|
|
|
245
|
-
|
|
296
|
+
##### `.deleteAllTestBranches()`
|
|
246
297
|
|
|
247
|
-
|
|
298
|
+
Deletes all test branches from your Neon project. This is useful for cleanup when tests fail unexpectedly and leave orphaned test branches.
|
|
248
299
|
|
|
249
300
|
```ts
|
|
250
|
-
import {
|
|
301
|
+
import { neonTesting } from "./neon-testing";
|
|
251
302
|
|
|
252
|
-
|
|
253
|
-
await withNeonTestBranch.deleteAllTestBranches();
|
|
303
|
+
await neonTesting.deleteAllTestBranches();
|
|
254
304
|
```
|
|
255
305
|
|
|
256
306
|
The function identifies test branches by looking for the `integration-test: true` annotation that Neon Testing automatically adds to all test branches it creates.
|
|
257
307
|
|
|
258
|
-
|
|
308
|
+
#### Accessing branch information
|
|
309
|
+
|
|
310
|
+
When you call the configured lifecycle function in your test files, it returns a function that gives you access to the current test branch:
|
|
311
|
+
|
|
312
|
+
```ts
|
|
313
|
+
import { neonTesting } from "./neon-testing";
|
|
314
|
+
|
|
315
|
+
const getBranch = neonTesting();
|
|
316
|
+
|
|
317
|
+
test("access branch information", () => {
|
|
318
|
+
const branch = getBranch();
|
|
319
|
+
console.log(branch.id);
|
|
320
|
+
console.log(branch.project_id);
|
|
321
|
+
console.log(branch.expires_at);
|
|
322
|
+
});
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
See the [Neon Branch API documentation](https://api-docs.neon.tech/reference/getprojectbranch) for all available properties.
|
|
326
|
+
|
|
327
|
+
### Vite plugin (`neon-testing/vite`)
|
|
328
|
+
|
|
329
|
+
The Vite plugin clears any existing `DATABASE_URL` environment variable before tests run, ensuring tests use isolated test databases.
|
|
330
|
+
|
|
331
|
+
```ts
|
|
332
|
+
import { defineConfig } from "vitest/config";
|
|
333
|
+
import { neonTesting } from "neon-testing/vite";
|
|
334
|
+
|
|
335
|
+
export default defineConfig({
|
|
336
|
+
plugins: [neonTesting()],
|
|
337
|
+
});
|
|
338
|
+
```
|
|
339
|
+
|
|
340
|
+
**Options:**
|
|
341
|
+
|
|
342
|
+
- `debug` (boolean, default: `false`) - Enable debug logging
|
|
343
|
+
|
|
344
|
+
This plugin is recommended but not required. Without it, tests might accidentally use your existing `DATABASE_URL` instead of isolated test databases.
|
|
345
|
+
|
|
346
|
+
### Utilities (`neon-testing/utils`)
|
|
347
|
+
|
|
348
|
+
#### lazySingleton(factory)
|
|
259
349
|
|
|
260
|
-
|
|
350
|
+
Creates a lazy singleton from a factory function. This is useful for managing database connections efficiently:
|
|
261
351
|
|
|
262
352
|
```ts
|
|
263
353
|
import { lazySingleton } from "neon-testing/utils";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"branch-expiration.test.d.ts","sourceRoot":"","sources":["../../examples/branch-expiration.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { describe, expect, test } from "vitest";
|
|
2
|
+
import { neonTesting } from "./neon-testing";
|
|
3
|
+
import invariant from "tiny-invariant";
|
|
4
|
+
describe("Branch expiration with default settings", () => {
|
|
5
|
+
const getBranch = neonTesting();
|
|
6
|
+
test("sets default 10-minute expiration on created branch", async () => {
|
|
7
|
+
const branch = getBranch();
|
|
8
|
+
invariant(branch, "Branch not found");
|
|
9
|
+
invariant(branch.expires_at, "Branch expires_at not set");
|
|
10
|
+
// Verify the expires_at matches what Neon API returns
|
|
11
|
+
// https://api-docs.neon.tech/reference/getprojectbranch
|
|
12
|
+
const { data } = await neonTesting.api.getProjectBranch(branch.project_id, branch.id);
|
|
13
|
+
expect(data.branch?.expires_at).toBe(branch.expires_at);
|
|
14
|
+
// Verify it's approximately 600 seconds (10 minutes) in the future
|
|
15
|
+
const expiresAt = new Date(branch.expires_at).getTime();
|
|
16
|
+
const createdAt = new Date(branch.created_at).getTime();
|
|
17
|
+
const expectedExpiresAt = createdAt + 600 * 1000;
|
|
18
|
+
// Allow 10 seconds of tolerance
|
|
19
|
+
expect(expiresAt).toBeGreaterThan(createdAt);
|
|
20
|
+
expect(expiresAt).toBeLessThan(expectedExpiresAt + 10000);
|
|
21
|
+
expect(expiresAt).toBeGreaterThan(expectedExpiresAt - 10000);
|
|
22
|
+
});
|
|
23
|
+
});
|
|
24
|
+
describe("Branch expiration with custom settings", () => {
|
|
25
|
+
const getBranch = neonTesting({
|
|
26
|
+
expiresIn: 1800,
|
|
27
|
+
});
|
|
28
|
+
test("sets custom 30-minute expiration on created branch", async () => {
|
|
29
|
+
const branch = getBranch();
|
|
30
|
+
invariant(branch, "Branch not found");
|
|
31
|
+
invariant(branch.expires_at, "Branch expires_at not set");
|
|
32
|
+
// Verify the expires_at matches what Neon API returns
|
|
33
|
+
// https://api-docs.neon.tech/reference/getprojectbranch
|
|
34
|
+
const { data } = await neonTesting.api.getProjectBranch(branch.project_id, branch.id);
|
|
35
|
+
expect(data.branch?.expires_at).toBe(branch.expires_at);
|
|
36
|
+
// Verify it's approximately 1800 seconds (30 minutes) in the future
|
|
37
|
+
const expiresAt = new Date(branch.expires_at).getTime();
|
|
38
|
+
const createdAt = new Date(branch.created_at).getTime();
|
|
39
|
+
const expectedExpiresAt = createdAt + 1800 * 1000;
|
|
40
|
+
// Allow 10 seconds of tolerance
|
|
41
|
+
expect(expiresAt).toBeGreaterThan(createdAt);
|
|
42
|
+
expect(expiresAt).toBeLessThan(expectedExpiresAt + 10000);
|
|
43
|
+
expect(expiresAt).toBeGreaterThan(expectedExpiresAt - 10000);
|
|
44
|
+
});
|
|
45
|
+
});
|
|
46
|
+
describe("Branch expiration disabled", () => {
|
|
47
|
+
const getBranch = neonTesting({
|
|
48
|
+
expiresIn: null,
|
|
49
|
+
});
|
|
50
|
+
test("creates branch without expiration when disabled", async () => {
|
|
51
|
+
const branch = getBranch();
|
|
52
|
+
invariant(branch, "Branch not found");
|
|
53
|
+
// Verify the expires_at matches what Neon API returns (both should be undefined)
|
|
54
|
+
// https://api-docs.neon.tech/reference/getprojectbranch
|
|
55
|
+
const { data } = await neonTesting.api.getProjectBranch(branch.project_id, branch.id);
|
|
56
|
+
expect(branch.expires_at).toBeUndefined();
|
|
57
|
+
expect(data.branch?.expires_at).toBe(branch.expires_at);
|
|
58
|
+
});
|
|
59
|
+
});
|
|
60
|
+
//# sourceMappingURL=branch-expiration.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"branch-expiration.test.js","sourceRoot":"","sources":["../../examples/branch-expiration.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http-neon-drizzle.test.d.ts","sourceRoot":"","sources":["../../../examples/drivers/http-neon-drizzle.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @neondatabase/serverless
|
|
3
|
+
*
|
|
4
|
+
* Protocol: | HTTP
|
|
5
|
+
* Driver: | @neondatabase/serverless
|
|
6
|
+
* ORM: | drizzle-orm
|
|
7
|
+
* Interactive transactions | ❌
|
|
8
|
+
* Automatic connection lifecycle management | ✅
|
|
9
|
+
*
|
|
10
|
+
* https://www.npmjs.com/package/@neondatabase/serverless
|
|
11
|
+
* https://www.npmjs.com/package/drizzle-orm
|
|
12
|
+
* https://orm.drizzle.team/docs/get-started/neon-new
|
|
13
|
+
* https://orm.drizzle.team/docs/connect-neon
|
|
14
|
+
*/
|
|
15
|
+
import { describe, expect, test } from "vitest";
|
|
16
|
+
import { neonTesting } from "../neon-testing";
|
|
17
|
+
import { neon } from "@neondatabase/serverless";
|
|
18
|
+
import { drizzle } from "drizzle-orm/neon-http";
|
|
19
|
+
import { lazySingleton } from "neon-testing/utils";
|
|
20
|
+
const cases = [
|
|
21
|
+
["pooler", (url) => drizzle(url)],
|
|
22
|
+
["direct", (url) => drizzle(url)],
|
|
23
|
+
["pooler", (url) => drizzle({ client: neon(url) })],
|
|
24
|
+
["direct", (url) => drizzle({ client: neon(url) })],
|
|
25
|
+
];
|
|
26
|
+
describe.each(cases)("Drizzle Neon HTTP (%s)", (endpoint, makeDb) => {
|
|
27
|
+
neonTesting({ endpoint });
|
|
28
|
+
const db = lazySingleton(() => makeDb(process.env.DATABASE_URL));
|
|
29
|
+
test("create table", async () => {
|
|
30
|
+
await db().execute(`
|
|
31
|
+
CREATE TABLE users (
|
|
32
|
+
id SERIAL PRIMARY KEY,
|
|
33
|
+
name TEXT NOT NULL UNIQUE
|
|
34
|
+
)
|
|
35
|
+
`);
|
|
36
|
+
const { rows: newUser } = await db().execute(`
|
|
37
|
+
INSERT INTO users (name)
|
|
38
|
+
VALUES ('Ellen Ripley')
|
|
39
|
+
RETURNING *
|
|
40
|
+
`);
|
|
41
|
+
expect(newUser).toStrictEqual([{ id: 1, name: "Ellen Ripley" }]);
|
|
42
|
+
const { rows: users } = await db().execute(`SELECT * FROM users`);
|
|
43
|
+
expect(users).toStrictEqual([{ id: 1, name: "Ellen Ripley" }]);
|
|
44
|
+
});
|
|
45
|
+
test("tests are not isolated within a test file", async () => {
|
|
46
|
+
const { rows: newUser } = await db().execute(`
|
|
47
|
+
INSERT INTO users (name)
|
|
48
|
+
VALUES ('Rebecca Jorden')
|
|
49
|
+
RETURNING *
|
|
50
|
+
`);
|
|
51
|
+
expect(newUser).toStrictEqual([{ id: 2, name: "Rebecca Jorden" }]);
|
|
52
|
+
const { rows: users } = await db().execute(`SELECT * FROM users`);
|
|
53
|
+
expect(users).toStrictEqual([
|
|
54
|
+
// Ellen Ripley is already in the table from the previous test
|
|
55
|
+
{ id: 1, name: "Ellen Ripley" },
|
|
56
|
+
{ id: 2, name: "Rebecca Jorden" },
|
|
57
|
+
]);
|
|
58
|
+
});
|
|
59
|
+
test("interactive transactions are NOT supported", async () => {
|
|
60
|
+
try {
|
|
61
|
+
await db().execute(`BEGIN`);
|
|
62
|
+
await db().execute(`INSERT INTO users (name) VALUES ('Private Vasquez')`);
|
|
63
|
+
// Duplicate unique constraint error - will fail but not roll back
|
|
64
|
+
await db().execute(`INSERT INTO users (name) VALUES ('Private Vasquez')`);
|
|
65
|
+
await db().execute(`COMMIT`);
|
|
66
|
+
}
|
|
67
|
+
catch {
|
|
68
|
+
await db().execute(`ROLLBACK`);
|
|
69
|
+
}
|
|
70
|
+
const { rows: users } = await db().execute(`SELECT * FROM users`);
|
|
71
|
+
expect(users).toStrictEqual([
|
|
72
|
+
{ id: 1, name: "Ellen Ripley" },
|
|
73
|
+
{ id: 2, name: "Rebecca Jorden" },
|
|
74
|
+
// Private Vasquez is inserted despite the unique constraint error because
|
|
75
|
+
// interactive transactions are not supported by this driver.
|
|
76
|
+
{ id: 3, name: "Private Vasquez" },
|
|
77
|
+
]);
|
|
78
|
+
});
|
|
79
|
+
});
|
|
80
|
+
//# sourceMappingURL=http-neon-drizzle.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http-neon-drizzle.test.js","sourceRoot":"","sources":["../../../examples/drivers/http-neon-drizzle.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http-neon.test.d.ts","sourceRoot":"","sources":["../../../examples/drivers/http-neon.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @neondatabase/serverless
|
|
3
|
+
*
|
|
4
|
+
* Protocol: | HTTP
|
|
5
|
+
* Driver: | @neondatabase/serverless
|
|
6
|
+
* ORM: | -
|
|
7
|
+
* Interactive transactions | ❌
|
|
8
|
+
* Automatic connection lifecycle management | ✅
|
|
9
|
+
*
|
|
10
|
+
* https://www.npmjs.com/package/@neondatabase/serverless
|
|
11
|
+
*/
|
|
12
|
+
import { describe, expect, test } from "vitest";
|
|
13
|
+
import { neonTesting } from "../neon-testing";
|
|
14
|
+
import { neon } from "@neondatabase/serverless";
|
|
15
|
+
import { lazySingleton } from "neon-testing/utils";
|
|
16
|
+
const endpoints = ["pooler", "direct"];
|
|
17
|
+
describe.each(endpoints)("Neon HTTP (%s)", (endpoint) => {
|
|
18
|
+
neonTesting({ endpoint });
|
|
19
|
+
const sql = lazySingleton(() => neon(process.env.DATABASE_URL));
|
|
20
|
+
test("create table", async () => {
|
|
21
|
+
await sql() `
|
|
22
|
+
CREATE TABLE users (
|
|
23
|
+
id SERIAL PRIMARY KEY,
|
|
24
|
+
name TEXT NOT NULL UNIQUE
|
|
25
|
+
)
|
|
26
|
+
`;
|
|
27
|
+
const newUser = await sql() `
|
|
28
|
+
INSERT INTO users (name)
|
|
29
|
+
VALUES ('Ellen Ripley')
|
|
30
|
+
RETURNING *
|
|
31
|
+
`;
|
|
32
|
+
expect(newUser).toStrictEqual([{ id: 1, name: "Ellen Ripley" }]);
|
|
33
|
+
const users = await sql() `SELECT * FROM users`;
|
|
34
|
+
expect(users).toStrictEqual([{ id: 1, name: "Ellen Ripley" }]);
|
|
35
|
+
});
|
|
36
|
+
test("tests are not isolated within a test file", async () => {
|
|
37
|
+
const newUser = await sql() `
|
|
38
|
+
INSERT INTO users (name)
|
|
39
|
+
VALUES ('Rebecca Jorden')
|
|
40
|
+
RETURNING *
|
|
41
|
+
`;
|
|
42
|
+
expect(newUser).toStrictEqual([{ id: 2, name: "Rebecca Jorden" }]);
|
|
43
|
+
const users = await sql() `SELECT * FROM users`;
|
|
44
|
+
expect(users).toStrictEqual([
|
|
45
|
+
// Ellen Ripley is already in the table from the previous test
|
|
46
|
+
{ id: 1, name: "Ellen Ripley" },
|
|
47
|
+
{ id: 2, name: "Rebecca Jorden" },
|
|
48
|
+
]);
|
|
49
|
+
});
|
|
50
|
+
test("interactive transactions are NOT supported", async () => {
|
|
51
|
+
try {
|
|
52
|
+
await sql() `BEGIN`;
|
|
53
|
+
await sql() `INSERT INTO users (name) VALUES ('Private Vasquez')`;
|
|
54
|
+
// Duplicate unique constraint error - will fail but not roll back
|
|
55
|
+
await sql() `INSERT INTO users (name) VALUES ('Private Vasquez')`;
|
|
56
|
+
await sql() `COMMIT`;
|
|
57
|
+
}
|
|
58
|
+
catch {
|
|
59
|
+
await sql() `ROLLBACK`;
|
|
60
|
+
}
|
|
61
|
+
const users = await sql() `SELECT * FROM users`;
|
|
62
|
+
expect(users).toStrictEqual([
|
|
63
|
+
{ id: 1, name: "Ellen Ripley" },
|
|
64
|
+
{ id: 2, name: "Rebecca Jorden" },
|
|
65
|
+
// Private Vasquez is inserted despite the unique constraint error because
|
|
66
|
+
// interactive transactions are not supported by this driver.
|
|
67
|
+
{ id: 3, name: "Private Vasquez" },
|
|
68
|
+
]);
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
//# sourceMappingURL=http-neon.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http-neon.test.js","sourceRoot":"","sources":["../../../examples/drivers/http-neon.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAChD,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC9C,OAAO,EAAE,IAAI,EAAE,MAAM,0BAA0B,CAAC;AAChD,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAEnD,MAAM,SAAS,GAAG,CAAC,QAAQ,EAAE,QAAQ,CAAU,CAAC;AAEhD,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,gBAAgB,EAAE,CAAC,QAAQ,EAAE,EAAE;IACtD,WAAW,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC;IAE1B,MAAM,GAAG,GAAG,aAAa,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,YAAa,CAAC,CAAC,CAAC;IAEjE,IAAI,CAAC,cAAc,EAAE,KAAK,IAAI,EAAE;QAC9B,MAAM,GAAG,EAAE,CAAA;;;;;KAKV,CAAC;QAEF,MAAM,OAAO,GAAG,MAAM,GAAG,EAAE,CAAA;;;;KAI1B,CAAC;QACF,MAAM,CAAC,OAAO,CAAC,CAAC,aAAa,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,IAAI,EAAE,cAAc,EAAE,CAAC,CAAC,CAAC;QAEjE,MAAM,KAAK,GAAG,MAAM,GAAG,EAAE,CAAA,qBAAqB,CAAC;QAC/C,MAAM,CAAC,KAAK,CAAC,CAAC,aAAa,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,IAAI,EAAE,cAAc,EAAE,CAAC,CAAC,CAAC;IACjE,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,2CAA2C,EAAE,KAAK,IAAI,EAAE;QAC3D,MAAM,OAAO,GAAG,MAAM,GAAG,EAAE,CAAA;;;;KAI1B,CAAC;QACF,MAAM,CAAC,OAAO,CAAC,CAAC,aAAa,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,IAAI,EAAE,gBAAgB,EAAE,CAAC,CAAC,CAAC;QAEnE,MAAM,KAAK,GAAG,MAAM,GAAG,EAAE,CAAA,qBAAqB,CAAC;QAC/C,MAAM,CAAC,KAAK,CAAC,CAAC,aAAa,CAAC;YAC1B,8DAA8D;YAC9D,EAAE,EAAE,EAAE,CAAC,EAAE,IAAI,EAAE,cAAc,EAAE;YAC/B,EAAE,EAAE,EAAE,CAAC,EAAE,IAAI,EAAE,gBAAgB,EAAE;SAClC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,4CAA4C,EAAE,KAAK,IAAI,EAAE;QAC5D,IAAI,CAAC;YACH,MAAM,GAAG,EAAE,CAAA,OAAO,CAAC;YACnB,MAAM,GAAG,EAAE,CAAA,qDAAqD,CAAC;YACjE,kEAAkE;YAClE,MAAM,GAAG,EAAE,CAAA,qDAAqD,CAAC;YACjE,MAAM,GAAG,EAAE,CAAA,QAAQ,CAAC;QACtB,CAAC;QAAC,MAAM,CAAC;YACP,MAAM,GAAG,EAAE,CAAA,UAAU,CAAC;QACxB,CAAC;QAED,MAAM,KAAK,GAAG,MAAM,GAAG,EAAE,CAAA,qBAAqB,CAAC;QAC/C,MAAM,CAAC,KAAK,CAAC,CAAC,aAAa,CAAC;YAC1B,EAAE,EAAE,EAAE,CAAC,EAAE,IAAI,EAAE,cAAc,EAAE;YAC/B,EAAE,EAAE,EAAE,CAAC,EAAE,IAAI,EAAE,gBAAgB,EAAE;YACjC,0EAA0E;YAC1E,6DAA6D;YAC7D,EAAE,EAAE,EAAE,CAAC,EAAE,IAAI,EAAE,iBAAiB,EAAE;SACnC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tcp-pg-drizzle.test.d.ts","sourceRoot":"","sources":["../../../examples/drivers/tcp-pg-drizzle.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* pg (node-postgres)
|
|
3
|
+
*
|
|
4
|
+
* Protocol: | TCP
|
|
5
|
+
* Driver: | pg
|
|
6
|
+
* ORM: | drizzle-orm
|
|
7
|
+
* Interactive transactions | ✅
|
|
8
|
+
* Automatic connection lifecycle management | ❌
|
|
9
|
+
*
|
|
10
|
+
* https://www.npmjs.com/package/pg
|
|
11
|
+
* https://www.npmjs.com/package/drizzle-orm
|
|
12
|
+
* https://orm.drizzle.team/docs/get-started-postgresql#postgresjs
|
|
13
|
+
*/
|
|
14
|
+
import { describe, expect, test } from "vitest";
|
|
15
|
+
import { neonTesting } from "../neon-testing";
|
|
16
|
+
import { Pool } from "pg";
|
|
17
|
+
import { drizzle } from "drizzle-orm/node-postgres";
|
|
18
|
+
const cases = [
|
|
19
|
+
["pooler", (url) => drizzle(url)],
|
|
20
|
+
["direct", (url) => drizzle(url)],
|
|
21
|
+
[
|
|
22
|
+
"pooler",
|
|
23
|
+
(url) => drizzle({ client: new Pool({ connectionString: url }) }),
|
|
24
|
+
],
|
|
25
|
+
[
|
|
26
|
+
"direct",
|
|
27
|
+
(url) => drizzle({ client: new Pool({ connectionString: url }) }),
|
|
28
|
+
],
|
|
29
|
+
];
|
|
30
|
+
describe.each(cases)("node-postgres (%s)", (endpoint, makeDb) => {
|
|
31
|
+
neonTesting({ endpoint });
|
|
32
|
+
test("create table", async () => {
|
|
33
|
+
const pool = makeDb(process.env.DATABASE_URL);
|
|
34
|
+
await pool.execute(`
|
|
35
|
+
CREATE TABLE users (
|
|
36
|
+
id SERIAL PRIMARY KEY,
|
|
37
|
+
name TEXT NOT NULL UNIQUE
|
|
38
|
+
)
|
|
39
|
+
`);
|
|
40
|
+
const newUser = await pool.execute(`
|
|
41
|
+
INSERT INTO users (name)
|
|
42
|
+
VALUES ('Ellen Ripley')
|
|
43
|
+
RETURNING *
|
|
44
|
+
`);
|
|
45
|
+
expect(newUser.rows[0]).toStrictEqual({ id: 1, name: "Ellen Ripley" });
|
|
46
|
+
const users = await pool.execute(`SELECT * FROM users`);
|
|
47
|
+
expect(users.rows).toStrictEqual([{ id: 1, name: "Ellen Ripley" }]);
|
|
48
|
+
// 👎 Have to manually end the connection unless disabling `deleteBranch`
|
|
49
|
+
await pool.$client.end();
|
|
50
|
+
});
|
|
51
|
+
test("tests are not isolated within a test file", async () => {
|
|
52
|
+
const pool = makeDb(process.env.DATABASE_URL);
|
|
53
|
+
const newUser = await pool.execute(`
|
|
54
|
+
INSERT INTO users (name)
|
|
55
|
+
VALUES ('Rebecca Jorden')
|
|
56
|
+
RETURNING *
|
|
57
|
+
`);
|
|
58
|
+
expect(newUser.rows).toStrictEqual([{ id: 2, name: "Rebecca Jorden" }]);
|
|
59
|
+
const users = await pool.execute(`SELECT * FROM users`);
|
|
60
|
+
expect(users.rows).toStrictEqual([
|
|
61
|
+
// Ellen Ripley is already in the table from the previous test
|
|
62
|
+
{ id: 1, name: "Ellen Ripley" },
|
|
63
|
+
{ id: 2, name: "Rebecca Jorden" },
|
|
64
|
+
]);
|
|
65
|
+
// 👎 Have to manually end the connection unless disabling `deleteBranch`
|
|
66
|
+
await pool.$client.end();
|
|
67
|
+
});
|
|
68
|
+
test("interactive transactions are supported", async () => {
|
|
69
|
+
const pool = makeDb(process.env.DATABASE_URL);
|
|
70
|
+
try {
|
|
71
|
+
await pool.execute("BEGIN");
|
|
72
|
+
await pool.execute(`INSERT INTO users (name) VALUES ('Private Vasquez')`);
|
|
73
|
+
// Duplicate unique constraint error - will roll back the transaction
|
|
74
|
+
await pool.execute(`INSERT INTO users (name) VALUES ('Private Vasquez')`);
|
|
75
|
+
await pool.execute("COMMIT");
|
|
76
|
+
}
|
|
77
|
+
catch {
|
|
78
|
+
await pool.execute("ROLLBACK");
|
|
79
|
+
}
|
|
80
|
+
const users = await pool.execute(`SELECT * FROM users`);
|
|
81
|
+
expect(users.rows).toStrictEqual([
|
|
82
|
+
{ id: 1, name: "Ellen Ripley" },
|
|
83
|
+
{ id: 2, name: "Rebecca Jorden" },
|
|
84
|
+
// Private Vasquez is not inserted because of the transaction rollback
|
|
85
|
+
]);
|
|
86
|
+
// 👎 Have to manually end the connection unless disabling `deleteBranch`
|
|
87
|
+
await pool.$client.end();
|
|
88
|
+
});
|
|
89
|
+
});
|
|
90
|
+
//# sourceMappingURL=tcp-pg-drizzle.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tcp-pg-drizzle.test.js","sourceRoot":"","sources":["../../../examples/drivers/tcp-pg-drizzle.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tcp-pg.test.d.ts","sourceRoot":"","sources":["../../../examples/drivers/tcp-pg.test.ts"],"names":[],"mappings":""}
|