@dxos/echo-pipeline 0.6.11 → 0.6.12-main.5cc132e

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 (30) hide show
  1. package/dist/lib/browser/meta.json +1 -1
  2. package/dist/lib/node-esm/chunk-BZ3FKMCP.mjs +21 -0
  3. package/dist/lib/node-esm/chunk-BZ3FKMCP.mjs.map +7 -0
  4. package/dist/lib/node-esm/chunk-HH4RB7HI.mjs +2150 -0
  5. package/dist/lib/node-esm/chunk-HH4RB7HI.mjs.map +7 -0
  6. package/dist/lib/node-esm/chunk-ZWS5AMHO.mjs +2000 -0
  7. package/dist/lib/node-esm/chunk-ZWS5AMHO.mjs.map +7 -0
  8. package/dist/lib/node-esm/index.mjs +73 -0
  9. package/dist/lib/node-esm/index.mjs.map +7 -0
  10. package/dist/lib/node-esm/light.mjs +31 -0
  11. package/dist/lib/node-esm/light.mjs.map +7 -0
  12. package/dist/lib/node-esm/meta.json +1 -0
  13. package/dist/lib/node-esm/testing/index.mjs +551 -0
  14. package/dist/lib/node-esm/testing/index.mjs.map +7 -0
  15. package/package.json +38 -41
  16. package/src/automerge/automerge-host.test.ts +8 -9
  17. package/src/automerge/automerge-repo.test.ts +18 -16
  18. package/src/automerge/collection-synchronizer.test.ts +7 -4
  19. package/src/automerge/echo-data-monitor.test.ts +1 -3
  20. package/src/automerge/echo-network-adapter.test.ts +4 -3
  21. package/src/automerge/storage-adapter.test.ts +2 -3
  22. package/src/db-host/documents-synchronizer.test.ts +2 -2
  23. package/src/pipeline/pipeline-stress.test.ts +44 -47
  24. package/src/pipeline/pipeline.test.ts +3 -4
  25. package/src/space/control-pipeline.test.ts +2 -3
  26. package/src/space/replication.browser.test.ts +2 -8
  27. package/src/space/space-manager.browser.test.ts +6 -5
  28. package/src/space/space-protocol.browser.test.ts +29 -34
  29. package/src/space/space-protocol.test.ts +29 -27
  30. package/src/space/space.test.ts +28 -11
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dxos/echo-pipeline",
3
- "version": "0.6.11",
3
+ "version": "0.6.12-main.5cc132e",
4
4
  "description": "ECHO database.",
5
5
  "homepage": "https://dxos.org",
6
6
  "bugs": "https://github.com/dxos/dxos/issues",
@@ -10,21 +10,24 @@
10
10
  ".": {
11
11
  "browser": "./dist/lib/browser/index.mjs",
12
12
  "node": {
13
- "default": "./dist/lib/node/index.cjs"
13
+ "require": "./dist/lib/node/index.cjs",
14
+ "default": "./dist/lib/node-esm/index.mjs"
14
15
  },
15
16
  "types": "./dist/types/src/index.d.ts"
16
17
  },
17
18
  "./light": {
18
19
  "browser": "./dist/lib/browser/light.mjs",
19
20
  "node": {
20
- "default": "./dist/lib/node/light.cjs"
21
+ "require": "./dist/lib/node/light.cjs",
22
+ "default": "./dist/lib/node-esm/light.mjs"
21
23
  },
22
24
  "types": "./dist/types/src/light.d.ts"
23
25
  },
24
26
  "./testing": {
25
27
  "browser": "./dist/lib/browser/testing/index.mjs",
26
28
  "node": {
27
- "default": "./dist/lib/node/testing/index.cjs"
29
+ "require": "./dist/lib/node/testing/index.cjs",
30
+ "default": "./dist/lib/node-esm/testing/index.mjs"
28
31
  },
29
32
  "types": "./dist/types/src/testing/index.d.ts"
30
33
  }
@@ -47,48 +50,42 @@
47
50
  "src"
