@fedify/testing 1.8.1-pr.283.1138

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/mock.test.ts ADDED
@@ -0,0 +1,361 @@
1
+ import { Create, Note, Person } from "@fedify/fedify/vocab";
2
+ import { assertEquals, assertRejects } from "@std/assert";
3
+ import { test } from "../fedify/testing/mod.ts";
4
+ import { MockContext, MockFederation } from "./mock.ts";
5
+
6
+ test("getSentActivities returns sent activities", async () => {
7
+ const mockFederation = new MockFederation<void>();
8
+ const context = mockFederation.createContext(
9
+ new URL("https://example.com"),
10
+ undefined,
11
+ );
12
+
13
+ // Create a test activity
14
+ const activity = new Create({
15
+ id: new URL("https://example.com/activities/1"),
16
+ actor: new URL("https://example.com/users/alice"),
17
+ object: new Note({
18
+ id: new URL("https://example.com/notes/1"),
19
+ content: "Hello, world!",
20
+ }),
21
+ });
22
+
23
+ // Send the activity
24
+ await context.sendActivity(
25
+ { identifier: "alice" },
26
+ new Person({ id: new URL("https://example.com/users/bob") }),
27
+ activity,
28
+ );
29
+
30
+ // Check that the activity was recorded
31
+ assertEquals(mockFederation.sentActivities.length, 1);
32
+ assertEquals(mockFederation.sentActivities[0].activity, activity);
33
+ assertEquals(mockFederation.sentActivities[0].queued, false);
34
+ assertEquals(mockFederation.sentActivities[0].sentOrder, 1);
35
+ });
36
+
37
+ test("reset clears sent activities", async () => {
38
+ const mockFederation = new MockFederation<void>();
39
+ const context = mockFederation.createContext(
40
+ new URL("https://example.com"),
41
+ undefined,
42
+ );
43
+
44
+ // Send an activity
45
+ const activity = new Create({
46
+ id: new URL("https://example.com/activities/1"),
47
+ actor: new URL("https://example.com/users/alice"),
48
+ });
49
+
50
+ await context.sendActivity(
51
+ { identifier: "alice" },
52
+ new Person({ id: new URL("https://example.com/users/bob") }),
53
+ activity,
54
+ );
55
+
56
+ // Verify it was sent
57
+ assertEquals(mockFederation.sentActivities.length, 1);
58
+ assertEquals(mockFederation.sentActivities[0].activity, activity);
59
+
60
+ // Clear sent activities
61
+ mockFederation.reset();
62
+
63
+ // Verify they were cleared
64
+ assertEquals(mockFederation.sentActivities.length, 0);
65
+ });
66
+
67
+ test("receiveActivity triggers inbox listeners", async () => {
68
+ // Provide contextData through constructor
69
+ const mockFederation = new MockFederation<{ test: string }>({
70
+ contextData: { test: "data" },
71
+ });
72
+ let receivedActivity: Create | null = null;
73
+
74
+ // Set up an inbox listener
75
+ mockFederation
76
+ .setInboxListeners("/users/{identifier}/inbox")
77
+ // deno-lint-ignore require-await
78
+ .on(Create, async (_ctx, activity) => {
79
+ receivedActivity = activity;
80
+ });
81
+
82
+ // Create and receive an activity
83
+ const activity = new Create({
84
+ id: new URL("https://example.com/activities/1"),
85
+ actor: new URL("https://example.com/users/alice"),
86
+ object: new Note({
87
+ id: new URL("https://example.com/notes/1"),
88
+ content: "Test note",
89
+ }),
90
+ });
91
+
92
+ await mockFederation.receiveActivity(activity);
93
+
94
+ // Verify the listener was triggered
95
+ assertEquals(receivedActivity, activity);
96
+ });
97
+
98
+ test("MockContext tracks sent activities", async () => {
99
+ const mockFederation = new MockFederation<void>();
100
+ const mockContext = new MockContext({
101
+ url: new URL("https://example.com"),
102
+ data: undefined,
103
+ federation: mockFederation,
104
+ });
105
+
106
+ // Create a test activity
107
+ const activity = new Create({
108
+ id: new URL("https://example.com/activities/1"),
109
+ actor: new URL("https://example.com/users/alice"),
110
+ object: new Note({
111
+ id: new URL("https://example.com/notes/1"),
112
+ content: "Hello from MockContext!",
113
+ }),
114
+ });
115
+
116
+ // Send the activity
117
+ await mockContext.sendActivity(
118
+ { identifier: "alice" },
119
+ new Person({ id: new URL("https://example.com/users/bob") }),
120
+ activity,
121
+ );
122
+
123
+ // Check that the activity was recorded in the context
124
+ const contextSentActivities = mockContext.getSentActivities();
125
+ assertEquals(contextSentActivities.length, 1);
126
+ assertEquals(contextSentActivities[0].activity, activity);
127
+
128
+ // Check that it was also recorded in the federation
129
+ assertEquals(mockFederation.sentActivities.length, 1);
130
+ assertEquals(mockFederation.sentActivities[0].activity, activity);
131
+ });
132
+
133
+ test("MockContext URI methods should work correctly", () => {
134
+ const mockFederation = new MockFederation<void>();
135
+ const mockContext = new MockContext({
136
+ url: new URL("https://example.com"),
137
+ data: undefined,
138
+ federation: mockFederation,
139
+ });
140
+
141
+ // Test URI generation methods
142
+ assertEquals(
143
+ mockContext.getActorUri("alice").href,
144
+ "https://example.com/users/alice",
145
+ );
146
+ assertEquals(
147
+ mockContext.getInboxUri("alice").href,
148
+ "https://example.com/users/alice/inbox",
149
+ );
150
+ assertEquals(mockContext.getInboxUri().href, "https://example.com/inbox");
151
+ assertEquals(
152
+ mockContext.getOutboxUri("alice").href,
153
+ "https://example.com/users/alice/outbox",
154
+ );
155
+ assertEquals(
156
+ mockContext.getFollowingUri("alice").href,
157
+ "https://example.com/users/alice/following",
158
+ );
159
+ assertEquals(
160
+ mockContext.getFollowersUri("alice").href,
161
+ "https://example.com/users/alice/followers",
162
+ );
163
+
164
+ const actorUri = new URL("https://example.com/users/alice");
165
+ const parsed = mockContext.parseUri(actorUri);
166
+ assertEquals(parsed?.type, "actor");
167
+ if (parsed?.type === "actor") {
168
+ assertEquals(parsed.identifier, "alice");
169
+ }
170
+ });
171
+
172
+ test("MockContext URI methods respect registered paths", () => {
173
+ const mockFederation = new MockFederation<void>();
174
+
175
+ // Register custom paths with dummy dispatchers
176
+ mockFederation.setNodeInfoDispatcher("/.well-known/nodeinfo", () => ({
177
+ software: { name: "test", version: { major: 1, minor: 0, patch: 0 } },
178
+ protocols: [],
179
+ usage: {
180
+ users: {},
181
+ localPosts: 0,
182
+ localComments: 0,
183
+ },
184
+ }));
185
+ mockFederation.setActorDispatcher("/actors/{identifier}", () => null);
186
+ mockFederation.setObjectDispatcher(Note, "/notes/{id}", () => null);
187
+ mockFederation.setInboxListeners(
188
+ "/actors/{identifier}/inbox",
189
+ "/shared-inbox",
190
+ );
191
+ mockFederation.setOutboxDispatcher("/actors/{identifier}/outbox", () => null);
192
+ mockFederation.setFollowingDispatcher(
193
+ "/actors/{identifier}/following",
194
+ () => null,
195
+ );
196
+ mockFederation.setFollowersDispatcher(
197
+ "/actors/{identifier}/followers",
198
+ () => null,
199
+ );
200
+ mockFederation.setLikedDispatcher("/actors/{identifier}/liked", () => null);
201
+ mockFederation.setFeaturedDispatcher(
202
+ "/actors/{identifier}/featured",
203
+ () => null,
204
+ );
205
+ mockFederation.setFeaturedTagsDispatcher(
206
+ "/actors/{identifier}/tags",
207
+ () => null,
208
+ );
209
+
210
+ const context = mockFederation.createContext(
211
+ new URL("https://example.com"),
212
+ undefined,
213
+ );
214
+
215
+ // Test that URIs use the registered paths
216
+ assertEquals(
217
+ context.getNodeInfoUri().href,
218
+ "https://example.com/.well-known/nodeinfo",
219
+ );
220
+ assertEquals(
221
+ context.getActorUri("alice").href,
222
+ "https://example.com/actors/alice",
223
+ );
224
+ assertEquals(
225
+ context.getObjectUri(Note, { id: "123" }).href,
226
+ "https://example.com/notes/123",
227
+ );
228
+ assertEquals(
229
+ context.getInboxUri("alice").href,
230
+ "https://example.com/actors/alice/inbox",
231
+ );
232
+ assertEquals(
233
+ context.getInboxUri().href,
234
+ "https://example.com/shared-inbox",
235
+ );
236
+ assertEquals(
237
+ context.getOutboxUri("alice").href,
238
+ "https://example.com/actors/alice/outbox",
239
+ );
240
+ assertEquals(
241
+ context.getFollowingUri("alice").href,
242
+ "https://example.com/actors/alice/following",
243
+ );
244
+ assertEquals(
245
+ context.getFollowersUri("alice").href,
246
+ "https://example.com/actors/alice/followers",
247
+ );
248
+ assertEquals(
249
+ context.getLikedUri("alice").href,
250
+ "https://example.com/actors/alice/liked",
251
+ );
252
+ assertEquals(
253
+ context.getFeaturedUri("alice").href,
254
+ "https://example.com/actors/alice/featured",
255
+ );
256
+ assertEquals(
257
+ context.getFeaturedTagsUri("alice").href,
258
+ "https://example.com/actors/alice/tags",
259
+ );
260
+ });
261
+
262
+ test("receiveActivity throws error when contextData not initialized", async () => {
263
+ const mockFederation = new MockFederation<void>();
264
+
265
+ // Set up an inbox listener without initializing contextData
266
+ mockFederation
267
+ .setInboxListeners("/users/{identifier}/inbox")
268
+ .on(Create, async (_ctx, _activity) => {
269
+ /* should not happen */
270
+ });
271
+
272
+ const activity = new Create({
273
+ id: new URL("https://example.com/activities/1"),
274
+ actor: new URL("https://example.com/users/alice"),
275
+ });
276
+
277
+ // Should throw error
278
+ await assertRejects(
279
+ () => mockFederation.receiveActivity(activity),
280
+ Error,
281
+ "MockFederation.receiveActivity(): contextData is not initialized. Please provide contextData through the constructor or call startQueue() before receiving activities.",
282
+ );
283
+ });
284
+
285
+ test("MockFederation distinguishes between immediate and queued activities", async () => {
286
+ const mockFederation = new MockFederation<void>();
287
+
288
+ // Start the queue to enable queued sending
289
+ await mockFederation.startQueue(undefined);
290
+
291
+ const context = mockFederation.createContext(
292
+ new URL("https://example.com"),
293
+ undefined,
294
+ );
295
+
296
+ const activity1 = new Create({
297
+ id: new URL("https://example.com/activities/1"),
298
+ actor: new URL("https://example.com/users/alice"),
299
+ });
300
+
301
+ const activity2 = new Create({
302
+ id: new URL("https://example.com/activities/2"),
303
+ actor: new URL("https://example.com/users/alice"),
304
+ });
305
+
306
+ // Send activities after queue is started - should be marked as queued
307
+ await context.sendActivity(
308
+ { identifier: "alice" },
309
+ new Person({ id: new URL("https://example.com/users/bob") }),
310
+ activity1,
311
+ );
312
+
313
+ await context.sendActivity(
314
+ { identifier: "alice" },
315
+ new Person({ id: new URL("https://example.com/users/bob") }),
316
+ activity2,
317
+ );
318
+
319
+ // Check activity details
320
+ assertEquals(mockFederation.sentActivities.length, 2);
321
+ assertEquals(mockFederation.sentActivities[0].activity, activity1);
322
+ assertEquals(mockFederation.sentActivities[1].activity, activity2);
323
+
324
+ // Both should be marked as sent via queue
325
+ assertEquals(mockFederation.sentActivities[0].queued, true);
326
+ assertEquals(mockFederation.sentActivities[1].queued, true);
327
+ assertEquals(mockFederation.sentActivities[0].queue, "outbox");
328
+ assertEquals(mockFederation.sentActivities[1].queue, "outbox");
329
+ assertEquals(mockFederation.sentActivities[0].sentOrder, 1);
330
+ assertEquals(mockFederation.sentActivities[1].sentOrder, 2);
331
+ });
332
+
333
+ test("MockFederation without queue sends all activities immediately", async () => {
334
+ const mockFederation = new MockFederation<void>();
335
+
336
+ const context = mockFederation.createContext(
337
+ new URL("https://example.com"),
338
+ undefined,
339
+ );
340
+
341
+ const activity = new Create({
342
+ id: new URL("https://example.com/activities/1"),
343
+ actor: new URL("https://example.com/users/alice"),
344
+ });
345
+
346
+ // Send activity - should be marked as immediate since queue not started
347
+ await context.sendActivity(
348
+ { identifier: "alice" },
349
+ new Person({ id: new URL("https://example.com/users/bob") }),
350
+ activity,
351
+ );
352
+
353
+ // Check activity details
354
+ assertEquals(mockFederation.sentActivities.length, 1);
355
+ assertEquals(mockFederation.sentActivities[0].activity, activity);
356
+
357
+ // Should be marked as sent immediately
358
+ assertEquals(mockFederation.sentActivities[0].queued, false);
359
+ assertEquals(mockFederation.sentActivities[0].queue, undefined);
360
+ assertEquals(mockFederation.sentActivities[0].sentOrder, 1);
361
+ });