detox 20.27.3 → 20.27.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (72) hide show
  1. package/Detox-android/com/wix/detox/{20.27.3/detox-20.27.3-sources.jar → 20.27.4/detox-20.27.4-sources.jar} +0 -0
  2. package/Detox-android/com/wix/detox/20.27.4/detox-20.27.4-sources.jar.md5 +1 -0
  3. package/Detox-android/com/wix/detox/20.27.4/detox-20.27.4-sources.jar.sha1 +1 -0
  4. package/Detox-android/com/wix/detox/20.27.4/detox-20.27.4-sources.jar.sha256 +1 -0
  5. package/Detox-android/com/wix/detox/20.27.4/detox-20.27.4-sources.jar.sha512 +1 -0
  6. package/Detox-android/com/wix/detox/20.27.4/detox-20.27.4.aar +0 -0
  7. package/Detox-android/com/wix/detox/20.27.4/detox-20.27.4.aar.md5 +1 -0
  8. package/Detox-android/com/wix/detox/20.27.4/detox-20.27.4.aar.sha1 +1 -0
  9. package/Detox-android/com/wix/detox/20.27.4/detox-20.27.4.aar.sha256 +1 -0
  10. package/Detox-android/com/wix/detox/20.27.4/detox-20.27.4.aar.sha512 +1 -0
  11. package/Detox-android/com/wix/detox/{20.27.3/detox-20.27.3.pom → 20.27.4/detox-20.27.4.pom} +1 -1
  12. package/Detox-android/com/wix/detox/20.27.4/detox-20.27.4.pom.md5 +1 -0
  13. package/Detox-android/com/wix/detox/20.27.4/detox-20.27.4.pom.sha1 +1 -0
  14. package/Detox-android/com/wix/detox/20.27.4/detox-20.27.4.pom.sha256 +1 -0
  15. package/Detox-android/com/wix/detox/20.27.4/detox-20.27.4.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.3/detox-legacy-20.27.3-sources.jar → 20.27.4/detox-legacy-20.27.4-sources.jar} +0 -0
  22. package/Detox-android/com/wix/detox-legacy/20.27.4/detox-legacy-20.27.4-sources.jar.md5 +1 -0
  23. package/Detox-android/com/wix/detox-legacy/20.27.4/detox-legacy-20.27.4-sources.jar.sha1 +1 -0
  24. package/Detox-android/com/wix/detox-legacy/20.27.4/detox-legacy-20.27.4-sources.jar.sha256 +1 -0
  25. package/Detox-android/com/wix/detox-legacy/20.27.4/detox-legacy-20.27.4-sources.jar.sha512 +1 -0
  26. package/Detox-android/com/wix/detox-legacy/20.27.4/detox-legacy-20.27.4.aar +0 -0
  27. package/Detox-android/com/wix/detox-legacy/20.27.4/detox-legacy-20.27.4.aar.md5 +1 -0
  28. package/Detox-android/com/wix/detox-legacy/20.27.4/detox-legacy-20.27.4.aar.sha1 +1 -0
  29. package/Detox-android/com/wix/detox-legacy/20.27.4/detox-legacy-20.27.4.aar.sha256 +1 -0
  30. package/Detox-android/com/wix/detox-legacy/20.27.4/detox-legacy-20.27.4.aar.sha512 +1 -0
  31. package/Detox-android/com/wix/detox-legacy/{20.27.3/detox-legacy-20.27.3.pom → 20.27.4/detox-legacy-20.27.4.pom} +1 -1
  32. package/Detox-android/com/wix/detox-legacy/20.27.4/detox-legacy-20.27.4.pom.md5 +1 -0
  33. package/Detox-android/com/wix/detox-legacy/20.27.4/detox-legacy-20.27.4.pom.sha1 +1 -0
  34. package/Detox-android/com/wix/detox-legacy/20.27.4/detox-legacy-20.27.4.pom.sha256 +1 -0
  35. package/Detox-android/com/wix/detox-legacy/20.27.4/detox-legacy-20.27.4.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/hierarchy/ViewHierarchyGenerator.kt +3 -3
  45. package/package.json +3 -3
  46. package/src/copilot/detoxCopilotFrameworkDriver.js +122 -91
  47. package/Detox-android/com/wix/detox/20.27.3/detox-20.27.3-sources.jar.md5 +0 -1
  48. package/Detox-android/com/wix/detox/20.27.3/detox-20.27.3-sources.jar.sha1 +0 -1
  49. package/Detox-android/com/wix/detox/20.27.3/detox-20.27.3-sources.jar.sha256 +0 -1
  50. package/Detox-android/com/wix/detox/20.27.3/detox-20.27.3-sources.jar.sha512 +0 -1
  51. package/Detox-android/com/wix/detox/20.27.3/detox-20.27.3.aar +0 -0
  52. package/Detox-android/com/wix/detox/20.27.3/detox-20.27.3.aar.md5 +0 -1
  53. package/Detox-android/com/wix/detox/20.27.3/detox-20.27.3.aar.sha1 +0 -1
  54. package/Detox-android/com/wix/detox/20.27.3/detox-20.27.3.aar.sha256 +0 -1
  55. package/Detox-android/com/wix/detox/20.27.3/detox-20.27.3.aar.sha512 +0 -1
  56. package/Detox-android/com/wix/detox/20.27.3/detox-20.27.3.pom.md5 +0 -1
  57. package/Detox-android/com/wix/detox/20.27.3/detox-20.27.3.pom.sha1 +0 -1
  58. package/Detox-android/com/wix/detox/20.27.3/detox-20.27.3.pom.sha256 +0 -1
  59. package/Detox-android/com/wix/detox/20.27.3/detox-20.27.3.pom.sha512 +0 -1
  60. package/Detox-android/com/wix/detox-legacy/20.27.3/detox-legacy-20.27.3-sources.jar.md5 +0 -1
  61. package/Detox-android/com/wix/detox-legacy/20.27.3/detox-legacy-20.27.3-sources.jar.sha1 +0 -1
  62. package/Detox-android/com/wix/detox-legacy/20.27.3/detox-legacy-20.27.3-sources.jar.sha256 +0 -1
  63. package/Detox-android/com/wix/detox-legacy/20.27.3/detox-legacy-20.27.3-sources.jar.sha512 +0 -1
  64. package/Detox-android/com/wix/detox-legacy/20.27.3/detox-legacy-20.27.3.aar +0 -0
  65. package/Detox-android/com/wix/detox-legacy/20.27.3/detox-legacy-20.27.3.aar.md5 +0 -1
  66. package/Detox-android/com/wix/detox-legacy/20.27.3/detox-legacy-20.27.3.aar.sha1 +0 -1
  67. package/Detox-android/com/wix/detox-legacy/20.27.3/detox-legacy-20.27.3.aar.sha256 +0 -1
  68. package/Detox-android/com/wix/detox-legacy/20.27.3/detox-legacy-20.27.3.aar.sha512 +0 -1
  69. package/Detox-android/com/wix/detox-legacy/20.27.3/detox-legacy-20.27.3.pom.md5 +0 -1
  70. package/Detox-android/com/wix/detox-legacy/20.27.3/detox-legacy-20.27.3.pom.sha1 +0 -1
  71. package/Detox-android/com/wix/detox-legacy/20.27.3/detox-legacy-20.27.3.pom.sha256 +0 -1
  72. package/Detox-android/com/wix/detox-legacy/20.27.3/detox-legacy-20.27.3.pom.sha512 +0 -1
