detox 20.27.3 → 20.27.4

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 (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