@midscene/ios 0.30.9 → 0.30.11-beta-20251218071621.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.
Files changed (65) hide show
  1. package/README.md +11 -11
  2. package/dist/es/bin.mjs +467 -339
  3. package/dist/es/index.mjs +194 -76
  4. package/dist/lib/bin.js +437 -295
  5. package/dist/lib/index.js +199 -81
  6. package/dist/types/index.d.ts +103 -14
  7. package/package.json +8 -7
  8. package/static/index.html +1 -1
  9. package/static/static/css/index.d32b7df9.css +2 -0
  10. package/static/static/css/index.d32b7df9.css.map +1 -0
  11. package/static/static/js/79.25af61dc.js +611 -0
  12. package/static/static/js/{931.dc961e99.js.LICENSE.txt → 79.25af61dc.js.LICENSE.txt} +0 -4
  13. package/static/static/js/79.25af61dc.js.map +1 -0
  14. package/static/static/js/async/195.0366f6e8.js +3 -0
  15. package/static/static/js/async/195.0366f6e8.js.map +1 -0
  16. package/static/static/js/async/{702.60261735.js → 199.f31e52e7.js} +20 -20
  17. package/static/static/js/async/199.f31e52e7.js.map +1 -0
  18. package/static/static/js/async/221.591b048e.js +21 -0
  19. package/static/static/js/async/221.591b048e.js.map +1 -0
  20. package/static/static/js/async/271.15d46ff8.js +30 -0
  21. package/static/static/js/async/271.15d46ff8.js.map +1 -0
  22. package/static/static/js/async/35.2b64fb0f.js +1 -0
  23. package/static/static/js/async/{644.6bdc4065.js → 467.710fa05a.js} +1 -1
  24. package/static/static/js/async/652.b5a7c7b4.js +3 -0
  25. package/static/static/js/async/652.b5a7c7b4.js.map +1 -0
  26. package/static/static/js/async/856.be9fd814.js +158 -0
  27. package/static/static/js/async/{212.e243c338.js.map → 856.be9fd814.js.map} +1 -1
  28. package/static/static/js/async/860.b56301d9.js +2 -0
  29. package/static/static/js/async/860.b56301d9.js.map +1 -0
  30. package/static/static/js/async/990.82a78a53.js +26 -0
  31. package/static/static/js/async/990.82a78a53.js.map +1 -0
  32. package/static/static/js/index.0bbfffbf.js +10 -0
  33. package/static/static/js/index.0bbfffbf.js.map +1 -0
  34. package/static/static/js/lib-react.7b1abe58.js +3 -0
  35. package/static/static/js/lib-react.7b1abe58.js.map +1 -0
  36. package/static/static/css/index.44466eb4.css +0 -2
  37. package/static/static/css/index.44466eb4.css.map +0 -1
  38. package/static/static/js/931.dc961e99.js +0 -620
  39. package/static/static/js/931.dc961e99.js.map +0 -1
  40. package/static/static/js/async/173.9cf6b074.js +0 -3
  41. package/static/static/js/async/173.9cf6b074.js.map +0 -1
  42. package/static/static/js/async/212.e243c338.js +0 -158
  43. package/static/static/js/async/329.f888b505.js +0 -26
  44. package/static/static/js/async/329.f888b505.js.map +0 -1
  45. package/static/static/js/async/364.1821e74b.js +0 -30
  46. package/static/static/js/async/364.1821e74b.js.map +0 -1
  47. package/static/static/js/async/544.b73fa603.js +0 -2
  48. package/static/static/js/async/544.b73fa603.js.map +0 -1
  49. package/static/static/js/async/582.5dccae2d.js +0 -21
  50. package/static/static/js/async/582.5dccae2d.js.map +0 -1
  51. package/static/static/js/async/624.45ee2b2c.js +0 -3
  52. package/static/static/js/async/624.45ee2b2c.js.map +0 -1
  53. package/static/static/js/async/659.9afd03db.js +0 -21
  54. package/static/static/js/async/659.9afd03db.js.map +0 -1
  55. package/static/static/js/async/702.60261735.js.map +0 -1
  56. package/static/static/js/async/920.7d9a9aa8.js +0 -2
  57. package/static/static/js/async/920.7d9a9aa8.js.map +0 -1
  58. package/static/static/js/async/983.8b91303f.js +0 -1
  59. package/static/static/js/index.c7ba8adb.js +0 -10
  60. package/static/static/js/index.c7ba8adb.js.map +0 -1
  61. package/static/static/js/lib-react.f566a9ed.js +0 -3
  62. package/static/static/js/lib-react.f566a9ed.js.map +0 -1
  63. /package/static/static/js/{index.c7ba8adb.js.LICENSE.txt → index.0bbfffbf.js.LICENSE.txt} +0 -0
  64. /package/static/static/js/{lib-react.f566a9ed.js.LICENSE.txt → lib-react.7b1abe58.js.LICENSE.txt} +0 -0
  65. /package/static/static/wasm/{9e906fbf55e08f98.module.wasm → 9e906fbf.module.wasm} +0 -0
