@irtio/testing 4.0.0 → 4.1.0
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/README.md +66 -0
- package/dist/{chunk-LQ5TGD2E.js → chunk-7GS3V7QO.js} +7 -5
- package/dist/index.js +1 -1
- package/dist/matchers.js +1 -1
- package/package.json +7 -7
package/README.md
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# @irtio/testing
|
|
2
|
+
|
|
3
|
+
Test room logic with real irtio clients and a controllable clock. Check synchronization, RPCs,
|
|
4
|
+
reconnection, and visibility without opening sockets.
|
|
5
|
+
|
|
6
|
+
```bash
|
|
7
|
+
npm install --save-dev @irtio/testing vitest
|
|
8
|
+
```
|
|
9
|
+
|
|
10
|
+
## Test a player update
|
|
11
|
+
|
|
12
|
+
This test uses the room generated by `npx irtio init --tick --yes`.
|
|
13
|
+
Create or replace `irtio/room.test.ts`:
|
|
14
|
+
|
|
15
|
+
```ts
|
|
16
|
+
import { expect, test } from 'vitest';
|
|
17
|
+
import { testRoom } from '@irtio/testing';
|
|
18
|
+
import '@irtio/testing/matchers';
|
|
19
|
+
import room from './room.js';
|
|
20
|
+
|
|
21
|
+
test('an owned write reaches another player', async () => {
|
|
22
|
+
const t = await testRoom(room);
|
|
23
|
+
try {
|
|
24
|
+
const [a, b] = await t.join(2, { role: 'player' });
|
|
25
|
+
const player = a.state.players.get(a.id);
|
|
26
|
+
expect(player).toBeDefined();
|
|
27
|
+
player!.x = 10;
|
|
28
|
+
a.flush();
|
|
29
|
+
await t.tick(2);
|
|
30
|
+
|
|
31
|
+
expect(t.state.players.get(a.id)?.x).toBe(10);
|
|
32
|
+
expect(b.state.players.get(a.id)?.x).toBe(10);
|
|
33
|
+
expect(t).toHaveConverged();
|
|
34
|
+
expect(t).toHaveNoVisibilityLeaks();
|
|
35
|
+
} finally {
|
|
36
|
+
t.stop();
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
npx vitest run irtio/room.test.ts
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## Drive the clock
|
|
46
|
+
|
|
47
|
+
| Method | Behavior |
|
|
48
|
+
| --- | --- |
|
|
49
|
+
| `await t.join(spec?)` | Join one client |
|
|
50
|
+
| `await t.join(n, spec?)` | Join multiple clients |
|
|
51
|
+
| `await t.tick(n?)` | Advance server ticks; defaults to one |
|
|
52
|
+
| `await t.run(ms)` | Advance fake time in milliseconds |
|
|
53
|
+
| `await t.until(predicate, options?)` | Advance until a condition holds, or reject at the limit |
|
|
54
|
+
| `t.stop()` | Stop the room and its clients |
|
|
55
|
+
|
|
56
|
+
Await all clock operations. By default, awaiting client RPCs also advances the clock until they
|
|
57
|
+
settle, and a room handler error fails the test. Configure `autoPump` and `failOnHandlerError`
|
|
58
|
+
when testing those behaviors explicitly.
|
|
59
|
+
|
|
60
|
+
`testRelay()` tests schema-less relay messaging. Import `@irtio/testing/matchers` to register
|
|
61
|
+
Vitest matchers; the main entry point also exports assertion functions for other runners.
|
|
62
|
+
For physics rooms, await the corresponding `initPhysics`, `initRapier2d`, or `initMatter`
|
|
63
|
+
initializer before creating the test room.
|
|
64
|
+
|
|
65
|
+
See the [testing reference](https://irt.io/docs/reference/testing) for all options, matchers,
|
|
66
|
+
network conditions, and physics helpers.
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
// src/compare.ts
|
|
2
|
+
import { isPerClient } from "@irtio/runtime";
|
|
2
3
|
import {
|
|
3
4
|
cloneValue,
|
|
4
5
|
computeDirty,
|
|
@@ -46,7 +47,7 @@ function divergence(ext, authority, client, visible, memberships = /* @__PURE__
|
|
|
46
47
|
for (const [name, cd] of computeDirty(ext, authority, client)) {
|
|
47
48
|
if (!visible.has(name)) continue;
|
|
48
49
|
const desc = ext.collection(name);
|
|
49
|
-
const membership = desc
|
|
50
|
+
const membership = isPerClient(desc) ? memberships.get(name) : void 0;
|
|
50
51
|
for (const id of cd.added) {
|
|
51
52
|
if (!membership || !membership.has(id)) out.push(`${name}[${id}]: only in the client's view`);
|
|
52
53
|
}
|
|
@@ -108,6 +109,7 @@ import {
|
|
|
108
109
|
RoomCore,
|
|
109
110
|
RoomFullError,
|
|
110
111
|
createVisibilityPolicy,
|
|
112
|
+
isPerClient as isPerClient2,
|
|
111
113
|
visibleNames
|
|
112
114
|
} from "@irtio/runtime";
|
|
113
115
|
import { FakeClock, HarnessHost, frameTypeName } from "@irtio/runtime/test";
|
|
@@ -874,16 +876,16 @@ var TestHarness = class {
|
|
|
874
876
|
const seen = this.deliveredIds(link.clientId, dc.name);
|
|
875
877
|
const leaked = dc.ops.filter((op) => {
|
|
876
878
|
if (op.op === "remove") {
|
|
877
|
-
if (keep.has(dc.name)) return desc
|
|
879
|
+
if (keep.has(dc.name)) return isPerClient2(desc) && !seen.has(op.id);
|
|
878
880
|
return !seen.has(op.id);
|
|
879
881
|
}
|
|
880
882
|
if (!keep.has(dc.name)) return true;
|
|
881
|
-
if (desc
|
|
883
|
+
if (!isPerClient2(desc)) return false;
|
|
882
884
|
return !policy.maySeeEntity(desc, op.id);
|
|
883
885
|
});
|
|
884
886
|
for (const op of dc.ops) {
|
|
885
887
|
if (op.op === "remove") seen.delete(op.id);
|
|
886
|
-
else if (desc
|
|
888
|
+
else if (!isPerClient2(desc) || policy.maySeeEntity(desc, op.id)) {
|
|
887
889
|
seen.add(op.id);
|
|
888
890
|
}
|
|
889
891
|
}
|
|
@@ -1205,7 +1207,7 @@ var TestHarness = class {
|
|
|
1205
1207
|
const policy = createVisibilityPolicy(this.ext, this.plain, client.id, role);
|
|
1206
1208
|
const view = client.view;
|
|
1207
1209
|
for (const c of this.ext.collections) {
|
|
1208
|
-
if (c
|
|
1210
|
+
if (isPerClient2(c)) {
|
|
1209
1211
|
const coll = view[c.name];
|
|
1210
1212
|
const ids = coll ? [...coll.ids()].filter((id) => !policy.maySeeEntity(c, id)) : [];
|
|
1211
1213
|
if (ids.length > 0) {
|
package/dist/index.js
CHANGED
package/dist/matchers.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@irtio/testing",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.1.0",
|
|
4
4
|
"description": "irtio's blessed test API: testRoom() in-process rooms with real client semantics, plus Vitest matchers",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -28,12 +28,12 @@
|
|
|
28
28
|
"dist"
|
|
29
29
|
],
|
|
30
30
|
"dependencies": {
|
|
31
|
-
"@irtio/bots": "^4.
|
|
32
|
-
"@irtio/client": "^4.
|
|
33
|
-
"@irtio/protocol": "^4.
|
|
34
|
-
"@irtio/runtime": "^4.
|
|
35
|
-
"@irtio/schema": "^4.
|
|
36
|
-
"@irtio/server": "^4.
|
|
31
|
+
"@irtio/bots": "^4.1.0",
|
|
32
|
+
"@irtio/client": "^4.1.0",
|
|
33
|
+
"@irtio/protocol": "^4.1.0",
|
|
34
|
+
"@irtio/runtime": "^4.1.0",
|
|
35
|
+
"@irtio/schema": "^4.1.0",
|
|
36
|
+
"@irtio/server": "^4.1.0"
|
|
37
37
|
},
|
|
38
38
|
"peerDependencies": {
|
|
39
39
|
"vitest": ">=3"
|