appium-xcuitest-driver 10.14.1 → 10.14.3

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 (74) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/build/lib/commands/alert.d.ts +26 -31
  3. package/build/lib/commands/alert.d.ts.map +1 -1
  4. package/build/lib/commands/alert.js +20 -29
  5. package/build/lib/commands/alert.js.map +1 -1
  6. package/build/lib/commands/appearance.d.ts +7 -9
  7. package/build/lib/commands/appearance.d.ts.map +1 -1
  8. package/build/lib/commands/appearance.js +13 -19
  9. package/build/lib/commands/appearance.js.map +1 -1
  10. package/build/lib/commands/execute.d.ts +10 -22
  11. package/build/lib/commands/execute.d.ts.map +1 -1
  12. package/build/lib/commands/execute.js +12 -28
  13. package/build/lib/commands/execute.js.map +1 -1
  14. package/build/lib/commands/location.d.ts +8 -11
  15. package/build/lib/commands/location.d.ts.map +1 -1
  16. package/build/lib/commands/location.js +7 -15
  17. package/build/lib/commands/location.js.map +1 -1
  18. package/build/lib/commands/navigation.d.ts +14 -26
  19. package/build/lib/commands/navigation.d.ts.map +1 -1
  20. package/build/lib/commands/navigation.js +10 -18
  21. package/build/lib/commands/navigation.js.map +1 -1
  22. package/build/lib/commands/pcap.d.ts +18 -38
  23. package/build/lib/commands/pcap.d.ts.map +1 -1
  24. package/build/lib/commands/pcap.js +9 -14
  25. package/build/lib/commands/pcap.js.map +1 -1
  26. package/build/lib/commands/permissions.d.ts +15 -17
  27. package/build/lib/commands/permissions.d.ts.map +1 -1
  28. package/build/lib/commands/permissions.js +12 -18
  29. package/build/lib/commands/permissions.js.map +1 -1
  30. package/build/lib/commands/proxy-helper.d.ts +11 -11
  31. package/build/lib/commands/proxy-helper.d.ts.map +1 -1
  32. package/build/lib/commands/proxy-helper.js +15 -24
  33. package/build/lib/commands/proxy-helper.js.map +1 -1
  34. package/build/lib/commands/screenshots.d.ts +15 -9
  35. package/build/lib/commands/screenshots.d.ts.map +1 -1
  36. package/build/lib/commands/screenshots.js +13 -11
  37. package/build/lib/commands/screenshots.js.map +1 -1
  38. package/build/lib/commands/simctl.d.ts +16 -22
  39. package/build/lib/commands/simctl.d.ts.map +1 -1
  40. package/build/lib/commands/simctl.js +8 -17
  41. package/build/lib/commands/simctl.js.map +1 -1
  42. package/build/lib/commands/source.d.ts +10 -8
  43. package/build/lib/commands/source.d.ts.map +1 -1
  44. package/build/lib/commands/source.js +11 -14
  45. package/build/lib/commands/source.js.map +1 -1
  46. package/build/lib/commands/timeouts.d.ts +25 -32
  47. package/build/lib/commands/timeouts.d.ts.map +1 -1
  48. package/build/lib/commands/timeouts.js +18 -14
  49. package/build/lib/commands/timeouts.js.map +1 -1
  50. package/build/lib/driver.js +1 -1
  51. package/build/lib/driver.js.map +1 -1
  52. package/build/lib/execute-method-map.d.ts.map +1 -1
  53. package/build/lib/execute-method-map.js +0 -2
  54. package/build/lib/execute-method-map.js.map +1 -1
  55. package/lib/commands/alert.ts +98 -0
  56. package/lib/commands/appearance.ts +70 -0
  57. package/lib/commands/{execute.js → execute.ts} +41 -37
  58. package/lib/commands/{location.js → location.ts} +19 -22
  59. package/lib/commands/{navigation.js → navigation.ts} +23 -26
  60. package/lib/commands/{pcap.js → pcap.ts} +28 -28
  61. package/lib/commands/permissions.ts +90 -0
  62. package/lib/commands/{proxy-helper.js → proxy-helper.ts} +26 -26
  63. package/lib/commands/{screenshots.js → screenshots.ts} +24 -16
  64. package/lib/commands/{simctl.js → simctl.ts} +27 -21
  65. package/lib/commands/{source.js → source.ts} +23 -20
  66. package/lib/commands/timeouts.ts +95 -0
  67. package/lib/driver.ts +1 -1
  68. package/lib/execute-method-map.ts +0 -2
  69. package/npm-shrinkwrap.json +5 -5
  70. package/package.json +1 -1
  71. package/lib/commands/alert.js +0 -88
  72. package/lib/commands/appearance.js +0 -71
  73. package/lib/commands/permissions.js +0 -85
  74. package/lib/commands/timeouts.js +0 -68