package/dist/es/index.mjs CHANGED
@@ -150,6 +150,48 @@ class IOSWebDriverClient extends WebDriverClient {
150
150
  debugIOS(`Warning: Key "${key}" is not supported on iOS platform`);
151
151
  throw new Error(`Key "${key}" is not supported on iOS platform`);
152
152
  }
153
+ async getActiveElement() {
154
+ this.ensureSession();
155
+ debugIOS('Getting active element');
156
+ try {
157
+ const response = await this.makeRequest('GET', `/session/${this.sessionId}/element/active`);
158
+ const elementId = response.value?.ELEMENT || response.value?.['element-6066-11e4-a52e-4f735466cecf'] || response.ELEMENT || response['element-6066-11e4-a52e-4f735466cecf'];
159
+ if (elementId) {
160
+ debugIOS(`Got active element ID: ${elementId}`);
161
+ return elementId;
162
+ }
163
+ debugIOS('No active element found');
164
+ return null;
165
+ } catch (error) {
166
+ debugIOS(`Failed to get active element: ${error}`);
167
+ return null;
168
+ }
169
+ }
170
+ async clearElement(elementId) {
171
+ this.ensureSession();
172
+ debugIOS(`Clearing element: ${elementId}`);
173
+ try {
174
+ await this.makeRequest('POST', `/session/${this.sessionId}/element/${elementId}/clear`);
175
+ debugIOS('Element cleared successfully');
176
+ } catch (error) {
177
+ debugIOS(`Failed to clear element: ${error}`);
178
+ throw new Error(`Failed to clear element: ${error}`);
179
+ }
180
+ }
181
+ async clearActiveElement() {
182
+ try {
183
+ const elementId = await this.getActiveElement();
184
+ if (!elementId) {
185
+ debugIOS('No active element to clear');
186
+ return false;
187
+ }
188
+ await this.clearElement(elementId);
189
+ return true;
190
+ } catch (error) {
191
+ debugIOS(`Failed to clear active element: ${error}`);
192
+ return false;
193
+ }
194
+ }
153
195
  normalizeKeyName(key) {
154
196
  return key.charAt(0).toUpperCase() + key.slice(1).toLowerCase();
155
197
  }
@@ -190,8 +232,17 @@ class IOSWebDriverClient extends WebDriverClient {
190
232
  });
191
233
  debugIOS(`Tapped at coordinates (${x}, ${y})`);
192
234
  } catch (error) {
193
- debugIOS(`Failed to tap at (${x}, ${y}): ${error}`);
194
- throw new Error(`Failed to tap at coordinates: ${error}`);
235
+ debugIOS(`New tap endpoint failed, trying legacy endpoint: ${error}`);
236
+ try {
237
+ await this.makeRequest('POST', `/session/${this.sessionId}/wda/tap/0`, {
238
+ x,
239
+ y
240
+ });
241
+ debugIOS(`Tapped at coordinates (${x}, ${y}) using legacy endpoint`);
242
+ } catch (fallbackError) {
243
+ debugIOS(`Failed to tap at (${x}, ${y}): ${fallbackError}`);
244
+ throw new Error(`Failed to tap at coordinates: ${fallbackError}`);
245
+ }
195
246
  }
