@fedify/testing 2.0.0-dev.1690 → 2.0.0-dev.170
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 +1 -1
- package/README.md +9 -7
- package/dist/mod.cjs +109 -43
- package/dist/mod.d.cts +83 -254
- package/dist/mod.d.ts +83 -254
- package/dist/mod.js +108 -41
- package/package.json +3 -6
package/LICENSE
CHANGED
package/README.md
CHANGED
|
@@ -40,7 +40,7 @@ interface for unit testing:
|
|
|
40
40
|
|
|
41
41
|
~~~~ typescript
|
|
42
42
|
import { MockFederation } from "@fedify/testing";
|
|
43
|
-
import { Create } from "@fedify/
|
|
43
|
+
import { Create } from "@fedify/vocab";
|
|
44
44
|
|
|
45
45
|
// Create a mock federation
|
|
46
46
|
const federation = new MockFederation<{ userId: string }>();
|
|
@@ -95,10 +95,12 @@ The package also exports helper functions for creating various context types:
|
|
|
95
95
|
- `createRequestContext()`: Creates a request context
|
|
96
96
|
- `createInboxContext()`: Creates an inbox context
|
|
97
97
|
|
|
98
|
-
## Features
|
|
99
98
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
-
|
|
104
|
-
-
|
|
99
|
+
Features
|
|
100
|
+
--------
|
|
101
|
+
|
|
102
|
+
- Track sent activities with metadata
|
|
103
|
+
- Simulate activity reception
|
|
104
|
+
- Configure custom URI templates
|
|
105
|
+
- Test queue-based activity processing
|
|
106
|
+
- Mock document loaders and context loaders
|
package/dist/mod.cjs
CHANGED
|
@@ -21,10 +21,8 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
21
21
|
}) : target, mod));
|
|
22
22
|
|
|
23
23
|
//#endregion
|
|
24
|
-
const __opentelemetry_api = __toESM(require("@opentelemetry/api"));
|
|
25
24
|
const __fedify_fedify_federation = __toESM(require("@fedify/fedify/federation"));
|
|
26
|
-
const
|
|
27
|
-
const __fedify_fedify_webfinger = __toESM(require("@fedify/fedify/webfinger"));
|
|
25
|
+
const __fedify_vocab = __toESM(require("@fedify/vocab"));
|
|
28
26
|
|
|
29
27
|
//#region src/docloader.ts
|
|
30
28
|
const mockDocumentLoader = async (url) => ({
|
|
@@ -35,6 +33,10 @@ const mockDocumentLoader = async (url) => ({
|
|
|
35
33
|
|
|
36
34
|
//#endregion
|
|
37
35
|
//#region src/context.ts
|
|
36
|
+
const noopTracerProvider$1 = { getTracer: () => ({
|
|
37
|
+
startActiveSpan: () => void 0,
|
|
38
|
+
startSpan: () => void 0
|
|
39
|
+
}) };
|
|
38
40
|
function createContext(values) {
|
|
39
41
|
const { federation, url = new URL("http://example.com/"), canonicalOrigin, data, documentLoader, contextLoader, tracerProvider, clone, getNodeInfoUri, getActorUri, getObjectUri, getCollectionUri, getOutboxUri, getInboxUri, getFollowingUri, getFollowersUri, getLikedUri, getFeaturedUri, getFeaturedTagsUri, parseUri, getActorKeyPairs, getDocumentLoader, lookupObject, traverseCollection, lookupNodeInfo, lookupWebFinger, sendActivity, routeActivity } = values;
|
|
40
42
|
function throwRouteError() {
|
|
@@ -49,7 +51,7 @@ function createContext(values) {
|
|
|
49
51
|
hostname: url.hostname,
|
|
50
52
|
documentLoader: documentLoader ?? mockDocumentLoader,
|
|
51
53
|
contextLoader: contextLoader ?? mockDocumentLoader,
|
|
52
|
-
tracerProvider: tracerProvider ??
|
|
54
|
+
tracerProvider: tracerProvider ?? noopTracerProvider$1,
|
|
53
55
|
clone: clone ?? ((data$1) => createContext({
|
|
54
56
|
...values,
|
|
55
57
|
data: data$1
|
|
@@ -73,13 +75,13 @@ function createContext(values) {
|
|
|
73
75
|
}),
|
|
74
76
|
getActorKeyPairs: getActorKeyPairs ?? ((_handle) => Promise.resolve([])),
|
|
75
77
|
lookupObject: lookupObject ?? ((uri, options = {}) => {
|
|
76
|
-
return (0,
|
|
78
|
+
return (0, __fedify_vocab.lookupObject)(uri, {
|
|
77
79
|
documentLoader: options.documentLoader ?? documentLoader ?? mockDocumentLoader,
|
|
78
80
|
contextLoader: options.contextLoader ?? contextLoader ?? mockDocumentLoader
|
|
79
81
|
});
|
|
80
82
|
}),
|
|
81
83
|
traverseCollection: traverseCollection ?? ((collection, options = {}) => {
|
|
82
|
-
return (0,
|
|
84
|
+
return (0, __fedify_vocab.traverseCollection)(collection, {
|
|
83
85
|
documentLoader: options.documentLoader ?? documentLoader ?? mockDocumentLoader,
|
|
84
86
|
contextLoader: options.contextLoader ?? contextLoader ?? mockDocumentLoader
|
|
85
87
|
});
|
|
@@ -87,8 +89,8 @@ function createContext(values) {
|
|
|
87
89
|
lookupNodeInfo: lookupNodeInfo ?? ((_params) => {
|
|
88
90
|
throw new Error("Not implemented");
|
|
89
91
|
}),
|
|
90
|
-
lookupWebFinger: lookupWebFinger ?? ((
|
|
91
|
-
return
|
|
92
|
+
lookupWebFinger: lookupWebFinger ?? ((_resource, _options = {}) => {
|
|
93
|
+
return Promise.resolve(null);
|
|
92
94
|
}),
|
|
93
95
|
sendActivity: sendActivity ?? ((_params) => {
|
|
94
96
|
throw new Error("Not implemented");
|
|
@@ -98,6 +100,13 @@ function createContext(values) {
|
|
|
98
100
|
})
|
|
99
101
|
};
|
|
100
102
|
}
|
|
103
|
+
/**
|
|
104
|
+
* Creates a RequestContext for testing purposes.
|
|
105
|
+
* Not exported - used internally only. Public API is in mock.ts
|
|
106
|
+
* @param args Partial RequestContext properties
|
|
107
|
+
* @returns A RequestContext instance
|
|
108
|
+
* @since 1.8.0
|
|
109
|
+
*/
|
|
101
110
|
function createRequestContext(args) {
|
|
102
111
|
return {
|
|
103
112
|
...createContext(args),
|
|
@@ -116,6 +125,13 @@ function createRequestContext(args) {
|
|
|
116
125
|
})
|
|
117
126
|
};
|
|
118
127
|
}
|
|
128
|
+
/**
|
|
129
|
+
* Creates an InboxContext for testing purposes.
|
|
130
|
+
* Not exported - used internally only. Public API is in mock.ts
|
|
131
|
+
* @param args Partial InboxContext properties
|
|
132
|
+
* @returns An InboxContext instance
|
|
133
|
+
* @since 1.8.0
|
|
134
|
+
*/
|
|
119
135
|
function createInboxContext(args) {
|
|
120
136
|
return {
|
|
121
137
|
...createContext(args),
|
|
@@ -132,6 +148,10 @@ function createInboxContext(args) {
|
|
|
132
148
|
|
|
133
149
|
//#endregion
|
|
134
150
|
//#region src/mock.ts
|
|
151
|
+
const noopTracerProvider = { getTracer: () => ({
|
|
152
|
+
startActiveSpan: () => void 0,
|
|
153
|
+
startSpan: () => void 0
|
|
154
|
+
}) };
|
|
135
155
|
/**
|
|
136
156
|
* Helper function to expand URI templates with values.
|
|
137
157
|
* Supports simple placeholders like {identifier}, {handle}, etc.
|
|
@@ -151,18 +171,18 @@ function expandUriTemplate(template, values) {
|
|
|
151
171
|
*
|
|
152
172
|
* @example
|
|
153
173
|
* ```typescript
|
|
154
|
-
* import { Create } from "@fedify/
|
|
155
|
-
* import {
|
|
174
|
+
* import { Create } from "@fedify/vocab";
|
|
175
|
+
* import { createFederation } from "@fedify/testing";
|
|
156
176
|
*
|
|
157
177
|
* // Create a mock federation with contextData
|
|
158
|
-
* const federation =
|
|
178
|
+
* const federation = createFederation<{ userId: string }>({
|
|
159
179
|
* contextData: { userId: "test-user" }
|
|
160
180
|
* });
|
|
161
181
|
*
|
|
162
182
|
* // Set up inbox listeners
|
|
163
183
|
* federation
|
|
164
184
|
* .setInboxListeners("/users/{identifier}/inbox")
|
|
165
|
-
* .on(Create, async (ctx, activity) => {
|
|
185
|
+
* .on(Create, async (ctx: any, activity: any) => {
|
|
166
186
|
* console.log("Received:", activity);
|
|
167
187
|
* });
|
|
168
188
|
*
|
|
@@ -339,22 +359,9 @@ var MockFederation = class {
|
|
|
339
359
|
}
|
|
340
360
|
createContext(baseUrlOrRequest, contextData) {
|
|
341
361
|
const mockFederation = this;
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
data: contextData,
|
|
346
|
-
federation: mockFederation,
|
|
347
|
-
sendActivity: async (sender, recipients, activity, options) => {
|
|
348
|
-
const tempContext = new MockContext({
|
|
349
|
-
url: new URL(baseUrlOrRequest.url),
|
|
350
|
-
data: contextData,
|
|
351
|
-
federation: mockFederation
|
|
352
|
-
});
|
|
353
|
-
await tempContext.sendActivity(sender, recipients, activity, options);
|
|
354
|
-
}
|
|
355
|
-
});
|
|
356
|
-
else return new MockContext({
|
|
357
|
-
url: baseUrlOrRequest,
|
|
362
|
+
const url = baseUrlOrRequest instanceof Request ? new URL(baseUrlOrRequest.url) : baseUrlOrRequest;
|
|
363
|
+
return new MockContext({
|
|
364
|
+
url,
|
|
358
365
|
data: contextData,
|
|
359
366
|
federation: mockFederation
|
|
360
367
|
});
|
|
@@ -412,22 +419,66 @@ var MockFederation = class {
|
|
|
412
419
|
}
|
|
413
420
|
};
|
|
414
421
|
/**
|
|
422
|
+
* Creates a mock Federation instance for testing purposes.
|
|
423
|
+
*
|
|
424
|
+
* @template TContextData The type of context data to use
|
|
425
|
+
* @param options Optional configuration for the mock federation
|
|
426
|
+
* @returns A Federation instance that can be used for testing
|
|
427
|
+
* @since 1.9.1
|
|
428
|
+
*
|
|
429
|
+
* @example
|
|
430
|
+
* ```typescript
|
|
431
|
+
* import { Create } from "@fedify/vocab";
|
|
432
|
+
* import { createFederation } from "@fedify/testing";
|
|
433
|
+
*
|
|
434
|
+
* // Create a mock federation with contextData
|
|
435
|
+
* const federation = createFederation<{ userId: string }>({
|
|
436
|
+
* contextData: { userId: "test-user" }
|
|
437
|
+
* });
|
|
438
|
+
*
|
|
439
|
+
* // Set up inbox listeners
|
|
440
|
+
* federation
|
|
441
|
+
* .setInboxListeners("/users/{identifier}/inbox")
|
|
442
|
+
* .on(Create, async (ctx, activity) => {
|
|
443
|
+
* console.log("Received:", activity);
|
|
444
|
+
* });
|
|
445
|
+
*
|
|
446
|
+
* // Simulate receiving an activity
|
|
447
|
+
* const createActivity = new Create({
|
|
448
|
+
* id: new URL("https://example.com/create/1"),
|
|
449
|
+
* actor: new URL("https://example.com/users/alice")
|
|
450
|
+
* });
|
|
451
|
+
* await federation.receiveActivity(createActivity);
|
|
452
|
+
*
|
|
453
|
+
* // Check sent activities
|
|
454
|
+
* console.log(federation.sentActivities);
|
|
455
|
+
* ```
|
|
456
|
+
*/
|
|
457
|
+
function createFederation(options = {}) {
|
|
458
|
+
return new MockFederation(options);
|
|
459
|
+
}
|
|
460
|
+
/**
|
|
415
461
|
* A mock implementation of the {@link Context} interface for unit testing.
|
|
416
462
|
* This class provides a way to test Fedify applications without needing
|
|
417
463
|
* a real federation context.
|
|
418
464
|
*
|
|
465
|
+
* Note: This class is not exported from the public API to avoid JSR type
|
|
466
|
+
* analyzer issues. The MockContext class has complex type dependencies that
|
|
467
|
+
* can cause JSR's type analyzer to hang during processing (issue #468).
|
|
468
|
+
* Use {@link MockFederation.createContext}, {@link createContext},
|
|
469
|
+
* {@link createRequestContext}, or {@link createInboxContext} instead.
|
|
470
|
+
*
|
|
419
471
|
* @example
|
|
420
472
|
* ```typescript
|
|
421
|
-
* import { Person, Create } from "@fedify/
|
|
422
|
-
* import {
|
|
473
|
+
* import { Person, Create } from "@fedify/vocab";
|
|
474
|
+
* import { createFederation } from "@fedify/testing";
|
|
423
475
|
*
|
|
424
|
-
* // Create a mock context
|
|
425
|
-
* const
|
|
426
|
-
* const context =
|
|
427
|
-
*
|
|
428
|
-
*
|
|
429
|
-
*
|
|
430
|
-
* });
|
|
476
|
+
* // Create a mock federation and context
|
|
477
|
+
* const federation = createFederation<{ userId: string }>();
|
|
478
|
+
* const context = federation.createContext(
|
|
479
|
+
* new URL("https://example.com"),
|
|
480
|
+
* { userId: "test-user" }
|
|
481
|
+
* );
|
|
431
482
|
*
|
|
432
483
|
* // Send an activity
|
|
433
484
|
* const recipient = new Person({ id: new URL("https://example.com/users/bob") });
|
|
@@ -441,8 +492,8 @@ var MockFederation = class {
|
|
|
441
492
|
* activity
|
|
442
493
|
* );
|
|
443
494
|
*
|
|
444
|
-
* // Check sent activities
|
|
445
|
-
* const sent =
|
|
495
|
+
* // Check sent activities from the federation
|
|
496
|
+
* const sent = federation.sentActivities;
|
|
446
497
|
* console.log(sent[0].activity);
|
|
447
498
|
* ```
|
|
448
499
|
*
|
|
@@ -459,6 +510,8 @@ var MockContext = class MockContext {
|
|
|
459
510
|
documentLoader;
|
|
460
511
|
contextLoader;
|
|
461
512
|
tracerProvider;
|
|
513
|
+
request;
|
|
514
|
+
url;
|
|
462
515
|
sentActivities = [];
|
|
463
516
|
constructor(options) {
|
|
464
517
|
const url = options.url ?? new URL("https://example.com");
|
|
@@ -466,6 +519,8 @@ var MockContext = class MockContext {
|
|
|
466
519
|
this.canonicalOrigin = url.origin;
|
|
467
520
|
this.host = url.host;
|
|
468
521
|
this.hostname = url.hostname;
|
|
522
|
+
this.url = url;
|
|
523
|
+
this.request = new Request(url);
|
|
469
524
|
this.data = options.data;
|
|
470
525
|
this.federation = options.federation;
|
|
471
526
|
this.documentLoader = options.documentLoader ?? (async (url$1) => ({
|
|
@@ -474,11 +529,23 @@ var MockContext = class MockContext {
|
|
|
474
529
|
documentUrl: url$1
|
|
475
530
|
}));
|
|
476
531
|
this.contextLoader = options.contextLoader ?? this.documentLoader;
|
|
477
|
-
this.tracerProvider = options.tracerProvider ??
|
|
532
|
+
this.tracerProvider = options.tracerProvider ?? noopTracerProvider;
|
|
533
|
+
}
|
|
534
|
+
getActor(_handle) {
|
|
535
|
+
return Promise.resolve(null);
|
|
536
|
+
}
|
|
537
|
+
getObject(_cls, _values) {
|
|
538
|
+
return Promise.resolve(null);
|
|
539
|
+
}
|
|
540
|
+
getSignedKey() {
|
|
541
|
+
return Promise.resolve(null);
|
|
542
|
+
}
|
|
543
|
+
getSignedKeyOwner() {
|
|
544
|
+
return Promise.resolve(null);
|
|
478
545
|
}
|
|
479
546
|
clone(data) {
|
|
480
547
|
return new MockContext({
|
|
481
|
-
url:
|
|
548
|
+
url: this.url,
|
|
482
549
|
data,
|
|
483
550
|
federation: this.federation,
|
|
484
551
|
documentLoader: this.documentLoader,
|
|
@@ -660,8 +727,7 @@ var MockContext = class MockContext {
|
|
|
660
727
|
};
|
|
661
728
|
|
|
662
729
|
//#endregion
|
|
663
|
-
exports.MockContext = MockContext;
|
|
664
|
-
exports.MockFederation = MockFederation;
|
|
665
730
|
exports.createContext = createContext;
|
|
731
|
+
exports.createFederation = createFederation;
|
|
666
732
|
exports.createInboxContext = createInboxContext;
|
|
667
733
|
exports.createRequestContext = createRequestContext;
|
package/dist/mod.d.cts
CHANGED
|
@@ -1,12 +1,45 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { DocumentLoader } from "@fedify/fedify/runtime";
|
|
4
|
-
import { Activity, Actor, Collection, Hashtag, LookupObjectOptions, Object as Object$1, Recipient, TraverseCollectionOptions } from "@fedify/fedify/vocab";
|
|
5
|
-
import { ResourceDescriptor } from "@fedify/fedify/webfinger";
|
|
6
|
-
import { TracerProvider } from "@opentelemetry/api";
|
|
1
|
+
import { Context, Federation, InboxContext, RequestContext } from "@fedify/fedify/federation";
|
|
2
|
+
import { Activity } from "@fedify/vocab";
|
|
7
3
|
|
|
4
|
+
//#region src/context.d.ts
|
|
5
|
+
declare function createContext<TContextData>(values: Partial<Context<TContextData>> & {
|
|
6
|
+
url?: URL;
|
|
7
|
+
data: TContextData;
|
|
8
|
+
federation: Federation<TContextData>;
|
|
9
|
+
}): Context<TContextData>;
|
|
10
|
+
/**
|
|
11
|
+
* Creates a RequestContext for testing purposes.
|
|
12
|
+
* Not exported - used internally only. Public API is in mock.ts
|
|
13
|
+
* @param args Partial RequestContext properties
|
|
14
|
+
* @returns A RequestContext instance
|
|
15
|
+
* @since 1.8.0
|
|
16
|
+
*/
|
|
17
|
+
declare function createRequestContext<TContextData>(args: Partial<RequestContext<TContextData>> & {
|
|
18
|
+
url: URL;
|
|
19
|
+
data: TContextData;
|
|
20
|
+
federation: Federation<TContextData>;
|
|
21
|
+
}): RequestContext<TContextData>;
|
|
22
|
+
/**
|
|
23
|
+
* Test-specific InboxContext type alias.
|
|
24
|
+
* This indirection helps avoid JSR type analyzer issues.
|
|
25
|
+
* @since 1.9.1
|
|
26
|
+
*/
|
|
27
|
+
type TestInboxContext<TContextData> = InboxContext<TContextData>;
|
|
28
|
+
/**
|
|
29
|
+
* Creates an InboxContext for testing purposes.
|
|
30
|
+
* Not exported - used internally only. Public API is in mock.ts
|
|
31
|
+
* @param args Partial InboxContext properties
|
|
32
|
+
* @returns An InboxContext instance
|
|
33
|
+
* @since 1.8.0
|
|
34
|
+
*/
|
|
35
|
+
declare function createInboxContext<TContextData>(args: Partial<InboxContext<TContextData>> & {
|
|
36
|
+
url?: URL;
|
|
37
|
+
data: TContextData;
|
|
38
|
+
recipient?: string | null;
|
|
39
|
+
federation: Federation<TContextData>;
|
|
40
|
+
}): TestInboxContext<TContextData>;
|
|
41
|
+
//#endregion
|
|
8
42
|
//#region src/mock.d.ts
|
|
9
|
-
|
|
10
43
|
/**
|
|
11
44
|
* Represents a sent activity with metadata about how it was sent.
|
|
12
45
|
* @since 1.8.0
|
|
@@ -22,17 +55,47 @@ interface SentActivity {
|
|
|
22
55
|
sentOrder: number;
|
|
23
56
|
}
|
|
24
57
|
/**
|
|
25
|
-
* A mock
|
|
26
|
-
*
|
|
27
|
-
*
|
|
58
|
+
* A mock Context interface for testing purposes.
|
|
59
|
+
* Extends the standard Context interface with additional testing utilities.
|
|
60
|
+
* @since 1.9.1
|
|
61
|
+
*/
|
|
62
|
+
interface TestContext<TContextData> extends Omit<Context<TContextData>, "clone">, Pick<RequestContext<TContextData>, "request" | "url" | "getActor" | "getObject" | "getSignedKey" | "getSignedKeyOwner" | "sendActivity" | "routeActivity"> {
|
|
63
|
+
clone(data: TContextData): TestContext<TContextData>;
|
|
64
|
+
getSentActivities(): Array<{
|
|
65
|
+
sender: any;
|
|
66
|
+
recipients: any;
|
|
67
|
+
activity: Activity;
|
|
68
|
+
}>;
|
|
69
|
+
reset(): void;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* A mock Federation interface for testing purposes.
|
|
73
|
+
* Extends the standard Federation interface with additional testing utilities.
|
|
74
|
+
* @since 1.9.1
|
|
75
|
+
*/
|
|
76
|
+
interface TestFederation<TContextData> extends Omit<Federation<TContextData>, "createContext"> {
|
|
77
|
+
sentActivities: SentActivity[];
|
|
78
|
+
queueStarted: boolean;
|
|
79
|
+
sentCounter: number;
|
|
80
|
+
receiveActivity(activity: Activity): Promise<void>;
|
|
81
|
+
reset(): void;
|
|
82
|
+
createContext(baseUrlOrRequest: URL | Request, contextData: TContextData): TestContext<TContextData>;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Creates a mock Federation instance for testing purposes.
|
|
86
|
+
*
|
|
87
|
+
* @template TContextData The type of context data to use
|
|
88
|
+
* @param options Optional configuration for the mock federation
|
|
89
|
+
* @returns A Federation instance that can be used for testing
|
|
90
|
+
* @since 1.9.1
|
|
28
91
|
*
|
|
29
92
|
* @example
|
|
30
93
|
* ```typescript
|
|
31
|
-
* import { Create } from "@fedify/
|
|
32
|
-
* import {
|
|
94
|
+
* import { Create } from "@fedify/vocab";
|
|
95
|
+
* import { createFederation } from "@fedify/testing";
|
|
33
96
|
*
|
|
34
97
|
* // Create a mock federation with contextData
|
|
35
|
-
* const federation =
|
|
98
|
+
* const federation = createFederation<{ userId: string }>({
|
|
36
99
|
* contextData: { userId: "test-user" }
|
|
37
100
|
* });
|
|
38
101
|
*
|
|
@@ -49,249 +112,15 @@ interface SentActivity {
|
|
|
49
112
|
* actor: new URL("https://example.com/users/alice")
|
|
50
113
|
* });
|
|
51
114
|
* await federation.receiveActivity(createActivity);
|
|
52
|
-
* ```
|
|
53
|
-
*
|
|
54
|
-
* @template TContextData The context data to pass to the {@link Context}.
|
|
55
|
-
* @since 1.8.0
|
|
56
|
-
*/
|
|
57
|
-
declare class MockFederation<TContextData> implements Federation<TContextData> {
|
|
58
|
-
private options;
|
|
59
|
-
sentActivities: SentActivity[];
|
|
60
|
-
queueStarted: boolean;
|
|
61
|
-
private activeQueues;
|
|
62
|
-
sentCounter: number;
|
|
63
|
-
private nodeInfoDispatcher?;
|
|
64
|
-
private webFingerDispatcher?;
|
|
65
|
-
private actorDispatchers;
|
|
66
|
-
actorPath?: string;
|
|
67
|
-
inboxPath?: string;
|
|
68
|
-
outboxPath?: string;
|
|
69
|
-
followingPath?: string;
|
|
70
|
-
followersPath?: string;
|
|
71
|
-
likedPath?: string;
|
|
72
|
-
featuredPath?: string;
|
|
73
|
-
featuredTagsPath?: string;
|
|
74
|
-
nodeInfoPath?: string;
|
|
75
|
-
sharedInboxPath?: string;
|
|
76
|
-
objectPaths: Map<string, string>;
|
|
77
|
-
private objectDispatchers;
|
|
78
|
-
private inboxDispatcher?;
|
|
79
|
-
private outboxDispatcher?;
|
|
80
|
-
private followingDispatcher?;
|
|
81
|
-
private followersDispatcher?;
|
|
82
|
-
private likedDispatcher?;
|
|
83
|
-
private featuredDispatcher?;
|
|
84
|
-
private featuredTagsDispatcher?;
|
|
85
|
-
private inboxListeners;
|
|
86
|
-
private contextData?;
|
|
87
|
-
private receivedActivities;
|
|
88
|
-
constructor(options?: {
|
|
89
|
-
contextData?: TContextData;
|
|
90
|
-
origin?: string;
|
|
91
|
-
tracerProvider?: TracerProvider;
|
|
92
|
-
});
|
|
93
|
-
setNodeInfoDispatcher(path: string, dispatcher: NodeInfoDispatcher<TContextData>): void;
|
|
94
|
-
setWebFingerLinksDispatcher(dispatcher: WebFingerLinksDispatcher<TContextData>): void;
|
|
95
|
-
setActorDispatcher(path: `${string}{identifier}${string}` | `${string}{handle}${string}`, dispatcher: ActorDispatcher<TContextData>): ActorCallbackSetters<TContextData>;
|
|
96
|
-
setObjectDispatcher<TObject extends Object$1, TParam extends string>(cls: (new (...args: any[]) => TObject) & {
|
|
97
|
-
typeId: URL;
|
|
98
|
-
}, path: string, dispatcher: ObjectDispatcher<TContextData, TObject, TParam>): ObjectCallbackSetters<TContextData, TObject, TParam>;
|
|
99
|
-
setInboxDispatcher(_path: `${string}{identifier}${string}` | `${string}{handle}${string}`, dispatcher: CollectionDispatcher<Activity, RequestContext<TContextData>, TContextData, void>): CollectionCallbackSetters<RequestContext<TContextData>, TContextData, void>;
|
|
100
|
-
setOutboxDispatcher(path: `${string}{identifier}${string}` | `${string}{handle}${string}`, dispatcher: CollectionDispatcher<Activity, RequestContext<TContextData>, TContextData, void>): CollectionCallbackSetters<RequestContext<TContextData>, TContextData, void>;
|
|
101
|
-
setFollowingDispatcher(path: `${string}{identifier}${string}` | `${string}{handle}${string}`, dispatcher: CollectionDispatcher<Actor | URL, RequestContext<TContextData>, TContextData, void>): CollectionCallbackSetters<RequestContext<TContextData>, TContextData, void>;
|
|
102
|
-
setFollowersDispatcher(path: `${string}{identifier}${string}` | `${string}{handle}${string}`, dispatcher: CollectionDispatcher<Recipient, Context<TContextData>, TContextData, URL>): CollectionCallbackSetters<Context<TContextData>, TContextData, URL>;
|
|
103
|
-
setLikedDispatcher(path: `${string}{identifier}${string}` | `${string}{handle}${string}`, dispatcher: CollectionDispatcher<Object$1 | URL, RequestContext<TContextData>, TContextData, void>): CollectionCallbackSetters<RequestContext<TContextData>, TContextData, void>;
|
|
104
|
-
setFeaturedDispatcher(path: `${string}{identifier}${string}` | `${string}{handle}${string}`, dispatcher: CollectionDispatcher<Object$1, RequestContext<TContextData>, TContextData, void>): CollectionCallbackSetters<RequestContext<TContextData>, TContextData, void>;
|
|
105
|
-
setFeaturedTagsDispatcher(path: `${string}{identifier}${string}` | `${string}{handle}${string}`, dispatcher: CollectionDispatcher<Hashtag, RequestContext<TContextData>, TContextData, void>): CollectionCallbackSetters<RequestContext<TContextData>, TContextData, void>;
|
|
106
|
-
setInboxListeners(inboxPath: `${string}{identifier}${string}` | `${string}{handle}${string}`, sharedInboxPath?: string): InboxListenerSetters<TContextData>;
|
|
107
|
-
startQueue(contextData: TContextData, options?: FederationStartQueueOptions): Promise<void>;
|
|
108
|
-
processQueuedTask(contextData: TContextData, _message: Message): Promise<void>;
|
|
109
|
-
createContext(baseUrl: URL, contextData: TContextData): Context<TContextData>;
|
|
110
|
-
createContext(request: Request, contextData: TContextData): RequestContext<TContextData>;
|
|
111
|
-
fetch(request: Request, options: FederationFetchOptions<TContextData>): Promise<Response>;
|
|
112
|
-
/**
|
|
113
|
-
* Simulates receiving an activity. This method is specific to the mock
|
|
114
|
-
* implementation and is used for testing purposes.
|
|
115
|
-
*
|
|
116
|
-
* @param activity The activity to receive.
|
|
117
|
-
* @returns A promise that resolves when the activity has been processed.
|
|
118
|
-
* @since 1.8.0
|
|
119
|
-
*/
|
|
120
|
-
receiveActivity(activity: Activity): Promise<void>;
|
|
121
|
-
/**
|
|
122
|
-
* Clears all sent activities from the mock federation.
|
|
123
|
-
* This method is specific to the mock implementation and is used for
|
|
124
|
-
* testing purposes.
|
|
125
|
-
*
|
|
126
|
-
* @since 1.8.0
|
|
127
|
-
*/
|
|
128
|
-
reset(): void;
|
|
129
|
-
setCollectionDispatcher<TObject extends Object$1, TParams extends Record<string, string>>(_name: string | symbol, _itemType: any, _path: any, _dispatcher: any): any;
|
|
130
|
-
setOrderedCollectionDispatcher<TObject extends Object$1, TParams extends Record<string, string>>(_name: string | symbol, _itemType: any, _path: any, _dispatcher: any): any;
|
|
131
|
-
}
|
|
132
|
-
/**
|
|
133
|
-
* A mock implementation of the {@link Context} interface for unit testing.
|
|
134
|
-
* This class provides a way to test Fedify applications without needing
|
|
135
|
-
* a real federation context.
|
|
136
|
-
*
|
|
137
|
-
* @example
|
|
138
|
-
* ```typescript
|
|
139
|
-
* import { Person, Create } from "@fedify/fedify/vocab";
|
|
140
|
-
* import { MockContext, MockFederation } from "@fedify/testing";
|
|
141
|
-
*
|
|
142
|
-
* // Create a mock context
|
|
143
|
-
* const mockFederation = new MockFederation<{ userId: string }>();
|
|
144
|
-
* const context = new MockContext({
|
|
145
|
-
* url: new URL("https://example.com"),
|
|
146
|
-
* data: { userId: "test-user" },
|
|
147
|
-
* federation: mockFederation
|
|
148
|
-
* });
|
|
149
|
-
*
|
|
150
|
-
* // Send an activity
|
|
151
|
-
* const recipient = new Person({ id: new URL("https://example.com/users/bob") });
|
|
152
|
-
* const activity = new Create({
|
|
153
|
-
* id: new URL("https://example.com/create/1"),
|
|
154
|
-
* actor: new URL("https://example.com/users/alice")
|
|
155
|
-
* });
|
|
156
|
-
* await context.sendActivity(
|
|
157
|
-
* { identifier: "alice" },
|
|
158
|
-
* recipient,
|
|
159
|
-
* activity
|
|
160
|
-
* );
|
|
161
115
|
*
|
|
162
116
|
* // Check sent activities
|
|
163
|
-
*
|
|
164
|
-
* console.log(sent[0].activity);
|
|
117
|
+
* console.log(federation.sentActivities);
|
|
165
118
|
* ```
|
|
166
|
-
*
|
|
167
|
-
* @template TContextData The context data to pass to the {@link Context}.
|
|
168
|
-
* @since 1.8.0
|
|
169
119
|
*/
|
|
170
|
-
declare
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
readonly data: TContextData;
|
|
176
|
-
readonly federation: Federation<TContextData>;
|
|
177
|
-
readonly documentLoader: DocumentLoader;
|
|
178
|
-
readonly contextLoader: DocumentLoader;
|
|
179
|
-
readonly tracerProvider: TracerProvider;
|
|
180
|
-
private sentActivities;
|
|
181
|
-
constructor(options: {
|
|
182
|
-
url?: URL;
|
|
183
|
-
data: TContextData;
|
|
184
|
-
federation: Federation<TContextData>;
|
|
185
|
-
documentLoader?: DocumentLoader;
|
|
186
|
-
contextLoader?: DocumentLoader;
|
|
187
|
-
tracerProvider?: TracerProvider;
|
|
188
|
-
});
|
|
189
|
-
clone(data: TContextData): Context<TContextData>;
|
|
190
|
-
getNodeInfoUri(): URL;
|
|
191
|
-
getActorUri(identifier: string): URL;
|
|
192
|
-
getObjectUri<TObject extends Object$1>(cls: (new (...args: any[]) => TObject) & {
|
|
193
|
-
typeId: URL;
|
|
194
|
-
}, values: Record<string, string>): URL;
|
|
195
|
-
getOutboxUri(identifier: string): URL;
|
|
196
|
-
getInboxUri(identifier: string): URL;
|
|
197
|
-
getInboxUri(): URL;
|
|
198
|
-
getFollowingUri(identifier: string): URL;
|
|
199
|
-
getFollowersUri(identifier: string): URL;
|
|
200
|
-
getLikedUri(identifier: string): URL;
|
|
201
|
-
getFeaturedUri(identifier: string): URL;
|
|
202
|
-
getFeaturedTagsUri(identifier: string): URL;
|
|
203
|
-
getCollectionUri<TParam extends Record<string, string>>(_name: string | symbol, values: TParam): URL;
|
|
204
|
-
parseUri(uri: URL): ParseUriResult | null;
|
|
205
|
-
getActorKeyPairs(_identifier: string): Promise<ActorKeyPair[]>;
|
|
206
|
-
getDocumentLoader(params: {
|
|
207
|
-
handle: string;
|
|
208
|
-
} | {
|
|
209
|
-
identifier: string;
|
|
210
|
-
}): Promise<DocumentLoader>;
|
|
211
|
-
getDocumentLoader(params: {
|
|
212
|
-
keyId: URL;
|
|
213
|
-
privateKey: CryptoKey;
|
|
214
|
-
}): DocumentLoader;
|
|
215
|
-
lookupObject(_uri: URL | string, _options?: LookupObjectOptions): Promise<Object$1 | null>;
|
|
216
|
-
traverseCollection<TItem, TContext extends Context<TContextData>>(_collection: Collection | URL | null, _options?: TraverseCollectionOptions): AsyncIterable<TItem>;
|
|
217
|
-
lookupNodeInfo(url: URL | string, options?: {
|
|
218
|
-
parse?: "strict" | "best-effort";
|
|
219
|
-
} & any): Promise<NodeInfo | undefined>;
|
|
220
|
-
lookupNodeInfo(url: URL | string, options?: {
|
|
221
|
-
parse: "none";
|
|
222
|
-
} & any): Promise<JsonValue | undefined>;
|
|
223
|
-
lookupWebFinger(_resource: URL | `acct:${string}@${string}` | string, _options?: any): Promise<ResourceDescriptor | null>;
|
|
224
|
-
sendActivity(sender: SenderKeyPair | SenderKeyPair[] | {
|
|
225
|
-
identifier: string;
|
|
226
|
-
} | {
|
|
227
|
-
username: string;
|
|
228
|
-
} | {
|
|
229
|
-
handle: string;
|
|
230
|
-
}, recipients: Recipient | Recipient[], activity: Activity, options?: SendActivityOptions): Promise<void>;
|
|
231
|
-
sendActivity(sender: {
|
|
232
|
-
identifier: string;
|
|
233
|
-
} | {
|
|
234
|
-
username: string;
|
|
235
|
-
} | {
|
|
236
|
-
handle: string;
|
|
237
|
-
}, recipients: "followers", activity: Activity, options?: SendActivityOptionsForCollection): Promise<void>;
|
|
238
|
-
sendActivity(sender: SenderKeyPair | SenderKeyPair[] | {
|
|
239
|
-
identifier: string;
|
|
240
|
-
} | {
|
|
241
|
-
username: string;
|
|
242
|
-
} | {
|
|
243
|
-
handle: string;
|
|
244
|
-
}, recipients: Recipient | Recipient[], activity: Activity, options?: SendActivityOptions): Promise<void>;
|
|
245
|
-
sendActivity(sender: {
|
|
246
|
-
identifier: string;
|
|
247
|
-
} | {
|
|
248
|
-
username: string;
|
|
249
|
-
} | {
|
|
250
|
-
handle: string;
|
|
251
|
-
}, recipients: "followers", activity: Activity, options?: SendActivityOptionsForCollection): Promise<void>;
|
|
252
|
-
routeActivity(_recipient: string | null, _activity: Activity, _options?: RouteActivityOptions): Promise<boolean>;
|
|
253
|
-
/**
|
|
254
|
-
* Gets all activities that have been sent through this mock context.
|
|
255
|
-
* This method is specific to the mock implementation and is used for
|
|
256
|
-
* testing purposes.
|
|
257
|
-
*
|
|
258
|
-
* @returns An array of sent activity records.
|
|
259
|
-
*/
|
|
260
|
-
getSentActivities(): Array<{
|
|
261
|
-
sender: SenderKeyPair | SenderKeyPair[] | {
|
|
262
|
-
identifier: string;
|
|
263
|
-
} | {
|
|
264
|
-
username: string;
|
|
265
|
-
} | {
|
|
266
|
-
handle: string;
|
|
267
|
-
};
|
|
268
|
-
recipients: Recipient | Recipient[] | "followers";
|
|
269
|
-
activity: Activity;
|
|
270
|
-
}>;
|
|
271
|
-
/**
|
|
272
|
-
* Clears all sent activities from the mock context.
|
|
273
|
-
* This method is specific to the mock implementation and is used for
|
|
274
|
-
* testing purposes.
|
|
275
|
-
*/
|
|
276
|
-
reset(): void;
|
|
277
|
-
}
|
|
278
|
-
//#endregion
|
|
279
|
-
//#region src/context.d.ts
|
|
280
|
-
declare function createContext<TContextData>(values: Partial<Context<TContextData>> & {
|
|
281
|
-
url?: URL;
|
|
282
|
-
data: TContextData;
|
|
283
|
-
federation: Federation<TContextData>;
|
|
284
|
-
}): Context<TContextData>;
|
|
285
|
-
declare function createRequestContext<TContextData>(args: Partial<RequestContext<TContextData>> & {
|
|
286
|
-
url: URL;
|
|
287
|
-
data: TContextData;
|
|
288
|
-
federation: Federation<TContextData>;
|
|
289
|
-
}): RequestContext<TContextData>;
|
|
290
|
-
declare function createInboxContext<TContextData>(args: Partial<InboxContext<TContextData>> & {
|
|
291
|
-
url?: URL;
|
|
292
|
-
data: TContextData;
|
|
293
|
-
recipient?: string | null;
|
|
294
|
-
federation: Federation<TContextData>;
|
|
295
|
-
}): InboxContext<TContextData>;
|
|
120
|
+
declare function createFederation<TContextData>(options?: {
|
|
121
|
+
contextData?: TContextData;
|
|
122
|
+
origin?: string;
|
|
123
|
+
tracerProvider?: any;
|
|
124
|
+
}): TestFederation<TContextData>;
|
|
296
125
|
//#endregion
|
|
297
|
-
export {
|
|
126
|
+
export { createContext, createFederation, createInboxContext, createRequestContext };
|
package/dist/mod.d.ts
CHANGED
|
@@ -1,12 +1,45 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { Activity, Actor, Collection, Hashtag, LookupObjectOptions, Object as Object$1, Recipient, TraverseCollectionOptions } from "@fedify/fedify/vocab";
|
|
4
|
-
import { ResourceDescriptor } from "@fedify/fedify/webfinger";
|
|
5
|
-
import { JsonValue, NodeInfo } from "@fedify/fedify/nodeinfo";
|
|
6
|
-
import { DocumentLoader } from "@fedify/fedify/runtime";
|
|
1
|
+
import { Context, Federation, InboxContext, RequestContext } from "@fedify/fedify/federation";
|
|
2
|
+
import { Activity } from "@fedify/vocab";
|
|
7
3
|
|
|
4
|
+
//#region src/context.d.ts
|
|
5
|
+
declare function createContext<TContextData>(values: Partial<Context<TContextData>> & {
|
|
6
|
+
url?: URL;
|
|
7
|
+
data: TContextData;
|
|
8
|
+
federation: Federation<TContextData>;
|
|
9
|
+
}): Context<TContextData>;
|
|
10
|
+
/**
|
|
11
|
+
* Creates a RequestContext for testing purposes.
|
|
12
|
+
* Not exported - used internally only. Public API is in mock.ts
|
|
13
|
+
* @param args Partial RequestContext properties
|
|
14
|
+
* @returns A RequestContext instance
|
|
15
|
+
* @since 1.8.0
|
|
16
|
+
*/
|
|
17
|
+
declare function createRequestContext<TContextData>(args: Partial<RequestContext<TContextData>> & {
|
|
18
|
+
url: URL;
|
|
19
|
+
data: TContextData;
|
|
20
|
+
federation: Federation<TContextData>;
|
|
21
|
+
}): RequestContext<TContextData>;
|
|
22
|
+
/**
|
|
23
|
+
* Test-specific InboxContext type alias.
|
|
24
|
+
* This indirection helps avoid JSR type analyzer issues.
|
|
25
|
+
* @since 1.9.1
|
|
26
|
+
*/
|
|
27
|
+
type TestInboxContext<TContextData> = InboxContext<TContextData>;
|
|
28
|
+
/**
|
|
29
|
+
* Creates an InboxContext for testing purposes.
|
|
30
|
+
* Not exported - used internally only. Public API is in mock.ts
|
|
31
|
+
* @param args Partial InboxContext properties
|
|
32
|
+
* @returns An InboxContext instance
|
|
33
|
+
* @since 1.8.0
|
|
34
|
+
*/
|
|
35
|
+
declare function createInboxContext<TContextData>(args: Partial<InboxContext<TContextData>> & {
|
|
36
|
+
url?: URL;
|
|
37
|
+
data: TContextData;
|
|
38
|
+
recipient?: string | null;
|
|
39
|
+
federation: Federation<TContextData>;
|
|
40
|
+
}): TestInboxContext<TContextData>;
|
|
41
|
+
//#endregion
|
|
8
42
|
//#region src/mock.d.ts
|
|
9
|
-
|
|
10
43
|
/**
|
|
11
44
|
* Represents a sent activity with metadata about how it was sent.
|
|
12
45
|
* @since 1.8.0
|
|
@@ -22,17 +55,47 @@ interface SentActivity {
|
|
|
22
55
|
sentOrder: number;
|
|
23
56
|
}
|
|
24
57
|
/**
|
|
25
|
-
* A mock
|
|
26
|
-
*
|
|
27
|
-
*
|
|
58
|
+
* A mock Context interface for testing purposes.
|
|
59
|
+
* Extends the standard Context interface with additional testing utilities.
|
|
60
|
+
* @since 1.9.1
|
|
61
|
+
*/
|
|
62
|
+
interface TestContext<TContextData> extends Omit<Context<TContextData>, "clone">, Pick<RequestContext<TContextData>, "request" | "url" | "getActor" | "getObject" | "getSignedKey" | "getSignedKeyOwner" | "sendActivity" | "routeActivity"> {
|
|
63
|
+
clone(data: TContextData): TestContext<TContextData>;
|
|
64
|
+
getSentActivities(): Array<{
|
|
65
|
+
sender: any;
|
|
66
|
+
recipients: any;
|
|
67
|
+
activity: Activity;
|
|
68
|
+
}>;
|
|
69
|
+
reset(): void;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* A mock Federation interface for testing purposes.
|
|
73
|
+
* Extends the standard Federation interface with additional testing utilities.
|
|
74
|
+
* @since 1.9.1
|
|
75
|
+
*/
|
|
76
|
+
interface TestFederation<TContextData> extends Omit<Federation<TContextData>, "createContext"> {
|
|
77
|
+
sentActivities: SentActivity[];
|
|
78
|
+
queueStarted: boolean;
|
|
79
|
+
sentCounter: number;
|
|
80
|
+
receiveActivity(activity: Activity): Promise<void>;
|
|
81
|
+
reset(): void;
|
|
82
|
+
createContext(baseUrlOrRequest: URL | Request, contextData: TContextData): TestContext<TContextData>;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Creates a mock Federation instance for testing purposes.
|
|
86
|
+
*
|
|
87
|
+
* @template TContextData The type of context data to use
|
|
88
|
+
* @param options Optional configuration for the mock federation
|
|
89
|
+
* @returns A Federation instance that can be used for testing
|
|
90
|
+
* @since 1.9.1
|
|
28
91
|
*
|
|
29
92
|
* @example
|
|
30
93
|
* ```typescript
|
|
31
|
-
* import { Create } from "@fedify/
|
|
32
|
-
* import {
|
|
94
|
+
* import { Create } from "@fedify/vocab";
|
|
95
|
+
* import { createFederation } from "@fedify/testing";
|
|
33
96
|
*
|
|
34
97
|
* // Create a mock federation with contextData
|
|
35
|
-
* const federation =
|
|
98
|
+
* const federation = createFederation<{ userId: string }>({
|
|
36
99
|
* contextData: { userId: "test-user" }
|
|
37
100
|
* });
|
|
38
101
|
*
|
|
@@ -49,249 +112,15 @@ interface SentActivity {
|
|
|
49
112
|
* actor: new URL("https://example.com/users/alice")
|
|
50
113
|
* });
|
|
51
114
|
* await federation.receiveActivity(createActivity);
|
|
52
|
-
* ```
|
|
53
|
-
*
|
|
54
|
-
* @template TContextData The context data to pass to the {@link Context}.
|
|
55
|
-
* @since 1.8.0
|
|
56
|
-
*/
|
|
57
|
-
declare class MockFederation<TContextData> implements Federation<TContextData> {
|
|
58
|
-
private options;
|
|
59
|
-
sentActivities: SentActivity[];
|
|
60
|
-
queueStarted: boolean;
|
|
61
|
-
private activeQueues;
|
|
62
|
-
sentCounter: number;
|
|
63
|
-
private nodeInfoDispatcher?;
|
|
64
|
-
private webFingerDispatcher?;
|
|
65
|
-
private actorDispatchers;
|
|
66
|
-
actorPath?: string;
|
|
67
|
-
inboxPath?: string;
|
|
68
|
-
outboxPath?: string;
|
|
69
|
-
followingPath?: string;
|
|
70
|
-
followersPath?: string;
|
|
71
|
-
likedPath?: string;
|
|
72
|
-
featuredPath?: string;
|
|
73
|
-
featuredTagsPath?: string;
|
|
74
|
-
nodeInfoPath?: string;
|
|
75
|
-
sharedInboxPath?: string;
|
|
76
|
-
objectPaths: Map<string, string>;
|
|
77
|
-
private objectDispatchers;
|
|
78
|
-
private inboxDispatcher?;
|
|
79
|
-
private outboxDispatcher?;
|
|
80
|
-
private followingDispatcher?;
|
|
81
|
-
private followersDispatcher?;
|
|
82
|
-
private likedDispatcher?;
|
|
83
|
-
private featuredDispatcher?;
|
|
84
|
-
private featuredTagsDispatcher?;
|
|
85
|
-
private inboxListeners;
|
|
86
|
-
private contextData?;
|
|
87
|
-
private receivedActivities;
|
|
88
|
-
constructor(options?: {
|
|
89
|
-
contextData?: TContextData;
|
|
90
|
-
origin?: string;
|
|
91
|
-
tracerProvider?: TracerProvider;
|
|
92
|
-
});
|
|
93
|
-
setNodeInfoDispatcher(path: string, dispatcher: NodeInfoDispatcher<TContextData>): void;
|
|
94
|
-
setWebFingerLinksDispatcher(dispatcher: WebFingerLinksDispatcher<TContextData>): void;
|
|
95
|
-
setActorDispatcher(path: `${string}{identifier}${string}` | `${string}{handle}${string}`, dispatcher: ActorDispatcher<TContextData>): ActorCallbackSetters<TContextData>;
|
|
96
|
-
setObjectDispatcher<TObject extends Object$1, TParam extends string>(cls: (new (...args: any[]) => TObject) & {
|
|
97
|
-
typeId: URL;
|
|
98
|
-
}, path: string, dispatcher: ObjectDispatcher<TContextData, TObject, TParam>): ObjectCallbackSetters<TContextData, TObject, TParam>;
|
|
99
|
-
setInboxDispatcher(_path: `${string}{identifier}${string}` | `${string}{handle}${string}`, dispatcher: CollectionDispatcher<Activity, RequestContext<TContextData>, TContextData, void>): CollectionCallbackSetters<RequestContext<TContextData>, TContextData, void>;
|
|
100
|
-
setOutboxDispatcher(path: `${string}{identifier}${string}` | `${string}{handle}${string}`, dispatcher: CollectionDispatcher<Activity, RequestContext<TContextData>, TContextData, void>): CollectionCallbackSetters<RequestContext<TContextData>, TContextData, void>;
|
|
101
|
-
setFollowingDispatcher(path: `${string}{identifier}${string}` | `${string}{handle}${string}`, dispatcher: CollectionDispatcher<Actor | URL, RequestContext<TContextData>, TContextData, void>): CollectionCallbackSetters<RequestContext<TContextData>, TContextData, void>;
|
|
102
|
-
setFollowersDispatcher(path: `${string}{identifier}${string}` | `${string}{handle}${string}`, dispatcher: CollectionDispatcher<Recipient, Context<TContextData>, TContextData, URL>): CollectionCallbackSetters<Context<TContextData>, TContextData, URL>;
|
|
103
|
-
setLikedDispatcher(path: `${string}{identifier}${string}` | `${string}{handle}${string}`, dispatcher: CollectionDispatcher<Object$1 | URL, RequestContext<TContextData>, TContextData, void>): CollectionCallbackSetters<RequestContext<TContextData>, TContextData, void>;
|
|
104
|
-
setFeaturedDispatcher(path: `${string}{identifier}${string}` | `${string}{handle}${string}`, dispatcher: CollectionDispatcher<Object$1, RequestContext<TContextData>, TContextData, void>): CollectionCallbackSetters<RequestContext<TContextData>, TContextData, void>;
|
|
105
|
-
setFeaturedTagsDispatcher(path: `${string}{identifier}${string}` | `${string}{handle}${string}`, dispatcher: CollectionDispatcher<Hashtag, RequestContext<TContextData>, TContextData, void>): CollectionCallbackSetters<RequestContext<TContextData>, TContextData, void>;
|
|
106
|
-
setInboxListeners(inboxPath: `${string}{identifier}${string}` | `${string}{handle}${string}`, sharedInboxPath?: string): InboxListenerSetters<TContextData>;
|
|
107
|
-
startQueue(contextData: TContextData, options?: FederationStartQueueOptions): Promise<void>;
|
|
108
|
-
processQueuedTask(contextData: TContextData, _message: Message): Promise<void>;
|
|
109
|
-
createContext(baseUrl: URL, contextData: TContextData): Context<TContextData>;
|
|
110
|
-
createContext(request: Request, contextData: TContextData): RequestContext<TContextData>;
|
|
111
|
-
fetch(request: Request, options: FederationFetchOptions<TContextData>): Promise<Response>;
|
|
112
|
-
/**
|
|
113
|
-
* Simulates receiving an activity. This method is specific to the mock
|
|
114
|
-
* implementation and is used for testing purposes.
|
|
115
|
-
*
|
|
116
|
-
* @param activity The activity to receive.
|
|
117
|
-
* @returns A promise that resolves when the activity has been processed.
|
|
118
|
-
* @since 1.8.0
|
|
119
|
-
*/
|
|
120
|
-
receiveActivity(activity: Activity): Promise<void>;
|
|
121
|
-
/**
|
|
122
|
-
* Clears all sent activities from the mock federation.
|
|
123
|
-
* This method is specific to the mock implementation and is used for
|
|
124
|
-
* testing purposes.
|
|
125
|
-
*
|
|
126
|
-
* @since 1.8.0
|
|
127
|
-
*/
|
|
128
|
-
reset(): void;
|
|
129
|
-
setCollectionDispatcher<TObject extends Object$1, TParams extends Record<string, string>>(_name: string | symbol, _itemType: any, _path: any, _dispatcher: any): any;
|
|
130
|
-
setOrderedCollectionDispatcher<TObject extends Object$1, TParams extends Record<string, string>>(_name: string | symbol, _itemType: any, _path: any, _dispatcher: any): any;
|
|
131
|
-
}
|
|
132
|
-
/**
|
|
133
|
-
* A mock implementation of the {@link Context} interface for unit testing.
|
|
134
|
-
* This class provides a way to test Fedify applications without needing
|
|
135
|
-
* a real federation context.
|
|
136
|
-
*
|
|
137
|
-
* @example
|
|
138
|
-
* ```typescript
|
|
139
|
-
* import { Person, Create } from "@fedify/fedify/vocab";
|
|
140
|
-
* import { MockContext, MockFederation } from "@fedify/testing";
|
|
141
|
-
*
|
|
142
|
-
* // Create a mock context
|
|
143
|
-
* const mockFederation = new MockFederation<{ userId: string }>();
|
|
144
|
-
* const context = new MockContext({
|
|
145
|
-
* url: new URL("https://example.com"),
|
|
146
|
-
* data: { userId: "test-user" },
|
|
147
|
-
* federation: mockFederation
|
|
148
|
-
* });
|
|
149
|
-
*
|
|
150
|
-
* // Send an activity
|
|
151
|
-
* const recipient = new Person({ id: new URL("https://example.com/users/bob") });
|
|
152
|
-
* const activity = new Create({
|
|
153
|
-
* id: new URL("https://example.com/create/1"),
|
|
154
|
-
* actor: new URL("https://example.com/users/alice")
|
|
155
|
-
* });
|
|
156
|
-
* await context.sendActivity(
|
|
157
|
-
* { identifier: "alice" },
|
|
158
|
-
* recipient,
|
|
159
|
-
* activity
|
|
160
|
-
* );
|
|
161
115
|
*
|
|
162
116
|
* // Check sent activities
|
|
163
|
-
*
|
|
164
|
-
* console.log(sent[0].activity);
|
|
117
|
+
* console.log(federation.sentActivities);
|
|
165
118
|
* ```
|
|
166
|
-
*
|
|
167
|
-
* @template TContextData The context data to pass to the {@link Context}.
|
|
168
|
-
* @since 1.8.0
|
|
169
119
|
*/
|
|
170
|
-
declare
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
readonly data: TContextData;
|
|
176
|
-
readonly federation: Federation<TContextData>;
|
|
177
|
-
readonly documentLoader: DocumentLoader;
|
|
178
|
-
readonly contextLoader: DocumentLoader;
|
|
179
|
-
readonly tracerProvider: TracerProvider;
|
|
180
|
-
private sentActivities;
|
|
181
|
-
constructor(options: {
|
|
182
|
-
url?: URL;
|
|
183
|
-
data: TContextData;
|
|
184
|
-
federation: Federation<TContextData>;
|
|
185
|
-
documentLoader?: DocumentLoader;
|
|
186
|
-
contextLoader?: DocumentLoader;
|
|
187
|
-
tracerProvider?: TracerProvider;
|
|
188
|
-
});
|
|
189
|
-
clone(data: TContextData): Context<TContextData>;
|
|
190
|
-
getNodeInfoUri(): URL;
|
|
191
|
-
getActorUri(identifier: string): URL;
|
|
192
|
-
getObjectUri<TObject extends Object$1>(cls: (new (...args: any[]) => TObject) & {
|
|
193
|
-
typeId: URL;
|
|
194
|
-
}, values: Record<string, string>): URL;
|
|
195
|
-
getOutboxUri(identifier: string): URL;
|
|
196
|
-
getInboxUri(identifier: string): URL;
|
|
197
|
-
getInboxUri(): URL;
|
|
198
|
-
getFollowingUri(identifier: string): URL;
|
|
199
|
-
getFollowersUri(identifier: string): URL;
|
|
200
|
-
getLikedUri(identifier: string): URL;
|
|
201
|
-
getFeaturedUri(identifier: string): URL;
|
|
202
|
-
getFeaturedTagsUri(identifier: string): URL;
|
|
203
|
-
getCollectionUri<TParam extends Record<string, string>>(_name: string | symbol, values: TParam): URL;
|
|
204
|
-
parseUri(uri: URL): ParseUriResult | null;
|
|
205
|
-
getActorKeyPairs(_identifier: string): Promise<ActorKeyPair[]>;
|
|
206
|
-
getDocumentLoader(params: {
|
|
207
|
-
handle: string;
|
|
208
|
-
} | {
|
|
209
|
-
identifier: string;
|
|
210
|
-
}): Promise<DocumentLoader>;
|
|
211
|
-
getDocumentLoader(params: {
|
|
212
|
-
keyId: URL;
|
|
213
|
-
privateKey: CryptoKey;
|
|
214
|
-
}): DocumentLoader;
|
|
215
|
-
lookupObject(_uri: URL | string, _options?: LookupObjectOptions): Promise<Object$1 | null>;
|
|
216
|
-
traverseCollection<TItem, TContext extends Context<TContextData>>(_collection: Collection | URL | null, _options?: TraverseCollectionOptions): AsyncIterable<TItem>;
|
|
217
|
-
lookupNodeInfo(url: URL | string, options?: {
|
|
218
|
-
parse?: "strict" | "best-effort";
|
|
219
|
-
} & any): Promise<NodeInfo | undefined>;
|
|
220
|
-
lookupNodeInfo(url: URL | string, options?: {
|
|
221
|
-
parse: "none";
|
|
222
|
-
} & any): Promise<JsonValue | undefined>;
|
|
223
|
-
lookupWebFinger(_resource: URL | `acct:${string}@${string}` | string, _options?: any): Promise<ResourceDescriptor | null>;
|
|
224
|
-
sendActivity(sender: SenderKeyPair | SenderKeyPair[] | {
|
|
225
|
-
identifier: string;
|
|
226
|
-
} | {
|
|
227
|
-
username: string;
|
|
228
|
-
} | {
|
|
229
|
-
handle: string;
|
|
230
|
-
}, recipients: Recipient | Recipient[], activity: Activity, options?: SendActivityOptions): Promise<void>;
|
|
231
|
-
sendActivity(sender: {
|
|
232
|
-
identifier: string;
|
|
233
|
-
} | {
|
|
234
|
-
username: string;
|
|
235
|
-
} | {
|
|
236
|
-
handle: string;
|
|
237
|
-
}, recipients: "followers", activity: Activity, options?: SendActivityOptionsForCollection): Promise<void>;
|
|
238
|
-
sendActivity(sender: SenderKeyPair | SenderKeyPair[] | {
|
|
239
|
-
identifier: string;
|
|
240
|
-
} | {
|
|
241
|
-
username: string;
|
|
242
|
-
} | {
|
|
243
|
-
handle: string;
|
|
244
|
-
}, recipients: Recipient | Recipient[], activity: Activity, options?: SendActivityOptions): Promise<void>;
|
|
245
|
-
sendActivity(sender: {
|
|
246
|
-
identifier: string;
|
|
247
|
-
} | {
|
|
248
|
-
username: string;
|
|
249
|
-
} | {
|
|
250
|
-
handle: string;
|
|
251
|
-
}, recipients: "followers", activity: Activity, options?: SendActivityOptionsForCollection): Promise<void>;
|
|
252
|
-
routeActivity(_recipient: string | null, _activity: Activity, _options?: RouteActivityOptions): Promise<boolean>;
|
|
253
|
-
/**
|
|
254
|
-
* Gets all activities that have been sent through this mock context.
|
|
255
|
-
* This method is specific to the mock implementation and is used for
|
|
256
|
-
* testing purposes.
|
|
257
|
-
*
|
|
258
|
-
* @returns An array of sent activity records.
|
|
259
|
-
*/
|
|
260
|
-
getSentActivities(): Array<{
|
|
261
|
-
sender: SenderKeyPair | SenderKeyPair[] | {
|
|
262
|
-
identifier: string;
|
|
263
|
-
} | {
|
|
264
|
-
username: string;
|
|
265
|
-
} | {
|
|
266
|
-
handle: string;
|
|
267
|
-
};
|
|
268
|
-
recipients: Recipient | Recipient[] | "followers";
|
|
269
|
-
activity: Activity;
|
|
270
|
-
}>;
|
|
271
|
-
/**
|
|
272
|
-
* Clears all sent activities from the mock context.
|
|
273
|
-
* This method is specific to the mock implementation and is used for
|
|
274
|
-
* testing purposes.
|
|
275
|
-
*/
|
|
276
|
-
reset(): void;
|
|
277
|
-
}
|
|
278
|
-
//#endregion
|
|
279
|
-
//#region src/context.d.ts
|
|
280
|
-
declare function createContext<TContextData>(values: Partial<Context<TContextData>> & {
|
|
281
|
-
url?: URL;
|
|
282
|
-
data: TContextData;
|
|
283
|
-
federation: Federation<TContextData>;
|
|
284
|
-
}): Context<TContextData>;
|
|
285
|
-
declare function createRequestContext<TContextData>(args: Partial<RequestContext<TContextData>> & {
|
|
286
|
-
url: URL;
|
|
287
|
-
data: TContextData;
|
|
288
|
-
federation: Federation<TContextData>;
|
|
289
|
-
}): RequestContext<TContextData>;
|
|
290
|
-
declare function createInboxContext<TContextData>(args: Partial<InboxContext<TContextData>> & {
|
|
291
|
-
url?: URL;
|
|
292
|
-
data: TContextData;
|
|
293
|
-
recipient?: string | null;
|
|
294
|
-
federation: Federation<TContextData>;
|
|
295
|
-
}): InboxContext<TContextData>;
|
|
120
|
+
declare function createFederation<TContextData>(options?: {
|
|
121
|
+
contextData?: TContextData;
|
|
122
|
+
origin?: string;
|
|
123
|
+
tracerProvider?: any;
|
|
124
|
+
}): TestFederation<TContextData>;
|
|
296
125
|
//#endregion
|
|
297
|
-
export {
|
|
126
|
+
export { createContext, createFederation, createInboxContext, createRequestContext };
|
package/dist/mod.js
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
|
-
import { trace } from "@opentelemetry/api";
|
|
2
1
|
import { RouterError } from "@fedify/fedify/federation";
|
|
3
|
-
import { lookupObject, traverseCollection } from "@fedify/
|
|
4
|
-
import { lookupWebFinger } from "@fedify/fedify/webfinger";
|
|
2
|
+
import { lookupObject, traverseCollection } from "@fedify/vocab";
|
|
5
3
|
|
|
6
4
|
//#region src/docloader.ts
|
|
7
5
|
const mockDocumentLoader = async (url) => ({
|
|
@@ -12,8 +10,12 @@ const mockDocumentLoader = async (url) => ({
|
|
|
12
10
|
|
|
13
11
|
//#endregion
|
|
14
12
|
//#region src/context.ts
|
|
13
|
+
const noopTracerProvider$1 = { getTracer: () => ({
|
|
14
|
+
startActiveSpan: () => void 0,
|
|
15
|
+
startSpan: () => void 0
|
|
16
|
+
}) };
|
|
15
17
|
function createContext(values) {
|
|
16
|
-
const { federation, url = new URL("http://example.com/"), canonicalOrigin, data, documentLoader, contextLoader, tracerProvider, clone, getNodeInfoUri, getActorUri, getObjectUri, getCollectionUri, getOutboxUri, getInboxUri, getFollowingUri, getFollowersUri, getLikedUri, getFeaturedUri, getFeaturedTagsUri, parseUri, getActorKeyPairs, getDocumentLoader, lookupObject: lookupObject$1, traverseCollection: traverseCollection$1, lookupNodeInfo, lookupWebFinger
|
|
18
|
+
const { federation, url = new URL("http://example.com/"), canonicalOrigin, data, documentLoader, contextLoader, tracerProvider, clone, getNodeInfoUri, getActorUri, getObjectUri, getCollectionUri, getOutboxUri, getInboxUri, getFollowingUri, getFollowersUri, getLikedUri, getFeaturedUri, getFeaturedTagsUri, parseUri, getActorKeyPairs, getDocumentLoader, lookupObject: lookupObject$1, traverseCollection: traverseCollection$1, lookupNodeInfo, lookupWebFinger, sendActivity, routeActivity } = values;
|
|
17
19
|
function throwRouteError() {
|
|
18
20
|
throw new RouterError("Not implemented");
|
|
19
21
|
}
|
|
@@ -26,7 +28,7 @@ function createContext(values) {
|
|
|
26
28
|
hostname: url.hostname,
|
|
27
29
|
documentLoader: documentLoader ?? mockDocumentLoader,
|
|
28
30
|
contextLoader: contextLoader ?? mockDocumentLoader,
|
|
29
|
-
tracerProvider: tracerProvider ??
|
|
31
|
+
tracerProvider: tracerProvider ?? noopTracerProvider$1,
|
|
30
32
|
clone: clone ?? ((data$1) => createContext({
|
|
31
33
|
...values,
|
|
32
34
|
data: data$1
|
|
@@ -64,8 +66,8 @@ function createContext(values) {
|
|
|
64
66
|
lookupNodeInfo: lookupNodeInfo ?? ((_params) => {
|
|
65
67
|
throw new Error("Not implemented");
|
|
66
68
|
}),
|
|
67
|
-
lookupWebFinger: lookupWebFinger
|
|
68
|
-
return
|
|
69
|
+
lookupWebFinger: lookupWebFinger ?? ((_resource, _options = {}) => {
|
|
70
|
+
return Promise.resolve(null);
|
|
69
71
|
}),
|
|
70
72
|
sendActivity: sendActivity ?? ((_params) => {
|
|
71
73
|
throw new Error("Not implemented");
|
|
@@ -75,6 +77,13 @@ function createContext(values) {
|
|
|
75
77
|
})
|
|
76
78
|
};
|
|
77
79
|
}
|
|
80
|
+
/**
|
|
81
|
+
* Creates a RequestContext for testing purposes.
|
|
82
|
+
* Not exported - used internally only. Public API is in mock.ts
|
|
83
|
+
* @param args Partial RequestContext properties
|
|
84
|
+
* @returns A RequestContext instance
|
|
85
|
+
* @since 1.8.0
|
|
86
|
+
*/
|
|
78
87
|
function createRequestContext(args) {
|
|
79
88
|
return {
|
|
80
89
|
...createContext(args),
|
|
@@ -93,6 +102,13 @@ function createRequestContext(args) {
|
|
|
93
102
|
})
|
|
94
103
|
};
|
|
95
104
|
}
|
|
105
|
+
/**
|
|
106
|
+
* Creates an InboxContext for testing purposes.
|
|
107
|
+
* Not exported - used internally only. Public API is in mock.ts
|
|
108
|
+
* @param args Partial InboxContext properties
|
|
109
|
+
* @returns An InboxContext instance
|
|
110
|
+
* @since 1.8.0
|
|
111
|
+
*/
|
|
96
112
|
function createInboxContext(args) {
|
|
97
113
|
return {
|
|
98
114
|
...createContext(args),
|
|
@@ -109,6 +125,10 @@ function createInboxContext(args) {
|
|
|
109
125
|
|
|
110
126
|
//#endregion
|
|
111
127
|
//#region src/mock.ts
|
|
128
|
+
const noopTracerProvider = { getTracer: () => ({
|
|
129
|
+
startActiveSpan: () => void 0,
|
|
130
|
+
startSpan: () => void 0
|
|
131
|
+
}) };
|
|
112
132
|
/**
|
|
113
133
|
* Helper function to expand URI templates with values.
|
|
114
134
|
* Supports simple placeholders like {identifier}, {handle}, etc.
|
|
@@ -128,18 +148,18 @@ function expandUriTemplate(template, values) {
|
|
|
128
148
|
*
|
|
129
149
|
* @example
|
|
130
150
|
* ```typescript
|
|
131
|
-
* import { Create } from "@fedify/
|
|
132
|
-
* import {
|
|
151
|
+
* import { Create } from "@fedify/vocab";
|
|
152
|
+
* import { createFederation } from "@fedify/testing";
|
|
133
153
|
*
|
|
134
154
|
* // Create a mock federation with contextData
|
|
135
|
-
* const federation =
|
|
155
|
+
* const federation = createFederation<{ userId: string }>({
|
|
136
156
|
* contextData: { userId: "test-user" }
|
|
137
157
|
* });
|
|
138
158
|
*
|
|
139
159
|
* // Set up inbox listeners
|
|
140
160
|
* federation
|
|
141
161
|
* .setInboxListeners("/users/{identifier}/inbox")
|
|
142
|
-
* .on(Create, async (ctx, activity) => {
|
|
162
|
+
* .on(Create, async (ctx: any, activity: any) => {
|
|
143
163
|
* console.log("Received:", activity);
|
|
144
164
|
* });
|
|
145
165
|
*
|
|
@@ -316,22 +336,9 @@ var MockFederation = class {
|
|
|
316
336
|
}
|
|
317
337
|
createContext(baseUrlOrRequest, contextData) {
|
|
318
338
|
const mockFederation = this;
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
data: contextData,
|
|
323
|
-
federation: mockFederation,
|
|
324
|
-
sendActivity: async (sender, recipients, activity, options) => {
|
|
325
|
-
const tempContext = new MockContext({
|
|
326
|
-
url: new URL(baseUrlOrRequest.url),
|
|
327
|
-
data: contextData,
|
|
328
|
-
federation: mockFederation
|
|
329
|
-
});
|
|
330
|
-
await tempContext.sendActivity(sender, recipients, activity, options);
|
|
331
|
-
}
|
|
332
|
-
});
|
|
333
|
-
else return new MockContext({
|
|
334
|
-
url: baseUrlOrRequest,
|
|
339
|
+
const url = baseUrlOrRequest instanceof Request ? new URL(baseUrlOrRequest.url) : baseUrlOrRequest;
|
|
340
|
+
return new MockContext({
|
|
341
|
+
url,
|
|
335
342
|
data: contextData,
|
|
336
343
|
federation: mockFederation
|
|
337
344
|
});
|
|
@@ -389,22 +396,66 @@ var MockFederation = class {
|
|
|
389
396
|
}
|
|
390
397
|
};
|
|
391
398
|
/**
|
|
399
|
+
* Creates a mock Federation instance for testing purposes.
|
|
400
|
+
*
|
|
401
|
+
* @template TContextData The type of context data to use
|
|
402
|
+
* @param options Optional configuration for the mock federation
|
|
403
|
+
* @returns A Federation instance that can be used for testing
|
|
404
|
+
* @since 1.9.1
|
|
405
|
+
*
|
|
406
|
+
* @example
|
|
407
|
+
* ```typescript
|
|
408
|
+
* import { Create } from "@fedify/vocab";
|
|
409
|
+
* import { createFederation } from "@fedify/testing";
|
|
410
|
+
*
|
|
411
|
+
* // Create a mock federation with contextData
|
|
412
|
+
* const federation = createFederation<{ userId: string }>({
|
|
413
|
+
* contextData: { userId: "test-user" }
|
|
414
|
+
* });
|
|
415
|
+
*
|
|
416
|
+
* // Set up inbox listeners
|
|
417
|
+
* federation
|
|
418
|
+
* .setInboxListeners("/users/{identifier}/inbox")
|
|
419
|
+
* .on(Create, async (ctx, activity) => {
|
|
420
|
+
* console.log("Received:", activity);
|
|
421
|
+
* });
|
|
422
|
+
*
|
|
423
|
+
* // Simulate receiving an activity
|
|
424
|
+
* const createActivity = new Create({
|
|
425
|
+
* id: new URL("https://example.com/create/1"),
|
|
426
|
+
* actor: new URL("https://example.com/users/alice")
|
|
427
|
+
* });
|
|
428
|
+
* await federation.receiveActivity(createActivity);
|
|
429
|
+
*
|
|
430
|
+
* // Check sent activities
|
|
431
|
+
* console.log(federation.sentActivities);
|
|
432
|
+
* ```
|
|
433
|
+
*/
|
|
434
|
+
function createFederation(options = {}) {
|
|
435
|
+
return new MockFederation(options);
|
|
436
|
+
}
|
|
437
|
+
/**
|
|
392
438
|
* A mock implementation of the {@link Context} interface for unit testing.
|
|
393
439
|
* This class provides a way to test Fedify applications without needing
|
|
394
440
|
* a real federation context.
|
|
395
441
|
*
|
|
442
|
+
* Note: This class is not exported from the public API to avoid JSR type
|
|
443
|
+
* analyzer issues. The MockContext class has complex type dependencies that
|
|
444
|
+
* can cause JSR's type analyzer to hang during processing (issue #468).
|
|
445
|
+
* Use {@link MockFederation.createContext}, {@link createContext},
|
|
446
|
+
* {@link createRequestContext}, or {@link createInboxContext} instead.
|
|
447
|
+
*
|
|
396
448
|
* @example
|
|
397
449
|
* ```typescript
|
|
398
|
-
* import { Person, Create } from "@fedify/
|
|
399
|
-
* import {
|
|
450
|
+
* import { Person, Create } from "@fedify/vocab";
|
|
451
|
+
* import { createFederation } from "@fedify/testing";
|
|
400
452
|
*
|
|
401
|
-
* // Create a mock context
|
|
402
|
-
* const
|
|
403
|
-
* const context =
|
|
404
|
-
*
|
|
405
|
-
*
|
|
406
|
-
*
|
|
407
|
-
* });
|
|
453
|
+
* // Create a mock federation and context
|
|
454
|
+
* const federation = createFederation<{ userId: string }>();
|
|
455
|
+
* const context = federation.createContext(
|
|
456
|
+
* new URL("https://example.com"),
|
|
457
|
+
* { userId: "test-user" }
|
|
458
|
+
* );
|
|
408
459
|
*
|
|
409
460
|
* // Send an activity
|
|
410
461
|
* const recipient = new Person({ id: new URL("https://example.com/users/bob") });
|
|
@@ -418,8 +469,8 @@ var MockFederation = class {
|
|
|
418
469
|
* activity
|
|
419
470
|
* );
|
|
420
471
|
*
|
|
421
|
-
* // Check sent activities
|
|
422
|
-
* const sent =
|
|
472
|
+
* // Check sent activities from the federation
|
|
473
|
+
* const sent = federation.sentActivities;
|
|
423
474
|
* console.log(sent[0].activity);
|
|
424
475
|
* ```
|
|
425
476
|
*
|
|
@@ -436,6 +487,8 @@ var MockContext = class MockContext {
|
|
|
436
487
|
documentLoader;
|
|
437
488
|
contextLoader;
|
|
438
489
|
tracerProvider;
|
|
490
|
+
request;
|
|
491
|
+
url;
|
|
439
492
|
sentActivities = [];
|
|
440
493
|
constructor(options) {
|
|
441
494
|
const url = options.url ?? new URL("https://example.com");
|
|
@@ -443,6 +496,8 @@ var MockContext = class MockContext {
|
|
|
443
496
|
this.canonicalOrigin = url.origin;
|
|
444
497
|
this.host = url.host;
|
|
445
498
|
this.hostname = url.hostname;
|
|
499
|
+
this.url = url;
|
|
500
|
+
this.request = new Request(url);
|
|
446
501
|
this.data = options.data;
|
|
447
502
|
this.federation = options.federation;
|
|
448
503
|
this.documentLoader = options.documentLoader ?? (async (url$1) => ({
|
|
@@ -451,11 +506,23 @@ var MockContext = class MockContext {
|
|
|
451
506
|
documentUrl: url$1
|
|
452
507
|
}));
|
|
453
508
|
this.contextLoader = options.contextLoader ?? this.documentLoader;
|
|
454
|
-
this.tracerProvider = options.tracerProvider ??
|
|
509
|
+
this.tracerProvider = options.tracerProvider ?? noopTracerProvider;
|
|
510
|
+
}
|
|
511
|
+
getActor(_handle) {
|
|
512
|
+
return Promise.resolve(null);
|
|
513
|
+
}
|
|
514
|
+
getObject(_cls, _values) {
|
|
515
|
+
return Promise.resolve(null);
|
|
516
|
+
}
|
|
517
|
+
getSignedKey() {
|
|
518
|
+
return Promise.resolve(null);
|
|
519
|
+
}
|
|
520
|
+
getSignedKeyOwner() {
|
|
521
|
+
return Promise.resolve(null);
|
|
455
522
|
}
|
|
456
523
|
clone(data) {
|
|
457
524
|
return new MockContext({
|
|
458
|
-
url:
|
|
525
|
+
url: this.url,
|
|
459
526
|
data,
|
|
460
527
|
federation: this.federation,
|
|
461
528
|
documentLoader: this.documentLoader,
|
|
@@ -637,4 +704,4 @@ var MockContext = class MockContext {
|
|
|
637
704
|
};
|
|
638
705
|
|
|
639
706
|
//#endregion
|
|
640
|
-
export {
|
|
707
|
+
export { createContext, createFederation, createInboxContext, createRequestContext };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fedify/testing",
|
|
3
|
-
"version": "2.0.0-dev.
|
|
3
|
+
"version": "2.0.0-dev.170+a03fedcd",
|
|
4
4
|
"description": "Testing utilities for Fedify applications",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"fedify",
|
|
@@ -50,17 +50,14 @@
|
|
|
50
50
|
"package.json"
|
|
51
51
|
],
|
|
52
52
|
"peerDependencies": {
|
|
53
|
-
"@fedify/fedify": "^2.0.0-dev.
|
|
54
|
-
},
|
|
55
|
-
"dependencies": {
|
|
56
|
-
"@opentelemetry/api": "^1.9.0"
|
|
53
|
+
"@fedify/fedify": "^2.0.0-dev.170+a03fedcd"
|
|
57
54
|
},
|
|
58
55
|
"devDependencies": {
|
|
59
56
|
"@js-temporal/polyfill": "^0.5.1",
|
|
60
57
|
"@std/assert": "npm:@jsr/std__assert@^1.0.13",
|
|
61
58
|
"@std/async": "npm:@jsr/std__async@^1.0.13",
|
|
62
59
|
"tsdown": "^0.12.9",
|
|
63
|
-
"typescript": "^5.9.
|
|
60
|
+
"typescript": "^5.9.3"
|
|
64
61
|
},
|
|
65
62
|
"scripts": {
|
|
66
63
|
"build": "tsdown",
|