@@ -2,19 +2,23 @@ import {retryInterval} from 'asyncbox';
2
2
  import _ from 'lodash';
3
3
  import {errors} from 'appium/driver';
4
4
  import {util, imageUtil} from 'appium/support';
5
+ import type {XCUITestDriver} from '../driver';
6
+ import type {Simulator} from 'appium-ios-simulator';
7
+ import type {Element} from '@appium/types';
5
8
 
6
9
  /**
7
- * @this {XCUITestDriver}
8
- * @returns {Promise<string>}
10
+ * Takes a screenshot of the current screen.
11
+ *
12
+ * @returns Base64-encoded screenshot data
9
13
  */
10
- export async function getScreenshot() {
14
+ export async function getScreenshot(this: XCUITestDriver): Promise<string> {
11
15
  if (this.isWebContext()) {
12
16
  const webScreenshotMode = (await this.settings.getSettings()).webScreenshotMode;
13
17
  switch (_.toLower(webScreenshotMode)) {
14
18
  case 'page':
15
19
  case 'viewport':
16
20
  return await this.remote.captureScreenshot({
17
- coordinateSystem: /** @type {'Viewport'|'Page'} */ (_.capitalize(webScreenshotMode)),
21
+ coordinateSystem: _.capitalize(webScreenshotMode) as 'Viewport' | 'Page',
18
22
  });
19
23
  case 'native':
20
24
  case undefined:
@@ -29,7 +33,7 @@ export async function getScreenshot() {
29
33
  }
30
34
  }
31
35
 
32
- const getScreenshotFromWDA = async () => {
36
+ const getScreenshotFromWDA = async (): Promise<string> => {
33
37
  this.log.debug(`Taking screenshot with WDA`);
34
38
  const data = await this.proxyCommand('/screenshot', 'GET');
35
39
  if (!_.isString(data)) {
@@ -53,14 +57,14 @@ export async function getScreenshot() {
53
57
 
54
58
  try {
55
59
  return await getScreenshotFromWDA();
56
- } catch (err) {
60
+ } catch (err: any) {
57
61
  this.log.warn(`Error getting screenshot: ${err.message}`);
58
62
  }
59
63
 
60
64
  // simulator attempt
61
65
  if (this.isSimulator()) {
62
66
  this.log.info(`Falling back to 'simctl io screenshot' API`);
63
- const payload = await /** @type {import('appium-ios-simulator').Simulator} */ (this.device).simctl.getScreenshot();
67
+ const payload = await (this.device as Simulator).simctl.getScreenshot();
64
68
  if (!payload) {
65
69
  throw new errors.UnableToCaptureScreen();
66
70
  }
@@ -68,13 +72,19 @@ export async function getScreenshot() {
68
72
  }
69
73
 
70
74
  // Retry for real devices only. Fail fast on Simulator if simctl does not work as expected
71
- return /** @type {string} */ (await retryInterval(2, 1000, getScreenshotFromWDA));
75
+ return await retryInterval(2, 1000, getScreenshotFromWDA) as string;
72
76
  }
73
77
 
74
78
  /**
75
- * @this {XCUITestDriver}
79
+ * Takes a screenshot of a specific element.
80
+ *
81
+ * @param el - Element to capture
82
+ * @returns Base64-encoded screenshot data
76
83
  */
77
- export async function getElementScreenshot(el) {
84
+ export async function getElementScreenshot(
85
+ this: XCUITestDriver,
86
+ el: Element<string> | string,
87
+ ): Promise<string> {
78
88
  el = util.unwrapElement(el);
79
89
  if (this.isWebContext()) {
80
90
  const atomsElement = this.getAtomsElement(el);
@@ -96,10 +106,11 @@ export async function getElementScreenshot(el) {
96
106
  }
97
107
 
98
108
  /**
99
- * @this {XCUITestDriver}
100
- * @returns {Promise<string>}
109
+ * Takes a screenshot of the current viewport.
110
+ *
111
+ * @returns Base64-encoded screenshot data
101
112
  */
102
- export async function getViewportScreenshot() {
113
+ export async function getViewportScreenshot(this: XCUITestDriver): Promise<string> {
103
114
  if (this.isWebContext()) {
104
115
  return await this.remote.captureScreenshot();
105
116
  }
@@ -130,6 +141,3 @@ export async function getViewportScreenshot() {
130
141
  return await imageUtil.cropBase64Image(screenshot, region);
131
142
  }
132
143
 
133
- /**
134
- * @typedef {import('../driver').XCUITestDriver} XCUITestDriver
135
- */
@@ -1,4 +1,6 @@
1
1
  import { errors } from 'appium/driver';
2
+ import type {XCUITestDriver} from '../driver';
3
+ import type {Simulator} from 'appium-ios-simulator';
2
4
 
3
5
  /**
4
6
  * List of subcommands for `simctl` we provide as mobile simctl command.
@@ -27,19 +29,33 @@ const SUBCOMMANDS_HAS_DEVICE = [
27
29
  'terminate',
28
30
  'ui',
29
31
  'uninstall'
30
- ];
32
+ ] as const;
33
+
34
+ export interface SimctlExecResponse {
35
+ /** The output of standard out. */
36
+ stdout: string;
37
+ /** The output of standard error. */
38
+ stderr: string;
39
+ /** Return code. */
40
+ code: number;
41
+ }
31
42
 
32
43
  /**
33
44
  * Run the given command with arguments as `xcrun simctl` subcommand.
34
45
  * This method works behind the 'simctl' security flag.
35
- * @this {XCUITestDriver}
36
- * @param {string} command Subcommand to run with `xcrun simctl`
37
- * @param {string[]} [args=[]] arguments for the subcommand. The arguments should be after <device> in the help.
38
- * @param {number|undefined} timeout - The maximum number of milliseconds
39
- * @returns {Promise<SimctlExecResponse>}
40
- * @throws {Error} If the simctl subcommand command returns non-zero return code, or the given subcommand was invalid.
46
+ *
47
+ * @param command - Subcommand to run with `xcrun simctl`. Must be one of the supported commands.
48
+ * @param args - Arguments for the subcommand. The arguments should be after <device> in the help.
49
+ * @param timeout - The maximum number of milliseconds
50
+ * @returns The execution result with stdout, stderr, and return code
51
+ * @throws If the simctl subcommand command returns non-zero return code, or the given subcommand was invalid.
41
52
  */
42
- export async function mobileSimctl(command, args = [], timeout = undefined) {
53
+ export async function mobileSimctl(
54
+ this: XCUITestDriver,
55
+ command: string,
56
+ args: string[] = [],
57
+ timeout?: number,
58
+ ): Promise<SimctlExecResponse> {
43
59
  if (!this.isSimulator()) {
44
60
  throw new errors.UnsupportedOperationError(`Only simulator is supported.`);
45
61
  }
@@ -48,13 +64,13 @@ export async function mobileSimctl(command, args = [], timeout = undefined) {
48
64
  throw new errors.InvalidArgumentError(`Unknown device or simulator UDID: '${this.opts.udid}'`);
49
65
  }
50
66
 
51
- if (!SUBCOMMANDS_HAS_DEVICE.includes(command)) {
67
+ if (!(SUBCOMMANDS_HAS_DEVICE as readonly string[]).includes(command)) {
52
68
  throw new errors.InvalidArgumentError(`The given command '${command}' is not supported. ` +
53
69
  `Available subcommands are ${SUBCOMMANDS_HAS_DEVICE.join(',')}`);
54
70
  }
55
71
 
56
- const result = await /** @type {import('appium-ios-simulator').Simulator} */ (this.device).simctl.exec(
57
- command,
72
+ const result = await (this.device as Simulator).simctl.exec(
73
+ command as typeof SUBCOMMANDS_HAS_DEVICE[number],
58
74
  {args: [this.opts.udid, ...args], timeout}
59
75
  );
60
76
  return {
@@ -64,13 +80,3 @@ export async function mobileSimctl(command, args = [], timeout = undefined) {
64
80
  };
65
81
  }
66
82
 
67
- /**
68
- * @typedef {Object} SimctlExecResponse
69
- * @property {string} stdout The output of standard out.
70
- * @property {string} stderr The output of standard error.
71
- * @property {number} code Return code.
72
- */
73
-
74
- /**
75
- * @typedef {import('../driver').XCUITestDriver} XCUITestDriver
76
- */
@@ -1,12 +1,16 @@
1
1
  import _ from 'lodash';
2
2
  import js2xml from 'js2xmlparser2';
3
+ import type {XCUITestDriver} from '../driver';
4
+ import type {SourceFormat} from './types';
3
5
 
4
6
  const APPIUM_AUT_TAG = 'AppiumAUT';
5
7
 
6
8
  /**
7
- * @this {XCUITestDriver}
9
+ * Retrieves the page source of the current application.
10
+ *
11
+ * @returns The page source as XML or HTML string
8
12
  */
9
- export async function getPageSource() {
13
+ export async function getPageSource(this: XCUITestDriver): Promise<string> {
10
14
  if (this.isWebContext()) {
11
15
  const script = 'return document.documentElement.outerHTML';
12
16
  return await this.executeAtom('execute_script', [script, []]);
@@ -28,14 +32,17 @@ export async function getPageSource() {
28
32
  /**
29
33
  * Retrieve the source tree of the current page in XML or JSON format.
30
34
  *
31
- * @param {import('./types').SourceFormat} format - Page tree source representation format.
32
- * @param {string} [excludedAttributes] A comma-separated string of attribute names to exclude from the output. Only works if `format` is `xml`.
35
+ * @param format - Page tree source representation format.
36
+ * @param excludedAttributes - A comma-separated string of attribute names to exclude from the output. Only works if `format` is `xml`.
33
37
  * @privateRemarks Why isn't `excludedAttributes` an array?
34
- * @returns {Promise<string>} The source tree of the current page in the given format.
35
- * @this {XCUITestDriver}
38
+ * @returns The source tree of the current page in the given format.
36
39
  */
37
- export async function mobileGetSource(format = 'xml', excludedAttributes) {
38
- const paramsMap = {
40
+ export async function mobileGetSource(
41
+ this: XCUITestDriver,
42
+ format: SourceFormat = 'xml',
43
+ excludedAttributes?: string,
44
+ ): Promise<string> {
45
+ const paramsMap: Record<string, string> = {
39
46
  format,
40
47
  scope: APPIUM_AUT_TAG,
41
48
  };
@@ -45,7 +52,7 @@ export async function mobileGetSource(format = 'xml', excludedAttributes) {
45
52
  const query = Object.entries(paramsMap)
46
53
  .map(([k, v]) => `${encodeURIComponent(k)}=${encodeURIComponent(v)}`)
47
54
  .join('&');
48
- return /** @type {string} */ (await this.proxyCommand(`/source?${query}`, 'GET'));
55
+ return await this.proxyCommand(`/source?${query}`, 'GET') as string;
49
56
  }
50
57
 
51
58
  /**
@@ -76,15 +83,14 @@ export async function mobileGetSource(format = 'xml', excludedAttributes) {
76
83
  * rawIdentifier: null }
77
84
  * ```
78
85
  */
79
- function getTreeForXML(srcTree) {
80
- function getTree(element, elementIndex, parentPath) {
81
- let curPath = `${parentPath}/${elementIndex}`;
82
- let rect = element.rect || {};
86
+ function getTreeForXML(srcTree: any): any {
87
+ function getTree(element: any, elementIndex: number, parentPath: string): any {
88
+ const curPath = `${parentPath}/${elementIndex}`;
89
+ const rect = element.rect || {};
83
90
  /**
84
91
  * @privateRemarks I don't even want to try to type this right now
85
- * @type {any}
86
92
  */
87
- let subtree = {
93
+ const subtree: any = {
88
94
  '@': {
89
95
  type: `XCUIElementType${element.type}`,
90
96
  enabled: parseInt(element.isEnabled, 10) === 1,
@@ -114,11 +120,11 @@ function getTreeForXML(srcTree) {
114
120
  [`XCUIElementType${element.type}`]: subtree,
115
121
  };
116
122
  }
117
- let tree = getTree(srcTree, 0, '');
123
+ const tree = getTree(srcTree, 0, '');
118
124
  return tree;
119
125
  }
120
126
 
121
- function getSourceXml(jsonSource) {
127
+ function getSourceXml(jsonSource: any): string {
122
128
  return js2xml('AppiumAUT', jsonSource, {
123
129
  wrapArray: {enabled: false, elementName: 'element'},
124
130
  declaration: {include: true},
@@ -126,6 +132,3 @@ function getSourceXml(jsonSource) {
126
132
  });
127
133
  }
128
134
 
129
- /**
130
- * @typedef {import('../driver').XCUITestDriver} XCUITestDriver
131
- */
@@ -0,0 +1,95 @@
1
+ import type {XCUITestDriver} from '../driver';
2
+
3
+ /**
4
+ * Sets the page load timeout using W3C protocol.
5
+ *
6
+ * @param ms - Timeout in milliseconds
7
+ */
8
+ export async function pageLoadTimeoutW3C(
9
+ this: XCUITestDriver,
10
+ ms: number,
11
+ ): Promise<void> {
12
+ await this.setPageLoadTimeout(this.parseTimeoutArgument(ms));
13
+ }
14
+
15
+ /**
16
+ * Sets the page load timeout using MJSONWP protocol.
17
+ *
18
+ * @param ms - Timeout in milliseconds
19
+ */
20
+ export async function pageLoadTimeoutMJSONWP(
21
+ this: XCUITestDriver,
22
+ ms: number,
23
+ ): Promise<void> {
24
+ await this.setPageLoadTimeout(this.parseTimeoutArgument(ms));
25
+ }
26
+
27
+ /**
28
+ * Sets the async script timeout using W3C protocol.
29
+ *
30
+ * @param ms - Timeout in milliseconds
31
+ */
32
+ export async function scriptTimeoutW3C(
33
+ this: XCUITestDriver,
34
+ ms: number,
35
+ ): Promise<void> {
36
+ // XXX: this is synchronous
37
+ await this.setAsyncScriptTimeout(this.parseTimeoutArgument(ms));
38
+ }
39
+
40
+ /**
41
+ * Alias for {@linkcode XCUITestDriver.scriptTimeoutW3C}.
42
+ *
43
+ * @param ms - The timeout in milliseconds
44
+ * @deprecated Use {@linkcode XCUITestDriver.scriptTimeoutW3C} instead
45
+ */
46
+ export async function scriptTimeoutMJSONWP(
47
+ this: XCUITestDriver,
48
+ ms: number,
49
+ ): Promise<void> {
50
+ await this.asyncScriptTimeout(ms);
51
+ }
52
+
53
+ /**
54
+ * Alias for {@linkcode XCUITestDriver.scriptTimeoutW3C}.
55
+ *
56
+ * @param ms - The timeout in milliseconds
57
+ * @deprecated Use {@linkcode XCUITestDriver.scriptTimeoutW3C} instead
58
+ */
59
+ export async function asyncScriptTimeout(
60
+ this: XCUITestDriver,
61
+ ms: number,
62
+ ): Promise<void> {
63
+ await this.scriptTimeoutW3C(ms);
64
+ }
65
+
66
+ /**
67
+ * Sets the page load timeout.
68
+ *
69
+ * @param ms - Timeout in milliseconds
70
+ */
71
+ export function setPageLoadTimeout(
72
+ this: XCUITestDriver,
73
+ ms: number,
74
+ ): void {
75
+ ms = parseInt(String(ms), 10);
76
+ this.pageLoadMs = ms;
77
+ if (this._remote) {
78
+ this.remote.pageLoadMs = ms;
79
+ }
80
+ this.log.debug(`Set page load timeout to ${ms}ms`);
81
+ }
82
+
83
+ /**
84
+ * Sets the async script timeout.
85
+ *
86
+ * @param ms - Timeout in milliseconds
87
+ */
88
+ export function setAsyncScriptTimeout(
89
+ this: XCUITestDriver,
90
+ ms: number,
91
+ ): void {
92
+ this.asyncWaitMs = ms;
93
+ this.log.debug(`Set async script timeout to ${ms}ms`);
94
+ }
95
+
package/lib/driver.ts CHANGED
@@ -500,7 +500,7 @@ export class XCUITestDriver
500
500
  this.log.debug(`Executing command '${cmd}'`);
501
501
 
502
502
  if (cmd === 'receiveAsyncResponse') {
503
- return await this.receiveAsyncResponse(...args);
503
+ return await this.receiveAsyncResponse(args[0], args[1]);
504
504
  }
505
505
  // TODO: once this fix gets into base driver remove from here
506
506
  if (cmd === 'getStatus') {
@@ -466,14 +466,12 @@ export const executeMethodMap = {
466
466
  command: 'mobileResetLocationService',
467
467
  },
468
468
  'mobile: startPcap': {
469
- // @ts-expect-error Method exists on XCUITestDriver but is defined in pcap.js (JS file), so TypeScript can't verify it
470
469
  command: 'mobileStartPcap',
471
470
  params: {
472
471
  optional: ['timeLimitSec', 'forceRestart'],
473
472
  },
474
473
  },
475
474
  'mobile: stopPcap': {
476
- // @ts-expect-error Method exists on XCUITestDriver but is defined in pcap.js (JS file), so TypeScript can't verify it
477
475
  command: 'mobileStopPcap',
478
476
  },
479
477
  'mobile: listConditionInducers': {
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "appium-xcuitest-driver",
3
- "version": "10.14.1",
3
+ "version": "10.14.3",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "appium-xcuitest-driver",
9
- "version": "10.14.1",
9
+ "version": "10.14.3",
10
10
  "license": "Apache-2.0",
11
11
  "dependencies": {
12
12
  "@appium/strongbox": "^1.0.0-rc.1",
@@ -692,9 +692,9 @@
692
692
  }
693
693
  },
694
694
  "node_modules/appium-ios-remotexpc": {
695
- "version": "0.21.1",
696
- "resolved": "https://registry.npmjs.org/appium-ios-remotexpc/-/appium-ios-remotexpc-0.21.1.tgz",
697
- "integrity": "sha512-E3dJxiZQEivGLRWMkFZMd3PSc1eT8V4uhJ/xAtwZxrIKYHYIVEvWeDQ6YHydGu9Jq1soX2aZFfBgfHIPeE8SSg==",
695
+ "version": "0.24.1",
696
+ "resolved": "https://registry.npmjs.org/appium-ios-remotexpc/-/appium-ios-remotexpc-0.24.1.tgz",
697
+ "integrity": "sha512-LJ83A/cHx+CFOX9yGLoG+bsfgYiJdN1PSBDDe7FkZ/C6DGTi+5zvDxOwaBSLmhgEh6uae40EGK8/FbFiKwR4Kg==",
698
698
  "license": "Apache-2.0",
699
699
  "optional": true,
700
700
  "dependencies": {
package/package.json CHANGED
@@ -8,7 +8,7 @@
8
8
  "xcuitest",
9
9
  "xctest"
10
10
  ],
11
- "version": "10.14.1",
11
+ "version": "10.14.3",
12
12
  "author": "Appium Contributors",
13
13
  "license": "Apache-2.0",
14
14
  "repository": {
@@ -1,88 +0,0 @@
1
- /**
2
- * @this {XCUITestDriver}
3
- */
4
- export async function getAlertText() {
5
- return /** @type {string|null} */ (await this.proxyCommand('/alert/text', 'GET'));
6
- }
7
-
8
- /**
9
- * @param {string} value
10
- * @this {XCUITestDriver}
11
- * @returns {Promise<void>}
12
- */
13
- export async function setAlertText(value) {
14
- await this.proxyCommand('/alert/text', 'POST', {value});
15
- }
16
-
17
- /**
18
- * @param { {buttonLabel?: string} } opts
19
- * @returns {Promise<void>}
20
- * @this {XCUITestDriver}
21
- */
22
- export async function postAcceptAlert(opts = {}) {
23
- await this.proxyCommand('/alert/accept', 'POST', toAlertParams(opts));
24
- }
25
-
26
- /**
27
- * @param { {buttonLabel?: string} } opts
28
- * @returns {Promise<void>}
29
- * @this {XCUITestDriver}
30
- */
31
- export async function postDismissAlert(opts = {}) {
32
- await this.proxyCommand('/alert/dismiss', 'POST', toAlertParams(opts));
33
- }
34
-
35
- /**
36
- * @internal
37
- * @this {XCUITestDriver}
38
- * @returns {Promise<string[]>} The list of button labels
39
- */
40
- export async function getAlertButtons() {
41
- return /** @type {string[]} */ (await this.proxyCommand('/wda/alert/buttons', 'GET'));
42
- }
43
-
44
- /**
45
- * Tries to apply the given action to the currently visible alert.
46
- *
47
- * @param {AlertAction} action - The actual action to apply.
48
- * @param {string} [buttonLabel] - The name of the button used to perform the chosen alert action. Only makes sense if the action is `accept` or `dismiss`.
49
- * @returns {Promise<string[]|void>} If `action` is `getButtons`, a list of alert button labelsp; otherwise nothing.
50
- * @remarks This should really be separate commands.
51
- * @this {XCUITestDriver}
52
- */
53
- export async function mobileHandleAlert(action, buttonLabel) {
54
- switch (action) {
55
- case 'accept':
56
- return await this.postAcceptAlert({buttonLabel});
57
- case 'dismiss':
58
- return await this.postDismissAlert({buttonLabel});
59
- case 'getButtons':
60
- return await this.getAlertButtons();
61
- default:
62
- throw new Error(
63
- `The 'action' value should be either 'accept', 'dismiss' or 'getButtons'. ` +
64
- `'${action}' is provided instead.`,
65
- );
66
- }
67
- }
68
-
69
- /**
70
- *
71
- * @param { {buttonLabel?: string} } opts
72
- * @returns { {name?: string} }
73
- */
74
- function toAlertParams(opts = {}) {
75
- const params = {};
76
- if (opts.buttonLabel) {
77
- params.name = opts.buttonLabel;
78
- }
79
- return params;
80
- }
81
-
82
- /**
83
- * @typedef {'accept'|'dismiss'|'getButtons'} AlertAction
84
- */
85
-
86
- /**
87
- * @typedef {import('../driver').XCUITestDriver} XCUITestDriver
88
- */
@@ -1,71 +0,0 @@
1
- import _ from 'lodash';
2
- import {util} from 'appium/support';
3
-
4
- /**
5
- * Set the device's UI appearance style
6
- *
7
- * @since iOS 12.0
8
- * @param {'dark'|'light'} style - The appearance style to set
9
- * @throws {Error} if the current platform does not support UI appearance changes
10
- * @this {XCUITestDriver}
11
- */
12
- export async function mobileSetAppearance(style) {
13
- if (!['light', 'dark'].includes(_.toLower(style))) {
14
- throw new Error(`The 'style' value is expected to equal either 'light' or 'dark'`);
15
- }
16
- if (util.compareVersions(/** @type {string} */ (this.opts.platformVersion), '<', '12.0')) {
17
- throw new Error('Changing appearance is only supported since iOS 12');
18
- }
19
-
20
- if (this.isSimulator()) {
21
- try {
22
- return void (await /** @type {import('appium-ios-simulator').Simulator} */ (this.device).setAppearance(style));
23
- } catch (e) {
24
- this.log.debug(e.stack);
25
- }
26
- }
27
- try {
28
- return void (await this.proxyCommand('/wda/device/appearance', 'POST', {name: style}, false));
29
- } catch (e) {
30
- this.log.debug(e.stack);
31
- }
32
- // Fall back to the ugly Siri workaround if the current SDK is too old
33
- await this.mobileSiriCommand(`Turn ${_.toLower(style) === 'dark' ? 'on' : 'off'} dark mode`);
34
- }
35
-
36
- /**
37
- * Get the device's UI appearance style.
38
- *
39
- * @since Xcode SDK 11
40
- * @returns {Promise<{style: Style}>}
41
- * @this {XCUITestDriver}
42
- */
43
- export async function mobileGetAppearance() {
44
- if (util.compareVersions(/** @type {string} */ (this.opts.platformVersion), '<', '12.0')) {
45
- return {style: 'unsupported'};
46
- }
47
-
48
- /** @type {Style|undefined} */
49
- let style;
50
- if (this.isSimulator()) {
51
- try {
52
- style = /** @type {Style} */ (
53
- await /** @type {import('appium-ios-simulator').Simulator} */ (this.device).getAppearance()
54
- );
55
- } catch {}
56
- }
57
- if (!style) {
58
- style = /** @type {Style} */ (
59
- /** @type {any} */ (await this.proxyCommand('/wda/device/info', 'GET'))
60
- ?.userInterfaceStyle ?? 'unknown'
61
- );
62
- }
63
- return {
64
- style,
65
- };
66
- }
67
-
68
- /**
69
- * @typedef {import('../driver').XCUITestDriver} XCUITestDriver
70
- * @typedef {import('./types').Style} Style
71
- */
@@ -1,85 +0,0 @@
1
- import _ from 'lodash';
2
- import {PermissionService} from './enum';
3
- import {assertSimulator as _assertSimulator} from '../utils';
4
-
5
- const assertSimulator = (driver) => _assertSimulator.call(driver, 'Permission-related operations');
6
-
7
- /**
8
- * Resets the given permission for the active application under test.
9
- * Works for both Simulator and real devices using Xcode SDK 11.4+
10
- *
11
- * @param {PermissionService|number} service - One of the available service names. This could also be an integer protected resource identifier; see [this list](https://developer.apple.com/documentation/xctest/xcuiprotectedresource?language=objc)
12
- * @throws {Error} If permission reset fails on the device.
13
- * @this {XCUITestDriver}
14
- */
15
- export async function mobileResetPermission(service) {
16
- if (!service) {
17
- throw new Error(`The 'service' option is expected to be present`);
18
- }
19
- let resource;
20
- if (_.isString(service)) {
21
- resource = PermissionService[_.toLower(service)];
22
- if (!resource) {
23
- throw new Error(
24
- `The 'service' value must be one of ` + `${JSON.stringify(_.keys(PermissionService))}`,
25
- );
26
- }
27
- } else if (_.isInteger(service)) {
28
- resource = service;
29
- } else {
30
- throw new Error(
31
- `The 'service' value must be either a string or an integer. ` +
32
- `'${service}' is passed instead`,
33
- );
34
- }
35
-
36
- await this.proxyCommand('/wda/resetAppAuth', 'POST', {resource});
37
- }
38
-
39
- /**
40
- * Gets application permission state on a simulated device.
41
- *
42
- * **This method requires [WIX applesimutils](https://github.com/wix/AppleSimulatorUtils) to be installed on the Appium server host.**
43
- *
44
- * @param {string} bundleId - Bundle identifier of the target application
45
- * @param {import('./enum').PermissionService} service - Service name
46
- * @returns {Promise<import('./types').PermissionState>} Either 'yes', 'no', 'unset' or 'limited'
47
- * @throws {Error} If permission getting fails or the device is not a Simulator.
48
- * @this {XCUITestDriver}
49
- * @group Simulator Only
50
- */
51
- export async function mobileGetPermission(bundleId, service) {
52
- if (!service) {
53
- throw new Error(`The 'service' option is expected to be present`);
54
- }
55
- assertSimulator(this);
56
-
57
- return /** @type {import('./types').PermissionState} */ (
58
- await /** @type {import('appium-ios-simulator').Simulator} */ (this.device).getPermission(
59
- bundleId, String(service)
60
- )
61
- );
62
- }
63
-
64
- /**
65
- * Set application permission state on Simulator.
66
- *
67
- * @param {Record<Partial<import('./types').AccessRule>, import('./types').PermissionState>} access - One or more access rules to set.
68
- * @param {string} bundleId - Bundle identifier of the target application
69
- * @since Xcode SDK 11.4
70
- * @throws {Error} If permission setting fails or the device is not a Simulator.
71
- * @group Simulator Only
72
- * @this {XCUITestDriver}
73
- */
74
- export async function mobileSetPermissions(access, bundleId) {
75
- if (!_.isPlainObject(access)) {
76
- throw new Error(`The 'access' option is expected to be a map`);
77
- }
78
- assertSimulator(this);
79
-
80
- await /** @type {import('appium-ios-simulator').Simulator} */ (this.device).setPermissions(bundleId, access);
81
- }
82
-
83
- /**
84
- * @typedef {import('../driver').XCUITestDriver} XCUITestDriver
85
- */