@rest-vir/run-service 0.0.3 → 0.0.4
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.
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { CollapsedFetchEndpointParams, EndpointDefinition } from '@rest-vir/define-service';
|
|
2
|
+
/**
|
|
3
|
+
* The type definition for {@link testEndpoint}.
|
|
4
|
+
*
|
|
5
|
+
* @category Internal
|
|
6
|
+
* @category Package : @rest-vir/run-service
|
|
7
|
+
* @package [`@rest-vir/run-service`](https://www.npmjs.com/package/@rest-vir/run-service)
|
|
8
|
+
*/
|
|
9
|
+
export type TestEndpoint = <EndpointToTest extends EndpointDefinition>(endpoint: EndpointToTest, ...args: CollapsedFetchEndpointParams<EndpointToTest, false>) => Promise<Response>;
|
|
10
|
+
/**
|
|
11
|
+
* Test your endpoint with real Request and Response objects!
|
|
12
|
+
*
|
|
13
|
+
* @category Testing : Backend
|
|
14
|
+
* @category Package : @rest-vir/run-service
|
|
15
|
+
* @example
|
|
16
|
+
*
|
|
17
|
+
* ```ts
|
|
18
|
+
* import {testEndpoint} from '@rest-vir/run-service';
|
|
19
|
+
*
|
|
20
|
+
* const response = await testEndpoint(myServiceImplementation.endpoints['/my-endpoint']);
|
|
21
|
+
* ```
|
|
22
|
+
*
|
|
23
|
+
* @package [`@rest-vir/run-service`](https://www.npmjs.com/package/@rest-vir/run-service)
|
|
24
|
+
*/
|
|
25
|
+
export declare const testEndpoint: TestEndpoint;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { testService } from './test-service.js';
|
|
2
|
+
/**
|
|
3
|
+
* Test your endpoint with real Request and Response objects!
|
|
4
|
+
*
|
|
5
|
+
* @category Testing : Backend
|
|
6
|
+
* @category Package : @rest-vir/run-service
|
|
7
|
+
* @example
|
|
8
|
+
*
|
|
9
|
+
* ```ts
|
|
10
|
+
* import {testEndpoint} from '@rest-vir/run-service';
|
|
11
|
+
*
|
|
12
|
+
* const response = await testEndpoint(myServiceImplementation.endpoints['/my-endpoint']);
|
|
13
|
+
* ```
|
|
14
|
+
*
|
|
15
|
+
* @package [`@rest-vir/run-service`](https://www.npmjs.com/package/@rest-vir/run-service)
|
|
16
|
+
*/
|
|
17
|
+
export const testEndpoint = async function testEndpoint(endpoint, ...args) {
|
|
18
|
+
const { fetchEndpoint, kill } = await testService({
|
|
19
|
+
...endpoint.service,
|
|
20
|
+
endpoints: {
|
|
21
|
+
[endpoint.path]: endpoint,
|
|
22
|
+
},
|
|
23
|
+
webSockets: {},
|
|
24
|
+
}, {
|
|
25
|
+
debug: true,
|
|
26
|
+
});
|
|
27
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
28
|
+
const response = await fetchEndpoint[endpoint.path](...args);
|
|
29
|
+
await kill();
|
|
30
|
+
return response;
|
|
31
|
+
};
|
|
@@ -0,0 +1,364 @@
|
|
|
1
|
+
import { type Overwrite, type PartialWithUndefined, type SelectFrom } from '@augment-vir/common';
|
|
2
|
+
import { ClientWebSocket, CollapsedConnectWebSocketParams, CollapsedFetchEndpointParams, EndpointDefinition, WebSocketDefinition } from '@rest-vir/define-service';
|
|
3
|
+
import { GenericServiceImplementation } from '@rest-vir/implement-service';
|
|
4
|
+
import { FastifyInstance } from 'fastify';
|
|
5
|
+
import { HandleRouteOptions } from '../handle-request/endpoint-handler.js';
|
|
6
|
+
import { StartServiceOptions, type StartServiceUserOptions } from '../start-service/start-service-options.js';
|
|
7
|
+
/**
|
|
8
|
+
* Options for {@link condenseResponse}.
|
|
9
|
+
*
|
|
10
|
+
* @category Internal
|
|
11
|
+
* @category Package : @rest-vir/run-service
|
|
12
|
+
* @package [`@rest-vir/run-service`](https://www.npmjs.com/package/@rest-vir/run-service)
|
|
13
|
+
*/
|
|
14
|
+
export type CondenseResponseOptions = {
|
|
15
|
+
/**
|
|
16
|
+
* Include all headers that fastify and rest-vir automatically append.
|
|
17
|
+
*
|
|
18
|
+
* @default false
|
|
19
|
+
*/
|
|
20
|
+
includeDefaultHeaders: boolean;
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* Condense a response into just the interesting properties for easier testing comparisons.
|
|
24
|
+
*
|
|
25
|
+
* @category Internal
|
|
26
|
+
* @category Package : @rest-vir/run-service
|
|
27
|
+
* @package [`@rest-vir/run-service`](https://www.npmjs.com/package/@rest-vir/run-service)
|
|
28
|
+
*/
|
|
29
|
+
export declare function condenseResponse(response: Response, options?: PartialWithUndefined<CondenseResponseOptions>): Promise<{
|
|
30
|
+
headers: Omit<{
|
|
31
|
+
[x: string]: /*elided*/ any;
|
|
32
|
+
accept?: string | string[] | undefined | undefined;
|
|
33
|
+
"accept-charset"?: string | string[] | undefined | undefined;
|
|
34
|
+
"accept-encoding"?: string | string[] | undefined | undefined;
|
|
35
|
+
"accept-language"?: string | string[] | undefined | undefined;
|
|
36
|
+
"accept-ranges"?: string | undefined | undefined;
|
|
37
|
+
"access-control-allow-credentials"?: string | undefined | undefined;
|
|
38
|
+
"access-control-allow-headers"?: string | undefined | undefined;
|
|
39
|
+
"access-control-allow-methods"?: string | undefined | undefined;
|
|
40
|
+
"access-control-allow-origin"?: string | undefined | undefined;
|
|
41
|
+
"access-control-expose-headers"?: string | undefined | undefined;
|
|
42
|
+
"access-control-max-age"?: string | undefined | undefined;
|
|
43
|
+
"access-control-request-headers"?: string | undefined | undefined;
|
|
44
|
+
"access-control-request-method"?: string | undefined | undefined;
|
|
45
|
+
age?: string | undefined | undefined;
|
|
46
|
+
allow?: string | undefined | undefined;
|
|
47
|
+
authorization?: string | undefined | undefined;
|
|
48
|
+
"cache-control"?: string | undefined | undefined;
|
|
49
|
+
"cdn-cache-control"?: string | undefined | undefined;
|
|
50
|
+
connection?: string | string[] | undefined | undefined;
|
|
51
|
+
"content-disposition"?: string | undefined | undefined;
|
|
52
|
+
"content-encoding"?: string | undefined | undefined;
|
|
53
|
+
"content-language"?: string | undefined | undefined;
|
|
54
|
+
"content-length"?: string | number | undefined | undefined;
|
|
55
|
+
"content-location"?: string | undefined | undefined;
|
|
56
|
+
"content-range"?: string | undefined | undefined;
|
|
57
|
+
"content-security-policy"?: string | undefined | undefined;
|
|
58
|
+
"content-security-policy-report-only"?: string | undefined | undefined;
|
|
59
|
+
"content-type"?: string | undefined | undefined;
|
|
60
|
+
cookie?: string | string[] | undefined | undefined;
|
|
61
|
+
dav?: string | string[] | undefined | undefined;
|
|
62
|
+
dnt?: string | undefined | undefined;
|
|
63
|
+
date?: string | undefined | undefined;
|
|
64
|
+
etag?: string | undefined | undefined;
|
|
65
|
+
expect?: string | undefined | undefined;
|
|
66
|
+
expires?: string | undefined | undefined;
|
|
67
|
+
forwarded?: string | undefined | undefined;
|
|
68
|
+
from?: string | undefined | undefined;
|
|
69
|
+
host?: string | undefined | undefined;
|
|
70
|
+
"if-match"?: string | undefined | undefined;
|
|
71
|
+
"if-modified-since"?: string | undefined | undefined;
|
|
72
|
+
"if-none-match"?: string | undefined | undefined;
|
|
73
|
+
"if-range"?: string | undefined | undefined;
|
|
74
|
+
"if-unmodified-since"?: string | undefined | undefined;
|
|
75
|
+
"last-modified"?: string | undefined | undefined;
|
|
76
|
+
link?: string | string[] | undefined | undefined;
|
|
77
|
+
location?: string | undefined | undefined;
|
|
78
|
+
"max-forwards"?: string | undefined | undefined;
|
|
79
|
+
origin?: string | undefined | undefined;
|
|
80
|
+
pragma?: string | string[] | undefined | undefined;
|
|
81
|
+
"proxy-authenticate"?: string | string[] | undefined | undefined;
|
|
82
|
+
"proxy-authorization"?: string | undefined | undefined;
|
|
83
|
+
"public-key-pins"?: string | undefined | undefined;
|
|
84
|
+
"public-key-pins-report-only"?: string | undefined | undefined;
|
|
85
|
+
range?: string | undefined | undefined;
|
|
86
|
+
referer?: string | undefined | undefined;
|
|
87
|
+
"referrer-policy"?: string | undefined | undefined;
|
|
88
|
+
refresh?: string | undefined | undefined;
|
|
89
|
+
"retry-after"?: string | undefined | undefined;
|
|
90
|
+
"sec-websocket-accept"?: string | undefined | undefined;
|
|
91
|
+
"sec-websocket-extensions"?: string | string[] | undefined | undefined;
|
|
92
|
+
"sec-websocket-key"?: string | undefined | undefined;
|
|
93
|
+
"sec-websocket-protocol"?: string | string[] | undefined | undefined;
|
|
94
|
+
"sec-websocket-version"?: string | undefined | undefined;
|
|
95
|
+
server?: string | undefined | undefined;
|
|
96
|
+
"set-cookie"?: string | string[] | undefined | undefined;
|
|
97
|
+
"strict-transport-security"?: string | undefined | undefined;
|
|
98
|
+
te?: string | undefined | undefined;
|
|
99
|
+
trailer?: string | undefined | undefined;
|
|
100
|
+
"transfer-encoding"?: string | undefined | undefined;
|
|
101
|
+
"user-agent"?: string | undefined | undefined;
|
|
102
|
+
upgrade?: string | undefined | undefined;
|
|
103
|
+
"upgrade-insecure-requests"?: string | undefined | undefined;
|
|
104
|
+
vary?: string | undefined | undefined;
|
|
105
|
+
via?: string | string[] | undefined | undefined;
|
|
106
|
+
warning?: string | undefined | undefined;
|
|
107
|
+
"www-authenticate"?: string | string[] | undefined | undefined;
|
|
108
|
+
"x-content-type-options"?: string | undefined | undefined;
|
|
109
|
+
"x-dns-prefetch-control"?: string | undefined | undefined;
|
|
110
|
+
"x-frame-options"?: string | undefined | undefined;
|
|
111
|
+
"x-xss-protection"?: string | undefined | undefined;
|
|
112
|
+
}, "connection" | "content-length" | "date" | "rest-vir-service" | "keep-alive">;
|
|
113
|
+
body: string;
|
|
114
|
+
status: import("@augment-vir/common").HttpStatus;
|
|
115
|
+
} | {
|
|
116
|
+
headers: Omit<{
|
|
117
|
+
[x: string]: /*elided*/ any;
|
|
118
|
+
accept?: string | string[] | undefined | undefined;
|
|
119
|
+
"accept-charset"?: string | string[] | undefined | undefined;
|
|
120
|
+
"accept-encoding"?: string | string[] | undefined | undefined;
|
|
121
|
+
"accept-language"?: string | string[] | undefined | undefined;
|
|
122
|
+
"accept-ranges"?: string | undefined | undefined;
|
|
123
|
+
"access-control-allow-credentials"?: string | undefined | undefined;
|
|
124
|
+
"access-control-allow-headers"?: string | undefined | undefined;
|
|
125
|
+
"access-control-allow-methods"?: string | undefined | undefined;
|
|
126
|
+
"access-control-allow-origin"?: string | undefined | undefined;
|
|
127
|
+
"access-control-expose-headers"?: string | undefined | undefined;
|
|
128
|
+
"access-control-max-age"?: string | undefined | undefined;
|
|
129
|
+
"access-control-request-headers"?: string | undefined | undefined;
|
|
130
|
+
"access-control-request-method"?: string | undefined | undefined;
|
|
131
|
+
age?: string | undefined | undefined;
|
|
132
|
+
allow?: string | undefined | undefined;
|
|
133
|
+
authorization?: string | undefined | undefined;
|
|
134
|
+
"cache-control"?: string | undefined | undefined;
|
|
135
|
+
"cdn-cache-control"?: string | undefined | undefined;
|
|
136
|
+
connection?: string | string[] | undefined | undefined;
|
|
137
|
+
"content-disposition"?: string | undefined | undefined;
|
|
138
|
+
"content-encoding"?: string | undefined | undefined;
|
|
139
|
+
"content-language"?: string | undefined | undefined;
|
|
140
|
+
"content-length"?: string | number | undefined | undefined;
|
|
141
|
+
"content-location"?: string | undefined | undefined;
|
|
142
|
+
"content-range"?: string | undefined | undefined;
|
|
143
|
+
"content-security-policy"?: string | undefined | undefined;
|
|
144
|
+
"content-security-policy-report-only"?: string | undefined | undefined;
|
|
145
|
+
"content-type"?: string | undefined | undefined;
|
|
146
|
+
cookie?: string | string[] | undefined | undefined;
|
|
147
|
+
dav?: string | string[] | undefined | undefined;
|
|
148
|
+
dnt?: string | undefined | undefined;
|
|
149
|
+
date?: string | undefined | undefined;
|
|
150
|
+
etag?: string | undefined | undefined;
|
|
151
|
+
expect?: string | undefined | undefined;
|
|
152
|
+
expires?: string | undefined | undefined;
|
|
153
|
+
forwarded?: string | undefined | undefined;
|
|
154
|
+
from?: string | undefined | undefined;
|
|
155
|
+
host?: string | undefined | undefined;
|
|
156
|
+
"if-match"?: string | undefined | undefined;
|
|
157
|
+
"if-modified-since"?: string | undefined | undefined;
|
|
158
|
+
"if-none-match"?: string | undefined | undefined;
|
|
159
|
+
"if-range"?: string | undefined | undefined;
|
|
160
|
+
"if-unmodified-since"?: string | undefined | undefined;
|
|
161
|
+
"last-modified"?: string | undefined | undefined;
|
|
162
|
+
link?: string | string[] | undefined | undefined;
|
|
163
|
+
location?: string | undefined | undefined;
|
|
164
|
+
"max-forwards"?: string | undefined | undefined;
|
|
165
|
+
origin?: string | undefined | undefined;
|
|
166
|
+
pragma?: string | string[] | undefined | undefined;
|
|
167
|
+
"proxy-authenticate"?: string | string[] | undefined | undefined;
|
|
168
|
+
"proxy-authorization"?: string | undefined | undefined;
|
|
169
|
+
"public-key-pins"?: string | undefined | undefined;
|
|
170
|
+
"public-key-pins-report-only"?: string | undefined | undefined;
|
|
171
|
+
range?: string | undefined | undefined;
|
|
172
|
+
referer?: string | undefined | undefined;
|
|
173
|
+
"referrer-policy"?: string | undefined | undefined;
|
|
174
|
+
refresh?: string | undefined | undefined;
|
|
175
|
+
"retry-after"?: string | undefined | undefined;
|
|
176
|
+
"sec-websocket-accept"?: string | undefined | undefined;
|
|
177
|
+
"sec-websocket-extensions"?: string | string[] | undefined | undefined;
|
|
178
|
+
"sec-websocket-key"?: string | undefined | undefined;
|
|
179
|
+
"sec-websocket-protocol"?: string | string[] | undefined | undefined;
|
|
180
|
+
"sec-websocket-version"?: string | undefined | undefined;
|
|
181
|
+
server?: string | undefined | undefined;
|
|
182
|
+
"set-cookie"?: string | string[] | undefined | undefined;
|
|
183
|
+
"strict-transport-security"?: string | undefined | undefined;
|
|
184
|
+
te?: string | undefined | undefined;
|
|
185
|
+
trailer?: string | undefined | undefined;
|
|
186
|
+
"transfer-encoding"?: string | undefined | undefined;
|
|
187
|
+
"user-agent"?: string | undefined | undefined;
|
|
188
|
+
upgrade?: string | undefined | undefined;
|
|
189
|
+
"upgrade-insecure-requests"?: string | undefined | undefined;
|
|
190
|
+
vary?: string | undefined | undefined;
|
|
191
|
+
via?: string | string[] | undefined | undefined;
|
|
192
|
+
warning?: string | undefined | undefined;
|
|
193
|
+
"www-authenticate"?: string | string[] | undefined | undefined;
|
|
194
|
+
"x-content-type-options"?: string | undefined | undefined;
|
|
195
|
+
"x-dns-prefetch-control"?: string | undefined | undefined;
|
|
196
|
+
"x-frame-options"?: string | undefined | undefined;
|
|
197
|
+
"x-xss-protection"?: string | undefined | undefined;
|
|
198
|
+
}, "connection" | "content-length" | "date" | "rest-vir-service" | "keep-alive">;
|
|
199
|
+
body?: never;
|
|
200
|
+
status: import("@augment-vir/common").HttpStatus;
|
|
201
|
+
}>;
|
|
202
|
+
/**
|
|
203
|
+
* Used for each individual endpoint's fetcher in {@link FetchTestService}.
|
|
204
|
+
*
|
|
205
|
+
* @category Internal
|
|
206
|
+
* @category Package : @rest-vir/run-service
|
|
207
|
+
* @package [`@rest-vir/run-service`](https://www.npmjs.com/package/@rest-vir/run-service)
|
|
208
|
+
*/
|
|
209
|
+
export type FetchTestEndpoint<EndpointToTest extends EndpointDefinition> = (...params: CollapsedFetchEndpointParams<EndpointToTest, false>) => Promise<Response>;
|
|
210
|
+
/**
|
|
211
|
+
* Used for each individual endpoint's fetcher in {@link FetchTestService}.
|
|
212
|
+
*
|
|
213
|
+
* @category Internal
|
|
214
|
+
* @category Package : @rest-vir/run-service
|
|
215
|
+
* @package [`@rest-vir/run-service`](https://www.npmjs.com/package/@rest-vir/run-service)
|
|
216
|
+
*/
|
|
217
|
+
export type ConnectTestWebSocket<WebSocketToTest extends WebSocketDefinition> = (...params: CollapsedConnectWebSocketParams<WebSocketToTest, false>) => Promise<ClientWebSocket<WebSocketToTest>>;
|
|
218
|
+
/**
|
|
219
|
+
* Type for the `fetchEndpoint` function provided by {@link testService} and {@link describeService}.
|
|
220
|
+
*
|
|
221
|
+
* @category Internal
|
|
222
|
+
* @category Package : @rest-vir/run-service
|
|
223
|
+
* @package [`@rest-vir/run-service`](https://www.npmjs.com/package/@rest-vir/run-service)
|
|
224
|
+
*/
|
|
225
|
+
export type FetchTestService<Service extends SelectFrom<GenericServiceImplementation, {
|
|
226
|
+
endpoints: true;
|
|
227
|
+
}>> = {
|
|
228
|
+
[EndpointPath in keyof Service['endpoints']]: Service['endpoints'][EndpointPath] extends EndpointDefinition ? FetchTestEndpoint<Service['endpoints'][EndpointPath]> : never;
|
|
229
|
+
};
|
|
230
|
+
/**
|
|
231
|
+
* Type for the `connectWebSocket` function provided by {@link testService} and
|
|
232
|
+
* {@link describeService}.
|
|
233
|
+
*
|
|
234
|
+
* @category Internal
|
|
235
|
+
* @category Package : @rest-vir/run-service
|
|
236
|
+
* @package [`@rest-vir/run-service`](https://www.npmjs.com/package/@rest-vir/run-service)
|
|
237
|
+
*/
|
|
238
|
+
export type ConnectTestServiceWebSocket<Service extends SelectFrom<GenericServiceImplementation, {
|
|
239
|
+
webSockets: true;
|
|
240
|
+
}>> = {
|
|
241
|
+
[WebSocketPath in keyof Service['webSockets']]: Service['webSockets'][WebSocketPath] extends WebSocketDefinition ? ConnectTestWebSocket<Service['webSockets'][WebSocketPath]> : never;
|
|
242
|
+
};
|
|
243
|
+
/**
|
|
244
|
+
* Options for {@link testService}.
|
|
245
|
+
*
|
|
246
|
+
* @category Internal
|
|
247
|
+
* @category Package : @rest-vir/run-service
|
|
248
|
+
* @package [`@rest-vir/run-service`](https://www.npmjs.com/package/@rest-vir/run-service)
|
|
249
|
+
*/
|
|
250
|
+
export type TestServiceOptions = Overwrite<StartServiceUserOptions, {
|
|
251
|
+
port?: number | undefined | false;
|
|
252
|
+
}>;
|
|
253
|
+
/**
|
|
254
|
+
* Test your service with actual Request and Response objects! The returned object includes
|
|
255
|
+
* utilities for sending fetch requests and WebSocket connections to the service.
|
|
256
|
+
*
|
|
257
|
+
* Make sure to use the `kill` output after your tests are finished. To automatically kill the
|
|
258
|
+
* server, use {@link describeService} instead.
|
|
259
|
+
*
|
|
260
|
+
* By default, this uses Fastify's request injection strategy to avoid using up real system ports.
|
|
261
|
+
* To instead use an actual port, set `port` in the options parameter.
|
|
262
|
+
*
|
|
263
|
+
* @category Internal
|
|
264
|
+
* @category Package : @rest-vir/run-service
|
|
265
|
+
* @example
|
|
266
|
+
*
|
|
267
|
+
* ```ts
|
|
268
|
+
* import {testService} from '@rest-vir/run-service';
|
|
269
|
+
*
|
|
270
|
+
* const {connectWebsocket, kill, fetchEndpoint} = await testService(myServiceImplementation);
|
|
271
|
+
*
|
|
272
|
+
* // run tests
|
|
273
|
+
*
|
|
274
|
+
* await kill();
|
|
275
|
+
* ```
|
|
276
|
+
*
|
|
277
|
+
* @package [`@rest-vir/run-service`](https://www.npmjs.com/package/@rest-vir/run-service)
|
|
278
|
+
*/
|
|
279
|
+
export declare function testService<const Service extends Readonly<SelectFrom<GenericServiceImplementation, {
|
|
280
|
+
webSockets: true;
|
|
281
|
+
endpoints: true;
|
|
282
|
+
serviceName: true;
|
|
283
|
+
createContext: true;
|
|
284
|
+
serviceOrigin: true;
|
|
285
|
+
requiredClientOrigin: true;
|
|
286
|
+
logger: true;
|
|
287
|
+
}>>>(service: Readonly<Service>, testServiceOptions?: Readonly<Omit<PartialWithUndefined<StartServiceUserOptions>, 'workerCount' | 'preventWorkerRespawn' | ''>>): Promise<{
|
|
288
|
+
/** Kill the server being tested. This should always be called after your tests are finished. */
|
|
289
|
+
kill(this: void): Promise<void>;
|
|
290
|
+
/** Send a request to the service. */
|
|
291
|
+
fetchEndpoint: FetchTestService<Service>;
|
|
292
|
+
/** Connect to a service WebSocket. */
|
|
293
|
+
connectWebSocket: ConnectTestServiceWebSocket<Service>;
|
|
294
|
+
}>;
|
|
295
|
+
/**
|
|
296
|
+
* Similar to {@link testService} but used to test against a Fastify server that you've already
|
|
297
|
+
* started elsewhere. This will merely attach all route listeners to it and return test callbacks.
|
|
298
|
+
*
|
|
299
|
+
* The returned object includes a function to send fetches to directly to the running service.
|
|
300
|
+
*
|
|
301
|
+
* By default, this uses Fastify's request injection strategy to avoid using up real system ports.
|
|
302
|
+
* To instead listen to an actual port, set `port` in the options parameter.
|
|
303
|
+
*
|
|
304
|
+
* @category Internal
|
|
305
|
+
* @category Package : @rest-vir/run-service
|
|
306
|
+
* @package [`@rest-vir/run-service`](https://www.npmjs.com/package/@rest-vir/run-service)
|
|
307
|
+
*/
|
|
308
|
+
export declare function testExistingServer<const Service extends Readonly<SelectFrom<GenericServiceImplementation, {
|
|
309
|
+
webSockets: true;
|
|
310
|
+
endpoints: true;
|
|
311
|
+
serviceName: true;
|
|
312
|
+
createContext: true;
|
|
313
|
+
serviceOrigin: true;
|
|
314
|
+
requiredClientOrigin: true;
|
|
315
|
+
logger: true;
|
|
316
|
+
}>>>(server: Readonly<FastifyInstance>, service: Readonly<Service>, options?: Readonly<HandleRouteOptions & Omit<PartialWithUndefined<StartServiceOptions>, 'workerCount' | 'preventWorkerRespawn'>>): Promise<{
|
|
317
|
+
/** Send a request to the service. */
|
|
318
|
+
fetchEndpoint: FetchTestService<Service>;
|
|
319
|
+
/** Connect to a service WebSocket. */
|
|
320
|
+
connectWebSocket: ConnectTestServiceWebSocket<Service>;
|
|
321
|
+
}>;
|
|
322
|
+
/**
|
|
323
|
+
* Use this in conjunction with
|
|
324
|
+
* [`@augment-vir/test`](https://www.npmjs.com/package/@augment-vir/test) or the Node.js built-in
|
|
325
|
+
* test runner to run tests for a service and automatically kill the service when all tests have
|
|
326
|
+
* finished. The describe callback is passed a params object which includes a fetch function.
|
|
327
|
+
*
|
|
328
|
+
* See {@link testService} for more control over how tests are run (but without automatic server
|
|
329
|
+
* shutdown).
|
|
330
|
+
*
|
|
331
|
+
* @category Testing : Backend
|
|
332
|
+
* @category Package : @rest-vir/run-service
|
|
333
|
+
* @example
|
|
334
|
+
*
|
|
335
|
+
* ```ts
|
|
336
|
+
* import {describeService} from '@rest-vir/run-service';
|
|
337
|
+
* import {it} from '@augment-vir/test';
|
|
338
|
+
*
|
|
339
|
+
* describeService({service: myService}, ({fetchEndpoint}) => {
|
|
340
|
+
* it('responds', async () => {
|
|
341
|
+
* const response = await fetchEndpoint['/my-endpoint']();
|
|
342
|
+
* });
|
|
343
|
+
* });
|
|
344
|
+
* ```
|
|
345
|
+
*
|
|
346
|
+
* @package [`@rest-vir/run-service`](https://www.npmjs.com/package/@rest-vir/run-service)
|
|
347
|
+
*/
|
|
348
|
+
export declare function describeService<const Service extends Readonly<SelectFrom<GenericServiceImplementation, {
|
|
349
|
+
webSockets: true;
|
|
350
|
+
endpoints: true;
|
|
351
|
+
serviceName: true;
|
|
352
|
+
createContext: true;
|
|
353
|
+
serviceOrigin: true;
|
|
354
|
+
requiredClientOrigin: true;
|
|
355
|
+
logger: true;
|
|
356
|
+
}>>>({ service, options, }: {
|
|
357
|
+
/** The service to startup and send requests to. */
|
|
358
|
+
service: Readonly<Service>;
|
|
359
|
+
/** Options for starting the service. */
|
|
360
|
+
options?: PartialWithUndefined<StartServiceUserOptions>;
|
|
361
|
+
}, describeCallback: (params: {
|
|
362
|
+
/** Send a request to the service. */
|
|
363
|
+
fetchEndpoint: FetchTestService<Service>;
|
|
364
|
+
}) => void | undefined): void;
|
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
import { assert, assertWrap, check } from '@augment-vir/assert';
|
|
2
|
+
import { ensureErrorAndPrependMessage, log, mapObjectValues, mergeDeep, mergeDefinedProperties, omitObjectKeys, } from '@augment-vir/common';
|
|
3
|
+
import { describe, it } from '@augment-vir/test';
|
|
4
|
+
import { assertValidWebSocketProtocols, buildEndpointRequestInit, buildWebSocketUrl, finalizeWebSocket, restVirServiceNameHeader, WebSocketLocation, } from '@rest-vir/define-service';
|
|
5
|
+
import fastify from 'fastify';
|
|
6
|
+
import { buildUrl, parseUrl } from 'url-vir';
|
|
7
|
+
import { attachService } from '../start-service/attach-service.js';
|
|
8
|
+
import { applyDebugLogger } from '../util/debug.js';
|
|
9
|
+
/**
|
|
10
|
+
* Condense a response into just the interesting properties for easier testing comparisons.
|
|
11
|
+
*
|
|
12
|
+
* @category Internal
|
|
13
|
+
* @category Package : @rest-vir/run-service
|
|
14
|
+
* @package [`@rest-vir/run-service`](https://www.npmjs.com/package/@rest-vir/run-service)
|
|
15
|
+
*/
|
|
16
|
+
export async function condenseResponse(response, options = {}) {
|
|
17
|
+
const bodyText = await response.text();
|
|
18
|
+
const bodyObject = bodyText
|
|
19
|
+
? {
|
|
20
|
+
body: bodyText,
|
|
21
|
+
}
|
|
22
|
+
: {};
|
|
23
|
+
const headers = Object.fromEntries(response.headers.entries());
|
|
24
|
+
return {
|
|
25
|
+
status: assertWrap.isHttpStatus(response.status),
|
|
26
|
+
...bodyObject,
|
|
27
|
+
headers: options.includeDefaultHeaders
|
|
28
|
+
? headers
|
|
29
|
+
: omitObjectKeys(headers, [
|
|
30
|
+
/**
|
|
31
|
+
* These headers are automatically set by fastify so we don't care about
|
|
32
|
+
* inspecting them in tests.
|
|
33
|
+
*/
|
|
34
|
+
'connection',
|
|
35
|
+
'content-length',
|
|
36
|
+
'date',
|
|
37
|
+
'keep-alive',
|
|
38
|
+
restVirServiceNameHeader,
|
|
39
|
+
]),
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Test your service with actual Request and Response objects! The returned object includes
|
|
44
|
+
* utilities for sending fetch requests and WebSocket connections to the service.
|
|
45
|
+
*
|
|
46
|
+
* Make sure to use the `kill` output after your tests are finished. To automatically kill the
|
|
47
|
+
* server, use {@link describeService} instead.
|
|
48
|
+
*
|
|
49
|
+
* By default, this uses Fastify's request injection strategy to avoid using up real system ports.
|
|
50
|
+
* To instead use an actual port, set `port` in the options parameter.
|
|
51
|
+
*
|
|
52
|
+
* @category Internal
|
|
53
|
+
* @category Package : @rest-vir/run-service
|
|
54
|
+
* @example
|
|
55
|
+
*
|
|
56
|
+
* ```ts
|
|
57
|
+
* import {testService} from '@rest-vir/run-service';
|
|
58
|
+
*
|
|
59
|
+
* const {connectWebsocket, kill, fetchEndpoint} = await testService(myServiceImplementation);
|
|
60
|
+
*
|
|
61
|
+
* // run tests
|
|
62
|
+
*
|
|
63
|
+
* await kill();
|
|
64
|
+
* ```
|
|
65
|
+
*
|
|
66
|
+
* @package [`@rest-vir/run-service`](https://www.npmjs.com/package/@rest-vir/run-service)
|
|
67
|
+
*/
|
|
68
|
+
export async function testService(service, testServiceOptions = {}) {
|
|
69
|
+
const { host = 'localhost', port, debug, } = mergeDefinedProperties({
|
|
70
|
+
port: false,
|
|
71
|
+
debug: true,
|
|
72
|
+
}, testServiceOptions, {
|
|
73
|
+
workerCount: 1,
|
|
74
|
+
preventWorkerRespawn: true,
|
|
75
|
+
});
|
|
76
|
+
const server = fastify();
|
|
77
|
+
/* node:coverage ignore next 5: this is just here to cover edge cases */
|
|
78
|
+
if (debug) {
|
|
79
|
+
server.setErrorHandler((error) => {
|
|
80
|
+
log.error(ensureErrorAndPrependMessage(error, 'Fastify error handler caught:'));
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
assert.isDefined(server, 'Service server was not started.');
|
|
84
|
+
const output = {
|
|
85
|
+
...(await testExistingServer(server, service, {
|
|
86
|
+
port: port || undefined,
|
|
87
|
+
host,
|
|
88
|
+
throwErrorsForExternalHandling: false,
|
|
89
|
+
debug,
|
|
90
|
+
})),
|
|
91
|
+
/** Kill the server being tested. This should always be called after your tests are finished. */
|
|
92
|
+
async kill() {
|
|
93
|
+
await server.close();
|
|
94
|
+
},
|
|
95
|
+
};
|
|
96
|
+
if (check.isNumber(port)) {
|
|
97
|
+
await server.listen({
|
|
98
|
+
port,
|
|
99
|
+
host,
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
return output;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Similar to {@link testService} but used to test against a Fastify server that you've already
|
|
106
|
+
* started elsewhere. This will merely attach all route listeners to it and return test callbacks.
|
|
107
|
+
*
|
|
108
|
+
* The returned object includes a function to send fetches to directly to the running service.
|
|
109
|
+
*
|
|
110
|
+
* By default, this uses Fastify's request injection strategy to avoid using up real system ports.
|
|
111
|
+
* To instead listen to an actual port, set `port` in the options parameter.
|
|
112
|
+
*
|
|
113
|
+
* @category Internal
|
|
114
|
+
* @category Package : @rest-vir/run-service
|
|
115
|
+
* @package [`@rest-vir/run-service`](https://www.npmjs.com/package/@rest-vir/run-service)
|
|
116
|
+
*/
|
|
117
|
+
export async function testExistingServer(server, service, options = {}) {
|
|
118
|
+
applyDebugLogger(options.debug, service);
|
|
119
|
+
await attachService(server, service, options);
|
|
120
|
+
const fetchOrigin = options.port == undefined
|
|
121
|
+
? undefined
|
|
122
|
+
: buildUrl({
|
|
123
|
+
protocol: 'http',
|
|
124
|
+
hostname: options.host,
|
|
125
|
+
port: options.port,
|
|
126
|
+
}).origin;
|
|
127
|
+
const fetchEndpoint = mapObjectValues(service.endpoints, (endpointPath, endpoint) => {
|
|
128
|
+
return async (...args) => {
|
|
129
|
+
await server.ready();
|
|
130
|
+
const overwrittenOriginEndpoint = mergeDeep(endpoint, fetchOrigin
|
|
131
|
+
? {
|
|
132
|
+
service: {
|
|
133
|
+
serviceOrigin: fetchOrigin,
|
|
134
|
+
},
|
|
135
|
+
}
|
|
136
|
+
: {});
|
|
137
|
+
const { url, requestInit } = buildEndpointRequestInit(overwrittenOriginEndpoint, ...args);
|
|
138
|
+
const { href, fullPath } = parseUrl(url);
|
|
139
|
+
if (fetchOrigin == undefined) {
|
|
140
|
+
const withPayload = requestInit.body
|
|
141
|
+
? {
|
|
142
|
+
body: requestInit.body,
|
|
143
|
+
}
|
|
144
|
+
: {};
|
|
145
|
+
const innerResponse = await server.inject({
|
|
146
|
+
remoteAddress: href,
|
|
147
|
+
headers: requestInit.headers,
|
|
148
|
+
method: requestInit.method,
|
|
149
|
+
url: fullPath,
|
|
150
|
+
...withPayload,
|
|
151
|
+
});
|
|
152
|
+
const response = new Response(innerResponse.rawPayload, {
|
|
153
|
+
status: innerResponse.statusCode,
|
|
154
|
+
headers: innerResponse.headers,
|
|
155
|
+
statusText: innerResponse.statusMessage,
|
|
156
|
+
});
|
|
157
|
+
return response;
|
|
158
|
+
}
|
|
159
|
+
else {
|
|
160
|
+
return globalThis.fetch(href, requestInit);
|
|
161
|
+
}
|
|
162
|
+
};
|
|
163
|
+
});
|
|
164
|
+
const webSocketOrigin = options.port == undefined
|
|
165
|
+
? undefined
|
|
166
|
+
: buildUrl({
|
|
167
|
+
protocol: 'ws',
|
|
168
|
+
hostname: options.host,
|
|
169
|
+
port: options.port,
|
|
170
|
+
}).origin;
|
|
171
|
+
const connectWebSocket = mapObjectValues(service.webSockets, (webSocketPath, webSocketDefinition) => {
|
|
172
|
+
return async (...args) => {
|
|
173
|
+
await server.ready();
|
|
174
|
+
const [{ protocols = [], listeners } = {}] = args;
|
|
175
|
+
const overwrittenOriginWebSocket = mergeDeep(webSocketDefinition, webSocketOrigin
|
|
176
|
+
? {
|
|
177
|
+
service: {
|
|
178
|
+
serviceOrigin: webSocketOrigin,
|
|
179
|
+
},
|
|
180
|
+
}
|
|
181
|
+
: {});
|
|
182
|
+
const webSocketUrl = buildWebSocketUrl(overwrittenOriginWebSocket, ...args);
|
|
183
|
+
assertValidWebSocketProtocols(protocols);
|
|
184
|
+
const webSocket = webSocketOrigin == undefined
|
|
185
|
+
? (await server.injectWS(parseUrl(webSocketUrl).pathname, protocols.length
|
|
186
|
+
? {
|
|
187
|
+
headers: {
|
|
188
|
+
'sec-websocket-protocol': protocols.join(', '),
|
|
189
|
+
},
|
|
190
|
+
}
|
|
191
|
+
: {}))
|
|
192
|
+
: new WebSocket(webSocketUrl, protocols);
|
|
193
|
+
const finalized = await finalizeWebSocket(webSocketDefinition, webSocket, listeners, WebSocketLocation.OnClient);
|
|
194
|
+
return finalized;
|
|
195
|
+
};
|
|
196
|
+
});
|
|
197
|
+
return {
|
|
198
|
+
/** Send a request to the service. */
|
|
199
|
+
fetchEndpoint,
|
|
200
|
+
/** Connect to a service WebSocket. */
|
|
201
|
+
connectWebSocket,
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* Use this in conjunction with
|
|
206
|
+
* [`@augment-vir/test`](https://www.npmjs.com/package/@augment-vir/test) or the Node.js built-in
|
|
207
|
+
* test runner to run tests for a service and automatically kill the service when all tests have
|
|
208
|
+
* finished. The describe callback is passed a params object which includes a fetch function.
|
|
209
|
+
*
|
|
210
|
+
* See {@link testService} for more control over how tests are run (but without automatic server
|
|
211
|
+
* shutdown).
|
|
212
|
+
*
|
|
213
|
+
* @category Testing : Backend
|
|
214
|
+
* @category Package : @rest-vir/run-service
|
|
215
|
+
* @example
|
|
216
|
+
*
|
|
217
|
+
* ```ts
|
|
218
|
+
* import {describeService} from '@rest-vir/run-service';
|
|
219
|
+
* import {it} from '@augment-vir/test';
|
|
220
|
+
*
|
|
221
|
+
* describeService({service: myService}, ({fetchEndpoint}) => {
|
|
222
|
+
* it('responds', async () => {
|
|
223
|
+
* const response = await fetchEndpoint['/my-endpoint']();
|
|
224
|
+
* });
|
|
225
|
+
* });
|
|
226
|
+
* ```
|
|
227
|
+
*
|
|
228
|
+
* @package [`@rest-vir/run-service`](https://www.npmjs.com/package/@rest-vir/run-service)
|
|
229
|
+
*/
|
|
230
|
+
export function describeService({ service, options, }, describeCallback) {
|
|
231
|
+
const servicePromise = testService(service, options);
|
|
232
|
+
const fetchServiceObject = mapObjectValues(service.endpoints, (endpointPath) => {
|
|
233
|
+
return async (...args) => {
|
|
234
|
+
const { fetchEndpoint } = await servicePromise;
|
|
235
|
+
return await fetchEndpoint[endpointPath](...args);
|
|
236
|
+
};
|
|
237
|
+
});
|
|
238
|
+
describe(service.serviceName, () => {
|
|
239
|
+
describeCallback({
|
|
240
|
+
fetchEndpoint: fetchServiceObject,
|
|
241
|
+
});
|
|
242
|
+
/**
|
|
243
|
+
* The built-in Node.js test runner runs `it` calls sequentially so this will always be
|
|
244
|
+
* called last.
|
|
245
|
+
*/
|
|
246
|
+
it('can be killed', async () => {
|
|
247
|
+
const { kill } = await servicePromise;
|
|
248
|
+
await kill();
|
|
249
|
+
});
|
|
250
|
+
});
|
|
251
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { type MaybePromise } from '@augment-vir/common';
|
|
2
|
+
import { type ClientWebSocket, type CollapsedConnectWebSocketParams, type ConnectWebSocketParams, type WebSocketDefinition } from '@rest-vir/define-service';
|
|
3
|
+
import { type ImplementedWebSocket } from '@rest-vir/implement-service';
|
|
4
|
+
/**
|
|
5
|
+
* Type for {@link testWebSocket}.
|
|
6
|
+
*
|
|
7
|
+
* @category Internal
|
|
8
|
+
* @category Package : @rest-vir/run-service
|
|
9
|
+
* @package [`@rest-vir/run-service`](https://www.npmjs.com/package/@rest-vir/run-service)
|
|
10
|
+
*/
|
|
11
|
+
export type TestWebSocket = <WebSocketToTest extends WebSocketDefinition>(webSocketDefinition: WebSocketToTest, ...args: CollapsedConnectWebSocketParams<WebSocketToTest, false>) => Promise<ClientWebSocket<WebSocketToTest>>;
|
|
12
|
+
/**
|
|
13
|
+
* Test your WebSocket implementation with a real connection pipeline. Make sure to close your
|
|
14
|
+
* WebSocket after each test. Use {@link withWebSocketTest} to automatically close the WebSocket
|
|
15
|
+
* after a test.
|
|
16
|
+
*
|
|
17
|
+
* @category Internal
|
|
18
|
+
* @category Package : @rest-vir/run-service
|
|
19
|
+
* @package [`@rest-vir/run-service`](https://www.npmjs.com/package/@rest-vir/run-service)
|
|
20
|
+
*/
|
|
21
|
+
export declare const testWebSocket: TestWebSocket;
|
|
22
|
+
/**
|
|
23
|
+
* Callback type for {@link withWebSocketTest}.
|
|
24
|
+
*
|
|
25
|
+
* @category Internal
|
|
26
|
+
* @category Package : @rest-vir/run-service
|
|
27
|
+
* @package [`@rest-vir/run-service`](https://www.npmjs.com/package/@rest-vir/run-service)
|
|
28
|
+
*/
|
|
29
|
+
export type WithWebSocketTestCallback<WebSocketToTest extends ImplementedWebSocket> = (clientWebSocket: ClientWebSocket<WebSocketToTest>) => MaybePromise<void>;
|
|
30
|
+
/**
|
|
31
|
+
* Test your WebSocket implementation with a real connection pipeline. This is used to generate an
|
|
32
|
+
* `it` callback and will automatically close the WebSocket connection at the end of the test.
|
|
33
|
+
*
|
|
34
|
+
* You can also use {@link testWebSocket} to directly test a WebSocket but it does not automatically
|
|
35
|
+
* close the WebSocket.
|
|
36
|
+
*
|
|
37
|
+
* This should be used in backend testing to verify your WebSocket implementation.
|
|
38
|
+
*
|
|
39
|
+
* @category Testing : Backend
|
|
40
|
+
* @category Package : @rest-vir/run-service
|
|
41
|
+
* @example
|
|
42
|
+
*
|
|
43
|
+
* ```ts
|
|
44
|
+
* import {withWebSocketTest} from '@rest-vir/run-service';
|
|
45
|
+
* import {describe, it} from '@augment-vir/test'; // or use mocha, jest, etc. values
|
|
46
|
+
*
|
|
47
|
+
* describe('my WebSocket', () => {
|
|
48
|
+
* it(
|
|
49
|
+
* 'does a thing',
|
|
50
|
+
* withWebSocketTest(
|
|
51
|
+
* myServiceImplementation.webSockets['/my-web-socket-path'],
|
|
52
|
+
* {},
|
|
53
|
+
* (webSocket) => {
|
|
54
|
+
* const response = await webSocket.sendAndWaitForReply();
|
|
55
|
+
* assert.strictEquals(response, 'ok');
|
|
56
|
+
* },
|
|
57
|
+
* ),
|
|
58
|
+
* );
|
|
59
|
+
* });
|
|
60
|
+
* ```
|
|
61
|
+
*
|
|
62
|
+
* @package [`@rest-vir/run-service`](https://www.npmjs.com/package/@rest-vir/run-service)
|
|
63
|
+
*/
|
|
64
|
+
export declare function withWebSocketTest<const WebSocketToTest extends ImplementedWebSocket>(webSocketDefinition: WebSocketToTest, params: Omit<ConnectWebSocketParams<WebSocketToTest, false>, 'listeners'>, callback: WithWebSocketTestCallback<WebSocketToTest>): () => Promise<void>;
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { testService } from './test-service.js';
|
|
2
|
+
/**
|
|
3
|
+
* Test your WebSocket implementation with a real connection pipeline. Make sure to close your
|
|
4
|
+
* WebSocket after each test. Use {@link withWebSocketTest} to automatically close the WebSocket
|
|
5
|
+
* after a test.
|
|
6
|
+
*
|
|
7
|
+
* @category Internal
|
|
8
|
+
* @category Package : @rest-vir/run-service
|
|
9
|
+
* @package [`@rest-vir/run-service`](https://www.npmjs.com/package/@rest-vir/run-service)
|
|
10
|
+
*/
|
|
11
|
+
export const testWebSocket = async function testWebSocket(webSocketImplementation, params) {
|
|
12
|
+
const { connectWebSocket, kill } = await testService({
|
|
13
|
+
...webSocketImplementation.service,
|
|
14
|
+
webSockets: {
|
|
15
|
+
[webSocketImplementation.path]: webSocketImplementation,
|
|
16
|
+
},
|
|
17
|
+
endpoints: {},
|
|
18
|
+
}, {
|
|
19
|
+
debug: true,
|
|
20
|
+
});
|
|
21
|
+
const webSocket = await connectWebSocket[webSocketImplementation.path](params);
|
|
22
|
+
webSocket.addEventListener('close', async () => {
|
|
23
|
+
await kill();
|
|
24
|
+
});
|
|
25
|
+
return webSocket;
|
|
26
|
+
};
|
|
27
|
+
/**
|
|
28
|
+
* Test your WebSocket implementation with a real connection pipeline. This is used to generate an
|
|
29
|
+
* `it` callback and will automatically close the WebSocket connection at the end of the test.
|
|
30
|
+
*
|
|
31
|
+
* You can also use {@link testWebSocket} to directly test a WebSocket but it does not automatically
|
|
32
|
+
* close the WebSocket.
|
|
33
|
+
*
|
|
34
|
+
* This should be used in backend testing to verify your WebSocket implementation.
|
|
35
|
+
*
|
|
36
|
+
* @category Testing : Backend
|
|
37
|
+
* @category Package : @rest-vir/run-service
|
|
38
|
+
* @example
|
|
39
|
+
*
|
|
40
|
+
* ```ts
|
|
41
|
+
* import {withWebSocketTest} from '@rest-vir/run-service';
|
|
42
|
+
* import {describe, it} from '@augment-vir/test'; // or use mocha, jest, etc. values
|
|
43
|
+
*
|
|
44
|
+
* describe('my WebSocket', () => {
|
|
45
|
+
* it(
|
|
46
|
+
* 'does a thing',
|
|
47
|
+
* withWebSocketTest(
|
|
48
|
+
* myServiceImplementation.webSockets['/my-web-socket-path'],
|
|
49
|
+
* {},
|
|
50
|
+
* (webSocket) => {
|
|
51
|
+
* const response = await webSocket.sendAndWaitForReply();
|
|
52
|
+
* assert.strictEquals(response, 'ok');
|
|
53
|
+
* },
|
|
54
|
+
* ),
|
|
55
|
+
* );
|
|
56
|
+
* });
|
|
57
|
+
* ```
|
|
58
|
+
*
|
|
59
|
+
* @package [`@rest-vir/run-service`](https://www.npmjs.com/package/@rest-vir/run-service)
|
|
60
|
+
*/
|
|
61
|
+
export function withWebSocketTest(webSocketDefinition, params, callback) {
|
|
62
|
+
return async () => {
|
|
63
|
+
const clientWebSocket = await testWebSocket(webSocketDefinition, params);
|
|
64
|
+
await callback(clientWebSocket);
|
|
65
|
+
clientWebSocket.close();
|
|
66
|
+
};
|
|
67
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rest-vir/run-service",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.4",
|
|
4
4
|
"description": "Run a service defined by @rest-vir/define-service and implemented by @rest-vir/implement-service.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"rest",
|
|
@@ -43,8 +43,8 @@
|
|
|
43
43
|
"@augment-vir/common": "^31.9.1",
|
|
44
44
|
"@augment-vir/node": "^31.9.1",
|
|
45
45
|
"@fastify/websocket": "^11.0.2",
|
|
46
|
-
"@rest-vir/define-service": "^0.0.
|
|
47
|
-
"@rest-vir/implement-service": "^0.0.
|
|
46
|
+
"@rest-vir/define-service": "^0.0.4",
|
|
47
|
+
"@rest-vir/implement-service": "^0.0.4",
|
|
48
48
|
"cluster-vir": "^0.1.0",
|
|
49
49
|
"date-vir": "^7.2.0",
|
|
50
50
|
"fastify": "^5.2.1",
|