@powerhousedao/reactor 4.1.0-dev.56 → 4.1.0-dev.57
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/bench/event-bus.bench.d.ts +2 -0
- package/dist/bench/event-bus.bench.d.ts.map +1 -0
- package/dist/bench/event-bus.bench.js +228 -0
- package/dist/bench/event-bus.bench.js.map +1 -0
- package/dist/bench/queue-only.bench.d.ts +2 -0
- package/dist/bench/queue-only.bench.d.ts.map +1 -0
- package/dist/bench/queue-only.bench.js +47 -0
- package/dist/bench/queue-only.bench.js.map +1 -0
- package/dist/bench/reactor-throughput.bench.d.ts +2 -0
- package/dist/bench/reactor-throughput.bench.d.ts.map +1 -0
- package/dist/bench/reactor-throughput.bench.js +145 -0
- package/dist/bench/reactor-throughput.bench.js.map +1 -0
- package/dist/src/client/reactor-client.d.ts +46 -7
- package/dist/src/client/reactor-client.d.ts.map +1 -1
- package/dist/src/client/reactor-client.js +13 -0
- package/dist/src/client/reactor-client.js.map +1 -1
- package/dist/src/client/types.d.ts +2 -2
- package/dist/src/client/types.d.ts.map +1 -1
- package/dist/src/client/types.js.map +1 -1
- package/dist/src/core/reactor.d.ts +3 -4
- package/dist/src/core/reactor.d.ts.map +1 -1
- package/dist/src/core/reactor.js +3 -8
- package/dist/src/core/reactor.js.map +1 -1
- package/dist/src/core/types.d.ts +2 -2
- package/dist/src/core/types.d.ts.map +1 -1
- package/dist/src/executor/simple-job-executor.d.ts +1 -1
- package/dist/src/executor/simple-job-executor.d.ts.map +1 -1
- package/dist/src/index.js +8 -0
- package/dist/src/index.js.map +1 -1
- package/dist/src/registry/implementation.d.ts.map +1 -1
- package/dist/src/registry/implementation.js +1 -0
- package/dist/src/registry/implementation.js.map +1 -1
- package/dist/src/shared/awaiter.d.ts +1 -1
- package/dist/src/shared/awaiter.d.ts.map +1 -1
- package/dist/src/shared/awaiter.js.map +1 -1
- package/dist/test/client/client-passthrough.test.d.ts +2 -0
- package/dist/test/client/client-passthrough.test.d.ts.map +1 -0
- package/dist/test/client/client-passthrough.test.js +199 -0
- package/dist/test/client/client-passthrough.test.js.map +1 -0
- package/dist/test/event-bus.test.d.ts +2 -0
- package/dist/test/event-bus.test.d.ts.map +1 -0
- package/dist/test/event-bus.test.js +541 -0
- package/dist/test/event-bus.test.js.map +1 -0
- package/dist/test/executor/executor-integration.test.d.ts +2 -0
- package/dist/test/executor/executor-integration.test.d.ts.map +1 -0
- package/dist/test/executor/executor-integration.test.js +287 -0
- package/dist/test/executor/executor-integration.test.js.map +1 -0
- package/dist/test/executor/job-execution-handle.test.d.ts +2 -0
- package/dist/test/executor/job-execution-handle.test.d.ts.map +1 -0
- package/dist/test/executor/job-execution-handle.test.js +272 -0
- package/dist/test/executor/job-execution-handle.test.js.map +1 -0
- package/dist/test/executor/simple-job-executor-manager.test.d.ts +2 -0
- package/dist/test/executor/simple-job-executor-manager.test.d.ts.map +1 -0
- package/dist/test/executor/simple-job-executor-manager.test.js +132 -0
- package/dist/test/executor/simple-job-executor-manager.test.js.map +1 -0
- package/dist/test/executor/simple-job-executor.test.d.ts +2 -0
- package/dist/test/executor/simple-job-executor.test.d.ts.map +1 -0
- package/dist/test/executor/simple-job-executor.test.js +139 -0
- package/dist/test/executor/simple-job-executor.test.js.map +1 -0
- package/dist/test/factories.d.ts +122 -0
- package/dist/test/factories.d.ts.map +1 -0
- package/dist/test/factories.js +319 -0
- package/dist/test/factories.js.map +1 -0
- package/dist/test/integration/document-drive-integration.test.d.ts +2 -0
- package/dist/test/integration/document-drive-integration.test.d.ts.map +1 -0
- package/dist/test/integration/document-drive-integration.test.js +1102 -0
- package/dist/test/integration/document-drive-integration.test.js.map +1 -0
- package/dist/test/integration/reactor-read.test.d.ts +2 -0
- package/dist/test/integration/reactor-read.test.d.ts.map +1 -0
- package/dist/test/integration/reactor-read.test.js +291 -0
- package/dist/test/integration/reactor-read.test.js.map +1 -0
- package/dist/test/queue/queue-integration.test.d.ts +2 -0
- package/dist/test/queue/queue-integration.test.d.ts.map +1 -0
- package/dist/test/queue/queue-integration.test.js +322 -0
- package/dist/test/queue/queue-integration.test.js.map +1 -0
- package/dist/test/queue/queue.test.d.ts +2 -0
- package/dist/test/queue/queue.test.d.ts.map +1 -0
- package/dist/test/queue/queue.test.js +770 -0
- package/dist/test/queue/queue.test.js.map +1 -0
- package/dist/test/registry/registry.test.d.ts +2 -0
- package/dist/test/registry/registry.test.d.ts.map +1 -0
- package/dist/test/registry/registry.test.js +182 -0
- package/dist/test/registry/registry.test.js.map +1 -0
- package/dist/test/shared/awaiter.test.d.ts +2 -0
- package/dist/test/shared/awaiter.test.d.ts.map +1 -0
- package/dist/test/shared/awaiter.test.js +330 -0
- package/dist/test/shared/awaiter.test.js.map +1 -0
- package/dist/test/subs/react-subscription-manager.test.d.ts +2 -0
- package/dist/test/subs/react-subscription-manager.test.d.ts.map +1 -0
- package/dist/test/subs/react-subscription-manager.test.js +693 -0
- package/dist/test/subs/react-subscription-manager.test.js.map +1 -0
- package/dist/test/utils.test.d.ts +2 -0
- package/dist/test/utils.test.d.ts.map +1 -0
- package/dist/test/utils.test.js +66 -0
- package/dist/test/utils.test.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/dist/vitest.config.d.ts +3 -0
- package/dist/vitest.config.d.ts.map +1 -0
- package/dist/vitest.config.js +11 -0
- package/dist/vitest.config.js.map +1 -0
- package/package.json +9 -19
|
@@ -0,0 +1,693 @@
|
|
|
1
|
+
import { describe, it, expect, vi, beforeEach } from "vitest";
|
|
2
|
+
import { ReactorSubscriptionManager } from "../../src/subs/react-subscription-manager.js";
|
|
3
|
+
import { RelationshipChangeType, } from "../../src/shared/types.js";
|
|
4
|
+
describe("ReactorSubscriptionManager", () => {
|
|
5
|
+
let manager;
|
|
6
|
+
let mockErrorHandler;
|
|
7
|
+
beforeEach(() => {
|
|
8
|
+
// Use a mock error handler that doesn't throw for most tests
|
|
9
|
+
mockErrorHandler = {
|
|
10
|
+
handleError: vi.fn(),
|
|
11
|
+
};
|
|
12
|
+
manager = new ReactorSubscriptionManager(mockErrorHandler);
|
|
13
|
+
});
|
|
14
|
+
describe("Subscription Methods", () => {
|
|
15
|
+
describe("onDocumentCreated", () => {
|
|
16
|
+
it("should register a subscription and return unsubscribe function", () => {
|
|
17
|
+
const callback = vi.fn();
|
|
18
|
+
const unsubscribe = manager.onDocumentCreated(callback);
|
|
19
|
+
expect(unsubscribe).toBeInstanceOf(Function);
|
|
20
|
+
// Verify subscription works
|
|
21
|
+
manager.notifyDocumentsCreated(["doc1"]);
|
|
22
|
+
expect(callback).toHaveBeenCalledTimes(1);
|
|
23
|
+
// Unsubscribe and verify it no longer receives notifications
|
|
24
|
+
unsubscribe();
|
|
25
|
+
manager.notifyDocumentsCreated(["doc2"]);
|
|
26
|
+
expect(callback).toHaveBeenCalledTimes(1); // Still 1, not 2
|
|
27
|
+
});
|
|
28
|
+
it("should register multiple subscriptions", () => {
|
|
29
|
+
const callback1 = vi.fn();
|
|
30
|
+
const callback2 = vi.fn();
|
|
31
|
+
const unsub1 = manager.onDocumentCreated(callback1);
|
|
32
|
+
const unsub2 = manager.onDocumentCreated(callback2);
|
|
33
|
+
// Both should receive notifications
|
|
34
|
+
manager.notifyDocumentsCreated(["doc1"]);
|
|
35
|
+
expect(callback1).toHaveBeenCalledTimes(1);
|
|
36
|
+
expect(callback2).toHaveBeenCalledTimes(1);
|
|
37
|
+
// Unsubscribe first callback
|
|
38
|
+
unsub1();
|
|
39
|
+
manager.notifyDocumentsCreated(["doc2"]);
|
|
40
|
+
expect(callback1).toHaveBeenCalledTimes(1); // Still 1
|
|
41
|
+
expect(callback2).toHaveBeenCalledTimes(2); // Now 2
|
|
42
|
+
// Unsubscribe second callback
|
|
43
|
+
unsub2();
|
|
44
|
+
manager.notifyDocumentsCreated(["doc3"]);
|
|
45
|
+
expect(callback1).toHaveBeenCalledTimes(1); // Still 1
|
|
46
|
+
expect(callback2).toHaveBeenCalledTimes(2); // Still 2
|
|
47
|
+
});
|
|
48
|
+
it("should store search filters with subscription", () => {
|
|
49
|
+
const callback = vi.fn();
|
|
50
|
+
const search = { type: "Document" };
|
|
51
|
+
manager.onDocumentCreated(callback, search);
|
|
52
|
+
manager.notifyDocumentsCreated(["doc1"], new Map([["doc1", "Document"]]));
|
|
53
|
+
expect(callback).toHaveBeenCalledWith(expect.objectContaining({
|
|
54
|
+
results: ["doc1"],
|
|
55
|
+
}));
|
|
56
|
+
});
|
|
57
|
+
});
|
|
58
|
+
describe("onDocumentDeleted", () => {
|
|
59
|
+
it("should register a subscription and return unsubscribe function", () => {
|
|
60
|
+
const callback = vi.fn();
|
|
61
|
+
const unsubscribe = manager.onDocumentDeleted(callback);
|
|
62
|
+
expect(unsubscribe).toBeInstanceOf(Function);
|
|
63
|
+
// Verify subscription works
|
|
64
|
+
manager.notifyDocumentsDeleted(["doc1"]);
|
|
65
|
+
expect(callback).toHaveBeenCalledTimes(1);
|
|
66
|
+
// Unsubscribe and verify it no longer receives notifications
|
|
67
|
+
unsubscribe();
|
|
68
|
+
manager.notifyDocumentsDeleted(["doc2"]);
|
|
69
|
+
expect(callback).toHaveBeenCalledTimes(1); // Still 1, not 2
|
|
70
|
+
});
|
|
71
|
+
});
|
|
72
|
+
describe("onDocumentStateUpdated", () => {
|
|
73
|
+
it("should register a subscription with view filter", () => {
|
|
74
|
+
const callback = vi.fn();
|
|
75
|
+
const search = { type: "Document" };
|
|
76
|
+
const view = { branch: "main" };
|
|
77
|
+
const unsubscribe = manager.onDocumentStateUpdated(callback, search, view);
|
|
78
|
+
expect(unsubscribe).toBeInstanceOf(Function);
|
|
79
|
+
// Verify subscription works with matching filter
|
|
80
|
+
const doc = {
|
|
81
|
+
header: {
|
|
82
|
+
id: "doc1",
|
|
83
|
+
documentType: "Document",
|
|
84
|
+
slug: "doc-1",
|
|
85
|
+
},
|
|
86
|
+
};
|
|
87
|
+
manager.notifyDocumentsUpdated([doc]);
|
|
88
|
+
expect(callback).toHaveBeenCalledTimes(1);
|
|
89
|
+
// Unsubscribe and verify it no longer receives notifications
|
|
90
|
+
unsubscribe();
|
|
91
|
+
manager.notifyDocumentsUpdated([doc]);
|
|
92
|
+
expect(callback).toHaveBeenCalledTimes(1); // Still 1
|
|
93
|
+
});
|
|
94
|
+
});
|
|
95
|
+
describe("onRelationshipChanged", () => {
|
|
96
|
+
it("should register a subscription", () => {
|
|
97
|
+
const callback = vi.fn();
|
|
98
|
+
const unsubscribe = manager.onRelationshipChanged(callback);
|
|
99
|
+
expect(unsubscribe).toBeInstanceOf(Function);
|
|
100
|
+
// Verify subscription works
|
|
101
|
+
manager.notifyRelationshipChanged("parent1", "child1", RelationshipChangeType.Added);
|
|
102
|
+
expect(callback).toHaveBeenCalledTimes(1);
|
|
103
|
+
// Unsubscribe and verify it no longer receives notifications
|
|
104
|
+
unsubscribe();
|
|
105
|
+
manager.notifyRelationshipChanged("parent2", "child2", RelationshipChangeType.Added);
|
|
106
|
+
expect(callback).toHaveBeenCalledTimes(1); // Still 1
|
|
107
|
+
});
|
|
108
|
+
});
|
|
109
|
+
});
|
|
110
|
+
describe("Notification Methods", () => {
|
|
111
|
+
describe("notifyDocumentsCreated", () => {
|
|
112
|
+
it("should notify all subscribers with created documents", () => {
|
|
113
|
+
const callback1 = vi.fn();
|
|
114
|
+
const callback2 = vi.fn();
|
|
115
|
+
manager.onDocumentCreated(callback1);
|
|
116
|
+
manager.onDocumentCreated(callback2);
|
|
117
|
+
const documentIds = ["doc1", "doc2"];
|
|
118
|
+
manager.notifyDocumentsCreated(documentIds);
|
|
119
|
+
expect(callback1).toHaveBeenCalledWith(expect.objectContaining({
|
|
120
|
+
results: documentIds,
|
|
121
|
+
options: { cursor: "", limit: 2 },
|
|
122
|
+
}));
|
|
123
|
+
expect(callback2).toHaveBeenCalledWith(expect.objectContaining({
|
|
124
|
+
results: documentIds,
|
|
125
|
+
options: { cursor: "", limit: 2 },
|
|
126
|
+
}));
|
|
127
|
+
});
|
|
128
|
+
it("should filter documents by type", () => {
|
|
129
|
+
const callback = vi.fn();
|
|
130
|
+
const search = { type: "Task" };
|
|
131
|
+
manager.onDocumentCreated(callback, search);
|
|
132
|
+
const documentIds = ["doc1", "doc2", "doc3"];
|
|
133
|
+
const types = new Map([
|
|
134
|
+
["doc1", "Task"],
|
|
135
|
+
["doc2", "Document"],
|
|
136
|
+
["doc3", "Task"],
|
|
137
|
+
]);
|
|
138
|
+
manager.notifyDocumentsCreated(documentIds, types);
|
|
139
|
+
expect(callback).toHaveBeenCalledWith(expect.objectContaining({
|
|
140
|
+
results: ["doc1", "doc3"],
|
|
141
|
+
}));
|
|
142
|
+
});
|
|
143
|
+
it("should filter documents by parentId", () => {
|
|
144
|
+
const callback = vi.fn();
|
|
145
|
+
const search = { parentId: "parent1" };
|
|
146
|
+
manager.onDocumentCreated(callback, search);
|
|
147
|
+
const documentIds = ["doc1", "doc2", "doc3"];
|
|
148
|
+
const parentIds = new Map([
|
|
149
|
+
["doc1", "parent1"],
|
|
150
|
+
["doc2", "parent2"],
|
|
151
|
+
["doc3", "parent1"],
|
|
152
|
+
]);
|
|
153
|
+
manager.notifyDocumentsCreated(documentIds, undefined, parentIds);
|
|
154
|
+
expect(callback).toHaveBeenCalledWith(expect.objectContaining({
|
|
155
|
+
results: ["doc1", "doc3"],
|
|
156
|
+
}));
|
|
157
|
+
});
|
|
158
|
+
it("should not notify if no documents match filter", () => {
|
|
159
|
+
const callback = vi.fn();
|
|
160
|
+
const search = { type: "NonExistent" };
|
|
161
|
+
manager.onDocumentCreated(callback, search);
|
|
162
|
+
const documentIds = ["doc1", "doc2"];
|
|
163
|
+
const types = new Map([
|
|
164
|
+
["doc1", "Task"],
|
|
165
|
+
["doc2", "Document"],
|
|
166
|
+
]);
|
|
167
|
+
manager.notifyDocumentsCreated(documentIds, types);
|
|
168
|
+
expect(callback).not.toHaveBeenCalled();
|
|
169
|
+
});
|
|
170
|
+
});
|
|
171
|
+
describe("notifyDocumentsDeleted", () => {
|
|
172
|
+
it("should notify subscribers with deleted document IDs", () => {
|
|
173
|
+
const callback = vi.fn();
|
|
174
|
+
manager.onDocumentDeleted(callback);
|
|
175
|
+
const documentIds = ["doc1", "doc2"];
|
|
176
|
+
manager.notifyDocumentsDeleted(documentIds);
|
|
177
|
+
expect(callback).toHaveBeenCalledWith(documentIds);
|
|
178
|
+
});
|
|
179
|
+
it("should filter deleted documents by search criteria", () => {
|
|
180
|
+
const callback = vi.fn();
|
|
181
|
+
const search = { ids: ["doc1", "doc3"] };
|
|
182
|
+
manager.onDocumentDeleted(callback, search);
|
|
183
|
+
const documentIds = ["doc1", "doc2", "doc3", "doc4"];
|
|
184
|
+
manager.notifyDocumentsDeleted(documentIds);
|
|
185
|
+
expect(callback).toHaveBeenCalledWith(["doc1", "doc3"]);
|
|
186
|
+
});
|
|
187
|
+
});
|
|
188
|
+
describe("notifyDocumentsUpdated", () => {
|
|
189
|
+
it("should notify subscribers with updated documents", () => {
|
|
190
|
+
const callback = vi.fn();
|
|
191
|
+
manager.onDocumentStateUpdated(callback);
|
|
192
|
+
const documents = [
|
|
193
|
+
{
|
|
194
|
+
header: {
|
|
195
|
+
id: "doc1",
|
|
196
|
+
documentType: "Task",
|
|
197
|
+
slug: "task-1",
|
|
198
|
+
},
|
|
199
|
+
},
|
|
200
|
+
{
|
|
201
|
+
header: {
|
|
202
|
+
id: "doc2",
|
|
203
|
+
documentType: "Document",
|
|
204
|
+
slug: "doc-2",
|
|
205
|
+
},
|
|
206
|
+
},
|
|
207
|
+
];
|
|
208
|
+
manager.notifyDocumentsUpdated(documents);
|
|
209
|
+
expect(callback).toHaveBeenCalledWith(expect.objectContaining({
|
|
210
|
+
results: documents,
|
|
211
|
+
options: { cursor: "", limit: 2 },
|
|
212
|
+
}));
|
|
213
|
+
});
|
|
214
|
+
it("should filter updated documents by type", () => {
|
|
215
|
+
const callback = vi.fn();
|
|
216
|
+
const search = { type: "Task" };
|
|
217
|
+
manager.onDocumentStateUpdated(callback, search);
|
|
218
|
+
const documents = [
|
|
219
|
+
{
|
|
220
|
+
header: {
|
|
221
|
+
id: "doc1",
|
|
222
|
+
documentType: "Task",
|
|
223
|
+
slug: "task-1",
|
|
224
|
+
},
|
|
225
|
+
},
|
|
226
|
+
{
|
|
227
|
+
header: {
|
|
228
|
+
id: "doc2",
|
|
229
|
+
documentType: "Document",
|
|
230
|
+
slug: "doc-2",
|
|
231
|
+
},
|
|
232
|
+
},
|
|
233
|
+
];
|
|
234
|
+
manager.notifyDocumentsUpdated(documents);
|
|
235
|
+
expect(callback).toHaveBeenCalledWith(expect.objectContaining({
|
|
236
|
+
results: [documents[0]],
|
|
237
|
+
}));
|
|
238
|
+
});
|
|
239
|
+
it("should filter updated documents by slug", () => {
|
|
240
|
+
const callback = vi.fn();
|
|
241
|
+
const search = { slugs: ["task-1", "task-3"] };
|
|
242
|
+
manager.onDocumentStateUpdated(callback, search);
|
|
243
|
+
const documents = [
|
|
244
|
+
{
|
|
245
|
+
header: {
|
|
246
|
+
id: "doc1",
|
|
247
|
+
documentType: "Task",
|
|
248
|
+
slug: "task-1",
|
|
249
|
+
},
|
|
250
|
+
},
|
|
251
|
+
{
|
|
252
|
+
header: {
|
|
253
|
+
id: "doc2",
|
|
254
|
+
documentType: "Task",
|
|
255
|
+
slug: "task-2",
|
|
256
|
+
},
|
|
257
|
+
},
|
|
258
|
+
{
|
|
259
|
+
header: {
|
|
260
|
+
id: "doc3",
|
|
261
|
+
documentType: "Task",
|
|
262
|
+
slug: "task-3",
|
|
263
|
+
},
|
|
264
|
+
},
|
|
265
|
+
];
|
|
266
|
+
manager.notifyDocumentsUpdated(documents);
|
|
267
|
+
const result = callback.mock.calls[0][0];
|
|
268
|
+
expect(result.results).toHaveLength(2);
|
|
269
|
+
expect(result.results[0].header.slug).toBe("task-1");
|
|
270
|
+
expect(result.results[1].header.slug).toBe("task-3");
|
|
271
|
+
});
|
|
272
|
+
});
|
|
273
|
+
describe("notifyRelationshipChanged", () => {
|
|
274
|
+
it("should notify subscribers about relationship changes", () => {
|
|
275
|
+
const callback = vi.fn();
|
|
276
|
+
manager.onRelationshipChanged(callback);
|
|
277
|
+
manager.notifyRelationshipChanged("parent1", "child1", RelationshipChangeType.Added);
|
|
278
|
+
expect(callback).toHaveBeenCalledWith("parent1", "child1", RelationshipChangeType.Added);
|
|
279
|
+
});
|
|
280
|
+
it("should filter by parentId", () => {
|
|
281
|
+
const callback = vi.fn();
|
|
282
|
+
const search = { parentId: "parent1" };
|
|
283
|
+
manager.onRelationshipChanged(callback, search);
|
|
284
|
+
manager.notifyRelationshipChanged("parent1", "child1", RelationshipChangeType.Added);
|
|
285
|
+
manager.notifyRelationshipChanged("parent2", "child2", RelationshipChangeType.Added);
|
|
286
|
+
expect(callback).toHaveBeenCalledTimes(1);
|
|
287
|
+
expect(callback).toHaveBeenCalledWith("parent1", "child1", RelationshipChangeType.Added);
|
|
288
|
+
});
|
|
289
|
+
it("should filter by child document type", () => {
|
|
290
|
+
const callback = vi.fn();
|
|
291
|
+
const search = { type: "Task" };
|
|
292
|
+
manager.onRelationshipChanged(callback, search);
|
|
293
|
+
manager.notifyRelationshipChanged("parent1", "child1", RelationshipChangeType.Added, "Task");
|
|
294
|
+
manager.notifyRelationshipChanged("parent1", "child2", RelationshipChangeType.Added, "Document");
|
|
295
|
+
expect(callback).toHaveBeenCalledTimes(1);
|
|
296
|
+
expect(callback).toHaveBeenCalledWith("parent1", "child1", RelationshipChangeType.Added);
|
|
297
|
+
});
|
|
298
|
+
it("should filter by child IDs", () => {
|
|
299
|
+
const callback = vi.fn();
|
|
300
|
+
const search = { ids: ["child1", "child3"] };
|
|
301
|
+
manager.onRelationshipChanged(callback, search);
|
|
302
|
+
manager.notifyRelationshipChanged("parent1", "child1", RelationshipChangeType.Added);
|
|
303
|
+
manager.notifyRelationshipChanged("parent1", "child2", RelationshipChangeType.Added);
|
|
304
|
+
manager.notifyRelationshipChanged("parent1", "child3", RelationshipChangeType.Removed);
|
|
305
|
+
expect(callback).toHaveBeenCalledTimes(2);
|
|
306
|
+
expect(callback).toHaveBeenNthCalledWith(1, "parent1", "child1", RelationshipChangeType.Added);
|
|
307
|
+
expect(callback).toHaveBeenNthCalledWith(2, "parent1", "child3", RelationshipChangeType.Removed);
|
|
308
|
+
});
|
|
309
|
+
});
|
|
310
|
+
});
|
|
311
|
+
describe("Utility Methods", () => {
|
|
312
|
+
describe("clearAll", () => {
|
|
313
|
+
it("should remove all subscriptions", () => {
|
|
314
|
+
const createdCallback = vi.fn();
|
|
315
|
+
const deletedCallback = vi.fn();
|
|
316
|
+
const updatedCallback = vi.fn();
|
|
317
|
+
const relationshipCallback = vi.fn();
|
|
318
|
+
manager.onDocumentCreated(createdCallback);
|
|
319
|
+
manager.onDocumentDeleted(deletedCallback);
|
|
320
|
+
manager.onDocumentStateUpdated(updatedCallback);
|
|
321
|
+
manager.onRelationshipChanged(relationshipCallback);
|
|
322
|
+
// Verify all subscriptions work
|
|
323
|
+
manager.notifyDocumentsCreated(["doc1"]);
|
|
324
|
+
manager.notifyDocumentsDeleted(["doc2"]);
|
|
325
|
+
const doc = {
|
|
326
|
+
header: { id: "doc3", documentType: "Task", slug: "task-3" },
|
|
327
|
+
};
|
|
328
|
+
manager.notifyDocumentsUpdated([doc]);
|
|
329
|
+
manager.notifyRelationshipChanged("parent1", "child1", RelationshipChangeType.Added);
|
|
330
|
+
expect(createdCallback).toHaveBeenCalledTimes(1);
|
|
331
|
+
expect(deletedCallback).toHaveBeenCalledTimes(1);
|
|
332
|
+
expect(updatedCallback).toHaveBeenCalledTimes(1);
|
|
333
|
+
expect(relationshipCallback).toHaveBeenCalledTimes(1);
|
|
334
|
+
// Clear all subscriptions
|
|
335
|
+
manager.clearAll();
|
|
336
|
+
// Verify no callbacks are called after clearAll
|
|
337
|
+
manager.notifyDocumentsCreated(["doc4"]);
|
|
338
|
+
manager.notifyDocumentsDeleted(["doc5"]);
|
|
339
|
+
manager.notifyDocumentsUpdated([doc]);
|
|
340
|
+
manager.notifyRelationshipChanged("parent2", "child2", RelationshipChangeType.Removed);
|
|
341
|
+
// All callbacks should still have been called only once
|
|
342
|
+
expect(createdCallback).toHaveBeenCalledTimes(1);
|
|
343
|
+
expect(deletedCallback).toHaveBeenCalledTimes(1);
|
|
344
|
+
expect(updatedCallback).toHaveBeenCalledTimes(1);
|
|
345
|
+
expect(relationshipCallback).toHaveBeenCalledTimes(1);
|
|
346
|
+
});
|
|
347
|
+
it("should not notify cleared subscriptions", () => {
|
|
348
|
+
const callback = vi.fn();
|
|
349
|
+
manager.onDocumentCreated(callback);
|
|
350
|
+
// Verify subscription works before clear
|
|
351
|
+
manager.notifyDocumentsCreated(["doc1"]);
|
|
352
|
+
expect(callback).toHaveBeenCalledTimes(1);
|
|
353
|
+
// Clear and verify no more notifications
|
|
354
|
+
manager.clearAll();
|
|
355
|
+
manager.notifyDocumentsCreated(["doc2"]);
|
|
356
|
+
expect(callback).toHaveBeenCalledTimes(1); // Still 1
|
|
357
|
+
});
|
|
358
|
+
});
|
|
359
|
+
});
|
|
360
|
+
describe("Complex Filtering Scenarios", () => {
|
|
361
|
+
it("should handle multiple filters in combination", () => {
|
|
362
|
+
const callback = vi.fn();
|
|
363
|
+
const search = {
|
|
364
|
+
type: "Task",
|
|
365
|
+
parentId: "parent1",
|
|
366
|
+
ids: ["doc1", "doc2", "doc3"],
|
|
367
|
+
};
|
|
368
|
+
manager.onDocumentCreated(callback, search);
|
|
369
|
+
const documentIds = ["doc1", "doc2", "doc3", "doc4"];
|
|
370
|
+
const types = new Map([
|
|
371
|
+
["doc1", "Task"],
|
|
372
|
+
["doc2", "Document"],
|
|
373
|
+
["doc3", "Task"],
|
|
374
|
+
["doc4", "Task"],
|
|
375
|
+
]);
|
|
376
|
+
const parentIds = new Map([
|
|
377
|
+
["doc1", "parent1"],
|
|
378
|
+
["doc2", "parent1"],
|
|
379
|
+
["doc3", "parent2"],
|
|
380
|
+
["doc4", "parent1"],
|
|
381
|
+
]);
|
|
382
|
+
manager.notifyDocumentsCreated(documentIds, types, parentIds);
|
|
383
|
+
// Only doc1 matches all criteria: id in list, type=Task, parentId=parent1
|
|
384
|
+
expect(callback).toHaveBeenCalledWith(expect.objectContaining({
|
|
385
|
+
results: ["doc1"],
|
|
386
|
+
}));
|
|
387
|
+
});
|
|
388
|
+
it("should handle subscriptions with no filters", () => {
|
|
389
|
+
const callback = vi.fn();
|
|
390
|
+
manager.onDocumentCreated(callback);
|
|
391
|
+
const documentIds = ["doc1", "doc2", "doc3"];
|
|
392
|
+
manager.notifyDocumentsCreated(documentIds);
|
|
393
|
+
expect(callback).toHaveBeenCalledWith(expect.objectContaining({
|
|
394
|
+
results: documentIds,
|
|
395
|
+
}));
|
|
396
|
+
});
|
|
397
|
+
it("should handle empty document lists", () => {
|
|
398
|
+
const callback = vi.fn();
|
|
399
|
+
manager.onDocumentCreated(callback);
|
|
400
|
+
manager.notifyDocumentsCreated([]);
|
|
401
|
+
expect(callback).not.toHaveBeenCalled();
|
|
402
|
+
});
|
|
403
|
+
it("should handle null parent IDs", () => {
|
|
404
|
+
const callback = vi.fn();
|
|
405
|
+
const search = { parentId: "parent1" };
|
|
406
|
+
manager.onDocumentCreated(callback, search);
|
|
407
|
+
const documentIds = ["doc1", "doc2", "doc3"];
|
|
408
|
+
const parentIds = new Map([
|
|
409
|
+
["doc1", "parent1"],
|
|
410
|
+
["doc2", null],
|
|
411
|
+
["doc3", "parent1"],
|
|
412
|
+
]);
|
|
413
|
+
manager.notifyDocumentsCreated(documentIds, undefined, parentIds);
|
|
414
|
+
expect(callback).toHaveBeenCalledWith(expect.objectContaining({
|
|
415
|
+
results: ["doc1", "doc3"],
|
|
416
|
+
}));
|
|
417
|
+
});
|
|
418
|
+
});
|
|
419
|
+
describe("Independent Subscription Management", () => {
|
|
420
|
+
it("should manage subscriptions independently", () => {
|
|
421
|
+
const createdCallback = vi.fn();
|
|
422
|
+
const deletedCallback = vi.fn();
|
|
423
|
+
const updatedCallback = vi.fn();
|
|
424
|
+
manager.onDocumentCreated(createdCallback);
|
|
425
|
+
manager.onDocumentDeleted(deletedCallback);
|
|
426
|
+
manager.onDocumentStateUpdated(updatedCallback);
|
|
427
|
+
// Notify created - should only call created callback
|
|
428
|
+
manager.notifyDocumentsCreated(["doc1"]);
|
|
429
|
+
expect(createdCallback).toHaveBeenCalledTimes(1);
|
|
430
|
+
expect(deletedCallback).not.toHaveBeenCalled();
|
|
431
|
+
expect(updatedCallback).not.toHaveBeenCalled();
|
|
432
|
+
// Notify deleted - should only call deleted callback
|
|
433
|
+
manager.notifyDocumentsDeleted(["doc2"]);
|
|
434
|
+
expect(createdCallback).toHaveBeenCalledTimes(1);
|
|
435
|
+
expect(deletedCallback).toHaveBeenCalledTimes(1);
|
|
436
|
+
expect(updatedCallback).not.toHaveBeenCalled();
|
|
437
|
+
// Notify updated - should only call updated callback
|
|
438
|
+
const doc = {
|
|
439
|
+
header: { id: "doc3", documentType: "Task", slug: "task-3" },
|
|
440
|
+
};
|
|
441
|
+
manager.notifyDocumentsUpdated([doc]);
|
|
442
|
+
expect(createdCallback).toHaveBeenCalledTimes(1);
|
|
443
|
+
expect(deletedCallback).toHaveBeenCalledTimes(1);
|
|
444
|
+
expect(updatedCallback).toHaveBeenCalledTimes(1);
|
|
445
|
+
});
|
|
446
|
+
it("should handle multiple unsubscribes correctly", () => {
|
|
447
|
+
const callback1 = vi.fn();
|
|
448
|
+
const callback2 = vi.fn();
|
|
449
|
+
const callback3 = vi.fn();
|
|
450
|
+
const unsub1 = manager.onDocumentCreated(callback1);
|
|
451
|
+
const unsub2 = manager.onDocumentCreated(callback2);
|
|
452
|
+
const unsub3 = manager.onDocumentCreated(callback3);
|
|
453
|
+
// Unsubscribe middle one
|
|
454
|
+
unsub2();
|
|
455
|
+
manager.notifyDocumentsCreated(["doc1"]);
|
|
456
|
+
expect(callback1).toHaveBeenCalled();
|
|
457
|
+
expect(callback2).not.toHaveBeenCalled();
|
|
458
|
+
expect(callback3).toHaveBeenCalled();
|
|
459
|
+
// Unsubscribe remaining
|
|
460
|
+
unsub1();
|
|
461
|
+
unsub3();
|
|
462
|
+
manager.notifyDocumentsCreated(["doc2"]);
|
|
463
|
+
expect(callback1).toHaveBeenCalledTimes(1);
|
|
464
|
+
expect(callback2).toHaveBeenCalledTimes(0);
|
|
465
|
+
expect(callback3).toHaveBeenCalledTimes(1);
|
|
466
|
+
});
|
|
467
|
+
it("should handle double unsubscribe gracefully", () => {
|
|
468
|
+
const callback = vi.fn();
|
|
469
|
+
const unsubscribe = manager.onDocumentCreated(callback);
|
|
470
|
+
// Verify subscription works
|
|
471
|
+
manager.notifyDocumentsCreated(["doc1"]);
|
|
472
|
+
expect(callback).toHaveBeenCalledTimes(1);
|
|
473
|
+
// First unsubscribe
|
|
474
|
+
unsubscribe();
|
|
475
|
+
manager.notifyDocumentsCreated(["doc2"]);
|
|
476
|
+
expect(callback).toHaveBeenCalledTimes(1); // Still 1
|
|
477
|
+
// Second unsubscribe should not cause issues
|
|
478
|
+
unsubscribe();
|
|
479
|
+
manager.notifyDocumentsCreated(["doc3"]);
|
|
480
|
+
expect(callback).toHaveBeenCalledTimes(1); // Still 1
|
|
481
|
+
});
|
|
482
|
+
});
|
|
483
|
+
describe("Error Handling and Guaranteed Delivery", () => {
|
|
484
|
+
let errorHandler;
|
|
485
|
+
let errorManager;
|
|
486
|
+
beforeEach(() => {
|
|
487
|
+
errorHandler = {
|
|
488
|
+
handleError: vi.fn(),
|
|
489
|
+
};
|
|
490
|
+
errorManager = new ReactorSubscriptionManager(errorHandler);
|
|
491
|
+
});
|
|
492
|
+
describe("Document Created Events", () => {
|
|
493
|
+
it("should catch errors and continue delivering to other subscribers", () => {
|
|
494
|
+
const callback1 = vi.fn();
|
|
495
|
+
const callback2 = vi.fn().mockImplementation(() => {
|
|
496
|
+
throw new Error("Callback 2 error");
|
|
497
|
+
});
|
|
498
|
+
const callback3 = vi.fn();
|
|
499
|
+
errorManager.onDocumentCreated(callback1);
|
|
500
|
+
errorManager.onDocumentCreated(callback2);
|
|
501
|
+
errorManager.onDocumentCreated(callback3);
|
|
502
|
+
errorManager.notifyDocumentsCreated(["doc1"]);
|
|
503
|
+
// All callbacks should be called despite callback2 throwing
|
|
504
|
+
expect(callback1).toHaveBeenCalledTimes(1);
|
|
505
|
+
expect(callback2).toHaveBeenCalledTimes(1);
|
|
506
|
+
expect(callback3).toHaveBeenCalledTimes(1);
|
|
507
|
+
// Error handler should be called for callback2
|
|
508
|
+
expect(errorHandler.handleError).toHaveBeenCalledTimes(1);
|
|
509
|
+
expect(errorHandler.handleError).toHaveBeenCalledWith(expect.any(Error), expect.objectContaining({
|
|
510
|
+
eventType: "created",
|
|
511
|
+
subscriptionId: expect.stringContaining("created-"),
|
|
512
|
+
eventData: ["doc1"],
|
|
513
|
+
}));
|
|
514
|
+
});
|
|
515
|
+
it("should provide error context with filtered data", () => {
|
|
516
|
+
const callback = vi.fn().mockImplementation(() => {
|
|
517
|
+
throw new Error("Test error");
|
|
518
|
+
});
|
|
519
|
+
errorManager.onDocumentCreated(callback, { type: "Task" });
|
|
520
|
+
const documentIds = ["doc1", "doc2"];
|
|
521
|
+
const types = new Map([
|
|
522
|
+
["doc1", "Task"],
|
|
523
|
+
["doc2", "Document"],
|
|
524
|
+
]);
|
|
525
|
+
errorManager.notifyDocumentsCreated(documentIds, types);
|
|
526
|
+
expect(errorHandler.handleError).toHaveBeenCalledWith(expect.any(Error), expect.objectContaining({
|
|
527
|
+
eventType: "created",
|
|
528
|
+
eventData: ["doc1"], // Only filtered doc
|
|
529
|
+
}));
|
|
530
|
+
});
|
|
531
|
+
});
|
|
532
|
+
describe("Document Deleted Events", () => {
|
|
533
|
+
it("should catch errors and continue delivering to other subscribers", () => {
|
|
534
|
+
const callback1 = vi.fn();
|
|
535
|
+
const callback2 = vi.fn().mockImplementation(() => {
|
|
536
|
+
throw new Error("Delete callback error");
|
|
537
|
+
});
|
|
538
|
+
const callback3 = vi.fn();
|
|
539
|
+
errorManager.onDocumentDeleted(callback1);
|
|
540
|
+
errorManager.onDocumentDeleted(callback2);
|
|
541
|
+
errorManager.onDocumentDeleted(callback3);
|
|
542
|
+
errorManager.notifyDocumentsDeleted(["doc1", "doc2"]);
|
|
543
|
+
expect(callback1).toHaveBeenCalledTimes(1);
|
|
544
|
+
expect(callback2).toHaveBeenCalledTimes(1);
|
|
545
|
+
expect(callback3).toHaveBeenCalledTimes(1);
|
|
546
|
+
expect(errorHandler.handleError).toHaveBeenCalledTimes(1);
|
|
547
|
+
expect(errorHandler.handleError).toHaveBeenCalledWith(expect.any(Error), expect.objectContaining({
|
|
548
|
+
eventType: "deleted",
|
|
549
|
+
eventData: ["doc1", "doc2"],
|
|
550
|
+
}));
|
|
551
|
+
});
|
|
552
|
+
});
|
|
553
|
+
describe("Document Updated Events", () => {
|
|
554
|
+
it("should catch errors and continue delivering to other subscribers", () => {
|
|
555
|
+
const callback1 = vi.fn();
|
|
556
|
+
const callback2 = vi.fn().mockImplementation(() => {
|
|
557
|
+
throw new Error("Update callback error");
|
|
558
|
+
});
|
|
559
|
+
const callback3 = vi.fn();
|
|
560
|
+
errorManager.onDocumentStateUpdated(callback1);
|
|
561
|
+
errorManager.onDocumentStateUpdated(callback2);
|
|
562
|
+
errorManager.onDocumentStateUpdated(callback3);
|
|
563
|
+
const doc = {
|
|
564
|
+
header: {
|
|
565
|
+
id: "doc1",
|
|
566
|
+
documentType: "Task",
|
|
567
|
+
slug: "task-1",
|
|
568
|
+
},
|
|
569
|
+
};
|
|
570
|
+
errorManager.notifyDocumentsUpdated([doc]);
|
|
571
|
+
expect(callback1).toHaveBeenCalledTimes(1);
|
|
572
|
+
expect(callback2).toHaveBeenCalledTimes(1);
|
|
573
|
+
expect(callback3).toHaveBeenCalledTimes(1);
|
|
574
|
+
expect(errorHandler.handleError).toHaveBeenCalledTimes(1);
|
|
575
|
+
expect(errorHandler.handleError).toHaveBeenCalledWith(expect.any(Error), expect.objectContaining({
|
|
576
|
+
eventType: "updated",
|
|
577
|
+
eventData: [doc],
|
|
578
|
+
}));
|
|
579
|
+
});
|
|
580
|
+
});
|
|
581
|
+
describe("Relationship Changed Events", () => {
|
|
582
|
+
it("should catch errors and continue delivering to other subscribers", () => {
|
|
583
|
+
const callback1 = vi.fn();
|
|
584
|
+
const callback2 = vi.fn().mockImplementation(() => {
|
|
585
|
+
throw new Error("Relationship callback error");
|
|
586
|
+
});
|
|
587
|
+
const callback3 = vi.fn();
|
|
588
|
+
errorManager.onRelationshipChanged(callback1);
|
|
589
|
+
errorManager.onRelationshipChanged(callback2);
|
|
590
|
+
errorManager.onRelationshipChanged(callback3);
|
|
591
|
+
errorManager.notifyRelationshipChanged("parent1", "child1", RelationshipChangeType.Added);
|
|
592
|
+
expect(callback1).toHaveBeenCalledTimes(1);
|
|
593
|
+
expect(callback2).toHaveBeenCalledTimes(1);
|
|
594
|
+
expect(callback3).toHaveBeenCalledTimes(1);
|
|
595
|
+
expect(errorHandler.handleError).toHaveBeenCalledTimes(1);
|
|
596
|
+
expect(errorHandler.handleError).toHaveBeenCalledWith(expect.any(Error), expect.objectContaining({
|
|
597
|
+
eventType: "relationshipChanged",
|
|
598
|
+
eventData: {
|
|
599
|
+
parentId: "parent1",
|
|
600
|
+
childId: "child1",
|
|
601
|
+
changeType: RelationshipChangeType.Added,
|
|
602
|
+
},
|
|
603
|
+
}));
|
|
604
|
+
});
|
|
605
|
+
});
|
|
606
|
+
describe("Multiple Errors", () => {
|
|
607
|
+
it("should handle multiple errors in the same notification", () => {
|
|
608
|
+
const callback1 = vi.fn().mockImplementation(() => {
|
|
609
|
+
throw new Error("Error 1");
|
|
610
|
+
});
|
|
611
|
+
const callback2 = vi.fn();
|
|
612
|
+
const callback3 = vi.fn().mockImplementation(() => {
|
|
613
|
+
throw new Error("Error 3");
|
|
614
|
+
});
|
|
615
|
+
errorManager.onDocumentCreated(callback1);
|
|
616
|
+
errorManager.onDocumentCreated(callback2);
|
|
617
|
+
errorManager.onDocumentCreated(callback3);
|
|
618
|
+
errorManager.notifyDocumentsCreated(["doc1"]);
|
|
619
|
+
// All callbacks should be called
|
|
620
|
+
expect(callback1).toHaveBeenCalledTimes(1);
|
|
621
|
+
expect(callback2).toHaveBeenCalledTimes(1);
|
|
622
|
+
expect(callback3).toHaveBeenCalledTimes(1);
|
|
623
|
+
// Error handler should be called twice
|
|
624
|
+
expect(errorHandler.handleError).toHaveBeenCalledTimes(2);
|
|
625
|
+
});
|
|
626
|
+
it("should handle errors across different event types", () => {
|
|
627
|
+
const createdCallback = vi.fn().mockImplementation(() => {
|
|
628
|
+
throw new Error("Created error");
|
|
629
|
+
});
|
|
630
|
+
const deletedCallback = vi.fn().mockImplementation(() => {
|
|
631
|
+
throw new Error("Deleted error");
|
|
632
|
+
});
|
|
633
|
+
errorManager.onDocumentCreated(createdCallback);
|
|
634
|
+
errorManager.onDocumentDeleted(deletedCallback);
|
|
635
|
+
errorManager.notifyDocumentsCreated(["doc1"]);
|
|
636
|
+
errorManager.notifyDocumentsDeleted(["doc2"]);
|
|
637
|
+
expect(errorHandler.handleError).toHaveBeenCalledTimes(2);
|
|
638
|
+
expect(errorHandler.handleError).toHaveBeenNthCalledWith(1, expect.any(Error), expect.objectContaining({ eventType: "created" }));
|
|
639
|
+
expect(errorHandler.handleError).toHaveBeenNthCalledWith(2, expect.any(Error), expect.objectContaining({ eventType: "deleted" }));
|
|
640
|
+
});
|
|
641
|
+
});
|
|
642
|
+
describe("Default Error Handler", () => {
|
|
643
|
+
it("should throw enhanced errors with context", async () => {
|
|
644
|
+
const { DefaultSubscriptionErrorHandler } = await import("../../src/subs/default-error-handler.js");
|
|
645
|
+
const throwingHandler = new DefaultSubscriptionErrorHandler();
|
|
646
|
+
const throwingManager = new ReactorSubscriptionManager(throwingHandler);
|
|
647
|
+
const callback = vi.fn().mockImplementation(() => {
|
|
648
|
+
throw new Error("Test error");
|
|
649
|
+
});
|
|
650
|
+
throwingManager.onDocumentCreated(callback);
|
|
651
|
+
// The notification should throw because the default handler re-throws
|
|
652
|
+
expect(() => {
|
|
653
|
+
throwingManager.notifyDocumentsCreated(["doc1"]);
|
|
654
|
+
}).toThrow("Subscription error in created");
|
|
655
|
+
});
|
|
656
|
+
it("should handle non-Error objects in default handler", async () => {
|
|
657
|
+
const { DefaultSubscriptionErrorHandler } = await import("../../src/subs/default-error-handler.js");
|
|
658
|
+
const throwingHandler = new DefaultSubscriptionErrorHandler();
|
|
659
|
+
const throwingManager = new ReactorSubscriptionManager(throwingHandler);
|
|
660
|
+
const callback = vi.fn().mockImplementation(() => {
|
|
661
|
+
// eslint-disable-next-line @typescript-eslint/only-throw-error
|
|
662
|
+
throw "string error"; // Throwing a non-Error object to test handling
|
|
663
|
+
});
|
|
664
|
+
throwingManager.onDocumentCreated(callback);
|
|
665
|
+
expect(() => {
|
|
666
|
+
throwingManager.notifyDocumentsCreated(["doc1"]);
|
|
667
|
+
}).toThrow("Subscription error in created");
|
|
668
|
+
});
|
|
669
|
+
});
|
|
670
|
+
describe("Error Handler receives correct subscription IDs", () => {
|
|
671
|
+
it("should pass unique subscription IDs to error handler", () => {
|
|
672
|
+
const callback1 = vi.fn().mockImplementation(() => {
|
|
673
|
+
throw new Error("Error 1");
|
|
674
|
+
});
|
|
675
|
+
const callback2 = vi.fn().mockImplementation(() => {
|
|
676
|
+
throw new Error("Error 2");
|
|
677
|
+
});
|
|
678
|
+
errorManager.onDocumentCreated(callback1);
|
|
679
|
+
errorManager.onDocumentCreated(callback2);
|
|
680
|
+
errorManager.notifyDocumentsCreated(["doc1"]);
|
|
681
|
+
expect(errorHandler.handleError).toHaveBeenCalledTimes(2);
|
|
682
|
+
const mockHandleError = vi.mocked(errorHandler.handleError);
|
|
683
|
+
const calls = mockHandleError.mock.calls;
|
|
684
|
+
const context1 = calls[0][1];
|
|
685
|
+
const context2 = calls[1][1];
|
|
686
|
+
expect(context1.subscriptionId).not.toBe(context2.subscriptionId);
|
|
687
|
+
expect(context1.subscriptionId).toContain("created-");
|
|
688
|
+
expect(context2.subscriptionId).toContain("created-");
|
|
689
|
+
});
|
|
690
|
+
});
|
|
691
|
+
});
|
|
692
|
+
});
|
|
693
|
+
//# sourceMappingURL=react-subscription-manager.test.js.map
|