@@ -0,0 +1 @@
1
+ 9ace4a96235511950308086f1d57d806
@@ -0,0 +1 @@
1
+ 22cc9e5934c1c0ba48217d81dc0a0403d6383378
@@ -0,0 +1 @@
1
+ c4f49a1754ae4e50e6a32cd8f22a51cb920e2a58b8e9da6a5d443aa6715a59f5
@@ -0,0 +1 @@
1
+ 503797c9ab31332033756727a60af64c7797d51b731d88e6e841cba4c477f68ed1df2872602097587c91c5b357377007e7c9cb7e4f2b838172d1f99af52b5334
@@ -0,0 +1 @@
1
+ 05c87fc838b557d8c9537d4f432a9033
@@ -0,0 +1 @@
1
+ acc5c69d438baaadcfe97fa1f168e2799c3ce03a
@@ -0,0 +1 @@
1
+ 9b9bb763d1adae07410c1057e4212277e5d1e3342afd286fbccd623511f86ce9
@@ -0,0 +1 @@
1
+ 507cda9204d0726835db6d44cb80d23dd7fe4765c9b6387e635c1ad9cf8849e5d3d799100796106e7fcdd7fe4b4adb6aeb582aaccbf1db85639ae6b81e8b552e
@@ -3,7 +3,7 @@
3
3
  <modelVersion>4.0.0</modelVersion>
4
4
  <groupId>com.wix</groupId>
5
5
  <artifactId>detox</artifactId>
6
- <version>20.27.3</version>
6
+ <version>20.27.4</version>
7
7
  <packaging>aar</packaging>
8
8
  <name>Detox</name>
9
9
  <description>Gray box end-to-end testing and automation library for mobile apps</description>
@@ -0,0 +1 @@
1
+ 69801cb935f0a63f247f867c28709f8d
@@ -0,0 +1 @@
1
+ 9605245c61fd0ea528dd0cd2eda73ac0866ba25f
@@ -0,0 +1 @@
1
+ 69e7b3363b16f075838fe56272dd13fd089b4d9b344ab4d4456a91d9444e0bbb
@@ -0,0 +1 @@
1
+ 9f3223915c0899fed72f86c5781ee7c1f6f9737f0a016224582372e7b5f29ec6672fd943163717465549159f3f75a11a2ee6eca488589b97bc29775c3cbc3fe5
@@ -3,11 +3,11 @@
3
3
  <groupId>com.wix</groupId>
4
4
  <artifactId>detox</artifactId>
5
5
  <versioning>
6
- <latest>20.27.3</latest>
7
- <release>20.27.3</release>
6
+ <latest>20.27.4</latest>
7
+ <release>20.27.4</release>
8
8
  <versions>
9
- <version>20.27.3</version>
9
+ <version>20.27.4</version>
10
10
  </versions>
11
- <lastUpdated>20241009154552</lastUpdated>
11
+ <lastUpdated>20241019191347</lastUpdated>
12
12
  </versioning>
13
13
  </metadata>
