@constructive-io/playwright-test 3.1.1 → 3.3.2
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 +60 -9
- package/esm/get-connections.js +12 -6
- package/esm/index.js +1 -1
- package/esm/server.js +37 -49
- package/get-connections.js +11 -5
- package/index.d.ts +1 -1
- package/index.js +2 -1
- package/package.json +11 -10
- package/server.d.ts +13 -3
- package/server.js +39 -53
- package/types.d.ts +16 -0
package/README.md
CHANGED
|
@@ -14,7 +14,12 @@
|
|
|
14
14
|
|
|
15
15
|
Constructive Playwright Testing with HTTP server support for end-to-end testing.
|
|
16
16
|
|
|
17
|
-
This package extends `@constructive-io/graphql-test` to provide an actual HTTP server for Playwright and other E2E testing frameworks. It creates isolated test databases and starts a GraphQL server
|
|
17
|
+
This package extends `@constructive-io/graphql-test` to provide an actual HTTP server for Playwright and other E2E testing frameworks. It creates isolated test databases and starts a GraphQL server for your suite to hit over HTTP.
|
|
18
|
+
|
|
19
|
+
It can run either server, selected per-suite with `server.scopedRouting`:
|
|
20
|
+
|
|
21
|
+
- `server.scopedRouting: false` (default) — the single-tenant `@constructive-io/graphql-dev-server` (pure PostGraphile). No host route resolution and no database id; the configured schemas are exposed directly. Best for UI/local suites.
|
|
22
|
+
- `server.scopedRouting: true` — the production `@constructive-io/graphql-server`. Every request is resolved through the scoped-routing plane (`constructive_routing_public.resolve_route()`), so the suite must seed real routing/database records and reach the api surface via its seeded host (`Host` header).
|
|
18
23
|
|
|
19
24
|
## Installation
|
|
20
25
|
|
|
@@ -54,6 +59,43 @@ describe('E2E Tests', () => {
|
|
|
54
59
|
});
|
|
55
60
|
```
|
|
56
61
|
|
|
62
|
+
### Against the real (scoped-routing) server
|
|
63
|
+
|
|
64
|
+
Set `server.scopedRouting: true` to run the production `@constructive-io/graphql-server`. Seed real routing/database records and address the api surface by its seeded host:
|
|
65
|
+
|
|
66
|
+
```typescript
|
|
67
|
+
import { test, expect } from '@playwright/test';
|
|
68
|
+
import { getConnectionsWithServer, seed } from '@constructive-io/playwright-test';
|
|
69
|
+
|
|
70
|
+
test('resolves through the scoped routing plane', async ({ request }) => {
|
|
71
|
+
const { server, teardown } = await getConnectionsWithServer(
|
|
72
|
+
{
|
|
73
|
+
schemas: ['simple-pets-public'],
|
|
74
|
+
authRole: 'anonymous',
|
|
75
|
+
server: {
|
|
76
|
+
scopedRouting: true,
|
|
77
|
+
api: {
|
|
78
|
+
scopedRoutingSchema: 'constructive_routing_public',
|
|
79
|
+
isPublic: true,
|
|
80
|
+
metaSchemas: ['constructive_routing_public', 'metaschema_public']
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
},
|
|
84
|
+
[seed.pgpm(pgpmWorkspace), seed.sqlfile([/* app schema + routing records */])]
|
|
85
|
+
);
|
|
86
|
+
|
|
87
|
+
try {
|
|
88
|
+
const res = await request.post(server.graphqlUrl, {
|
|
89
|
+
headers: { 'Content-Type': 'application/json', Host: 'app.test.constructive.io' },
|
|
90
|
+
data: { query: '{ animals { nodes { name } } }' }
|
|
91
|
+
});
|
|
92
|
+
expect(res.ok()).toBeTruthy();
|
|
93
|
+
} finally {
|
|
94
|
+
await teardown();
|
|
95
|
+
}
|
|
96
|
+
});
|
|
97
|
+
```
|
|
98
|
+
|
|
57
99
|
### With Playwright
|
|
58
100
|
|
|
59
101
|
```typescript
|
|
@@ -124,6 +166,8 @@ Creates database connections and starts an HTTP server for testing.
|
|
|
124
166
|
- `input.authRole` - Default authentication role (e.g., 'anonymous', 'authenticated')
|
|
125
167
|
- `input.server.port` - Port to run the server on (defaults to random available port)
|
|
126
168
|
- `input.server.host` - Host to bind to (defaults to 'localhost')
|
|
169
|
+
- `input.server.scopedRouting` - `false` (default) runs the dev server; `true` runs the production scoped-routing server
|
|
170
|
+
- `input.server.api` - API options forwarded to the production scoped server (e.g. `metaSchemas`, `isPublic`); only used when `scopedRouting` is `true`
|
|
127
171
|
- `input.graphile` - Optional Graphile configuration overrides
|
|
128
172
|
- `seedAdapters` - Optional array of seed adapters for database setup
|
|
129
173
|
|
|
@@ -144,24 +188,31 @@ Same as `getConnectionsWithServer` but throws on GraphQL errors instead of retur
|
|
|
144
188
|
|
|
145
189
|
### createTestServer(opts, serverOpts?)
|
|
146
190
|
|
|
147
|
-
Low-level function to create just the HTTP server without database setup.
|
|
191
|
+
Low-level function to create just the single-tenant dev HTTP server without database setup.
|
|
192
|
+
|
|
193
|
+
### createScopedTestServer(opts, serverOpts?)
|
|
194
|
+
|
|
195
|
+
Low-level function to create just the production `@constructive-io/graphql-server` (scoped routing) HTTP server without database setup.
|
|
148
196
|
|
|
149
197
|
## How It Works
|
|
150
198
|
|
|
151
199
|
1. Creates an isolated test database using `pgsql-test`
|
|
152
|
-
2. Starts
|
|
153
|
-
3.
|
|
154
|
-
4.
|
|
155
|
-
5.
|
|
156
|
-
6. Provides a teardown function that stops the server and cleans up the database
|
|
200
|
+
2. Starts either the dev server or the production scoped-routing server (see `server.scopedRouting`)
|
|
201
|
+
3. Exposes the GraphQL endpoint for your suite to hit over HTTP
|
|
202
|
+
4. Returns the server URL for Playwright to connect to
|
|
203
|
+
5. Provides a teardown function that stops the server and cleans up the database
|
|
157
204
|
|
|
158
205
|
## Configuration
|
|
159
206
|
|
|
160
|
-
|
|
161
|
-
- No host route resolution (`resolve_route()`) is required
|
|
207
|
+
By default (`scopedRouting: false`) the server runs `@constructive-io/graphql-dev-server`, which means:
|
|
208
|
+
- No host route resolution (`resolve_route()`) is required and no database id is needed
|
|
162
209
|
- Schemas are exposed directly based on the `schemas` parameter
|
|
163
210
|
- Perfect for isolated testing without complex domain setup
|
|
164
211
|
|
|
212
|
+
With `scopedRouting: true` the server runs the production `@constructive-io/graphql-server`:
|
|
213
|
+
- Every request is resolved through `constructive_routing_public.resolve_route()`
|
|
214
|
+
- The suite must seed real routing/database records and address the api surface by its seeded host
|
|
215
|
+
|
|
165
216
|
---
|
|
166
217
|
|
|
167
218
|
## Education and Tutorials
|
package/esm/get-connections.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { getEnvOptions } from '@constructive-io/graphql-env';
|
|
2
2
|
import { GraphQLTest } from '@constructive-io/graphql-test';
|
|
3
3
|
import { getConnections as getPgConnections } from 'pgsql-test';
|
|
4
|
-
import { createTestServer } from './server';
|
|
4
|
+
import { createScopedTestServer, createTestServer } from './server';
|
|
5
5
|
/**
|
|
6
6
|
* Core unwrapping utility - throws on GraphQL errors
|
|
7
7
|
*/
|
|
@@ -24,18 +24,24 @@ const createConnectionsWithServerBase = async (input, seedAdapters) => {
|
|
|
24
24
|
// Set up GraphQL test context for direct queries
|
|
25
25
|
const gqlContext = GraphQLTest(input, conn);
|
|
26
26
|
await gqlContext.setup();
|
|
27
|
-
// Build options for the HTTP server
|
|
27
|
+
// Build options for the HTTP server. Merge any user-provided server.api
|
|
28
|
+
// options (used by the production scoped server) with the convenience
|
|
29
|
+
// properties (schemas, authRole).
|
|
28
30
|
const serverOpts = getEnvOptions({
|
|
29
31
|
pg: pg.config,
|
|
30
32
|
api: {
|
|
31
|
-
|
|
33
|
+
...input.server?.api,
|
|
32
34
|
exposedSchemas: input.schemas,
|
|
33
|
-
defaultDatabaseId: 'test-database',
|
|
34
35
|
...(input.authRole && { anonRole: input.authRole, roleName: input.authRole })
|
|
35
36
|
}
|
|
36
37
|
});
|
|
37
|
-
// Start the HTTP server
|
|
38
|
-
|
|
38
|
+
// Start the HTTP server. Suites default to the single-tenant dev server;
|
|
39
|
+
// suites exercising the real routing plane opt into the production
|
|
40
|
+
// scoped-routing server with `server.scopedRouting: true`.
|
|
41
|
+
const scopedRouting = input.server?.scopedRouting ?? false;
|
|
42
|
+
const server = scopedRouting
|
|
43
|
+
? await createScopedTestServer(serverOpts, input.server)
|
|
44
|
+
: await createTestServer(serverOpts, input.server);
|
|
39
45
|
// Combined teardown function
|
|
40
46
|
const teardown = async () => {
|
|
41
47
|
await server.stop();
|
package/esm/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// Export our types
|
|
2
2
|
export * from './types';
|
|
3
3
|
// Export server utilities
|
|
4
|
-
export { createTestServer, getTestPool } from './server';
|
|
4
|
+
export { createScopedTestServer, createTestServer, getTestPool } from './server';
|
|
5
5
|
// Export connection functions with server support
|
|
6
6
|
export { getConnectionsWithServer, getConnectionsWithServerObject, getConnectionsWithServerUnwrapped } from './get-connections';
|
|
7
7
|
// Re-export seed and snapshot utilities from pgsql-test
|
package/esm/server.js
CHANGED
|
@@ -1,64 +1,52 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import
|
|
3
|
-
import { createServer } from 'http';
|
|
1
|
+
import { createDevServer } from '@constructive-io/graphql-dev-server';
|
|
2
|
+
import { Server } from '@constructive-io/graphql-server';
|
|
4
3
|
import { getPgPool } from 'pg-cache';
|
|
5
4
|
/**
|
|
6
|
-
*
|
|
5
|
+
* Create a single-tenant dev test server for Playwright testing.
|
|
6
|
+
*
|
|
7
|
+
* Delegates to `@constructive-io/graphql-dev-server`, a pure-PostGraphile
|
|
8
|
+
* single-tenant server (no scoped routing, no database id) that exposes the
|
|
9
|
+
* configured schemas directly.
|
|
7
10
|
*/
|
|
8
|
-
const
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
const address = server.address();
|
|
13
|
-
const port = typeof address === 'object' && address ? address.port : startPort;
|
|
14
|
-
server.close(() => resolve(port));
|
|
15
|
-
});
|
|
16
|
-
server.on('error', (err) => {
|
|
17
|
-
if (err.code === 'EADDRINUSE') {
|
|
18
|
-
resolve(findAvailablePort(startPort + 1));
|
|
19
|
-
}
|
|
20
|
-
else {
|
|
21
|
-
reject(err);
|
|
22
|
-
}
|
|
23
|
-
});
|
|
11
|
+
export const createTestServer = async (opts, serverOpts = {}) => {
|
|
12
|
+
const { httpServer, url, graphqlUrl, port, host, stop } = await createDevServer(opts, {
|
|
13
|
+
host: serverOpts.host ?? 'localhost',
|
|
14
|
+
port: serverOpts.port ?? 0
|
|
24
15
|
});
|
|
16
|
+
return { httpServer, url, graphqlUrl, port, host, stop };
|
|
25
17
|
};
|
|
26
18
|
/**
|
|
27
|
-
* Create a test server for Playwright testing
|
|
19
|
+
* Create a production scoped test server for Playwright testing.
|
|
28
20
|
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
21
|
+
* Uses the `Server` class from `@constructive-io/graphql-server` directly, so
|
|
22
|
+
* every request is resolved through the scoped-routing plane
|
|
23
|
+
* (`constructive_routing_public.resolve_route()`). Suites using this must seed
|
|
24
|
+
* real routing/database records so a real database id is resolved.
|
|
31
25
|
*/
|
|
32
|
-
export const
|
|
26
|
+
export const createScopedTestServer = async (opts, serverOpts = {}) => {
|
|
33
27
|
const host = serverOpts.host ?? 'localhost';
|
|
34
|
-
const
|
|
35
|
-
const
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
28
|
+
const port = serverOpts.port ?? 0;
|
|
29
|
+
const serverConfig = {
|
|
30
|
+
...opts,
|
|
31
|
+
server: {
|
|
32
|
+
...opts.server,
|
|
33
|
+
host,
|
|
34
|
+
port
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
const server = new Server(serverConfig);
|
|
38
|
+
const httpServer = server.listen();
|
|
39
|
+
await new Promise((resolve) => {
|
|
40
|
+
if (httpServer.listening) {
|
|
41
|
+
resolve();
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
httpServer.once('listening', () => resolve());
|
|
45
|
+
}
|
|
51
46
|
});
|
|
52
47
|
const actualPort = httpServer.address().port;
|
|
53
48
|
const stop = async () => {
|
|
54
|
-
|
|
55
|
-
httpServer.close((err) => {
|
|
56
|
-
if (err)
|
|
57
|
-
reject(err);
|
|
58
|
-
else
|
|
59
|
-
resolve();
|
|
60
|
-
});
|
|
61
|
-
});
|
|
49
|
+
await server.close({ closeCaches: true });
|
|
62
50
|
};
|
|
63
51
|
return {
|
|
64
52
|
httpServer,
|
package/get-connections.js
CHANGED
|
@@ -27,18 +27,24 @@ const createConnectionsWithServerBase = async (input, seedAdapters) => {
|
|
|
27
27
|
// Set up GraphQL test context for direct queries
|
|
28
28
|
const gqlContext = (0, graphql_test_1.GraphQLTest)(input, conn);
|
|
29
29
|
await gqlContext.setup();
|
|
30
|
-
// Build options for the HTTP server
|
|
30
|
+
// Build options for the HTTP server. Merge any user-provided server.api
|
|
31
|
+
// options (used by the production scoped server) with the convenience
|
|
32
|
+
// properties (schemas, authRole).
|
|
31
33
|
const serverOpts = (0, graphql_env_1.getEnvOptions)({
|
|
32
34
|
pg: pg.config,
|
|
33
35
|
api: {
|
|
34
|
-
|
|
36
|
+
...input.server?.api,
|
|
35
37
|
exposedSchemas: input.schemas,
|
|
36
|
-
defaultDatabaseId: 'test-database',
|
|
37
38
|
...(input.authRole && { anonRole: input.authRole, roleName: input.authRole })
|
|
38
39
|
}
|
|
39
40
|
});
|
|
40
|
-
// Start the HTTP server
|
|
41
|
-
|
|
41
|
+
// Start the HTTP server. Suites default to the single-tenant dev server;
|
|
42
|
+
// suites exercising the real routing plane opt into the production
|
|
43
|
+
// scoped-routing server with `server.scopedRouting: true`.
|
|
44
|
+
const scopedRouting = input.server?.scopedRouting ?? false;
|
|
45
|
+
const server = scopedRouting
|
|
46
|
+
? await (0, server_1.createScopedTestServer)(serverOpts, input.server)
|
|
47
|
+
: await (0, server_1.createTestServer)(serverOpts, input.server);
|
|
42
48
|
// Combined teardown function
|
|
43
49
|
const teardown = async () => {
|
|
44
50
|
await server.stop();
|
package/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { type GraphQLQueryOptions, type GraphQLTestContext, type GetConnectionsInput, type GraphQLResponse, type GraphQLQueryFn, type GraphQLQueryFnObj, type GraphQLQueryUnwrappedFn, type GraphQLQueryUnwrappedFnObj, } from '@constructive-io/graphql-test';
|
|
2
2
|
export * from './types';
|
|
3
|
-
export { createTestServer, getTestPool } from './server';
|
|
3
|
+
export { createScopedTestServer, createTestServer, getTestPool } from './server';
|
|
4
4
|
export { getConnectionsWithServer, getConnectionsWithServerObject, getConnectionsWithServerUnwrapped } from './get-connections';
|
|
5
5
|
export { seed, snapshot } from 'pgsql-test';
|
package/index.js
CHANGED
|
@@ -14,11 +14,12 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
14
14
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
-
exports.snapshot = exports.seed = exports.getConnectionsWithServerUnwrapped = exports.getConnectionsWithServerObject = exports.getConnectionsWithServer = exports.getTestPool = exports.createTestServer = void 0;
|
|
17
|
+
exports.snapshot = exports.seed = exports.getConnectionsWithServerUnwrapped = exports.getConnectionsWithServerObject = exports.getConnectionsWithServer = exports.getTestPool = exports.createTestServer = exports.createScopedTestServer = void 0;
|
|
18
18
|
// Export our types
|
|
19
19
|
__exportStar(require("./types"), exports);
|
|
20
20
|
// Export server utilities
|
|
21
21
|
var server_1 = require("./server");
|
|
22
|
+
Object.defineProperty(exports, "createScopedTestServer", { enumerable: true, get: function () { return server_1.createScopedTestServer; } });
|
|
22
23
|
Object.defineProperty(exports, "createTestServer", { enumerable: true, get: function () { return server_1.createTestServer; } });
|
|
23
24
|
Object.defineProperty(exports, "getTestPool", { enumerable: true, get: function () { return server_1.getTestPool; } });
|
|
24
25
|
// Export connection functions with server support
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@constructive-io/playwright-test",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.3.2",
|
|
4
4
|
"author": "Constructive <developers@constructive.io>",
|
|
5
5
|
"description": "Constructive Playwright Testing with HTTP server support",
|
|
6
6
|
"main": "index.js",
|
|
@@ -35,16 +35,17 @@
|
|
|
35
35
|
"makage": "^0.3.0"
|
|
36
36
|
},
|
|
37
37
|
"dependencies": {
|
|
38
|
-
"@constructive-io/graphql-
|
|
39
|
-
"@constructive-io/graphql-
|
|
40
|
-
"@constructive-io/graphql-
|
|
41
|
-
"@constructive-io/graphql-
|
|
42
|
-
"@
|
|
38
|
+
"@constructive-io/graphql-dev-server": "^3.3.2",
|
|
39
|
+
"@constructive-io/graphql-env": "^3.19.2",
|
|
40
|
+
"@constructive-io/graphql-server": "^5.3.2",
|
|
41
|
+
"@constructive-io/graphql-test": "^5.1.2",
|
|
42
|
+
"@constructive-io/graphql-types": "^3.18.2",
|
|
43
|
+
"@pgpmjs/types": "^2.37.2",
|
|
43
44
|
"express": "^5.2.1",
|
|
44
|
-
"graphile-test": "^5.
|
|
45
|
+
"graphile-test": "^5.1.2",
|
|
45
46
|
"pg": "^8.21.0",
|
|
46
|
-
"pg-cache": "^3.
|
|
47
|
-
"pgsql-test": "^5.
|
|
47
|
+
"pg-cache": "^3.16.2",
|
|
48
|
+
"pgsql-test": "^5.1.2"
|
|
48
49
|
},
|
|
49
50
|
"keywords": [
|
|
50
51
|
"testing",
|
|
@@ -55,5 +56,5 @@
|
|
|
55
56
|
"e2e",
|
|
56
57
|
"integration"
|
|
57
58
|
],
|
|
58
|
-
"gitHead": "
|
|
59
|
+
"gitHead": "08741ce3a6897192c2dbc7d1da48b9f456ffb59f"
|
|
59
60
|
}
|
package/server.d.ts
CHANGED
|
@@ -2,12 +2,22 @@ import type { ConstructiveOptions } from '@constructive-io/graphql-types';
|
|
|
2
2
|
import { Pool } from 'pg';
|
|
3
3
|
import type { PlaywrightServerOptions, ServerInfo } from './types';
|
|
4
4
|
/**
|
|
5
|
-
* Create a test server for Playwright testing
|
|
5
|
+
* Create a single-tenant dev test server for Playwright testing.
|
|
6
6
|
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
7
|
+
* Delegates to `@constructive-io/graphql-dev-server`, a pure-PostGraphile
|
|
8
|
+
* single-tenant server (no scoped routing, no database id) that exposes the
|
|
9
|
+
* configured schemas directly.
|
|
9
10
|
*/
|
|
10
11
|
export declare const createTestServer: (opts: ConstructiveOptions, serverOpts?: PlaywrightServerOptions) => Promise<ServerInfo>;
|
|
12
|
+
/**
|
|
13
|
+
* Create a production scoped test server for Playwright testing.
|
|
14
|
+
*
|
|
15
|
+
* Uses the `Server` class from `@constructive-io/graphql-server` directly, so
|
|
16
|
+
* every request is resolved through the scoped-routing plane
|
|
17
|
+
* (`constructive_routing_public.resolve_route()`). Suites using this must seed
|
|
18
|
+
* real routing/database records so a real database id is resolved.
|
|
19
|
+
*/
|
|
20
|
+
export declare const createScopedTestServer: (opts: ConstructiveOptions, serverOpts?: PlaywrightServerOptions) => Promise<ServerInfo>;
|
|
11
21
|
/**
|
|
12
22
|
* Get the PostgreSQL pool for the test server
|
|
13
23
|
*/
|
package/server.js
CHANGED
|
@@ -1,70 +1,56 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.getTestPool = exports.createTestServer = void 0;
|
|
3
|
+
exports.getTestPool = exports.createScopedTestServer = exports.createTestServer = void 0;
|
|
4
|
+
const graphql_dev_server_1 = require("@constructive-io/graphql-dev-server");
|
|
7
5
|
const graphql_server_1 = require("@constructive-io/graphql-server");
|
|
8
|
-
const express_1 = __importDefault(require("express"));
|
|
9
|
-
const http_1 = require("http");
|
|
10
6
|
const pg_cache_1 = require("pg-cache");
|
|
11
7
|
/**
|
|
12
|
-
*
|
|
8
|
+
* Create a single-tenant dev test server for Playwright testing.
|
|
9
|
+
*
|
|
10
|
+
* Delegates to `@constructive-io/graphql-dev-server`, a pure-PostGraphile
|
|
11
|
+
* single-tenant server (no scoped routing, no database id) that exposes the
|
|
12
|
+
* configured schemas directly.
|
|
13
13
|
*/
|
|
14
|
-
const
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
const address = server.address();
|
|
19
|
-
const port = typeof address === 'object' && address ? address.port : startPort;
|
|
20
|
-
server.close(() => resolve(port));
|
|
21
|
-
});
|
|
22
|
-
server.on('error', (err) => {
|
|
23
|
-
if (err.code === 'EADDRINUSE') {
|
|
24
|
-
resolve(findAvailablePort(startPort + 1));
|
|
25
|
-
}
|
|
26
|
-
else {
|
|
27
|
-
reject(err);
|
|
28
|
-
}
|
|
29
|
-
});
|
|
14
|
+
const createTestServer = async (opts, serverOpts = {}) => {
|
|
15
|
+
const { httpServer, url, graphqlUrl, port, host, stop } = await (0, graphql_dev_server_1.createDevServer)(opts, {
|
|
16
|
+
host: serverOpts.host ?? 'localhost',
|
|
17
|
+
port: serverOpts.port ?? 0
|
|
30
18
|
});
|
|
19
|
+
return { httpServer, url, graphqlUrl, port, host, stop };
|
|
31
20
|
};
|
|
21
|
+
exports.createTestServer = createTestServer;
|
|
32
22
|
/**
|
|
33
|
-
* Create a test server for Playwright testing
|
|
23
|
+
* Create a production scoped test server for Playwright testing.
|
|
34
24
|
*
|
|
35
|
-
*
|
|
36
|
-
*
|
|
25
|
+
* Uses the `Server` class from `@constructive-io/graphql-server` directly, so
|
|
26
|
+
* every request is resolved through the scoped-routing plane
|
|
27
|
+
* (`constructive_routing_public.resolve_route()`). Suites using this must seed
|
|
28
|
+
* real routing/database records so a real database id is resolved.
|
|
37
29
|
*/
|
|
38
|
-
const
|
|
30
|
+
const createScopedTestServer = async (opts, serverOpts = {}) => {
|
|
39
31
|
const host = serverOpts.host ?? 'localhost';
|
|
40
|
-
const
|
|
41
|
-
const
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
32
|
+
const port = serverOpts.port ?? 0;
|
|
33
|
+
const serverConfig = {
|
|
34
|
+
...opts,
|
|
35
|
+
server: {
|
|
36
|
+
...opts.server,
|
|
37
|
+
host,
|
|
38
|
+
port
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
const server = new graphql_server_1.Server(serverConfig);
|
|
42
|
+
const httpServer = server.listen();
|
|
43
|
+
await new Promise((resolve) => {
|
|
44
|
+
if (httpServer.listening) {
|
|
45
|
+
resolve();
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
httpServer.once('listening', () => resolve());
|
|
49
|
+
}
|
|
57
50
|
});
|
|
58
51
|
const actualPort = httpServer.address().port;
|
|
59
52
|
const stop = async () => {
|
|
60
|
-
|
|
61
|
-
httpServer.close((err) => {
|
|
62
|
-
if (err)
|
|
63
|
-
reject(err);
|
|
64
|
-
else
|
|
65
|
-
resolve();
|
|
66
|
-
});
|
|
67
|
-
});
|
|
53
|
+
await server.close({ closeCaches: true });
|
|
68
54
|
};
|
|
69
55
|
return {
|
|
70
56
|
httpServer,
|
|
@@ -75,7 +61,7 @@ const createTestServer = async (opts, serverOpts = {}) => {
|
|
|
75
61
|
stop
|
|
76
62
|
};
|
|
77
63
|
};
|
|
78
|
-
exports.
|
|
64
|
+
exports.createScopedTestServer = createScopedTestServer;
|
|
79
65
|
/**
|
|
80
66
|
* Get the PostgreSQL pool for the test server
|
|
81
67
|
*/
|
package/types.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { Server } from 'http';
|
|
2
2
|
import type { PgTestClient } from 'pgsql-test/test-client';
|
|
3
|
+
import type { ApiOptions } from '@constructive-io/graphql-types';
|
|
3
4
|
import type { GetConnectionsInput, GraphQLQueryFn, GraphQLQueryFnObj } from '@constructive-io/graphql-test';
|
|
4
5
|
/**
|
|
5
6
|
* Options for creating a Playwright test server
|
|
@@ -9,6 +10,21 @@ export interface PlaywrightServerOptions {
|
|
|
9
10
|
port?: number;
|
|
10
11
|
/** Host to bind the server to (defaults to localhost) */
|
|
11
12
|
host?: string;
|
|
13
|
+
/**
|
|
14
|
+
* Which server to run this suite against:
|
|
15
|
+
* - `false` (default): the single-tenant `@constructive-io/graphql-dev-server`
|
|
16
|
+
* (pure PostGraphile, no routing, no database id) exposing the configured
|
|
17
|
+
* schemas directly. Best for UI/local suites that don't need routing.
|
|
18
|
+
* - `true`: the production `@constructive-io/graphql-server`, which resolves
|
|
19
|
+
* every request through the scoped-routing plane. Suites must seed real
|
|
20
|
+
* routing/database records so `resolve_route()` returns a real database id.
|
|
21
|
+
*/
|
|
22
|
+
scopedRouting?: boolean;
|
|
23
|
+
/**
|
|
24
|
+
* API configuration forwarded to the production scoped server (e.g.
|
|
25
|
+
* `metaSchemas`, `isPublic`). Only used when `scopedRouting` is `true`.
|
|
26
|
+
*/
|
|
27
|
+
api?: Partial<ApiOptions>;
|
|
12
28
|
}
|
|
13
29
|
/**
|
|
14
30
|
* Input options for getConnectionsWithServer
|