196
247
  }
197
248
  async swipe(fromX, fromY, toX, toY, duration = 500) {
@@ -264,13 +315,34 @@ class IOSWebDriverClient extends WebDriverClient {
264
315
  debugIOS(`Triple tapped at coordinates (${x}, ${y})`);
265
316
  }
266
317
  async getScreenScale() {
267
- var _screenResponse_value;
268
- const screenResponse = await this.makeRequest('GET', '/wda/screen');
269
- if (null == screenResponse ? void 0 : null == (_screenResponse_value = screenResponse.value) ? void 0 : _screenResponse_value.scale) {
270
- debugIOS(`Got screen scale from WDA screen endpoint: ${screenResponse.value.scale}`);
271
- return screenResponse.value.scale;
318
+ this.ensureSession();
319
+ try {
320
+ const screenResponse = await this.makeRequest('GET', `/session/${this.sessionId}/wda/screen`);
321
+ if (screenResponse?.value?.scale) {
322
+ debugIOS(`Got screen scale from WDA screen endpoint: ${screenResponse.value.scale}`);
323
+ return screenResponse.value.scale;
324
+ }
325
+ } catch (error) {
326
+ debugIOS(`Failed to get screen scale from /wda/screen: ${error}`);
327
+ }
328
+ try {
329
+ debugIOS('Calculating screen scale from screenshot and window size');
330
+ const [screenshotBase64, windowSize] = await Promise.all([
331
+ this.takeScreenshot(),
332
+ this.getWindowSize()
333
+ ]);
334
+ const { jimpFromBase64 } = await import("@midscene/shared/img");
335
+ const screenshotImg = await jimpFromBase64(screenshotBase64);
336
+ const screenshotWidth = screenshotImg.bitmap.width;
337
+ const screenshotHeight = screenshotImg.bitmap.height;
338
+ const scale = Math.max(screenshotWidth, screenshotHeight) / Math.max(windowSize.width, windowSize.height);
339
+ const roundedScale = Math.round(scale);
340
+ debugIOS(`Calculated screen scale: ${roundedScale} (screenshot: ${screenshotWidth}x${screenshotHeight}, window: ${windowSize.width}x${windowSize.height})`);
341
+ return roundedScale;
342
+ } catch (error) {
343
+ debugIOS(`Failed to calculate screen scale: ${error}`);
272
344
  }
273
- debugIOS('No screen scale found in WDA screen response');
345
+ debugIOS('No screen scale found');
274
346
  return null;
275
347
  }
276
348
  async createSession(capabilities) {
@@ -297,6 +369,10 @@ class IOSWebDriverClient extends WebDriverClient {
297
369
  debugIOS(`Failed to apply iOS session configuration: ${error}`);
298
370
  }
299
371
  }
372
+ async executeRequest(method, endpoint, data) {
373
+ this.ensureSession();
374
+ return this.makeRequest(method, endpoint, data);
375
+ }
300
376
  }
301
377
  function _define_property(obj, key, value) {
302
378
  if (key in obj) Object.defineProperty(obj, key, {
@@ -309,7 +385,12 @@ function _define_property(obj, key, value) {
309
385
  return obj;
310
386
  }
311
387
  const debugDevice = getDebug('ios:device');
312
- const BackspaceChar = '\u0008';
388
+ const WDA_HTTP_METHODS = [
389
+ 'GET',
390
+ 'POST',
391
+ 'DELETE',
392
+ 'PUT'
393
+ ];
313
394
  class IOSDevice {
314
395
  actionSpace() {
315
396
  const defaultActions = [
@@ -329,7 +410,7 @@ class IOSDevice {
329
410
  interfaceAlias: 'aiInput',
330
411
  paramSchema: z.object({
331
412
  value: z.string().describe('The text to input. Provide the final content for replace/append modes, or an empty string when using clear mode to remove existing text.'),
332
- autoDismissKeyboard: z.boolean().optional().describe('If true, the keyboard will be dismissed after the input is completed. Do not set it unless the user asks you to do so.'),
413
+ autoDismissKeyboard: z.boolean().optional().describe('Whether to dismiss the keyboard after input. Defaults to true if not specified. Set to false to keep the keyboard visible after input.'),
333
414
  mode: z["enum"]([
334
415
  'replace',
335
416
  'clear',
@@ -338,14 +419,13 @@ class IOSDevice {
338
419
  locate: getMidsceneLocationSchema().describe('The input field to be filled').optional()
339
420
  }),
340
421
  call: async (param)=>{
341
- var _this_options;
342
422
  const element = param.locate;
343
423
  if (element) {
344
424
  if ('append' !== param.mode) await this.clearInput(element);
345
425
  }
346
426
  if ('clear' === param.mode) return;
347
427
  if (!param || !param.value) return;
348
- const autoDismissKeyboard = param.autoDismissKeyboard ?? (null == (_this_options = this.options) ? void 0 : _this_options.autoDismissKeyboard);
428
+ const autoDismissKeyboard = param.autoDismissKeyboard ?? this.options?.autoDismissKeyboard;
349
429
  await this.typeText(param.value, {
350
430
  autoDismissKeyboard
351
431
  });
@@ -357,18 +437,18 @@ class IOSDevice {
357
437
  left: element.center[0],
358
438
  top: element.center[1]
359
439
  } : void 0;
360
- const scrollToEventName = null == param ? void 0 : param.scrollType;
361
- if ('untilTop' === scrollToEventName) await this.scrollUntilTop(startingPoint);
362
- else if ('untilBottom' === scrollToEventName) await this.scrollUntilBottom(startingPoint);
363
- else if ('untilRight' === scrollToEventName) await this.scrollUntilRight(startingPoint);
364
- else if ('untilLeft' === scrollToEventName) await this.scrollUntilLeft(startingPoint);
365
- else if ('once' !== scrollToEventName && scrollToEventName) throw new Error(`Unknown scroll event type: ${scrollToEventName}, param: ${JSON.stringify(param)}`);
440
+ const scrollToEventName = param?.scrollType;
441
+ if ('scrollToTop' === scrollToEventName) await this.scrollUntilTop(startingPoint);
442
+ else if ('scrollToBottom' === scrollToEventName) await this.scrollUntilBottom(startingPoint);
443
+ else if ('scrollToRight' === scrollToEventName) await this.scrollUntilRight(startingPoint);
444
+ else if ('scrollToLeft' === scrollToEventName) await this.scrollUntilLeft(startingPoint);
445
+ else if ('singleAction' !== scrollToEventName && scrollToEventName) throw new Error(`Unknown scroll event type: ${scrollToEventName}, param: ${JSON.stringify(param)}`);
366
446
  else {
367
- if ((null == param ? void 0 : param.direction) !== 'down' && param && param.direction) if ('up' === param.direction) await this.scrollUp(param.distance || void 0, startingPoint);
447
+ if (param?.direction !== 'down' && param && param.direction) if ('up' === param.direction) await this.scrollUp(param.distance || void 0, startingPoint);
368
448
  else if ('left' === param.direction) await this.scrollLeft(param.distance || void 0, startingPoint);
369
449
  else if ('right' === param.direction) await this.scrollRight(param.distance || void 0, startingPoint);
370
450
  else throw new Error(`Unknown scroll direction: ${param.direction}`);
371
- else await this.scrollDown((null == param ? void 0 : param.distance) || void 0, startingPoint);
451
+ else await this.scrollDown(param?.distance || void 0, startingPoint);
372
452
  await sleep(500);
373
453
  }
374
454
  }),
@@ -382,22 +462,6 @@ class IOSDevice {
382
462
  defineActionKeyboardPress(async (param)=>{
383
463
  await this.pressKey(param.keyName);
384
464
  }),
385
- defineAction({
386
- name: 'IOSHomeButton',
387
- description: 'Trigger the system "home" operation on iOS devices',
388
- paramSchema: z.object({}),
389
- call: async ()=>{
390
- await this.home();
391
- }
392
- }),
393
- defineAction({
394
- name: 'IOSAppSwitcher',
395
- description: 'Trigger the system "app switcher" operation on iOS devices',
396
- paramSchema: z.object({}),
397
- call: async ()=>{
398
- await this.appSwitcher();
399
- }
400
- }),
401
465
  defineAction({
402
466
  name: 'IOSLongPress',
403
467
  description: 'Trigger a long press on the screen at specified coordinates on iOS devices',
@@ -409,7 +473,7 @@ class IOSDevice {
409
473
  const element = param.locate;
410
474
  node_assert(element, 'IOSLongPress requires an element to be located');
411
475
  const [x, y] = element.center;
412
- await this.longPress(x, y, null == param ? void 0 : param.duration);
476
+ await this.longPress(x, y, param?.duration);
413
477
  }
414
478
  }),
415
479
  defineActionClearInput(async (param)=>{
@@ -418,9 +482,11 @@ class IOSDevice {
418
482
  await this.clearInput(element);
419
483
  })
420
484
  ];
485
+ const platformSpecificActions = Object.values(createPlatformActions(this));
421
486
  const customActions = this.customActions || [];
422
487
  return [
423
488
  ...defaultActions,
489
+ ...platformSpecificActions,
424
490
  ...customActions
425
491
  ];
426
492
  }
@@ -437,7 +503,7 @@ class IOSDevice {
437
503
  await this.wdaManager.start();
438
504
  await this.wdaBackend.createSession();
439
505
  const deviceInfo = await this.wdaBackend.getDeviceInfo();
440
- if (null == deviceInfo ? void 0 : deviceInfo.udid) {
506
+ if (deviceInfo?.udid) {
441
507
  this.deviceId = deviceInfo.udid;
442
508
  debugDevice(`Updated device ID to real UDID: ${this.deviceId}`);
443
509
  }
@@ -518,19 +584,9 @@ ScreenSize: ${size.width}x${size.height} (DPR: ${size.scale})
518
584
  if (!element) return;
519
585
  await this.tap(element.center[0], element.center[1]);
520
586
  await sleep(100);
521
- try {
522
- await this.tripleTap(element.center[0], element.center[1]);
523
- await sleep(200);
524
- await this.wdaBackend.typeText(BackspaceChar);
525
- } catch (error2) {
526
- debugDevice(`Method 1 failed, trying method 2: ${error2}`);
527
- try {
528
- const backspaces = Array(100).fill(BackspaceChar).join('');
529
- await this.wdaBackend.typeText(backspaces);
530
- } catch (error3) {
531
- debugDevice(`All clear methods failed: ${error3}`);
532
- }
533
- }
587
+ debugDevice('Attempting to clear input with WebDriver Clear API');
588
+ const cleared = await this.wdaBackend.clearActiveElement();
589
+ cleared ? debugDevice('Successfully cleared input with WebDriver Clear API') : debugDevice('WebDriver Clear API returned false (no active element or clear failed)');
534
590
  }
535
591
  async url() {
536
592
  return '';
@@ -555,9 +611,8 @@ ScreenSize: ${size.width}x${size.height} (DPR: ${size.scale})
555
611
  await this.wdaBackend.swipe(Math.round(fromX), Math.round(fromY), Math.round(toX), Math.round(toY), duration);
556
612
  }
557
613
  async typeText(text, options) {
558
- var _this_options;
559
614
  if (!text) return;
560
- const shouldAutoDismissKeyboard = (null == options ? void 0 : options.autoDismissKeyboard) ?? (null == (_this_options = this.options) ? void 0 : _this_options.autoDismissKeyboard) ?? true;
615
+ const shouldAutoDismissKeyboard = options?.autoDismissKeyboard ?? this.options?.autoDismissKeyboard ?? true;
561
616
  debugDevice(`Typing text: "${text}"`);
562
617
  try {
563
618
  await sleep(200);
@@ -759,20 +814,30 @@ ScreenSize: ${size.width}x${size.height} (DPR: ${size.scale})
759
814
  }
760
815
  async hideKeyboard(keyNames) {
761
816
  try {
762
- if (keyNames && keyNames.length > 0) {
763
- debugDevice(`Using keyNames to dismiss keyboard: ${keyNames.join(', ')}`);
764
- await this.wdaBackend.dismissKeyboard(keyNames);
765
- debugDevice('Dismissed keyboard using provided keyNames');
766
- await sleep(300);
817
+ const dismissKeys = keyNames && keyNames.length > 0 ? keyNames : [
818
+ 'return',
819
+ 'done',
820
+ 'go',
821
+ 'search',
822
+ 'next',
823
+ 'send'
824
+ ];
825
+ debugDevice(`Attempting to dismiss keyboard using WDA API with keys: ${dismissKeys.join(', ')}`);
826
+ try {
827
+ await this.wdaBackend.dismissKeyboard(dismissKeys);
828
+ debugDevice('Successfully dismissed keyboard using WDA API');
829
+ await sleep(500);
767
830
  return true;
831
+ } catch (wdaError) {
832
+ debugDevice(`WDA dismissKeyboard failed, falling back to swipe gesture: ${wdaError}`);
768
833
  }
769
834
  const windowSize = await this.wdaBackend.getWindowSize();
770
835
  const centerX = Math.round(windowSize.width / 2);
771
- const startY = Math.round(0.33 * windowSize.height);
772
- const endY = Math.round(0.33 * windowSize.height + 10);
773
- await this.swipe(centerX, startY, centerX, endY, 50);
774
- debugDevice('Dismissed keyboard with swipe down gesture at screen one-third position');
775
- await sleep(300);
836
+ const startY = Math.round(0.9 * windowSize.height);
837
+ const endY = Math.round(0.5 * windowSize.height);
838
+ await this.swipe(centerX, startY, centerX, endY, 300);
839
+ debugDevice('Dismissed keyboard with swipe up gesture from bottom of screen');
840
+ await sleep(500);
776
841
  return true;
777
842
  } catch (error) {
778
843
  debugDevice(`Failed to hide keyboard: ${error}`);
@@ -801,6 +866,7 @@ ScreenSize: ${size.width}x${size.height} (DPR: ${size.scale})
801
866
  async openUrlViaSafari(url) {
802
867
  try {
803
868
  debugDevice(`Opening URL via Safari: ${url}`);
869
+ await this.wdaBackend.terminateApp('com.apple.mobilesafari');
804
870
  await this.wdaBackend.launchApp('com.apple.mobilesafari');
805
871
  await sleep(2000);
806
872
  await this.typeText(url);
@@ -818,6 +884,9 @@ ScreenSize: ${size.width}x${size.height} (DPR: ${size.scale})
818
884
  throw new Error(`Failed to open URL via Safari: ${error}`);
819
885
  }
820
886
  }
887
+ async runWdaRequest(method, endpoint, data) {
888
+ return await this.wdaBackend.executeRequest(method, endpoint, data);
889
+ }
821
890
  async destroy() {
822
891
  if (this.destroyed) return;
823
892
  try {
@@ -843,9 +912,9 @@ ScreenSize: ${size.width}x${size.height} (DPR: ${size.scale})
843
912
  _define_property(this, "options", void 0);
844
913
  this.deviceId = 'pending-connection';
845
914
  this.options = options;
846
- this.customActions = null == options ? void 0 : options.customActions;
847
- const wdaPort = (null == options ? void 0 : options.wdaPort) || DEFAULT_WDA_PORT;
848
- const wdaHost = (null == options ? void 0 : options.wdaHost) || 'localhost';
915
+ this.customActions = options?.customActions;
916
+ const wdaPort = options?.wdaPort || DEFAULT_WDA_PORT;
917
+ const wdaHost = options?.wdaHost || 'localhost';
849
918
  this.wdaBackend = new IOSWebDriverClient({
850
919
  port: wdaPort,
851
920
  host: wdaHost
@@ -853,6 +922,44 @@ ScreenSize: ${size.width}x${size.height} (DPR: ${size.scale})
853
922
  this.wdaManager = WDAManager.getInstance(wdaPort, wdaHost);
854
923
  }
855
924
  }
925
+ const runWdaRequestParamSchema = z.object({
926
+ method: z["enum"](WDA_HTTP_METHODS).describe('HTTP method (GET, POST, DELETE, PUT)'),
927
+ endpoint: z.string().describe('WebDriver API endpoint'),
928
+ data: z.object({}).passthrough().optional().describe('Optional request body data as JSON object')
929
+ });
930
+ const launchParamSchema = z.string().describe('App bundle ID or URL to launch');
931
+ const createPlatformActions = (device)=>({
932
+ RunWdaRequest: defineAction({
933
+ name: 'RunWdaRequest',
934
+ description: 'Execute WebDriverAgent API request directly on iOS device',
935
+ interfaceAlias: 'runWdaRequest',
936
+ paramSchema: runWdaRequestParamSchema,
937
+ call: async (param)=>await device.runWdaRequest(param.method, param.endpoint, param.data)
938
+ }),
939
+ Launch: defineAction({
940
+ name: 'Launch',
941
+ description: 'Launch an iOS app or URL',
942
+ interfaceAlias: 'launch',
943
+ paramSchema: launchParamSchema,
944
+ call: async (param)=>{
945
+ await device.launch(param);
946
+ }
947
+ }),
948
+ IOSHomeButton: defineAction({
949
+ name: 'IOSHomeButton',
950
+ description: 'Trigger the system "home" operation on iOS devices',
951
+ call: async ()=>{
952
+ await device.home();
953
+ }
954
+ }),
955
+ IOSAppSwitcher: defineAction({
956
+ name: 'IOSAppSwitcher',
957
+ description: 'Trigger the system "app switcher" operation on iOS devices',
958
+ call: async ()=>{
959
+ await device.appSwitcher();
960
+ }
961
+ })
962
+ });
856
963
  const execAsync = promisify(exec);
857
964
  const debugUtils = getDebug('ios:utils');
858
965
  function checkMacOSPlatform() {
@@ -899,24 +1006,35 @@ async function checkIOSEnvironment() {
899
1006
  };
900
1007
  }
901
1008
  }
1009
+ function agent_define_property(obj, key, value) {
1010
+ if (key in obj) Object.defineProperty(obj, key, {
1011
+ value: value,
1012
+ enumerable: true,
1013
+ configurable: true,
1014
+ writable: true
1015
+ });
1016
+ else obj[key] = value;
1017
+ return obj;
1018
+ }
902
1019
  const debugAgent = getDebug('ios:agent');
903
1020
  class IOSAgent extends Agent {
904
- async launch(uri) {
905
- const device = this.page;
906
- await device.launch(uri);
1021
+ createActionWrapper(name) {
1022
+ const action = this.wrapActionInActionSpace(name);
1023
+ return (...args)=>action(args[0]);
1024
+ }
1025
+ constructor(device, opts){
1026
+ super(device, opts), agent_define_property(this, "launch", void 0), agent_define_property(this, "runWdaRequest", void 0), agent_define_property(this, "home", void 0), agent_define_property(this, "appSwitcher", void 0);
1027
+ this.launch = this.createActionWrapper('Launch');
1028
+ this.runWdaRequest = this.createActionWrapper('RunWdaRequest');
1029
+ this.home = this.createActionWrapper('IOSHomeButton');
1030
+ this.appSwitcher = this.createActionWrapper('IOSAppSwitcher');
907
1031
  }
908
1032
  }
909
1033
  async function agentFromWebDriverAgent(opts) {
910
1034
  debugAgent('Creating iOS agent with WebDriverAgent auto-detection');
911
1035
  const envCheck = await checkIOSEnvironment();
912
1036
  if (!envCheck.available) throw new Error(`iOS environment not available: ${envCheck.error}`);
913
- const device = new IOSDevice({
914
- autoDismissKeyboard: null == opts ? void 0 : opts.autoDismissKeyboard,
915
- customActions: null == opts ? void 0 : opts.customActions,
916
- wdaPort: null == opts ? void 0 : opts.wdaPort,
917
- wdaHost: null == opts ? void 0 : opts.wdaHost,
918
- useWDA: null == opts ? void 0 : opts.useWDA
919
- });
1037
+ const device = new IOSDevice(opts || {});
920
1038
  await device.connect();
921
1039
  return new IOSAgent(device, opts);
922
1040
  }