@@ -1 +1 @@
1
- 27e42826d06e4da1ec0844db0255a70c
1
+ 4e15390d4670f66357943485fa05acea
@@ -1 +1 @@
1
- 8a719a4551a0fde056e3f53cd841131fe908fc4d
1
+ 3475202451a2cb5e3534b59b14612e32df033626
@@ -1 +1 @@
1
- ad19b8a5540aabca7a9ea07890509a1e9161848db2682d1c82274168fcf710ef
1
+ d1b63410f852b05d5e00c1a0358fd61afe51474be017e2e78fef15e30cb09d44
@@ -1 +1 @@
1
- b4fcc3ee40ae9bb22b6c97fd768a3b52281ca32229fd3fc50d8512b81ccec8cbbc3c94f03be1e843016fe97de37a5042938ba549e512894d6c08686ebf2d43c2
1
+ 8b1cc9ffb3d076da45ed87bbaa606ccd89be6fc53dd5e57e8f3d3be5ed09eece128d7cbe4f398606441c1f837cf07268e0a35071c90894c2bd0f5f259b8865c7
@@ -0,0 +1 @@
1
+ 11e61e70a680b35bc8433c99dbe93fa7
@@ -0,0 +1 @@
1
+ 461391ec015ccc3107d8d1d1f4f90fdef1e89d4d
@@ -0,0 +1 @@
1
+ 37d6621cb43970a45655c142a2d3f87202228010f48c9359b1608f968fc29965
@@ -0,0 +1 @@
1
+ f21f72c93ca515baebf73681a7406d25682550f537943a6f7b3933ba0bc318a3c83a243e7c7ac45372deb363a7dce7396132e101545a586c7b23ecaa6d3606e4
@@ -0,0 +1 @@
1
+ af13b71ab208d17b33c1fc7a1ef4e529
@@ -0,0 +1 @@
1
+ 47dca63caffe4427b6fec3ab51e13ade0e234e6d
@@ -0,0 +1 @@
1
+ 22561e652905451c48ffb378b015ae046634e2efea239e6f08875ccbd179db3e
@@ -0,0 +1 @@
1
+ 46aa7c047bc8cbe7ad61270652a5bcc88955545e33c6d8338a9cc610e157d5cf6b2ecea224bacdb13cffc027d92617abecf0d1faa7eb89fb5b8c10cd7c410eb1
@@ -3,7 +3,7 @@
3
3
  <modelVersion>4.0.0</modelVersion>
4
4
  <groupId>com.wix</groupId>
5
5
  <artifactId>detox-legacy</artifactId>
6
- <version>20.27.3</version>
6
+ <version>20.27.4</version>
7
7
  <packaging>aar</packaging>
8
8
  <name>Detox</name>
9
9
  <description>Gray box end-to-end testing and automation library for mobile apps</description>
@@ -0,0 +1 @@
1
+ 07b3035704b21925bce075aa8ceaa610
@@ -0,0 +1 @@
1
+ 5369c9600c539c3142ab367ea81df17920762e86
@@ -0,0 +1 @@
1
+ 675cf33b02458dfa9d2c997a5d51f70a138d6e05cc2a1794c530ded4be481f48
@@ -0,0 +1 @@
1
+ 8f6bf9c98b0d80bec51af79d562411dc85ac6fb11ee7cb952f1875abd43ac73df3ffb90dc426485fe8e21dc0200b27a0ad646fbc8edc89576502690eaa817ca3
@@ -3,11 +3,11 @@
3
3
  <groupId>com.wix</groupId>
4
4
  <artifactId>detox-legacy</artifactId>
5
5
  <versioning>
6
- <latest>20.27.3</latest>
7
- <release>20.27.3</release>
6
+ <latest>20.27.4</latest>
7
+ <release>20.27.4</release>
8
8
  <versions>
9
- <version>20.27.3</version>
9
+ <version>20.27.4</version>
10
10
  </versions>
11
- <lastUpdated>20241009154624</lastUpdated>
11
+ <lastUpdated>20241019191405</lastUpdated>
12
12
  </versioning>
13
13
  </metadata>
@@ -1 +1 @@
1
- 6ddea16ac39ebcaa72590d9b50ca41a1
1
+ 06da87cac17d41b217b1204e3baac71c
@@ -1 +1 @@
1
- 1ad379b7c3de738b8adebc19d859742fdbf6797a
1
+ 3260642fbd27ef17b3f677a27b9060f29ecddd68
@@ -1 +1 @@
1
- 61f5bf7772111546173237486ddc5909ee6bc7053595adc3305c0ccfeb927736
1
+ 7aaa8a6d2ea4aed57f4c789a4d2229070c7619b8466e959fe73d930c6d2f09c5
@@ -1 +1 @@
1
- 03e8049bdb4784b4c54b25e9a14b30012ee6212ae6b7329d61ea357ed97f485d1e88a8f2e0d573046020c07fd7681ac9cd84189d195598b867401ef83e97b1e9
1
+ 437e4f341f9a2a317ff3fc9c8ad606d36974f884172e105b36c2eb256d3245791fc0dabad87c8c23ea76fc9995528af1b6d6b9a5a28f389afe158b0d8318e6da
Binary file
package/Detox-ios-src.tbz CHANGED
Binary file
Binary file
@@ -16,10 +16,10 @@ import kotlin.coroutines.resume
16
16
 
17
17
 
