@react-native-harness/bridge 1.0.0-alpha.1

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 ADDED
@@ -0,0 +1,20 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Callstack
4
+ Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ of this software and associated documentation files (the "Software"), to deal
6
+ in the Software without restriction, including without limitation the rights
7
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ copies of the Software, and to permit persons to whom the Software is
9
+ furnished to do so, subject to the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be included in all
12
+ copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,7 @@
1
+ # bridge
2
+
3
+ This library was generated with [Nx](https://nx.dev).
4
+
5
+ ## Building
6
+
7
+ Run `nx build bridge` to build the library.
@@ -0,0 +1,9 @@
1
+ import { BirpcReturn } from 'birpc';
2
+ import type { BridgeClientFunctions, BridgeServerFunctions } from './shared.js';
3
+ export type BridgeClient = {
4
+ rpc: BirpcReturn<BridgeServerFunctions, BridgeClientFunctions>;
5
+ disconnect: () => void;
6
+ };
7
+ declare const getBridgeClient: (url: string, handlers: BridgeClientFunctions) => Promise<BridgeClient>;
8
+ export { getBridgeClient };
9
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAe,MAAM,OAAO,CAAC;AACjD,OAAO,KAAK,EAAE,qBAAqB,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AAEhF,MAAM,MAAM,YAAY,GAAG;IACzB,GAAG,EAAE,WAAW,CAAC,qBAAqB,EAAE,qBAAqB,CAAC,CAAC;IAC/D,UAAU,EAAE,MAAM,IAAI,CAAC;CACxB,CAAC;AAEF,QAAA,MAAM,eAAe,GACnB,KAAK,MAAM,EACX,UAAU,qBAAqB,KAC9B,OAAO,CAAC,YAAY,CA+BtB,CAAC;AAEF,OAAO,EAAE,eAAe,EAAE,CAAC"}
package/dist/client.js ADDED
@@ -0,0 +1,28 @@
1
+ import { WebSocket } from 'partysocket';
2
+ import { createBirpc } from 'birpc';
3
+ const getBridgeClient = async (url, handlers) => {
4
+ return new Promise((resolve) => {
5
+ const ws = new WebSocket(url);
6
+ const handleOpen = () => {
7
+ const rpc = createBirpc(handlers, {
8
+ post: (data) => ws.send(data),
9
+ on: (handler) => {
10
+ ws.addEventListener('message', (event) => {
11
+ handler(event.data);
12
+ });
13
+ },
14
+ serialize: JSON.stringify,
15
+ deserialize: JSON.parse,
16
+ });
17
+ const client = {
18
+ rpc,
19
+ disconnect: () => {
20
+ ws.close();
21
+ },
22
+ };
23
+ resolve(client);
24
+ };
25
+ ws.addEventListener('open', handleOpen, { once: true });
26
+ });
27
+ };
28
+ export { getBridgeClient };
@@ -0,0 +1,45 @@
1
+ export type ExecutionStartedEvent = {
2
+ type: 'execution-started';
3
+ path: string;
4
+ numberOfTests: number;
5
+ };
6
+ export type ExecutionFinishedEvent = {
7
+ type: 'execution-finished';
8
+ path: string;
9
+ duration: number;
10
+ };
11
+ export type SuiteStartedEvent = {
12
+ type: 'suite-started';
13
+ path: string;
14
+ name: string;
15
+ };
16
+ export type SuiteFinishedEvent = {
17
+ type: 'suite-finished';
18
+ path: string;
19
+ name: string;
20
+ duration: number;
21
+ reason: 'passed' | 'failed' | 'skipped' | 'todo';
22
+ };
23
+ export type TestStartedEvent = {
24
+ type: 'test-started';
25
+ path: string;
26
+ suite: string;
27
+ name: string;
28
+ };
29
+ export type TestFinishedEvent = {
30
+ type: 'test-finished';
31
+ path: string;
32
+ suite: string;
33
+ name: string;
34
+ duration: number;
35
+ reason: 'passed' | 'failed' | 'skipped' | 'todo';
36
+ };
37
+ export type BridgeEvents = {
38
+ 'execution-started': ExecutionStartedEvent;
39
+ 'execution-finished': ExecutionFinishedEvent;
40
+ 'suite-started': SuiteStartedEvent;
41
+ 'suite-finished': SuiteFinishedEvent;
42
+ 'test-started': TestStartedEvent;
43
+ 'test-finished': TestFinishedEvent;
44
+ };
45
+ //# sourceMappingURL=events.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../src/events.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,qBAAqB,GAAG;IAClC,IAAI,EAAE,mBAAmB,CAAC;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,aAAa,EAAE,MAAM,CAAC;CACvB,CAAC;AAEF,MAAM,MAAM,sBAAsB,GAAG;IACnC,IAAI,EAAE,oBAAoB,CAAC;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,IAAI,EAAE,eAAe,CAAC;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,IAAI,EAAE,gBAAgB,CAAC;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,QAAQ,GAAG,QAAQ,GAAG,SAAS,GAAG,MAAM,CAAC;CAClD,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,IAAI,EAAE,cAAc,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,IAAI,EAAE,eAAe,CAAC;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,QAAQ,GAAG,QAAQ,GAAG,SAAS,GAAG,MAAM,CAAC;CAClD,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG;IACzB,mBAAmB,EAAE,qBAAqB,CAAC;IAC3C,oBAAoB,EAAE,sBAAsB,CAAC;IAC7C,eAAe,EAAE,iBAAiB,CAAC;IACnC,gBAAgB,EAAE,kBAAkB,CAAC;IACrC,cAAc,EAAE,gBAAgB,CAAC;IACjC,eAAe,EAAE,iBAAiB,CAAC;CACpC,CAAC"}
package/dist/events.js ADDED
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,2 @@
1
+ export * from './shared.js';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1 @@
1
+ export * from './shared.js';
@@ -0,0 +1,18 @@
1
+ import { WebSocketServer } from 'ws';
2
+ import { type BirpcGroup } from 'birpc';
3
+ import type { BridgeServerFunctions, BridgeClientFunctions, DeviceDescriptor, BridgeEventsMap } from './shared.js';
4
+ export type BridgeServerOptions = {
5
+ port: number;
6
+ };
7
+ export type BridgeServerEvents = {
8
+ ready: (device: DeviceDescriptor) => void;
9
+ } & BridgeEventsMap;
10
+ export type BridgeServer = {
11
+ ws: WebSocketServer;
12
+ rpc: BirpcGroup<BridgeClientFunctions, BridgeServerFunctions>;
13
+ on: <T extends keyof BridgeServerEvents>(event: T, listener: BridgeServerEvents[T]) => void;
14
+ once: <T extends keyof BridgeServerEvents>(event: T, listener: BridgeServerEvents[T]) => void;
15
+ off: <T extends keyof BridgeServerEvents>(event: T, listener: BridgeServerEvents[T]) => void;
16
+ };
17
+ export declare const getBridgeServer: ({ port, }: BridgeServerOptions) => Promise<BridgeServer>;
18
+ //# sourceMappingURL=server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAkB,MAAM,IAAI,CAAC;AACrD,OAAO,EAAE,KAAK,UAAU,EAAoB,MAAM,OAAO,CAAC;AAG1D,OAAO,KAAK,EACV,qBAAqB,EACrB,qBAAqB,EACrB,gBAAgB,EAChB,eAAe,EAChB,MAAM,aAAa,CAAC;AAErB,MAAM,MAAM,mBAAmB,GAAG;IAChC,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,KAAK,EAAE,CAAC,MAAM,EAAE,gBAAgB,KAAK,IAAI,CAAC;CAC3C,GAAG,eAAe,CAAC;AAEpB,MAAM,MAAM,YAAY,GAAG;IACzB,EAAE,EAAE,eAAe,CAAC;IACpB,GAAG,EAAE,UAAU,CAAC,qBAAqB,EAAE,qBAAqB,CAAC,CAAC;IAC9D,EAAE,EAAE,CAAC,CAAC,SAAS,MAAM,kBAAkB,EACrC,KAAK,EAAE,CAAC,EACR,QAAQ,EAAE,kBAAkB,CAAC,CAAC,CAAC,KAC5B,IAAI,CAAC;IACV,IAAI,EAAE,CAAC,CAAC,SAAS,MAAM,kBAAkB,EACvC,KAAK,EAAE,CAAC,EACR,QAAQ,EAAE,kBAAkB,CAAC,CAAC,CAAC,KAC5B,IAAI,CAAC;IACV,GAAG,EAAE,CAAC,CAAC,SAAS,MAAM,kBAAkB,EACtC,KAAK,EAAE,CAAC,EACR,QAAQ,EAAE,kBAAkB,CAAC,CAAC,CAAC,KAC5B,IAAI,CAAC;CACX,CAAC;AAEF,eAAO,MAAM,eAAe,GAAU,WAEnC,mBAAmB,KAAG,OAAO,CAAC,YAAY,CAoE5C,CAAC"}
package/dist/server.js ADDED
@@ -0,0 +1,64 @@
1
+ import { WebSocketServer } from 'ws';
2
+ import { createBirpcGroup } from 'birpc';
3
+ import { logger } from '@react-native-harness/tools';
4
+ import { EventEmitter } from 'node:events';
5
+ export const getBridgeServer = async ({ port, }) => {
6
+ const wss = await new Promise((resolve) => {
7
+ const server = new WebSocketServer({ port, host: '0.0.0.0' }, () => {
8
+ resolve(server);
9
+ });
10
+ });
11
+ const emitter = new EventEmitter();
12
+ const clients = new Set();
13
+ const group = createBirpcGroup({
14
+ reportReady: (device) => {
15
+ emitter.emit('ready', device);
16
+ },
17
+ emitEvent: (event, data) => {
18
+ emitter.emit(event, data);
19
+ },
20
+ }, []);
21
+ wss.on('connection', (ws) => {
22
+ logger.debug('Client connected to the bridge');
23
+ ws.on('close', () => {
24
+ logger.debug('Client disconnected from the bridge');
25
+ // TODO: Remove channel when connection is closed.
26
+ clients.delete(ws);
27
+ });
28
+ group.updateChannels((channels) => {
29
+ channels.push({
30
+ post: (data) => ws.send(data),
31
+ on: (handler) => {
32
+ ws.on('message', (event) => {
33
+ const message = event.toString();
34
+ handler(message);
35
+ });
36
+ },
37
+ serialize: (data) => {
38
+ if (data.e) {
39
+ // Serialize error by hand (include message, stack and cause).
40
+ return JSON.stringify({
41
+ ...data,
42
+ e: {
43
+ ...data.e,
44
+ name: data.e.name,
45
+ message: data.e.message,
46
+ stack: data.e.stack,
47
+ cause: data.e.cause,
48
+ },
49
+ });
50
+ }
51
+ return JSON.stringify(data);
52
+ },
53
+ deserialize: JSON.parse,
54
+ });
55
+ });
56
+ });
57
+ return {
58
+ ws: wss,
59
+ rpc: group,
60
+ on: emitter.on.bind(emitter),
61
+ once: emitter.once.bind(emitter),
62
+ off: emitter.off.bind(emitter),
63
+ };
64
+ };
@@ -0,0 +1,35 @@
1
+ export type TestStatus = 'active' | 'skipped' | 'todo';
2
+ export type TestFn = () => void | Promise<void>;
3
+ export type TestCase = {
4
+ name: string;
5
+ fn: TestFn;
6
+ status: TestStatus;
7
+ };
8
+ export type TestSuite = {
9
+ name: string;
10
+ tests: TestCase[];
11
+ suites: TestSuite[];
12
+ parent?: TestSuite;
13
+ beforeAll: TestFn[];
14
+ afterAll: TestFn[];
15
+ beforeEach: TestFn[];
16
+ afterEach: TestFn[];
17
+ status?: TestStatus;
18
+ _hasFocused?: boolean;
19
+ };
20
+ export type CollectionResult = {
21
+ testSuite: TestSuite;
22
+ /** Number of tests that will actually be executed (excludes skipped and todo tests) */
23
+ totalTests: number;
24
+ };
25
+ export type TestCollectionStartedEvent = {
26
+ type: 'collection-started';
27
+ file: string;
28
+ };
29
+ export type TestCollectionFinishedEvent = {
30
+ type: 'collection-finished';
31
+ file: string;
32
+ duration: number;
33
+ };
34
+ export type TestCollectorEvents = TestCollectionStartedEvent | TestCollectionFinishedEvent;
35
+ //# sourceMappingURL=test-collector.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test-collector.d.ts","sourceRoot":"","sources":["../../src/shared/test-collector.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,UAAU,GAAG,QAAQ,GAAG,SAAS,GAAG,MAAM,CAAC;AAEvD,MAAM,MAAM,MAAM,GAAG,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;AAEhD,MAAM,MAAM,QAAQ,GAAG;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,UAAU,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,SAAS,GAAG;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,QAAQ,EAAE,CAAC;IAClB,MAAM,EAAE,SAAS,EAAE,CAAC;IACpB,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,MAAM,CAAC,EAAE,UAAU,CAAC;IACpB,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,SAAS,EAAE,SAAS,CAAC;IACrB,uFAAuF;IACvF,UAAU,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,0BAA0B,GAAG;IACvC,IAAI,EAAE,oBAAoB,CAAC;IAC3B,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,MAAM,MAAM,2BAA2B,GAAG;IACxC,IAAI,EAAE,qBAAqB,CAAC;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAC3B,0BAA0B,GAC1B,2BAA2B,CAAC"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,59 @@
1
+ export type TestResultStatus = 'passed' | 'failed' | 'skipped' | 'todo';
2
+ export type SerializedError = {
3
+ name: string;
4
+ message: string;
5
+ stack?: string;
6
+ };
7
+ export type TestRunnerFileStartedEvent = {
8
+ type: 'file-started';
9
+ file: string;
10
+ };
11
+ export type TestRunnerFileFinishedEvent = {
12
+ type: 'file-finished';
13
+ file: string;
14
+ duration: number;
15
+ };
16
+ export type TestRunnerSuiteStartedEvent = {
17
+ type: 'suite-started';
18
+ name: string;
19
+ file: string;
20
+ };
21
+ export type TestRunnerTestStartedEvent = {
22
+ type: 'test-started';
23
+ name: string;
24
+ suite: string;
25
+ file: string;
26
+ };
27
+ export type TestRunnerTestFinishedEvent = {
28
+ type: 'test-finished';
29
+ name: string;
30
+ suite: string;
31
+ file: string;
32
+ duration: number;
33
+ error?: SerializedError;
34
+ status: TestResultStatus;
35
+ };
36
+ export type TestRunnerSuiteFinishedEvent = {
37
+ type: 'suite-finished';
38
+ name: string;
39
+ file: string;
40
+ duration: number;
41
+ error?: SerializedError;
42
+ status: TestResultStatus;
43
+ };
44
+ export type TestRunnerEvents = TestRunnerFileStartedEvent | TestRunnerFileFinishedEvent | TestRunnerTestStartedEvent | TestRunnerTestFinishedEvent | TestRunnerSuiteStartedEvent | TestRunnerSuiteFinishedEvent;
45
+ export type TestResult = {
46
+ name: string;
47
+ status: TestResultStatus;
48
+ error?: SerializedError;
49
+ duration: number;
50
+ };
51
+ export type TestSuiteResult = {
52
+ name: string;
53
+ tests: TestResult[];
54
+ suites: TestSuiteResult[];
55
+ status: TestResultStatus;
56
+ error?: SerializedError;
57
+ duration: number;
58
+ };
59
+ //# sourceMappingURL=test-runner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test-runner.d.ts","sourceRoot":"","sources":["../../src/shared/test-runner.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,gBAAgB,GAAG,QAAQ,GAAG,QAAQ,GAAG,SAAS,GAAG,MAAM,CAAC;AAExE,MAAM,MAAM,eAAe,GAAG;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,0BAA0B,GAAG;IACvC,IAAI,EAAE,cAAc,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,MAAM,MAAM,2BAA2B,GAAG;IACxC,IAAI,EAAE,eAAe,CAAC;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,2BAA2B,GAAG;IACxC,IAAI,EAAE,eAAe,CAAC;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,MAAM,MAAM,0BAA0B,GAAG;IACvC,IAAI,EAAE,cAAc,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,MAAM,MAAM,2BAA2B,GAAG;IACxC,IAAI,EAAE,eAAe,CAAC;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,eAAe,CAAC;IACxB,MAAM,EAAE,gBAAgB,CAAC;CAC1B,CAAC;AAEF,MAAM,MAAM,4BAA4B,GAAG;IACzC,IAAI,EAAE,gBAAgB,CAAC;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,eAAe,CAAC;IACxB,MAAM,EAAE,gBAAgB,CAAC;CAC1B,CAAC;AAEF,MAAM,MAAM,gBAAgB,GACxB,0BAA0B,GAC1B,2BAA2B,GAC3B,0BAA0B,GAC1B,2BAA2B,GAC3B,2BAA2B,GAC3B,4BAA4B,CAAC;AAEjC,MAAM,MAAM,UAAU,GAAG;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,gBAAgB,CAAC;IACzB,KAAK,CAAC,EAAE,eAAe,CAAC;IACxB,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,UAAU,EAAE,CAAC;IACpB,MAAM,EAAE,eAAe,EAAE,CAAC;IAC1B,MAAM,EAAE,gBAAgB,CAAC;IACzB,KAAK,CAAC,EAAE,eAAe,CAAC;IACxB,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,24 @@
1
+ import type { TestRunnerEvents, TestSuiteResult } from './shared/test-runner.js';
2
+ import type { TestCollectorEvents } from './shared/test-collector.js';
3
+ export type { TestCollectorEvents, TestCollectionStartedEvent, TestCollectionFinishedEvent, TestSuite, TestCase, CollectionResult, } from './shared/test-collector.js';
4
+ export type { TestRunnerEvents, TestRunnerFileStartedEvent, TestRunnerFileFinishedEvent, TestRunnerSuiteStartedEvent, TestRunnerTestStartedEvent, TestRunnerTestFinishedEvent, TestRunnerSuiteFinishedEvent, TestSuiteResult, TestResult, TestResultStatus, SerializedError, } from './shared/test-runner.js';
5
+ export type DeviceDescriptor = {
6
+ platform: 'ios' | 'android';
7
+ manufacturer: string;
8
+ model: string;
9
+ osVersion: string;
10
+ };
11
+ export type BridgeEvents = TestCollectorEvents | TestRunnerEvents;
12
+ export type BridgeEventsMap = {
13
+ [K in BridgeEvents['type']]: (event: Extract<BridgeEvents, {
14
+ type: K;
15
+ }>) => void;
16
+ };
17
+ export type BridgeClientFunctions = {
18
+ runTests: (path: string) => Promise<TestSuiteResult>;
19
+ };
20
+ export type BridgeServerFunctions = {
21
+ reportReady: (device: DeviceDescriptor) => void;
22
+ emitEvent: <TEvent extends BridgeEvents>(event: TEvent['type'], data: TEvent) => void;
23
+ };
24
+ //# sourceMappingURL=shared.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shared.d.ts","sourceRoot":"","sources":["../src/shared.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,gBAAgB,EAChB,eAAe,EAChB,MAAM,yBAAyB,CAAC;AACjC,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AAEtE,YAAY,EACV,mBAAmB,EACnB,0BAA0B,EAC1B,2BAA2B,EAC3B,SAAS,EACT,QAAQ,EACR,gBAAgB,GACjB,MAAM,4BAA4B,CAAC;AACpC,YAAY,EACV,gBAAgB,EAChB,0BAA0B,EAC1B,2BAA2B,EAC3B,2BAA2B,EAC3B,0BAA0B,EAC1B,2BAA2B,EAC3B,4BAA4B,EAC5B,eAAe,EACf,UAAU,EACV,gBAAgB,EAChB,eAAe,GAChB,MAAM,yBAAyB,CAAC;AAEjC,MAAM,MAAM,gBAAgB,GAAG;IAC7B,QAAQ,EAAE,KAAK,GAAG,SAAS,CAAC;IAC5B,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG,mBAAmB,GAAG,gBAAgB,CAAC;AAElE,MAAM,MAAM,eAAe,GAAG;KAC3B,CAAC,IAAI,YAAY,CAAC,MAAM,CAAC,GAAG,CAC3B,KAAK,EAAE,OAAO,CAAC,YAAY,EAAE;QAAE,IAAI,EAAE,CAAC,CAAA;KAAE,CAAC,KACtC,IAAI;CACV,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAAG;IAClC,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,eAAe,CAAC,CAAC;CACtD,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAAG;IAClC,WAAW,EAAE,CAAC,MAAM,EAAE,gBAAgB,KAAK,IAAI,CAAC;IAChD,SAAS,EAAE,CAAC,MAAM,SAAS,YAAY,EACrC,KAAK,EAAE,MAAM,CAAC,MAAM,CAAC,EACrB,IAAI,EAAE,MAAM,KACT,IAAI,CAAC;CACX,CAAC"}
package/dist/shared.js ADDED
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ {"fileNames":["../../../node_modules/typescript/lib/lib.es5.d.ts","../../../node_modules/typescript/lib/lib.es2015.d.ts","../../../node_modules/typescript/lib/lib.es2016.d.ts","../../../node_modules/typescript/lib/lib.es2017.d.ts","../../../node_modules/typescript/lib/lib.es2018.d.ts","../../../node_modules/typescript/lib/lib.es2019.d.ts","../../../node_modules/typescript/lib/lib.es2020.d.ts","../../../node_modules/typescript/lib/lib.dom.d.ts","../../../node_modules/typescript/lib/lib.es2015.core.d.ts","../../../node_modules/typescript/lib/lib.es2015.collection.d.ts","../../../node_modules/typescript/lib/lib.es2015.generator.d.ts","../../../node_modules/typescript/lib/lib.es2015.iterable.d.ts","../../../node_modules/typescript/lib/lib.es2015.promise.d.ts","../../../node_modules/typescript/lib/lib.es2015.proxy.d.ts","../../../node_modules/typescript/lib/lib.es2015.reflect.d.ts","../../../node_modules/typescript/lib/lib.es2015.symbol.d.ts","../../../node_modules/typescript/lib/lib.es2015.symbol.wellknown.d.ts","../../../node_modules/typescript/lib/lib.es2016.array.include.d.ts","../../../node_modules/typescript/lib/lib.es2016.intl.d.ts","../../../node_modules/typescript/lib/lib.es2017.arraybuffer.d.ts","../../../node_modules/typescript/lib/lib.es2017.date.d.ts","../../../node_modules/typescript/lib/lib.es2017.object.d.ts","../../../node_modules/typescript/lib/lib.es2017.sharedmemory.d.ts","../../../node_modules/typescript/lib/lib.es2017.string.d.ts","../../../node_modules/typescript/lib/lib.es2017.intl.d.ts","../../../node_modules/typescript/lib/lib.es2017.typedarrays.d.ts","../../../node_modules/typescript/lib/lib.es2018.asyncgenerator.d.ts","../../../node_modules/typescript/lib/lib.es2018.asynciterable.d.ts","../../../node_modules/typescript/lib/lib.es2018.intl.d.ts","../../../node_modules/typescript/lib/lib.es2018.promise.d.ts","../../../node_modules/typescript/lib/lib.es2018.regexp.d.ts","../../../node_modules/typescript/lib/lib.es2019.array.d.ts","../../../node_modules/typescript/lib/lib.es2019.object.d.ts","../../../node_modules/typescript/lib/lib.es2019.string.d.ts","../../../node_modules/typescript/lib/lib.es2019.symbol.d.ts","../../../node_modules/typescript/lib/lib.es2019.intl.d.ts","../../../node_modules/typescript/lib/lib.es2020.bigint.d.ts","../../../node_modules/typescript/lib/lib.es2020.date.d.ts","../../../node_modules/typescript/lib/lib.es2020.promise.d.ts","../../../node_modules/typescript/lib/lib.es2020.sharedmemory.d.ts","../../../node_modules/typescript/lib/lib.es2020.string.d.ts","../../../node_modules/typescript/lib/lib.es2020.symbol.wellknown.d.ts","../../../node_modules/typescript/lib/lib.es2020.intl.d.ts","../../../node_modules/typescript/lib/lib.es2020.number.d.ts","../../../node_modules/typescript/lib/lib.esnext.intl.d.ts","../../../node_modules/typescript/lib/lib.decorators.d.ts","../../../node_modules/typescript/lib/lib.decorators.legacy.d.ts","../../../node_modules/tslib/tslib.d.ts","../../../node_modules/tslib/modules/index.d.ts","../../../node_modules/partysocket/ws.d.ts","../../../node_modules/partysocket/index.d.ts","../../../node_modules/birpc/dist/index.d.ts","../src/shared/test-runner.ts","../src/shared/test-collector.ts","../src/shared.ts","../src/client.ts","../src/index.ts","../../../node_modules/@types/node/assert.d.ts","../../../node_modules/@types/node/assert/strict.d.ts","../../../node_modules/@types/node/globals.d.ts","../../../node_modules/@types/node/async_hooks.d.ts","../../../node_modules/@types/node/buffer.d.ts","../../../node_modules/@types/node/child_process.d.ts","../../../node_modules/@types/node/cluster.d.ts","../../../node_modules/@types/node/console.d.ts","../../../node_modules/@types/node/constants.d.ts","../../../node_modules/@types/node/crypto.d.ts","../../../node_modules/@types/node/dgram.d.ts","../../../node_modules/@types/node/diagnostics_channel.d.ts","../../../node_modules/@types/node/dns.d.ts","../../../node_modules/@types/node/dns/promises.d.ts","../../../node_modules/@types/node/domain.d.ts","../../../node_modules/@types/node/dom-events.d.ts","../../../node_modules/@types/node/events.d.ts","../../../node_modules/@types/node/fs.d.ts","../../../node_modules/@types/node/fs/promises.d.ts","../../../node_modules/@types/node/http.d.ts","../../../node_modules/@types/node/http2.d.ts","../../../node_modules/@types/node/https.d.ts","../../../node_modules/@types/node/inspector.d.ts","../../../node_modules/@types/node/module.d.ts","../../../node_modules/@types/node/net.d.ts","../../../node_modules/@types/node/os.d.ts","../../../node_modules/@types/node/path.d.ts","../../../node_modules/@types/node/perf_hooks.d.ts","../../../node_modules/@types/node/process.d.ts","../../../node_modules/@types/node/punycode.d.ts","../../../node_modules/@types/node/querystring.d.ts","../../../node_modules/@types/node/readline.d.ts","../../../node_modules/@types/node/readline/promises.d.ts","../../../node_modules/@types/node/repl.d.ts","../../../node_modules/@types/node/stream.d.ts","../../../node_modules/@types/node/stream/promises.d.ts","../../../node_modules/@types/node/stream/consumers.d.ts","../../../node_modules/@types/node/stream/web.d.ts","../../../node_modules/@types/node/string_decoder.d.ts","../../../node_modules/@types/node/test.d.ts","../../../node_modules/@types/node/timers.d.ts","../../../node_modules/@types/node/timers/promises.d.ts","../../../node_modules/@types/node/tls.d.ts","../../../node_modules/@types/node/trace_events.d.ts","../../../node_modules/@types/node/tty.d.ts","../../../node_modules/@types/node/url.d.ts","../../../node_modules/@types/node/util.d.ts","../../../node_modules/@types/node/v8.d.ts","../../../node_modules/@types/node/vm.d.ts","../../../node_modules/@types/node/wasi.d.ts","../../../node_modules/@types/node/worker_threads.d.ts","../../../node_modules/@types/node/zlib.d.ts","../../../node_modules/@types/node/globals.global.d.ts","../../../node_modules/@types/node/index.d.ts","../../../node_modules/@types/ws/index.d.mts","../../tools/dist/abort.d.ts","../../../node_modules/picocolors/types.d.ts","../../../node_modules/picocolors/picocolors.d.ts","../../tools/dist/color.d.ts","../../tools/dist/logger.d.ts","../../../node_modules/@clack/core/dist/index.d.mts","../../../node_modules/@clack/prompts/dist/index.d.mts","../../tools/dist/prompts.d.ts","../../../node_modules/nano-spawn/source/index.d.ts","../../tools/dist/spawn.d.ts","../../tools/dist/react-native.d.ts","../../tools/dist/index.d.ts","../src/server.ts"],"fileIdsList":[[89,92,104],[92,104,118],[58,104],[61,104],[62,67,95,104],[63,74,75,82,92,103,104],[63,64,74,82,104],[65,104],[66,67,75,83,104],[67,92,100,104],[68,70,74,82,104],[69,104],[70,71,104],[74,104],[72,74,104],[74,75,76,92,103,104],[74,75,76,89,92,95,104],[104,108],[104],[70,74,77,82,92,103,104],[74,75,77,78,82,92,100,103,104],[77,79,92,100,103,104],[58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110],[74,80,104],[81,103,104],[70,74,82,92,104],[83,104],[84,104],[61,85,104],[86,102,104,108],[87,104],[88,104],[74,89,90,104],[89,91,104,106],[62,74,92,93,94,95,104],[62,92,94,104],[92,93,104],[95,104],[96,104],[74,98,99,104],[98,99,104],[67,82,92,100,104],[101,104],[82,102,104],[62,77,88,103,104],[67,104],[92,104,105],[104,106],[104,107],[62,67,74,76,85,92,103,104,106,108],[92,104,109],[74,77,79,82,92,100,103,104,109,111],[63,104],[50,104],[104,114],[48,104],[49,51,52,55,104],[49,55,104],[49,52,55,74,104,112,124],[49,53,54,104],[49,104],[104,115],[104,113,116,117,120,122,123],[104,119],[104,121]],"fileInfos":[{"version":"69684132aeb9b5642cbcd9e22dff7818ff0ee1aa831728af0ecf97d3364d5546","affectsGlobalScope":true,"impliedFormat":1},{"version":"45b7ab580deca34ae9729e97c13cfd999df04416a79116c3bfb483804f85ded4","impliedFormat":1},{"version":"3facaf05f0c5fc569c5649dd359892c98a85557e3e0c847964caeb67076f4d75","impliedFormat":1},{"version":"e44bb8bbac7f10ecc786703fe0a6a4b952189f908707980ba8f3c8975a760962","impliedFormat":1},{"version":"5e1c4c362065a6b95ff952c0eab010f04dcd2c3494e813b493ecfd4fcb9fc0d8","impliedFormat":1},{"version":"68d73b4a11549f9c0b7d352d10e91e5dca8faa3322bfb77b661839c42b1ddec7","impliedFormat":1},{"version":"5efce4fc3c29ea84e8928f97adec086e3dc876365e0982cc8479a07954a3efd4","impliedFormat":1},{"version":"092c2bfe125ce69dbb1223c85d68d4d2397d7d8411867b5cc03cec902c233763","affectsGlobalScope":true,"impliedFormat":1},{"version":"c57796738e7f83dbc4b8e65132f11a377649c00dd3eee333f672b8f0a6bea671","affectsGlobalScope":true,"impliedFormat":1},{"version":"dc2df20b1bcdc8c2d34af4926e2c3ab15ffe1160a63e58b7e09833f616efff44","affectsGlobalScope":true,"impliedFormat":1},{"version":"515d0b7b9bea2e31ea4ec968e9edd2c39d3eebf4a2d5cbd04e88639819ae3b71","affectsGlobalScope":true,"impliedFormat":1},{"version":"0559b1f683ac7505ae451f9a96ce4c3c92bdc71411651ca6ddb0e88baaaad6a3","affectsGlobalScope":true,"impliedFormat":1},{"version":"0dc1e7ceda9b8b9b455c3a2d67b0412feab00bd2f66656cd8850e8831b08b537","affectsGlobalScope":true,"impliedFormat":1},{"version":"ce691fb9e5c64efb9547083e4a34091bcbe5bdb41027e310ebba8f7d96a98671","affectsGlobalScope":true,"impliedFormat":1},{"version":"8d697a2a929a5fcb38b7a65594020fcef05ec1630804a33748829c5ff53640d0","affectsGlobalScope":true,"impliedFormat":1},{"version":"4ff2a353abf8a80ee399af572debb8faab2d33ad38c4b4474cff7f26e7653b8d","affectsGlobalScope":true,"impliedFormat":1},{"version":"936e80ad36a2ee83fc3caf008e7c4c5afe45b3cf3d5c24408f039c1d47bdc1df","affectsGlobalScope":true,"impliedFormat":1},{"version":"d15bea3d62cbbdb9797079416b8ac375ae99162a7fba5de2c6c505446486ac0a","affectsGlobalScope":true,"impliedFormat":1},{"version":"68d18b664c9d32a7336a70235958b8997ebc1c3b8505f4f1ae2b7e7753b87618","affectsGlobalScope":true,"impliedFormat":1},{"version":"eb3d66c8327153d8fa7dd03f9c58d351107fe824c79e9b56b462935176cdf12a","affectsGlobalScope":true,"impliedFormat":1},{"version":"38f0219c9e23c915ef9790ab1d680440d95419ad264816fa15009a8851e79119","affectsGlobalScope":true,"impliedFormat":1},{"version":"69ab18c3b76cd9b1be3d188eaf8bba06112ebbe2f47f6c322b5105a6fbc45a2e","affectsGlobalScope":true,"impliedFormat":1},{"version":"fef8cfad2e2dc5f5b3d97a6f4f2e92848eb1b88e897bb7318cef0e2820bceaab","affectsGlobalScope":true,"impliedFormat":1},{"version":"2f11ff796926e0832f9ae148008138ad583bd181899ab7dd768a2666700b1893","affectsGlobalScope":true,"impliedFormat":1},{"version":"4de680d5bb41c17f7f68e0419412ca23c98d5749dcaaea1896172f06435891fc","affectsGlobalScope":true,"impliedFormat":1},{"version":"954296b30da6d508a104a3a0b5d96b76495c709785c1d11610908e63481ee667","affectsGlobalScope":true,"impliedFormat":1},{"version":"ac9538681b19688c8eae65811b329d3744af679e0bdfa5d842d0e32524c73e1c","affectsGlobalScope":true,"impliedFormat":1},{"version":"0a969edff4bd52585473d24995c5ef223f6652d6ef46193309b3921d65dd4376","affectsGlobalScope":true,"impliedFormat":1},{"version":"9e9fbd7030c440b33d021da145d3232984c8bb7916f277e8ffd3dc2e3eae2bdb","affectsGlobalScope":true,"impliedFormat":1},{"version":"811ec78f7fefcabbda4bfa93b3eb67d9ae166ef95f9bff989d964061cbf81a0c","affectsGlobalScope":true,"impliedFormat":1},{"version":"717937616a17072082152a2ef351cb51f98802fb4b2fdabd32399843875974ca","affectsGlobalScope":true,"impliedFormat":1},{"version":"d7e7d9b7b50e5f22c915b525acc5a49a7a6584cf8f62d0569e557c5cfc4b2ac2","affectsGlobalScope":true,"impliedFormat":1},{"version":"71c37f4c9543f31dfced6c7840e068c5a5aacb7b89111a4364b1d5276b852557","affectsGlobalScope":true,"impliedFormat":1},{"version":"576711e016cf4f1804676043e6a0a5414252560eb57de9faceee34d79798c850","affectsGlobalScope":true,"impliedFormat":1},{"version":"89c1b1281ba7b8a96efc676b11b264de7a8374c5ea1e6617f11880a13fc56dc6","affectsGlobalScope":true,"impliedFormat":1},{"version":"74f7fa2d027d5b33eb0471c8e82a6c87216223181ec31247c357a3e8e2fddc5b","affectsGlobalScope":true,"impliedFormat":1},{"version":"d6d7ae4d1f1f3772e2a3cde568ed08991a8ae34a080ff1151af28b7f798e22ca","affectsGlobalScope":true,"impliedFormat":1},{"version":"063600664504610fe3e99b717a1223f8b1900087fab0b4cad1496a114744f8df","affectsGlobalScope":true,"impliedFormat":1},{"version":"934019d7e3c81950f9a8426d093458b65d5aff2c7c1511233c0fd5b941e608ab","affectsGlobalScope":true,"impliedFormat":1},{"version":"52ada8e0b6e0482b728070b7639ee42e83a9b1c22d205992756fe020fd9f4a47","affectsGlobalScope":true,"impliedFormat":1},{"version":"3bdefe1bfd4d6dee0e26f928f93ccc128f1b64d5d501ff4a8cf3c6371200e5e6","affectsGlobalScope":true,"impliedFormat":1},{"version":"59fb2c069260b4ba00b5643b907ef5d5341b167e7d1dbf58dfd895658bda2867","affectsGlobalScope":true,"impliedFormat":1},{"version":"639e512c0dfc3fad96a84caad71b8834d66329a1f28dc95e3946c9b58176c73a","affectsGlobalScope":true,"impliedFormat":1},{"version":"368af93f74c9c932edd84c58883e736c9e3d53cec1fe24c0b0ff451f529ceab1","affectsGlobalScope":true,"impliedFormat":1},{"version":"811c71eee4aa0ac5f7adf713323a5c41b0cf6c4e17367a34fbce379e12bbf0a4","affectsGlobalScope":true,"impliedFormat":1},{"version":"8e7f8264d0fb4c5339605a15daadb037bf238c10b654bb3eee14208f860a32ea","affectsGlobalScope":true,"impliedFormat":1},{"version":"782dec38049b92d4e85c1585fbea5474a219c6984a35b004963b00beb1aab538","affectsGlobalScope":true,"impliedFormat":1},{"version":"a6a5253138c5432c68a1510c70fe78a644fe2e632111ba778e1978010d6edfec","impliedFormat":1},{"version":"b8f34dd1757f68e03262b1ca3ddfa668a855b872f8bdd5224d6f993a7b37dc2c","impliedFormat":99},{"version":"269658e7a0ee3ddc32320370f336fc6a51232f42f06e7f703d18aca6aeed8bfc","impliedFormat":1},{"version":"7c2fbbc70bc773f521aa8fa216186f7b73ea0faa4cbff2a88f7385fd4953f461","impliedFormat":1},{"version":"f2ee9c0f4e3e40fa79743b5bad3d085d41cf6854c68687737c00d3f6d0ed7941","impliedFormat":99},{"version":"4457df3f99740d38767d2842cb6df8eb684a129f0cbff5e5f0cfe092993c49c4","signature":"be389ee0d0f5e70329ea4c2fb44b7716e7ceda3680fa0ee32c22329ef8ef7e60","impliedFormat":99},{"version":"c7e2f93c8dc02ea5819fef27dd724c64090276077c56de6fba18ab923b060b80","signature":"402ac3b4c96c5718d18c00339c6e4c66ff0b1a0d8a166570107472342fd57e7a","impliedFormat":99},{"version":"1fc644692defa56153623d6fbdfac66a78e209fb8c4804af1184d163f02784fe","signature":"0df9e64851cbe9801f868551cae57fffd2d4339ac98b4d6ff00aad10a5cd8f33","impliedFormat":99},{"version":"a07f6f12820ee781272ed2752c92fd3d316d8d5f381e365495ebe755fe25214e","signature":"b49462226b8bfbdbc25c8aa2a294d2052e9b273f39a094044492854dd6a7b515","impliedFormat":99},{"version":"a955c49e9dc38915d1a9860dc049a3b5fa46cb4e9b832ebcde89d96d6e68b8e3","impliedFormat":99},{"version":"7e771891adaa85b690266bc37bd6eb43bc57eecc4b54693ead36467e7369952a","impliedFormat":1},{"version":"a69c09dbea52352f479d3e7ac949fde3d17b195abe90b045d619f747b38d6d1a","impliedFormat":1},{"version":"f749812878fecfa53cfc13b36e5d35086fb6377983a9df44175da83ccc23af1f","affectsGlobalScope":true,"impliedFormat":1},{"version":"7d2e3fea24c712c99c03ad8f556abedbfe105f87f1be10b95dbd409d24bc05a3","impliedFormat":1},{"version":"211e3f15fbced4ab4be19f49ffa990b9ff20d749d33b65ff753be691e7616239","affectsGlobalScope":true,"impliedFormat":1},{"version":"3719525a8f6ab731e3dfd585d9f87df55ec7d50d461df84f74eb4d68bb165244","impliedFormat":1},{"version":"5a94487653355b56018122d92392beb2e5f4a6c63ba5cef83bbe1c99775ef713","impliedFormat":1},{"version":"d5135ad93b33adcce80b18f8065087934cdc1730d63db58562edcf017e1aad9b","affectsGlobalScope":true,"impliedFormat":1},{"version":"82408ed3e959ddc60d3e9904481b5a8dc16469928257af22a3f7d1a3bc7fd8c4","impliedFormat":1},{"version":"e596c9bb2f29a2699fdd4ae89139612652245192f67f45617c5a4b20832aaae9","impliedFormat":1},{"version":"bb9c4ffa5e6290c6980b63c815cdd1625876dadb2efaf77edbe82984be93e55e","impliedFormat":1},{"version":"1cdcfc1f624d6c08aa12c73935f6e13f095919cd99edf95752951796eb225729","impliedFormat":1},{"version":"4eaff3d8e10676fd7913d8c108890e71c688e1e7d52f6d1d55c39514f493dc47","impliedFormat":1},{"version":"14b5aa23c5d0ae1907bc696ac7b6915d88f7d85799cc0dc2dcf98fbce2c5a67c","impliedFormat":1},{"version":"5c439dafdc09abe4d6c260a96b822fa0ba5be7203c71a63ab1f1423cd9e838ea","impliedFormat":1},{"version":"6b526a5ec4a401ca7c26cfe6a48e641d8f30af76673bad3b06a1b4504594a960","affectsGlobalScope":true,"impliedFormat":1},{"version":"00dee7cdca8b8420c47ea4a31a34b8e8294013ebc4f463fd941e867e7bf05029","affectsGlobalScope":true,"impliedFormat":1},{"version":"3256f3cccd578f9e7fe3a28096c505634bebcee8afb738ffa99368e536ca3a0b","impliedFormat":1},{"version":"1c84b46267610a34028edfd0d035509341751262bac1062857f3c8df7aff7153","impliedFormat":1},{"version":"7f138842074d0a40681775af008c8452093b68c383c94de31759e853c6d06b5c","impliedFormat":1},{"version":"a3d541d303ee505053f5dcbf9fafb65cac3d5631037501cd616195863a6c5740","impliedFormat":1},{"version":"8d3c583a07e0c37e876908c2d5da575019f689df8d9fa4c081d99119d53dba22","impliedFormat":1},{"version":"2c828a5405191d006115ab34e191b8474bc6c86ffdc401d1a9864b1b6e088a58","impliedFormat":1},{"version":"e630e5528e899219ae319e83bef54bf3bcb91b01d76861ecf881e8e614b167f0","affectsGlobalScope":true,"impliedFormat":1},{"version":"bcebb922784739bdb34c18ee51095d25a92b560c78ccd2eaacd6bd00f7443d83","impliedFormat":1},{"version":"7ee6ed878c4528215c82b664fe0cfe80e8b4da6c0d4cc80869367868774db8b1","impliedFormat":1},{"version":"b0973c3cbcdc59b37bf477731d468696ecaf442593ec51bab497a613a580fe30","impliedFormat":1},{"version":"4989e92ba5b69b182d2caaea6295af52b7dc73a4f7a2e336a676722884e7139d","affectsGlobalScope":true,"impliedFormat":1},{"version":"0715e4cd28ad471b2a93f3e552ff51a3ae423417a01a10aa1d3bc7c6b95059d6","affectsGlobalScope":true,"impliedFormat":1},{"version":"5153a2fd150e46ce57bb3f8db1318d33f6ad3261ed70ceeff92281c0608c74a3","impliedFormat":1},{"version":"210d54cd652ec0fec8c8916e4af59bb341065576ecda039842f9ffb2e908507c","impliedFormat":1},{"version":"36b03690b628eab08703d63f04eaa89c5df202e5f1edf3989f13ad389cd2c091","impliedFormat":1},{"version":"0effadd232a20498b11308058e334d3339cc5bf8c4c858393e38d9d4c0013dcf","impliedFormat":1},{"version":"25846d43937c672bab7e8195f3d881f93495df712ee901860effc109918938cc","impliedFormat":1},{"version":"4f3fdeba4e28e21aa719c081b8dc8f91d47e12e773389b9d35679c08151c9d37","impliedFormat":1},{"version":"1b952304137851e45bc009785de89ada562d9376177c97e37702e39e60c2f1ff","impliedFormat":1},{"version":"69ee23dd0d215b09907ad30d23f88b7790c93329d1faf31d7835552a10cf7cbf","impliedFormat":1},{"version":"44b8b584a338b190a59f4f6929d072431950c7bd92ec2694821c11bce180c8a5","impliedFormat":1},{"version":"23b89798789dffbd437c0c423f5d02d11f9736aea73d6abf16db4f812ff36eda","impliedFormat":1},{"version":"f69ff39996a61a0dd10f4bce73272b52e8024a4d58b13ab32bf4712909d0a2b7","impliedFormat":1},{"version":"3c4ba1dd9b12ffa284b565063108f2f031d150ea15b8fafbdc17f5d2a07251f3","affectsGlobalScope":true,"impliedFormat":1},{"version":"e10177274a35a9d07c825615340b2fcde2f610f53f3fb40269fd196b4288dda6","impliedFormat":1},{"version":"1422cd9e705adcc09088fda85a900c2b70e3ad36ea85846f68bd1a884cdf4e2b","impliedFormat":1},{"version":"3c13ef48634e7b5012fcf7e8fce7496352c2d779a7201389ca96a2a81ee4314d","impliedFormat":1},{"version":"5d0a25ec910fa36595f85a67ac992d7a53dd4064a1ba6aea1c9f14ab73a023f2","impliedFormat":1},{"version":"a73ae8c0e62103bb9e21bb6538700881bf135b9a8b125b857ec68edfa0da4ed3","affectsGlobalScope":true,"impliedFormat":1},{"version":"e1c1b2fbe236bf7ee3e342eeae7e20efb8988a0ac7da1cbbfa2c1f66b76c3423","affectsGlobalScope":true,"impliedFormat":1},{"version":"868831cab82b65dfe1d68180e898af1f2101e89ba9b754d1db6fb8cc2fac1921","impliedFormat":1},{"version":"0fe8985a28f82c450a04a6edf1279d7181c0893f37da7d2a27f8efd4fd5edb03","impliedFormat":1},{"version":"e59a892d87e72733e2a9ca21611b9beb52977be2696c7ba4b216cbbb9a48f5aa","impliedFormat":1},{"version":"52120bb7e4583612225bdf08e7c12559548170f11e660d33a33623bae9bbdbba","affectsGlobalScope":true,"impliedFormat":1},{"version":"8a300fa9b698845a1f9c41ecbe2c5966634582a8e2020d51abcace9b55aa959e","impliedFormat":1},{"version":"ab9b9a36e5284fd8d3bf2f7d5fcbc60052f25f27e4d20954782099282c60d23e","affectsGlobalScope":true,"impliedFormat":1},{"version":"a6dd3dba8e665ac43d279e0fdf5219edda0eed69b5e9a5061f46cd6a65c4f7a1","impliedFormat":1},{"version":"316f1486e15cbf7896425f0a16dfe12d447dd57cfb3244b8b119c77df870858f","impliedFormat":99},{"version":"3e442c402123b264ccdf7123c1366e1473d9c39f5db69373e938284fc01c49ce","impliedFormat":99},{"version":"590595c1230ebb7c43ebac51b2b2da956a719b213355b4358e2a6b16a8b5936c","impliedFormat":1},{"version":"8c5f0739f00f89f89b03a1fe6658c6d78000d7ebd7f556f0f8d6908fa679de35","impliedFormat":1},{"version":"a15c0df1ac9b2a4d833490522614fc57ae97d70a07bf4964a4d6bb73f3f56399","impliedFormat":99},{"version":"e4cead4a8596a6f051c36ef184f5fb6f117232eefdc1f98ef9847c9efc2c8911","impliedFormat":99},{"version":"e191585a6a460d89791b3d3d39a10607bbcefa7f7c9812af6ca5f11c33d398d1","impliedFormat":99},{"version":"24379e38ef6db808a7aed9b162dae44d16f84f63c04994efb8b0106bcc589909","impliedFormat":99},{"version":"8af66ec621033f41ccb2bcee775e883c2649fa0db71192fe863185b0281082a6","impliedFormat":99},{"version":"9d4af7bde3e345d3071b5fefbece2d3482971aae89ded50f302c8cb246e81581","impliedFormat":99},{"version":"f3eb748185038bca941a02994b1b0b5803c0a2ce818b8a7d72a24a6b814f5d3e","impliedFormat":99},{"version":"2ba26b5ab00dd3495eeb733cdb46d939a8eb755a395a91169158cdf962aff6c3","impliedFormat":99},{"version":"2e1c22b413f96fd388774b174588816f4bd787486ecfe74f5bcb361dd6bfce50","impliedFormat":99},{"version":"69434e84aa26b9375f0500bcbe84a6bc78f1108cc9866e993e116bc0da2fc5df","signature":"18b54e0f8a18bb6b39598a08fe20f310fe683c6e0421bd1d2cda71faeb36e630","impliedFormat":99}],"root":[[53,57],125],"options":{"composite":true,"declarationMap":true,"emitDeclarationOnly":false,"importHelpers":true,"module":199,"noEmitOnError":true,"noFallthroughCasesInSwitch":true,"noImplicitOverride":true,"noImplicitReturns":true,"noUnusedLocals":true,"outDir":"./","rootDir":"../src","skipLibCheck":true,"strict":true,"target":9,"tsBuildInfoFile":"./tsconfig.lib.tsbuildinfo"},"referencedMap":[[118,1],[119,2],[58,3],[59,3],[61,4],[62,5],[63,6],[64,7],[65,8],[66,9],[67,10],[68,11],[69,12],[70,13],[71,13],[73,14],[72,15],[74,14],[75,16],[76,17],[60,18],[110,19],[77,20],[78,21],[79,22],[111,23],[80,24],[81,25],[82,26],[83,27],[84,28],[85,29],[86,30],[87,31],[88,32],[89,33],[90,33],[91,34],[92,35],[94,36],[93,37],[95,38],[96,39],[97,19],[98,40],[99,41],[100,42],[101,43],[102,44],[103,45],[104,46],[105,47],[106,48],[107,49],[108,50],[109,51],[112,52],[52,19],[121,53],[51,54],[50,19],[115,55],[114,19],[49,56],[48,19],[46,19],[47,19],[8,19],[10,19],[9,19],[2,19],[11,19],[12,19],[13,19],[14,19],[15,19],[16,19],[17,19],[18,19],[3,19],[19,19],[20,19],[4,19],[21,19],[25,19],[22,19],[23,19],[24,19],[26,19],[27,19],[28,19],[5,19],[29,19],[30,19],[31,19],[32,19],[6,19],[36,19],[33,19],[34,19],[35,19],[37,19],[7,19],[38,19],[43,19],[44,19],[39,19],[40,19],[41,19],[42,19],[1,19],[45,19],[56,57],[57,58],[125,59],[55,60],[54,61],[53,61],[113,19],[116,62],[124,63],[117,19],[120,64],[123,19],[122,65]],"latestChangedDtsFile":"./server.d.ts","version":"5.8.3"}
@@ -0,0 +1,19 @@
1
+ import baseConfig from '../../eslint.config.mjs';
2
+
3
+ export default [
4
+ ...baseConfig,
5
+ {
6
+ files: ['**/*.json'],
7
+ rules: {
8
+ '@nx/dependency-checks': [
9
+ 'error',
10
+ {
11
+ ignoredFiles: ['{projectRoot}/eslint.config.{js,cjs,mjs,ts,cts,mts}'],
12
+ },
13
+ ],
14
+ },
15
+ languageOptions: {
16
+ parser: await import('jsonc-eslint-parser'),
17
+ },
18
+ },
19
+ ];
package/package.json ADDED
@@ -0,0 +1,39 @@
1
+ {
2
+ "name": "@react-native-harness/bridge",
3
+ "version": "1.0.0-alpha.1",
4
+ "type": "module",
5
+ "main": "./dist/index.js",
6
+ "module": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ "./package.json": "./package.json",
10
+ ".": {
11
+ "development": "./src/index.ts",
12
+ "types": "./dist/index.d.ts",
13
+ "import": "./dist/index.js",
14
+ "default": "./dist/index.js"
15
+ },
16
+ "./client": {
17
+ "development": "./src/client.ts",
18
+ "types": "./dist/client.d.ts",
19
+ "import": "./dist/client.js",
20
+ "default": "./dist/client.js"
21
+ },
22
+ "./server": {
23
+ "development": "./src/server.ts",
24
+ "types": "./dist/server.d.ts",
25
+ "import": "./dist/server.js",
26
+ "default": "./dist/server.js"
27
+ }
28
+ },
29
+ "dependencies": {
30
+ "birpc": "^2.4.0",
31
+ "partysocket": "^1.1.4",
32
+ "tslib": "^2.3.0",
33
+ "ws": "^8.18.2",
34
+ "@react-native-harness/tools": "1.0.0-alpha.1"
35
+ },
36
+ "devDependencies": {
37
+ "@types/ws": "^8.18.1"
38
+ }
39
+ }
package/src/client.ts ADDED
@@ -0,0 +1,46 @@
1
+ import { WebSocket } from 'partysocket';
2
+ import { BirpcReturn, createBirpc } from 'birpc';
3
+ import type { BridgeClientFunctions, BridgeServerFunctions } from './shared.js';
4
+
5
+ export type BridgeClient = {
6
+ rpc: BirpcReturn<BridgeServerFunctions, BridgeClientFunctions>;
7
+ disconnect: () => void;
8
+ };
9
+
10
+ const getBridgeClient = async (
11
+ url: string,
12
+ handlers: BridgeClientFunctions
13
+ ): Promise<BridgeClient> => {
14
+ return new Promise((resolve) => {
15
+ const ws = new WebSocket(url);
16
+
17
+ const handleOpen = () => {
18
+ const rpc = createBirpc<BridgeServerFunctions, BridgeClientFunctions>(
19
+ handlers,
20
+ {
21
+ post: (data) => ws.send(data),
22
+ on: (handler) => {
23
+ ws.addEventListener('message', (event: any) => {
24
+ handler(event.data);
25
+ });
26
+ },
27
+ serialize: JSON.stringify,
28
+ deserialize: JSON.parse,
29
+ }
30
+ );
31
+
32
+ const client: BridgeClient = {
33
+ rpc,
34
+ disconnect: () => {
35
+ ws.close();
36
+ },
37
+ };
38
+
39
+ resolve(client);
40
+ };
41
+
42
+ ws.addEventListener('open', handleOpen, { once: true });
43
+ });
44
+ };
45
+
46
+ export { getBridgeClient };
package/src/index.ts ADDED
@@ -0,0 +1 @@
1
+ export * from './shared.js';
package/src/server.ts ADDED
@@ -0,0 +1,107 @@
1
+ import { WebSocketServer, type WebSocket } from 'ws';
2
+ import { type BirpcGroup, createBirpcGroup } from 'birpc';
3
+ import { logger } from '@react-native-harness/tools';
4
+ import { EventEmitter } from 'node:events';
5
+ import type {
6
+ BridgeServerFunctions,
7
+ BridgeClientFunctions,
8
+ DeviceDescriptor,
9
+ BridgeEventsMap,
10
+ } from './shared.js';
11
+
12
+ export type BridgeServerOptions = {
13
+ port: number;
14
+ };
15
+
16
+ export type BridgeServerEvents = {
17
+ ready: (device: DeviceDescriptor) => void;
18
+ } & BridgeEventsMap;
19
+
20
+ export type BridgeServer = {
21
+ ws: WebSocketServer;
22
+ rpc: BirpcGroup<BridgeClientFunctions, BridgeServerFunctions>;
23
+ on: <T extends keyof BridgeServerEvents>(
24
+ event: T,
25
+ listener: BridgeServerEvents[T]
26
+ ) => void;
27
+ once: <T extends keyof BridgeServerEvents>(
28
+ event: T,
29
+ listener: BridgeServerEvents[T]
30
+ ) => void;
31
+ off: <T extends keyof BridgeServerEvents>(
32
+ event: T,
33
+ listener: BridgeServerEvents[T]
34
+ ) => void;
35
+ };
36
+
37
+ export const getBridgeServer = async ({
38
+ port,
39
+ }: BridgeServerOptions): Promise<BridgeServer> => {
40
+ const wss = await new Promise<WebSocketServer>((resolve) => {
41
+ const server = new WebSocketServer({ port, host: '0.0.0.0' }, () => {
42
+ resolve(server);
43
+ });
44
+ });
45
+ const emitter = new EventEmitter();
46
+ const clients = new Set<WebSocket>();
47
+
48
+ const group = createBirpcGroup<BridgeClientFunctions, BridgeServerFunctions>(
49
+ {
50
+ reportReady: (device) => {
51
+ emitter.emit('ready', device);
52
+ },
53
+ emitEvent: (event, data) => {
54
+ emitter.emit(event, data);
55
+ },
56
+ } satisfies BridgeServerFunctions,
57
+ []
58
+ );
59
+
60
+ wss.on('connection', (ws: WebSocket) => {
61
+ logger.debug('Client connected to the bridge');
62
+ ws.on('close', () => {
63
+ logger.debug('Client disconnected from the bridge');
64
+
65
+ // TODO: Remove channel when connection is closed.
66
+ clients.delete(ws);
67
+ });
68
+
69
+ group.updateChannels((channels) => {
70
+ channels.push({
71
+ post: (data) => ws.send(data),
72
+ on: (handler) => {
73
+ ws.on('message', (event: Buffer | ArrayBuffer | Buffer[]) => {
74
+ const message = event.toString();
75
+ handler(message);
76
+ });
77
+ },
78
+ serialize: (data) => {
79
+ if (data.e) {
80
+ // Serialize error by hand (include message, stack and cause).
81
+ return JSON.stringify({
82
+ ...data,
83
+ e: {
84
+ ...data.e,
85
+ name: data.e.name,
86
+ message: data.e.message,
87
+ stack: data.e.stack,
88
+ cause: data.e.cause,
89
+ },
90
+ });
91
+ }
92
+
93
+ return JSON.stringify(data);
94
+ },
95
+ deserialize: JSON.parse,
96
+ });
97
+ });
98
+ });
99
+
100
+ return {
101
+ ws: wss,
102
+ rpc: group,
103
+ on: emitter.on.bind(emitter),
104
+ once: emitter.once.bind(emitter),
105
+ off: emitter.off.bind(emitter),
106
+ };
107
+ };
@@ -0,0 +1,43 @@
1
+ export type TestStatus = 'active' | 'skipped' | 'todo';
2
+
3
+ export type TestFn = () => void | Promise<void>;
4
+
5
+ export type TestCase = {
6
+ name: string;
7
+ fn: TestFn;
8
+ status: TestStatus;
9
+ };
10
+
11
+ export type TestSuite = {
12
+ name: string;
13
+ tests: TestCase[];
14
+ suites: TestSuite[];
15
+ parent?: TestSuite;
16
+ beforeAll: TestFn[];
17
+ afterAll: TestFn[];
18
+ beforeEach: TestFn[];
19
+ afterEach: TestFn[];
20
+ status?: TestStatus;
21
+ _hasFocused?: boolean;
22
+ };
23
+
24
+ export type CollectionResult = {
25
+ testSuite: TestSuite;
26
+ /** Number of tests that will actually be executed (excludes skipped and todo tests) */
27
+ totalTests: number;
28
+ };
29
+
30
+ export type TestCollectionStartedEvent = {
31
+ type: 'collection-started';
32
+ file: string;
33
+ };
34
+
35
+ export type TestCollectionFinishedEvent = {
36
+ type: 'collection-finished';
37
+ file: string;
38
+ duration: number;
39
+ };
40
+
41
+ export type TestCollectorEvents =
42
+ | TestCollectionStartedEvent
43
+ | TestCollectionFinishedEvent;
@@ -0,0 +1,74 @@
1
+ export type TestResultStatus = 'passed' | 'failed' | 'skipped' | 'todo';
2
+
3
+ export type SerializedError = {
4
+ name: string;
5
+ message: string;
6
+ stack?: string;
7
+ };
8
+
9
+ export type TestRunnerFileStartedEvent = {
10
+ type: 'file-started';
11
+ file: string;
12
+ };
13
+
14
+ export type TestRunnerFileFinishedEvent = {
15
+ type: 'file-finished';
16
+ file: string;
17
+ duration: number;
18
+ };
19
+
20
+ export type TestRunnerSuiteStartedEvent = {
21
+ type: 'suite-started';
22
+ name: string;
23
+ file: string;
24
+ };
25
+
26
+ export type TestRunnerTestStartedEvent = {
27
+ type: 'test-started';
28
+ name: string;
29
+ suite: string;
30
+ file: string;
31
+ };
32
+
33
+ export type TestRunnerTestFinishedEvent = {
34
+ type: 'test-finished';
35
+ name: string;
36
+ suite: string;
37
+ file: string;
38
+ duration: number;
39
+ error?: SerializedError;
40
+ status: TestResultStatus;
41
+ };
42
+
43
+ export type TestRunnerSuiteFinishedEvent = {
44
+ type: 'suite-finished';
45
+ name: string;
46
+ file: string;
47
+ duration: number;
48
+ error?: SerializedError;
49
+ status: TestResultStatus;
50
+ };
51
+
52
+ export type TestRunnerEvents =
53
+ | TestRunnerFileStartedEvent
54
+ | TestRunnerFileFinishedEvent
55
+ | TestRunnerTestStartedEvent
56
+ | TestRunnerTestFinishedEvent
57
+ | TestRunnerSuiteStartedEvent
58
+ | TestRunnerSuiteFinishedEvent;
59
+
60
+ export type TestResult = {
61
+ name: string;
62
+ status: TestResultStatus;
63
+ error?: SerializedError;
64
+ duration: number;
65
+ };
66
+
67
+ export type TestSuiteResult = {
68
+ name: string;
69
+ tests: TestResult[];
70
+ suites: TestSuiteResult[];
71
+ status: TestResultStatus;
72
+ error?: SerializedError;
73
+ duration: number;
74
+ };
package/src/shared.ts ADDED
@@ -0,0 +1,54 @@
1
+ import type {
2
+ TestRunnerEvents,
3
+ TestSuiteResult,
4
+ } from './shared/test-runner.js';
5
+ import type { TestCollectorEvents } from './shared/test-collector.js';
6
+
7
+ export type {
8
+ TestCollectorEvents,
9
+ TestCollectionStartedEvent,
10
+ TestCollectionFinishedEvent,
11
+ TestSuite,
12
+ TestCase,
13
+ CollectionResult,
14
+ } from './shared/test-collector.js';
15
+ export type {
16
+ TestRunnerEvents,
17
+ TestRunnerFileStartedEvent,
18
+ TestRunnerFileFinishedEvent,
19
+ TestRunnerSuiteStartedEvent,
20
+ TestRunnerTestStartedEvent,
21
+ TestRunnerTestFinishedEvent,
22
+ TestRunnerSuiteFinishedEvent,
23
+ TestSuiteResult,
24
+ TestResult,
25
+ TestResultStatus,
26
+ SerializedError,
27
+ } from './shared/test-runner.js';
28
+
29
+ export type DeviceDescriptor = {
30
+ platform: 'ios' | 'android';
31
+ manufacturer: string;
32
+ model: string;
33
+ osVersion: string;
34
+ };
35
+
36
+ export type BridgeEvents = TestCollectorEvents | TestRunnerEvents;
37
+
38
+ export type BridgeEventsMap = {
39
+ [K in BridgeEvents['type']]: (
40
+ event: Extract<BridgeEvents, { type: K }>
41
+ ) => void;
42
+ };
43
+
44
+ export type BridgeClientFunctions = {
45
+ runTests: (path: string) => Promise<TestSuiteResult>;
46
+ };
47
+
48
+ export type BridgeServerFunctions = {
49
+ reportReady: (device: DeviceDescriptor) => void;
50
+ emitEvent: <TEvent extends BridgeEvents>(
51
+ event: TEvent['type'],
52
+ data: TEvent
53
+ ) => void;
54
+ };
package/tsconfig.json ADDED
@@ -0,0 +1,10 @@
1
+ {
2
+ "extends": "../../tsconfig.base.json",
3
+ "files": [],
4
+ "include": [],
5
+ "references": [
6
+ {
7
+ "path": "./tsconfig.lib.json"
8
+ }
9
+ ]
10
+ }
@@ -0,0 +1,19 @@
1
+ {
2
+ "extends": "../../tsconfig.base.json",
3
+ "compilerOptions": {
4
+ "baseUrl": ".",
5
+ "rootDir": "src",
6
+ "outDir": "dist",
7
+ "tsBuildInfoFile": "dist/tsconfig.lib.tsbuildinfo",
8
+ "emitDeclarationOnly": false,
9
+ "forceConsistentCasingInFileNames": true,
10
+ "types": ["node"],
11
+ "lib": ["ES2020", "DOM"]
12
+ },
13
+ "include": ["src/**/*.ts"],
14
+ "references": [
15
+ {
16
+ "path": "../tools/tsconfig.lib.json"
17
+ }
18
+ ]
19
+ }