cojson 0.19.7 → 0.19.10

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.
@@ -148,31 +148,59 @@ describe("transactions that exceed the byte size limit are rejected", () => {
148
148
  });
149
149
  });
150
150
 
151
- test("new transactions in a group correctly update owned values, including subscriptions", async () => {
151
+ test("subscribe to a map emits an update when a new transaction is added", async () => {
152
152
  const client = await setupTestAccount();
153
153
 
154
- const agent = client.node.getCurrentAgent();
155
-
156
154
  const group = client.node.createGroup();
157
155
 
158
156
  const map = group.createMap();
159
157
 
160
- await new Promise((resolve) => setTimeout(resolve, 10));
158
+ const subscriptionSpy = vi.fn();
159
+ const unsubscribe = map.core.subscribe(subscriptionSpy, false);
161
160
 
162
161
  map.set("hello", "world");
163
162
 
164
- const transaction = map.core.getValidSortedTransactions().at(-1);
163
+ await waitFor(() => {
164
+ expect(subscriptionSpy).toHaveBeenCalled();
165
+ });
166
+
167
+ expect(subscriptionSpy).toHaveBeenCalledTimes(1);
168
+ unsubscribe();
169
+ });
170
+
171
+ test("new transactions in a group correctly update owned values, including subscriptions", async () => {
172
+ const alice = await setupTestAccount({
173
+ connected: true,
174
+ });
175
+
176
+ const bob = await setupTestAccount({
177
+ connected: true,
178
+ });
179
+
180
+ const bobAccount = await loadCoValueOrFail(alice.node, bob.accountID);
181
+ const group = alice.node.createGroup();
182
+
183
+ group.addMember(bobAccount, "writer");
184
+
185
+ const map = group.createMap();
186
+
187
+ await new Promise((resolve) => setTimeout(resolve, 10));
188
+
189
+ const mapOnBob = await loadCoValueOrFail(bob.node, map.id);
190
+ mapOnBob.set("hello", "world");
191
+
192
+ const transaction = mapOnBob.core.getValidSortedTransactions().at(-1);
165
193
 
166
194
  assert(transaction);
167
195
 
168
196
  expect(transaction.isValid).toBe(true);
169
- expect(group.get(agent.id)).toBe("admin");
197
+ expect(group.roleOf(bobAccount.id)).toBe("writer");
170
198
 
171
199
  group.core.makeTransaction(
172
200
  [
173
201
  {
174
202
  op: "set",
175
- key: agent.id,
203
+ key: bobAccount.id,
176
204
  value: "revoked",
177
205
  },
178
206
  ],
@@ -181,48 +209,49 @@ test("new transactions in a group correctly update owned values, including subsc
181
209
  transaction.madeAt - 1, // Make the revocation to be before the map update
182
210
  );
183
211
 
184
- expect(group.get(agent.id)).toBe("revoked");
212
+ await group.core.waitForSync();
213
+
214
+ expect(transaction.isValid).toBe(false);
215
+ expect(mapOnBob.core.getValidSortedTransactions().length).toBe(0);
185
216
  expect(map.core.getValidSortedTransactions().length).toBe(0);
186
217
  });
187
218
 
188
- // TODO: The test is skipped because we don't support this invalidation yet
189
- test.skip("new transactions in a parent group correctly update owned values, including subscriptions", async () => {
190
- const client = await setupTestAccount();
219
+ test("new transactions in a parent group correctly update owned values, including subscriptions", async () => {
220
+ const alice = await setupTestAccount({
221
+ connected: true,
222
+ });
191
223
 
192
- const agent = client.node.getCurrentAgent();
224
+ const bob = await setupTestAccount({
225
+ connected: true,
226
+ });
193
227
 
194
- const group = client.node.createGroup();
195
- const parentGroup = client.node.createGroup();
228
+ const bobAccount = await loadCoValueOrFail(alice.node, bob.accountID);
229
+ const parentGroup = alice.node.createGroup();
230
+
231
+ parentGroup.addMember(bobAccount, "writer");
232
+
233
+ const group = alice.node.createGroup();
196
234
  group.extend(parentGroup);
197
- group.core.makeTransaction(
198
- [
199
- {
200
- op: "set",
201
- key: agent.id,
202
- value: "revoked",
203
- },
204
- ],
205
- "trusting",
206
- );
207
235
 
208
236
  const map = group.createMap();
209
237
 
210
238
  await new Promise((resolve) => setTimeout(resolve, 10));
211
239
 
212
- map.set("hello", "world");
240
+ const mapOnBob = await loadCoValueOrFail(bob.node, map.id);
241
+ mapOnBob.set("hello", "world");
213
242
 
214
- const transaction = map.core.getValidSortedTransactions().at(-1);
243
+ const transaction = mapOnBob.core.getValidSortedTransactions().at(-1);
215
244
 
216
245
  assert(transaction);
217
246
 
218
247
  expect(transaction.isValid).toBe(true);
219
- expect(group.roleOfInternal(agent.id)).toBe("admin");
248
+ expect(group.roleOf(bobAccount.id)).toBe("writer");
220
249
 
221
250
  parentGroup.core.makeTransaction(
222
251
  [
223
252
  {
224
253
  op: "set",
225
- key: agent.id,
254
+ key: bobAccount.id,
226
255
  value: "revoked",
227
256
  },
228
257
  ],
@@ -231,11 +260,98 @@ test.skip("new transactions in a parent group correctly update owned values, inc
231
260
  transaction.madeAt - 1, // Make the revocation to be before the map update
232
261
  );
233
262
 
234
- expect(group.roleOfInternal(agent.id)).toBe(undefined);
263
+ await parentGroup.core.waitForSync();
235
264
 
236
- await waitFor(() =>
237
- expect(map.core.getValidSortedTransactions().length).toBe(0),
238
- );
265
+ expect(transaction.isValid).toBe(false);
266
+ expect(mapOnBob.core.getValidSortedTransactions().length).toBe(0);
267
+ expect(map.core.getValidSortedTransactions().length).toBe(0);
268
+ });
269
+
270
+ test("resetParsedTransactions triggers rebuildFromCore only when the validation state changes", async () => {
271
+ const alice = await setupTestAccount({
272
+ connected: true,
273
+ });
274
+ const bob = await setupTestAccount({
275
+ connected: true,
276
+ });
277
+
278
+ const group = alice.node.createGroup();
279
+
280
+ const map = group.createMap();
281
+
282
+ map.set("hello", "world");
283
+
284
+ const rebuildOnAliceSpy = vi.spyOn(map, "rebuildFromCore");
285
+
286
+ const mapOnBob = await loadCoValueOrFail(bob.node, map.id);
287
+
288
+ const rebuildOnBobSpy = vi.spyOn(mapOnBob, "rebuildFromCore");
289
+
290
+ group.addMember("everyone", "reader");
291
+
292
+ await group.core.waitForSync();
293
+
294
+ expect(rebuildOnAliceSpy).toHaveBeenCalledTimes(0);
295
+ expect(rebuildOnBobSpy).toHaveBeenCalledTimes(1);
296
+ });
297
+
298
+ test("group change trigger a subscription emit, even if the content doesn't change", async () => {
299
+ const alice = await setupTestAccount({
300
+ connected: true,
301
+ });
302
+ const bob = await setupTestAccount({
303
+ connected: true,
304
+ });
305
+
306
+ const group = alice.node.createGroup();
307
+
308
+ const map = group.createMap();
309
+
310
+ map.set("hello", "world");
311
+
312
+ const mapOnBob = await loadCoValueOrFail(bob.node, map.id);
313
+
314
+ const aliceSubscriptionSpy = vi.fn();
315
+ const aliceUnsubscribe = map.subscribe(aliceSubscriptionSpy);
316
+ const bobSubscriptionSpy = vi.fn();
317
+ const bobUnsubscribe = mapOnBob.subscribe(bobSubscriptionSpy);
318
+ aliceSubscriptionSpy.mockClear();
319
+ bobSubscriptionSpy.mockClear();
320
+
321
+ group.addMember("everyone", "reader");
322
+
323
+ await waitFor(() => {
324
+ expect(aliceSubscriptionSpy).toHaveBeenCalledTimes(1);
325
+ expect(bobSubscriptionSpy).toHaveBeenCalledTimes(1);
326
+ });
327
+
328
+ aliceUnsubscribe();
329
+ bobUnsubscribe();
330
+ });
331
+
332
+ test("changing parent and child group trigger only one invalidation on the local map", async () => {
333
+ const alice = await setupTestAccount();
334
+
335
+ const parentGroup = alice.node.createGroup();
336
+ const group = alice.node.createGroup();
337
+ group.extend(parentGroup);
338
+
339
+ const map = group.createMap();
340
+
341
+ map.set("hello", "world");
342
+
343
+ const aliceSubscriptionSpy = vi.fn();
344
+ const aliceUnsubscribe = map.subscribe(aliceSubscriptionSpy);
345
+ aliceSubscriptionSpy.mockClear();
346
+
347
+ parentGroup.addMember("everyone", "reader");
348
+ group.addMember("everyone", "reader");
349
+
350
+ await waitFor(() => {
351
+ expect(aliceSubscriptionSpy).toHaveBeenCalledTimes(1);
352
+ });
353
+
354
+ aliceUnsubscribe();
239
355
  });
240
356
 
241
357
  test("correctly records transactions", async () => {