18
18
  private const val GET_HTML_SCRIPT = """
19
+ (function() {
19
20
  const blacklistedTags = ['script', 'style', 'head', 'meta'];
20
21
  const blackListedTagsSelector = blacklistedTags.join(',');
21
22
 
22
- (function() {
23
23
  // Clone the entire document
24
24
  var clonedDoc = document.documentElement.cloneNode(true);
25
25
 
@@ -170,9 +170,9 @@ object ViewHierarchyGenerator {
170
170
  if (shouldInjectNewTestId) {
171
171
  val newTestId = "${injectedPrefix}${indexPath.joinToString("_")}"
172
172
  view.tag = newTestId
173
- attributes["testID"] = newTestId
173
+ attributes["id"] = newTestId
174
174
  } else {
175
- attributes["testID"] = currentTestId
175
+ attributes["id"] = currentTestId
176
176
  }
177
177
 
178
178
  attributes
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "detox",
3
3
  "description": "E2E tests and automation for mobile",
4
- "version": "20.27.3",
4
+ "version": "20.27.4",
5
5
  "bin": {
6
6
  "detox": "local-cli/cli.js"
7
7
  },
@@ -71,7 +71,7 @@
71
71
  "caf": "^15.0.1",
72
72
  "chalk": "^4.0.0",
73
73
  "child-process-promise": "^2.2.0",
74
- "detox-copilot": "^0.0.14",
74
+ "detox-copilot": "^0.0.23",
75
75
  "execa": "^5.1.1",
76
76
  "find-up": "^5.0.0",
77
77
  "fs-extra": "^11.0.0",
@@ -116,5 +116,5 @@
116
116
  "browserslist": [
117
117
  "node 14"
118
118
  ],
119
- "gitHead": "4ccef46fa6cbc2526d02af45f3b2ca92f6e5d1df"
119
+ "gitHead": "74a2c1426616e4e65fa830b9b98689e18a0677e3"
120
120
  }
@@ -106,7 +106,7 @@ const detoxCopilotFrameworkDriver = {
106
106
  ],
107
107
  },
108
108
  {
109
- signature: 'whileElement(element: Matcher)',
109
+ signature: 'waitFor(element: Matcher)..toBeVisible().whileElement(element: Matcher).scroll(offset: number, direction: string)',
110
110
  description: 'Continuously performs an action while waiting for an expectation to be fulfilled.',
111
111
  example: `
112
112
  await waitFor(element(by.text('Load More')))
@@ -335,14 +335,20 @@ await device.launchApp({ launchArgs: { someLaunchArg: 1234 } });`,
335
335
  example: "system.element(by.system.label('Allow')).tap();",
336
336
  guidelines: [
337
337
  'Can be used for iOS system alerts and permissions dialogs',
338
+ 'Always use `system.element()` to interact with system dialog elements (alerts, permission requests).',
338
339
  'Check the platform with `device.getPlatform()` before using, as it is iOS-specific',
340
+ 'Permission alerts are part of the system UI, not the app UI. Therefore should be matched with `system.element()`.',
339
341
  'System dialogs are not part of the app, so they won\'t be found in the app\'s view hierarchy. Identify the relevant system element from the snapshot.',
340
342
  ]
341
343
  },
342
344
  {
343
345
  signature: 'by.system.label(label: string)',
344
- description: 'Matches system elements by label.',
346
+ description: 'Matches system elements by their label (text).',
345
347
  example: "system.element(by.system.label('Dismiss'));",
348
+ guidelines: [
349
+ 'System elements will not be found in the app\'s view hierarchy. Read the text from the snapshot.',
350
+ 'If no system dialog can be found, throw an error with the relevant message.',
351
+ ],
346
352
  },
347
353
  {
348
354
  signature: 'by.system.type(type: string)',
@@ -357,12 +363,12 @@ await device.launchApp({ launchArgs: { someLaunchArg: 1234 } });`,
357
363
  {
358
364
  signature: 'toExist()',
359
365
  description: 'Asserts that the system element exists.',
360
- example: "await system.element(by.system.label('Allow')).toExist();",
366
+ example: "await expect(system.element(by.system.label('Allow'))).toExist();",
361
367
  },
362
368
  {
363
369
  signature: 'not',
364
370
  description: 'Negates the expectation for system elements.',
365
- example: "await system.element(by.system.label('Allow')).not.toExist();",
371
+ example: "await expect(system.element(by.system.label('Allow'))).not.toExist();",
366
372
  },
367
373
  ],
368
374
  },
@@ -372,99 +378,121 @@ await device.launchApp({ launchArgs: { someLaunchArg: 1234 } });`,
372
378
  {
373
379
  signature: 'web.element(matcher: Matcher)',
374
380
  description: 'Selects an element within a web view. Use when there is only one web view on the screen.',
375
- example: "const element = web.element(by.web.id('username'));",
381
+ example: `
382
+ await web.element(by.web.id('email')).typeText('test@example.com');
383
+ await web.element(by.web.id('password')).typeText('password123');
384
+ await web.element(by.web.id('login-button')).tap();
385
+ `,
376
386
  guidelines: [
377
- 'Web APIs can only be used with web elements (within web views).',
378
- 'Avoid using web APIs for native elements or native APIs for web elements.',
379
- 'Always prefer the `by.web.id` matcher when possible.',
387
+ '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
+ 'After the initial wait, you can interact with web elements without additional delays.',
389
+ '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.',
380
391
  ],
381
392
  },
382
393
  {
383
- signature: 'web(nativeMatcher).element(matcher: Matcher)',
394
+ signature: 'web(nativeMatcher: NativeMatcher).element(matcher: Matcher)',
384
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.',
385
- example: "const element = web(by.id('webview')).element(by.web.id('password'));",
396
+ example: `
397
+ // Wait for the specific web view to appear and load (only once before interacting)
398
+ await expect(element(by.id('checkout-webview'))).toBeVisible();
399
+
400
+ // Interact with elements within a specific web view
401
+ const specificWebView = web(by.id('checkout-webview'));
402
+
403
+ await specificWebView.element(by.web.id('credit-card-number')).typeText('4111111111111111');
404
+ await specificWebView.element(by.web.id('expiration-date')).typeText('12/25');
405
+ await specificWebView.element(by.web.id('cvv')).typeText('123');
406
+ await specificWebView.element(by.web.id('pay-button')).tap();
407
+ `,
386
408
  guidelines: [
387
409
  'Use this method when multiple web views are present.',
388
- 'Prefer `web.element` if only one web view is present on the screen.',
410
+ 'Ensure the web view is visible and its content is loaded before interacting. This wait should happen only once.',
411
+ 'After the initial wait, you can interact with elements within the web view without additional delays.',
412
+ 'Webview must be matched with `web(nativeMatcher)` (e.g., `web(by.id(..))` instead of `element(by.id(..))`).',
413
+ 'Prefer the basic `web.element()` if only one web view is present on the screen.',
389
414
  ],
390
415
  },
391
416
  {
392
- signature: 'web(nativeMatcher).atIndex(index: number).element(matcher: Matcher)',
417
+ signature: 'web(nativeMatcher: NativeMatcher).atIndex(index: number).element(matcher: Matcher)',
393
418
  description: 'Selects an element within a specific web view at a given index (iOS only).',
394
- example: "const element = web(by.id('webview')).atIndex(1).element(by.web.id('password'));",
419
+ example: `
420
+ // Interact with an element within the second web view (index starts from 0)
421
+ const secondWebView = web(by.id('webview')).atIndex(1);
422
+ await secondWebView.element(by.web.id('search-input')).typeText('Detox Testing');
423
+ await secondWebView.element(by.web.id('search-button')).tap();
424
+ `,
395
425
  guidelines: [
396
426
  'Use when multiple web views with the same identifier are present on iOS.',
397
- 'This matcher is available for iOS only.',
427
+ 'This method is available for iOS only.',
398
428
  'Check the platform with `device.getPlatform()` before using.',
399
429
  ],
400
430
  },
401
431
  {
402
432
  signature: 'by.web.id(id: string)',
403
- description: 'Matches web elements by their ID attribute.',
404
- example: "web.element(by.web.id('submit_button'));",
433
+ description: 'Matches web elements by their "id" attribute.',
434
+ example: `await web.element(by.web.id('search')).tap();`,
405
435
  guidelines: [
406
- 'Use for web elements with unique IDs.',
407
- 'This is the best-practice matcher for web elements.',
436
+ 'Prefer `by.web.id` over any other matchers when available.',
408
437
  ],
409
438
  },
410
439
  {
411
440
  signature: 'by.web.className(className: string)',
412
441
  description: 'Matches web elements by their CSS class name.',
413
- example: "web.element(by.web.className('btn-primary'));",
442
+ example: `await web.element(by.web.className('btn-login')).tap();`,
414
443
  },
415
444
  {
416
445
  signature: 'by.web.cssSelector(cssSelector: string)',
417
446
  description: 'Matches web elements using a CSS selector.',
418
- example: "web.element(by.web.cssSelector('.container > .item'));",
447
+ example: `await web.element(by.web.cssSelector('#product-list .product-item[data-id="123"]')).scrollToView();`,
419
448
  },
420
449
  {
421
450
  signature: 'by.web.name(name: string)',
422
451
  description: 'Matches web elements by their name attribute.',
423
- example: "web.element(by.web.name('email'));",
452
+ example: `await web.element(by.web.name('firstName')).typeText('John');`,
424
453
  },
425
454
  {
426
455
  signature: 'by.web.xpath(xpath: string)',
427
456
  description: 'Matches web elements using an XPath expression.',
428
- example: "web.element(by.web.xpath('//*[@id=\"submit\"]'));",
429
- guidelines: [
430
- 'Use when `by.web.id` is not available.',
431
- 'XPath matchers can be less performant.',
432
- ],
457
+ example: `await web.element(by.web.xpath('//button[text()="Continue"]')).tap();`,
433
458
  },
434
459
  {
435
460
  signature: 'by.web.href(href: string)',
436
461
  description: 'Matches web elements by their href attribute.',
437
- example: "web.element(by.web.href('https://example.com'));",
462
+ example: `await web.element(by.web.href('https://www.example.com/contact')).tap();`,
438
463
  },
439
464
  {
440
465
  signature: 'by.web.hrefContains(href: string)',
441
466
  description: 'Matches web elements whose href attribute contains the specified string.',
442
- example: "web.element(by.web.hrefContains('example.com'));",
467
+ example: `await web.element(by.web.hrefContains('/about')).tap();`,
443
468
  },
444
469
  {
445
470
  signature: 'by.web.tag(tag: string)',
446
471
  description: 'Matches web elements by their tag name.',
447
- example: "web.element(by.web.tag('h1'));",
472
+ example: `await expect(web.element(by.web.tag('h1'))).toHaveText('Welcome to Our Site');`,
448
473
  },
449
474
  {
450
475
  signature: 'by.web.value(value: string)',
451
476
  description: 'Matches web elements by their value attribute (iOS only).',
452
- example: "web.element(by.web.value('Submit'));",
453
- guidelines: ['Available on iOS only.'],
477
+ example: `await web.element(by.web.value('Sign In')).tap();`,
478
+ guidelines: [
479
+ 'Available on iOS only.',
480
+ ],
454
481
  },
455
482
  {
456
483
  signature: 'by.web.label(label: string)',
457
- description: 'Matches web elements by their accessibility label (iOS only, supports `asSecured()`).',
458
- example: "web.element(by.web.label('Submit')).asSecured();",
484
+ description: 'Matches web elements by their label (iOS only, supports `asSecured()`).',
485
+ example: `await web.element(by.web.label('Next')).tap();`,
459
486
  guidelines: [
460
487
  'Available on iOS only.',
461
- 'Use when the element has a unique label.',
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.',
462
490
  ],
463
491
  },
464
492
  {
465
493
  signature: 'by.web.type(accessibilityType: string)',
466
- description: 'Matches web elements by accessibility type (iOS only, with `asSecured()`).',
467
- example: "web.element(by.web.type('textField')).asSecured();",
494
+ description: 'Matches web elements by accessibility type (iOS only, `asSecured()` only).',
495
+ example: `await web.element(by.web.type('textField')).asSecured().typeText('Sample Text');`,
468
496
  guidelines: [
469
497
  'Available on iOS only and used with `asSecured()`.',
470
498
  'Type can be any XCUIElement.ElementType, e.g., "button", "textField".',
@@ -473,163 +501,166 @@ await device.launchApp({ launchArgs: { someLaunchArg: 1234 } });`,
473
501
  {
474
502
  signature: 'atIndex(index: number)',
475
503
  description: 'Selects the web element at the specified index from matched elements.',
476
- example: "web.element(by.web.tag('h1')).atIndex(1);",
477
- guidelines: ['Use when multiple web elements match the same matcher.'],
504
+ example: `await expect(web.element(by.web.tag('h2')).atIndex(1)).toHaveText('Features');`,
505
+ guidelines: [
506
+ 'Use when multiple web elements match the same matcher.',
507
+ ],
478
508
  },
479
509
  {
480
510
  signature: 'tap()',
481
511
  description: 'Taps on a web element.',
482
- example: "await web.element(by.web.id('link')).tap();",
512
+ example: `await web.element(by.web.label('Submit')).tap();`,
483
513
  guidelines: [
484
514
  'Supports `asSecured()` on iOS.',
485
- 'Use `asSecured()` when interacting with secured web views.',
486
515
  ],
487
516
  },
488
517
  {
489
- signature: 'typeText(text: string, isContentEditable?: boolean)',
518
+ signature: 'typeText(text: string)',
490
519
  description: 'Types text into a web element.',
491
- example: "await web.element(by.web.name('search')).typeText('Detox');",
520
+ example: `await web.element(by.web.id('rich-text-editor')).typeText('This is a test message');`,
492
521
  guidelines: [
493
- 'Set `isContentEditable` to `true` for content-editable elements on Android.',
494
- 'On iOS, content-editable elements are automatically detected.',
495
522
  'Supports `asSecured()` on iOS.',
496
523
  ],
497
524
  },
498
525
  {
499
526
  signature: 'replaceText(text: string)',
500
527
  description: 'Replaces text in a web element.',
501
- example: "await web.element(by.web.name('search')).replaceText('Detox');",
528
+ example: `await web.element(by.web.id('username')).replaceText('new_user');`,
502
529
  guidelines: [
503
- 'Currently not supported for content-editable elements on Android.',
504
530
  'Supports `asSecured()` on iOS.',
505
531
  ],
506
532
  },
507
533
  {
508
534
  signature: 'clearText()',
509
535
  description: 'Clears text from a web element.',
510
- example: "await web.element(by.web.name('search')).clearText();",
536
+ example: `await web.element(by.web.id('comments')).clearText();`,
511
537
  guidelines: [
512
- 'Currently not supported for content-editable elements on Android.',
513
538
  'Supports `asSecured()` on iOS.',
514
539
  ],
515
540
  },
516
541
  {
517
542
  signature: 'selectAllText()',
518
543
  description: 'Selects all text in a web element.',
519
- example: "await web.element(by.web.id('editor')).selectAllText();",
520
- guidelines: [
521
- 'Supported for content-editable elements only on Android.',
522
- 'On iOS, Detox can select all text of any element that supports it.',
523
- ],
544
+ example: `await web.element(by.web.id('notes')).selectAllText();`,
524
545
  },
525
546
  {
526
547
  signature: 'getText()',
527
548
  description: 'Retrieves the text content of a web element.',
528
549
  example: `
529
- const text = await web.element(by.web.id('identifier')).getText();
530
- jestExpect(text).toBe('Hello World!');
531
- `,
550
+ const description = await web.element(by.web.id('product-description')).getText();
551
+ jestExpect(description).toContain('This product is made from the finest materials.');
552
+ `,
532
553
  guidelines: [
533
554
  'Use for assertions on the element\'s text content.',
534
- 'Requires importing `jestExpect` for assertions.',
535
555
  ],
536
556
  },
537
557
  {
538
558
  signature: 'scrollToView()',
539
559
  description: 'Scrolls the web view to bring the element into view.',
540
- example: "await web.element(by.web.id('footer')).scrollToView();",
560
+ example: `await web.element(by.web.id('contact-section')).scrollToView();`,
541
561
  },
542
562
  {
543
563
  signature: 'focus()',
544
564
  description: 'Focuses on a web element.',
545
- example: "await web.element(by.web.id('search')).focus();",
565
+ example: `
566
+ await web.element(by.web.id('email-input')).focus();
567
+ await web.element(by.web.id('email-input')).typeText('user@example.com');
568
+ `,
569
+ guidelines: [
570
+ 'Useful for input fields that require focus before typing.',
571
+ 'No need for secured interactions on iOS.',
572
+ ]
546
573
  },
547
574
  {
548
575
  signature: 'moveCursorToEnd()',
549
576
  description: 'Moves the input cursor to the end of the element\'s content.',
550
- example: "await web.element(by.web.id('editor')).moveCursorToEnd();",
551
- guidelines: [
552
- 'Supported for content-editable elements only on Android.',
553
- 'On iOS, Detox can move the cursor to the end of any element that supports it.',
554
- ],
577
+ example: `
578
+ await web.element(by.web.id('message-box')).moveCursorToEnd();
579
+ await web.element(by.web.id('message-box')).typeText(' Adding more text.');
580
+ `,
555
581
  },
556
582
  {
557
583
  signature: 'runScript(script: string, args?: any[])',
558
584
  description: 'Runs a JavaScript function on the element.',
559
585
  example: `
560
- const webElement = web.element(by.web.id('identifier'));
561
- await webElement.runScript('(el) => el.click()');
586
+ // Click an element using a custom script
587
+ await web.element(by.web.id('hidden-button')).runScript('el => el.click()');
562
588
 
563
- // With arguments
564
- await webElement.runScript('(el, args) => el.setAttribute("value", args[0])', ['Detox']);
589
+ // Set the value of an input field using a custom script
590
+ await web.element(by.web.id('username')).runScript('(el, args) => el.value = args[0]', ['new_user']);
565
591
 
566
- // Using function syntax
567
- const fontSize = await webElement.runScript(function get(element) {
568
- return element.style.fontSize;
592
+ // Get the color of an element
593
+ const color = await web.element(by.web.id('header')).runScript(function(el) {
594
+ return window.getComputedStyle(el).color;
569
595
  });
570
- jestExpect(fontSize).toBe('16px');
596
+ jestExpect(color).toBe('rgb(0, 0, 0)');
571
597
 
572
- // Scrolling to the bottom of a scrollable web-element
573
- await webElement.runScript('el => el.scrollTop = el.scrollHeight');
574
- `,
598
+ // Scroll an element into view if not visible
599
+ await web.element(by.web.id('lazy-image')).runScript('el => el.scrollIntoView()');
600
+ `,
575
601
  guidelines: [
576
602
  'The script can accept additional arguments and return a value.',
577
603
  'Ensure that arguments and return values are serializable.',
578
604
  'Useful for custom interactions or retrieving properties.',
605
+ 'Avoid using this method for simple interactions like tapping or typing.',
579
606
  ],
580
607
  },
581
608
  {
582
609
  signature: 'getCurrentUrl()',
583
610
  description: 'Retrieves the current URL of the web view.',
584
611
  example: `
585
- const url = await web.element(by.web.id('identifier')).getCurrentUrl();
586
- jestExpect(url).toBe('https://example.com');
587
- `,
612
+ await web.element(by.web.id('link-to-page')).tap();
613
+ const currentUrl = await web.element(by.web.tag('body')).getCurrentUrl();
614
+ jestExpect(currentUrl).toBe('https://www.example.com/target-page');
615
+ `,
588
616
  guidelines: [
589
617
  'Must be called from an inner element, not the root web view.',
590
- 'May have issues on Android; check relevant GitHub issues.',
591
618
  ],
592
619
  },
593
620
  {
594
621
  signature: 'getTitle()',
595
622
  description: 'Retrieves the title of the web view.',
596
623
  example: `
597
- const title = await web.element(by.web.id('identifier')).getTitle();
598
- jestExpect(title).toBe('Welcome Page');
599
- `,
624
+ const pageTitle = await web.element(by.web.tag('body')).getTitle();
625
+ jestExpect(pageTitle).toBe('Dashboard - MyApp');
626
+ `,
600
627
  guidelines: [
601
628
  'Must be called from an inner element, not the root web view.',
602
629
  ],
603
630
  },
604
631
  {
605
632
  signature: 'toHaveText(text: string)',
606
- description: 'Asserts that the web element has the specified text.',
607
- example: "await expect(web.element(by.web.tag('h1'))).toHaveText('Welcome');",
633
+ description: 'Asserts that the web element has the specified text. Used with `expect()`.',
634
+ example: `await expect(web.element(by.web.name('submit-button'))).toHaveText('Submit');`,
635
+ guidelines: [
636
+ 'For web views, the text is the inner text of the element, e.g., `<h1>Welcome to the webpage!</h1>`.',
637
+ ],
608
638
  },
609
639
  {
610
640
  signature: 'toExist()',
611
- description: 'Asserts that the web element exists.',
612
- example: "await expect(web.element(by.web.xpath('//*[@id=\"main\"]'))).toExist();",
641
+ description: 'Asserts that the web element exists. Used with `expect()`.',
642
+ example: `await expect(web.element(by.web.id('error-message'))).toExist();`,
613
643
  guidelines: [
644
+ 'Verifies the presence of a web element in the DOM.',
614
645
  'Supports `asSecured()` on iOS.',
615
646
  ],
616
647
  },
617
648
  {
618
649
  signature: 'not',
619
650
  description: 'Negates the expectation for web elements.',
620
- example: "await expect(web.element(by.web.id('error'))).not.toExist();",
651
+ example: `await expect(web.element(by.web.id('loading-spinner'))).not.toExist();`,
621
652
  guidelines: [
653
+ 'Use `not` to assert that an element should not be present.',
622
654
  'Supports `asSecured()` on iOS.',
623
655
  ],
624
656
  },
625
657
  {
626
658
  signature: 'asSecured()',
627
659
  description: 'Interacts with secured web views (iOS only).',
628
- example: "await web.element(by.web.label('Submit')).asSecured().tap();",
660
+ example: `await web.element(by.web.label('Confirm')).asSecured().tap();`,
629
661
  guidelines: [
630
662
  'Use for web pages with secured protocols when regular interactions fail.',
631
- 'Available on iOS only and currently experimental.',
632
- 'Less performant and has fewer APIs.',
663
+ 'Applicable on iOS only with specific APIs.',
633
664
  ],
634
665
  },
635
666
  ],
@@ -638,7 +669,7 @@ jestExpect(title).toBe('Welcome Page');
638
669
  },
639
670
 
640
671
  captureSnapshotImage: async function () {
641
- const fileName = `snapshot_${Date.now()}.png`;
672
+ const fileName = `snapshot_${Date.now()}.png`;
642
673
  try {
643
674
  return await detox.device.takeScreenshot(fileName);
644
675
  } catch (_error) {
@@ -1 +0,0 @@
1
- 8cd2f48786d004ff90fcc48db9b9e69a
@@ -1 +0,0 @@
1
- 4afea56e335fc27ee2b92be48673dea8a05185aa
@@ -1 +0,0 @@
1
- 0568be3312760e3a3a4259cc771a7253074502547e8eb3350213cde9f8db6165
@@ -1 +0,0 @@
1
- 2287316f0b862561456bef92c561598fcff17e286f17bc262470ef25cc6f71e84b16a8058e37f7f1536fc3a0433df990ba20173dd132b4c561c71e62a07e2fe6
@@ -1 +0,0 @@
1
- 14161501d9cf4606ee49296e14c047e4
@@ -1 +0,0 @@
1
- 38e956edb72453c00c00ab752443f394389737bf
@@ -1 +0,0 @@
1
- 0a76b1d5efeea5e83fa9e92e75bc29913b9e7db28b7b30652638966506299f90
@@ -1 +0,0 @@
1
- f3b3510a065744da054200cbcfb62549d469aa27068939879f07c64421cfef223aa34ed6346b6e9c5839a1a42cdc76699b16ad4395545abfb01cd611381df408
@@ -1 +0,0 @@
1
- 2d7e0ca8745e2abb2087e946367c0538
@@ -1 +0,0 @@
1
- 071d2ecd2ac499ecef2bff9c5b3f830c613709ca
@@ -1 +0,0 @@
1
- 865a27d4ce918936ef0a629b2eb2c21dedc9e21629710732b2eb8ae9fd4374df
@@ -1 +0,0 @@
1
- 58f3c7bc9e6bbc5885f03460545c4832bab2c29490afcbc003d5ee0acb3cf6975f0d890292d4ac587d73c986a42e1c67624617f6fee6da9163ccf76ee5d730ab
@@ -1 +0,0 @@
1
- b4efad81e134dacbb7d81b566aed6d89
@@ -1 +0,0 @@
1
- e994e4dad3f2dce5f5fde279bc6cd917ee6b2f07
@@ -1 +0,0 @@
1
- 7e9153002e13fa5ffeef31eeda43b00e38bacbcba46640ce59fb42220a51c22a
@@ -1 +0,0 @@
1
- 818984bbddf7bf9561bc6bc9e646cb2f89d5cd83c863aef37c5bf1a3911d08c6a4dc04b8251a85208c7ae308b11e6970a94d33fb2293dbd8bf3c6df6cd55d3ab
@@ -1 +0,0 @@
1
- 02d974914d78e64b365486e3369ae1e1
@@ -1 +0,0 @@
1
- 173b898bfecd41c34b0ad24d7e1996c8d3b0621b
@@ -1 +0,0 @@
1
- 8a30f740e17ad80816f17ceb61b354d7da12f651764e040ddf85b1c3609992a3
@@ -1 +0,0 @@
1
- 90f61852b868773b3548daf4c04793cc0285df750cbfb8947375ec81f5882469cf6e6132295e3b115b27d61733c1bb5f4954a14e7246aa8da19e97bd28191c5f
@@ -1 +0,0 @@
1
- 965972ea4b2739cb5d958a329b9bcc3d
@@ -1 +0,0 @@
1
- b6d5cfb02046495791ca031d12b9f2310f799a0e
@@ -1 +0,0 @@
1
- b27221155e7cfcfab8c62c949d47cd71967e19b243c001e53ac518e4cf900769
@@ -1 +0,0 @@
1
- d9c28fba54e53d5546f30c9b43326175f6ac8cf3194a8d0faea4d97b487198eb994f06249994c579b0f82f7ab0c7685689fe605887668dc2eaa5e659892e388a