48
51
  ],
49
52
  "dependencies": {
50
- "abstract-level": "^1.0.2",
51
53
  "crc-32": "^1.2.2",
52
- "level": "^8.0.1",
53
54
  "level-transcoder": "^1.0.1",
54
- "@dxos/async": "0.6.11",
55
- "@dxos/codec-protobuf": "0.6.11",
56
- "@dxos/context": "0.6.11",
57
- "@dxos/credentials": "0.6.11",
58
- "@dxos/crypto": "0.6.11",
59
- "@dxos/debug": "0.6.11",
60
- "@dxos/echo-protocol": "0.6.11",
61
- "@dxos/echo-schema": "0.6.11",
62
- "@dxos/feed-store": "0.6.11",
63
- "@dxos/hypercore": "0.6.11",
64
- "@dxos/indexing": "0.6.11",
65
- "@dxos/invariant": "0.6.11",
66
- "@dxos/keyring": "0.6.11",
67
- "@dxos/keys": "0.6.11",
68
- "@dxos/kv-store": "0.6.11",
69
- "@dxos/log": "0.6.11",
70
- "@dxos/messaging": "0.6.11",
71
- "@dxos/network-manager": "0.6.11",
72
- "@dxos/node-std": "0.6.11",
73
- "@dxos/protocols": "0.6.11",
74
- "@dxos/random-access-storage": "0.6.11",
75
- "@dxos/rpc": "0.6.11",
76
- "@dxos/teleport-extension-automerge-replicator": "0.6.11",
77
- "@dxos/teleport-extension-gossip": "0.6.11",
78
- "@dxos/teleport-extension-object-sync": "0.6.11",
79
- "@dxos/timeframe": "0.6.11",
80
- "@dxos/typings": "0.6.11",
81
- "@dxos/tracing": "0.6.11",
82
- "@dxos/util": "0.6.11",
83
- "@dxos/teleport": "0.6.11",
84
- "@dxos/teleport-extension-replicator": "0.6.11",
85
- "@dxos/automerge": "0.6.11"
55
+ "@dxos/async": "0.6.12-main.5cc132e",
56
+ "@dxos/codec-protobuf": "0.6.12-main.5cc132e",
57
+ "@dxos/automerge": "0.6.12-main.5cc132e",
58
+ "@dxos/context": "0.6.12-main.5cc132e",
59
+ "@dxos/crypto": "0.6.12-main.5cc132e",
60
+ "@dxos/echo-protocol": "0.6.12-main.5cc132e",
61
+ "@dxos/credentials": "0.6.12-main.5cc132e",
62
+ "@dxos/debug": "0.6.12-main.5cc132e",
63
+ "@dxos/feed-store": "0.6.12-main.5cc132e",
64
+ "@dxos/hypercore": "0.6.12-main.5cc132e",
65
+ "@dxos/indexing": "0.6.12-main.5cc132e",
66
+ "@dxos/invariant": "0.6.12-main.5cc132e",
67
+ "@dxos/kv-store": "0.6.12-main.5cc132e",
68
+ "@dxos/keyring": "0.6.12-main.5cc132e",
69
+ "@dxos/network-manager": "0.6.12-main.5cc132e",
70
+ "@dxos/log": "0.6.12-main.5cc132e",
71
+ "@dxos/node-std": "0.6.12-main.5cc132e",
72
+ "@dxos/messaging": "0.6.12-main.5cc132e",
73
+ "@dxos/protocols": "0.6.12-main.5cc132e",
74
+ "@dxos/teleport": "0.6.12-main.5cc132e",
75
+ "@dxos/random-access-storage": "0.6.12-main.5cc132e",
76
+ "@dxos/teleport-extension-automerge-replicator": "0.6.12-main.5cc132e",
77
+ "@dxos/teleport-extension-object-sync": "0.6.12-main.5cc132e",
78
+ "@dxos/teleport-extension-replicator": "0.6.12-main.5cc132e",
79
+ "@dxos/teleport-extension-gossip": "0.6.12-main.5cc132e",
80
+ "@dxos/timeframe": "0.6.12-main.5cc132e",
81
+ "@dxos/tracing": "0.6.12-main.5cc132e",
82
+ "@dxos/typings": "0.6.12-main.5cc132e",
83
+ "@dxos/util": "0.6.12-main.5cc132e",
84
+ "@dxos/keys": "0.6.12-main.5cc132e"
86
85
  },
