@midscene/webdriver 1.13.3 → 1.13.4-beta-20260924033639.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/dist/es/index.mjs CHANGED
@@ -33,6 +33,16 @@ class BaseServiceManager {
33
33
  this.host = host;
34
34
  }
35
35
  }
36
+ function normalizeWebDriverBaseUrl(baseUrl) {
37
+ let url;
38
+ try {
39
+ url = new URL(baseUrl);
40
+ } catch {
41
+ throw new Error('Invalid WebDriver base URL: expected a full HTTP(S) URL');
42
+ }
43
+ if ('http:' !== url.protocol && 'https:' !== url.protocol || !url.hostname || url.username || url.password || baseUrl.includes('?') || baseUrl.includes('#') || url.search || url.hash) throw new Error('WebDriver base URL must be an HTTP(S) URL without credentials, query, or fragment');
44
+ return url.toString().replace(/\/+$/, '');
45
+ }
36
46
  function WDAManager_define_property(obj, key, value) {
37
47
  if (key in obj) Object.defineProperty(obj, key, {
38
48
  value: value,
@@ -46,26 +56,27 @@ function WDAManager_define_property(obj, key, value) {
46
56
  promisify(exec);
47
57
  const debugWDA = getDebug('webdriver:wda-manager');
48
58
  class WDAManager extends BaseServiceManager {
49
- static getInstance(port = DEFAULT_WDA_PORT, host) {
50
- const key = `${host || 'localhost'}:${port}`;
59
+ static getInstance(port = DEFAULT_WDA_PORT, host, baseUrl) {
60
+ const key = void 0 !== baseUrl ? normalizeWebDriverBaseUrl(baseUrl) : `http://${host || 'localhost'}:${port}`;
51
61
  if (!WDAManager.instances.has(key)) WDAManager.instances.set(key, new WDAManager({
52
62
  port,
53
- host
63
+ host,
64
+ baseUrl: key
54
65
  }));
55
66
  return WDAManager.instances.get(key);
56
67
  }
57
68
  async start() {
58
- if (this.isStarted) return void debugWDA(`WDA already started on ${this.config.host}:${this.config.port}`);
69
+ if (this.isStarted) return void debugWDA('WDA already started');
59
70
  try {
60
71
  if (await this.isWDARunning()) {
61
- debugWDA(`WDA already running on port ${this.config.port}`);
72
+ debugWDA('WDA already running');
62
73
  this.isStarted = true;
63
74
  return;
64
75
  }
65
76
  await this.startWDA();
66
77
  await this.waitForWDA();
67
78
  this.isStarted = true;
68
- debugWDA(`WDA started successfully on ${this.config.host}:${this.config.port}`);
79
+ debugWDA('WDA started successfully');
69
80
  } catch (error) {
70
81
  debugWDA(`Failed to start WDA: ${error}`);
71
82
  throw new Error(`Failed to start WebDriverAgent: ${error}`);
@@ -75,7 +86,7 @@ class WDAManager extends BaseServiceManager {
75
86
  if (!this.isStarted) return;
76
87
  try {
77
88
  this.isStarted = false;
78
- debugWDA(`WDA stopped on ${this.config.host}:${this.config.port}`);
89
+ debugWDA('WDA stopped');
79
90
  } catch (error) {
80
91
  debugWDA(`Error stopping WDA: ${error}`);
81
92
  }
@@ -83,26 +94,29 @@ class WDAManager extends BaseServiceManager {
83
94
  isRunning() {
84
95
  return this.isStarted;
85
96
  }
97
+ getEndpoint() {
98
+ return this.baseUrl;
99
+ }
86
100
  async startWDA() {
87
101
  await this.checkWDAPreparation();
88
102
  debugWDA('WebDriverAgent verification completed');
89
103
  }
90
104
  async checkWDAPreparation() {
91
- if (await this.isWDARunning()) return void debugWDA(`WebDriverAgent is already running on port ${this.config.port}`);
92
- throw new Error(`WebDriverAgent is not running on ${this.config.host}:${this.config.port}. Please start WebDriverAgent manually:
105
+ if (await this.isWDARunning()) return void debugWDA('WebDriverAgent is already running');
106
+ throw new Error(`WebDriverAgent is not reachable at the configured address. Please start WebDriverAgent manually or check the gateway route:
93
107
 
94
108
  🔧 Setup Instructions:
95
109
  1. Install WebDriverAgent: npm install appium-webdriveragent
96
110
  2. Build and run WebDriverAgent:
97
111
  - For simulators: Use Xcode to run WebDriverAgentRunner on your target simulator
98
112
  - For real devices: Build WebDriverAgentRunner and install on your device
99
- 3. Ensure WebDriverAgent is listening on ${this.config.host}:${this.config.port}
113
+ 3. Ensure WebDriverAgent is reachable at the configured address
100
114
 
101
115
  💡 Alternative: You can also specify a different host/port where WebDriverAgent is running.`);
102
116
  }
103
117
  async isWDARunning() {
104
118
  try {
105
- const url = `http://${this.config.host}:${this.config.port}/status`;
119
+ const url = `${this.getEndpoint()}/status`;
106
120
  const response = await fetch(url);
107
121
  if (!response.ok) return false;
108
122
  const responseText = await response.text();
@@ -120,14 +134,9 @@ class WDAManager extends BaseServiceManager {
120
134
  throw new Error(`WebDriverAgent did not start within ${timeout}ms`);
121
135
  }
122
136
  constructor(config){
123
- super(config.port, config.host), WDAManager_define_property(this, "config", void 0), WDAManager_define_property(this, "isStarted", false);
124
- this.config = {
125
- bundleId: 'com.apple.WebDriverAgentRunner.xctrunner',
126
- usePrebuiltWDA: true,
127
- host: 'localhost',
128
- ...config,
129
- port: config.port || DEFAULT_WDA_PORT
130
- };
137
+ const address = config.baseUrl ? new URL(config.baseUrl) : void 0;
138
+ super(address ? Number(address.port || ('https:' === address.protocol ? 443 : 80)) : config.port, address?.hostname ?? config.host), WDAManager_define_property(this, "baseUrl", void 0), WDAManager_define_property(this, "isStarted", false);
139
+ this.baseUrl = config.baseUrl ?? super.getEndpoint();
131
140
  }
132
141
  }
133
142
  WDAManager_define_property(WDAManager, "instances", new Map());
@@ -150,7 +159,7 @@ class WebDriverRequestError extends Error {
150
159
  }
151
160
  async function makeWebDriverRequest(baseUrl, method, endpoint, data, timeout = 30000) {
152
161
  const url = `${baseUrl}${endpoint}`;
153
- debugRequest(`${method} ${url}${data ? ` with data: ${JSON.stringify(data)}` : ''}`);
162
+ debugRequest(`${method} ${endpoint}${data ? ` with data: ${JSON.stringify(data)}` : ''}`);
154
163
  const controller = new AbortController();
155
164
  const timeoutId = setTimeout(()=>controller.abort(), timeout);
156
165
  try {
@@ -305,10 +314,10 @@ class WebDriverClient {
305
314
  this.port = options.port || DEFAULT_WDA_PORT;
306
315
  this.host = options.host || 'localhost';
307
316
  this.timeout = options.timeout || 30000;
308
- this.baseUrl = `http://${this.host}:${this.port}`;
317
+ this.baseUrl = void 0 !== options.baseUrl ? normalizeWebDriverBaseUrl(options.baseUrl) : `http://${this.host}:${this.port}`;
309
318
  this.sessionId = options.sessionId || null;
310
319
  this.ownsSession = !options.sessionId;
311
- debugClient(`Initialized WebDriver client on ${this.host}:${this.port}`);
320
+ debugClient('Initialized WebDriver client');
312
321
  }
313
322
  }
314
- export { BaseServiceManager, WDAManager, WebDriverClient, WebDriverRequestError, makeWebDriverRequest };
323
+ export { BaseServiceManager, WDAManager, WebDriverClient, WebDriverRequestError, makeWebDriverRequest, normalizeWebDriverBaseUrl };
package/dist/lib/index.js CHANGED
@@ -24,6 +24,7 @@ var __webpack_require__ = {};
24
24
  var __webpack_exports__ = {};
25
25
  __webpack_require__.r(__webpack_exports__);
26
26
  __webpack_require__.d(__webpack_exports__, {
27
+ normalizeWebDriverBaseUrl: ()=>normalizeWebDriverBaseUrl,
27
28
  WDAManager: ()=>WDAManager,
28
29
  makeWebDriverRequest: ()=>makeWebDriverRequest,
29
30
  WebDriverRequestError: ()=>WebDriverRequestError,
@@ -65,6 +66,16 @@ const external_node_child_process_namespaceObject = require("node:child_process"
65
66
  const external_node_util_namespaceObject = require("node:util");
66
67
  const constants_namespaceObject = require("@midscene/shared/constants");
67
68
  const logger_namespaceObject = require("@midscene/shared/logger");
69
+ function normalizeWebDriverBaseUrl(baseUrl) {
70
+ let url;
71
+ try {
72
+ url = new URL(baseUrl);
73
+ } catch {
74
+ throw new Error('Invalid WebDriver base URL: expected a full HTTP(S) URL');
75
+ }
76
+ if ('http:' !== url.protocol && 'https:' !== url.protocol || !url.hostname || url.username || url.password || baseUrl.includes('?') || baseUrl.includes('#') || url.search || url.hash) throw new Error('WebDriver base URL must be an HTTP(S) URL without credentials, query, or fragment');
77
+ return url.toString().replace(/\/+$/, '');
78
+ }
68
79
  function WDAManager_define_property(obj, key, value) {
69
80
  if (key in obj) Object.defineProperty(obj, key, {
70
81
  value: value,
@@ -78,26 +89,27 @@ function WDAManager_define_property(obj, key, value) {
78
89
  (0, external_node_util_namespaceObject.promisify)(external_node_child_process_namespaceObject.exec);
79
90
  const debugWDA = (0, logger_namespaceObject.getDebug)('webdriver:wda-manager');
80
91
  class WDAManager extends BaseServiceManager {
81
- static getInstance(port = constants_namespaceObject.DEFAULT_WDA_PORT, host) {
82
- const key = `${host || 'localhost'}:${port}`;
92
+ static getInstance(port = constants_namespaceObject.DEFAULT_WDA_PORT, host, baseUrl) {
93
+ const key = void 0 !== baseUrl ? normalizeWebDriverBaseUrl(baseUrl) : `http://${host || 'localhost'}:${port}`;
83
94
  if (!WDAManager.instances.has(key)) WDAManager.instances.set(key, new WDAManager({
84
95
  port,
85
- host
96
+ host,
97
+ baseUrl: key
86
98
  }));
87
99
  return WDAManager.instances.get(key);
88
100
  }
89
101
  async start() {
90
- if (this.isStarted) return void debugWDA(`WDA already started on ${this.config.host}:${this.config.port}`);
102
+ if (this.isStarted) return void debugWDA('WDA already started');
91
103
  try {
92
104
  if (await this.isWDARunning()) {
93
- debugWDA(`WDA already running on port ${this.config.port}`);
105
+ debugWDA('WDA already running');
94
106
  this.isStarted = true;
95
107
  return;
96
108
  }
97
109
  await this.startWDA();
98
110
  await this.waitForWDA();
99
111
  this.isStarted = true;
100
- debugWDA(`WDA started successfully on ${this.config.host}:${this.config.port}`);
112
+ debugWDA('WDA started successfully');
101
113
  } catch (error) {
102
114
  debugWDA(`Failed to start WDA: ${error}`);
103
115
  throw new Error(`Failed to start WebDriverAgent: ${error}`);
@@ -107,7 +119,7 @@ class WDAManager extends BaseServiceManager {
107
119
  if (!this.isStarted) return;
108
120
  try {
109
121
  this.isStarted = false;
110
- debugWDA(`WDA stopped on ${this.config.host}:${this.config.port}`);
122
+ debugWDA('WDA stopped');
111
123
  } catch (error) {
112
124
  debugWDA(`Error stopping WDA: ${error}`);
113
125
  }
@@ -115,26 +127,29 @@ class WDAManager extends BaseServiceManager {
115
127
  isRunning() {
116
128
  return this.isStarted;
117
129
  }
130
+ getEndpoint() {
131
+ return this.baseUrl;
132
+ }
118
133
  async startWDA() {
119
134
  await this.checkWDAPreparation();
120
135
  debugWDA('WebDriverAgent verification completed');
121
136
  }
122
137
  async checkWDAPreparation() {
123
- if (await this.isWDARunning()) return void debugWDA(`WebDriverAgent is already running on port ${this.config.port}`);
124
- throw new Error(`WebDriverAgent is not running on ${this.config.host}:${this.config.port}. Please start WebDriverAgent manually:
138
+ if (await this.isWDARunning()) return void debugWDA('WebDriverAgent is already running');
139
+ throw new Error(`WebDriverAgent is not reachable at the configured address. Please start WebDriverAgent manually or check the gateway route:
125
140
 
126
141
  🔧 Setup Instructions:
127
142
  1. Install WebDriverAgent: npm install appium-webdriveragent
128
143
  2. Build and run WebDriverAgent:
129
144
  - For simulators: Use Xcode to run WebDriverAgentRunner on your target simulator
130
145
  - For real devices: Build WebDriverAgentRunner and install on your device
131
- 3. Ensure WebDriverAgent is listening on ${this.config.host}:${this.config.port}
146
+ 3. Ensure WebDriverAgent is reachable at the configured address
132
147
 
133
148
  💡 Alternative: You can also specify a different host/port where WebDriverAgent is running.`);
134
149
  }
135
150
  async isWDARunning() {
136
151
  try {
137
- const url = `http://${this.config.host}:${this.config.port}/status`;
152
+ const url = `${this.getEndpoint()}/status`;
138
153
  const response = await fetch(url);
139
154
  if (!response.ok) return false;
140
155
  const responseText = await response.text();
@@ -152,14 +167,9 @@ class WDAManager extends BaseServiceManager {
152
167
  throw new Error(`WebDriverAgent did not start within ${timeout}ms`);
153
168
  }
154
169
  constructor(config){
155
- super(config.port, config.host), WDAManager_define_property(this, "config", void 0), WDAManager_define_property(this, "isStarted", false);
156
- this.config = {
157
- bundleId: 'com.apple.WebDriverAgentRunner.xctrunner',
158
- usePrebuiltWDA: true,
159
- host: 'localhost',
160
- ...config,
161
- port: config.port || constants_namespaceObject.DEFAULT_WDA_PORT
162
- };
170
+ const address = config.baseUrl ? new URL(config.baseUrl) : void 0;
171
+ super(address ? Number(address.port || ('https:' === address.protocol ? 443 : 80)) : config.port, address?.hostname ?? config.host), WDAManager_define_property(this, "baseUrl", void 0), WDAManager_define_property(this, "isStarted", false);
172
+ this.baseUrl = config.baseUrl ?? super.getEndpoint();
163
173
  }
164
174
  }
165
175
  WDAManager_define_property(WDAManager, "instances", new Map());
@@ -182,7 +192,7 @@ class WebDriverRequestError extends Error {
182
192
  }
183
193
  async function makeWebDriverRequest(baseUrl, method, endpoint, data, timeout = 30000) {
184
194
  const url = `${baseUrl}${endpoint}`;
185
- debugRequest(`${method} ${url}${data ? ` with data: ${JSON.stringify(data)}` : ''}`);
195
+ debugRequest(`${method} ${endpoint}${data ? ` with data: ${JSON.stringify(data)}` : ''}`);
186
196
  const controller = new AbortController();
187
197
  const timeoutId = setTimeout(()=>controller.abort(), timeout);
188
198
  try {
@@ -337,10 +347,10 @@ class WebDriverClient {
337
347
  this.port = options.port || constants_namespaceObject.DEFAULT_WDA_PORT;
338
348
  this.host = options.host || 'localhost';
339
349
  this.timeout = options.timeout || 30000;
340
- this.baseUrl = `http://${this.host}:${this.port}`;
350
+ this.baseUrl = void 0 !== options.baseUrl ? normalizeWebDriverBaseUrl(options.baseUrl) : `http://${this.host}:${this.port}`;
341
351
  this.sessionId = options.sessionId || null;
342
352
  this.ownsSession = !options.sessionId;
343
- debugClient(`Initialized WebDriver client on ${this.host}:${this.port}`);
353
+ debugClient('Initialized WebDriver client');
344
354
  }
345
355
  }
346
356
  exports.BaseServiceManager = __webpack_exports__.BaseServiceManager;
@@ -348,12 +358,14 @@ exports.WDAManager = __webpack_exports__.WDAManager;
348
358
  exports.WebDriverClient = __webpack_exports__.WebDriverClient;
349
359
  exports.WebDriverRequestError = __webpack_exports__.WebDriverRequestError;
350
360
  exports.makeWebDriverRequest = __webpack_exports__.makeWebDriverRequest;
361
+ exports.normalizeWebDriverBaseUrl = __webpack_exports__.normalizeWebDriverBaseUrl;
351
362
  for(var __rspack_i in __webpack_exports__)if (-1 === [
352
363
  "BaseServiceManager",
353
364
  "WDAManager",
354
365
  "WebDriverClient",
355
366
  "WebDriverRequestError",
356
- "makeWebDriverRequest"
367
+ "makeWebDriverRequest",
368
+ "normalizeWebDriverBaseUrl"
357
369
  ].indexOf(__rspack_i)) exports[__rspack_i] = __webpack_exports__[__rspack_i];
358
370
  Object.defineProperty(exports, '__esModule', {
359
371
  value: true
@@ -21,6 +21,9 @@ export declare interface DeviceInfo {
21
21
 
22
22
  export declare function makeWebDriverRequest(baseUrl: string, method: string, endpoint: string, data?: any, timeout?: number): Promise<any>;
23
23
 
24
+ /** Normalize a WebDriver server URL before appending API endpoint paths. */
25
+ export declare function normalizeWebDriverBaseUrl(baseUrl: string): string;
26
+
24
27
  export declare interface Point {
25
28
  x: number;
26
29
  y: number;
@@ -34,6 +37,7 @@ export declare interface Size {
34
37
  export declare interface WDAConfig {
35
38
  port: number;
36
39
  host?: string;
40
+ baseUrl?: string;
37
41
  wdaPath?: string;
38
42
  bundleId?: string;
39
43
  usePrebuiltWDA?: boolean;
@@ -61,13 +65,14 @@ export declare interface WDAElementInfo {
61
65
 
62
66
  export declare class WDAManager extends BaseServiceManager {
63
67
  private static instances;
64
- private config;
68
+ private readonly baseUrl;
65
69
  private isStarted;
66
70
  private constructor();
67
- static getInstance(port?: number, host?: string): WDAManager;
71
+ static getInstance(port?: number, host?: string, baseUrl?: string): WDAManager;
68
72
  start(): Promise<void>;
69
73
  stop(): Promise<void>;
70
74
  isRunning(): boolean;
75
+ getEndpoint(): string;
71
76
  private startWDA;
72
77
  private checkWDAPreparation;
73
78
  private isWDARunning;
@@ -104,6 +109,8 @@ export declare class WebDriverClient {
104
109
  }
105
110
 
106
111
  export declare interface WebDriverOptions {
112
+ /** Full WebDriver API base URL, including any gateway path prefix. */
113
+ baseUrl?: string;
107
114
  port?: number;
108
115
  host?: string;
109
116
  timeout?: number;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@midscene/webdriver",
3
- "version": "1.13.3",
3
+ "version": "1.13.4-beta-20260924033639.0",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/web-infra-dev/midscene.git",
@@ -12,7 +12,7 @@
12
12
  "types": "dist/types/index.d.ts",
13
13
  "dependencies": {
14
14
  "node-fetch": "^3.3.2",
15
- "@midscene/shared": "1.13.3"
15
+ "@midscene/shared": "1.13.4-beta-20260924033639.0"
16
16
  },
17
17
  "devDependencies": {
18
18
  "@rslib/core": "^0.18.3",