Skip to content

Commit 2227d64

Browse files
authored
feat: make Harness WS port configurable (#44)
Added webSocketPort option to rn-harness.config (default 3001). This allows configuring the Bridge Server port, enabling usage of custom ports without rebuilding the application.
1 parent 2124133 commit 2227d64

11 files changed

Lines changed: 29 additions & 8 deletions

File tree

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
__default__: prerelease
3+
---
4+
5+
Added `webSocketPort` option to `rn-harness.config` (default 3001). This allows configuring the Bridge Server port, enabling usage of custom ports without rebuilding the application.

apps/playground/rn-harness.config.mjs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ const config = {
5151
],
5252
defaultRunner: 'android',
5353
bridgeTimeout: 120000,
54+
webSocketPort: 3002,
5455

5556
resetEnvironmentBetweenTestFiles: true,
5657
unstable__skipAlreadyIncludedModules: false,

packages/config/src/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ export const ConfigSchema = z
88
.min(1, 'App registry component name is required'),
99
runners: z.array(z.any()).min(1, 'At least one runner is required'),
1010
defaultRunner: z.string().optional(),
11+
webSocketPort: z.number().optional().default(3001),
1112
bridgeTimeout: z
1213
.number()
1314
.min(1000, 'Bridge timeout must be at least 1 second')

packages/jest/src/harness.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,11 @@ const getHarnessInternal = async (
2222
): Promise<Harness> => {
2323
const [metroInstance, platformInstance, serverBridge] = await Promise.all([
2424
getMetroInstance({ projectRoot, harnessConfig: config }, signal),
25-
import(platform.runner).then((module) => module.default(platform.config)),
25+
import(platform.runner).then((module) =>
26+
module.default(platform.config, config)
27+
),
2628
getBridgeServer({
27-
port: 3001,
29+
port: config.webSocketPort,
2830
timeout: config.bridgeTimeout,
2931
}),
3032
]);

packages/metro/src/manifest.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,10 @@ import fs from 'node:fs';
33
import { Config as HarnessConfig } from '@react-native-harness/config';
44

55
const getManifestContent = (harnessConfig: HarnessConfig): string => {
6-
return `global.RN_HARNESS = { appRegistryComponentName: '${harnessConfig.appRegistryComponentName}' };`;
6+
return `global.RN_HARNESS = {
7+
appRegistryComponentName: '${harnessConfig.appRegistryComponentName}',
8+
webSocketPort: ${harnessConfig.webSocketPort}
9+
};`;
710
};
811

912
export const getHarnessManifest = (harnessConfig: HarnessConfig): string => {

packages/platform-android/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
"dependencies": {
1919
"@react-native-harness/platforms": "workspace:*",
2020
"@react-native-harness/tools": "workspace:*",
21+
"@react-native-harness/config": "workspace:*",
2122
"zod": "^3.25.67",
2223
"tslib": "^2.3.0"
2324
},

packages/platform-android/src/adb.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,10 @@ export const isAppInstalled = async (
1818

1919
export const reversePort = async (
2020
adbId: string,
21-
port: number
21+
port: number,
22+
hostPort: number = port
2223
): Promise<void> => {
23-
await spawn('adb', ['-s', adbId, 'reverse', `tcp:${port}`, `tcp:${port}`]);
24+
await spawn('adb', ['-s', adbId, 'reverse', `tcp:${port}`, `tcp:${hostPort}`]);
2425
};
2526

2627
export const stopApp = async (

packages/platform-android/src/runner.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import {
33
AppNotInstalledError,
44
HarnessPlatformRunner,
55
} from '@react-native-harness/platforms';
6+
import { Config } from '@react-native-harness/config';
67
import {
78
AndroidPlatformConfigSchema,
89
type AndroidPlatformConfig,
@@ -12,7 +13,8 @@ import * as adb from './adb.js';
1213
import { getDeviceName } from './utils.js';
1314

1415
const getAndroidRunner = async (
15-
config: AndroidPlatformConfig
16+
config: AndroidPlatformConfig,
17+
harnessConfig: Config
1618
): Promise<HarnessPlatformRunner> => {
1719
const parsedConfig = AndroidPlatformConfigSchema.parse(config);
1820
const adbId = await getAdbId(parsedConfig.device);
@@ -33,7 +35,7 @@ const getAndroidRunner = async (
3335
await Promise.all([
3436
adb.reversePort(adbId, 8081),
3537
adb.reversePort(adbId, 8080),
36-
adb.reversePort(adbId, 3001),
38+
adb.reversePort(adbId, harnessConfig.webSocketPort),
3739
]);
3840

3941
return {

packages/runtime/src/client/getWSServer.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { WS_SERVER_PORT } from '../constants.js';
44
export const getWSServer = (): string => {
55
const devServerUrl = getDevServerUrl();
66
const hostname = devServerUrl.split('://')[1].split(':')[0];
7+
const port = global.RN_HARNESS?.webSocketPort || WS_SERVER_PORT;
78

8-
return `ws://${hostname}:${WS_SERVER_PORT}`;
9+
return `ws://${hostname}:${port}`;
910
};

packages/runtime/src/globals.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
export type HarnessGlobal = {
22
appRegistryComponentName: string;
3+
webSocketPort?: number;
34
};
45

56
declare global {

0 commit comments

Comments
 (0)