87
86
  "devDependencies": {
88
87
  "fast-check": "^3.19.0",
89
- "hypercore-protocol": "^8.0.7",
90
- "source-map-support": "^0.5.12",
91
- "wait-for-expect": "^3.0.2"
88
+ "@dxos/test-utils": "0.6.12-main.5cc132e"
92
89
  },
93
90
  "publishConfig": {
94
91
  "access": "public"
@@ -2,15 +2,14 @@
2
2
  // Copyright 2023 DXOS.org
3
3
  //
4
4
 
5
- import expect from 'expect';
6
- import waitForExpect from 'wait-for-expect';
5
+ import { onTestFinished, describe, expect, test } from 'vitest';
7
6
 
8
7
  import { getHeads } from '@dxos/automerge/automerge';
9
8
  import type { DocumentId, Heads } from '@dxos/automerge/automerge-repo';
10
9
  import { IndexMetadataStore } from '@dxos/indexing';
11
10
  import type { LevelDB } from '@dxos/kv-store';
12
11
  import { createTestLevel } from '@dxos/kv-store/testing';
13
- import { afterTest, describe, openAndClose, test } from '@dxos/test';
12
+ import { openAndClose } from '@dxos/test-utils';
14
13
  import { range } from '@dxos/util';
15
14
 
16
15
  import { AutomergeHost } from './automerge-host';
@@ -114,11 +113,9 @@ describe('AutomergeHost', () => {
114
113
  await host1.addReplicator(await network.createReplicator());
115
114
  await host2.addReplicator(await network.createReplicator());
116
115
 
117
- await waitForExpect(async () => {
118
- for (const documentId of documentIds) {
119
- expect(await host1.getHeads([documentId])).toEqual(await host2.getHeads([documentId]));
120
- }
121
- });
116
+ for (const documentId of documentIds) {
117
+ await expect.poll(() => host1.getHeads([documentId])).toEqual(await host2.getHeads([documentId]));
118
+ }
122
119
 
123
120
  await host1.close();
124
121
  await host2.close();
@@ -137,6 +134,8 @@ const setupAutomergeHost = async ({ level }: { level: LevelDB }) => {
137
134
  indexMetadataStore: new IndexMetadataStore({ db: level.sublevel('index-metadata') }),
138
135
  });
139
136
  await host.open();
140
- afterTest(() => host.close());
137
+ onTestFinished(async () => {
138
+ await host.close();
139
+ });
141
140
  return host;
142
141
  };
@@ -2,8 +2,7 @@
2
2
  // Copyright 2024 DXOS.org
3
3
  //
4
4
 
5
- import { expect } from 'chai';
6
- import waitForExpect from 'wait-for-expect';
5
+ import { onTestFinished, describe, expect, test } from 'vitest';
7
6
 
8
7
  import { asyncTimeout, sleep } from '@dxos/async';
9
8
  import {
@@ -34,7 +33,7 @@ import { randomBytes } from '@dxos/crypto';
34
33
  import { PublicKey } from '@dxos/keys';
35
34
  import { createTestLevel } from '@dxos/kv-store/testing';
36
35
  import { TestBuilder as TeleportBuilder, TestPeer as TeleportPeer } from '@dxos/teleport/testing';
37
- import { afterTest, describe, openAndClose, test } from '@dxos/test';
36
+ import { openAndClose } from '@dxos/test-utils';
38
37
  import { nonNullable, range } from '@dxos/util';
39
38
 
40
39
  import { EchoNetworkAdapter } from './echo-network-adapter';
@@ -377,10 +376,8 @@ describe('AutomergeRepo', () => {
377
376
  const hostHandle = peer1.find(url as AutomergeUrl);
378
377
 
379
378
  // Doc should be pushed to peer2
380
- await waitForExpect(() => {
381
- expect(hostHandle.docSync().text).not.to.be.undefined;
382
- expect(peer2.handles[hostHandle.documentId].docSync()).to.deep.eq(hostHandle.docSync());
383
- });
379
+ await expect.poll(() => hostHandle.docSync().text).not.toBeUndefined();
380
+ await expect.poll(() => peer2.handles[hostHandle.documentId].docSync()).toEqual(hostHandle.docSync());
384
381
  });
385
382
 
386
383
  test('client cold-starts and syncs doc from a Repo', async () => {
@@ -480,7 +477,7 @@ describe('AutomergeRepo', () => {
480
477
  const [spaceKey] = PublicKey.randomSequence();
481
478
 
482
479
  const teleportBuilder = new TeleportBuilder();
483
- afterTest(() => teleportBuilder.destroy());
480
+ onTestFinished(() => teleportBuilder.destroy());
484
481
 
485
482
  const peer1 = await createTeleportTestPeer(teleportBuilder, spaceKey);
486
483
  const peer2 = await createTeleportTestPeer(teleportBuilder, spaceKey);
@@ -493,11 +490,16 @@ describe('AutomergeRepo', () => {
493
490
  handle.change((doc: any) => {
494
491
  doc.text = text;
495
492
  });
496
- await waitForExpect(async () => {
497
- const docOnPeer2 = peer2.repo.find(handle.url);
498
- const doc = await asyncTimeout(docOnPeer2.doc(), 1000);
499
- expect(doc.text).to.eq(text);
500
- }, 1000);
493
+ await expect
494
+ .poll(
495
+ async () => {
496
+ const docOnPeer2 = peer2.repo.find(handle.url);
497
+ const doc = await asyncTimeout(docOnPeer2.doc(), 1000);
498
+ return doc.text;
499
+ },
500
+ { timeout: 1_000 },
501
+ )
502
+ .toEqual(text);
501
503
  }
502
504
 
503
505
  const offlineText = 'This has been written while the connection was off';
@@ -536,7 +538,7 @@ describe('AutomergeRepo', () => {
536
538
  const [spaceKey] = PublicKey.randomSequence();
537
539
 
538
540
  const teleportBuilder = new TeleportBuilder();
539
- afterTest(() => teleportBuilder.destroy());
541
+ onTestFinished(() => teleportBuilder.destroy());
540
542
 
541
543
  const peerWithDocs = await createTeleportPeerWithStoredDocs(teleportBuilder, spaceKey, async (repo) => {
542
544
  return range(2, (idx) => {
@@ -569,7 +571,7 @@ describe('AutomergeRepo', () => {
569
571
  const [spaceKey, anotherSpaceKey] = PublicKey.randomSequence();
570
572
 
571
573
  const teleportBuilder = new TeleportBuilder();
572
- afterTest(() => teleportBuilder.destroy());
574
+ onTestFinished(() => teleportBuilder.destroy());
573
575
 
574
576
  const peerWithDocs = await createTeleportPeerWithStoredDocs(teleportBuilder, spaceKey, async (repo) => {
575
577
  const document = repo.create();
@@ -600,7 +602,7 @@ describe('AutomergeRepo', () => {
600
602
  const [spaceKey] = PublicKey.randomSequence();
601
603
 
602
604
  const teleportBuilder = new TeleportBuilder();
603
- afterTest(() => teleportBuilder.destroy());
605
+ onTestFinished(() => teleportBuilder.destroy());
604
606
 
605
607
  const peerWithDocs = await createTeleportPeerWithStoredDocs(teleportBuilder, spaceKey, async (repo) => {
606
608
  const document = repo.create();
@@ -2,11 +2,10 @@
2
2
  // Copyright 2024 DXOS.org
3
3
  //
4
4
 
5
- import { expect } from 'chai';
5
+ import { onTestFinished, describe, expect, test } from 'vitest';
6
6
 
7
7
  import { sleep } from '@dxos/async';
8
8
  import type { PeerId } from '@dxos/automerge/automerge-repo';
9
- import { afterTest, describe, test } from '@dxos/test';
10
9
 
11
10
  import { CollectionSynchronizer, diffCollectionState, type CollectionState } from './collection-synchronizer';
12
11
 
@@ -31,7 +30,9 @@ describe('CollectionSynchronizer', () => {
31
30
  }),
32
31
  shouldSyncCollection: () => true,
33
32
  }).open();
34
- afterTest(() => peer1.close());
33
+ onTestFinished(async () => {
34
+ await peer1.close();
35
+ });
35
36
  const peer2 = await new CollectionSynchronizer({
36
37
  queryCollectionState: (collectionId, peerId) =>
37
38
  queueMicrotask(async () => {
@@ -45,7 +46,9 @@ describe('CollectionSynchronizer', () => {
45
46
  }),
46
47
  shouldSyncCollection: () => true,
47
48
  }).open();
48
- afterTest(() => peer2.close());
49
+ onTestFinished(async () => {
50
+ await peer2.close();
51
+ });
49
52
 
50
53
  peer1.onConnectionOpen(peerId2);
51
54
  peer2.onConnectionOpen(peerId1);
@@ -2,9 +2,7 @@
2
2
  // Copyright 2024 DXOS.org
3
3
  //
4
4
 
5
- import { expect } from 'chai';
6
-
7
- import { describe, test } from '@dxos/test';
5
+ import { describe, expect, test } from 'vitest';
8
6
 
9
7
  import { EchoDataMonitor } from './echo-data-monitor';
10
8
 
@@ -2,7 +2,7 @@
2
2
  // Copyright 2024 DXOS.org
3
3
  //
4
4
 
5
- import { expect } from 'chai';
5
+ import { onTestFinished, describe, expect, test } from 'vitest';
6
6
 
7
7
  import { sleep, Trigger, waitForCondition } from '@dxos/async';
8
8
  import { cbor, type PeerId } from '@dxos/automerge/automerge-repo';
@@ -14,7 +14,6 @@ import {
14
14
  type AutomergeReplicatorCallbacks,
15
15
  type AutomergeReplicatorFactory,
16
16
  } from '@dxos/teleport-extension-automerge-replicator';
17
- import { afterTest, describe, test } from '@dxos/test';
18
17
 
19
18
  import { EchoNetworkAdapter } from './echo-network-adapter';
20
19
  import { MeshEchoReplicator } from './mesh-echo-replicator';
@@ -111,7 +110,9 @@ describe('EchoNetworkAdapter', () => {
111
110
  });
112
111
  adapter.connect(PEER_ID);
113
112
  await adapter.open();
114
- afterTest(() => adapter.close());
113
+ onTestFinished(async () => {
114
+ await adapter.close();
115
+ });
115
116
  await adapter.addReplicator(replicator);
116
117
  return adapter;
117
118
  };
@@ -2,12 +2,11 @@
2
2
  // Copyright 2024 DXOS.org
3
3
  //
4
4
 
5
- import { expect } from 'chai';
5
+ import { onTestFinished, describe, expect, test } from 'vitest';
6
6
 
7
7
  import { randomBytes } from '@dxos/crypto';
8
8
  import { PublicKey } from '@dxos/keys';
9
9
  import { createTestLevel } from '@dxos/kv-store/testing';
10
- import { afterTest, describe, test } from '@dxos/test';
11
10
  import { arrayToBuffer, bufferToArray } from '@dxos/util';
12
11
 
13
12
  import { LevelDBStorageAdapter } from './leveldb-storage-adapter';
@@ -23,7 +22,7 @@ describe('LevelDBStorageAdapter', () => {
23
22
  await adapter.close();
24
23
  await level.close();
25
24
  };
26
- afterTest(close);
25
+ onTestFinished(close);
27
26
  return {
28
27
  adapter,
29
28
  close,
@@ -2,12 +2,12 @@
2
2
  // Copyright 2024 DXOS.org
3
3
  //
4
4
 
5
- import { expect } from 'chai';
5
+ import { describe, expect, test } from 'vitest';
6
6
 
7
7
  import { sleep } from '@dxos/async';
8
8
  import { next as A } from '@dxos/automerge/automerge';
9
9
  import { generateAutomergeUrl, parseAutomergeUrl, Repo } from '@dxos/automerge/automerge-repo';
10
- import { describe, openAndClose, test } from '@dxos/test';
10
+ import { openAndClose } from '@dxos/test-utils';
11
11
 
12
12
  import { DocumentsSynchronizer } from './documents-synchronizer';
13
13
 
@@ -2,9 +2,9 @@
2
2
  // Copyright 2022 DXOS.org
3
3
  //
4
4
 
5
- import expect from 'expect';
6
5
  import * as fc from 'fast-check';
7
- import { inspect } from 'util';
6
+ import { inspect } from 'node:util';
7
+ import { describe, expect, test } from 'vitest';
8
8
 
9
9
  import { asyncTimeout } from '@dxos/async';
10
10
  import { type FeedStore, type FeedWrapper } from '@dxos/feed-store';
@@ -12,7 +12,6 @@ import { PublicKey } from '@dxos/keys';
12
12
  import { log } from '@dxos/log';
13
13
  import { type FeedMessageBlock } from '@dxos/protocols';
14
14
  import { type FeedMessage } from '@dxos/protocols/proto/dxos/echo/feed';
15
- import { describe, test } from '@dxos/test';
16
15
  import { Timeframe } from '@dxos/timeframe';
17
16
  import { range } from '@dxos/util';
18
17
 
@@ -24,53 +23,51 @@ const NUM_MESSAGES = 10;
24
23
 
25
24
  // TODO(burdon): Describe test.
26
25
  describe('pipeline/stress test', () => {
27
- test
28
- .skip('stress', async () => {
29
- const builder = new TestFeedBuilder();
30
-
31
- const agentIds = range(NUM_AGENTS).map(() => PublicKey.random().toHex().slice(0, 8));
32
- const anAgentId = fc.constantFrom(...agentIds);
33
-
34
- const commands = fc.commands(
35
- [
36
- fc.tuple(anAgentId, fc.integer({ min: 1, max: 10 })).map(([agent, count]) => new WriteCommand(agent, count)),
37
- fc.constant(new SyncCommand()),
38
- anAgentId.map((agent) => new RestartCommand(agent)),
39
- ],
40
- { size: 'large' },
41
- );
42
-
43
- const model = fc.asyncProperty(commands, async (commands) => {
44
- const feedStore = builder.createFeedStore();
45
-
46
- const agents = new Map(agentIds.map((id) => [id, new Agent(builder, feedStore, id)]));
47
- await Promise.all(Array.from(agents.values()).map((agent) => agent.open()));
48
- await Promise.all(Array.from(agents.values()).map((agent) => agent.start()));
49
-
50
- const setup: fc.ModelRunSetup<Model, Real> = () => ({
51
- model: {},
52
- real: {
53
- feedStore,
54
- agents,
55
- },
56
- });
57
-
58
- try {
59
- await fc.asyncModelRun(setup, [...commands, new SyncCommand()]);
60
- } finally {
61
- await Promise.all(Array.from(agents.values()).map((agent) => agent.stop()));
62
- await Promise.all(Array.from(agents.values()).map((agent) => agent.close()));
63
- }
26
+ test.skip('stress', { timeout: 60_000 }, async () => {
27
+ const builder = new TestFeedBuilder();
28
+
29
+ const agentIds = range(NUM_AGENTS).map(() => PublicKey.random().toHex().slice(0, 8));
30
+ const anAgentId = fc.constantFrom(...agentIds);
31
+
32
+ const commands = fc.commands(
33
+ [
34
+ fc.tuple(anAgentId, fc.integer({ min: 1, max: 10 })).map(([agent, count]) => new WriteCommand(agent, count)),
35
+ fc.constant(new SyncCommand()),
36
+ anAgentId.map((agent) => new RestartCommand(agent)),
37
+ ],
38
+ { size: 'large' },
39
+ );
40
+
41
+ const model = fc.asyncProperty(commands, async (commands) => {
42
+ const feedStore = builder.createFeedStore();
43
+
44
+ const agents = new Map(agentIds.map((id) => [id, new Agent(builder, feedStore, id)]));
45
+ await Promise.all(Array.from(agents.values()).map((agent) => agent.open()));
46
+ await Promise.all(Array.from(agents.values()).map((agent) => agent.start()));
47
+
48
+ const setup: fc.ModelRunSetup<Model, Real> = () => ({
49
+ model: {},
50
+ real: {
51
+ feedStore,
52
+ agents,
53
+ },
64
54
  });
65
55
 
66
- const examples: [commands: Iterable<fc.AsyncCommand<Model, Real, boolean>>][] = [
67
- [[new WriteCommand(agentIds[0], 10), new WriteCommand(agentIds[1], 10), new SyncCommand()]],
68
- [[new WriteCommand(agentIds[0], 4), new RestartCommand(agentIds[0]), new SyncCommand()]],
69
- ];
56
+ try {
57
+ await fc.asyncModelRun(setup, [...commands, new SyncCommand()]);
58
+ } finally {
59
+ await Promise.all(Array.from(agents.values()).map((agent) => agent.stop()));
60
+ await Promise.all(Array.from(agents.values()).map((agent) => agent.close()));
61
+ }
62
+ });
63
+
64
+ const examples: [commands: Iterable<fc.AsyncCommand<Model, Real, boolean>>][] = [
65
+ [[new WriteCommand(agentIds[0], 10), new WriteCommand(agentIds[1], 10), new SyncCommand()]],
66
+ [[new WriteCommand(agentIds[0], 4), new RestartCommand(agentIds[0]), new SyncCommand()]],
67
+ ];
70
68
 
71
- await fc.assert(model, { examples });
72
- })
73
- .timeout(60_000);
69
+ await fc.assert(model, { examples });
70
+ });
74
71
  });
75
72
 
76
73
  class Agent {
@@ -2,11 +2,10 @@
2
2
  // Copyright 2022 DXOS.org
3
3
  //
4
4
 
5
- import expect from 'expect';
5
+ import { describe, expect, test, onTestFinished } from 'vitest';
6
6
 
7
7
  import { Event, sleep } from '@dxos/async';
8
8
  import { type FeedMessage } from '@dxos/protocols/proto/dxos/echo/feed';
9
- import { describe, test, afterTest } from '@dxos/test';
10
9
  import { Timeframe } from '@dxos/timeframe';
11
10
  import { range } from '@dxos/util';
12
11
 
@@ -62,7 +61,7 @@ describe('pipeline/Pipeline', () => {
62
61
 
63
62
  test('reading and writing with cursor changes', async () => {
64
63
  const pipeline = new Pipeline();
65
- afterTest(() => pipeline.stop());
64
+ onTestFinished(() => pipeline.stop());
66
65
 
67
66
  const builder = new TestFeedBuilder();
68
67
  const feedStore = builder.createFeedStore();
@@ -105,7 +104,7 @@ describe('pipeline/Pipeline', () => {
105
104
 
106
105
  test('cursor change while polling', async () => {
107
106
  const pipeline = new Pipeline();
108
- afterTest(() => pipeline.stop());
107
+ onTestFinished(() => pipeline.stop());
109
108
 
110
109
  const builder = new TestFeedBuilder();
111
110
  const feedStore = builder.createFeedStore();
@@ -2,7 +2,7 @@
2
2
  // Copyright 2022 DXOS.org
3
3
  //
4
4
 
5
- import expect from 'expect';
5
+ import { describe, expect, test, onTestFinished } from 'vitest';
6
6
 
7
7
  import { CredentialGenerator, createCredential } from '@dxos/credentials';
8
8
  import { FeedFactory, FeedStore } from '@dxos/feed-store';
@@ -12,7 +12,6 @@ import { log } from '@dxos/log';
12
12
  import type { FeedMessage } from '@dxos/protocols/proto/dxos/echo/feed';
13
13
  import { AdmittedFeed } from '@dxos/protocols/proto/dxos/halo/credentials';
14
14
  import { createStorage, StorageType } from '@dxos/random-access-storage';
15
- import { describe, test, afterTest } from '@dxos/test';
16
15
  import { Timeframe } from '@dxos/timeframe';
17
16
 
18
17
  import { ControlPipeline } from './control-pipeline';
@@ -62,7 +61,7 @@ describe('space/control-pipeline', () => {
62
61
  await controlPipeline.setWriteFeed(genesisFeed);
63
62
  await controlPipeline.start();
64
63
 
65
- afterTest(() => controlPipeline.stop());
64
+ onTestFinished(() => controlPipeline.stop());
66
65
 
67
66
  //
68
67
  // Genesis
@@ -2,16 +2,12 @@
2
2
  // Copyright 2021 DXOS.org
3
3
  //
4
4
 
5
- // @dxos/test platform=browser
6
-
7
- import expect from 'expect';
8
- import waitForExpect from 'wait-for-expect';
5
+ import { describe, expect, test } from 'vitest';
9
6
 
10
7
  import { FeedFactory, FeedStore } from '@dxos/feed-store';
11
8
  import { Keyring } from '@dxos/keyring';
12
9
  import type { FeedMessage } from '@dxos/protocols/proto/dxos/echo/feed';
13
10
  import { createStorage } from '@dxos/random-access-storage';
14
- import { describe, test } from '@dxos/test';
15
11
  import { Timeframe } from '@dxos/timeframe';
16
12
 
17
13
  import { valueEncoding } from '../common';
@@ -57,8 +53,6 @@ describe('replication', () => {
57
53
  timeframe: new Timeframe([[feed1.key, 123]]),
58
54
  });
59
55
 
60
- await waitForExpect(() => {
61
- expect(feed2.properties.length).toEqual(1);
62
- });
56
+ await expect.poll(() => feed2.properties.length).toEqual(1);
63
57
  });
64
58
  });
@@ -2,10 +2,9 @@
2
2
  // Copyright 2022 DXOS.org
3
3
  //
4
4
 
5
- // @dxos/test platform=browser
5
+ import { describe, test, onTestFinished } from 'vitest';
6
6
 
7
7
  import { createStorage } from '@dxos/random-access-storage';
8
- import { describe, test, afterTest } from '@dxos/test';
9
8
 
10
9
  import { TestAgentBuilder, WebsocketNetworkManagerProvider } from '../testing';
11
10
 
@@ -20,7 +19,9 @@ describe('space-manager', () => {
20
19
  storage: createStorage(),
21
20
  networkManagerProvider: WebsocketNetworkManagerProvider(SIGNAL_URL),
22
21
  });
23
- afterTest(async () => await builder.close());
22
+ onTestFinished(async () => {
23
+ await builder.close();
24
+ });
24
25
 
25
26
  const peer1 = await builder.createPeer();
26
27
  const spaceManager1 = peer1.spaceManager;
@@ -30,8 +31,8 @@ describe('space-manager', () => {
30
31
  const spaceManager2 = peer2.spaceManager;
31
32
  await spaceManager2.open();
32
33
 
33
- afterTest(() => spaceManager1.close());
34
- afterTest(() => spaceManager2.close());
34
+ onTestFinished(() => spaceManager1.close());
35
+ onTestFinished(() => spaceManager2.close());
35
36
 
36
37
  // const space1 = await spaceManager1.createSpace();
37
38
  // expect(space1.isOpen).to.be.true;