@zudojs/testing 1.1.2 → 1.2.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 +138 -2
- package/dist/assertions/httpAssertions.core.d.ts +2 -2
- package/dist/httpTestClient/httpTestClient.cookieJar.d.ts +30 -0
- package/dist/httpTestClient/httpTestClient.cookieJar.js +107 -0
- package/dist/httpTestClient/httpTestClient.factory.d.ts +25 -0
- package/dist/httpTestClient/httpTestClient.factory.js +84 -0
- package/dist/httpTestClient/httpTestClient.target.d.ts +16 -0
- package/dist/httpTestClient/httpTestClient.target.js +80 -0
- package/dist/httpTestClient/httpTestClient.type.d.ts +74 -0
- package/dist/httpTestClient/httpTestClient.type.js +5 -0
- package/dist/httpTestClient/httpTestRequest/httpTestRequest.core.d.ts +10 -0
- package/dist/httpTestClient/httpTestRequest/httpTestRequest.core.js +97 -0
- package/dist/httpTestClient/httpTestRequest/httpTestRequest.encode.d.ts +26 -0
- package/dist/httpTestClient/httpTestRequest/httpTestRequest.encode.js +73 -0
- package/dist/httpTestClient/httpTestRequest/httpTestRequest.execute.d.ts +26 -0
- package/dist/httpTestClient/httpTestRequest/httpTestRequest.execute.js +58 -0
- package/dist/httpTestClient/httpTestRequest/httpTestRequest.type.d.ts +53 -0
- package/dist/httpTestClient/httpTestRequest/httpTestRequest.type.js +5 -0
- package/dist/httpTestClient/httpTestRequest/index.d.ts +13 -0
- package/dist/httpTestClient/httpTestRequest/index.js +10 -0
- package/dist/httpTestClient/httpTestResponse/httpTestResponse.core.d.ts +15 -0
- package/dist/httpTestClient/httpTestResponse/httpTestResponse.core.js +71 -0
- package/dist/httpTestClient/httpTestResponse/httpTestResponse.expect.d.ts +19 -0
- package/dist/httpTestClient/httpTestResponse/httpTestResponse.expect.js +74 -0
- package/dist/httpTestClient/httpTestResponse/httpTestResponse.match.d.ts +15 -0
- package/dist/httpTestClient/httpTestResponse/httpTestResponse.match.js +52 -0
- package/dist/httpTestClient/httpTestResponse/httpTestResponse.type.d.ts +44 -0
- package/dist/httpTestClient/httpTestResponse/httpTestResponse.type.js +5 -0
- package/dist/httpTestClient/httpTestResponse/index.d.ts +12 -0
- package/dist/httpTestClient/httpTestResponse/index.js +10 -0
- package/dist/httpTestClient/httpTestTransport/httpTestTransport.fetch.d.ts +15 -0
- package/dist/httpTestClient/httpTestTransport/httpTestTransport.fetch.js +65 -0
- package/dist/httpTestClient/httpTestTransport/httpTestTransport.node.d.ts +18 -0
- package/dist/httpTestClient/httpTestTransport/httpTestTransport.node.js +94 -0
- package/dist/httpTestClient/httpTestTransport/httpTestTransport.server.d.ts +23 -0
- package/dist/httpTestClient/httpTestTransport/httpTestTransport.server.js +76 -0
- package/dist/httpTestClient/httpTestTransport/httpTestTransport.type.d.ts +46 -0
- package/dist/httpTestClient/httpTestTransport/httpTestTransport.type.js +9 -0
- package/dist/httpTestClient/httpTestTransport/httpTestTransport.zudo.d.ts +25 -0
- package/dist/httpTestClient/httpTestTransport/httpTestTransport.zudo.js +71 -0
- package/dist/httpTestClient/httpTestTransport/index.d.ts +15 -0
- package/dist/httpTestClient/httpTestTransport/index.js +13 -0
- package/dist/httpTestClient/index.d.ts +18 -0
- package/dist/httpTestClient/index.js +13 -0
- package/dist/httpTesting/httpRequest/httpRequest.builder.d.ts +13 -0
- package/dist/httpTesting/httpRequest/httpRequest.builder.js +64 -0
- package/dist/httpTesting/httpRequest/httpRequest.factory.d.ts +17 -0
- package/dist/httpTesting/httpRequest/httpRequest.factory.js +25 -0
- package/dist/httpTesting/{httpRequest.core.d.ts → httpRequest/httpRequest.type.d.ts} +6 -21
- package/dist/httpTesting/httpRequest/httpRequest.type.js +5 -0
- package/dist/httpTesting/httpRequest/index.d.ts +10 -0
- package/dist/httpTesting/httpRequest/index.js +9 -0
- package/dist/httpTesting/{httpResponse.helpers.d.ts → httpResponse/httpResponse.helpers.d.ts} +1 -1
- package/dist/httpTesting/{httpResponse.type.d.ts → httpResponse/httpResponse.type.d.ts} +1 -1
- package/dist/httpTesting/httpResponse/index.d.ts +10 -0
- package/dist/httpTesting/httpResponse/index.js +9 -0
- package/dist/httpTesting/index.d.ts +6 -6
- package/dist/httpTesting/index.js +4 -4
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/mocking/spy.core.d.ts +6 -1
- package/dist/mocking/spy.core.js +1 -3
- package/dist/mocking/stub.core.d.ts +3 -1
- package/dist/mocking/stub.core.js +15 -2
- package/dist/testApplication/index.d.ts +1 -1
- package/dist/testApplication/index.js +1 -1
- package/dist/testApplication/testApplication.core.d.ts +35 -5
- package/dist/testApplication/testApplication.core.js +18 -3
- package/dist/testEventBus/index.d.ts +2 -2
- package/dist/testEventBus/index.js +1 -1
- package/dist/testEventBus/testEventBus.core.d.ts +12 -45
- package/dist/testEventBus/testEventBus.core.js +55 -46
- package/dist/testEventBus/testEventBus.type.d.ts +40 -0
- package/dist/testEventBus/testEventBus.type.js +2 -0
- package/dist/testMessageBus/index.d.ts +1 -1
- package/dist/testMessageBus/index.js +1 -1
- package/dist/testMessageBus/testMessageBus.core.d.ts +20 -24
- package/dist/testMessageBus/testMessageBus.core.js +45 -47
- package/dist/testQueue/index.d.ts +2 -2
- package/dist/testQueue/index.js +1 -1
- package/dist/testQueue/testQueue.core.d.ts +19 -38
- package/dist/testQueue/testQueue.core.js +34 -30
- package/dist/testQueue/testQueue.type.d.ts +30 -0
- package/dist/testQueue/testQueue.type.js +2 -0
- package/dist/testQueue/testQueue.view.d.ts +37 -0
- package/dist/testQueue/testQueue.view.js +44 -0
- package/dist/testStorage/testStorageMemory.core.d.ts +6 -1
- package/dist/testStorage/testStorageMemory.core.js +13 -3
- package/package.json +17 -17
- package/dist/httpTesting/httpRequest.core.js +0 -114
- package/dist/httpTesting/httpStatusCode.type.d.ts +0 -10
- package/dist/httpTesting/httpStatusCode.type.js +0 -9
- /package/dist/httpTesting/{httpResponse.core.d.ts → httpResponse/httpResponse.core.d.ts} +0 -0
- /package/dist/httpTesting/{httpResponse.core.js → httpResponse/httpResponse.core.js} +0 -0
- /package/dist/httpTesting/{httpResponse.helpers.js → httpResponse/httpResponse.helpers.js} +0 -0
- /package/dist/httpTesting/{httpResponse.type.js → httpResponse/httpResponse.type.js} +0 -0
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @zudojs/testing — one-call HTTP request factory.
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Creates a simple test HTTP request without the builder pattern.
|
|
6
|
+
*
|
|
7
|
+
* `query` and `params` are copied, so mutating the object passed in after the
|
|
8
|
+
* call does not change the request (the builder already behaved this way).
|
|
9
|
+
*
|
|
10
|
+
* @param method - HTTP method.
|
|
11
|
+
* @param path - Request path.
|
|
12
|
+
* @param options - Optional headers, query, params, and body.
|
|
13
|
+
* @returns A TestHTTPRequest instance.
|
|
14
|
+
*/
|
|
15
|
+
export function createHTTPRequest(method, path, options = {}) {
|
|
16
|
+
return {
|
|
17
|
+
method,
|
|
18
|
+
path,
|
|
19
|
+
headers: new Headers(options.headers),
|
|
20
|
+
query: { ...options.query },
|
|
21
|
+
body: options.body,
|
|
22
|
+
params: { ...options.params },
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=httpRequest.factory.js.map
|
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* HTTP request
|
|
3
|
-
*
|
|
4
|
-
* Provides a fluent API for constructing test HTTP requests.
|
|
2
|
+
* @zudojs/testing — HTTP request test double types.
|
|
5
3
|
*/
|
|
6
|
-
/** HTTP method
|
|
4
|
+
/** HTTP method accepted by the request builders and the test client. */
|
|
7
5
|
export type HTTPMethod = "GET" | "POST" | "PUT" | "PATCH" | "DELETE" | "HEAD" | "OPTIONS";
|
|
8
6
|
/**
|
|
9
7
|
* A test HTTP request.
|
|
@@ -46,24 +44,11 @@ export interface HTTPRequestBuilder {
|
|
|
46
44
|
withBody: (body: unknown) => HTTPRequestBuilder;
|
|
47
45
|
build: () => TestHTTPRequest;
|
|
48
46
|
}
|
|
49
|
-
/**
|
|
50
|
-
|
|
51
|
-
*
|
|
52
|
-
* @returns An HTTPRequestBuilder instance.
|
|
53
|
-
*/
|
|
54
|
-
export declare function createTestHTTPRequest(): HTTPRequestBuilder;
|
|
55
|
-
/**
|
|
56
|
-
* Creates a simple test HTTP request without the builder pattern.
|
|
57
|
-
*
|
|
58
|
-
* @param method - HTTP method.
|
|
59
|
-
* @param path - Request path.
|
|
60
|
-
* @param options - Optional headers, query, and body.
|
|
61
|
-
* @returns A TestHTTPRequest instance.
|
|
62
|
-
*/
|
|
63
|
-
export declare function createHTTPRequest(method: HTTPMethod, path: string, options?: {
|
|
47
|
+
/** Options accepted by `createHTTPRequest`. */
|
|
48
|
+
export interface HTTPRequestOptions {
|
|
64
49
|
readonly headers?: Headers | Record<string, string>;
|
|
65
50
|
readonly query?: Record<string, string>;
|
|
66
51
|
readonly body?: unknown;
|
|
67
52
|
readonly params?: Record<string, string>;
|
|
68
|
-
}
|
|
69
|
-
//# sourceMappingURL=httpRequest.
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=httpRequest.type.d.ts.map
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @zudojs/testing — HTTP request test doubles.
|
|
3
|
+
*
|
|
4
|
+
* A fluent request builder and a one-call factory. Built requests can be sent
|
|
5
|
+
* to a real app with `createHttpTestClient(app).request(built)`.
|
|
6
|
+
*/
|
|
7
|
+
export { createTestHTTPRequest } from "./httpRequest.builder.js";
|
|
8
|
+
export { createHTTPRequest } from "./httpRequest.factory.js";
|
|
9
|
+
export type { HTTPMethod, HTTPRequestBuilder, HTTPRequestOptions, TestHTTPRequest, } from "./httpRequest.type.js";
|
|
10
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @zudojs/testing — HTTP request test doubles.
|
|
3
|
+
*
|
|
4
|
+
* A fluent request builder and a one-call factory. Built requests can be sent
|
|
5
|
+
* to a real app with `createHttpTestClient(app).request(built)`.
|
|
6
|
+
*/
|
|
7
|
+
export { createTestHTTPRequest } from "./httpRequest.builder.js";
|
|
8
|
+
export { createHTTPRequest } from "./httpRequest.factory.js";
|
|
9
|
+
//# sourceMappingURL=index.js.map
|
package/dist/httpTesting/{httpResponse.helpers.d.ts → httpResponse/httpResponse.helpers.d.ts}
RENAMED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Convenience functions for creating common test HTTP responses.
|
|
5
5
|
*/
|
|
6
|
-
import type { HTTPStatusCode } from "
|
|
6
|
+
import type { HTTPStatusCode } from "@zudojs/http";
|
|
7
7
|
import type { TestHTTPResponse } from "./httpResponse.type.js";
|
|
8
8
|
/**
|
|
9
9
|
* Creates a simple test HTTP response without the builder pattern.
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Types for test HTTP responses and response builders.
|
|
5
5
|
*/
|
|
6
|
-
import type { HTTPStatusCode } from "
|
|
6
|
+
import type { HTTPStatusCode } from "@zudojs/http";
|
|
7
7
|
/** A test HTTP response. */
|
|
8
8
|
export interface TestHTTPResponse {
|
|
9
9
|
readonly status: HTTPStatusCode;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @zudojs/testing — HTTP response test doubles.
|
|
3
|
+
*
|
|
4
|
+
* A fluent response builder plus one-line helpers for the common responses
|
|
5
|
+
* (`jsonResponse`, `notFoundResponse`, ...).
|
|
6
|
+
*/
|
|
7
|
+
export { createTestHTTPResponse } from "./httpResponse.core.js";
|
|
8
|
+
export type { HTTPResponseBuilder, TestHTTPResponse, } from "./httpResponse.type.js";
|
|
9
|
+
export { createHTTPResponse, jsonResponse, createdResponse, noContentResponse, badRequestResponse, notFoundResponse, serverErrorResponse, } from "./httpResponse.helpers.js";
|
|
10
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @zudojs/testing — HTTP response test doubles.
|
|
3
|
+
*
|
|
4
|
+
* A fluent response builder plus one-line helpers for the common responses
|
|
5
|
+
* (`jsonResponse`, `notFoundResponse`, ...).
|
|
6
|
+
*/
|
|
7
|
+
export { createTestHTTPResponse } from "./httpResponse.core.js";
|
|
8
|
+
export { createHTTPResponse, jsonResponse, createdResponse, noContentResponse, badRequestResponse, notFoundResponse, serverErrorResponse, } from "./httpResponse.helpers.js";
|
|
9
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @zudojs/testing — HTTP testing helpers.
|
|
3
3
|
*
|
|
4
|
-
* Request and response builders for HTTP testing.
|
|
4
|
+
* Request and response builders for HTTP testing. To drive a running app,
|
|
5
|
+
* see `createHttpTestClient` in `httpTestClient/`.
|
|
5
6
|
*/
|
|
6
|
-
export { createTestHTTPRequest, createHTTPRequest, } from "./httpRequest.
|
|
7
|
-
export type { HTTPRequestBuilder, TestHTTPRequest, } from "./httpRequest.
|
|
8
|
-
export { createTestHTTPResponse } from "./httpResponse.
|
|
9
|
-
export type { HTTPResponseBuilder, TestHTTPResponse, } from "./httpResponse.
|
|
10
|
-
export { createHTTPResponse, jsonResponse, createdResponse, noContentResponse, badRequestResponse, notFoundResponse, serverErrorResponse, } from "./httpResponse.helpers.js";
|
|
7
|
+
export { createTestHTTPRequest, createHTTPRequest, } from "./httpRequest/index.js";
|
|
8
|
+
export type { HTTPRequestBuilder, TestHTTPRequest, } from "./httpRequest/index.js";
|
|
9
|
+
export { createTestHTTPResponse, createHTTPResponse, jsonResponse, createdResponse, noContentResponse, badRequestResponse, notFoundResponse, serverErrorResponse, } from "./httpResponse/index.js";
|
|
10
|
+
export type { HTTPResponseBuilder, TestHTTPResponse, } from "./httpResponse/index.js";
|
|
11
11
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @zudojs/testing — HTTP testing helpers.
|
|
3
3
|
*
|
|
4
|
-
* Request and response builders for HTTP testing.
|
|
4
|
+
* Request and response builders for HTTP testing. To drive a running app,
|
|
5
|
+
* see `createHttpTestClient` in `httpTestClient/`.
|
|
5
6
|
*/
|
|
6
|
-
export { createTestHTTPRequest, createHTTPRequest, } from "./httpRequest.
|
|
7
|
-
export { createTestHTTPResponse } from "./httpResponse.
|
|
8
|
-
export { createHTTPResponse, jsonResponse, createdResponse, noContentResponse, badRequestResponse, notFoundResponse, serverErrorResponse, } from "./httpResponse.helpers.js";
|
|
7
|
+
export { createTestHTTPRequest, createHTTPRequest, } from "./httpRequest/index.js";
|
|
8
|
+
export { createTestHTTPResponse, createHTTPResponse, jsonResponse, createdResponse, noContentResponse, badRequestResponse, notFoundResponse, serverErrorResponse, } from "./httpResponse/index.js";
|
|
9
9
|
//# sourceMappingURL=index.js.map
|
package/dist/index.d.ts
CHANGED
|
@@ -15,6 +15,7 @@ export * from "./testEventBus/index.js";
|
|
|
15
15
|
export * from "./testMessageBus/index.js";
|
|
16
16
|
export * from "./testQueue/index.js";
|
|
17
17
|
export * from "./httpTesting/index.js";
|
|
18
|
+
export * from "./httpTestClient/index.js";
|
|
18
19
|
export * from "./mocking/index.js";
|
|
19
20
|
export * from "./fixtures/index.js";
|
|
20
21
|
export * from "./assertions/index.js";
|
package/dist/index.js
CHANGED
|
@@ -15,6 +15,7 @@ export * from "./testEventBus/index.js";
|
|
|
15
15
|
export * from "./testMessageBus/index.js";
|
|
16
16
|
export * from "./testQueue/index.js";
|
|
17
17
|
export * from "./httpTesting/index.js";
|
|
18
|
+
export * from "./httpTestClient/index.js";
|
|
18
19
|
export * from "./mocking/index.js";
|
|
19
20
|
export * from "./fixtures/index.js";
|
|
20
21
|
export * from "./assertions/index.js";
|
|
@@ -49,7 +49,11 @@ export interface SpyMethod<TObj, TMethod extends keyof TObj> {
|
|
|
49
49
|
readonly results: readonly unknown[];
|
|
50
50
|
readonly errors: readonly unknown[];
|
|
51
51
|
readonly callCount: number;
|
|
52
|
-
/**
|
|
52
|
+
/**
|
|
53
|
+
* Reinstates the original method exactly as it was found. The recorded
|
|
54
|
+
* `calls`, `results` and `errors` are kept, so they can be asserted after
|
|
55
|
+
* restoring; calls made after `restore()` are not recorded.
|
|
56
|
+
*/
|
|
53
57
|
restore: () => void;
|
|
54
58
|
}
|
|
55
59
|
/**
|
|
@@ -69,6 +73,7 @@ export interface SpyMethod<TObj, TMethod extends keyof TObj> {
|
|
|
69
73
|
* expect(spy.calls).toHaveLength(1);
|
|
70
74
|
*
|
|
71
75
|
* spy.restore();
|
|
76
|
+
* expect(spy.calls).toHaveLength(1); // still recorded after restore
|
|
72
77
|
* ```
|
|
73
78
|
*/
|
|
74
79
|
export declare function createSpyMethod<TObj, TMethod extends keyof TObj>(object: TObj, property: TMethod): SpyMethod<TObj, TMethod>;
|
package/dist/mocking/spy.core.js
CHANGED
|
@@ -77,6 +77,7 @@ export function createSpyFn(fn) {
|
|
|
77
77
|
* expect(spy.calls).toHaveLength(1);
|
|
78
78
|
*
|
|
79
79
|
* spy.restore();
|
|
80
|
+
* expect(spy.calls).toHaveLength(1); // still recorded after restore
|
|
80
81
|
* ```
|
|
81
82
|
*/
|
|
82
83
|
export function createSpyMethod(object, property) {
|
|
@@ -120,9 +121,6 @@ export function createSpyMethod(object, property) {
|
|
|
120
121
|
target[key] = original;
|
|
121
122
|
else
|
|
122
123
|
delete target[key];
|
|
123
|
-
calls.length = 0;
|
|
124
|
-
results.length = 0;
|
|
125
|
-
errors.length = 0;
|
|
126
124
|
},
|
|
127
125
|
};
|
|
128
126
|
}
|
|
@@ -7,7 +7,9 @@
|
|
|
7
7
|
* Creates a stub object from an interface.
|
|
8
8
|
*
|
|
9
9
|
* All methods return undefined by default. Override specific methods
|
|
10
|
-
* by passing an overrides object.
|
|
10
|
+
* by passing an overrides object. The overrides are the stub's own
|
|
11
|
+
* enumerable properties, so `Object.keys(stub)`, `{ ...stub }` and
|
|
12
|
+
* `expect.objectContaining` see them; unstubbed no-ops are not own keys.
|
|
11
13
|
*
|
|
12
14
|
* @typeParam T - The interface type to stub.
|
|
13
15
|
* @param overrides - Optional method implementations.
|
|
@@ -8,12 +8,14 @@
|
|
|
8
8
|
*
|
|
9
9
|
* `then` is the important one: answering it makes the stub a thenable, so
|
|
10
10
|
* `await stub` calls it expecting a promise callback. The fake never resolves,
|
|
11
|
-
* and the test hangs until it times out with no indication why.
|
|
11
|
+
* and the test hangs until it times out with no indication why. Likewise
|
|
12
|
+
* `asymmetricMatch` makes Vitest's `equals` treat the stub as a matcher.
|
|
12
13
|
*/
|
|
13
14
|
const NON_CALLABLE_KEYS = new Set([
|
|
14
15
|
"then",
|
|
15
16
|
"catch",
|
|
16
17
|
"finally",
|
|
18
|
+
"asymmetricMatch",
|
|
17
19
|
Symbol.toPrimitive,
|
|
18
20
|
Symbol.iterator,
|
|
19
21
|
Symbol.asyncIterator,
|
|
@@ -23,7 +25,9 @@ const NON_CALLABLE_KEYS = new Set([
|
|
|
23
25
|
* Creates a stub object from an interface.
|
|
24
26
|
*
|
|
25
27
|
* All methods return undefined by default. Override specific methods
|
|
26
|
-
* by passing an overrides object.
|
|
28
|
+
* by passing an overrides object. The overrides are the stub's own
|
|
29
|
+
* enumerable properties, so `Object.keys(stub)`, `{ ...stub }` and
|
|
30
|
+
* `expect.objectContaining` see them; unstubbed no-ops are not own keys.
|
|
27
31
|
*
|
|
28
32
|
* @typeParam T - The interface type to stub.
|
|
29
33
|
* @param overrides - Optional method implementations.
|
|
@@ -69,6 +73,15 @@ export function createStub(overrides = {}) {
|
|
|
69
73
|
has(_target, prop) {
|
|
70
74
|
return !NON_CALLABLE_KEYS.has(prop);
|
|
71
75
|
},
|
|
76
|
+
ownKeys() {
|
|
77
|
+
return Reflect.ownKeys(overrides);
|
|
78
|
+
},
|
|
79
|
+
getOwnPropertyDescriptor(_target, prop) {
|
|
80
|
+
const descriptor = Reflect.getOwnPropertyDescriptor(overrides, prop);
|
|
81
|
+
return descriptor === undefined
|
|
82
|
+
? undefined
|
|
83
|
+
: { ...descriptor, configurable: true };
|
|
84
|
+
},
|
|
72
85
|
});
|
|
73
86
|
}
|
|
74
87
|
/**
|
|
@@ -3,6 +3,6 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Simplified test application context creation.
|
|
5
5
|
*/
|
|
6
|
-
export { createTestApplication } from "./testApplication.core.js";
|
|
6
|
+
export { createTestApplication, DEFAULT_TEST_APPLICATION_TIME, } from "./testApplication.core.js";
|
|
7
7
|
export type { TestApplication, TestApplicationOptions, } from "./testApplication.core.js";
|
|
8
8
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -6,25 +6,47 @@
|
|
|
6
6
|
*/
|
|
7
7
|
import type { Container } from "@zudojs/container";
|
|
8
8
|
import type { Logger } from "@zudojs/logger";
|
|
9
|
+
import type { SpyLogger } from "../spyLogger/spyLogger.type.js";
|
|
9
10
|
import type { CleanupManager } from "../cleanupManager/cleanupManager.core.js";
|
|
10
11
|
import type { TestClock } from "../testClock/testClock.core.js";
|
|
12
|
+
/**
|
|
13
|
+
* The instant a test application's default clock starts at:
|
|
14
|
+
* 2026-01-01T00:00:00.000Z. Fixed, so a test that reads `app.clock.now`
|
|
15
|
+
* gets the same answer on every run.
|
|
16
|
+
*/
|
|
17
|
+
export declare const DEFAULT_TEST_APPLICATION_TIME: number;
|
|
11
18
|
/**
|
|
12
19
|
* Options for creating a test application.
|
|
13
20
|
*/
|
|
14
|
-
export interface TestApplicationOptions {
|
|
21
|
+
export interface TestApplicationOptions<TLogger extends Logger = Logger> {
|
|
15
22
|
readonly name?: string;
|
|
16
23
|
readonly container?: Container;
|
|
17
|
-
|
|
24
|
+
/**
|
|
25
|
+
* The application's logger. Defaults to a silent `createSpyLogger(name)`
|
|
26
|
+
* that records every line in `app.logger.calls`. Pass a real logger
|
|
27
|
+
* (`createLogger({ name })` from `@zudojs/logger`) to print instead.
|
|
28
|
+
*/
|
|
29
|
+
readonly logger?: TLogger;
|
|
30
|
+
/**
|
|
31
|
+
* The application's clock. Defaults to a test clock pinned at
|
|
32
|
+
* `startTime`.
|
|
33
|
+
*/
|
|
18
34
|
readonly clock?: TestClock;
|
|
35
|
+
/**
|
|
36
|
+
* Where the default clock starts. Defaults to
|
|
37
|
+
* {@link DEFAULT_TEST_APPLICATION_TIME}; pass `Date.now()` to start at
|
|
38
|
+
* the wall-clock time. Ignored when `clock` is given.
|
|
39
|
+
*/
|
|
40
|
+
readonly startTime?: Date | string | number;
|
|
19
41
|
readonly cleanup?: CleanupManager;
|
|
20
42
|
}
|
|
21
43
|
/**
|
|
22
44
|
* A test application context.
|
|
23
45
|
*/
|
|
24
|
-
export interface TestApplication {
|
|
46
|
+
export interface TestApplication<TLogger extends Logger = Logger> {
|
|
25
47
|
readonly name: string;
|
|
26
48
|
readonly container: Container;
|
|
27
|
-
readonly logger:
|
|
49
|
+
readonly logger: TLogger;
|
|
28
50
|
readonly clock: TestClock;
|
|
29
51
|
readonly cleanup: CleanupManager;
|
|
30
52
|
dispose: () => Promise<void>;
|
|
@@ -32,6 +54,11 @@ export interface TestApplication {
|
|
|
32
54
|
/**
|
|
33
55
|
* Creates a test application context.
|
|
34
56
|
*
|
|
57
|
+
* Deterministic and quiet by default: the logger is a recording
|
|
58
|
+
* `SpyLogger` that prints nothing, and the clock is a test clock pinned at
|
|
59
|
+
* {@link DEFAULT_TEST_APPLICATION_TIME}. Pass `logger` or `clock` (or
|
|
60
|
+
* `startTime`) to use something else.
|
|
61
|
+
*
|
|
35
62
|
* @param options - Test application options.
|
|
36
63
|
* @returns A TestApplication instance.
|
|
37
64
|
*
|
|
@@ -42,8 +69,11 @@ export interface TestApplication {
|
|
|
42
69
|
* app.container.registerValue(token, implementation);
|
|
43
70
|
* const service = app.container.resolve(token);
|
|
44
71
|
*
|
|
72
|
+
* app.logger.calls; // what the code under test logged
|
|
73
|
+
* app.clock.now.toISOString(); // "2026-01-01T00:00:00.000Z"
|
|
74
|
+
*
|
|
45
75
|
* await app.dispose();
|
|
46
76
|
* ```
|
|
47
77
|
*/
|
|
48
|
-
export declare function createTestApplication(options?: TestApplicationOptions): TestApplication
|
|
78
|
+
export declare function createTestApplication<TLogger extends Logger = SpyLogger>(options?: TestApplicationOptions<TLogger>): TestApplication<TLogger>;
|
|
49
79
|
//# sourceMappingURL=testApplication.core.d.ts.map
|
|
@@ -5,12 +5,23 @@
|
|
|
5
5
|
* contexts without the full Runtime lifecycle.
|
|
6
6
|
*/
|
|
7
7
|
import { createStartedContainer } from "@zudojs/container";
|
|
8
|
-
import { createLogger } from "@zudojs/logger";
|
|
9
8
|
import { createCleanupManager } from "../cleanupManager/cleanupManager.core.js";
|
|
10
9
|
import { createTestClock } from "../testClock/testClock.core.js";
|
|
10
|
+
import { createSpyLogger } from "../spyLogger/spyLogger.core.js";
|
|
11
|
+
/**
|
|
12
|
+
* The instant a test application's default clock starts at:
|
|
13
|
+
* 2026-01-01T00:00:00.000Z. Fixed, so a test that reads `app.clock.now`
|
|
14
|
+
* gets the same answer on every run.
|
|
15
|
+
*/
|
|
16
|
+
export const DEFAULT_TEST_APPLICATION_TIME = Date.UTC(2026, 0, 1);
|
|
11
17
|
/**
|
|
12
18
|
* Creates a test application context.
|
|
13
19
|
*
|
|
20
|
+
* Deterministic and quiet by default: the logger is a recording
|
|
21
|
+
* `SpyLogger` that prints nothing, and the clock is a test clock pinned at
|
|
22
|
+
* {@link DEFAULT_TEST_APPLICATION_TIME}. Pass `logger` or `clock` (or
|
|
23
|
+
* `startTime`) to use something else.
|
|
24
|
+
*
|
|
14
25
|
* @param options - Test application options.
|
|
15
26
|
* @returns A TestApplication instance.
|
|
16
27
|
*
|
|
@@ -21,14 +32,18 @@ import { createTestClock } from "../testClock/testClock.core.js";
|
|
|
21
32
|
* app.container.registerValue(token, implementation);
|
|
22
33
|
* const service = app.container.resolve(token);
|
|
23
34
|
*
|
|
35
|
+
* app.logger.calls; // what the code under test logged
|
|
36
|
+
* app.clock.now.toISOString(); // "2026-01-01T00:00:00.000Z"
|
|
37
|
+
*
|
|
24
38
|
* await app.dispose();
|
|
25
39
|
* ```
|
|
26
40
|
*/
|
|
27
41
|
export function createTestApplication(options = {}) {
|
|
28
42
|
const name = options.name ?? "test-app";
|
|
29
43
|
const container = options.container ?? createStartedContainer();
|
|
30
|
-
const logger = options.logger ??
|
|
31
|
-
const clock = options.clock ??
|
|
44
|
+
const logger = options.logger ?? createSpyLogger(name);
|
|
45
|
+
const clock = options.clock ??
|
|
46
|
+
createTestClock(options.startTime ?? DEFAULT_TEST_APPLICATION_TIME);
|
|
32
47
|
const cleanup = options.cleanup ?? createCleanupManager();
|
|
33
48
|
// Cleanups run in reverse registration order, so the logger is registered
|
|
34
49
|
// first and therefore closed last: anything that logs while the container
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Test event bus helpers.
|
|
3
3
|
*
|
|
4
|
-
* EventBus
|
|
4
|
+
* A real EventBus that records every publication.
|
|
5
5
|
*/
|
|
6
6
|
export { createTestEventBus } from "./testEventBus.core.js";
|
|
7
|
-
export type { RecordedEvent, TestEventBus } from "./testEventBus.
|
|
7
|
+
export type { RecordedEvent, TestEventBus } from "./testEventBus.type.js";
|
|
8
8
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1,60 +1,27 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Test event bus helpers.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
4
|
+
* A real EventBus that records every publication, whichever method it
|
|
5
|
+
* came through.
|
|
5
6
|
*/
|
|
6
|
-
import {
|
|
7
|
-
import type {
|
|
7
|
+
import type { EventBusOptions } from "@zudojs/events";
|
|
8
|
+
import type { TestEventBus } from "./testEventBus.type.js";
|
|
9
|
+
export type { RecordedEvent, TestEventBus } from "./testEventBus.type.js";
|
|
8
10
|
/**
|
|
9
|
-
*
|
|
10
|
-
*/
|
|
11
|
-
export interface RecordedEvent<TPayload = unknown> {
|
|
12
|
-
readonly event: Event<TPayload>;
|
|
13
|
-
readonly result: EventPublishResult<Event<TPayload>>;
|
|
14
|
-
readonly timestamp: Date;
|
|
15
|
-
}
|
|
16
|
-
/**
|
|
17
|
-
* A test event bus with recording capabilities.
|
|
18
|
-
*/
|
|
19
|
-
export interface TestEventBus {
|
|
20
|
-
readonly bus: EventBus;
|
|
21
|
-
/**
|
|
22
|
-
* All recorded publications.
|
|
23
|
-
*/
|
|
24
|
-
readonly published: readonly RecordedEvent[];
|
|
25
|
-
/**
|
|
26
|
-
* Publish an event and record the result.
|
|
27
|
-
*/
|
|
28
|
-
publish: <TPayload>(input: EventInput<TPayload>) => Promise<EventPublishResult<Event<TPayload>>>;
|
|
29
|
-
/**
|
|
30
|
-
* Find published events by type.
|
|
31
|
-
*/
|
|
32
|
-
findByType: (type: string) => readonly RecordedEvent[];
|
|
33
|
-
/**
|
|
34
|
-
* Clear recorded publications.
|
|
35
|
-
*/
|
|
36
|
-
clear: () => void;
|
|
37
|
-
/**
|
|
38
|
-
* Dispose the event bus.
|
|
39
|
-
*/
|
|
40
|
-
dispose: () => void;
|
|
41
|
-
}
|
|
42
|
-
/**
|
|
43
|
-
* Creates a test event bus with recording.
|
|
11
|
+
* Creates a started test event bus that records every publication.
|
|
44
12
|
*
|
|
45
13
|
* @param options - EventBus options.
|
|
46
|
-
* @returns A TestEventBus
|
|
14
|
+
* @returns A TestEventBus, which is itself an `EventBus`.
|
|
47
15
|
*
|
|
48
16
|
* @example
|
|
49
17
|
* ```ts
|
|
50
|
-
* const
|
|
51
|
-
*
|
|
52
|
-
* await testBus.publish({ type: "user.created", payload: { id: "123" } });
|
|
18
|
+
* const events = createTestEventBus();
|
|
19
|
+
* const service = new UserService(events); // takes an EventBus
|
|
53
20
|
*
|
|
54
|
-
*
|
|
55
|
-
* expect(testBus.findByType("user.created")).toHaveLength(1);
|
|
21
|
+
* await service.register("ann"); // calls events.publishEvent(...)
|
|
56
22
|
*
|
|
57
|
-
*
|
|
23
|
+
* expect(events.findByType("user.created")).toHaveLength(1);
|
|
24
|
+
* events.dispose();
|
|
58
25
|
* ```
|
|
59
26
|
*/
|
|
60
27
|
export declare function createTestEventBus(options?: EventBusOptions): TestEventBus;
|
|
@@ -1,64 +1,73 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Test event bus helpers.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
4
|
+
* A real EventBus that records every publication, whichever method it
|
|
5
|
+
* came through.
|
|
5
6
|
*/
|
|
6
|
-
import { EventBus } from "@zudojs/events";
|
|
7
|
-
import { randomUUID } from "node:crypto";
|
|
7
|
+
import { EventBus, isEvent } from "@zudojs/events";
|
|
8
8
|
/**
|
|
9
|
-
*
|
|
9
|
+
* EventBus subclass that records at the publish entry points every other
|
|
10
|
+
* path (`emit`, a bus handed to code under test) funnels into.
|
|
11
|
+
*/
|
|
12
|
+
class RecordingEventBus extends EventBus {
|
|
13
|
+
recorded = [];
|
|
14
|
+
constructor(options) {
|
|
15
|
+
super(options);
|
|
16
|
+
// Bound, so `const { publish, clear } = createTestEventBus()` keeps
|
|
17
|
+
// working as it did with the earlier closure-based wrapper.
|
|
18
|
+
this.publish = this.publish.bind(this);
|
|
19
|
+
this.publishEvent = this.publishEvent.bind(this);
|
|
20
|
+
this.emit = this.emit.bind(this);
|
|
21
|
+
this.findByType = this.findByType.bind(this);
|
|
22
|
+
this.clear = this.clear.bind(this);
|
|
23
|
+
this.dispose = this.dispose.bind(this);
|
|
24
|
+
}
|
|
25
|
+
get bus() {
|
|
26
|
+
return this;
|
|
27
|
+
}
|
|
28
|
+
get published() {
|
|
29
|
+
return [...this.recorded];
|
|
30
|
+
}
|
|
31
|
+
async publish(input, options = {}) {
|
|
32
|
+
const result = isEvent(input)
|
|
33
|
+
? await super.publish(input, options)
|
|
34
|
+
: await super.publishEvent(input, options);
|
|
35
|
+
return this.record(result);
|
|
36
|
+
}
|
|
37
|
+
async publishEvent(input, options = {}) {
|
|
38
|
+
return this.record(await super.publishEvent(input, options));
|
|
39
|
+
}
|
|
40
|
+
findByType(type) {
|
|
41
|
+
return this.recorded.filter((entry) => entry.event.type === type);
|
|
42
|
+
}
|
|
43
|
+
clear() {
|
|
44
|
+
this.recorded.length = 0;
|
|
45
|
+
}
|
|
46
|
+
record(result) {
|
|
47
|
+
this.recorded.push(Object.freeze({ event: result.event, result, timestamp: new Date() }));
|
|
48
|
+
return result;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Creates a started test event bus that records every publication.
|
|
10
53
|
*
|
|
11
54
|
* @param options - EventBus options.
|
|
12
|
-
* @returns A TestEventBus
|
|
55
|
+
* @returns A TestEventBus, which is itself an `EventBus`.
|
|
13
56
|
*
|
|
14
57
|
* @example
|
|
15
58
|
* ```ts
|
|
16
|
-
* const
|
|
17
|
-
*
|
|
18
|
-
* await testBus.publish({ type: "user.created", payload: { id: "123" } });
|
|
59
|
+
* const events = createTestEventBus();
|
|
60
|
+
* const service = new UserService(events); // takes an EventBus
|
|
19
61
|
*
|
|
20
|
-
*
|
|
21
|
-
* expect(testBus.findByType("user.created")).toHaveLength(1);
|
|
62
|
+
* await service.register("ann"); // calls events.publishEvent(...)
|
|
22
63
|
*
|
|
23
|
-
*
|
|
64
|
+
* expect(events.findByType("user.created")).toHaveLength(1);
|
|
65
|
+
* events.dispose();
|
|
24
66
|
* ```
|
|
25
67
|
*/
|
|
26
68
|
export function createTestEventBus(options = {}) {
|
|
27
|
-
const bus = new
|
|
28
|
-
const published = [];
|
|
69
|
+
const bus = new RecordingEventBus(options);
|
|
29
70
|
bus.start();
|
|
30
|
-
|
|
31
|
-
const event = {
|
|
32
|
-
id: `evt_${randomUUID()}`,
|
|
33
|
-
type: input.type,
|
|
34
|
-
payload: input.payload,
|
|
35
|
-
timestamp: new Date(),
|
|
36
|
-
...(input.metadata ? { metadata: input.metadata } : {}),
|
|
37
|
-
};
|
|
38
|
-
const result = await bus.publish(event);
|
|
39
|
-
published.push({
|
|
40
|
-
event: result.event,
|
|
41
|
-
result,
|
|
42
|
-
timestamp: new Date(),
|
|
43
|
-
});
|
|
44
|
-
return result;
|
|
45
|
-
};
|
|
46
|
-
const findByType = (type) => published.filter((e) => e.event.type === type);
|
|
47
|
-
const clear = () => {
|
|
48
|
-
published.length = 0;
|
|
49
|
-
};
|
|
50
|
-
const dispose = () => {
|
|
51
|
-
bus.dispose();
|
|
52
|
-
};
|
|
53
|
-
return {
|
|
54
|
-
bus,
|
|
55
|
-
get published() {
|
|
56
|
-
return [...published];
|
|
57
|
-
},
|
|
58
|
-
publish,
|
|
59
|
-
findByType,
|
|
60
|
-
clear,
|
|
61
|
-
dispose,
|
|
62
|
-
};
|
|
71
|
+
return bus;
|
|
63
72
|
}
|
|
64
73
|
//# sourceMappingURL=testEventBus.core.js.map
|