cojson 0.10.8 → 0.10.15

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.
Files changed (59) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/CHANGELOG.md +6 -0
  3. package/dist/coValueCore.js +3 -9
  4. package/dist/coValueCore.js.map +1 -1
  5. package/dist/coValues/account.js +9 -10
  6. package/dist/coValues/account.js.map +1 -1
  7. package/dist/coValues/group.js +1 -3
  8. package/dist/coValues/group.js.map +1 -1
  9. package/dist/localNode.js +3 -5
  10. package/dist/localNode.js.map +1 -1
  11. package/dist/permissions.js +2 -5
  12. package/dist/permissions.js.map +1 -1
  13. package/dist/tests/PeerKnownStates.test.js +82 -0
  14. package/dist/tests/PeerKnownStates.test.js.map +1 -0
  15. package/dist/tests/PeerState.test.js +188 -0
  16. package/dist/tests/PeerState.test.js.map +1 -0
  17. package/dist/tests/PriorityBasedMessageQueue.test.js +120 -0
  18. package/dist/tests/PriorityBasedMessageQueue.test.js.map +1 -0
  19. package/dist/tests/SyncStateManager.test.js +127 -0
  20. package/dist/tests/SyncStateManager.test.js.map +1 -0
  21. package/dist/tests/account.test.js +66 -0
  22. package/dist/tests/account.test.js.map +1 -0
  23. package/dist/tests/coList.test.js +120 -0
  24. package/dist/tests/coList.test.js.map +1 -0
  25. package/dist/tests/coMap.test.js +164 -0
  26. package/dist/tests/coMap.test.js.map +1 -0
  27. package/dist/tests/coPlainText.test.js +99 -0
  28. package/dist/tests/coPlainText.test.js.map +1 -0
  29. package/dist/tests/coStream.test.js +206 -0
  30. package/dist/tests/coStream.test.js.map +1 -0
  31. package/dist/tests/coValueCore.test.js +164 -0
  32. package/dist/tests/coValueCore.test.js.map +1 -0
  33. package/dist/tests/coValueState.test.js +364 -0
  34. package/dist/tests/coValueState.test.js.map +1 -0
  35. package/dist/tests/crypto.test.js +144 -0
  36. package/dist/tests/crypto.test.js.map +1 -0
  37. package/dist/tests/cryptoImpl.test.js +144 -0
  38. package/dist/tests/cryptoImpl.test.js.map +1 -0
  39. package/dist/tests/group.test.js +446 -0
  40. package/dist/tests/group.test.js.map +1 -0
  41. package/dist/tests/logger.test.js +118 -0
  42. package/dist/tests/logger.test.js.map +1 -0
  43. package/dist/tests/permissions.test.js +1858 -0
  44. package/dist/tests/permissions.test.js.map +1 -0
  45. package/dist/tests/priority.test.js +61 -0
  46. package/dist/tests/priority.test.js.map +1 -0
  47. package/dist/tests/sync.test.js +1548 -0
  48. package/dist/tests/sync.test.js.map +1 -0
  49. package/dist/tests/testUtils.js +312 -0
  50. package/dist/tests/testUtils.js.map +1 -0
  51. package/package.json +1 -1
  52. package/src/coValueCore.ts +3 -9
  53. package/src/coValues/account.ts +15 -15
  54. package/src/coValues/group.ts +1 -3
  55. package/src/localNode.ts +3 -5
  56. package/src/permissions.ts +2 -11
  57. package/src/tests/coValueCore.test.ts +2 -2
  58. package/src/tests/permissions.test.ts +45 -57
  59. package/tsconfig.json +1 -1
