react-native-web-serial-api 0.1.0 → 0.2.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 +188 -117
- package/TESTING.md +417 -176
- package/android/build.gradle +14 -0
- package/android/src/main/java/dev/webserialapi/NativeUsbSerialModule.java +74 -11
- package/android/src/main/java/dev/webserialapi/PortPickerActivity.java +61 -59
- package/bin/expose-serial.js +205 -0
- package/lib/commonjs/UsbSerial.js +1 -1
- package/lib/commonjs/WebSerial.js +110 -26
- package/lib/commonjs/WebSerial.js.map +1 -1
- package/lib/commonjs/index.js +2 -2
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/lib/event-target.js +3 -1
- package/lib/commonjs/lib/event-target.js.map +1 -1
- package/lib/commonjs/lib/web-streams.js +42 -0
- package/lib/commonjs/lib/web-streams.js.map +1 -0
- package/lib/commonjs/testing/device-fixture.js +70 -0
- package/lib/commonjs/testing/device-fixture.js.map +1 -0
- package/lib/commonjs/testing/expose.js +91 -0
- package/lib/commonjs/testing/expose.js.map +1 -0
- package/lib/commonjs/testing/harness.js +98 -0
- package/lib/commonjs/testing/harness.js.map +1 -0
- package/lib/commonjs/testing/{virtual-serial.js → in-memory-serial-transport.js} +66 -28
- package/lib/commonjs/testing/in-memory-serial-transport.js.map +1 -0
- package/lib/commonjs/testing/index.js +100 -17
- package/lib/commonjs/testing/index.js.map +1 -1
- package/lib/commonjs/testing/install-in-memory-serial-transport.js +54 -0
- package/lib/commonjs/testing/install-in-memory-serial-transport.js.map +1 -0
- package/lib/commonjs/testing/serial-client.js +277 -0
- package/lib/commonjs/testing/serial-client.js.map +1 -0
- package/lib/commonjs/testing/{serial-device.js → simulated-device.js} +17 -17
- package/lib/commonjs/testing/simulated-device.js.map +1 -0
- package/lib/commonjs/testing/test-suite.js +142 -0
- package/lib/commonjs/testing/test-suite.js.map +1 -0
- package/lib/commonjs/transport.js +3 -3
- package/lib/commonjs/websocket/WebSocketSerialTransport.js +659 -0
- package/lib/commonjs/websocket/WebSocketSerialTransport.js.map +1 -0
- package/lib/commonjs/websocket/bridge.js +234 -0
- package/lib/commonjs/websocket/bridge.js.map +1 -0
- package/lib/commonjs/websocket/index.js +33 -0
- package/lib/commonjs/websocket/index.js.map +1 -0
- package/lib/commonjs/websocket/protocol.js +55 -0
- package/lib/commonjs/websocket/protocol.js.map +1 -0
- package/lib/commonjs/websocket/serial-device-bridge.js +130 -0
- package/lib/commonjs/websocket/serial-device-bridge.js.map +1 -0
- package/lib/typescript/src/UsbSerial.d.ts +1 -1
- package/lib/typescript/src/WebSerial.d.ts +7 -7
- package/lib/typescript/src/WebSerial.d.ts.map +1 -1
- package/lib/typescript/src/index.d.ts +1 -1
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/lib/typescript/src/lib/event-target.d.ts +2 -0
- package/lib/typescript/src/lib/event-target.d.ts.map +1 -1
- package/lib/typescript/src/lib/web-streams.d.ts +9 -0
- package/lib/typescript/src/lib/web-streams.d.ts.map +1 -0
- package/lib/typescript/src/testing/device-fixture.d.ts +70 -0
- package/lib/typescript/src/testing/device-fixture.d.ts.map +1 -0
- package/lib/typescript/src/testing/expose.d.ts +71 -0
- package/lib/typescript/src/testing/expose.d.ts.map +1 -0
- package/lib/typescript/src/testing/harness.d.ts +34 -0
- package/lib/typescript/src/testing/harness.d.ts.map +1 -0
- package/lib/typescript/src/testing/{virtual-serial.d.ts → in-memory-serial-transport.d.ts} +37 -26
- package/lib/typescript/src/testing/in-memory-serial-transport.d.ts.map +1 -0
- package/lib/typescript/src/testing/index.d.ts +18 -8
- package/lib/typescript/src/testing/index.d.ts.map +1 -1
- package/lib/typescript/src/testing/install-in-memory-serial-transport.d.ts +25 -0
- package/lib/typescript/src/testing/install-in-memory-serial-transport.d.ts.map +1 -0
- package/lib/typescript/src/testing/serial-client.d.ts +62 -0
- package/lib/typescript/src/testing/serial-client.d.ts.map +1 -0
- package/lib/typescript/src/testing/{serial-device.d.ts → simulated-device.d.ts} +23 -23
- package/lib/typescript/src/testing/simulated-device.d.ts.map +1 -0
- package/lib/typescript/src/testing/test-suite.d.ts +75 -0
- package/lib/typescript/src/testing/test-suite.d.ts.map +1 -0
- package/lib/typescript/src/transport.d.ts +3 -3
- package/lib/typescript/src/websocket/WebSocketSerialTransport.d.ts +111 -0
- package/lib/typescript/src/websocket/WebSocketSerialTransport.d.ts.map +1 -0
- package/lib/typescript/src/websocket/bridge.d.ts +66 -0
- package/lib/typescript/src/websocket/bridge.d.ts.map +1 -0
- package/lib/typescript/src/websocket/index.d.ts +19 -0
- package/lib/typescript/src/websocket/index.d.ts.map +1 -0
- package/lib/typescript/src/websocket/protocol.d.ts +64 -0
- package/lib/typescript/src/websocket/protocol.d.ts.map +1 -0
- package/lib/typescript/src/websocket/serial-device-bridge.d.ts +32 -0
- package/lib/typescript/src/websocket/serial-device-bridge.d.ts.map +1 -0
- package/package.json +21 -3
- package/src/UsbSerial.ts +1 -1
- package/src/WebSerial.ts +134 -35
- package/src/index.ts +4 -1
- package/src/lib/event-target.ts +12 -0
- package/src/lib/web-streams.ts +43 -0
- package/src/testing/device-fixture.ts +150 -0
- package/src/testing/expose.ts +147 -0
- package/src/testing/harness.ts +124 -0
- package/src/testing/{virtual-serial.ts → in-memory-serial-transport.ts} +95 -56
- package/src/testing/index.ts +69 -21
- package/src/testing/install-in-memory-serial-transport.ts +65 -0
- package/src/testing/serial-client.ts +313 -0
- package/src/testing/{serial-device.ts → simulated-device.ts} +23 -23
- package/src/testing/test-suite.ts +186 -0
- package/src/transport.ts +3 -3
- package/src/websocket/WebSocketSerialTransport.ts +796 -0
- package/src/websocket/bridge.ts +299 -0
- package/src/websocket/index.ts +38 -0
- package/src/websocket/protocol.ts +101 -0
- package/src/websocket/serial-device-bridge.ts +160 -0
- package/lib/commonjs/testing/install.js +0 -54
- package/lib/commonjs/testing/install.js.map +0 -1
- package/lib/commonjs/testing/serial-device.js.map +0 -1
- package/lib/commonjs/testing/virtual-serial.js.map +0 -1
- package/lib/typescript/src/testing/install.d.ts +0 -25
- package/lib/typescript/src/testing/install.d.ts.map +0 -1
- package/lib/typescript/src/testing/serial-device.d.ts.map +0 -1
- package/lib/typescript/src/testing/virtual-serial.d.ts.map +0 -1
- package/src/testing/install.ts +0 -65
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.installInMemorySerialTransport = installInMemorySerialTransport;
|
|
7
|
+
var _UsbSerial = require("../UsbSerial");
|
|
8
|
+
var _inMemorySerialTransport = require("./in-memory-serial-transport");
|
|
9
|
+
var _simulatedDevice = require("./simulated-device");
|
|
10
|
+
/**
|
|
11
|
+
* installInMemorySerialTransport — point the library at a simulated device set in one call.
|
|
12
|
+
*
|
|
13
|
+
* Built for E2E: call it once at app startup, behind your own env/build flag, to
|
|
14
|
+
* make `navigator.serial` / this library's `serial` talk to simulated
|
|
15
|
+
* {@link SimulatedDevice}s instead of real USB hardware while a test driver
|
|
16
|
+
* (Maestro, Detox, …) exercises the app on a device/emulator.
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* // index.js (debug/E2E build only)
|
|
20
|
+
* import {installInMemorySerialTransport, LoopbackDevice} from 'react-native-web-serial-api/testing';
|
|
21
|
+
* installInMemorySerialTransport({
|
|
22
|
+
* enabled: process.env.RNWS_SERIAL_MOCK === '1',
|
|
23
|
+
* devices: [new LoopbackDevice(), new MyThermometer()],
|
|
24
|
+
* });
|
|
25
|
+
*/
|
|
26
|
+
|
|
27
|
+
/** A device to register: a SimulatedDevice, optionally with transport options. */
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Build an {@link InMemorySerialTransport} from `devices` and install it globally
|
|
31
|
+
* via {@link setUsbSerial}. SimulatedDevices default to granted USB permission (so
|
|
32
|
+
* they show up immediately); pass the `{device, options}` form to override.
|
|
33
|
+
* Returns the transport (handy for driving devices in-test), or `null` when
|
|
34
|
+
* disabled.
|
|
35
|
+
*/
|
|
36
|
+
function installInMemorySerialTransport(options) {
|
|
37
|
+
if (options.enabled === false) return null;
|
|
38
|
+
const transport = new _inMemorySerialTransport.InMemorySerialTransport(options.transport);
|
|
39
|
+
for (const entry of options.devices) {
|
|
40
|
+
if (entry instanceof _simulatedDevice.SimulatedDevice) {
|
|
41
|
+
transport.addDevice(entry, {
|
|
42
|
+
hasPermission: true
|
|
43
|
+
});
|
|
44
|
+
} else {
|
|
45
|
+
transport.addDevice(entry.device, {
|
|
46
|
+
hasPermission: true,
|
|
47
|
+
...entry.options
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
(0, _UsbSerial.setUsbSerial)(transport);
|
|
52
|
+
return transport;
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=install-in-memory-serial-transport.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["_UsbSerial","require","_inMemorySerialTransport","_simulatedDevice","installInMemorySerialTransport","options","enabled","transport","InMemorySerialTransport","entry","devices","SimulatedDevice","addDevice","hasPermission","device","setUsbSerial"],"sourceRoot":"../../../src","sources":["testing/install-in-memory-serial-transport.ts"],"mappings":";;;;;;AAgBA,IAAAA,UAAA,GAAAC,OAAA;AAKA,IAAAC,wBAAA,GAAAD,OAAA;AACA,IAAAE,gBAAA,GAAAF,OAAA;AAtBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AASA;;AAcA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,SAASG,8BAA8BA,CAC5CC,OAA8C,EACd;EAChC,IAAIA,OAAO,CAACC,OAAO,KAAK,KAAK,EAAE,OAAO,IAAI;EAE1C,MAAMC,SAAS,GAAG,IAAIC,gDAAuB,CAACH,OAAO,CAACE,SAAS,CAAC;EAChE,KAAK,MAAME,KAAK,IAAIJ,OAAO,CAACK,OAAO,EAAE;IACnC,IAAID,KAAK,YAAYE,gCAAe,EAAE;MACpCJ,SAAS,CAACK,SAAS,CAACH,KAAK,EAAE;QAACI,aAAa,EAAE;MAAI,CAAC,CAAC;IACnD,CAAC,MAAM;MACLN,SAAS,CAACK,SAAS,CAACH,KAAK,CAACK,MAAM,EAAE;QAChCD,aAAa,EAAE,IAAI;QACnB,GAAGJ,KAAK,CAACJ;MACX,CAAC,CAAC;IACJ;EACF;EAEA,IAAAU,uBAAY,EAACR,SAAS,CAAC;EACvB,OAAOA,SAAS;AAClB","ignoreList":[]}
|
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.SerialClient = void 0;
|
|
7
|
+
exports.createSerialClient = createSerialClient;
|
|
8
|
+
var _simulatedDevice = require("./simulated-device");
|
|
9
|
+
/**
|
|
10
|
+
* A fluent request/response client over a {@link SerialPort} — the host-side
|
|
11
|
+
* driver every serial test otherwise hand-rolls (reader + writer, a pending
|
|
12
|
+
* byte buffer, framed reads with timeouts). Works on ANY SerialPort: the
|
|
13
|
+
* in-memory {@link InMemorySerialTransport}, a real USB device, or a
|
|
14
|
+
* WebSocket-backed one — so the same test runs in Jest and on a device.
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* const {client} = await mountDeviceFixture(new MyDevice());
|
|
18
|
+
* await client.open({baudRate: 115200});
|
|
19
|
+
* await client.write('PING\n');
|
|
20
|
+
* expect(await client.readLine()).toBe('PONG');
|
|
21
|
+
* await client.close();
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
function indexOfSubsequence(haystack, needle) {
|
|
25
|
+
if (needle.length === 0) return 0;
|
|
26
|
+
outer: for (let i = 0; i + needle.length <= haystack.length; i++) {
|
|
27
|
+
for (let j = 0; j < needle.length; j++) {
|
|
28
|
+
if (haystack[i + j] !== needle[j]) continue outer;
|
|
29
|
+
}
|
|
30
|
+
return i;
|
|
31
|
+
}
|
|
32
|
+
return -1;
|
|
33
|
+
}
|
|
34
|
+
class SerialClient {
|
|
35
|
+
#port;
|
|
36
|
+
#defaultTimeout;
|
|
37
|
+
#reader = null;
|
|
38
|
+
#writer = null;
|
|
39
|
+
#open = false;
|
|
40
|
+
#done = false;
|
|
41
|
+
#closed = false;
|
|
42
|
+
/** Inbound bytes read by the pump but not yet consumed. */
|
|
43
|
+
#pending = [];
|
|
44
|
+
/** Resolvers woken whenever #pending grows or the stream ends. */
|
|
45
|
+
#waiters = [];
|
|
46
|
+
constructor(port, options = {}) {
|
|
47
|
+
this.#port = port;
|
|
48
|
+
this.#defaultTimeout = options.defaultTimeoutMs ?? 2000;
|
|
49
|
+
}
|
|
50
|
+
get port() {
|
|
51
|
+
return this.#port;
|
|
52
|
+
}
|
|
53
|
+
get isOpen() {
|
|
54
|
+
return this.#open;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/** True once the underlying stream has ended (device closed or lost). */
|
|
58
|
+
get ended() {
|
|
59
|
+
return this.#done;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/** Open the port (idempotent) and acquire reader + writer; start reading. */
|
|
63
|
+
async open(options = {
|
|
64
|
+
baudRate: 115200
|
|
65
|
+
}) {
|
|
66
|
+
if (this.#open) return this;
|
|
67
|
+
await this.#port.open(options);
|
|
68
|
+
this.#reader = this.#port.readable.getReader();
|
|
69
|
+
this.#writer = this.#port.writable.getWriter();
|
|
70
|
+
this.#open = true;
|
|
71
|
+
this.#done = false;
|
|
72
|
+
this.#closed = false;
|
|
73
|
+
void this.#pump();
|
|
74
|
+
return this;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/** Background reader: drains the stream into #pending and wakes waiters. */
|
|
78
|
+
async #pump() {
|
|
79
|
+
const reader = this.#reader;
|
|
80
|
+
/* istanbul ignore next */
|
|
81
|
+
if (!reader) return;
|
|
82
|
+
try {
|
|
83
|
+
while (!this.#closed) {
|
|
84
|
+
const {
|
|
85
|
+
done,
|
|
86
|
+
value
|
|
87
|
+
} = await reader.read();
|
|
88
|
+
if (done) break;
|
|
89
|
+
/* istanbul ignore else — InMemorySerialTransport never emits empty chunks */
|
|
90
|
+
if (value && value.length > 0) {
|
|
91
|
+
for (let i = 0; i < value.length; i++) this.#pending.push(value[i]);
|
|
92
|
+
this.#wake();
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
} catch {
|
|
96
|
+
// read errored (e.g. device lost) — surface as end-of-stream to waiters
|
|
97
|
+
} finally {
|
|
98
|
+
this.#done = true;
|
|
99
|
+
this.#wake();
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
#wake() {
|
|
103
|
+
const waiters = this.#waiters;
|
|
104
|
+
this.#waiters = [];
|
|
105
|
+
for (const w of waiters) w();
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/** Resolve on the next #pending change / stream end, or reject after `ms`. */
|
|
109
|
+
#waitForChange(ms) {
|
|
110
|
+
return new Promise((resolve, reject) => {
|
|
111
|
+
const timer = setTimeout(() => {
|
|
112
|
+
this.#waiters = this.#waiters.filter(w => w !== waiter);
|
|
113
|
+
reject(new Error('read timeout'));
|
|
114
|
+
}, ms);
|
|
115
|
+
const waiter = () => {
|
|
116
|
+
clearTimeout(timer);
|
|
117
|
+
resolve();
|
|
118
|
+
};
|
|
119
|
+
this.#waiters.push(waiter);
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Block until `ready(buffer)` returns a non-negative count of bytes to
|
|
125
|
+
* consume, then splice and return them. Rejects with `label` on timeout.
|
|
126
|
+
*/
|
|
127
|
+
async #consume(ready, timeoutMs, label) {
|
|
128
|
+
const deadline = Date.now() + timeoutMs;
|
|
129
|
+
while (true) {
|
|
130
|
+
const take = ready(this.#pending);
|
|
131
|
+
if (take !== false) {
|
|
132
|
+
return Uint8Array.from(this.#pending.splice(0, take));
|
|
133
|
+
}
|
|
134
|
+
if (this.#done) {
|
|
135
|
+
if (this.#pending.length > 0) {
|
|
136
|
+
// Return whatever is buffered rather than hang on a closed stream.
|
|
137
|
+
return Uint8Array.from(this.#pending.splice(0, this.#pending.length));
|
|
138
|
+
}
|
|
139
|
+
// The transport can surface end-of-stream before the final queued data
|
|
140
|
+
// event has been pumped into #pending. Give that last turn a chance to
|
|
141
|
+
// land before we conclude there is nothing buffered.
|
|
142
|
+
await new Promise(resolve => setTimeout(resolve, 0));
|
|
143
|
+
/* istanbul ignore next -- race-guard checks again after yielding */
|
|
144
|
+
if (this.#pending.length === 0) {
|
|
145
|
+
return Uint8Array.from([]);
|
|
146
|
+
}
|
|
147
|
+
/* istanbul ignore next -- race-guard re-enters the loop after yielding */
|
|
148
|
+
continue;
|
|
149
|
+
}
|
|
150
|
+
const remaining = deadline - Date.now();
|
|
151
|
+
if (remaining <= 0) throw new Error(label());
|
|
152
|
+
try {
|
|
153
|
+
await this.#waitForChange(remaining);
|
|
154
|
+
} catch {
|
|
155
|
+
throw new Error(label());
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/** Write bytes (string → char codes & 0xff). */
|
|
161
|
+
async write(data) {
|
|
162
|
+
if (!this.#writer) throw new Error('SerialClient is not open.');
|
|
163
|
+
await this.#writer.write(Uint8Array.from((0, _simulatedDevice.toBytes)(data)));
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/** Read exactly `n` bytes (fewer only if the stream ends first). */
|
|
167
|
+
readBytes(n, options = {}) {
|
|
168
|
+
const timeout = options.timeout ?? this.#defaultTimeout;
|
|
169
|
+
return this.#consume(buf => buf.length >= n ? n : false, timeout, () => `timed out reading ${n} bytes (got ${this.#pending.length})`);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/** Read up to and including `delimiter`; returns the slice (incl. delimiter). */
|
|
173
|
+
readUntil(delimiter, options = {}) {
|
|
174
|
+
const needle = (0, _simulatedDevice.toBytes)(delimiter);
|
|
175
|
+
const timeout = options.timeout ?? this.#defaultTimeout;
|
|
176
|
+
return this.#consume(buf => {
|
|
177
|
+
const idx = indexOfSubsequence(buf, needle);
|
|
178
|
+
return idx < 0 ? false : idx + needle.length;
|
|
179
|
+
}, timeout, () => `timed out reading until delimiter`);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/** Read one `\n`-terminated line as text (trailing CR/LF stripped). */
|
|
183
|
+
async readLine(options = {}) {
|
|
184
|
+
const bytes = await this.readUntil('\n', options);
|
|
185
|
+
let end = bytes.length;
|
|
186
|
+
if (end > 0 && bytes[end - 1] === 0x0a) end--;
|
|
187
|
+
if (end > 0 && bytes[end - 1] === 0x0d) end--;
|
|
188
|
+
return String.fromCharCode(...bytes.subarray(0, end));
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* Frame a message: `predicate(buffer)` returns the number of leading bytes the
|
|
193
|
+
* next frame occupies (consumed and returned), or `false` to wait for more.
|
|
194
|
+
*/
|
|
195
|
+
readMatching(predicate, options = {}) {
|
|
196
|
+
const timeout = options.timeout ?? this.#defaultTimeout;
|
|
197
|
+
return this.#consume(buf => predicate(Uint8Array.from(buf)), timeout, () => `timed out waiting for a frame`);
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* Resolve with the next chunk of buffered inbound bytes (one or more), or an
|
|
202
|
+
* empty array once the stream has ended. Rejects on timeout. Use this to layer
|
|
203
|
+
* your own framing/decoder (SLIP, COBS, length-prefix, …) on the byte stream;
|
|
204
|
+
* pair it with {@link ended} to stop when the device goes away.
|
|
205
|
+
*/
|
|
206
|
+
readAvailable(options = {}) {
|
|
207
|
+
const timeout = options.timeout ?? this.#defaultTimeout;
|
|
208
|
+
return this.#consume(buf => buf.length > 0 ? buf.length : false, timeout, () => `timed out waiting for data`);
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
/** Assert no inbound bytes arrive for `ms`. Rejects if any do. */
|
|
212
|
+
async expectIdle(ms) {
|
|
213
|
+
if (this.#pending.length > 0) {
|
|
214
|
+
throw new Error(`expected no inbound data but ${this.#pending.length} byte(s) were already buffered`);
|
|
215
|
+
}
|
|
216
|
+
try {
|
|
217
|
+
await this.#waitForChange(ms);
|
|
218
|
+
} catch {
|
|
219
|
+
return; // no change within the window — idle, as expected
|
|
220
|
+
}
|
|
221
|
+
if (this.#pending.length > 0) {
|
|
222
|
+
throw new Error(`expected no inbound data for ${ms}ms but received ${this.#pending.length} byte(s)`);
|
|
223
|
+
}
|
|
224
|
+
// stream ended with no data — also idle
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
/** Drop any buffered-but-unread inbound bytes. */
|
|
228
|
+
drain() {
|
|
229
|
+
this.#pending.length = 0;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
/** Release reader + writer locks and close the port. Safe to call twice. */
|
|
233
|
+
async close() {
|
|
234
|
+
if (this.#closed) return;
|
|
235
|
+
this.#closed = true;
|
|
236
|
+
this.#wake();
|
|
237
|
+
if (this.#reader) {
|
|
238
|
+
try {
|
|
239
|
+
await this.#reader.cancel();
|
|
240
|
+
} catch {
|
|
241
|
+
// ignore
|
|
242
|
+
}
|
|
243
|
+
try {
|
|
244
|
+
this.#reader.releaseLock();
|
|
245
|
+
} catch {
|
|
246
|
+
// already released
|
|
247
|
+
}
|
|
248
|
+
this.#reader = null;
|
|
249
|
+
}
|
|
250
|
+
if (this.#writer) {
|
|
251
|
+
try {
|
|
252
|
+
await this.#writer.close();
|
|
253
|
+
} catch {
|
|
254
|
+
// ignore
|
|
255
|
+
}
|
|
256
|
+
try {
|
|
257
|
+
this.#writer.releaseLock();
|
|
258
|
+
} catch {
|
|
259
|
+
// already released
|
|
260
|
+
}
|
|
261
|
+
this.#writer = null;
|
|
262
|
+
}
|
|
263
|
+
this.#open = false;
|
|
264
|
+
try {
|
|
265
|
+
await this.#port.close();
|
|
266
|
+
} catch {
|
|
267
|
+
// already closed
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
/** Create a {@link SerialClient} for any SerialPort (virtual, real, or WS). */
|
|
273
|
+
exports.SerialClient = SerialClient;
|
|
274
|
+
function createSerialClient(port, options) {
|
|
275
|
+
return new SerialClient(port, options);
|
|
276
|
+
}
|
|
277
|
+
//# sourceMappingURL=serial-client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["_simulatedDevice","require","indexOfSubsequence","haystack","needle","length","outer","i","j","SerialClient","port","defaultTimeout","reader","writer","open","done","closed","pending","waiters","constructor","options","defaultTimeoutMs","isOpen","ended","baudRate","readable","getReader","writable","getWriter","pump","#pump","value","read","push","wake","#wake","w","waitForChange","#waitForChange","ms","Promise","resolve","reject","timer","setTimeout","filter","waiter","Error","clearTimeout","consume","#consume","ready","timeoutMs","label","deadline","Date","now","take","Uint8Array","from","splice","remaining","write","data","toBytes","readBytes","n","timeout","buf","readUntil","delimiter","idx","readLine","bytes","end","String","fromCharCode","subarray","readMatching","predicate","readAvailable","expectIdle","drain","close","cancel","releaseLock","exports","createSerialClient"],"sourceRoot":"../../../src","sources":["testing/serial-client.ts"],"mappings":";;;;;;;AAeA,IAAAA,gBAAA,GAAAC,OAAA;AAfA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAcA,SAASC,kBAAkBA,CAACC,QAAkB,EAAEC,MAAgB,EAAU;EACxE,IAAIA,MAAM,CAACC,MAAM,KAAK,CAAC,EAAE,OAAO,CAAC;EACjCC,KAAK,EAAE,KAAK,IAAIC,CAAC,GAAG,CAAC,EAAEA,CAAC,GAAGH,MAAM,CAACC,MAAM,IAAIF,QAAQ,CAACE,MAAM,EAAEE,CAAC,EAAE,EAAE;IAChE,KAAK,IAAIC,CAAC,GAAG,CAAC,EAAEA,CAAC,GAAGJ,MAAM,CAACC,MAAM,EAAEG,CAAC,EAAE,EAAE;MACtC,IAAIL,QAAQ,CAACI,CAAC,GAAGC,CAAC,CAAC,KAAKJ,MAAM,CAACI,CAAC,CAAC,EAAE,SAASF,KAAK;IACnD;IACA,OAAOC,CAAC;EACV;EACA,OAAO,CAAC,CAAC;AACX;AAEO,MAAME,YAAY,CAAC;EACf,CAACC,IAAI;EACL,CAACC,cAAc;EAExB,CAACC,MAAM,GAAmD,IAAI;EAC9D,CAACC,MAAM,GAAmD,IAAI;EAC9D,CAACC,IAAI,GAAG,KAAK;EACb,CAACC,IAAI,GAAG,KAAK;EACb,CAACC,MAAM,GAAG,KAAK;EACf;EACS,CAACC,OAAO,GAAa,EAAE;EAChC;EACA,CAACC,OAAO,GAAsB,EAAE;EAEhCC,WAAWA,CAACT,IAAgB,EAAEU,OAA4B,GAAG,CAAC,CAAC,EAAE;IAC/D,IAAI,CAAC,CAACV,IAAI,GAAGA,IAAI;IACjB,IAAI,CAAC,CAACC,cAAc,GAAGS,OAAO,CAACC,gBAAgB,IAAI,IAAI;EACzD;EAEA,IAAIX,IAAIA,CAAA,EAAe;IACrB,OAAO,IAAI,CAAC,CAACA,IAAI;EACnB;EAEA,IAAIY,MAAMA,CAAA,EAAY;IACpB,OAAO,IAAI,CAAC,CAACR,IAAI;EACnB;;EAEA;EACA,IAAIS,KAAKA,CAAA,EAAY;IACnB,OAAO,IAAI,CAAC,CAACR,IAAI;EACnB;;EAEA;EACA,MAAMD,IAAIA,CAACM,OAAsB,GAAG;IAACI,QAAQ,EAAE;EAAM,CAAC,EAAiB;IACrE,IAAI,IAAI,CAAC,CAACV,IAAI,EAAE,OAAO,IAAI;IAC3B,MAAM,IAAI,CAAC,CAACJ,IAAI,CAACI,IAAI,CAACM,OAAO,CAAC;IAC9B,IAAI,CAAC,CAACR,MAAM,GAAG,IAAI,CAAC,CAACF,IAAI,CAACe,QAAQ,CAAEC,SAAS,CAAC,CAAC;IAC/C,IAAI,CAAC,CAACb,MAAM,GAAG,IAAI,CAAC,CAACH,IAAI,CAACiB,QAAQ,CAAEC,SAAS,CAAC,CAAC;IAC/C,IAAI,CAAC,CAACd,IAAI,GAAG,IAAI;IACjB,IAAI,CAAC,CAACC,IAAI,GAAG,KAAK;IAClB,IAAI,CAAC,CAACC,MAAM,GAAG,KAAK;IACpB,KAAK,IAAI,CAAC,CAACa,IAAI,CAAC,CAAC;IACjB,OAAO,IAAI;EACb;;EAEA;EACA,MAAM,CAACA,IAAIC,CAAA,EAAkB;IAC3B,MAAMlB,MAAM,GAAG,IAAI,CAAC,CAACA,MAAM;IAC3B;IACA,IAAI,CAACA,MAAM,EAAE;IACb,IAAI;MACF,OAAO,CAAC,IAAI,CAAC,CAACI,MAAM,EAAE;QACpB,MAAM;UAACD,IAAI;UAAEgB;QAAK,CAAC,GAAG,MAAMnB,MAAM,CAACoB,IAAI,CAAC,CAAC;QACzC,IAAIjB,IAAI,EAAE;QACV;QACA,IAAIgB,KAAK,IAAIA,KAAK,CAAC1B,MAAM,GAAG,CAAC,EAAE;UAC7B,KAAK,IAAIE,CAAC,GAAG,CAAC,EAAEA,CAAC,GAAGwB,KAAK,CAAC1B,MAAM,EAAEE,CAAC,EAAE,EAAE,IAAI,CAAC,CAACU,OAAO,CAACgB,IAAI,CAACF,KAAK,CAACxB,CAAC,CAAC,CAAC;UACnE,IAAI,CAAC,CAAC2B,IAAI,CAAC,CAAC;QACd;MACF;IACF,CAAC,CAAC,MAAM;MACN;IAAA,CACD,SAAS;MACR,IAAI,CAAC,CAACnB,IAAI,GAAG,IAAI;MACjB,IAAI,CAAC,CAACmB,IAAI,CAAC,CAAC;IACd;EACF;EAEA,CAACA,IAAIC,CAAA,EAAS;IACZ,MAAMjB,OAAO,GAAG,IAAI,CAAC,CAACA,OAAO;IAC7B,IAAI,CAAC,CAACA,OAAO,GAAG,EAAE;IAClB,KAAK,MAAMkB,CAAC,IAAIlB,OAAO,EAAEkB,CAAC,CAAC,CAAC;EAC9B;;EAEA;EACA,CAACC,aAAaC,CAACC,EAAU,EAAiB;IACxC,OAAO,IAAIC,OAAO,CAAO,CAACC,OAAO,EAAEC,MAAM,KAAK;MAC5C,MAAMC,KAAK,GAAGC,UAAU,CAAC,MAAM;QAC7B,IAAI,CAAC,CAAC1B,OAAO,GAAG,IAAI,CAAC,CAACA,OAAO,CAAC2B,MAAM,CAACT,CAAC,IAAIA,CAAC,KAAKU,MAAM,CAAC;QACvDJ,MAAM,CAAC,IAAIK,KAAK,CAAC,cAAc,CAAC,CAAC;MACnC,CAAC,EAAER,EAAE,CAAC;MACN,MAAMO,MAAM,GAAGA,CAAA,KAAM;QACnBE,YAAY,CAACL,KAAK,CAAC;QACnBF,OAAO,CAAC,CAAC;MACX,CAAC;MACD,IAAI,CAAC,CAACvB,OAAO,CAACe,IAAI,CAACa,MAAM,CAAC;IAC5B,CAAC,CAAC;EACJ;;EAEA;AACF;AACA;AACA;EACE,MAAM,CAACG,OAAOC,CACZC,KAA2C,EAC3CC,SAAiB,EACjBC,KAAmB,EACE;IACrB,MAAMC,QAAQ,GAAGC,IAAI,CAACC,GAAG,CAAC,CAAC,GAAGJ,SAAS;IACvC,OAAO,IAAI,EAAE;MACX,MAAMK,IAAI,GAAGN,KAAK,CAAC,IAAI,CAAC,CAAClC,OAAO,CAAC;MACjC,IAAIwC,IAAI,KAAK,KAAK,EAAE;QAClB,OAAOC,UAAU,CAACC,IAAI,CAAC,IAAI,CAAC,CAAC1C,OAAO,CAAC2C,MAAM,CAAC,CAAC,EAAEH,IAAI,CAAC,CAAC;MACvD;MACA,IAAI,IAAI,CAAC,CAAC1C,IAAI,EAAE;QACd,IAAI,IAAI,CAAC,CAACE,OAAO,CAACZ,MAAM,GAAG,CAAC,EAAE;UAC5B;UACA,OAAOqD,UAAU,CAACC,IAAI,CAAC,IAAI,CAAC,CAAC1C,OAAO,CAAC2C,MAAM,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC3C,OAAO,CAACZ,MAAM,CAAC,CAAC;QACvE;QACA;QACA;QACA;QACA,MAAM,IAAImC,OAAO,CAACC,OAAO,IAAIG,UAAU,CAACH,OAAO,EAAE,CAAC,CAAC,CAAC;QACpD;QACA,IAAI,IAAI,CAAC,CAACxB,OAAO,CAACZ,MAAM,KAAK,CAAC,EAAE;UAC9B,OAAOqD,UAAU,CAACC,IAAI,CAAC,EAAE,CAAC;QAC5B;QACA;QACA;MACF;MACA,MAAME,SAAS,GAAGP,QAAQ,GAAGC,IAAI,CAACC,GAAG,CAAC,CAAC;MACvC,IAAIK,SAAS,IAAI,CAAC,EAAE,MAAM,IAAId,KAAK,CAACM,KAAK,CAAC,CAAC,CAAC;MAC5C,IAAI;QACF,MAAM,IAAI,CAAC,CAAChB,aAAa,CAACwB,SAAS,CAAC;MACtC,CAAC,CAAC,MAAM;QACN,MAAM,IAAId,KAAK,CAACM,KAAK,CAAC,CAAC,CAAC;MAC1B;IACF;EACF;;EAEA;EACA,MAAMS,KAAKA,CAACC,IAAoC,EAAiB;IAC/D,IAAI,CAAC,IAAI,CAAC,CAAClD,MAAM,EAAE,MAAM,IAAIkC,KAAK,CAAC,2BAA2B,CAAC;IAC/D,MAAM,IAAI,CAAC,CAAClC,MAAM,CAACiD,KAAK,CAACJ,UAAU,CAACC,IAAI,CAAC,IAAAK,wBAAO,EAACD,IAAI,CAAC,CAAC,CAAC;EAC1D;;EAEA;EACAE,SAASA,CAACC,CAAS,EAAE9C,OAAoB,GAAG,CAAC,CAAC,EAAuB;IACnE,MAAM+C,OAAO,GAAG/C,OAAO,CAAC+C,OAAO,IAAI,IAAI,CAAC,CAACxD,cAAc;IACvD,OAAO,IAAI,CAAC,CAACsC,OAAO,CAClBmB,GAAG,IAAKA,GAAG,CAAC/D,MAAM,IAAI6D,CAAC,GAAGA,CAAC,GAAG,KAAM,EACpCC,OAAO,EACP,MAAM,qBAAqBD,CAAC,eAAe,IAAI,CAAC,CAACjD,OAAO,CAACZ,MAAM,GACjE,CAAC;EACH;;EAEA;EACAgE,SAASA,CACPC,SAAyC,EACzClD,OAAoB,GAAG,CAAC,CAAC,EACJ;IACrB,MAAMhB,MAAM,GAAG,IAAA4D,wBAAO,EAACM,SAAS,CAAC;IACjC,MAAMH,OAAO,GAAG/C,OAAO,CAAC+C,OAAO,IAAI,IAAI,CAAC,CAACxD,cAAc;IACvD,OAAO,IAAI,CAAC,CAACsC,OAAO,CAClBmB,GAAG,IAAI;MACL,MAAMG,GAAG,GAAGrE,kBAAkB,CAACkE,GAAG,EAAEhE,MAAM,CAAC;MAC3C,OAAOmE,GAAG,GAAG,CAAC,GAAG,KAAK,GAAGA,GAAG,GAAGnE,MAAM,CAACC,MAAM;IAC9C,CAAC,EACD8D,OAAO,EACP,MAAM,mCACR,CAAC;EACH;;EAEA;EACA,MAAMK,QAAQA,CAACpD,OAAoB,GAAG,CAAC,CAAC,EAAmB;IACzD,MAAMqD,KAAK,GAAG,MAAM,IAAI,CAACJ,SAAS,CAAC,IAAI,EAAEjD,OAAO,CAAC;IACjD,IAAIsD,GAAG,GAAGD,KAAK,CAACpE,MAAM;IACtB,IAAIqE,GAAG,GAAG,CAAC,IAAID,KAAK,CAACC,GAAG,GAAG,CAAC,CAAC,KAAK,IAAI,EAAEA,GAAG,EAAE;IAC7C,IAAIA,GAAG,GAAG,CAAC,IAAID,KAAK,CAACC,GAAG,GAAG,CAAC,CAAC,KAAK,IAAI,EAAEA,GAAG,EAAE;IAC7C,OAAOC,MAAM,CAACC,YAAY,CAAC,GAAGH,KAAK,CAACI,QAAQ,CAAC,CAAC,EAAEH,GAAG,CAAC,CAAC;EACvD;;EAEA;AACF;AACA;AACA;EACEI,YAAYA,CACVC,SAAiD,EACjD3D,OAAoB,GAAG,CAAC,CAAC,EACJ;IACrB,MAAM+C,OAAO,GAAG/C,OAAO,CAAC+C,OAAO,IAAI,IAAI,CAAC,CAACxD,cAAc;IACvD,OAAO,IAAI,CAAC,CAACsC,OAAO,CAClBmB,GAAG,IAAIW,SAAS,CAACrB,UAAU,CAACC,IAAI,CAACS,GAAG,CAAC,CAAC,EACtCD,OAAO,EACP,MAAM,+BACR,CAAC;EACH;;EAEA;AACF;AACA;AACA;AACA;AACA;EACEa,aAAaA,CAAC5D,OAAoB,GAAG,CAAC,CAAC,EAAuB;IAC5D,MAAM+C,OAAO,GAAG/C,OAAO,CAAC+C,OAAO,IAAI,IAAI,CAAC,CAACxD,cAAc;IACvD,OAAO,IAAI,CAAC,CAACsC,OAAO,CAClBmB,GAAG,IAAKA,GAAG,CAAC/D,MAAM,GAAG,CAAC,GAAG+D,GAAG,CAAC/D,MAAM,GAAG,KAAM,EAC5C8D,OAAO,EACP,MAAM,4BACR,CAAC;EACH;;EAEA;EACA,MAAMc,UAAUA,CAAC1C,EAAU,EAAiB;IAC1C,IAAI,IAAI,CAAC,CAACtB,OAAO,CAACZ,MAAM,GAAG,CAAC,EAAE;MAC5B,MAAM,IAAI0C,KAAK,CACb,gCAAgC,IAAI,CAAC,CAAC9B,OAAO,CAACZ,MAAM,gCACtD,CAAC;IACH;IACA,IAAI;MACF,MAAM,IAAI,CAAC,CAACgC,aAAa,CAACE,EAAE,CAAC;IAC/B,CAAC,CAAC,MAAM;MACN,OAAO,CAAC;IACV;IACA,IAAI,IAAI,CAAC,CAACtB,OAAO,CAACZ,MAAM,GAAG,CAAC,EAAE;MAC5B,MAAM,IAAI0C,KAAK,CACb,gCAAgCR,EAAE,mBAAmB,IAAI,CAAC,CAACtB,OAAO,CAACZ,MAAM,UAC3E,CAAC;IACH;IACA;EACF;;EAEA;EACA6E,KAAKA,CAAA,EAAS;IACZ,IAAI,CAAC,CAACjE,OAAO,CAACZ,MAAM,GAAG,CAAC;EAC1B;;EAEA;EACA,MAAM8E,KAAKA,CAAA,EAAkB;IAC3B,IAAI,IAAI,CAAC,CAACnE,MAAM,EAAE;IAClB,IAAI,CAAC,CAACA,MAAM,GAAG,IAAI;IACnB,IAAI,CAAC,CAACkB,IAAI,CAAC,CAAC;IACZ,IAAI,IAAI,CAAC,CAACtB,MAAM,EAAE;MAChB,IAAI;QACF,MAAM,IAAI,CAAC,CAACA,MAAM,CAACwE,MAAM,CAAC,CAAC;MAC7B,CAAC,CAAC,MAAM;QACN;MAAA;MAEF,IAAI;QACF,IAAI,CAAC,CAACxE,MAAM,CAACyE,WAAW,CAAC,CAAC;MAC5B,CAAC,CAAC,MAAM;QACN;MAAA;MAEF,IAAI,CAAC,CAACzE,MAAM,GAAG,IAAI;IACrB;IACA,IAAI,IAAI,CAAC,CAACC,MAAM,EAAE;MAChB,IAAI;QACF,MAAM,IAAI,CAAC,CAACA,MAAM,CAACsE,KAAK,CAAC,CAAC;MAC5B,CAAC,CAAC,MAAM;QACN;MAAA;MAEF,IAAI;QACF,IAAI,CAAC,CAACtE,MAAM,CAACwE,WAAW,CAAC,CAAC;MAC5B,CAAC,CAAC,MAAM;QACN;MAAA;MAEF,IAAI,CAAC,CAACxE,MAAM,GAAG,IAAI;IACrB;IACA,IAAI,CAAC,CAACC,IAAI,GAAG,KAAK;IAClB,IAAI;MACF,MAAM,IAAI,CAAC,CAACJ,IAAI,CAACyE,KAAK,CAAC,CAAC;IAC1B,CAAC,CAAC,MAAM;MACN;IAAA;EAEJ;AACF;;AAEA;AAAAG,OAAA,CAAA7E,YAAA,GAAAA,YAAA;AACO,SAAS8E,kBAAkBA,CAChC7E,IAAgB,EAChBU,OAA6B,EACf;EACd,OAAO,IAAIX,YAAY,CAACC,IAAI,EAAEU,OAAO,CAAC;AACxC","ignoreList":[]}
|
|
@@ -3,20 +3,20 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
-
exports.
|
|
6
|
+
exports.SinkDevice = exports.SimulatedDevice = exports.LoopbackDevice = exports.LineBufferedDevice = void 0;
|
|
7
7
|
exports.toBytes = toBytes;
|
|
8
8
|
/**
|
|
9
|
-
*
|
|
9
|
+
* SimulatedDevice — author a complete simulated serial peripheral.
|
|
10
10
|
*
|
|
11
11
|
* Extend the class and override the lifecycle hooks to model a real device's
|
|
12
12
|
* whole behaviour (firmware/protocol): react to `open()`, to bytes the host
|
|
13
13
|
* writes, to control-signal changes, and stream data back over time. It is
|
|
14
|
-
* hosted by
|
|
14
|
+
* hosted by an {@link InMemorySerialTransport} ({@link ./virtual-serial}) and is
|
|
15
15
|
* free of any `react-native` dependency, so the same device runs under Jest,
|
|
16
16
|
* in a browser, and inside a React Native app on a device/emulator (for E2E).
|
|
17
17
|
*
|
|
18
18
|
* @example
|
|
19
|
-
* class Thermometer extends
|
|
19
|
+
* class Thermometer extends SimulatedDevice {
|
|
20
20
|
* usbVendorId = 0x0403;
|
|
21
21
|
* usbProductId = 0x6001;
|
|
22
22
|
* #timer?: ReturnType<typeof setInterval>;
|
|
@@ -38,8 +38,8 @@ exports.toBytes = toBytes;
|
|
|
38
38
|
/** Host-asserted output signals (DTR/RTS/break) the device observes. */
|
|
39
39
|
|
|
40
40
|
/**
|
|
41
|
-
* The handle a {@link
|
|
42
|
-
* the transport; you normally use the `protected` helpers on `
|
|
41
|
+
* The handle a {@link SimulatedDevice} uses to talk back to the host. Provided by
|
|
42
|
+
* the transport; you normally use the `protected` helpers on `SimulatedDevice`
|
|
43
43
|
* rather than this directly.
|
|
44
44
|
*/
|
|
45
45
|
|
|
@@ -57,7 +57,7 @@ function toBytes(data) {
|
|
|
57
57
|
* care about (all default to no-ops and may be async) and use the `protected`
|
|
58
58
|
* helpers to drive the host.
|
|
59
59
|
*/
|
|
60
|
-
class
|
|
60
|
+
class SimulatedDevice {
|
|
61
61
|
/** USB Vendor ID this device reports for enumeration. */
|
|
62
62
|
|
|
63
63
|
/** USB Product ID this device reports for enumeration. */
|
|
@@ -66,7 +66,7 @@ class SerialDevice {
|
|
|
66
66
|
|
|
67
67
|
#host = null;
|
|
68
68
|
|
|
69
|
-
/** @internal Bind the transport host (called by
|
|
69
|
+
/** @internal Bind the transport host (called by InMemorySerialTransport). */
|
|
70
70
|
_bind(host) {
|
|
71
71
|
this.#host = host;
|
|
72
72
|
}
|
|
@@ -111,10 +111,10 @@ class SerialDevice {
|
|
|
111
111
|
onClose() {}
|
|
112
112
|
}
|
|
113
113
|
|
|
114
|
-
/** Optional USB identity for
|
|
115
|
-
exports.
|
|
114
|
+
/** Optional USB identity for built-in devices. */
|
|
115
|
+
exports.SimulatedDevice = SimulatedDevice;
|
|
116
116
|
/** A loopback device: every byte written is echoed straight back. */
|
|
117
|
-
class
|
|
117
|
+
class LoopbackDevice extends SimulatedDevice {
|
|
118
118
|
constructor(identity = {}) {
|
|
119
119
|
super();
|
|
120
120
|
this.usbVendorId = identity.usbVendorId ?? 0x0403;
|
|
@@ -130,8 +130,8 @@ class EchoDevice extends SerialDevice {
|
|
|
130
130
|
* Base for a line-oriented command/response device: buffers incoming bytes and
|
|
131
131
|
* calls {@link onLine} for each `\n`-terminated line (trailing CR/LF stripped).
|
|
132
132
|
*/
|
|
133
|
-
exports.
|
|
134
|
-
class
|
|
133
|
+
exports.LoopbackDevice = LoopbackDevice;
|
|
134
|
+
class LineBufferedDevice extends SimulatedDevice {
|
|
135
135
|
#buffer = '';
|
|
136
136
|
|
|
137
137
|
/** Handle one line received from the host. */
|
|
@@ -151,8 +151,8 @@ class LineDevice extends SerialDevice {
|
|
|
151
151
|
}
|
|
152
152
|
|
|
153
153
|
/** A device that accepts writes but never sends anything back. */
|
|
154
|
-
exports.
|
|
155
|
-
class
|
|
154
|
+
exports.LineBufferedDevice = LineBufferedDevice;
|
|
155
|
+
class SinkDevice extends SimulatedDevice {
|
|
156
156
|
constructor(identity = {}) {
|
|
157
157
|
super();
|
|
158
158
|
this.usbVendorId = identity.usbVendorId ?? 0x0403;
|
|
@@ -160,5 +160,5 @@ class SilentDevice extends SerialDevice {
|
|
|
160
160
|
this.serialNumber = identity.serialNumber;
|
|
161
161
|
}
|
|
162
162
|
}
|
|
163
|
-
exports.
|
|
164
|
-
//# sourceMappingURL=
|
|
163
|
+
exports.SinkDevice = SinkDevice;
|
|
164
|
+
//# sourceMappingURL=simulated-device.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["toBytes","data","Array","from","c","charCodeAt","Uint8Array","map","n","SimulatedDevice","host","_bind","send","raiseError","message","name","setSignals","signals","openOptions","deviceId","portNumber","onOpen","_options","onData","_data","onHostSignals","_signals","onClose","exports","LoopbackDevice","constructor","identity","usbVendorId","usbProductId","serialNumber","LineBufferedDevice","buffer","i","length","String","fromCharCode","nl","indexOf","line","slice","replace","onLine","SinkDevice"],"sourceRoot":"../../../src","sources":["testing/simulated-device.ts"],"mappings":";;;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAGA;;AAGA;;AAQA;;AAOA;AACA;AACA;AACA;AACA;;AAWA;AACO,SAASA,OAAOA,CAACC,IAAoC,EAAY;EACtE,IAAI,OAAOA,IAAI,KAAK,QAAQ,EAAE;IAC5B,OAAOC,KAAK,CAACC,IAAI,CAACF,IAAI,EAAEG,CAAC,IAAIA,CAAC,CAACC,UAAU,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;EACtD;EACA,IAAIJ,IAAI,YAAYK,UAAU,EAAE,OAAOJ,KAAK,CAACC,IAAI,CAACF,IAAI,CAAC;EACvD,OAAOA,IAAI,CAACM,GAAG,CAACC,CAAC,IAAIA,CAAC,GAAG,IAAI,CAAC;AAChC;;AAEA;AACA;AACA;AACA;AACA;AACO,MAAeC,eAAe,CAAC;EACpC;;EAEA;;EAEA;;EAGA,CAACC,IAAI,GAA+B,IAAI;;EAExC;EACAC,KAAKA,CAACD,IAAyB,EAAQ;IACrC,IAAI,CAAC,CAACA,IAAI,GAAGA,IAAI;EACnB;;EAEA;EACUE,IAAIA,CAACX,IAAoC,EAAQ;IACzD,IAAI,CAAC,CAACS,IAAI,EAAEE,IAAI,CAACZ,OAAO,CAACC,IAAI,CAAC,CAAC;EACjC;;EAEA;AACF;AACA;AACA;AACA;EACYY,UAAUA,CAACC,OAAe,EAAEC,IAAa,EAAQ;IACzD,IAAI,CAAC,CAACL,IAAI,EAAEG,UAAU,CAACC,OAAO,EAAEC,IAAI,CAAC;EACvC;;EAEA;EACUC,UAAUA,CAACC,OAA2B,EAAQ;IACtD,IAAI,CAAC,CAACP,IAAI,EAAEM,UAAU,CAACC,OAAO,CAAC;EACjC;;EAEA;EACA,IAAcC,WAAWA,CAAA,EAAsC;IAC7D,OAAO,IAAI,CAAC,CAACR,IAAI,EAAEQ,WAAW,IAAI,IAAI;EACxC;EAEA,IAAcC,QAAQA,CAAA,EAAW;IAC/B,OAAO,IAAI,CAAC,CAACT,IAAI,EAAES,QAAQ,IAAI,CAAC,CAAC;EACnC;EAEA,IAAcC,UAAUA,CAAA,EAAW;IACjC,OAAO,IAAI,CAAC,CAACV,IAAI,EAAEU,UAAU,IAAI,CAAC;EACpC;;EAEA;EACAC,MAAMA,CAACC,QAAoC,EAAwB,CAAC;EACpE;EACAC,MAAMA,CAACC,KAAiB,EAAwB,CAAC;EACjD;EACAC,aAAaA,CAACC,QAAqB,EAAwB,CAAC;EAC5D;EACAC,OAAOA,CAAA,EAAyB,CAAC;AACnC;;AAEA;AAAAC,OAAA,CAAAnB,eAAA,GAAAA,eAAA;AAOA;AACO,MAAMoB,cAAc,SAASpB,eAAe,CAAC;EAKlDqB,WAAWA,CAACC,QAAiC,GAAG,CAAC,CAAC,EAAE;IAClD,KAAK,CAAC,CAAC;IACP,IAAI,CAACC,WAAW,GAAGD,QAAQ,CAACC,WAAW,IAAI,MAAM;IACjD,IAAI,CAACC,YAAY,GAAGF,QAAQ,CAACE,YAAY,IAAI,MAAM;IACnD,IAAI,CAACC,YAAY,GAAGH,QAAQ,CAACG,YAAY;EAC3C;EAEAX,MAAMA,CAACtB,IAAgB,EAAQ;IAC7B,IAAI,CAACW,IAAI,CAACX,IAAI,CAAC;EACjB;AACF;;AAEA;AACA;AACA;AACA;AAHA2B,OAAA,CAAAC,cAAA,GAAAA,cAAA;AAIO,MAAeM,kBAAkB,SAAS1B,eAAe,CAAC;EAC/D,CAAC2B,MAAM,GAAG,EAAE;;EAEZ;;EAGAb,MAAMA,CAACtB,IAAgB,EAAQ;IAC7B,KAAK,IAAIoC,CAAC,GAAG,CAAC,EAAEA,CAAC,GAAGpC,IAAI,CAACqC,MAAM,EAAED,CAAC,EAAE,EAAE;MACpC,IAAI,CAAC,CAACD,MAAM,IAAIG,MAAM,CAACC,YAAY,CAACvC,IAAI,CAACoC,CAAC,CAAC,CAAC;IAC9C;IACA,IAAII,EAAE,GAAG,IAAI,CAAC,CAACL,MAAM,CAACM,OAAO,CAAC,IAAI,CAAC;IACnC,OAAOD,EAAE,IAAI,CAAC,EAAE;MACd,MAAME,IAAI,GAAG,IAAI,CAAC,CAACP,MAAM,CAACQ,KAAK,CAAC,CAAC,EAAEH,EAAE,CAAC,CAACI,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC;MACzD,IAAI,CAAC,CAACT,MAAM,GAAG,IAAI,CAAC,CAACA,MAAM,CAACQ,KAAK,CAACH,EAAE,GAAG,CAAC,CAAC;MACzC,KAAK,IAAI,CAACK,MAAM,CAACH,IAAI,CAAC;MACtBF,EAAE,GAAG,IAAI,CAAC,CAACL,MAAM,CAACM,OAAO,CAAC,IAAI,CAAC;IACjC;EACF;AACF;;AAEA;AAAAd,OAAA,CAAAO,kBAAA,GAAAA,kBAAA;AACO,MAAMY,UAAU,SAAStC,eAAe,CAAC;EAK9CqB,WAAWA,CAACC,QAAiC,GAAG,CAAC,CAAC,EAAE;IAClD,KAAK,CAAC,CAAC;IACP,IAAI,CAACC,WAAW,GAAGD,QAAQ,CAACC,WAAW,IAAI,MAAM;IACjD,IAAI,CAACC,YAAY,GAAGF,QAAQ,CAACE,YAAY,IAAI,MAAM;IACnD,IAAI,CAACC,YAAY,GAAGH,QAAQ,CAACG,YAAY;EAC3C;AACF;AAACN,OAAA,CAAAmB,UAAA,GAAAA,UAAA","ignoreList":[]}
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.compareTestResults = compareTestResults;
|
|
7
|
+
exports.runTestSuite = runTestSuite;
|
|
8
|
+
var _harness = require("./harness");
|
|
9
|
+
var _serialClient = require("./serial-client");
|
|
10
|
+
/**
|
|
11
|
+
* A runtime-agnostic suite runner for serial device tests. Write a set of
|
|
12
|
+
* `SerialTest`s once and run them anywhere a {@link SerialPort} exists:
|
|
13
|
+
*
|
|
14
|
+
* - in Jest against a {@link DeviceHandle} simulator (in-memory),
|
|
15
|
+
* - on a device / emulator over a real or WebSocket-backed port, and
|
|
16
|
+
* - against BOTH, then {@link compareTestResults} to prove the device matches
|
|
17
|
+
* the simulator case-for-case.
|
|
18
|
+
*
|
|
19
|
+
* Each test receives an opened, host-side {@link SerialClient}; by default one
|
|
20
|
+
* client is shared across the whole suite (open once, close at the end), which
|
|
21
|
+
* matches how a request/response protocol session behaves. Pass `shared: false`
|
|
22
|
+
* to open and close a fresh client per test. The runner never throws — it
|
|
23
|
+
* collects a {@link SerialTestResult} per case — so it is safe to drive an
|
|
24
|
+
* on-device Self-Test screen.
|
|
25
|
+
*
|
|
26
|
+
* @example One suite, two transports, compared
|
|
27
|
+
* const sim = await runTestSuite(myTests, await virtualPort());
|
|
28
|
+
* const dev = await runTestSuite(myTests, realPort);
|
|
29
|
+
* const rows = compareTestResults(sim, dev); // a row passes when both agree
|
|
30
|
+
*/
|
|
31
|
+
|
|
32
|
+
/** One test case. `run` receives an already-opened client (typically per the
|
|
33
|
+
* suite's {@link TestClient}; `SerialClient` by default). */
|
|
34
|
+
|
|
35
|
+
/** Progress hooks so a UI can render results live as each test completes. */
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* How to build (and tear down) the per-suite client from a port. Provide this to
|
|
39
|
+
* run a higher-level protocol client (e.g. an HCI / NMEA framer built on a
|
|
40
|
+
* {@link SerialClient}) instead of the raw client. `connect` must also open the
|
|
41
|
+
* port; `disconnect` must release it (a `SerialClient.close()` does both).
|
|
42
|
+
*/
|
|
43
|
+
|
|
44
|
+
function defaultClientFactory(open) {
|
|
45
|
+
return {
|
|
46
|
+
async connect(port) {
|
|
47
|
+
const client = new _serialClient.SerialClient(port);
|
|
48
|
+
await client.open(open);
|
|
49
|
+
return client;
|
|
50
|
+
},
|
|
51
|
+
disconnect: client => client.close()
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Run `tests` against an already-acquired `port`, collecting one result per
|
|
57
|
+
* case. With the default (shared) client the port is opened once and closed at
|
|
58
|
+
* the end; with `shared: false` each test gets a fresh open/close. Never throws.
|
|
59
|
+
*/
|
|
60
|
+
async function runTestSuite(tests, port, options = {}) {
|
|
61
|
+
const factory = options.client ?? defaultClientFactory(options.open);
|
|
62
|
+
const shared = options.shared ?? true;
|
|
63
|
+
const progress = options.progress;
|
|
64
|
+
const results = [];
|
|
65
|
+
let sharedClient = null;
|
|
66
|
+
if (shared) {
|
|
67
|
+
try {
|
|
68
|
+
sharedClient = await factory.connect(port);
|
|
69
|
+
} catch (e) {
|
|
70
|
+
const result = {
|
|
71
|
+
name: 'open serial port',
|
|
72
|
+
passed: false,
|
|
73
|
+
error: (0, _harness.errorMessage)(e),
|
|
74
|
+
durationMs: 0
|
|
75
|
+
};
|
|
76
|
+
progress?.onResult?.(result);
|
|
77
|
+
return [result];
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
const total = tests.length;
|
|
81
|
+
try {
|
|
82
|
+
for (let i = 0; i < total; i++) {
|
|
83
|
+
const test = tests[i];
|
|
84
|
+
progress?.onStart?.(test.name, i, total);
|
|
85
|
+
const start = Date.now();
|
|
86
|
+
let perTest = null;
|
|
87
|
+
let result;
|
|
88
|
+
try {
|
|
89
|
+
if (!shared) perTest = await factory.connect(port);
|
|
90
|
+
const client = shared ? sharedClient : perTest;
|
|
91
|
+
await test.run(client);
|
|
92
|
+
result = {
|
|
93
|
+
name: test.name,
|
|
94
|
+
passed: true,
|
|
95
|
+
durationMs: Date.now() - start
|
|
96
|
+
};
|
|
97
|
+
} catch (e) {
|
|
98
|
+
result = {
|
|
99
|
+
name: test.name,
|
|
100
|
+
passed: false,
|
|
101
|
+
error: (0, _harness.errorMessage)(e),
|
|
102
|
+
durationMs: Date.now() - start
|
|
103
|
+
};
|
|
104
|
+
} finally {
|
|
105
|
+
if (perTest) await factory.disconnect(perTest).catch(() => {});
|
|
106
|
+
}
|
|
107
|
+
results.push(result);
|
|
108
|
+
progress?.onResult?.(result);
|
|
109
|
+
}
|
|
110
|
+
} finally {
|
|
111
|
+
if (sharedClient) await factory.disconnect(sharedClient).catch(() => {});
|
|
112
|
+
}
|
|
113
|
+
return results;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Compare two runs of the same suite case-by-case. A row passes when both runs
|
|
118
|
+
* agree (both passed or both failed), so the `candidate` is judged equivalent to
|
|
119
|
+
* the `reference` rather than judged on its own. Cases the candidate produced
|
|
120
|
+
* that the reference never ran are surfaced as failing `candidate: …` rows.
|
|
121
|
+
*/
|
|
122
|
+
function compareTestResults(reference, candidate) {
|
|
123
|
+
const candidateByName = new Map(candidate.map(r => [r.name, r]));
|
|
124
|
+
const candidateOnly = candidate.filter(r => !reference.some(s => s.name === r.name)).map(r => ({
|
|
125
|
+
name: `candidate: ${r.name}`,
|
|
126
|
+
passed: false,
|
|
127
|
+
error: r.error ?? 'candidate produced an unexpected result',
|
|
128
|
+
durationMs: r.durationMs
|
|
129
|
+
}));
|
|
130
|
+
const compared = reference.map(s => {
|
|
131
|
+
const r = candidateByName.get(s.name);
|
|
132
|
+
const identical = !!r && r.passed === s.passed;
|
|
133
|
+
return {
|
|
134
|
+
name: s.name,
|
|
135
|
+
passed: identical,
|
|
136
|
+
error: identical ? undefined : `reference ${s.passed ? 'passed' : 'failed'}, candidate ${r ? r.passed ? 'passed' : 'failed' : 'did not respond'}${r?.error ? `: ${r.error}` : ''}`,
|
|
137
|
+
durationMs: r?.durationMs ?? 0
|
|
138
|
+
};
|
|
139
|
+
});
|
|
140
|
+
return [...candidateOnly, ...compared];
|
|
141
|
+
}
|
|
142
|
+
//# sourceMappingURL=test-suite.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["_harness","require","_serialClient","defaultClientFactory","open","connect","port","client","SerialClient","disconnect","close","runTestSuite","tests","options","factory","shared","progress","results","sharedClient","e","result","name","passed","error","errorMessage","durationMs","onResult","total","length","i","test","onStart","start","Date","now","perTest","run","catch","push","compareTestResults","reference","candidate","candidateByName","Map","map","r","candidateOnly","filter","some","s","compared","get","identical","undefined"],"sourceRoot":"../../../src","sources":["testing/test-suite.ts"],"mappings":"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","ignoreList":[]}
|
|
@@ -5,13 +5,13 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
5
5
|
});
|
|
6
6
|
exports.StopBits = exports.Parity = exports.DataBits = exports.DEFAULT_OPEN_OPTIONS = void 0;
|
|
7
7
|
/**
|
|
8
|
-
* Hardware-transport
|
|
8
|
+
* Hardware-transport abstraction for the Web Serial polyfill.
|
|
9
9
|
*
|
|
10
10
|
* `SerialTransport` is the single interface that the `Serial`/`SerialPort`
|
|
11
11
|
* classes depend on to talk to "the device". The production implementation
|
|
12
12
|
* (`UsbSerialModule`, backed by the `NativeUsbSerial` TurboModule — see
|
|
13
13
|
* {@link ./UsbSerial}) and the in-memory test/dev double
|
|
14
|
-
* (`
|
|
14
|
+
* (`InMemorySerialTransport` — see {@link ./testing/in-memory-serial-transport}) both
|
|
15
15
|
* implement it.
|
|
16
16
|
*
|
|
17
17
|
* This module is intentionally free of any `react-native` import. That is what
|
|
@@ -53,7 +53,7 @@ const DEFAULT_OPEN_OPTIONS = exports.DEFAULT_OPEN_OPTIONS = {
|
|
|
53
53
|
* The contract every serial transport must satisfy. It mirrors the JS-friendly
|
|
54
54
|
* surface of `UsbSerialModule` exactly, so `UsbSerialModule implements
|
|
55
55
|
* SerialTransport` is a faithful 1:1 and any conforming double (e.g.
|
|
56
|
-
* `
|
|
56
|
+
* `InMemorySerialTransport`) is a drop-in replacement.
|
|
57
57
|
*
|
|
58
58
|
* Ports are addressed by the pair `(deviceId, portNumber)`. Inbound bytes,
|
|
59
59
|
* read errors and device attach/detach arrive through the `on*` subscriptions.
|