@fedify/testing 2.0.0-dev.1807 → 2.0.0-dev.1875

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/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
25
  const __fedify_fedify_vocab = __toESM(require("@fedify/fedify/vocab"));
27
- const __fedify_fedify_webfinger = __toESM(require("@fedify/fedify/webfinger"));
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 ?? __opentelemetry_api.trace.getTracerProvider(),
54
+ tracerProvider: tracerProvider ?? noopTracerProvider$1,
53
55
  clone: clone ?? ((data$1) => createContext({
54
56
  ...values,
55
57
  data: data$1
@@ -87,8 +89,8 @@ function createContext(values) {
87
89
  lookupNodeInfo: lookupNodeInfo ?? ((_params) => {
88
90
  throw new Error("Not implemented");
89
91
  }),
90
- lookupWebFinger: lookupWebFinger ?? ((resource, options = {}) => {
91
- return (0, __fedify_fedify_webfinger.lookupWebFinger)(resource, options);
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.
@@ -152,17 +172,17 @@ function expandUriTemplate(template, values) {
152
172
  * @example
153
173
  * ```typescript
154
174
  * import { Create } from "@fedify/fedify/vocab";
155
- * import { MockFederation } from "@fedify/testing";
175
+ * import { createFederation } from "@fedify/testing";
156
176
  *
157
177
  * // Create a mock federation with contextData
158
- * const federation = new MockFederation<{ userId: string }>({
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
- if (baseUrlOrRequest instanceof Request) return createRequestContext({
343
- url: new URL(baseUrlOrRequest.url),
344
- request: baseUrlOrRequest,
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/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
473
  * import { Person, Create } from "@fedify/fedify/vocab";
422
- * import { MockContext, MockFederation } from "@fedify/testing";
474
+ * import { createFederation } from "@fedify/testing";
423
475
  *
424
- * // Create a mock context
425
- * const mockFederation = new MockFederation<{ userId: string }>();
426
- * const context = new MockContext({
427
- * url: new URL("https://example.com"),
428
- * data: { userId: "test-user" },
429
- * federation: mockFederation
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 = context.getSentActivities();
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 ?? __opentelemetry_api.trace.getTracerProvider();
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: new URL(this.origin),
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 { ActorCallbackSetters, ActorDispatcher, ActorKeyPair, CollectionCallbackSetters, CollectionDispatcher, Context, Federation, FederationFetchOptions, FederationStartQueueOptions, InboxContext, InboxListenerSetters, Message, NodeInfoDispatcher, ObjectCallbackSetters, ObjectDispatcher, ParseUriResult, RequestContext, RouteActivityOptions, SendActivityOptions, SendActivityOptionsForCollection, SenderKeyPair, WebFingerLinksDispatcher } from "@fedify/fedify/federation";
2
- import { JsonValue, NodeInfo } from "@fedify/fedify/nodeinfo";
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 { DocumentLoader } from "@fedify/vocab-runtime";
6
- import { TracerProvider } from "@opentelemetry/api";
1
+ import { Context, Federation, InboxContext, RequestContext } from "@fedify/fedify/federation";
2
+ import { Activity } from "@fedify/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 implementation of the {@link Federation} interface for unit testing.
26
- * This class provides a way to test Fedify applications without needing
27
- * a real federation setup.
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
94
  * import { Create } from "@fedify/fedify/vocab";
32
- * import { MockFederation } from "@fedify/testing";
95
+ * import { createFederation } from "@fedify/testing";
33
96
  *
34
97
  * // Create a mock federation with contextData
35
- * const federation = new MockFederation<{ userId: string }>({
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
- * const sent = context.getSentActivities();
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 class MockContext<TContextData> implements Context<TContextData> {
171
- readonly origin: string;
172
- readonly canonicalOrigin: string;
173
- readonly host: string;
174
- readonly hostname: string;
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 { MockContext, MockFederation, SentActivity, createContext, createInboxContext, createRequestContext };
126
+ export { createContext, createFederation, createInboxContext, createRequestContext };
package/dist/mod.d.ts CHANGED
@@ -1,12 +1,45 @@
1
- import { TracerProvider } from "@opentelemetry/api";
2
- import { ActorCallbackSetters, ActorDispatcher, ActorKeyPair, CollectionCallbackSetters, CollectionDispatcher, Context, Federation, FederationFetchOptions, FederationStartQueueOptions, InboxContext, InboxListenerSetters, Message, NodeInfoDispatcher, ObjectCallbackSetters, ObjectDispatcher, ParseUriResult, RequestContext, RouteActivityOptions, SendActivityOptions, SendActivityOptionsForCollection, SenderKeyPair, WebFingerLinksDispatcher } from "@fedify/fedify/federation";
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/vocab-runtime";
1
+ import { Context, Federation, InboxContext, RequestContext } from "@fedify/fedify/federation";
2
+ import { Activity } from "@fedify/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 implementation of the {@link Federation} interface for unit testing.
26
- * This class provides a way to test Fedify applications without needing
27
- * a real federation setup.
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
94
  * import { Create } from "@fedify/fedify/vocab";
32
- * import { MockFederation } from "@fedify/testing";
95
+ * import { createFederation } from "@fedify/testing";
33
96
  *
34
97
  * // Create a mock federation with contextData
35
- * const federation = new MockFederation<{ userId: string }>({
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
- * const sent = context.getSentActivities();
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 class MockContext<TContextData> implements Context<TContextData> {
171
- readonly origin: string;
172
- readonly canonicalOrigin: string;
173
- readonly host: string;
174
- readonly hostname: string;
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 { MockContext, MockFederation, SentActivity, createContext, createInboxContext, createRequestContext };
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
2
  import { lookupObject, traverseCollection } from "@fedify/fedify/vocab";
4
- import { lookupWebFinger } from "@fedify/fedify/webfinger";
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: lookupWebFinger$1, sendActivity, routeActivity } = values;
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 ?? trace.getTracerProvider(),
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$1 ?? ((resource, options = {}) => {
68
- return lookupWebFinger(resource, options);
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.
@@ -129,17 +149,17 @@ function expandUriTemplate(template, values) {
129
149
  * @example
130
150
  * ```typescript
131
151
  * import { Create } from "@fedify/fedify/vocab";
132
- * import { MockFederation } from "@fedify/testing";
152
+ * import { createFederation } from "@fedify/testing";
133
153
  *
134
154
  * // Create a mock federation with contextData
135
- * const federation = new MockFederation<{ userId: string }>({
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
- if (baseUrlOrRequest instanceof Request) return createRequestContext({
320
- url: new URL(baseUrlOrRequest.url),
321
- request: baseUrlOrRequest,
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/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
450
  * import { Person, Create } from "@fedify/fedify/vocab";
399
- * import { MockContext, MockFederation } from "@fedify/testing";
451
+ * import { createFederation } from "@fedify/testing";
400
452
  *
401
- * // Create a mock context
402
- * const mockFederation = new MockFederation<{ userId: string }>();
403
- * const context = new MockContext({
404
- * url: new URL("https://example.com"),
405
- * data: { userId: "test-user" },
406
- * federation: mockFederation
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 = context.getSentActivities();
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 ?? trace.getTracerProvider();
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: new URL(this.origin),
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 { MockContext, MockFederation, createContext, createInboxContext, createRequestContext };
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.1807+00c7443d",
3
+ "version": "2.0.0-dev.1875+d712d60c",
4
4
  "description": "Testing utilities for Fedify applications",
5
5
  "keywords": [
6
6
  "fedify",
@@ -50,10 +50,7 @@
50
50
  "package.json"
51
51
  ],
52
52
  "peerDependencies": {
53
- "@fedify/fedify": "^2.0.0-dev.1807+00c7443d"
54
- },
55
- "dependencies": {
56
- "@opentelemetry/api": "^1.9.0"
53
+ "@fedify/fedify": "^2.0.0-dev.1875+d712d60c"
57
54
  },
58
55
  "devDependencies": {
59
56
  "@js-temporal/polyfill": "^0.5.1",