@@ -0,0 +1,188 @@
1
+ import { describe, expect, test, vi } from "vitest";
2
+ import { PeerState } from "../PeerState.js";
3
+ import { CO_VALUE_PRIORITY } from "../priority.js";
4
+ function setup() {
5
+ const mockPeer = {
6
+ id: "test-peer",
7
+ role: "peer",
8
+ priority: 1,
9
+ crashOnClose: false,
10
+ incoming: (async function* () { })(),
11
+ outgoing: {
12
+ push: vi.fn().mockResolvedValue(undefined),
13
+ close: vi.fn(),
14
+ },
15
+ };
16
+ const peerState = new PeerState(mockPeer, undefined);
17
+ return { mockPeer, peerState };
18
+ }
19
+ describe("PeerState", () => {
20
+ test("should push outgoing message to peer", async () => {
21
+ const { mockPeer, peerState } = setup();
22
+ const message = {
23
+ action: "load",
24
+ id: "co_ztest-id",
25
+ header: false,
26
+ sessions: {},
27
+ };
28
+ await peerState.pushOutgoingMessage(message);
29
+ expect(mockPeer.outgoing.push).toHaveBeenCalledWith(message);
30
+ });
31
+ test("should return peer's incoming when not closed", () => {
32
+ const { mockPeer, peerState } = setup();
33
+ expect(peerState.incoming).toBe(mockPeer.incoming);
34
+ });
35
+ test("should return Disconnected when closed", async () => {
36
+ const { peerState } = setup();
37
+ peerState.gracefulShutdown();
38
+ const incomingIterator = peerState.incoming[Symbol.asyncIterator]();
39
+ const { value, done } = await incomingIterator.next();
40
+ expect(value).toBe("Disconnected");
41
+ expect(done).toBe(false);
42
+ });
43
+ test("should perform graceful shutdown", () => {
44
+ const { mockPeer, peerState } = setup();
45
+ peerState.gracefulShutdown();
46
+ expect(mockPeer.outgoing.close).toHaveBeenCalled();
47
+ expect(peerState.closed).toBe(true);
48
+ });
49
+ test("should empty the queue when closing", async () => {
50
+ const { mockPeer, peerState } = setup();
51
+ mockPeer.outgoing.push = vi.fn().mockImplementation((message) => {
52
+ return new Promise((resolve) => {
53
+ setTimeout(resolve, 100);
54
+ });
55
+ });
56
+ const message1 = peerState.pushOutgoingMessage({
57
+ action: "content",
58
+ id: "co_z1",
59
+ new: {},
60
+ priority: CO_VALUE_PRIORITY.HIGH,
61
+ });
62
+ const message2 = peerState.pushOutgoingMessage({
63
+ action: "content",
64
+ id: "co_z1",
65
+ new: {},
66
+ priority: CO_VALUE_PRIORITY.HIGH,
67
+ });
68
+ peerState.gracefulShutdown();
69
+ await Promise.allSettled([message1, message2]);
70
+ await expect(message1).resolves.toBe(undefined);
71
+ await expect(message2).resolves.toBe(undefined);
72
+ });
73
+ test("should schedule outgoing messages based on their priority", async () => {
74
+ const { peerState } = setup();
75
+ const loadMessage = {
76
+ action: "load",
77
+ id: "co_zhigh",
78
+ header: false,
79
+ sessions: {},
80
+ };
81
+ const contentMessageHigh = {
82
+ action: "content",
83
+ id: "co_zhigh",
84
+ new: {},
85
+ priority: CO_VALUE_PRIORITY.HIGH,
86
+ };
87
+ const contentMessageMid = {
88
+ action: "content",
89
+ id: "co_zmid",
90
+ new: {},
91
+ priority: CO_VALUE_PRIORITY.MEDIUM,
92
+ };
93
+ const contentMessageLow = {
94
+ action: "content",
95
+ id: "co_zlow",
96
+ new: {},
97
+ priority: CO_VALUE_PRIORITY.LOW,
98
+ };
99
+ const promises = [
100
+ peerState.pushOutgoingMessage(contentMessageLow),
101
+ peerState.pushOutgoingMessage(contentMessageMid),
102
+ peerState.pushOutgoingMessage(contentMessageHigh),
103
+ peerState.pushOutgoingMessage(loadMessage),
104
+ ];
105
+ await Promise.all(promises);
106
+ // The first message is pushed directly, the other three are queued because are waiting
107
+ // for the first push to be completed.
108
+ expect(peerState["peer"].outgoing.push).toHaveBeenNthCalledWith(1, contentMessageLow);
109
+ // Load message are managed as high priority messages and having the same priority as the content message
110
+ // they follow the push order.
111
+ expect(peerState["peer"].outgoing.push).toHaveBeenNthCalledWith(2, contentMessageHigh);
112
+ expect(peerState["peer"].outgoing.push).toHaveBeenNthCalledWith(3, loadMessage);
113
+ expect(peerState["peer"].outgoing.push).toHaveBeenNthCalledWith(4, contentMessageMid);
114
+ });
115
+ test("should clone the knownStates into optimisticKnownStates and knownStates when passed as argument", () => {
116
+ const { peerState, mockPeer } = setup();
117
+ const action = {
118
+ type: "SET",
119
+ id: "co_z1",
120
+ value: {
121
+ id: "co_z1",
122
+ header: false,
123
+ sessions: {},
124
+ },
125
+ };
126
+ peerState.dispatchToKnownStates(action);
127
+ const newPeerState = new PeerState(mockPeer, peerState.knownStates);
128
+ expect(newPeerState.knownStates).toEqual(peerState.knownStates);
129
+ expect(newPeerState.optimisticKnownStates).toEqual(peerState.knownStates);
130
+ });
131
+ test("should dispatch to both states", () => {
132
+ const { peerState } = setup();
133
+ const knownStatesSpy = vi.spyOn(peerState.knownStates, "dispatch");
134
+ const optimisticKnownStatesSpy = vi.spyOn(peerState.optimisticKnownStates, "dispatch");
135
+ const action = {
136
+ type: "SET",
137
+ id: "co_z1",
138
+ value: {
139
+ id: "co_z1",
140
+ header: false,
141
+ sessions: {},
142
+ },
143
+ };
144
+ peerState.dispatchToKnownStates(action);
145
+ expect(knownStatesSpy).toHaveBeenCalledWith(action);
146
+ expect(optimisticKnownStatesSpy).toHaveBeenCalledWith(action);
147
+ });
148
+ test("should use same reference for knownStates and optimisticKnownStates for storage peers", () => {
149
+ const mockStoragePeer = {
150
+ id: "test-storage-peer",
151
+ role: "storage",
152
+ priority: 1,
153
+ crashOnClose: false,
154
+ incoming: (async function* () { })(),
155
+ outgoing: {
156
+ push: vi.fn().mockResolvedValue(undefined),
157
+ close: vi.fn(),
158
+ },
159
+ };
160
+ const peerState = new PeerState(mockStoragePeer, undefined);
161
+ // Verify they are the same reference
162
+ expect(peerState.knownStates).toBe(peerState.optimisticKnownStates);
163
+ // Verify that dispatching only updates one state
164
+ const knownStatesSpy = vi.spyOn(peerState.knownStates, "dispatch");
165
+ const optimisticKnownStatesSpy = vi.spyOn(peerState.optimisticKnownStates, "dispatch");
166
+ const action = {
167
+ type: "SET",
168
+ id: "co_z1",
169
+ value: {
170
+ id: "co_z1",
171
+ header: false,
172
+ sessions: {},
173
+ },
174
+ };
175
+ peerState.dispatchToKnownStates(action);
176
+ // Only one dispatch should happen since they're the same reference
177
+ expect(knownStatesSpy).toHaveBeenCalledTimes(1);
178
+ expect(knownStatesSpy).toHaveBeenCalledWith(action);
179
+ expect(optimisticKnownStatesSpy).toHaveBeenCalledTimes(1);
180
+ expect(optimisticKnownStatesSpy).toHaveBeenCalledWith(action);
181
+ });
182
+ test("should use separate references for knownStates and optimisticKnownStates for non-storage peers", () => {
183
+ const { peerState } = setup(); // Uses a regular peer
184
+ // Verify they are different references
185
+ expect(peerState.knownStates).not.toBe(peerState.optimisticKnownStates);
186
+ });
187
+ });
188
+ //# sourceMappingURL=PeerState.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PeerState.test.js","sourceRoot":"","sources":["../../src/tests/PeerState.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,120 @@
1
+ import { afterEach, describe, expect, test } from "vitest";
2
+ import { PriorityBasedMessageQueue } from "../PriorityBasedMessageQueue.js";
3
+ import { CO_VALUE_PRIORITY } from "../priority.js";
4
+ import { createTestMetricReader, tearDownTestMetricReader, } from "./testUtils.js";
5
+ function setup() {
6
+ const metricReader = createTestMetricReader();
7
+ const queue = new PriorityBasedMessageQueue(CO_VALUE_PRIORITY.MEDIUM);
8
+ return { queue, metricReader };
9
+ }
10
+ describe("PriorityBasedMessageQueue", () => {
11
+ afterEach(() => {
12
+ tearDownTestMetricReader();
13
+ });
14
+ test("should initialize with correct properties", () => {
15
+ const { queue } = setup();
16
+ expect(queue["defaultPriority"]).toBe(CO_VALUE_PRIORITY.MEDIUM);
17
+ expect(queue["queues"].length).toBe(8);
18
+ expect(queue["queues"].every((q) => !q.length)).toBe(true);
19
+ });
20
+ test("should push message with default priority", async () => {
21
+ const { queue } = setup();
22
+ const message = {
23
+ action: "load",
24
+ id: "co_ztest-id",
25
+ header: false,
26
+ sessions: {},
27
+ };
28
+ void queue.push(message);
29
+ const pulledEntry = queue.pull();
30
+ expect(pulledEntry?.msg).toEqual(message);
31
+ });
32
+ test("should push message with specified priority", async () => {
33
+ const { queue } = setup();
34
+ const message = {
35
+ action: "content",
36
+ id: "co_zhigh",
37
+ new: {},
38
+ priority: CO_VALUE_PRIORITY.HIGH,
39
+ };
40
+ void queue.push(message);
41
+ const pulledEntry = queue.pull();
42
+ expect(pulledEntry?.msg).toEqual(message);
43
+ });
44
+ test("should pull messages in priority order", async () => {
45
+ const { queue, metricReader } = setup();
46
+ const lowPriorityMsg = {
47
+ action: "content",
48
+ id: "co_zlow",
49
+ new: {},
50
+ priority: CO_VALUE_PRIORITY.LOW,
51
+ };
52
+ const mediumPriorityMsg = {
53
+ action: "content",
54
+ id: "co_zmedium",
55
+ new: {},
56
+ priority: CO_VALUE_PRIORITY.MEDIUM,
57
+ };
58
+ const highPriorityMsg = {
59
+ action: "content",
60
+ id: "co_zhigh",
61
+ new: {},
62
+ priority: CO_VALUE_PRIORITY.HIGH,
63
+ };
64
+ void queue.push(lowPriorityMsg);
65
+ expect(await metricReader.getMetricValue("jazz.messagequeue.size", {
66
+ priority: lowPriorityMsg.priority,
67
+ })).toBe(1);
68
+ void queue.push(mediumPriorityMsg);
69
+ expect(await metricReader.getMetricValue("jazz.messagequeue.size", {
70
+ priority: mediumPriorityMsg.priority,
71
+ })).toBe(1);
72
+ void queue.push(highPriorityMsg);
73
+ expect(await metricReader.getMetricValue("jazz.messagequeue.size", {
74
+ priority: highPriorityMsg.priority,
75
+ })).toBe(1);
76
+ expect(queue.pull()?.msg).toEqual(highPriorityMsg);
77
+ expect(await metricReader.getMetricValue("jazz.messagequeue.size", {
78
+ priority: highPriorityMsg.priority,
79
+ })).toBe(0);
80
+ expect(queue.pull()?.msg).toEqual(mediumPriorityMsg);
81
+ expect(await metricReader.getMetricValue("jazz.messagequeue.size", {
82
+ priority: mediumPriorityMsg.priority,
83
+ })).toBe(0);
84
+ expect(queue.pull()?.msg).toEqual(lowPriorityMsg);
85
+ expect(await metricReader.getMetricValue("jazz.messagequeue.size", {
86
+ priority: lowPriorityMsg.priority,
87
+ })).toBe(0);
88
+ });
89
+ test("should return undefined when pulling from empty queue", () => {
90
+ const { queue } = setup();
91
+ expect(queue.pull()).toBeUndefined();
92
+ });
93
+ test("should resolve promise when message is pulled", async () => {
94
+ const { queue } = setup();
95
+ const message = {
96
+ action: "load",
97
+ id: "co_ztest-id",
98
+ header: false,
99
+ sessions: {},
100
+ };
101
+ const pushPromise = queue.push(message);
102
+ const pulledEntry = queue.pull();
103
+ pulledEntry?.resolve();
104
+ await expect(pushPromise).resolves.toBeUndefined();
105
+ });
106
+ test("should reject promise when message is rejected", async () => {
107
+ const { queue } = setup();
108
+ const message = {
109
+ action: "load",
110
+ id: "co_ztest-id",
111
+ header: false,
112
+ sessions: {},
113
+ };
114
+ const pushPromise = queue.push(message);
115
+ const pulledEntry = queue.pull();
116
+ pulledEntry?.reject(new Error("Test error"));
117
+ await expect(pushPromise).rejects.toThrow("Test error");
118
+ });
119
+ });
120
+ //# sourceMappingURL=PriorityBasedMessageQueue.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PriorityBasedMessageQueue.test.js","sourceRoot":"","sources":["../../src/tests/PriorityBasedMessageQueue.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,127 @@
1
+ import { beforeEach, describe, expect, onTestFinished, test, vi } from "vitest";
2
+ import { connectedPeers } from "../streamUtils.js";
3
+ import { emptyKnownState } from "../sync.js";
4
+ import { blockMessageTypeOnOutgoingPeer, connectNodeToSyncServer, createTestNode, loadCoValueOrFail, setupSyncServer, waitFor, } from "./testUtils.js";
5
+ let jazzCloud = setupSyncServer();
6
+ beforeEach(async () => {
7
+ jazzCloud = setupSyncServer();
8
+ });
9
+ describe("SyncStateManager", () => {
10
+ test("subscribeToUpdates receives updates when peer state changes", async () => {
11
+ // Setup nodes
12
+ const client = createTestNode();
13
+ const { nodeToServerPeer } = connectNodeToSyncServer(client);
14
+ // Create test data
15
+ const group = client.createGroup();
16
+ const map = group.createMap();
17
+ map.set("key1", "value1", "trusting");
18
+ const subscriptionManager = client.syncManager.syncState;
19
+ const updateSpy = vi.fn();
20
+ const unsubscribe = subscriptionManager.subscribeToUpdates(updateSpy);
21
+ await client.syncManager.actuallySyncCoValue(map.core);
22
+ expect(updateSpy).toHaveBeenCalledWith(nodeToServerPeer.id, emptyKnownState(map.core.id), { uploaded: false });
23
+ await waitFor(() => {
24
+ return subscriptionManager.getCurrentSyncState(nodeToServerPeer.id, map.core.id).uploaded;
25
+ });
26
+ expect(updateSpy).toHaveBeenCalledWith(nodeToServerPeer.id, client.syncManager.peers[nodeToServerPeer.id].knownStates.get(map.core.id), { uploaded: true });
27
+ // Cleanup
28
+ unsubscribe();
29
+ });
30
+ test("subscribeToPeerUpdates receives updates only for specific peer", async () => {
31
+ // Setup nodes
32
+ const client = createTestNode();
33
+ const { nodeToServerPeer } = connectNodeToSyncServer(client);
34
+ // Create test data
35
+ const group = client.createGroup();
36
+ const map = group.createMap();
37
+ map.set("key1", "value1", "trusting");
38
+ const [clientStoragePeer] = connectedPeers("clientStorage", "unusedPeer", {
39
+ peer1role: "client",
40
+ peer2role: "server",
41
+ });
42
+ client.syncManager.addPeer(clientStoragePeer);
43
+ const subscriptionManager = client.syncManager.syncState;
44
+ const updateToJazzCloudSpy = vi.fn();
45
+ const updateToStorageSpy = vi.fn();
46
+ const unsubscribe1 = subscriptionManager.subscribeToPeerUpdates(nodeToServerPeer.id, updateToJazzCloudSpy);
47
+ const unsubscribe2 = subscriptionManager.subscribeToPeerUpdates(clientStoragePeer.id, updateToStorageSpy);
48
+ onTestFinished(() => {
49
+ unsubscribe1();
50
+ unsubscribe2();
51
+ });
52
+ await client.syncManager.actuallySyncCoValue(map.core);
53
+ expect(updateToJazzCloudSpy).toHaveBeenCalledWith(emptyKnownState(map.core.id), { uploaded: false });
54
+ await waitFor(() => {
55
+ return subscriptionManager.getCurrentSyncState(nodeToServerPeer.id, map.core.id).uploaded;
56
+ });
57
+ expect(updateToJazzCloudSpy).toHaveBeenLastCalledWith(client.syncManager.peers[nodeToServerPeer.id].knownStates.get(map.core.id), { uploaded: true });
58
+ expect(updateToStorageSpy).toHaveBeenLastCalledWith(emptyKnownState(map.core.id), { uploaded: false });
59
+ });
60
+ test("getIsCoValueFullyUploadedIntoPeer returns correct status", async () => {
61
+ // Setup nodes
62
+ const client = createTestNode();
63
+ const { nodeToServerPeer } = connectNodeToSyncServer(client);
64
+ // Create test data
65
+ const group = client.createGroup();
66
+ const map = group.createMap();
67
+ map.set("key1", "value1", "trusting");
68
+ await client.syncManager.actuallySyncCoValue(map.core);
69
+ const subscriptionManager = client.syncManager.syncState;
70
+ expect(subscriptionManager.getCurrentSyncState(nodeToServerPeer.id, map.core.id)
71
+ .uploaded).toBe(false);
72
+ await waitFor(() => {
73
+ return subscriptionManager.getCurrentSyncState(nodeToServerPeer.id, map.core.id).uploaded;
74
+ });
75
+ expect(subscriptionManager.getCurrentSyncState(nodeToServerPeer.id, map.core.id)
76
+ .uploaded).toBe(true);
77
+ });
78
+ test("unsubscribe stops receiving updates", async () => {
79
+ // Setup nodes
80
+ const client = createTestNode();
81
+ const { nodeToServerPeer } = connectNodeToSyncServer(client);
82
+ // Create test data
83
+ const group = client.createGroup();
84
+ const map = group.createMap();
85
+ map.set("key1", "value1", "trusting");
86
+ const subscriptionManager = client.syncManager.syncState;
87
+ const anyUpdateSpy = vi.fn();
88
+ const unsubscribe1 = subscriptionManager.subscribeToUpdates(anyUpdateSpy);
89
+ const unsubscribe2 = subscriptionManager.subscribeToPeerUpdates(nodeToServerPeer.id, anyUpdateSpy);
90
+ unsubscribe1();
91
+ unsubscribe2();
92
+ await client.syncManager.actuallySyncCoValue(map.core);
93
+ anyUpdateSpy.mockClear();
94
+ await waitFor(() => {
95
+ return subscriptionManager.getCurrentSyncState(nodeToServerPeer.id, map.core.id).uploaded;
96
+ });
97
+ expect(anyUpdateSpy).not.toHaveBeenCalled();
98
+ });
99
+ test("getCurrentSyncState should return the correct state", async () => {
100
+ // Setup nodes
101
+ const clientNode = createTestNode();
102
+ const serverNode = jazzCloud;
103
+ const { nodeToServerPeer: clientToServerPeer, serverToNodePeer: serverToClientPeer, } = connectNodeToSyncServer(clientNode);
104
+ // Create test data
105
+ const group = clientNode.createGroup();
106
+ const map = group.createMap();
107
+ map.set("key1", "value1", "trusting");
108
+ group.addMember("everyone", "writer");
109
+ // Initially should not be synced
110
+ expect(clientNode.syncManager.syncState.getCurrentSyncState(clientToServerPeer.id, map.core.id)).toEqual({ uploaded: false });
111
+ // Wait for full sync
112
+ await map.core.waitForSync();
113
+ expect(clientNode.syncManager.syncState.getCurrentSyncState(clientToServerPeer.id, map.core.id)).toEqual({ uploaded: true });
114
+ const mapOnServer = await loadCoValueOrFail(serverNode, map.id);
115
+ // Block the content messages so the client won't fully sync immediately
116
+ const outgoing = blockMessageTypeOnOutgoingPeer(serverToClientPeer, "content");
117
+ mapOnServer.set("key2", "value2", "trusting");
118
+ expect(clientNode.syncManager.syncState.getCurrentSyncState(clientToServerPeer.id, map.core.id)).toEqual({ uploaded: true });
119
+ expect(serverNode.syncManager.syncState.getCurrentSyncState(serverToClientPeer.id, map.core.id)).toEqual({ uploaded: false });
120
+ await outgoing.sendBlockedMessages();
121
+ outgoing.unblock();
122
+ await mapOnServer.core.waitForSync();
123
+ expect(clientNode.syncManager.syncState.getCurrentSyncState(clientToServerPeer.id, map.core.id)).toEqual({ uploaded: true });
124
+ expect(serverNode.syncManager.syncState.getCurrentSyncState(serverToClientPeer.id, map.core.id)).toEqual({ uploaded: true });
125
+ });
126
+ });
127
+ //# sourceMappingURL=SyncStateManager.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SyncStateManager.test.js","sourceRoot":"","sources":["../../src/tests/SyncStateManager.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,66 @@
1
+ import { expect, test } from "vitest";
2
+ import { WasmCrypto } from "../crypto/WasmCrypto.js";
3
+ import { LocalNode } from "../localNode.js";
4
+ import { connectedPeers } from "../streamUtils.js";
5
+ const Crypto = await WasmCrypto.create();
6
+ test("Can create a node while creating a new account with profile", async () => {
7
+ const { node, accountID, accountSecret, sessionID } = await LocalNode.withNewlyCreatedAccount({
8
+ creationProps: { name: "Hermes Puggington" },
9
+ crypto: Crypto,
10
+ });
11
+ expect(node).not.toBeNull();
12
+ expect(accountID).not.toBeNull();
13
+ expect(accountSecret).not.toBeNull();
14
+ expect(sessionID).not.toBeNull();
15
+ expect(node.expectProfileLoaded(accountID).get("name")).toEqual("Hermes Puggington");
16
+ });
17
+ test("A node with an account can create groups and and objects within them", async () => {
18
+ const { node, accountID } = await LocalNode.withNewlyCreatedAccount({
19
+ creationProps: { name: "Hermes Puggington" },
20
+ crypto: Crypto,
21
+ });
22
+ const group = await node.createGroup();
23
+ expect(group).not.toBeNull();
24
+ const map = group.createMap();
25
+ map.set("foo", "bar", "private");
26
+ expect(map.get("foo")).toEqual("bar");
27
+ expect(map.lastEditAt("foo")?.by).toEqual(accountID);
28
+ });
29
+ test("Can create account with one node, and then load it on another", async () => {
30
+ const { node, accountID, accountSecret } = await LocalNode.withNewlyCreatedAccount({
31
+ creationProps: { name: "Hermes Puggington" },
32
+ crypto: Crypto,
33
+ });
34
+ const group = await node.createGroup();
35
+ expect(group).not.toBeNull();
36
+ const map = group.createMap();
37
+ map.set("foo", "bar", "private");
38
+ expect(map.get("foo")).toEqual("bar");
39
+ const [node1asPeer, node2asPeer] = connectedPeers("node1", "node2", {
40
+ peer1role: "server",
41
+ peer2role: "client",
42
+ });
43
+ node.syncManager.addPeer(node2asPeer);
44
+ const node2 = await LocalNode.withLoadedAccount({
45
+ accountID,
46
+ accountSecret,
47
+ sessionID: Crypto.newRandomSessionID(accountID),
48
+ peersToLoadFrom: [node1asPeer],
49
+ crypto: Crypto,
50
+ });
51
+ const map2 = await node2.load(map.id);
52
+ if (map2 === "unavailable")
53
+ throw new Error("Map unavailable");
54
+ expect(map2.get("foo")).toEqual("bar");
55
+ });
56
+ test("throws an error if the user tried to create an invite from an account", async () => {
57
+ const { node, accountID } = await LocalNode.withNewlyCreatedAccount({
58
+ creationProps: { name: "Hermes Puggington" },
59
+ crypto: Crypto,
60
+ });
61
+ const account = await node.load(accountID);
62
+ if (account === "unavailable")
63
+ throw new Error("Account unavailable");
64
+ expect(() => account.createInvite("admin")).toThrow("Cannot create invite from an account");
65
+ });
66
+ //# sourceMappingURL=account.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"account.test.js","sourceRoot":"","sources":["../../src/tests/account.test.ts"],"names":[],"mappings":"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"}