detox 20.27.7-smoke.0 → 20.28.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (85) hide show
  1. package/Detox-android/com/wix/detox/{20.27.7-smoke.0/detox-20.27.7-smoke.0-sources.jar → 20.28.0/detox-20.28.0-sources.jar} +0 -0
  2. package/Detox-android/com/wix/detox/20.28.0/detox-20.28.0-sources.jar.md5 +1 -0
  3. package/Detox-android/com/wix/detox/20.28.0/detox-20.28.0-sources.jar.sha1 +1 -0
  4. package/Detox-android/com/wix/detox/20.28.0/detox-20.28.0-sources.jar.sha256 +1 -0
  5. package/Detox-android/com/wix/detox/20.28.0/detox-20.28.0-sources.jar.sha512 +1 -0
  6. package/Detox-android/com/wix/detox/20.28.0/detox-20.28.0.aar +0 -0
  7. package/Detox-android/com/wix/detox/20.28.0/detox-20.28.0.aar.md5 +1 -0
  8. package/Detox-android/com/wix/detox/20.28.0/detox-20.28.0.aar.sha1 +1 -0
  9. package/Detox-android/com/wix/detox/20.28.0/detox-20.28.0.aar.sha256 +1 -0
  10. package/Detox-android/com/wix/detox/20.28.0/detox-20.28.0.aar.sha512 +1 -0
  11. package/Detox-android/com/wix/detox/{20.27.7-smoke.0/detox-20.27.7-smoke.0.pom → 20.28.0/detox-20.28.0.pom} +1 -1
  12. package/Detox-android/com/wix/detox/20.28.0/detox-20.28.0.pom.md5 +1 -0
  13. package/Detox-android/com/wix/detox/20.28.0/detox-20.28.0.pom.sha1 +1 -0
  14. package/Detox-android/com/wix/detox/20.28.0/detox-20.28.0.pom.sha256 +1 -0
  15. package/Detox-android/com/wix/detox/20.28.0/detox-20.28.0.pom.sha512 +1 -0
  16. package/Detox-android/com/wix/detox/maven-metadata.xml +4 -4
  17. package/Detox-android/com/wix/detox/maven-metadata.xml.md5 +1 -1
  18. package/Detox-android/com/wix/detox/maven-metadata.xml.sha1 +1 -1
  19. package/Detox-android/com/wix/detox/maven-metadata.xml.sha256 +1 -1
  20. package/Detox-android/com/wix/detox/maven-metadata.xml.sha512 +1 -1
  21. package/Detox-android/com/wix/detox-legacy/{20.27.7-smoke.0/detox-legacy-20.27.7-smoke.0-sources.jar → 20.28.0/detox-legacy-20.28.0-sources.jar} +0 -0
  22. package/Detox-android/com/wix/detox-legacy/20.28.0/detox-legacy-20.28.0-sources.jar.md5 +1 -0
  23. package/Detox-android/com/wix/detox-legacy/20.28.0/detox-legacy-20.28.0-sources.jar.sha1 +1 -0
  24. package/Detox-android/com/wix/detox-legacy/20.28.0/detox-legacy-20.28.0-sources.jar.sha256 +1 -0
  25. package/Detox-android/com/wix/detox-legacy/20.28.0/detox-legacy-20.28.0-sources.jar.sha512 +1 -0
  26. package/Detox-android/com/wix/detox-legacy/{20.27.7-smoke.0/detox-legacy-20.27.7-smoke.0.aar → 20.28.0/detox-legacy-20.28.0.aar} +0 -0
  27. package/Detox-android/com/wix/detox-legacy/20.28.0/detox-legacy-20.28.0.aar.md5 +1 -0
  28. package/Detox-android/com/wix/detox-legacy/20.28.0/detox-legacy-20.28.0.aar.sha1 +1 -0
  29. package/Detox-android/com/wix/detox-legacy/20.28.0/detox-legacy-20.28.0.aar.sha256 +1 -0
  30. package/Detox-android/com/wix/detox-legacy/20.28.0/detox-legacy-20.28.0.aar.sha512 +1 -0
  31. package/Detox-android/com/wix/detox-legacy/{20.27.7-smoke.0/detox-legacy-20.27.7-smoke.0.pom → 20.28.0/detox-legacy-20.28.0.pom} +1 -1
  32. package/Detox-android/com/wix/detox-legacy/20.28.0/detox-legacy-20.28.0.pom.md5 +1 -0
  33. package/Detox-android/com/wix/detox-legacy/20.28.0/detox-legacy-20.28.0.pom.sha1 +1 -0
  34. package/Detox-android/com/wix/detox-legacy/20.28.0/detox-legacy-20.28.0.pom.sha256 +1 -0
  35. package/Detox-android/com/wix/detox-legacy/20.28.0/detox-legacy-20.28.0.pom.sha512 +1 -0
  36. package/Detox-android/com/wix/detox-legacy/maven-metadata.xml +4 -4
  37. package/Detox-android/com/wix/detox-legacy/maven-metadata.xml.md5 +1 -1
  38. package/Detox-android/com/wix/detox-legacy/maven-metadata.xml.sha1 +1 -1
  39. package/Detox-android/com/wix/detox-legacy/maven-metadata.xml.sha256 +1 -1
  40. package/Detox-android/com/wix/detox-legacy/maven-metadata.xml.sha512 +1 -1
  41. package/Detox-ios-framework.tbz +0 -0
  42. package/Detox-ios-src.tbz +0 -0
  43. package/Detox-ios-xcuitest.tbz +0 -0
  44. package/android/detox/src/full/java/com/wix/detox/espresso/EspressoDetox.java +53 -2
  45. package/android/detox/src/full/java/com/wix/detox/espresso/UiAutomatorHelper.java +11 -0
  46. package/android/detox/src/full/java/com/wix/detox/espresso/matcher/IsDisplayingAtLeastDetoxMatcher.kt +2 -2
  47. package/android/detox/src/full/java/com/wix/detox/espresso/web/DetoxWebAtomMatcher.java +6 -9
  48. package/android/detox/src/full/java/com/wix/detox/espresso/web/WebElement.java +0 -4
  49. package/detox.d.ts +39 -0
  50. package/package.json +3 -3
  51. package/src/android/espressoapi/EspressoDetox.js +83 -0
  52. package/src/copilot/detoxCopilotFrameworkDriver.js +27 -15
  53. package/src/devices/runtime/RuntimeDevice.js +11 -0
  54. package/src/devices/runtime/drivers/DeviceDriverBase.js +8 -0
  55. package/src/devices/runtime/drivers/android/AndroidDriver.js +16 -0
  56. package/src/devices/runtime/drivers/ios/SimulatorDriver.js +35 -0
  57. package/src/utils/assertArgument.js +9 -0
  58. package/src/utils/invocationTraceDescriptions.js +1 -0
  59. package/src/utils/mapDeviceLongPressArguments.js +56 -0
  60. package/Detox-android/com/wix/detox/20.27.7-smoke.0/detox-20.27.7-smoke.0-sources.jar.md5 +0 -1
  61. package/Detox-android/com/wix/detox/20.27.7-smoke.0/detox-20.27.7-smoke.0-sources.jar.sha1 +0 -1
  62. package/Detox-android/com/wix/detox/20.27.7-smoke.0/detox-20.27.7-smoke.0-sources.jar.sha256 +0 -1
  63. package/Detox-android/com/wix/detox/20.27.7-smoke.0/detox-20.27.7-smoke.0-sources.jar.sha512 +0 -1
  64. package/Detox-android/com/wix/detox/20.27.7-smoke.0/detox-20.27.7-smoke.0.aar +0 -0
  65. package/Detox-android/com/wix/detox/20.27.7-smoke.0/detox-20.27.7-smoke.0.aar.md5 +0 -1
  66. package/Detox-android/com/wix/detox/20.27.7-smoke.0/detox-20.27.7-smoke.0.aar.sha1 +0 -1
  67. package/Detox-android/com/wix/detox/20.27.7-smoke.0/detox-20.27.7-smoke.0.aar.sha256 +0 -1
  68. package/Detox-android/com/wix/detox/20.27.7-smoke.0/detox-20.27.7-smoke.0.aar.sha512 +0 -1
  69. package/Detox-android/com/wix/detox/20.27.7-smoke.0/detox-20.27.7-smoke.0.pom.md5 +0 -1
  70. package/Detox-android/com/wix/detox/20.27.7-smoke.0/detox-20.27.7-smoke.0.pom.sha1 +0 -1
  71. package/Detox-android/com/wix/detox/20.27.7-smoke.0/detox-20.27.7-smoke.0.pom.sha256 +0 -1
  72. package/Detox-android/com/wix/detox/20.27.7-smoke.0/detox-20.27.7-smoke.0.pom.sha512 +0 -1
  73. package/Detox-android/com/wix/detox-legacy/20.27.7-smoke.0/detox-legacy-20.27.7-smoke.0-sources.jar.md5 +0 -1
  74. package/Detox-android/com/wix/detox-legacy/20.27.7-smoke.0/detox-legacy-20.27.7-smoke.0-sources.jar.sha1 +0 -1
  75. package/Detox-android/com/wix/detox-legacy/20.27.7-smoke.0/detox-legacy-20.27.7-smoke.0-sources.jar.sha256 +0 -1
  76. package/Detox-android/com/wix/detox-legacy/20.27.7-smoke.0/detox-legacy-20.27.7-smoke.0-sources.jar.sha512 +0 -1
  77. package/Detox-android/com/wix/detox-legacy/20.27.7-smoke.0/detox-legacy-20.27.7-smoke.0.aar.md5 +0 -1
  78. package/Detox-android/com/wix/detox-legacy/20.27.7-smoke.0/detox-legacy-20.27.7-smoke.0.aar.sha1 +0 -1
  79. package/Detox-android/com/wix/detox-legacy/20.27.7-smoke.0/detox-legacy-20.27.7-smoke.0.aar.sha256 +0 -1
  80. package/Detox-android/com/wix/detox-legacy/20.27.7-smoke.0/detox-legacy-20.27.7-smoke.0.aar.sha512 +0 -1
  81. package/Detox-android/com/wix/detox-legacy/20.27.7-smoke.0/detox-legacy-20.27.7-smoke.0.pom.md5 +0 -1
  82. package/Detox-android/com/wix/detox-legacy/20.27.7-smoke.0/detox-legacy-20.27.7-smoke.0.pom.sha1 +0 -1
  83. package/Detox-android/com/wix/detox-legacy/20.27.7-smoke.0/detox-legacy-20.27.7-smoke.0.pom.sha256 +0 -1
  84. package/Detox-android/com/wix/detox-legacy/20.27.7-smoke.0/detox-legacy-20.27.7-smoke.0.pom.sha512 +0 -1
  85. package/android/detox/src/full/java/com/wix/detox/espresso/web/DetoxDriverAtoms.java +0 -642
