@faremeter/test-harness 0.16.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +165 -0
- package/README.md +41 -0
- package/dist/src/choosers.d.ts +12 -0
- package/dist/src/choosers.d.ts.map +1 -0
- package/dist/src/choosers.js +79 -0
- package/dist/src/harness/config.d.ts +38 -0
- package/dist/src/harness/config.d.ts.map +1 -0
- package/dist/src/harness/config.js +1 -0
- package/dist/src/harness/defaults.d.ts +8 -0
- package/dist/src/harness/defaults.d.ts.map +1 -0
- package/dist/src/harness/defaults.js +20 -0
- package/dist/src/harness/harness.d.ts +70 -0
- package/dist/src/harness/harness.d.ts.map +1 -0
- package/dist/src/harness/harness.js +205 -0
- package/dist/src/harness/harness.test.d.ts +3 -0
- package/dist/src/harness/harness.test.d.ts.map +1 -0
- package/dist/src/harness/harness.test.js +230 -0
- package/dist/src/harness/resource.d.ts +17 -0
- package/dist/src/harness/resource.d.ts.map +1 -0
- package/dist/src/harness/resource.js +8 -0
- package/dist/src/index.d.ts +23 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +17 -0
- package/dist/src/interceptors/delay.d.ts +5 -0
- package/dist/src/interceptors/delay.d.ts.map +1 -0
- package/dist/src/interceptors/delay.js +30 -0
- package/dist/src/interceptors/failures.d.ts +12 -0
- package/dist/src/interceptors/failures.d.ts.map +1 -0
- package/dist/src/interceptors/failures.js +62 -0
- package/dist/src/interceptors/hooks.d.ts +20 -0
- package/dist/src/interceptors/hooks.d.ts.map +1 -0
- package/dist/src/interceptors/hooks.js +56 -0
- package/dist/src/interceptors/logging.d.ts +20 -0
- package/dist/src/interceptors/logging.d.ts.map +1 -0
- package/dist/src/interceptors/logging.js +57 -0
- package/dist/src/interceptors/matchers.d.ts +15 -0
- package/dist/src/interceptors/matchers.d.ts.map +1 -0
- package/dist/src/interceptors/matchers.js +30 -0
- package/dist/src/interceptors/responses.d.ts +11 -0
- package/dist/src/interceptors/responses.d.ts.map +1 -0
- package/dist/src/interceptors/responses.js +47 -0
- package/dist/src/interceptors/types.d.ts +20 -0
- package/dist/src/interceptors/types.d.ts.map +1 -0
- package/dist/src/interceptors/types.js +19 -0
- package/dist/src/interceptors/utils.d.ts +2 -0
- package/dist/src/interceptors/utils.d.ts.map +1 -0
- package/dist/src/interceptors/utils.js +9 -0
- package/dist/src/scheme/client.d.ts +16 -0
- package/dist/src/scheme/client.d.ts.map +1 -0
- package/dist/src/scheme/client.js +38 -0
- package/dist/src/scheme/constants.d.ts +4 -0
- package/dist/src/scheme/constants.d.ts.map +1 -0
- package/dist/src/scheme/constants.js +3 -0
- package/dist/src/scheme/facilitator.d.ts +16 -0
- package/dist/src/scheme/facilitator.d.ts.map +1 -0
- package/dist/src/scheme/facilitator.js +121 -0
- package/dist/src/scheme/types.d.ts +8 -0
- package/dist/src/scheme/types.d.ts.map +1 -0
- package/dist/src/scheme/types.js +3 -0
- package/dist/src/testing/console.d.ts +9 -0
- package/dist/src/testing/console.d.ts.map +1 -0
- package/dist/src/testing/console.js +15 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/package.json +51 -0
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
#!/usr/bin/env pnpm tsx
|
|
2
|
+
import t from "tap";
|
|
3
|
+
import { TestHarness } from "./harness.js";
|
|
4
|
+
import { createTestFacilitatorHandler } from "../scheme/facilitator.js";
|
|
5
|
+
import { createTestPaymentHandler } from "../scheme/client.js";
|
|
6
|
+
import { TEST_SCHEME, TEST_NETWORK } from "../scheme/constants.js";
|
|
7
|
+
import { matchFacilitatorSettle, matchFacilitatorVerify, } from "../interceptors/matchers.js";
|
|
8
|
+
import { getURLFromRequestInfo } from "../interceptors/utils.js";
|
|
9
|
+
await t.test("interceptor composition", async (t) => {
|
|
10
|
+
await t.test("multiple middleware interceptors execute in order", async (t) => {
|
|
11
|
+
const executionOrder = [];
|
|
12
|
+
const harness = new TestHarness({
|
|
13
|
+
settleMode: "verify-then-settle",
|
|
14
|
+
accepts: [
|
|
15
|
+
{
|
|
16
|
+
scheme: TEST_SCHEME,
|
|
17
|
+
network: TEST_NETWORK,
|
|
18
|
+
maxAmountRequired: "100",
|
|
19
|
+
resource: "http://example.com/test",
|
|
20
|
+
description: "Test resource",
|
|
21
|
+
mimeType: "application/json",
|
|
22
|
+
payTo: "test-receiver",
|
|
23
|
+
maxTimeoutSeconds: 30,
|
|
24
|
+
asset: "",
|
|
25
|
+
},
|
|
26
|
+
],
|
|
27
|
+
facilitatorHandlers: [
|
|
28
|
+
createTestFacilitatorHandler({ payTo: "test-receiver" }),
|
|
29
|
+
],
|
|
30
|
+
clientHandlers: [createTestPaymentHandler()],
|
|
31
|
+
middlewareInterceptors: [
|
|
32
|
+
(fetch) => async (input, init) => {
|
|
33
|
+
executionOrder.push("interceptor-1-before");
|
|
34
|
+
const result = await fetch(input, init);
|
|
35
|
+
executionOrder.push("interceptor-1-after");
|
|
36
|
+
return result;
|
|
37
|
+
},
|
|
38
|
+
(fetch) => async (input, init) => {
|
|
39
|
+
executionOrder.push("interceptor-2-before");
|
|
40
|
+
const result = await fetch(input, init);
|
|
41
|
+
executionOrder.push("interceptor-2-after");
|
|
42
|
+
return result;
|
|
43
|
+
},
|
|
44
|
+
(fetch) => async (input, init) => {
|
|
45
|
+
executionOrder.push("interceptor-3-before");
|
|
46
|
+
const result = await fetch(input, init);
|
|
47
|
+
executionOrder.push("interceptor-3-after");
|
|
48
|
+
return result;
|
|
49
|
+
},
|
|
50
|
+
],
|
|
51
|
+
});
|
|
52
|
+
const fetch = harness.createFetch();
|
|
53
|
+
const response = await fetch("/test-resource");
|
|
54
|
+
t.equal(response.status, 200, "should complete successfully");
|
|
55
|
+
t.ok(executionOrder.length > 0, "interceptors should have executed");
|
|
56
|
+
// Verify proper nesting: 1-before, 2-before, 3-before, 3-after, 2-after, 1-after
|
|
57
|
+
const firstBefore = executionOrder.indexOf("interceptor-1-before");
|
|
58
|
+
const secondBefore = executionOrder.indexOf("interceptor-2-before");
|
|
59
|
+
const thirdBefore = executionOrder.indexOf("interceptor-3-before");
|
|
60
|
+
const thirdAfter = executionOrder.lastIndexOf("interceptor-3-after");
|
|
61
|
+
const secondAfter = executionOrder.lastIndexOf("interceptor-2-after");
|
|
62
|
+
const firstAfter = executionOrder.lastIndexOf("interceptor-1-after");
|
|
63
|
+
t.ok(firstBefore < secondBefore, "first interceptor before should execute first");
|
|
64
|
+
t.ok(secondBefore < thirdBefore, "second interceptor before should execute second");
|
|
65
|
+
t.ok(thirdAfter < secondAfter, "third interceptor after should execute before second after");
|
|
66
|
+
t.ok(secondAfter < firstAfter, "second interceptor after should execute before first after");
|
|
67
|
+
t.end();
|
|
68
|
+
});
|
|
69
|
+
await t.test("client and middleware interceptors are separate", async (t) => {
|
|
70
|
+
let clientInterceptorCalled = false;
|
|
71
|
+
let middlewareInterceptorCalled = false;
|
|
72
|
+
const harness = new TestHarness({
|
|
73
|
+
accepts: [
|
|
74
|
+
{
|
|
75
|
+
scheme: TEST_SCHEME,
|
|
76
|
+
network: TEST_NETWORK,
|
|
77
|
+
maxAmountRequired: "100",
|
|
78
|
+
resource: "http://example.com/test",
|
|
79
|
+
description: "Test resource",
|
|
80
|
+
mimeType: "application/json",
|
|
81
|
+
payTo: "test-receiver",
|
|
82
|
+
maxTimeoutSeconds: 30,
|
|
83
|
+
asset: "",
|
|
84
|
+
},
|
|
85
|
+
],
|
|
86
|
+
facilitatorHandlers: [
|
|
87
|
+
createTestFacilitatorHandler({ payTo: "test-receiver" }),
|
|
88
|
+
],
|
|
89
|
+
clientHandlers: [createTestPaymentHandler()],
|
|
90
|
+
clientInterceptors: [
|
|
91
|
+
(fetch) => async (input, init) => {
|
|
92
|
+
clientInterceptorCalled = true;
|
|
93
|
+
return fetch(input, init);
|
|
94
|
+
},
|
|
95
|
+
],
|
|
96
|
+
middlewareInterceptors: [
|
|
97
|
+
(fetch) => async (input, init) => {
|
|
98
|
+
middlewareInterceptorCalled = true;
|
|
99
|
+
return fetch(input, init);
|
|
100
|
+
},
|
|
101
|
+
],
|
|
102
|
+
});
|
|
103
|
+
const fetch = harness.createFetch();
|
|
104
|
+
const response = await fetch("/test-resource");
|
|
105
|
+
t.equal(response.status, 200, "should complete successfully");
|
|
106
|
+
t.ok(clientInterceptorCalled, "client interceptor should be called");
|
|
107
|
+
t.ok(middlewareInterceptorCalled, "middleware interceptor should be called");
|
|
108
|
+
t.end();
|
|
109
|
+
});
|
|
110
|
+
await t.test("interceptor can short-circuit request", async (t) => {
|
|
111
|
+
let facilitatorWasCalled = false;
|
|
112
|
+
const harness = new TestHarness({
|
|
113
|
+
accepts: [
|
|
114
|
+
{
|
|
115
|
+
scheme: TEST_SCHEME,
|
|
116
|
+
network: TEST_NETWORK,
|
|
117
|
+
maxAmountRequired: "100",
|
|
118
|
+
resource: "http://example.com/test",
|
|
119
|
+
description: "Test resource",
|
|
120
|
+
mimeType: "application/json",
|
|
121
|
+
payTo: "test-receiver",
|
|
122
|
+
maxTimeoutSeconds: 30,
|
|
123
|
+
asset: "",
|
|
124
|
+
},
|
|
125
|
+
],
|
|
126
|
+
facilitatorHandlers: [
|
|
127
|
+
createTestFacilitatorHandler({ payTo: "test-receiver" }),
|
|
128
|
+
],
|
|
129
|
+
clientHandlers: [createTestPaymentHandler()],
|
|
130
|
+
middlewareInterceptors: [
|
|
131
|
+
(fetch) => async (input, init) => {
|
|
132
|
+
const url = getURLFromRequestInfo(input);
|
|
133
|
+
if (url.includes("/facilitator/")) {
|
|
134
|
+
facilitatorWasCalled = true;
|
|
135
|
+
}
|
|
136
|
+
return fetch(input, init);
|
|
137
|
+
},
|
|
138
|
+
(fetch) => async (input, init) => {
|
|
139
|
+
const url = getURLFromRequestInfo(input);
|
|
140
|
+
// Short-circuit settle requests
|
|
141
|
+
if (matchFacilitatorSettle(url, init)) {
|
|
142
|
+
return new Response(JSON.stringify({
|
|
143
|
+
success: true,
|
|
144
|
+
txHash: "0xshortcircuit",
|
|
145
|
+
networkId: TEST_NETWORK,
|
|
146
|
+
}), {
|
|
147
|
+
status: 200,
|
|
148
|
+
headers: { "Content-Type": "application/json" },
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
return fetch(input, init);
|
|
152
|
+
},
|
|
153
|
+
],
|
|
154
|
+
});
|
|
155
|
+
const fetch = harness.createFetch();
|
|
156
|
+
const response = await fetch("/test-resource");
|
|
157
|
+
t.equal(response.status, 200, "should complete successfully");
|
|
158
|
+
t.ok(facilitatorWasCalled, "other facilitator endpoints should still be called");
|
|
159
|
+
t.end();
|
|
160
|
+
});
|
|
161
|
+
await t.test("dynamically added interceptors work correctly", async (t) => {
|
|
162
|
+
let dynamicInterceptorCalled = false;
|
|
163
|
+
const harness = new TestHarness({
|
|
164
|
+
settleMode: "verify-then-settle",
|
|
165
|
+
accepts: [
|
|
166
|
+
{
|
|
167
|
+
scheme: TEST_SCHEME,
|
|
168
|
+
network: TEST_NETWORK,
|
|
169
|
+
maxAmountRequired: "100",
|
|
170
|
+
resource: "http://example.com/test",
|
|
171
|
+
description: "Test resource",
|
|
172
|
+
mimeType: "application/json",
|
|
173
|
+
payTo: "test-receiver",
|
|
174
|
+
maxTimeoutSeconds: 30,
|
|
175
|
+
asset: "",
|
|
176
|
+
},
|
|
177
|
+
],
|
|
178
|
+
facilitatorHandlers: [
|
|
179
|
+
createTestFacilitatorHandler({ payTo: "test-receiver" }),
|
|
180
|
+
],
|
|
181
|
+
clientHandlers: [createTestPaymentHandler()],
|
|
182
|
+
});
|
|
183
|
+
// Add interceptor after construction to track verify endpoint calls
|
|
184
|
+
harness.addMiddlewareInterceptor((fetch) => async (input, init) => {
|
|
185
|
+
const url = getURLFromRequestInfo(input);
|
|
186
|
+
if (matchFacilitatorVerify(url, init)) {
|
|
187
|
+
dynamicInterceptorCalled = true;
|
|
188
|
+
}
|
|
189
|
+
return fetch(input, init);
|
|
190
|
+
});
|
|
191
|
+
const fetch = harness.createFetch();
|
|
192
|
+
const response = await fetch("/test-resource");
|
|
193
|
+
t.equal(response.status, 200, "should complete successfully");
|
|
194
|
+
t.ok(dynamicInterceptorCalled, "dynamically added interceptor should be called");
|
|
195
|
+
t.end();
|
|
196
|
+
});
|
|
197
|
+
await t.test("clearInterceptors removes added interceptors", async (t) => {
|
|
198
|
+
let dynamicInterceptorCalled = false;
|
|
199
|
+
const harness = new TestHarness({
|
|
200
|
+
accepts: [
|
|
201
|
+
{
|
|
202
|
+
scheme: TEST_SCHEME,
|
|
203
|
+
network: TEST_NETWORK,
|
|
204
|
+
maxAmountRequired: "100",
|
|
205
|
+
resource: "http://example.com/test",
|
|
206
|
+
description: "Test resource",
|
|
207
|
+
mimeType: "application/json",
|
|
208
|
+
payTo: "test-receiver",
|
|
209
|
+
maxTimeoutSeconds: 30,
|
|
210
|
+
asset: "",
|
|
211
|
+
},
|
|
212
|
+
],
|
|
213
|
+
facilitatorHandlers: [
|
|
214
|
+
createTestFacilitatorHandler({ payTo: "test-receiver" }),
|
|
215
|
+
],
|
|
216
|
+
clientHandlers: [createTestPaymentHandler()],
|
|
217
|
+
});
|
|
218
|
+
// Add then clear interceptor
|
|
219
|
+
harness.addMiddlewareInterceptor((fetch) => async (input, init) => {
|
|
220
|
+
dynamicInterceptorCalled = true;
|
|
221
|
+
return fetch(input, init);
|
|
222
|
+
});
|
|
223
|
+
harness.clearInterceptors();
|
|
224
|
+
const fetch = harness.createFetch();
|
|
225
|
+
const response = await fetch("/test-resource");
|
|
226
|
+
t.equal(response.status, 200, "should complete successfully");
|
|
227
|
+
t.equal(dynamicInterceptorCalled, false, "cleared interceptor should not be called");
|
|
228
|
+
t.end();
|
|
229
|
+
});
|
|
230
|
+
});
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { x402PaymentRequirements, x402PaymentPayload, x402SettleResponse, x402VerifyResponse } from "@faremeter/types/x402";
|
|
2
|
+
export type ResourceContext = {
|
|
3
|
+
resource: string;
|
|
4
|
+
request: Request;
|
|
5
|
+
paymentRequirements: x402PaymentRequirements;
|
|
6
|
+
paymentPayload: x402PaymentPayload;
|
|
7
|
+
settleResponse: x402SettleResponse;
|
|
8
|
+
verifyResponse?: x402VerifyResponse | undefined;
|
|
9
|
+
};
|
|
10
|
+
export type ResourceResult = {
|
|
11
|
+
status: number;
|
|
12
|
+
body: unknown;
|
|
13
|
+
headers?: Record<string, string>;
|
|
14
|
+
};
|
|
15
|
+
export type ResourceHandler = (ctx: ResourceContext) => ResourceResult | Promise<ResourceResult>;
|
|
16
|
+
export declare const defaultResourceHandler: ResourceHandler;
|
|
17
|
+
//# sourceMappingURL=resource.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resource.d.ts","sourceRoot":"","sources":["../../../src/harness/resource.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,uBAAuB,EACvB,kBAAkB,EAClB,kBAAkB,EAClB,kBAAkB,EACnB,MAAM,uBAAuB,CAAC;AAE/B,MAAM,MAAM,eAAe,GAAG;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,OAAO,CAAC;IACjB,mBAAmB,EAAE,uBAAuB,CAAC;IAC7C,cAAc,EAAE,kBAAkB,CAAC;IACnC,cAAc,EAAE,kBAAkB,CAAC;IACnC,cAAc,CAAC,EAAE,kBAAkB,GAAG,SAAS,CAAC;CACjD,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAClC,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG,CAC5B,GAAG,EAAE,eAAe,KACjB,cAAc,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;AAE9C,eAAO,MAAM,sBAAsB,EAAE,eAOnC,CAAC"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export { TestHarness } from "./harness/harness.js";
|
|
2
|
+
export type { TestHarnessConfig, SettleMode } from "./harness/config.js";
|
|
3
|
+
export type { ResourceHandler, ResourceContext, ResourceResult, } from "./harness/resource.js";
|
|
4
|
+
export { defaultResourceHandler } from "./harness/resource.js";
|
|
5
|
+
export { accepts } from "./harness/defaults.js";
|
|
6
|
+
export { TEST_SCHEME, TEST_NETWORK, TEST_ASSET } from "./scheme/constants.js";
|
|
7
|
+
export type { TestPaymentPayload } from "./scheme/types.js";
|
|
8
|
+
export { generateTestId } from "./scheme/types.js";
|
|
9
|
+
export { createTestFacilitatorHandler, type CreateTestFacilitatorHandlerOpts, } from "./scheme/facilitator.js";
|
|
10
|
+
export { createTestPaymentHandler, type CreateTestPaymentHandlerOpts, } from "./scheme/client.js";
|
|
11
|
+
export type { Interceptor, RequestMatcher } from "./interceptors/types.js";
|
|
12
|
+
export { composeInterceptors } from "./interceptors/types.js";
|
|
13
|
+
export { getURLFromRequestInfo } from "./interceptors/utils.js";
|
|
14
|
+
export { matchFacilitatorAccepts, matchFacilitatorVerify, matchFacilitatorSettle, matchFacilitatorSupported, matchFacilitator, matchResource, and, or, not, matchURL, matchMethod, matchAll, matchNone, } from "./interceptors/matchers.js";
|
|
15
|
+
export { jsonResponse, verifyFailedResponse, verifySuccessResponse, settleFailedResponse, settleSuccessResponse, paymentRequiredResponse, networkError, timeoutError, httpError, } from "./interceptors/responses.js";
|
|
16
|
+
export { createFailureInterceptor, failOnce, failNTimes, failUntilCleared, failWhen, } from "./interceptors/failures.js";
|
|
17
|
+
export { createDelayInterceptor, createResponseDelayInterceptor, createVariableDelayInterceptor, } from "./interceptors/delay.js";
|
|
18
|
+
export { createRequestHook, createResponseHook, createHook, createCaptureInterceptor, } from "./interceptors/hooks.js";
|
|
19
|
+
export type { LogEvent } from "./interceptors/logging.js";
|
|
20
|
+
export { createLoggingInterceptor, createConsoleLoggingInterceptor, createEventCollector, } from "./interceptors/logging.js";
|
|
21
|
+
export { chooseFirst, chooseCheapest, chooseMostExpensive, chooseByAsset, chooseByNetwork, chooseByScheme, chooseByIndex, chooseNone, chooseWithInspection, chooseWithFilter, } from "./choosers.js";
|
|
22
|
+
export { suppressConsoleErrors } from "./testing/console.js";
|
|
23
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,YAAY,EAAE,iBAAiB,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACtE,YAAY,EACV,eAAe,EACf,eAAe,EACf,cAAc,GACf,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAC;AAC5D,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAE7C,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAC3E,YAAY,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AACzD,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,EACL,4BAA4B,EAC5B,KAAK,gCAAgC,GACtC,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EACL,wBAAwB,EACxB,KAAK,4BAA4B,GAClC,MAAM,iBAAiB,CAAC;AAEzB,YAAY,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACxE,OAAO,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAE3D,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAE7D,OAAO,EACL,uBAAuB,EACvB,sBAAsB,EACtB,sBAAsB,EACtB,yBAAyB,EACzB,gBAAgB,EAChB,aAAa,EACb,GAAG,EACH,EAAE,EACF,GAAG,EACH,QAAQ,EACR,WAAW,EACX,QAAQ,EACR,SAAS,GACV,MAAM,yBAAyB,CAAC;AAEjC,OAAO,EACL,YAAY,EACZ,oBAAoB,EACpB,qBAAqB,EACrB,oBAAoB,EACpB,qBAAqB,EACrB,uBAAuB,EACvB,YAAY,EACZ,YAAY,EACZ,SAAS,GACV,MAAM,0BAA0B,CAAC;AAElC,OAAO,EACL,wBAAwB,EACxB,QAAQ,EACR,UAAU,EACV,gBAAgB,EAChB,QAAQ,GACT,MAAM,yBAAyB,CAAC;AAEjC,OAAO,EACL,sBAAsB,EACtB,8BAA8B,EAC9B,8BAA8B,GAC/B,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EACL,iBAAiB,EACjB,kBAAkB,EAClB,UAAU,EACV,wBAAwB,GACzB,MAAM,sBAAsB,CAAC;AAE9B,YAAY,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AACvD,OAAO,EACL,wBAAwB,EACxB,+BAA+B,EAC/B,oBAAoB,GACrB,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EACL,WAAW,EACX,cAAc,EACd,mBAAmB,EACnB,aAAa,EACb,eAAe,EACf,cAAc,EACd,aAAa,EACb,UAAU,EACV,oBAAoB,EACpB,gBAAgB,GACjB,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export { TestHarness } from "./harness/harness.js";
|
|
2
|
+
export { defaultResourceHandler } from "./harness/resource.js";
|
|
3
|
+
export { accepts } from "./harness/defaults.js";
|
|
4
|
+
export { TEST_SCHEME, TEST_NETWORK, TEST_ASSET } from "./scheme/constants.js";
|
|
5
|
+
export { generateTestId } from "./scheme/types.js";
|
|
6
|
+
export { createTestFacilitatorHandler, } from "./scheme/facilitator.js";
|
|
7
|
+
export { createTestPaymentHandler, } from "./scheme/client.js";
|
|
8
|
+
export { composeInterceptors } from "./interceptors/types.js";
|
|
9
|
+
export { getURLFromRequestInfo } from "./interceptors/utils.js";
|
|
10
|
+
export { matchFacilitatorAccepts, matchFacilitatorVerify, matchFacilitatorSettle, matchFacilitatorSupported, matchFacilitator, matchResource, and, or, not, matchURL, matchMethod, matchAll, matchNone, } from "./interceptors/matchers.js";
|
|
11
|
+
export { jsonResponse, verifyFailedResponse, verifySuccessResponse, settleFailedResponse, settleSuccessResponse, paymentRequiredResponse, networkError, timeoutError, httpError, } from "./interceptors/responses.js";
|
|
12
|
+
export { createFailureInterceptor, failOnce, failNTimes, failUntilCleared, failWhen, } from "./interceptors/failures.js";
|
|
13
|
+
export { createDelayInterceptor, createResponseDelayInterceptor, createVariableDelayInterceptor, } from "./interceptors/delay.js";
|
|
14
|
+
export { createRequestHook, createResponseHook, createHook, createCaptureInterceptor, } from "./interceptors/hooks.js";
|
|
15
|
+
export { createLoggingInterceptor, createConsoleLoggingInterceptor, createEventCollector, } from "./interceptors/logging.js";
|
|
16
|
+
export { chooseFirst, chooseCheapest, chooseMostExpensive, chooseByAsset, chooseByNetwork, chooseByScheme, chooseByIndex, chooseNone, chooseWithInspection, chooseWithFilter, } from "./choosers.js";
|
|
17
|
+
export { suppressConsoleErrors } from "./testing/console.js";
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { Interceptor, RequestMatcher } from "./types.js";
|
|
2
|
+
export declare function createDelayInterceptor(match: RequestMatcher, delayMs: number): Interceptor;
|
|
3
|
+
export declare function createResponseDelayInterceptor(match: RequestMatcher, delayMs: number): Interceptor;
|
|
4
|
+
export declare function createVariableDelayInterceptor(match: RequestMatcher, getDelay: (url: string, init?: RequestInit) => number): Interceptor;
|
|
5
|
+
//# sourceMappingURL=delay.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"delay.d.ts","sourceRoot":"","sources":["../../../src/interceptors/delay.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAG3D,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,cAAc,EACrB,OAAO,EAAE,MAAM,GACd,WAAW,CAUb;AAED,wBAAgB,8BAA8B,CAC5C,KAAK,EAAE,cAAc,EACrB,OAAO,EAAE,MAAM,GACd,WAAW,CAWb;AAED,wBAAgB,8BAA8B,CAC5C,KAAK,EAAE,cAAc,EACrB,QAAQ,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,WAAW,KAAK,MAAM,GACpD,WAAW,CAWb"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { getURLFromRequestInfo } from "./utils.js";
|
|
2
|
+
export function createDelayInterceptor(match, delayMs) {
|
|
3
|
+
return (fetch) => async (input, init) => {
|
|
4
|
+
const url = getURLFromRequestInfo(input);
|
|
5
|
+
if (match(url, init)) {
|
|
6
|
+
await new Promise((resolve) => setTimeout(resolve, delayMs));
|
|
7
|
+
}
|
|
8
|
+
return fetch(input, init);
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
export function createResponseDelayInterceptor(match, delayMs) {
|
|
12
|
+
return (fetch) => async (input, init) => {
|
|
13
|
+
const url = getURLFromRequestInfo(input);
|
|
14
|
+
const response = await fetch(input, init);
|
|
15
|
+
if (match(url, init)) {
|
|
16
|
+
await new Promise((resolve) => setTimeout(resolve, delayMs));
|
|
17
|
+
}
|
|
18
|
+
return response;
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
export function createVariableDelayInterceptor(match, getDelay) {
|
|
22
|
+
return (fetch) => async (input, init) => {
|
|
23
|
+
const url = getURLFromRequestInfo(input);
|
|
24
|
+
if (match(url, init)) {
|
|
25
|
+
const delayMs = getDelay(url, init);
|
|
26
|
+
await new Promise((resolve) => setTimeout(resolve, delayMs));
|
|
27
|
+
}
|
|
28
|
+
return fetch(input, init);
|
|
29
|
+
};
|
|
30
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { Interceptor, RequestMatcher } from "./types.js";
|
|
2
|
+
export declare function createFailureInterceptor(match: RequestMatcher, failFn: () => Response | Error | Promise<Response | Error>): Interceptor;
|
|
3
|
+
export declare function failOnce(match: RequestMatcher, failFn: () => Response | Error): Interceptor;
|
|
4
|
+
export declare function failNTimes(n: number, match: RequestMatcher, failFn: () => Response | Error): Interceptor;
|
|
5
|
+
export declare function failUntilCleared(match: RequestMatcher, failFn: () => Response | Error): Interceptor & {
|
|
6
|
+
clear(): void;
|
|
7
|
+
};
|
|
8
|
+
export declare function failWhen(match: RequestMatcher, shouldFail: (ctx: {
|
|
9
|
+
url: string;
|
|
10
|
+
attemptCount: number;
|
|
11
|
+
}) => boolean, failFn: () => Response | Error): Interceptor;
|
|
12
|
+
//# sourceMappingURL=failures.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"failures.d.ts","sourceRoot":"","sources":["../../../src/interceptors/failures.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAG3D,wBAAgB,wBAAwB,CACtC,KAAK,EAAE,cAAc,EACrB,MAAM,EAAE,MAAM,QAAQ,GAAG,KAAK,GAAG,OAAO,CAAC,QAAQ,GAAG,KAAK,CAAC,GACzD,WAAW,CAcb;AAED,wBAAgB,QAAQ,CACtB,KAAK,EAAE,cAAc,EACrB,MAAM,EAAE,MAAM,QAAQ,GAAG,KAAK,GAC7B,WAAW,CAab;AAED,wBAAgB,UAAU,CACxB,CAAC,EAAE,MAAM,EACT,KAAK,EAAE,cAAc,EACrB,MAAM,EAAE,MAAM,QAAQ,GAAG,KAAK,GAC7B,WAAW,CAab;AAED,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,cAAc,EACrB,MAAM,EAAE,MAAM,QAAQ,GAAG,KAAK,GAC7B,WAAW,GAAG;IAAE,KAAK,IAAI,IAAI,CAAA;CAAE,CAajC;AAED,wBAAgB,QAAQ,CACtB,KAAK,EAAE,cAAc,EACrB,UAAU,EAAE,CAAC,GAAG,EAAE;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAA;CAAE,KAAK,OAAO,EACnE,MAAM,EAAE,MAAM,QAAQ,GAAG,KAAK,GAC7B,WAAW,CAqBb"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { getURLFromRequestInfo } from "./utils.js";
|
|
2
|
+
export function createFailureInterceptor(match, failFn) {
|
|
3
|
+
return (fetch) => async (input, init) => {
|
|
4
|
+
const url = getURLFromRequestInfo(input);
|
|
5
|
+
if (match(url, init)) {
|
|
6
|
+
const result = await failFn();
|
|
7
|
+
if (result instanceof Error) {
|
|
8
|
+
throw result;
|
|
9
|
+
}
|
|
10
|
+
return result;
|
|
11
|
+
}
|
|
12
|
+
return fetch(input, init);
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
export function failOnce(match, failFn) {
|
|
16
|
+
let triggered = false;
|
|
17
|
+
return createFailureInterceptor((url, init) => {
|
|
18
|
+
if (triggered)
|
|
19
|
+
return false;
|
|
20
|
+
return match(url, init);
|
|
21
|
+
}, () => {
|
|
22
|
+
triggered = true;
|
|
23
|
+
return failFn();
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
export function failNTimes(n, match, failFn) {
|
|
27
|
+
let count = 0;
|
|
28
|
+
return createFailureInterceptor((url, init) => {
|
|
29
|
+
if (count >= n)
|
|
30
|
+
return false;
|
|
31
|
+
return match(url, init);
|
|
32
|
+
}, () => {
|
|
33
|
+
count++;
|
|
34
|
+
return failFn();
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
export function failUntilCleared(match, failFn) {
|
|
38
|
+
let active = true;
|
|
39
|
+
const interceptor = createFailureInterceptor((url, init) => active && match(url, init), failFn);
|
|
40
|
+
interceptor.clear = () => {
|
|
41
|
+
active = false;
|
|
42
|
+
};
|
|
43
|
+
return interceptor;
|
|
44
|
+
}
|
|
45
|
+
export function failWhen(match, shouldFail, failFn) {
|
|
46
|
+
const attemptCounts = new Map();
|
|
47
|
+
return (fetch) => async (input, init) => {
|
|
48
|
+
const url = getURLFromRequestInfo(input);
|
|
49
|
+
if (match(url, init)) {
|
|
50
|
+
const attemptCount = (attemptCounts.get(url) ?? 0) + 1;
|
|
51
|
+
attemptCounts.set(url, attemptCount);
|
|
52
|
+
if (shouldFail({ url, attemptCount })) {
|
|
53
|
+
const result = failFn();
|
|
54
|
+
if (result instanceof Error) {
|
|
55
|
+
throw result;
|
|
56
|
+
}
|
|
57
|
+
return result;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
return fetch(input, init);
|
|
61
|
+
};
|
|
62
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { Interceptor, RequestMatcher } from "./types.js";
|
|
2
|
+
export declare function createRequestHook(match: RequestMatcher, hook: (url: string, init?: RequestInit) => void | Promise<void>): Interceptor;
|
|
3
|
+
export declare function createResponseHook(match: RequestMatcher, hook: (url: string, response: Response, init?: RequestInit) => void | Promise<void>): Interceptor;
|
|
4
|
+
export declare function createHook(match: RequestMatcher, hooks: {
|
|
5
|
+
onRequest?: (url: string, init?: RequestInit) => void | Promise<void>;
|
|
6
|
+
onResponse?: (url: string, response: Response, init?: RequestInit) => void | Promise<void>;
|
|
7
|
+
}): Interceptor;
|
|
8
|
+
type CapturedRequest = {
|
|
9
|
+
url: string;
|
|
10
|
+
init?: RequestInit | undefined;
|
|
11
|
+
response: Response;
|
|
12
|
+
timestamp: number;
|
|
13
|
+
};
|
|
14
|
+
export declare function createCaptureInterceptor(match: RequestMatcher): {
|
|
15
|
+
interceptor: Interceptor;
|
|
16
|
+
captured: CapturedRequest[];
|
|
17
|
+
clear: () => void;
|
|
18
|
+
};
|
|
19
|
+
export {};
|
|
20
|
+
//# sourceMappingURL=hooks.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../../../src/interceptors/hooks.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAG3D,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,cAAc,EACrB,IAAI,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,WAAW,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,GAC9D,WAAW,CAUb;AAED,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,cAAc,EACrB,IAAI,EAAE,CACJ,GAAG,EAAE,MAAM,EACX,QAAQ,EAAE,QAAQ,EAClB,IAAI,CAAC,EAAE,WAAW,KACf,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,GACxB,WAAW,CAWb;AAED,wBAAgB,UAAU,CACxB,KAAK,EAAE,cAAc,EACrB,KAAK,EAAE;IACL,SAAS,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,WAAW,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACtE,UAAU,CAAC,EAAE,CACX,GAAG,EAAE,MAAM,EACX,QAAQ,EAAE,QAAQ,EAClB,IAAI,CAAC,EAAE,WAAW,KACf,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC3B,GACA,WAAW,CAgBb;AAED,KAAK,eAAe,GAAG;IACrB,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,WAAW,GAAG,SAAS,CAAC;IAC/B,QAAQ,EAAE,QAAQ,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,cAAc,GAAG;IAC/D,WAAW,EAAE,WAAW,CAAC;IACzB,QAAQ,EAAE,eAAe,EAAE,CAAC;IAC5B,KAAK,EAAE,MAAM,IAAI,CAAC;CACnB,CA0BA"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { getURLFromRequestInfo } from "./utils.js";
|
|
2
|
+
export function createRequestHook(match, hook) {
|
|
3
|
+
return (fetch) => async (input, init) => {
|
|
4
|
+
const url = getURLFromRequestInfo(input);
|
|
5
|
+
if (match(url, init)) {
|
|
6
|
+
await hook(url, init);
|
|
7
|
+
}
|
|
8
|
+
return fetch(input, init);
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
export function createResponseHook(match, hook) {
|
|
12
|
+
return (fetch) => async (input, init) => {
|
|
13
|
+
const url = getURLFromRequestInfo(input);
|
|
14
|
+
const response = await fetch(input, init);
|
|
15
|
+
if (match(url, init)) {
|
|
16
|
+
await hook(url, response, init);
|
|
17
|
+
}
|
|
18
|
+
return response;
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
export function createHook(match, hooks) {
|
|
22
|
+
return (fetch) => async (input, init) => {
|
|
23
|
+
const url = getURLFromRequestInfo(input);
|
|
24
|
+
if (match(url, init) && hooks.onRequest) {
|
|
25
|
+
await hooks.onRequest(url, init);
|
|
26
|
+
}
|
|
27
|
+
const response = await fetch(input, init);
|
|
28
|
+
if (match(url, init) && hooks.onResponse) {
|
|
29
|
+
await hooks.onResponse(url, response, init);
|
|
30
|
+
}
|
|
31
|
+
return response;
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
export function createCaptureInterceptor(match) {
|
|
35
|
+
const captured = [];
|
|
36
|
+
const interceptor = (fetch) => async (input, init) => {
|
|
37
|
+
const url = getURLFromRequestInfo(input);
|
|
38
|
+
const response = await fetch(input, init);
|
|
39
|
+
if (match(url, init)) {
|
|
40
|
+
captured.push({
|
|
41
|
+
url,
|
|
42
|
+
init,
|
|
43
|
+
response: response.clone(), // Clone so the original can still be consumed
|
|
44
|
+
timestamp: Date.now(),
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
return response;
|
|
48
|
+
};
|
|
49
|
+
return {
|
|
50
|
+
interceptor,
|
|
51
|
+
captured,
|
|
52
|
+
clear: () => {
|
|
53
|
+
captured.length = 0;
|
|
54
|
+
},
|
|
55
|
+
};
|
|
56
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { Interceptor } from "./types.js";
|
|
2
|
+
export type LogEvent = {
|
|
3
|
+
type: "request" | "response" | "error";
|
|
4
|
+
url: string;
|
|
5
|
+
method?: string;
|
|
6
|
+
status?: number;
|
|
7
|
+
error?: string;
|
|
8
|
+
timestamp: number;
|
|
9
|
+
};
|
|
10
|
+
export declare function createLoggingInterceptor(log: (event: LogEvent) => void): Interceptor;
|
|
11
|
+
export declare function createConsoleLoggingInterceptor(prefix?: string, log?: {
|
|
12
|
+
log: (msg: string) => void;
|
|
13
|
+
error: (msg: string) => void;
|
|
14
|
+
}): Interceptor;
|
|
15
|
+
export declare function createEventCollector(): {
|
|
16
|
+
interceptor: Interceptor;
|
|
17
|
+
events: LogEvent[];
|
|
18
|
+
clear: () => void;
|
|
19
|
+
};
|
|
20
|
+
//# sourceMappingURL=logging.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logging.d.ts","sourceRoot":"","sources":["../../../src/interceptors/logging.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAG3C,MAAM,MAAM,QAAQ,GAAG;IACrB,IAAI,EAAE,SAAS,GAAG,UAAU,GAAG,OAAO,CAAC;IACvC,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,wBAAgB,wBAAwB,CACtC,GAAG,EAAE,CAAC,KAAK,EAAE,QAAQ,KAAK,IAAI,GAC7B,WAAW,CAoCb;AAED,wBAAgB,+BAA+B,CAC7C,MAAM,SAAmB,EACzB,GAAG,GAAE;IACH,GAAG,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IAC3B,KAAK,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;CACpB,GACV,WAAW,CAUb;AAED,wBAAgB,oBAAoB,IAAI;IACtC,WAAW,EAAE,WAAW,CAAC;IACzB,MAAM,EAAE,QAAQ,EAAE,CAAC;IACnB,KAAK,EAAE,MAAM,IAAI,CAAC;CACnB,CAUA"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { getURLFromRequestInfo } from "./utils.js";
|
|
2
|
+
export function createLoggingInterceptor(log) {
|
|
3
|
+
return (fetch) => async (input, init) => {
|
|
4
|
+
const url = getURLFromRequestInfo(input);
|
|
5
|
+
const method = init?.method ?? "GET";
|
|
6
|
+
log({
|
|
7
|
+
type: "request",
|
|
8
|
+
url,
|
|
9
|
+
method,
|
|
10
|
+
timestamp: Date.now(),
|
|
11
|
+
});
|
|
12
|
+
try {
|
|
13
|
+
const response = await fetch(input, init);
|
|
14
|
+
log({
|
|
15
|
+
type: "response",
|
|
16
|
+
url,
|
|
17
|
+
method,
|
|
18
|
+
status: response.status,
|
|
19
|
+
timestamp: Date.now(),
|
|
20
|
+
});
|
|
21
|
+
return response;
|
|
22
|
+
}
|
|
23
|
+
catch (error) {
|
|
24
|
+
log({
|
|
25
|
+
type: "error",
|
|
26
|
+
url,
|
|
27
|
+
method,
|
|
28
|
+
error: error instanceof Error ? error.message : String(error),
|
|
29
|
+
timestamp: Date.now(),
|
|
30
|
+
});
|
|
31
|
+
throw error;
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
export function createConsoleLoggingInterceptor(prefix = "[test-harness]", log = console) {
|
|
36
|
+
return createLoggingInterceptor((event) => {
|
|
37
|
+
if (event.type === "request") {
|
|
38
|
+
log.log(`${prefix} ${event.method} ${event.url}`);
|
|
39
|
+
}
|
|
40
|
+
else if (event.type === "response") {
|
|
41
|
+
log.log(`${prefix} ${event.method} ${event.url} -> ${event.status}`);
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
log.error(`${prefix} ${event.method} ${event.url} ERROR: ${event.error}`);
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
export function createEventCollector() {
|
|
49
|
+
const events = [];
|
|
50
|
+
return {
|
|
51
|
+
interceptor: createLoggingInterceptor((event) => events.push(event)),
|
|
52
|
+
events,
|
|
53
|
+
clear: () => {
|
|
54
|
+
events.length = 0;
|
|
55
|
+
},
|
|
56
|
+
};
|
|
57
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { RequestMatcher } from "./types.js";
|
|
2
|
+
export declare const matchFacilitatorAccepts: RequestMatcher;
|
|
3
|
+
export declare const matchFacilitatorVerify: RequestMatcher;
|
|
4
|
+
export declare const matchFacilitatorSettle: RequestMatcher;
|
|
5
|
+
export declare const matchFacilitatorSupported: RequestMatcher;
|
|
6
|
+
export declare const matchFacilitator: RequestMatcher;
|
|
7
|
+
export declare const matchResource: RequestMatcher;
|
|
8
|
+
export declare function and(...matchers: RequestMatcher[]): RequestMatcher;
|
|
9
|
+
export declare function or(...matchers: RequestMatcher[]): RequestMatcher;
|
|
10
|
+
export declare function not(matcher: RequestMatcher): RequestMatcher;
|
|
11
|
+
export declare function matchURL(pattern: string | RegExp): RequestMatcher;
|
|
12
|
+
export declare function matchMethod(method: string): RequestMatcher;
|
|
13
|
+
export declare const matchAll: RequestMatcher;
|
|
14
|
+
export declare const matchNone: RequestMatcher;
|
|
15
|
+
//# sourceMappingURL=matchers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"matchers.d.ts","sourceRoot":"","sources":["../../../src/interceptors/matchers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAE9C,eAAO,MAAM,uBAAuB,EAAE,cACA,CAAC;AAEvC,eAAO,MAAM,sBAAsB,EAAE,cACA,CAAC;AAEtC,eAAO,MAAM,sBAAsB,EAAE,cACA,CAAC;AAEtC,eAAO,MAAM,yBAAyB,EAAE,cACA,CAAC;AAEzC,eAAO,MAAM,gBAAgB,EAAE,cAIC,CAAC;AAEjC,eAAO,MAAM,aAAa,EAAE,cAAgD,CAAC;AAE7E,wBAAgB,GAAG,CAAC,GAAG,QAAQ,EAAE,cAAc,EAAE,GAAG,cAAc,CAEjE;AAED,wBAAgB,EAAE,CAAC,GAAG,QAAQ,EAAE,cAAc,EAAE,GAAG,cAAc,CAEhE;AAED,wBAAgB,GAAG,CAAC,OAAO,EAAE,cAAc,GAAG,cAAc,CAE3D;AAED,wBAAgB,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,cAAc,CAKjE;AAED,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,cAAc,CAG1D;AAED,eAAO,MAAM,QAAQ,EAAE,cAA2B,CAAC;AAEnD,eAAO,MAAM,SAAS,EAAE,cAA4B,CAAC"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
export const matchFacilitatorAccepts = (url) => url.includes("/facilitator/accepts");
|
|
2
|
+
export const matchFacilitatorVerify = (url) => url.includes("/facilitator/verify");
|
|
3
|
+
export const matchFacilitatorSettle = (url) => url.includes("/facilitator/settle");
|
|
4
|
+
export const matchFacilitatorSupported = (url) => url.includes("/facilitator/supported");
|
|
5
|
+
export const matchFacilitator = (url) => matchFacilitatorAccepts(url) ||
|
|
6
|
+
matchFacilitatorVerify(url) ||
|
|
7
|
+
matchFacilitatorSettle(url) ||
|
|
8
|
+
matchFacilitatorSupported(url);
|
|
9
|
+
export const matchResource = (url) => !matchFacilitator(url);
|
|
10
|
+
export function and(...matchers) {
|
|
11
|
+
return (url, init) => matchers.every((m) => m(url, init));
|
|
12
|
+
}
|
|
13
|
+
export function or(...matchers) {
|
|
14
|
+
return (url, init) => matchers.some((m) => m(url, init));
|
|
15
|
+
}
|
|
16
|
+
export function not(matcher) {
|
|
17
|
+
return (url, init) => !matcher(url, init);
|
|
18
|
+
}
|
|
19
|
+
export function matchURL(pattern) {
|
|
20
|
+
if (typeof pattern === "string") {
|
|
21
|
+
return (url) => url.includes(pattern);
|
|
22
|
+
}
|
|
23
|
+
return (url) => pattern.test(url);
|
|
24
|
+
}
|
|
25
|
+
export function matchMethod(method) {
|
|
26
|
+
const upperMethod = method.toUpperCase();
|
|
27
|
+
return (_url, init) => (init?.method?.toUpperCase() ?? "GET") === upperMethod;
|
|
28
|
+
}
|
|
29
|
+
export const matchAll = () => true;
|
|
30
|
+
export const matchNone = () => false;
|