@hydranium/protocol 1.0.0-next.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.
- package/LICENSE +21 -0
- package/README.md +81 -0
- package/lib/abstract-logger.d.ts +66 -0
- package/lib/abstract-logger.d.ts.map +1 -0
- package/lib/abstract-logger.js +110 -0
- package/lib/abstract-logger.js.map +1 -0
- package/lib/browser-runtime.d.ts +124 -0
- package/lib/browser-runtime.d.ts.map +1 -0
- package/lib/browser-runtime.js +11 -0
- package/lib/browser-runtime.js.map +1 -0
- package/lib/client/data-events.d.ts +49 -0
- package/lib/client/data-events.d.ts.map +1 -0
- package/lib/client/data-events.js +60 -0
- package/lib/client/data-events.js.map +1 -0
- package/lib/client/data-port.d.ts +95 -0
- package/lib/client/data-port.d.ts.map +1 -0
- package/lib/client/data-port.js +11 -0
- package/lib/client/data-port.js.map +1 -0
- package/lib/client/data-session.d.ts +129 -0
- package/lib/client/data-session.d.ts.map +1 -0
- package/lib/client/data-session.js +179 -0
- package/lib/client/data-session.js.map +1 -0
- package/lib/client/index.d.ts +39 -0
- package/lib/client/index.d.ts.map +1 -0
- package/lib/client/index.js +55 -0
- package/lib/client/index.js.map +1 -0
- package/lib/client/message-relay.d.ts +111 -0
- package/lib/client/message-relay.d.ts.map +1 -0
- package/lib/client/message-relay.js +139 -0
- package/lib/client/message-relay.js.map +1 -0
- package/lib/client/post-message-transport.d.ts +77 -0
- package/lib/client/post-message-transport.d.ts.map +1 -0
- package/lib/client/post-message-transport.js +95 -0
- package/lib/client/post-message-transport.js.map +1 -0
- package/lib/clock.d.ts +111 -0
- package/lib/clock.d.ts.map +1 -0
- package/lib/clock.js +74 -0
- package/lib/clock.js.map +1 -0
- package/lib/data/data-protocol-methods.d.ts +39 -0
- package/lib/data/data-protocol-methods.d.ts.map +1 -0
- package/lib/data/data-protocol-methods.js +61 -0
- package/lib/data/data-protocol-methods.js.map +1 -0
- package/lib/data/data-server-protocol.d.ts +264 -0
- package/lib/data/data-server-protocol.d.ts.map +1 -0
- package/lib/data/data-server-protocol.js +11 -0
- package/lib/data/data-server-protocol.js.map +1 -0
- package/lib/data/diagnostics.d.ts +97 -0
- package/lib/data/diagnostics.d.ts.map +1 -0
- package/lib/data/diagnostics.js +25 -0
- package/lib/data/diagnostics.js.map +1 -0
- package/lib/data/events.d.ts +107 -0
- package/lib/data/events.d.ts.map +1 -0
- package/lib/data/events.js +11 -0
- package/lib/data/events.js.map +1 -0
- package/lib/data/index.d.ts +15 -0
- package/lib/data/index.d.ts.map +1 -0
- package/lib/data/index.js +38 -0
- package/lib/data/index.js.map +1 -0
- package/lib/data/methods.d.ts +57 -0
- package/lib/data/methods.d.ts.map +1 -0
- package/lib/data/methods.js +60 -0
- package/lib/data/methods.js.map +1 -0
- package/lib/data/requests.d.ts +65 -0
- package/lib/data/requests.d.ts.map +1 -0
- package/lib/data/requests.js +11 -0
- package/lib/data/requests.js.map +1 -0
- package/lib/debouncer.d.ts +75 -0
- package/lib/debouncer.d.ts.map +1 -0
- package/lib/debouncer.js +91 -0
- package/lib/debouncer.js.map +1 -0
- package/lib/errors.d.ts +84 -0
- package/lib/errors.d.ts.map +1 -0
- package/lib/errors.js +113 -0
- package/lib/errors.js.map +1 -0
- package/lib/host-diagnostics.d.ts +58 -0
- package/lib/host-diagnostics.d.ts.map +1 -0
- package/lib/host-diagnostics.js +18 -0
- package/lib/host-diagnostics.js.map +1 -0
- package/lib/index.d.ts +34 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +56 -0
- package/lib/index.js.map +1 -0
- package/lib/latency-collector.d.ts +126 -0
- package/lib/latency-collector.d.ts.map +1 -0
- package/lib/latency-collector.js +137 -0
- package/lib/latency-collector.js.map +1 -0
- package/lib/logger.d.ts +119 -0
- package/lib/logger.d.ts.map +1 -0
- package/lib/logger.js +126 -0
- package/lib/logger.js.map +1 -0
- package/lib/model-server.d.ts +352 -0
- package/lib/model-server.d.ts.map +1 -0
- package/lib/model-server.js +160 -0
- package/lib/model-server.js.map +1 -0
- package/lib/model-service/args.d.ts +64 -0
- package/lib/model-service/args.d.ts.map +1 -0
- package/lib/model-service/args.js +11 -0
- package/lib/model-service/args.js.map +1 -0
- package/lib/model-service/index.d.ts +11 -0
- package/lib/model-service/index.d.ts.map +1 -0
- package/lib/model-service/index.js +31 -0
- package/lib/model-service/index.js.map +1 -0
- package/lib/model-service/reference-candidate.d.ts +56 -0
- package/lib/model-service/reference-candidate.d.ts.map +1 -0
- package/lib/model-service/reference-candidate.js +11 -0
- package/lib/model-service/reference-candidate.js.map +1 -0
- package/lib/noop-logger.d.ts +25 -0
- package/lib/noop-logger.d.ts.map +1 -0
- package/lib/noop-logger.js +36 -0
- package/lib/noop-logger.js.map +1 -0
- package/lib/observable-value.d.ts +72 -0
- package/lib/observable-value.d.ts.map +1 -0
- package/lib/observable-value.js +52 -0
- package/lib/observable-value.js.map +1 -0
- package/lib/patch-merge.d.ts +123 -0
- package/lib/patch-merge.d.ts.map +1 -0
- package/lib/patch-merge.js +104 -0
- package/lib/patch-merge.js.map +1 -0
- package/lib/profile-session.d.ts +87 -0
- package/lib/profile-session.d.ts.map +1 -0
- package/lib/profile-session.js +98 -0
- package/lib/profile-session.js.map +1 -0
- package/lib/profiling.d.ts +83 -0
- package/lib/profiling.d.ts.map +1 -0
- package/lib/profiling.js +20 -0
- package/lib/profiling.js.map +1 -0
- package/lib/project.d.ts +121 -0
- package/lib/project.d.ts.map +1 -0
- package/lib/project.js +34 -0
- package/lib/project.js.map +1 -0
- package/lib/rpc/bind-rpc-methods.d.ts +100 -0
- package/lib/rpc/bind-rpc-methods.d.ts.map +1 -0
- package/lib/rpc/bind-rpc-methods.js +110 -0
- package/lib/rpc/bind-rpc-methods.js.map +1 -0
- package/lib/rpc/create-rpc-proxy.d.ts +188 -0
- package/lib/rpc/create-rpc-proxy.d.ts.map +1 -0
- package/lib/rpc/create-rpc-proxy.js +158 -0
- package/lib/rpc/create-rpc-proxy.js.map +1 -0
- package/lib/rpc/index.d.ts +12 -0
- package/lib/rpc/index.d.ts.map +1 -0
- package/lib/rpc/index.js +31 -0
- package/lib/rpc/index.js.map +1 -0
- package/lib/rpc/wire-prefix.d.ts +37 -0
- package/lib/rpc/wire-prefix.d.ts.map +1 -0
- package/lib/rpc/wire-prefix.js +49 -0
- package/lib/rpc/wire-prefix.js.map +1 -0
- package/lib/testing/data-doubles.d.ts +121 -0
- package/lib/testing/data-doubles.d.ts.map +1 -0
- package/lib/testing/data-doubles.js +102 -0
- package/lib/testing/data-doubles.js.map +1 -0
- package/lib/testing/fake-clock.d.ts +35 -0
- package/lib/testing/fake-clock.d.ts.map +1 -0
- package/lib/testing/fake-clock.js +86 -0
- package/lib/testing/fake-clock.js.map +1 -0
- package/lib/testing/harness.d.ts +24 -0
- package/lib/testing/harness.d.ts.map +1 -0
- package/lib/testing/harness.js +11 -0
- package/lib/testing/harness.js.map +1 -0
- package/lib/testing/index.d.ts +13 -0
- package/lib/testing/index.d.ts.map +1 -0
- package/lib/testing/index.js +41 -0
- package/lib/testing/index.js.map +1 -0
- package/lib/testing/node/duplex-connection.d.ts +25 -0
- package/lib/testing/node/duplex-connection.d.ts.map +1 -0
- package/lib/testing/node/duplex-connection.js +34 -0
- package/lib/testing/node/duplex-connection.js.map +1 -0
- package/lib/testing/node/duplex-stream.d.ts +32 -0
- package/lib/testing/node/duplex-stream.d.ts.map +1 -0
- package/lib/testing/node/duplex-stream.js +35 -0
- package/lib/testing/node/duplex-stream.js.map +1 -0
- package/lib/testing/node/index.d.ts +11 -0
- package/lib/testing/node/index.d.ts.map +1 -0
- package/lib/testing/node/index.js +37 -0
- package/lib/testing/node/index.js.map +1 -0
- package/lib/testing/wait-for.d.ts +69 -0
- package/lib/testing/wait-for.d.ts.map +1 -0
- package/lib/testing/wait-for.js +67 -0
- package/lib/testing/wait-for.js.map +1 -0
- package/lib/tracer.d.ts +115 -0
- package/lib/tracer.d.ts.map +1 -0
- package/lib/tracer.js +205 -0
- package/lib/tracer.js.map +1 -0
- package/lib/transfer-diagnostic.d.ts +73 -0
- package/lib/transfer-diagnostic.d.ts.map +1 -0
- package/lib/transfer-diagnostic.js +45 -0
- package/lib/transfer-diagnostic.js.map +1 -0
- package/lib/transfer-document.d.ts +73 -0
- package/lib/transfer-document.d.ts.map +1 -0
- package/lib/transfer-document.js +46 -0
- package/lib/transfer-document.js.map +1 -0
- package/lib/transfer-element.d.ts +39 -0
- package/lib/transfer-element.d.ts.map +1 -0
- package/lib/transfer-element.js +11 -0
- package/lib/transfer-element.js.map +1 -0
- package/lib/uri.d.ts +62 -0
- package/lib/uri.d.ts.map +1 -0
- package/lib/uri.js +28 -0
- package/lib/uri.js.map +1 -0
- package/lib/util.d.ts +147 -0
- package/lib/util.d.ts.map +1 -0
- package/lib/util.js +211 -0
- package/lib/util.js.map +1 -0
- package/package.json +100 -0
- package/src/abstract-logger.ts +120 -0
- package/src/browser-runtime.ts +135 -0
- package/src/client/data-events.ts +71 -0
- package/src/client/data-port.ts +99 -0
- package/src/client/data-session.ts +209 -0
- package/src/client/index.ts +40 -0
- package/src/client/message-relay.ts +216 -0
- package/src/client/post-message-transport.ts +167 -0
- package/src/clock.ts +173 -0
- package/src/data/data-protocol-methods.ts +79 -0
- package/src/data/data-server-protocol.ts +296 -0
- package/src/data/diagnostics.ts +116 -0
- package/src/data/events.ts +127 -0
- package/src/data/index.ts +23 -0
- package/src/data/methods.ts +59 -0
- package/src/data/requests.ts +70 -0
- package/src/debouncer.ts +118 -0
- package/src/errors.ts +127 -0
- package/src/host-diagnostics.ts +63 -0
- package/src/index.ts +41 -0
- package/src/latency-collector.ts +231 -0
- package/src/logger.ts +172 -0
- package/src/model-server.ts +479 -0
- package/src/model-service/args.ts +67 -0
- package/src/model-service/index.ts +16 -0
- package/src/model-service/reference-candidate.ts +58 -0
- package/src/noop-logger.ts +36 -0
- package/src/observable-value.ts +92 -0
- package/src/patch-merge.ts +165 -0
- package/src/profile-session.ts +164 -0
- package/src/profiling.ts +113 -0
- package/src/project.ts +125 -0
- package/src/rpc/README.md +163 -0
- package/src/rpc/bind-rpc-methods.ts +180 -0
- package/src/rpc/create-rpc-proxy.ts +292 -0
- package/src/rpc/index.ts +16 -0
- package/src/rpc/wire-prefix.ts +48 -0
- package/src/testing/data-doubles.ts +178 -0
- package/src/testing/fake-clock.ts +106 -0
- package/src/testing/harness.ts +24 -0
- package/src/testing/index.ts +26 -0
- package/src/testing/node/duplex-connection.ts +50 -0
- package/src/testing/node/duplex-stream.ts +51 -0
- package/src/testing/node/index.ts +22 -0
- package/src/testing/wait-for.ts +94 -0
- package/src/tracer.ts +277 -0
- package/src/transfer-diagnostic.ts +92 -0
- package/src/transfer-document.ts +99 -0
- package/src/transfer-element.ts +43 -0
- package/src/uri.ts +61 -0
- package/src/util.ts +250 -0
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/********************************************************************************
|
|
3
|
+
* Copyright (c) 2026 CrossBreeze, EclipseSource and others.
|
|
4
|
+
*
|
|
5
|
+
* This program and the accompanying materials are made available under the
|
|
6
|
+
* terms of the MIT License which is available in the project root.
|
|
7
|
+
*
|
|
8
|
+
* SPDX-License-Identifier: MIT
|
|
9
|
+
********************************************************************************/
|
|
10
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
|
+
exports.makeFakeDataPort = makeFakeDataPort;
|
|
12
|
+
exports.makeCapturingDataClient = makeCapturingDataClient;
|
|
13
|
+
/**
|
|
14
|
+
* The two CLIENT-side doubles of the data head: a {@link DataPort} whose
|
|
15
|
+
* transport the test supplies, and a {@link DataClientProtocol} that records
|
|
16
|
+
* what arrived.
|
|
17
|
+
*
|
|
18
|
+
* # Why standalone, when a harness already builds one
|
|
19
|
+
*
|
|
20
|
+
* `makeDataServerHarness` builds a capturing client too, but fused into a
|
|
21
|
+
* server-bearing harness: taking it means taking a duplex pair, a `DataServer`
|
|
22
|
+
* and a proxy. That is the right shape for testing the server. It is the wrong
|
|
23
|
+
* shape — and not available at all — for testing the CLIENT half: a
|
|
24
|
+
* `DataSession`, a widget model, a host's port adapter. Those need to stand a
|
|
25
|
+
* double on one side of the boundary and something else entirely on the other,
|
|
26
|
+
* which is why both halves get hand-rolled per suite instead.
|
|
27
|
+
*
|
|
28
|
+
* # Runner-agnostic, deliberately
|
|
29
|
+
*
|
|
30
|
+
* No `jest.fn`, no `vi.fn`, no `expect`. The recorded arrays ARE the assertion
|
|
31
|
+
* surface, so the same double works under vitest, jest and a bare script. A
|
|
32
|
+
* mock-framework double would also make "was it called" the observable, when
|
|
33
|
+
* what a data-head test actually asserts is the CONTENT of what arrived —
|
|
34
|
+
* which `sourceClientId`, which version, which reason.
|
|
35
|
+
*/
|
|
36
|
+
const vscode_jsonrpc_1 = require("vscode-jsonrpc");
|
|
37
|
+
/**
|
|
38
|
+
* A {@link DataPort} over a transport the caller supplies.
|
|
39
|
+
*
|
|
40
|
+
* It deliberately does not create the transport itself. What varies between the
|
|
41
|
+
* cases worth testing is exactly that: an in-process duplex pair, a socket, a
|
|
42
|
+
* connection with no server behind it, a different one per generation.
|
|
43
|
+
*/
|
|
44
|
+
function makeFakeDataPort(options) {
|
|
45
|
+
const connections = [];
|
|
46
|
+
const reported = [];
|
|
47
|
+
const disposeEmitter = new vscode_jsonrpc_1.Emitter();
|
|
48
|
+
return {
|
|
49
|
+
clientId: options.clientId ?? 'fake-data-port',
|
|
50
|
+
connections,
|
|
51
|
+
reported,
|
|
52
|
+
onDispose: disposeEmitter.event,
|
|
53
|
+
async connect() {
|
|
54
|
+
const connection = await options.connect();
|
|
55
|
+
connections.push(connection);
|
|
56
|
+
return connection;
|
|
57
|
+
},
|
|
58
|
+
reportError(error, context) {
|
|
59
|
+
reported.push({ error, context });
|
|
60
|
+
},
|
|
61
|
+
fireDispose() {
|
|
62
|
+
disposeEmitter.fire(undefined);
|
|
63
|
+
},
|
|
64
|
+
dispose() {
|
|
65
|
+
disposeEmitter.dispose();
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* A {@link DataClientProtocol} that records every notification it receives.
|
|
71
|
+
*
|
|
72
|
+
* Recording ALL THREE channels even when a suite reads one is deliberate: an
|
|
73
|
+
* event delivered on the wrong channel is a real defect of the data head, and a
|
|
74
|
+
* double that drops the other two turns it into silence on the one being
|
|
75
|
+
* watched.
|
|
76
|
+
*
|
|
77
|
+
* An override replaces a channel's recording rather than supplementing it, so
|
|
78
|
+
* the corresponding array stays empty — that is what makes an override usable
|
|
79
|
+
* as a barrier (rejecting, counting differently, throwing) rather than only as
|
|
80
|
+
* a spy.
|
|
81
|
+
*/
|
|
82
|
+
function makeCapturingDataClient(overrides = {}) {
|
|
83
|
+
const updates = [];
|
|
84
|
+
const saves = [];
|
|
85
|
+
const projectsChanges = [];
|
|
86
|
+
const client = {
|
|
87
|
+
onDocumentUpdated: overrides.onDocumentUpdated ??
|
|
88
|
+
(event => {
|
|
89
|
+
updates.push(event);
|
|
90
|
+
}),
|
|
91
|
+
onDocumentSaved: overrides.onDocumentSaved ??
|
|
92
|
+
(event => {
|
|
93
|
+
saves.push(event);
|
|
94
|
+
}),
|
|
95
|
+
onProjectsChanged: overrides.onProjectsChanged ??
|
|
96
|
+
(event => {
|
|
97
|
+
projectsChanges.push(event);
|
|
98
|
+
})
|
|
99
|
+
};
|
|
100
|
+
return { client, updates, saves, projectsChanges };
|
|
101
|
+
}
|
|
102
|
+
//# sourceMappingURL=data-doubles.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"data-doubles.js","sourceRoot":"","sources":["../../src/testing/data-doubles.ts"],"names":[],"mappings":";AAAA;;;;;;;kFAOkF;;AAyFlF,4CAwBC;AA+BD,0DA0BC;AAxKD;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,mDAAiE;AAwDjE;;;;;;GAMG;AACH,SAAgB,gBAAgB,CAAC,OAA4B;IAC1D,MAAM,WAAW,GAAwB,EAAE,CAAC;IAC5C,MAAM,QAAQ,GAA0C,EAAE,CAAC;IAC3D,MAAM,cAAc,GAAG,IAAI,wBAAO,EAAQ,CAAC;IAC3C,OAAO;QACJ,QAAQ,EAAE,OAAO,CAAC,QAAQ,IAAI,gBAAgB;QAC9C,WAAW;QACX,QAAQ;QACR,SAAS,EAAE,cAAc,CAAC,KAAK;QAC/B,KAAK,CAAC,OAAO;YACV,MAAM,UAAU,GAAG,MAAM,OAAO,CAAC,OAAO,EAAE,CAAC;YAC3C,WAAW,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YAC7B,OAAO,UAAU,CAAC;QACrB,CAAC;QACD,WAAW,CAAC,KAAc,EAAE,OAAe;YACxC,QAAQ,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,CAAC;QACrC,CAAC;QACD,WAAW;YACR,cAAc,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QAClC,CAAC;QACD,OAAO;YACJ,cAAc,CAAC,OAAO,EAAE,CAAC;QAC5B,CAAC;KACH,CAAC;AACL,CAAC;AAkBD;;;;;;;;;;;;GAYG;AACH,SAAgB,uBAAuB,CAIrC,YAA2E,EAAE;IAC5E,MAAM,OAAO,GAA2D,EAAE,CAAC;IAC3E,MAAM,KAAK,GAAyD,EAAE,CAAC;IACvE,MAAM,eAAe,GAAqC,EAAE,CAAC;IAC7D,MAAM,MAAM,GAAyD;QAClE,iBAAiB,EACd,SAAS,CAAC,iBAAiB;YAC3B,CAAC,KAAK,CAAC,EAAE;gBACN,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACvB,CAAC,CAAC;QACL,eAAe,EACZ,SAAS,CAAC,eAAe;YACzB,CAAC,KAAK,CAAC,EAAE;gBACN,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACrB,CAAC,CAAC;QACL,iBAAiB,EACd,SAAS,CAAC,iBAAiB;YAC3B,CAAC,KAAK,CAAC,EAAE;gBACN,eAAe,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAC/B,CAAC,CAAC;KACP,CAAC;IACF,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,eAAe,EAAE,CAAC;AACtD,CAAC"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/********************************************************************************
|
|
2
|
+
* Copyright (c) 2026 CrossBreeze, EclipseSource and others.
|
|
3
|
+
*
|
|
4
|
+
* This program and the accompanying materials are made available under the
|
|
5
|
+
* terms of the MIT License which is available in the project root.
|
|
6
|
+
*
|
|
7
|
+
* SPDX-License-Identifier: MIT
|
|
8
|
+
********************************************************************************/
|
|
9
|
+
import { type Clock } from '../clock';
|
|
10
|
+
/** A {@link Clock} whose time only moves when the test calls {@link FakeClock.advance}. */
|
|
11
|
+
export interface FakeClock extends Clock {
|
|
12
|
+
/**
|
|
13
|
+
* Move virtual time forward by `ms`, firing every {@link Clock.setTimer}
|
|
14
|
+
* whose deadline falls within the window — in chronological order, each at
|
|
15
|
+
* its own deadline (so `now()` inside a callback reads the fire instant, not
|
|
16
|
+
* the advance target). Timers scheduled by a callback fire too if they fall
|
|
17
|
+
* within the same window.
|
|
18
|
+
*/
|
|
19
|
+
advance(ms: number): void;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* In-process {@link Clock} double for deterministic time. The real
|
|
23
|
+
* `SystemClock` has two underlying sources
|
|
24
|
+
* (`Date.now` for `now()`, `performance.now()` for the stopwatch); the fake
|
|
25
|
+
* collapses them onto ONE virtual time axis, so a single
|
|
26
|
+
* {@link FakeClock.advance} drives `now()`, every live stopwatch's elapsed, and
|
|
27
|
+
* any due timer together.
|
|
28
|
+
*
|
|
29
|
+
* Server-free and DI-free — lives in `@hydranium/protocol/testing` so every
|
|
30
|
+
* head can bind it without pulling in a server package.
|
|
31
|
+
*/
|
|
32
|
+
export declare function makeFakeClock(options?: {
|
|
33
|
+
now?: number;
|
|
34
|
+
}): FakeClock;
|
|
35
|
+
//# sourceMappingURL=fake-clock.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fake-clock.d.ts","sourceRoot":"","sources":["../../src/testing/fake-clock.ts"],"names":[],"mappings":"AAAA;;;;;;;kFAOkF;AAElF,OAAO,EAAE,KAAK,KAAK,EAA8B,MAAM,UAAU,CAAC;AAGlE,2FAA2F;AAC3F,MAAM,WAAW,SAAU,SAAQ,KAAK;IACrC;;;;;;OAMG;IACH,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B;AASD;;;;;;;;;;GAUG;AACH,wBAAgB,aAAa,CAAC,OAAO,GAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAA;CAAO,GAAG,SAAS,CA+DvE"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/********************************************************************************
|
|
3
|
+
* Copyright (c) 2026 CrossBreeze, EclipseSource and others.
|
|
4
|
+
*
|
|
5
|
+
* This program and the accompanying materials are made available under the
|
|
6
|
+
* terms of the MIT License which is available in the project root.
|
|
7
|
+
*
|
|
8
|
+
* SPDX-License-Identifier: MIT
|
|
9
|
+
********************************************************************************/
|
|
10
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
|
+
exports.makeFakeClock = makeFakeClock;
|
|
12
|
+
const util_1 = require("../util");
|
|
13
|
+
/**
|
|
14
|
+
* In-process {@link Clock} double for deterministic time. The real
|
|
15
|
+
* `SystemClock` has two underlying sources
|
|
16
|
+
* (`Date.now` for `now()`, `performance.now()` for the stopwatch); the fake
|
|
17
|
+
* collapses them onto ONE virtual time axis, so a single
|
|
18
|
+
* {@link FakeClock.advance} drives `now()`, every live stopwatch's elapsed, and
|
|
19
|
+
* any due timer together.
|
|
20
|
+
*
|
|
21
|
+
* Server-free and DI-free — lives in `@hydranium/protocol/testing` so every
|
|
22
|
+
* head can bind it without pulling in a server package.
|
|
23
|
+
*/
|
|
24
|
+
function makeFakeClock(options = {}) {
|
|
25
|
+
let current = options.now ?? 0;
|
|
26
|
+
const timers = [];
|
|
27
|
+
const makeStopwatch = () => {
|
|
28
|
+
const start = current;
|
|
29
|
+
let lastLap = current;
|
|
30
|
+
let stopped;
|
|
31
|
+
return {
|
|
32
|
+
get elapsedMs() {
|
|
33
|
+
return (stopped ?? current) - start;
|
|
34
|
+
},
|
|
35
|
+
lap() {
|
|
36
|
+
const at = stopped ?? current;
|
|
37
|
+
const split = at - lastLap;
|
|
38
|
+
lastLap = at;
|
|
39
|
+
return split;
|
|
40
|
+
},
|
|
41
|
+
stop() {
|
|
42
|
+
if (stopped === undefined) {
|
|
43
|
+
stopped = current;
|
|
44
|
+
}
|
|
45
|
+
return stopped - start;
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
};
|
|
49
|
+
return {
|
|
50
|
+
now: () => current,
|
|
51
|
+
setTimer(callback, ms) {
|
|
52
|
+
const timer = { at: current + ms, callback, disposed: false, fired: false };
|
|
53
|
+
timers.push(timer);
|
|
54
|
+
return util_1.Disposable.create(() => {
|
|
55
|
+
timer.disposed = true;
|
|
56
|
+
});
|
|
57
|
+
},
|
|
58
|
+
stopwatch: makeStopwatch,
|
|
59
|
+
measure: ((callback) => {
|
|
60
|
+
const stopwatch = makeStopwatch();
|
|
61
|
+
const result = callback();
|
|
62
|
+
if (result instanceof Promise) {
|
|
63
|
+
return result.then(value => ({ result: value, elapsedMs: stopwatch.elapsedMs }));
|
|
64
|
+
}
|
|
65
|
+
return { result: result, elapsedMs: stopwatch.elapsedMs };
|
|
66
|
+
}),
|
|
67
|
+
advance(ms) {
|
|
68
|
+
const target = current + ms;
|
|
69
|
+
// Fire due timers one at a time, re-scanning after each so a callback
|
|
70
|
+
// that schedules a nearer timer still fires within this window.
|
|
71
|
+
for (;;) {
|
|
72
|
+
const next = timers
|
|
73
|
+
.filter(timer => !timer.disposed && !timer.fired && timer.at <= target)
|
|
74
|
+
.sort((left, right) => left.at - right.at)[0];
|
|
75
|
+
if (!next) {
|
|
76
|
+
break;
|
|
77
|
+
}
|
|
78
|
+
current = next.at;
|
|
79
|
+
next.fired = true;
|
|
80
|
+
next.callback();
|
|
81
|
+
}
|
|
82
|
+
current = target;
|
|
83
|
+
}
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
//# sourceMappingURL=fake-clock.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fake-clock.js","sourceRoot":"","sources":["../../src/testing/fake-clock.ts"],"names":[],"mappings":";AAAA;;;;;;;kFAOkF;;AAmClF,sCA+DC;AA/FD,kCAAqC;AAqBrC;;;;;;;;;;GAUG;AACH,SAAgB,aAAa,CAAC,UAA4B,EAAE;IACzD,IAAI,OAAO,GAAG,OAAO,CAAC,GAAG,IAAI,CAAC,CAAC;IAC/B,MAAM,MAAM,GAAgB,EAAE,CAAC;IAE/B,MAAM,aAAa,GAAG,GAAc,EAAE;QACnC,MAAM,KAAK,GAAG,OAAO,CAAC;QACtB,IAAI,OAAO,GAAG,OAAO,CAAC;QACtB,IAAI,OAA2B,CAAC;QAChC,OAAO;YACJ,IAAI,SAAS;gBACV,OAAO,CAAC,OAAO,IAAI,OAAO,CAAC,GAAG,KAAK,CAAC;YACvC,CAAC;YACD,GAAG;gBACA,MAAM,EAAE,GAAG,OAAO,IAAI,OAAO,CAAC;gBAC9B,MAAM,KAAK,GAAG,EAAE,GAAG,OAAO,CAAC;gBAC3B,OAAO,GAAG,EAAE,CAAC;gBACb,OAAO,KAAK,CAAC;YAChB,CAAC;YACD,IAAI;gBACD,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;oBACzB,OAAO,GAAG,OAAO,CAAC;gBACrB,CAAC;gBACD,OAAO,OAAO,GAAG,KAAK,CAAC;YAC1B,CAAC;SACH,CAAC;IACL,CAAC,CAAC;IAEF,OAAO;QACJ,GAAG,EAAE,GAAG,EAAE,CAAC,OAAO;QAClB,QAAQ,CAAC,QAAoB,EAAE,EAAU;YACtC,MAAM,KAAK,GAAc,EAAE,EAAE,EAAE,OAAO,GAAG,EAAE,EAAE,QAAQ,EAAE,QAAQ,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC;YACvF,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACnB,OAAO,iBAAU,CAAC,MAAM,CAAC,GAAG,EAAE;gBAC3B,KAAK,CAAC,QAAQ,GAAG,IAAI,CAAC;YACzB,CAAC,CAAC,CAAC;QACN,CAAC;QACD,SAAS,EAAE,aAAa;QACxB,OAAO,EAAE,CAAC,CAAI,QAA8B,EAAgC,EAAE;YAC3E,MAAM,SAAS,GAAG,aAAa,EAAE,CAAC;YAClC,MAAM,MAAM,GAAG,QAAQ,EAAE,CAAC;YAC1B,IAAI,MAAM,YAAY,OAAO,EAAE,CAAC;gBAC7B,OAAQ,MAAqB,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,SAAS,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC;YACpG,CAAC;YACD,OAAO,EAAE,MAAM,EAAE,MAAW,EAAE,SAAS,EAAE,SAAS,CAAC,SAAS,EAAE,CAAC;QAClE,CAAC,CAAqB;QACtB,OAAO,CAAC,EAAU;YACf,MAAM,MAAM,GAAG,OAAO,GAAG,EAAE,CAAC;YAC5B,sEAAsE;YACtE,gEAAgE;YAChE,SAAS,CAAC;gBACP,MAAM,IAAI,GAAG,MAAM;qBACf,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,QAAQ,IAAI,CAAC,KAAK,CAAC,KAAK,IAAI,KAAK,CAAC,EAAE,IAAI,MAAM,CAAC;qBACtE,IAAI,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,IAAI,CAAC,EAAE,GAAG,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;gBACjD,IAAI,CAAC,IAAI,EAAE,CAAC;oBACT,MAAM;gBACT,CAAC;gBACD,OAAO,GAAG,IAAI,CAAC,EAAE,CAAC;gBAClB,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;gBAClB,IAAI,CAAC,QAAQ,EAAE,CAAC;YACnB,CAAC;YACD,OAAO,GAAG,MAAM,CAAC;QACpB,CAAC;KACH,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/********************************************************************************
|
|
2
|
+
* Copyright (c) 2026 CrossBreeze, EclipseSource and others.
|
|
3
|
+
*
|
|
4
|
+
* This program and the accompanying materials are made available under the
|
|
5
|
+
* terms of the MIT License which is available in the project root.
|
|
6
|
+
*
|
|
7
|
+
* SPDX-License-Identifier: MIT
|
|
8
|
+
********************************************************************************/
|
|
9
|
+
/**
|
|
10
|
+
* The uniform contract every framework test harness satisfies. A harness is
|
|
11
|
+
* a wired bundle around a system-under-test, driven through a seam; its full
|
|
12
|
+
* shape is `{ <subject>, <seam>, …captureArrays, dispose() }`. This marker
|
|
13
|
+
* pins the one member that is identical across every harness — `dispose()` —
|
|
14
|
+
* so teardown is always `harness.dispose()` regardless of which harness, and
|
|
15
|
+
* a `Harness` reference can release any of them without knowing its concrete
|
|
16
|
+
* type. Each concrete harness interface — per head, and per conformance driver
|
|
17
|
+
* port — `extends Harness` and adds its subject / seam / capture members on
|
|
18
|
+
* top.
|
|
19
|
+
*/
|
|
20
|
+
export interface Harness {
|
|
21
|
+
/** Release every resource the harness holds. Idempotent; the uniform teardown hook. */
|
|
22
|
+
dispose(): void;
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=harness.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"harness.d.ts","sourceRoot":"","sources":["../../src/testing/harness.ts"],"names":[],"mappings":"AAAA;;;;;;;kFAOkF;AAElF;;;;;;;;;;GAUG;AACH,MAAM,WAAW,OAAO;IACrB,uFAAuF;IACvF,OAAO,IAAI,IAAI,CAAC;CAClB"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/********************************************************************************
|
|
3
|
+
* Copyright (c) 2026 CrossBreeze, EclipseSource and others.
|
|
4
|
+
*
|
|
5
|
+
* This program and the accompanying materials are made available under the
|
|
6
|
+
* terms of the MIT License which is available in the project root.
|
|
7
|
+
*
|
|
8
|
+
* SPDX-License-Identifier: MIT
|
|
9
|
+
********************************************************************************/
|
|
10
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
|
+
//# sourceMappingURL=harness.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"harness.js","sourceRoot":"","sources":["../../src/testing/harness.ts"],"names":[],"mappings":";AAAA;;;;;;;kFAOkF"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/********************************************************************************
|
|
2
|
+
* Copyright (c) 2026 CrossBreeze, EclipseSource and others.
|
|
3
|
+
*
|
|
4
|
+
* This program and the accompanying materials are made available under the
|
|
5
|
+
* terms of the MIT License which is available in the project root.
|
|
6
|
+
*
|
|
7
|
+
* SPDX-License-Identifier: MIT
|
|
8
|
+
********************************************************************************/
|
|
9
|
+
export * from './data-doubles';
|
|
10
|
+
export * from './fake-clock';
|
|
11
|
+
export * from './harness';
|
|
12
|
+
export * from './wait-for';
|
|
13
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/testing/index.ts"],"names":[],"mappings":"AAAA;;;;;;;kFAOkF;AAelF,cAAc,gBAAgB,CAAC;AAC/B,cAAc,cAAc,CAAC;AAC7B,cAAc,WAAW,CAAC;AAC1B,cAAc,YAAY,CAAC"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/********************************************************************************
|
|
3
|
+
* Copyright (c) 2026 CrossBreeze, EclipseSource and others.
|
|
4
|
+
*
|
|
5
|
+
* This program and the accompanying materials are made available under the
|
|
6
|
+
* terms of the MIT License which is available in the project root.
|
|
7
|
+
*
|
|
8
|
+
* SPDX-License-Identifier: MIT
|
|
9
|
+
********************************************************************************/
|
|
10
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
11
|
+
if (k2 === undefined) k2 = k;
|
|
12
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
13
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
14
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
15
|
+
}
|
|
16
|
+
Object.defineProperty(o, k2, desc);
|
|
17
|
+
}) : (function(o, m, k, k2) {
|
|
18
|
+
if (k2 === undefined) k2 = k;
|
|
19
|
+
o[k2] = m[k];
|
|
20
|
+
}));
|
|
21
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
22
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
23
|
+
};
|
|
24
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
25
|
+
// Subpath barrel for `@hydranium/protocol/testing` — the BROWSER-NEUTRAL shared
|
|
26
|
+
// primitives: `makeFakeClock` (deterministic `Clock` double on one virtual time
|
|
27
|
+
// axis), `waitFor` / `tick`, the client-side data-head doubles
|
|
28
|
+
// (`makeFakeDataPort` / `makeCapturingDataClient`), and the `Harness` marker
|
|
29
|
+
// interface every framework harness extends. Kept out of the main barrel so production bundles don't pull
|
|
30
|
+
// the test scaffolding in by default; adopters opt in by importing from
|
|
31
|
+
// `@hydranium/protocol/testing`.
|
|
32
|
+
//
|
|
33
|
+
// Neutrality is gated (`scripts/check-neutral-bundles.mjs`), which is why the
|
|
34
|
+
// duplex transports are NOT here: a `PassThrough` pair is in their exported
|
|
35
|
+
// type, so they cannot be made portable and live at `./testing/node` instead.
|
|
36
|
+
// The same rule the package surface uses — the portable name is the short one.
|
|
37
|
+
__exportStar(require("./data-doubles"), exports);
|
|
38
|
+
__exportStar(require("./fake-clock"), exports);
|
|
39
|
+
__exportStar(require("./harness"), exports);
|
|
40
|
+
__exportStar(require("./wait-for"), exports);
|
|
41
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/testing/index.ts"],"names":[],"mappings":";AAAA;;;;;;;kFAOkF;;;;;;;;;;;;;;;;AAElF,gFAAgF;AAChF,gFAAgF;AAChF,+DAA+D;AAC/D,6EAA6E;AAC7E,0GAA0G;AAC1G,wEAAwE;AACxE,iCAAiC;AACjC,EAAE;AACF,8EAA8E;AAC9E,4EAA4E;AAC5E,8EAA8E;AAC9E,+EAA+E;AAE/E,iDAA+B;AAC/B,+CAA6B;AAC7B,4CAA0B;AAC1B,6CAA2B"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/********************************************************************************
|
|
2
|
+
* Copyright (c) 2026 CrossBreeze, EclipseSource and others.
|
|
3
|
+
*
|
|
4
|
+
* This program and the accompanying materials are made available under the
|
|
5
|
+
* terms of the MIT License which is available in the project root.
|
|
6
|
+
*
|
|
7
|
+
* SPDX-License-Identifier: MIT
|
|
8
|
+
********************************************************************************/
|
|
9
|
+
import { type MessageConnection } from 'vscode-jsonrpc/node';
|
|
10
|
+
/**
|
|
11
|
+
* Bidirectional in-process vscode-jsonrpc bridge — two MessageConnections
|
|
12
|
+
* crossed over a PassThrough pair, both already listening. The framework's
|
|
13
|
+
* standard in-process test transport.
|
|
14
|
+
*
|
|
15
|
+
* Typical use: wire a `DataServer` to `pair.left` and exercise it from a
|
|
16
|
+
* client proxy on `pair.right` (or vice versa). Call `dispose` at test
|
|
17
|
+
* teardown to release the underlying streams.
|
|
18
|
+
*/
|
|
19
|
+
export interface DuplexConnectionPair {
|
|
20
|
+
readonly left: MessageConnection;
|
|
21
|
+
readonly right: MessageConnection;
|
|
22
|
+
dispose(): void;
|
|
23
|
+
}
|
|
24
|
+
export declare function makeDuplexConnectionPair(): DuplexConnectionPair;
|
|
25
|
+
//# sourceMappingURL=duplex-connection.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"duplex-connection.d.ts","sourceRoot":"","sources":["../../../src/testing/node/duplex-connection.ts"],"names":[],"mappings":"AAAA;;;;;;;kFAOkF;AAElF,OAAO,EAAqE,KAAK,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAGhI;;;;;;;;GAQG;AACH,MAAM,WAAW,oBAAoB;IAClC,QAAQ,CAAC,IAAI,EAAE,iBAAiB,CAAC;IACjC,QAAQ,CAAC,KAAK,EAAE,iBAAiB,CAAC;IAClC,OAAO,IAAI,IAAI,CAAC;CAClB;AAED,wBAAgB,wBAAwB,IAAI,oBAAoB,CAsB/D"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/********************************************************************************
|
|
3
|
+
* Copyright (c) 2026 CrossBreeze, EclipseSource and others.
|
|
4
|
+
*
|
|
5
|
+
* This program and the accompanying materials are made available under the
|
|
6
|
+
* terms of the MIT License which is available in the project root.
|
|
7
|
+
*
|
|
8
|
+
* SPDX-License-Identifier: MIT
|
|
9
|
+
********************************************************************************/
|
|
10
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
|
+
exports.makeDuplexConnectionPair = makeDuplexConnectionPair;
|
|
12
|
+
const node_1 = require("vscode-jsonrpc/node");
|
|
13
|
+
const duplex_stream_1 = require("./duplex-stream");
|
|
14
|
+
function makeDuplexConnectionPair() {
|
|
15
|
+
// `left` is the client side, `right` the server side: `clientToServer` is
|
|
16
|
+
// what `left` writes and `right` reads; `serverToClient` is what `right`
|
|
17
|
+
// writes and `left` reads.
|
|
18
|
+
const pair = (0, duplex_stream_1.makeDuplexStreamPair)();
|
|
19
|
+
const { clientToServer, serverToClient } = pair;
|
|
20
|
+
const left = (0, node_1.createMessageConnection)(new node_1.StreamMessageReader(serverToClient), new node_1.StreamMessageWriter(clientToServer));
|
|
21
|
+
const right = (0, node_1.createMessageConnection)(new node_1.StreamMessageReader(clientToServer), new node_1.StreamMessageWriter(serverToClient));
|
|
22
|
+
left.listen();
|
|
23
|
+
right.listen();
|
|
24
|
+
return {
|
|
25
|
+
left,
|
|
26
|
+
right,
|
|
27
|
+
dispose() {
|
|
28
|
+
left.dispose();
|
|
29
|
+
right.dispose();
|
|
30
|
+
pair.dispose();
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=duplex-connection.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"duplex-connection.js","sourceRoot":"","sources":["../../../src/testing/node/duplex-connection.ts"],"names":[],"mappings":";AAAA;;;;;;;kFAOkF;;AAoBlF,4DAsBC;AAxCD,8CAAgI;AAChI,mDAAuD;AAiBvD,SAAgB,wBAAwB;IACrC,0EAA0E;IAC1E,yEAAyE;IACzE,2BAA2B;IAC3B,MAAM,IAAI,GAAG,IAAA,oCAAoB,GAAE,CAAC;IACpC,MAAM,EAAE,cAAc,EAAE,cAAc,EAAE,GAAG,IAAI,CAAC;IAEhD,MAAM,IAAI,GAAG,IAAA,8BAAuB,EAAC,IAAI,0BAAmB,CAAC,cAAc,CAAC,EAAE,IAAI,0BAAmB,CAAC,cAAc,CAAC,CAAC,CAAC;IACvH,MAAM,KAAK,GAAG,IAAA,8BAAuB,EAAC,IAAI,0BAAmB,CAAC,cAAc,CAAC,EAAE,IAAI,0BAAmB,CAAC,cAAc,CAAC,CAAC,CAAC;IAExH,IAAI,CAAC,MAAM,EAAE,CAAC;IACd,KAAK,CAAC,MAAM,EAAE,CAAC;IAEf,OAAO;QACJ,IAAI;QACJ,KAAK;QACL,OAAO;YACJ,IAAI,CAAC,OAAO,EAAE,CAAC;YACf,KAAK,CAAC,OAAO,EAAE,CAAC;YAChB,IAAI,CAAC,OAAO,EAAE,CAAC;QAClB,CAAC;KACH,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/********************************************************************************
|
|
2
|
+
* Copyright (c) 2026 CrossBreeze, EclipseSource and others.
|
|
3
|
+
*
|
|
4
|
+
* This program and the accompanying materials are made available under the
|
|
5
|
+
* terms of the MIT License which is available in the project root.
|
|
6
|
+
*
|
|
7
|
+
* SPDX-License-Identifier: MIT
|
|
8
|
+
********************************************************************************/
|
|
9
|
+
import { PassThrough } from 'node:stream';
|
|
10
|
+
/**
|
|
11
|
+
* A crossed pair of in-process `PassThrough` streams modelling one
|
|
12
|
+
* bidirectional client/server transport. Each `PassThrough` is itself both
|
|
13
|
+
* readable and writable: the side named first writes, the side named second
|
|
14
|
+
* reads off the same object. The shared substrate under the framework's
|
|
15
|
+
* in-process test transports — `makeDuplexConnectionPair` layers a
|
|
16
|
+
* `MessageConnection` pair on top.
|
|
17
|
+
*/
|
|
18
|
+
export interface DuplexStreamPair {
|
|
19
|
+
/** Client writes here; server reads here. */
|
|
20
|
+
readonly clientToServer: PassThrough;
|
|
21
|
+
/** Server writes here; client reads here. */
|
|
22
|
+
readonly serverToClient: PassThrough;
|
|
23
|
+
/** Destroy both streams. Idempotent. */
|
|
24
|
+
dispose(): void;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Build a fresh {@link DuplexStreamPair}. The two streams are independent;
|
|
28
|
+
* data written to one never appears on the other. Call `dispose` at test
|
|
29
|
+
* teardown to release them.
|
|
30
|
+
*/
|
|
31
|
+
export declare function makeDuplexStreamPair(): DuplexStreamPair;
|
|
32
|
+
//# sourceMappingURL=duplex-stream.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"duplex-stream.d.ts","sourceRoot":"","sources":["../../../src/testing/node/duplex-stream.ts"],"names":[],"mappings":"AAAA;;;;;;;kFAOkF;AAElF,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE1C;;;;;;;GAOG;AACH,MAAM,WAAW,gBAAgB;IAC9B,6CAA6C;IAC7C,QAAQ,CAAC,cAAc,EAAE,WAAW,CAAC;IACrC,6CAA6C;IAC7C,QAAQ,CAAC,cAAc,EAAE,WAAW,CAAC;IACrC,wCAAwC;IACxC,OAAO,IAAI,IAAI,CAAC;CAClB;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,IAAI,gBAAgB,CAiBvD"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/********************************************************************************
|
|
3
|
+
* Copyright (c) 2026 CrossBreeze, EclipseSource and others.
|
|
4
|
+
*
|
|
5
|
+
* This program and the accompanying materials are made available under the
|
|
6
|
+
* terms of the MIT License which is available in the project root.
|
|
7
|
+
*
|
|
8
|
+
* SPDX-License-Identifier: MIT
|
|
9
|
+
********************************************************************************/
|
|
10
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
|
+
exports.makeDuplexStreamPair = makeDuplexStreamPair;
|
|
12
|
+
const node_stream_1 = require("node:stream");
|
|
13
|
+
/**
|
|
14
|
+
* Build a fresh {@link DuplexStreamPair}. The two streams are independent;
|
|
15
|
+
* data written to one never appears on the other. Call `dispose` at test
|
|
16
|
+
* teardown to release them.
|
|
17
|
+
*/
|
|
18
|
+
function makeDuplexStreamPair() {
|
|
19
|
+
const clientToServer = new node_stream_1.PassThrough();
|
|
20
|
+
const serverToClient = new node_stream_1.PassThrough();
|
|
21
|
+
let disposed = false;
|
|
22
|
+
return {
|
|
23
|
+
clientToServer,
|
|
24
|
+
serverToClient,
|
|
25
|
+
dispose() {
|
|
26
|
+
if (disposed) {
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
disposed = true;
|
|
30
|
+
clientToServer.destroy();
|
|
31
|
+
serverToClient.destroy();
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=duplex-stream.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"duplex-stream.js","sourceRoot":"","sources":["../../../src/testing/node/duplex-stream.ts"],"names":[],"mappings":";AAAA;;;;;;;kFAOkF;;AA0BlF,oDAiBC;AAzCD,6CAA0C;AAmB1C;;;;GAIG;AACH,SAAgB,oBAAoB;IACjC,MAAM,cAAc,GAAG,IAAI,yBAAW,EAAE,CAAC;IACzC,MAAM,cAAc,GAAG,IAAI,yBAAW,EAAE,CAAC;IAEzC,IAAI,QAAQ,GAAG,KAAK,CAAC;IACrB,OAAO;QACJ,cAAc;QACd,cAAc;QACd,OAAO;YACJ,IAAI,QAAQ,EAAE,CAAC;gBACZ,OAAO;YACV,CAAC;YACD,QAAQ,GAAG,IAAI,CAAC;YAChB,cAAc,CAAC,OAAO,EAAE,CAAC;YACzB,cAAc,CAAC,OAAO,EAAE,CAAC;QAC5B,CAAC;KACH,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/********************************************************************************
|
|
2
|
+
* Copyright (c) 2026 CrossBreeze, EclipseSource and others.
|
|
3
|
+
*
|
|
4
|
+
* This program and the accompanying materials are made available under the
|
|
5
|
+
* terms of the MIT License which is available in the project root.
|
|
6
|
+
*
|
|
7
|
+
* SPDX-License-Identifier: MIT
|
|
8
|
+
********************************************************************************/
|
|
9
|
+
export * from './duplex-connection';
|
|
10
|
+
export * from './duplex-stream';
|
|
11
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/testing/node/index.ts"],"names":[],"mappings":"AAAA;;;;;;;kFAOkF;AAalF,cAAc,qBAAqB,CAAC;AACpC,cAAc,iBAAiB,CAAC"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/********************************************************************************
|
|
3
|
+
* Copyright (c) 2026 CrossBreeze, EclipseSource and others.
|
|
4
|
+
*
|
|
5
|
+
* This program and the accompanying materials are made available under the
|
|
6
|
+
* terms of the MIT License which is available in the project root.
|
|
7
|
+
*
|
|
8
|
+
* SPDX-License-Identifier: MIT
|
|
9
|
+
********************************************************************************/
|
|
10
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
11
|
+
if (k2 === undefined) k2 = k;
|
|
12
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
13
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
14
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
15
|
+
}
|
|
16
|
+
Object.defineProperty(o, k2, desc);
|
|
17
|
+
}) : (function(o, m, k, k2) {
|
|
18
|
+
if (k2 === undefined) k2 = k;
|
|
19
|
+
o[k2] = m[k];
|
|
20
|
+
}));
|
|
21
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
22
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
23
|
+
};
|
|
24
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
25
|
+
// Subpath barrel for `@hydranium/protocol/testing/node` — the test transports
|
|
26
|
+
// that need a Node runtime: a crossed `PassThrough` pair and the in-process
|
|
27
|
+
// `MessageConnection` bridge over it.
|
|
28
|
+
//
|
|
29
|
+
// Separate from `./testing` because a `PassThrough` is in `DuplexStreamPair`'s
|
|
30
|
+
// exported type and `StreamMessageReader` comes from `vscode-jsonrpc/node`, so
|
|
31
|
+
// neither can be made portable — and keeping them in the neutral barrel taints
|
|
32
|
+
// every subpath that re-exports it, which is what made three of this repo's
|
|
33
|
+
// `./testing` entries unbundleable for a browser while having no Node code of
|
|
34
|
+
// their own.
|
|
35
|
+
__exportStar(require("./duplex-connection"), exports);
|
|
36
|
+
__exportStar(require("./duplex-stream"), exports);
|
|
37
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/testing/node/index.ts"],"names":[],"mappings":";AAAA;;;;;;;kFAOkF;;;;;;;;;;;;;;;;AAElF,8EAA8E;AAC9E,4EAA4E;AAC5E,sCAAsC;AACtC,EAAE;AACF,+EAA+E;AAC/E,+EAA+E;AAC/E,+EAA+E;AAC/E,4EAA4E;AAC5E,8EAA8E;AAC9E,aAAa;AAEb,sDAAoC;AACpC,kDAAgC"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/********************************************************************************
|
|
2
|
+
* Copyright (c) 2026 CrossBreeze, EclipseSource and others.
|
|
3
|
+
*
|
|
4
|
+
* This program and the accompanying materials are made available under the
|
|
5
|
+
* terms of the MIT License which is available in the project root.
|
|
6
|
+
*
|
|
7
|
+
* SPDX-License-Identifier: MIT
|
|
8
|
+
********************************************************************************/
|
|
9
|
+
/**
|
|
10
|
+
* Two test primitives for awaiting in-process asynchrony (RPC notifications
|
|
11
|
+
* crossing the duplex wire, `DocumentBuilder` phase events, etc.) WITHOUT a
|
|
12
|
+
* flaky fixed sleep.
|
|
13
|
+
*
|
|
14
|
+
* Decision rule:
|
|
15
|
+
* - Asserting an effect **will** happen ("eventually N events / a build ran /
|
|
16
|
+
* the doc reached a phase")? → {@link waitFor} with a predicate over the
|
|
17
|
+
* observable. Non-racy: resolves the instant it is true, tolerates a slow CI.
|
|
18
|
+
* - Asserting an effect **did not / has not yet** happened ("no event for an
|
|
19
|
+
* unsubscribed URI", "the gated call has not resolved")? → {@link tick}: a
|
|
20
|
+
* negative cannot be polled, so yield the loop a bounded moment to give the
|
|
21
|
+
* (unwanted) effect a chance, then assert its absence.
|
|
22
|
+
*
|
|
23
|
+
* Default to `waitFor`; reach for `tick` only when the assertion is an absence.
|
|
24
|
+
* A microtask flush (`await Promise.resolve()` / `queue-microtask`) is never the
|
|
25
|
+
* answer here — stream-delivered JSON-RPC notifications arrive on a macrotask/IO
|
|
26
|
+
* turn, after microtasks drain.
|
|
27
|
+
*/
|
|
28
|
+
/** Options for {@link waitFor}. */
|
|
29
|
+
export interface WaitForOptions {
|
|
30
|
+
/** Reject after this many milliseconds if the predicate is still false. Default 2000. */
|
|
31
|
+
readonly timeoutMs?: number;
|
|
32
|
+
/** Poll the predicate every this-many milliseconds. Default 5. */
|
|
33
|
+
readonly intervalMs?: number;
|
|
34
|
+
/** Error message on timeout. Default a generic phrasing. */
|
|
35
|
+
readonly message?: string;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Resolve once `predicate()` returns true, polling at `intervalMs`; reject with
|
|
39
|
+
* `message` once `timeoutMs` elapses. The **non-racy** alternative to a fixed
|
|
40
|
+
* sleep for awaiting an asynchronous side effect that lands on an observable
|
|
41
|
+
* value.
|
|
42
|
+
*
|
|
43
|
+
* It resolves the instant the condition holds, so it is *faster* than a fixed
|
|
44
|
+
* delay on the happy path, and tolerates a slow event loop up to `timeoutMs`, so
|
|
45
|
+
* it does not flake under parallel CI where a fixed `setTimeout` can be starved
|
|
46
|
+
* past the test timeout.
|
|
47
|
+
*
|
|
48
|
+
* @example
|
|
49
|
+
* await proxy.updateModelDocument({ uri, clientId, model });
|
|
50
|
+
* await waitFor(() => harness.events.length === 1); // the notification crossed
|
|
51
|
+
* expect(harness.events[0].document.uri).toBe(uri);
|
|
52
|
+
*/
|
|
53
|
+
export declare function waitFor(predicate: () => boolean, options?: WaitForOptions): Promise<void>;
|
|
54
|
+
/**
|
|
55
|
+
* Yield the event loop for `ms` (default 10). The bounded counterpart to
|
|
56
|
+
* {@link waitFor}, for the rare assertion that something has NOT happened — a
|
|
57
|
+
* *negative* you cannot poll positively. Give async delivery a real chance to
|
|
58
|
+
* (wrongly) occur, then assert it did not.
|
|
59
|
+
*
|
|
60
|
+
* A fixed yield is unavoidable here, but the failure mode is a false-green, not
|
|
61
|
+
* the flaky-red a fixed delay causes on a positive wait.
|
|
62
|
+
*
|
|
63
|
+
* @example
|
|
64
|
+
* await proxy.saveModelDocument({ uri, clientId, model }); // no subscriber yet
|
|
65
|
+
* await tick(); // give a (wrongly) fired event a chance to land
|
|
66
|
+
* expect(savedEvents).toHaveLength(0); // assert the ABSENCE
|
|
67
|
+
*/
|
|
68
|
+
export declare function tick(ms?: number): Promise<void>;
|
|
69
|
+
//# sourceMappingURL=wait-for.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wait-for.d.ts","sourceRoot":"","sources":["../../src/testing/wait-for.ts"],"names":[],"mappings":"AAAA;;;;;;;kFAOkF;AAElF;;;;;;;;;;;;;;;;;;GAkBG;AAEH,mCAAmC;AACnC,MAAM,WAAW,cAAc;IAC5B,yFAAyF;IACzF,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,kEAAkE;IAClE,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,4DAA4D;IAC5D,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,OAAO,CAAC,SAAS,EAAE,MAAM,OAAO,EAAE,OAAO,GAAE,cAAmB,GAAG,OAAO,CAAC,IAAI,CAAC,CAoB7F;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,IAAI,CAAC,EAAE,SAAK,GAAG,OAAO,CAAC,IAAI,CAAC,CAE3C"}
|