@@ -18,7 +18,7 @@ const detoxCopilotFrameworkDriver = {
18
18
  },
19
19
  {
20
20
  signature: 'by.text(text: string)',
21
- description: 'Matches elements by their text.',
21
+ description: 'Matches elements by their text (value).',
22
22
  example: "element(by.text('Login'))",
23
23
  guidelines: ['Prefer test IDs over text matchers when possible.'],
24
24
  },
@@ -34,6 +34,12 @@ const detoxCopilotFrameworkDriver = {
34
34
  example: "element(by.id('listItem')).atIndex(2)",
35
35
  guidelines: ['Use when multiple elements match the same matcher.'],
36
36
  },
37
+ {
38
+ signature: 'by.label(label: string)',
39
+ description: 'Match elements with the specified label.',
40
+ example: "element(by.label('Tuesday, 1 October'));",
41
+ guidelines: ['Use when there are no other identifiers, such as for date pickers to select specific days.'],
42
+ },
37
43
  ],
38
44
  },
39
45
  {
@@ -106,7 +112,7 @@ const detoxCopilotFrameworkDriver = {
106
112
  ],
107
113
  },
108
114
  {
109
- signature: 'waitFor(element: Matcher)..toBeVisible().whileElement(element: Matcher).scroll(offset: number, direction: string)',
115
+ signature: 'waitFor(element: Matcher).toBeVisible(percent?: number).whileElement(element: Matcher).scroll(offset: number, direction: string)',
110
116
  description: 'Continuously performs an action while waiting for an expectation to be fulfilled.',
111
117
  example: `
112
118
  await waitFor(element(by.text('Load More')))
@@ -185,9 +191,13 @@ jestExpect(attributes.text).toBe('Tap Me');`,
185
191
  title: 'Assertions',
186
192
  items: [
187
193
  {
188
- signature: 'toBeVisible()',
189
- description: 'Asserts that the element is visible.',
190
- example: "await expect(element(by.id('loginButton'))).toBeVisible();",
194
+ signature: 'toBeVisible(percent?: number)',
195
+ description: 'Asserts that the element is visible with at-least the specified percentage. Default percent is 75%.',
196
+ example: "await expect(element(by.id('loginButton'))).toBeVisible(38);",
197
+ guidelines: [
198
+ 'Use the default visibility percent unless a different percentage is required.',
199
+ 'If a percentage value is provided, use the exact percentage required for the test.',
200
+ ],
191
201
  },
192
202
  {
193
203
  signature: 'toExist()',
@@ -377,8 +387,8 @@ await device.launchApp({ launchArgs: { someLaunchArg: 1234 } });`,
377
387
  items: [
378
388
  {
379
389
  signature: 'web.element(matcher: Matcher)',
380
- description: 'Selects an element within a web view. Use when there is only one web view on the screen.',
381
- example: `
390
+ description: 'Selects an element within a web view (`WKWebView` or `RNCWebView`). Use when there is only one web view on the screen.',
391
+ example: `
382
392
  await web.element(by.web.id('email')).typeText('test@example.com');
383
393
  await web.element(by.web.id('password')).typeText('password123');
384
394
  await web.element(by.web.id('login-button')).tap();
@@ -387,19 +397,20 @@ await web.element(by.web.id('login-button')).tap();
387
397
  'The web view may take time to load; add a delay using `await new Promise(resolve => setTimeout(resolve, milliseconds));` before the first interaction. This wait should happen only once.',
388
398
  'After the initial wait, you can interact with web elements without additional delays.',
389
399
  'Use `by.web.id` matcher when possible for matching web elements, as it is the most reliable.',
390
- 'Web APIs can only be used with web elements (within web views). Avoid using web APIs for native elements or native APIs for web elements.',
400
+ 'Web APIs can only be used with web elements (within web views). Do not use web APIs for native elements or native APIs for web elements!',
401
+ 'Confirm that you are targeting a web view before using this method.'
391
402
  ],
392
403
  },
393
404
  {
394
405
  signature: 'web(nativeMatcher: NativeMatcher).element(matcher: Matcher)',
395
- description: 'Selects an element within a specific web view matched by a native matcher. Use when there are multiple web views on the screen.',
406
+ description: 'Selects an element within a specific web view (`WKWebView` or `RNCWebView`) matched by a native matcher. Use when there are multiple web views on the screen.',
396
407
  example: `
397
408
  // Wait for the specific web view to appear and load (only once before interacting)
398
409
  await expect(element(by.id('checkout-webview'))).toBeVisible();
399
410
 
400
411
  // Interact with elements within a specific web view
401
412
  const specificWebView = web(by.id('checkout-webview'));
402
-
413
+
403
414
  await specificWebView.element(by.web.id('credit-card-number')).typeText('4111111111111111');
404
415
  await specificWebView.element(by.web.id('expiration-date')).typeText('12/25');
405
416
  await specificWebView.element(by.web.id('cvv')).typeText('123');
@@ -411,6 +422,7 @@ await specificWebView.element(by.web.id('pay-button')).tap();
411
422
  'After the initial wait, you can interact with elements within the web view without additional delays.',
412
423
  'Webview must be matched with `web(nativeMatcher)` (e.g., `web(by.id(..))` instead of `element(by.id(..))`).',
413
424
  'Prefer the basic `web.element()` if only one web view is present on the screen.',
425
+ 'Confirm that you are targeting a web view before using this method.'
414
426
  ],
415
427
  },
416
428
  {
@@ -485,8 +497,8 @@ await secondWebView.element(by.web.id('search-button')).tap();
485
497
  example: `await web.element(by.web.label('Next')).tap();`,
486
498
  guidelines: [
487
499
  'Available on iOS only.',
488
- 'Use when the element has a unique label or aria-label.',
489
- 'Can be used to match buttons and input elements by their inner text content.',
500
+ 'Use when the inner web element has a unique label or aria-label.',
501
+ 'Can be used to match buttons and input elements inside a web view, by their inner text content.',
490
502
  ],
491
503
  },
492
504
  {
@@ -567,13 +579,13 @@ await web.element(by.web.id('email-input')).focus();
567
579
  await web.element(by.web.id('email-input')).typeText('user@example.com');
568
580
  `,
569
581
  guidelines: [
570
- 'Useful for input fields that require focus before typing.',
582
+ 'Useful for input fields in a web view that require focus before typing.',
571
583
  'No need for secured interactions on iOS.',
572
584
  ]
573
585
  },
574
586
  {
575
587
  signature: 'moveCursorToEnd()',
576
- description: 'Moves the input cursor to the end of the element\'s content.',
588
+ description: 'Moves the input cursor in a web view to the end of the element\'s content.',
577
589
  example: `
578
590
  await web.element(by.web.id('message-box')).moveCursorToEnd();
579
591
  await web.element(by.web.id('message-box')).typeText(' Adding more text.');
@@ -581,7 +593,7 @@ await web.element(by.web.id('message-box')).typeText(' Adding more text.');
581
593
  },
582
594
  {
583
595
  signature: 'runScript(script: string, args?: any[])',
584
- description: 'Runs a JavaScript function on the element.',
596
+ description: 'Runs a JavaScript function on the web view element.',
585
597
  example: `
586
598
  // Click an element using a custom script
587
599
  await web.element(by.web.id('hidden-button')).runScript('el => el.click()');
@@ -1,6 +1,7 @@
1
1
  const DetoxRuntimeError = require('../../errors/DetoxRuntimeError');
2
2
  const debug = require('../../utils/debug'); // debug utils, leave here even if unused
3
3
  const log = require('../../utils/logger').child({ cat: 'device' });
4
+ const mapDeviceLongPressArguments = require('../../utils/mapDeviceLongPressArguments');
4
5
  const traceMethods = require('../../utils/traceMethods');
5
6
  const wrapWithStackTraceCutter = require('../../utils/wrapWithStackTraceCutter');
6
7
 
@@ -283,6 +284,16 @@ class RuntimeDevice {
283
284
  await this.deviceDriver.setOrientation(orientation);
284
285
  }
285
286
 
287
+ async tap(point, shouldIgnoreStatusBar) {
288
+ await this.deviceDriver.tap(point, shouldIgnoreStatusBar, this._bundleId);
289
+ }
290
+
291
+ async longPress(arg1, arg2, arg3) {
292
+ let { point, duration, shouldIgnoreStatusBar } = mapDeviceLongPressArguments(arg1, arg2, arg3);
293
+
294
+ await this.deviceDriver.longPress(point, duration, shouldIgnoreStatusBar, this._bundleId);
295
+ }
296
+
286
297
  async setLocation(lat, lon) {
287
298
  lat = String(lat);
288
299
  lon = String(lon);
@@ -51,6 +51,14 @@ class DeviceDriverBase {
51
51
  return '';
52
52
  }
53
53
 
54
+ async tap(_bundleId) {
55
+ return '';
56
+ }
57
+
58
+ async longPress(_bundleId) {
59
+ return '';
60
+ }
61
+
54
62
  async sendToHome() {
55
63
  return '';
56
64
  }
@@ -245,6 +245,22 @@ class AndroidDriver extends DeviceDriverBase {
245
245
  await this.invocationManager.execute(call);
246
246
  }
247
247
 
248
+ async tap(point, shouldIgnoreStatusBar) {
249
+ let x = point?.x ?? 100;
250
+ let y = point?.y ?? 100;
251
+ let _shouldIgnoreStatusBar = shouldIgnoreStatusBar ?? true;
252
+ const call = EspressoDetoxApi.tap(x, y, _shouldIgnoreStatusBar);
253
+ await this.invocationManager.execute(call);
254
+ }
255
+
256
+ async longPress(point, duration, shouldIgnoreStatusBar) {
257
+ let x = point?.x ?? 100;
258
+ let y = point?.y ?? 100;
259
+ let _shouldIgnoreStatusBar = shouldIgnoreStatusBar ?? true;
260
+ const call = duration ? EspressoDetoxApi.longPress(x, y, duration, _shouldIgnoreStatusBar): EspressoDetoxApi.longPress(x, y, _shouldIgnoreStatusBar);
261
+ await this.invocationManager.execute(call);
262
+ }
263
+
248
264
  async generateViewHierarchyXml(shouldInjectTestIds) {
249
265
  const hierarchy = await this.invocationManager.execute(DetoxApi.generateViewHierarchyXml(shouldInjectTestIds));
250
266
  return hierarchy.result;
@@ -6,12 +6,17 @@ const _ = require('lodash');
6
6
 
7
7
  const temporaryPath = require('../../../../artifacts/utils/temporaryPath');
8
8
  const DetoxRuntimeError = require('../../../../errors/DetoxRuntimeError');
9
+ const XCUITestRunner = require('../../../../ios/XCUITestRunner');
10
+ const { assertTraceDescription } = require('../../../../utils/assertArgument');
9
11
  const getAbsoluteBinaryPath = require('../../../../utils/getAbsoluteBinaryPath');
12
+ const { actionDescription } = require('../../../../utils/invocationTraceDescriptions');
10
13
  const log = require('../../../../utils/logger').child({ cat: 'device' });
11
14
  const pressAnyKey = require('../../../../utils/pressAnyKey');
15
+ const traceInvocationCall = require('../../../../utils/traceInvocationCall').bind(null, log);
12
16
 
13
17
  const IosDriver = require('./IosDriver');
14
18
 
19
+
15
20
  /**
16
21
  * @typedef SimulatorDriverDeps { DeviceDriverDeps }
17
22
  * @property applesimutils { AppleSimUtils }
@@ -40,6 +45,19 @@ class SimulatorDriver extends IosDriver {
40
45
  this._applesimutils = deps.applesimutils;
41
46
  }
42
47
 
48
+ withAction(xcuitestRunner, action, traceDescription, ...params) {
49
+ assertTraceDescription(traceDescription);
50
+
51
+ const invocation = {
52
+ ...(params.length !== 0 && { params }),
53
+ type: 'systemAction',
54
+ ...(this.index !== undefined && { systemAtIndex: this.index }),
55
+ systemAction: action
56
+ };
57
+
58
+ return traceInvocationCall(traceDescription, invocation, xcuitestRunner.execute(invocation));
59
+ }
60
+
43
61
  getExternalId() {
44
62
  return this.udid;
45
63
  }
@@ -111,6 +129,23 @@ class SimulatorDriver extends IosDriver {
111
129
  await this.emitter.emit('terminateApp', { deviceId: udid, bundleId });
112
130
  }
113
131
 
132
+ async tap(point, shouldIgnoreStatusBar, _bundleId) {
133
+ const xcuitestRunner = new XCUITestRunner({ runtimeDevice: { id: this.getExternalId(), _bundleId } });
134
+ let x = point?.x ?? 100;
135
+ let y = point?.y ?? 100;
136
+ const traceDescription = actionDescription.tap({ x, y });
137
+ return this.withAction(xcuitestRunner, 'coordinateTap', traceDescription, x.toString(), y.toString());
138
+ }
139
+
140
+ async longPress(point, pressDuration, shouldIgnoreStatusBar, _bundleId) {
141
+ const xcuitestRunner = new XCUITestRunner({ runtimeDevice: { id: this.getExternalId(), _bundleId } });
142
+ let x = point?.x ?? 100;
143
+ let y = point?.y ?? 100;
144
+ let _pressDuration = pressDuration ? (pressDuration / 1000) : 1;
145
+ const traceDescription = actionDescription.longPress({ x, y }, _pressDuration);
146
+ return this.withAction(xcuitestRunner, 'coordinateLongPress', traceDescription, x.toString(), y.toString(), _pressDuration.toString());
147
+ }
148
+
114
149
  async setBiometricEnrollment(yesOrNo) {
115
150
  await this._applesimutils.setBiometricEnrollment(this.udid, yesOrNo);
116
151
  }
@@ -52,6 +52,14 @@ function assertPoint(point) {
52
52
  throw new DetoxRuntimeError(`point should be an object with x and y properties, but got ${JSON.stringify(point)}`);
53
53
  }
54
54
 
55
+ function assertShouldIgnoreStatusBar(shouldIgnoreStatusBar) {
56
+ if (typeof shouldIgnoreStatusBar === 'boolean') {
57
+ return true;
58
+ }
59
+
60
+ throw new DetoxRuntimeError('shouldIgnoreStatusBar should be a boolean, but got ' + (shouldIgnoreStatusBar + (' (' + (typeof shouldIgnoreStatusBar + ')'))));
61
+ }
62
+
55
63
  function assertUndefined(arg) {
56
64
  if (arg === undefined) {
57
65
  return true;
@@ -76,6 +84,7 @@ module.exports = {
76
84
  assertString,
77
85
  assertDuration,
78
86
  assertPoint,
87
+ assertShouldIgnoreStatusBar,
79
88
  assertUndefined,
80
89
  assertTraceDescription
81
90
  };
@@ -3,6 +3,7 @@ module.exports = {
3
3
  adjustSliderToPosition: (newPosition) => `adjust slider to position ${newPosition}`,
4
4
  clearText: () => 'clear input text',
5
5
  getAttributes: () => 'get element attributes',
6
+ tap: (point) => `tap at ${JSON.stringify(point)}`,
6
7
  longPress: (point, duration) => `long press${duration !== null ? ` for ${duration}ms` : ''}${point !== null ? ` at ${JSON.stringify(point)}` : ''}`,
7
8
  longPressAndDrag: (duration, startX, startY, targetElement, endX, endY, speed, holdDuration) =>
8
9
  `long press and drag from ${startX}, ${startY} to ${endX}, ${endY} with speed ${speed} and hold duration ${holdDuration}`,
@@ -0,0 +1,56 @@
1
+ const { DetoxRuntimeError } = require('../errors');
2
+
3
+ const { assertPoint, assertDuration, assertUndefined, assertShouldIgnoreStatusBar } = require('./assertArgument');
4
+
5
+ function mapDeviceLongPressArguments(optionalAllParams, optionalDurationOrIgnoreStatusBar, optionalIgnoreStatusBar) {
6
+ let point = null;
7
+ let duration = null;
8
+ let shouldIgnoreStatusBar = null;
9
+
10
+ try {
11
+ if (optionalAllParams === undefined) {
12
+ // Do nothing.
13
+ } else if (typeof optionalAllParams === 'number') {
14
+ duration = optionalAllParams;
15
+ if (typeof optionalDurationOrIgnoreStatusBar === 'boolean') {
16
+ shouldIgnoreStatusBar = optionalDurationOrIgnoreStatusBar;
17
+ } else {
18
+ assertUndefined(optionalDurationOrIgnoreStatusBar);
19
+ }
20
+ assertUndefined(optionalIgnoreStatusBar);
21
+ } else if (typeof optionalAllParams === 'boolean') {
22
+ shouldIgnoreStatusBar = optionalAllParams;
23
+ assertUndefined(optionalDurationOrIgnoreStatusBar);
24
+ assertUndefined(optionalIgnoreStatusBar);
25
+ } else {
26
+ assertPoint(optionalAllParams);
27
+ point = optionalAllParams;
28
+
29
+ if (typeof optionalDurationOrIgnoreStatusBar === 'number') {
30
+ assertDuration(optionalDurationOrIgnoreStatusBar);
31
+ duration = optionalDurationOrIgnoreStatusBar;
32
+ } else if (typeof optionalDurationOrIgnoreStatusBar === 'boolean') {
33
+ assertShouldIgnoreStatusBar(optionalDurationOrIgnoreStatusBar);
34
+ shouldIgnoreStatusBar = optionalDurationOrIgnoreStatusBar;
35
+ assertUndefined(optionalIgnoreStatusBar);
36
+ } else if (optionalDurationOrIgnoreStatusBar !== undefined) {
37
+ assertDuration(optionalDurationOrIgnoreStatusBar);
38
+ } else {
39
+ assertUndefined(optionalDurationOrIgnoreStatusBar);
40
+ assertUndefined(optionalIgnoreStatusBar);
41
+ }
42
+
43
+ if (optionalIgnoreStatusBar !== undefined) {
44
+ assertShouldIgnoreStatusBar(optionalIgnoreStatusBar);
45
+ shouldIgnoreStatusBar = optionalIgnoreStatusBar;
46
+ }
47
+ }
48
+ } catch (e) {
49
+ throw new DetoxRuntimeError(`longPress accepts either a duration (number) or a point ({x: number, y: number}) as ` +
50
+ `its first argument, optionally a duration (number) as its second argument, and optionally a ignoreStatusBar (boolean) as its third argument. Error: ${e.message}`);
51
+ }
52
+
53
+ return { point, duration, shouldIgnoreStatusBar };
54
+ }
55
+
56
+ module.exports = mapDeviceLongPressArguments;
@@ -1 +0,0 @@
1
- 390f49d71c399592a5a12dae4d0ba89a
@@ -1 +0,0 @@
1
- bb30d23b09a201006a4d923dffb96a4cb0b44458
@@ -1 +0,0 @@
1
- b3095ae31971d13a41e9225c401066365a7c5c54c0a7313797b7c8818251d569
@@ -1 +0,0 @@
1
- 1ca8d245b20bbe78438bbbfc06ac95123dffcaf759d816d6f49a0a4d23989c945686db119fb08967799e7e994e78a7192e7df185d4888e6b5b242a1d0bcd7c8e
@@ -1 +0,0 @@
1
- 1a5f2740c1c03528f2d9611aaa4634b6
@@ -1 +0,0 @@
1
- d752c96158c3984c8dfe1cde9ee0b14fbe2ab641
@@ -1 +0,0 @@
1
- 3bd563b4fe588be1d4cc5877a0b8464f31a5da309029a4e5703bf5465ee6df2d
@@ -1 +0,0 @@
1
- 1682f1d10b78729ebd15fc548860893b9c9585447777ed09e6bf7d5000e85745db9722e2f2d15bee539a2230d8714526d293bb669218e17578cd9461a9dd2446
@@ -1 +0,0 @@
1
- e88738f8b748e72b3381a6e14f7915da
@@ -1 +0,0 @@
1
- 75d405e7af82b69cd73b9d990c9b24fb6d909e4a
@@ -1 +0,0 @@
1
- 294b1c7cd9cc5eb44f6846594477c422a0fc25e758d3741d61ce85c9c11898a9
@@ -1 +0,0 @@
1
- ab28dbb7a126bdd7cd139f675d1bbe7633555af7e8d73b8449d1532031cbfe331db7e0f56377a6caa09c880b35723d90011c3d1b40890188761461137cc87b15
@@ -1 +0,0 @@
1
- a781f7f228f72a617c266dc471ae38fe4f83125a
@@ -1 +0,0 @@
1
- f451d882399883eb599d10bd8c59f27f3f48f7b5d9d8b0b64544efcecd2f7e2c
@@ -1 +0,0 @@
1
- a382597f97218664630944f9f014ffbf5dbe2de4a79eec96fb3370c0b418a2fb034b311439b50dc142e38bb2ddce32d049328db0651ae1ccf6316d1afbe7be25
@@ -1 +0,0 @@
1
- f97c69229516588039e2b4377ce427609242db16
@@ -1 +0,0 @@
1
- 464e93f88371093a2323125b79f3a2a9e97a908614909ff959d2505b971a1150
@@ -1 +0,0 @@
1
- b96a1d21679c252bcf9e8afb71a067eae95fe0716fe9b8e04dd703da9a119f57572f2bf92281f330e301d8683f4cd1ae3ab52a91aec92778ec61514725994b83
@@ -1 +0,0 @@
1
- fffa571b874d723aa306265eb76fc13d65722655
@@ -1 +0,0 @@
1
- eca27e544ff60053827726d933d18a00a1cd6d06a24b47a67204b598e3a495b5
@@ -1 +0,0 @@
1
- 93aab0e7f56de89d603faafdef30daa99761673ff1aeeb65b3aa968e768ecf8cd82f4867171503044b725f5e47daba016ce50be7156c8c5608abe8253ef2bb30