detox 21.0.0-rc.0 → 21.0.0-rc.10

Sign up to get free protection for your applications and to get access to all the features.
Files changed (202) hide show
  1. package/.eslintignore +3 -0
  2. package/.eslintrc.js +1 -40
  3. package/Detox-android/com/wix/detox/{21.0.0-rc.0/detox-21.0.0-rc.0-javadoc.jar → 21.0.0-rc.10/detox-21.0.0-rc.10-javadoc.jar} +0 -0
  4. package/Detox-android/com/wix/detox/21.0.0-rc.10/detox-21.0.0-rc.10-javadoc.jar.md5 +1 -0
  5. package/Detox-android/com/wix/detox/21.0.0-rc.10/detox-21.0.0-rc.10-javadoc.jar.sha1 +1 -0
  6. package/Detox-android/com/wix/detox/21.0.0-rc.10/detox-21.0.0-rc.10-javadoc.jar.sha256 +1 -0
  7. package/Detox-android/com/wix/detox/21.0.0-rc.10/detox-21.0.0-rc.10-javadoc.jar.sha512 +1 -0
  8. package/Detox-android/com/wix/detox/{21.0.0-rc.0/detox-21.0.0-rc.0-sources.jar → 21.0.0-rc.10/detox-21.0.0-rc.10-sources.jar} +0 -0
  9. package/Detox-android/com/wix/detox/21.0.0-rc.10/detox-21.0.0-rc.10-sources.jar.md5 +1 -0
  10. package/Detox-android/com/wix/detox/21.0.0-rc.10/detox-21.0.0-rc.10-sources.jar.sha1 +1 -0
  11. package/Detox-android/com/wix/detox/21.0.0-rc.10/detox-21.0.0-rc.10-sources.jar.sha256 +1 -0
  12. package/Detox-android/com/wix/detox/21.0.0-rc.10/detox-21.0.0-rc.10-sources.jar.sha512 +1 -0
  13. package/Detox-android/com/wix/detox/21.0.0-rc.10/detox-21.0.0-rc.10.aar +0 -0
  14. package/Detox-android/com/wix/detox/21.0.0-rc.10/detox-21.0.0-rc.10.aar.md5 +1 -0
  15. package/Detox-android/com/wix/detox/21.0.0-rc.10/detox-21.0.0-rc.10.aar.sha1 +1 -0
  16. package/Detox-android/com/wix/detox/21.0.0-rc.10/detox-21.0.0-rc.10.aar.sha256 +1 -0
  17. package/Detox-android/com/wix/detox/21.0.0-rc.10/detox-21.0.0-rc.10.aar.sha512 +1 -0
  18. package/Detox-android/com/wix/detox/{21.0.0-rc.0/detox-21.0.0-rc.0.pom → 21.0.0-rc.10/detox-21.0.0-rc.10.pom} +1 -7
  19. package/Detox-android/com/wix/detox/21.0.0-rc.10/detox-21.0.0-rc.10.pom.md5 +1 -0
  20. package/Detox-android/com/wix/detox/21.0.0-rc.10/detox-21.0.0-rc.10.pom.sha1 +1 -0
  21. package/Detox-android/com/wix/detox/21.0.0-rc.10/detox-21.0.0-rc.10.pom.sha256 +1 -0
  22. package/Detox-android/com/wix/detox/21.0.0-rc.10/detox-21.0.0-rc.10.pom.sha512 +1 -0
  23. package/Detox-android/com/wix/detox/maven-metadata.xml +4 -4
  24. package/Detox-android/com/wix/detox/maven-metadata.xml.md5 +1 -1
  25. package/Detox-android/com/wix/detox/maven-metadata.xml.sha1 +1 -1
  26. package/Detox-android/com/wix/detox/maven-metadata.xml.sha256 +1 -1
  27. package/Detox-android/com/wix/detox/maven-metadata.xml.sha512 +1 -1
  28. package/Detox-ios-framework.tbz +0 -0
  29. package/Detox-ios-src.tbz +0 -0
  30. package/Detox-ios-xcuitest.tbz +0 -0
  31. package/android/build.gradle +20 -10
  32. package/android/detox/build.gradle +24 -12
  33. package/android/detox/src/full/java/com/wix/detox/espresso/DetoxAssertion.java +44 -25
  34. package/android/detox/src/full/java/com/wix/detox/espresso/DetoxMatcher.java +12 -12
  35. package/android/detox/src/full/java/com/wix/detox/espresso/EspressoDetox.java +6 -7
  36. package/android/detox/src/full/java/com/wix/detox/espresso/action/AdjustSliderToPositionAction.kt +2 -2
  37. package/android/detox/src/full/java/com/wix/detox/espresso/action/GetAttributesAction.kt +34 -35
  38. package/android/detox/src/full/java/com/wix/detox/espresso/common/MaterialSliderHelper.kt +21 -0
  39. package/android/detox/src/full/java/com/wix/detox/espresso/common/{SliderHelper.kt → ReactSliderHelper.kt} +7 -6
  40. package/android/detox/src/full/java/com/wix/detox/espresso/matcher/RegexMatcher.kt +56 -0
  41. package/android/detox/src/full/java/com/wix/detox/espresso/matcher/ViewMatchers.kt +18 -6
  42. package/android/detox/src/full/java/com/wix/detox/espresso/performer/MultipleViewsActionPerformer.kt +43 -0
  43. package/android/detox/src/full/java/com/wix/detox/espresso/performer/SingleViewActionPerformer.kt +19 -0
  44. package/android/detox/src/full/java/com/wix/detox/espresso/performer/ViewActionPerformer.kt +24 -0
  45. package/android/detox/src/full/java/com/wix/detox/espresso/web/WebElement.java +4 -4
  46. package/android/detox/src/full/java/com/wix/invoke/types/Invocation.java +7 -6
  47. package/android/detox/src/main/java/com/wix/detox/espresso/MultipleViewsAction.kt +4 -0
  48. package/android/detox/src/main/java/com/wix/detox/espresso/UiControllerSpy.kt +0 -1
  49. package/android/detox/src/main/java/com/wix/detox/espresso/ViewActionWithResult.kt +2 -1
  50. package/android/detox/src/main/java/com/wix/detox/espresso/action/common/MotionEvents.kt +60 -4
  51. package/android/detox/src/testFull/java/com/wix/detox/espresso/action/GetAttributesActionTest.kt +6 -5
  52. package/android/detox/src/testFull/java/com/wix/detox/espresso/common/MaterialSliderHelperTest.kt +33 -0
  53. package/android/detox/src/testFull/java/com/wix/detox/espresso/common/{SliderHelperTest.kt → ReactSliderHelperTest.kt} +3 -3
  54. package/android/detox/src/testFull/java/com/wix/detox/espresso/matcher/RegexMatcherTest.kt +52 -0
  55. package/android/detox/src/testFull/java/com/wix/detox/espresso/performer/ViewActionPerformerSpec.kt +37 -0
  56. package/android/detox/src/testFull/java/com/wix/invoke/JsonParserTest.java +23 -7
  57. package/android/detox/src/testFull/resources/targetInvocationEspressoWebDetoxScript.json +47 -0
  58. package/android/gradle/wrapper/gradle-wrapper.properties +1 -1
  59. package/android/rninfo.gradle +25 -0
  60. package/android/settings.gradle +2 -1
  61. package/detox.d.ts +1840 -0
  62. package/globals.d.ts +23 -0
  63. package/index.d.ts +2 -1789
  64. package/internals.d.ts +11 -1
  65. package/jest.config.js +108 -0
  66. package/local-cli/reset-lock-file.js +5 -9
  67. package/local-cli/startCommand/AppStartCommand.js +4 -1
  68. package/local-cli/testCommand/TestRunnerCommand.js +26 -3
  69. package/local-cli/utils/interruptListeners.js +15 -0
  70. package/package.json +15 -108
  71. package/runners/jest/reporter.js +21 -1
  72. package/runners/jest/reporters/DetoxIPCReporter.js +34 -0
  73. package/runners/jest/reporters/DetoxReporterDispatcher.js +144 -0
  74. package/runners/jest/reporters/DetoxSummaryReporter.js +16 -0
  75. package/runners/jest/reporters/DetoxVerboseReporter.js +16 -0
  76. package/runners/jest/reporters/index.js +6 -0
  77. package/runners/jest/testEnvironment/index.js +11 -0
  78. package/src/DetoxWorker.js +5 -11
  79. package/src/android/core/NativeElement.js +26 -29
  80. package/src/android/core/WebElement.js +24 -6
  81. package/src/android/espressoapi/DetoxAssertion.js +16 -14
  82. package/src/android/espressoapi/DetoxMatcher.js +24 -8
  83. package/src/android/espressoapi/EspressoDetox.js +9 -2
  84. package/src/android/espressoapi/web/WebElement.js +1 -4
  85. package/src/android/interactions/native.js +2 -3
  86. package/src/android/matchers/index.js +4 -0
  87. package/src/android/matchers/native.js +9 -4
  88. package/src/android/matchers/web.js +26 -1
  89. package/src/artifacts/providers/index.js +3 -3
  90. package/src/artifacts/screenshot/SimulatorScreenshotPlugin.js +0 -17
  91. package/src/configuration/composeLoggerConfig.js +1 -0
  92. package/src/configuration/composeRunnerConfig.js +3 -1
  93. package/src/devices/allocation/DeviceAllocator.js +66 -20
  94. package/src/devices/allocation/DeviceList.js +44 -0
  95. package/src/devices/allocation/DeviceRegistry.js +189 -0
  96. package/src/devices/allocation/drivers/AllocationDriverBase.d.ts +15 -0
  97. package/src/devices/{common/drivers/android/tools → allocation/drivers/android}/FreeDeviceFinder.js +11 -10
  98. package/src/devices/allocation/drivers/android/attached/AttachedAndroidAllocDriver.js +22 -17
  99. package/src/devices/allocation/drivers/android/emulator/EmulatorAllocDriver.js +97 -38
  100. package/src/devices/allocation/drivers/android/emulator/EmulatorLauncher.js +32 -45
  101. package/src/devices/allocation/drivers/android/emulator/FreeEmulatorFinder.js +1 -1
  102. package/src/devices/allocation/drivers/android/emulator/FreePortFinder.js +37 -0
  103. package/src/devices/allocation/drivers/android/emulator/launchEmulatorProcess.js +3 -3
  104. package/src/devices/allocation/drivers/android/genycloud/GenyAllocDriver.js +104 -32
  105. package/src/devices/allocation/drivers/android/genycloud/GenyInstanceLauncher.js +40 -31
  106. package/src/devices/allocation/drivers/android/genycloud/GenyRegistry.js +121 -0
  107. package/src/devices/allocation/drivers/android/genycloud/services/GenyInstanceLifecycleService.js +24 -0
  108. package/src/devices/{common → allocation}/drivers/android/genycloud/services/GenyRecipesService.js +1 -1
  109. package/src/devices/allocation/drivers/android/genycloud/services/dto/GenyInstance.js +83 -0
  110. package/src/devices/allocation/drivers/android/genycloud/services/dto/GenyRecipe.js +25 -0
  111. package/src/devices/allocation/drivers/ios/SimulatorAllocDriver.js +95 -54
  112. package/src/devices/allocation/drivers/ios/SimulatorQuery.js +24 -0
  113. package/src/devices/allocation/factories/android.js +29 -35
  114. package/src/devices/allocation/factories/ios.js +6 -7
  115. package/src/devices/common/drivers/DeviceCookie.d.ts +12 -0
  116. package/src/devices/common/drivers/android/cookies.d.ts +11 -0
  117. package/src/devices/common/drivers/android/emulator/exec/EmulatorExec.js +17 -5
  118. package/src/devices/common/drivers/android/exec/ADB.js +1 -0
  119. package/src/devices/common/drivers/android/tools/instrumentationArgs.js +7 -1
  120. package/src/devices/common/drivers/ios/cookies.d.ts +9 -0
  121. package/src/devices/common/drivers/ios/tools/AppleSimUtils.js +3 -1
  122. package/src/devices/cookies/index.js +0 -6
  123. package/src/devices/runtime/drivers/android/genycloud/GenyCloudDriver.js +7 -6
  124. package/src/devices/runtime/drivers/ios/SimulatorDriver.js +9 -24
  125. package/src/devices/runtime/drivers/ios/XCUITestUtils.js +33 -19
  126. package/src/devices/runtime/factories/android.js +3 -11
  127. package/src/devices/runtime/factories/ios.js +3 -4
  128. package/src/{servicelocator → devices/servicelocator}/android/emulatorServiceLocator.js +1 -1
  129. package/src/devices/servicelocator/android/genycloudServiceLocator.js +17 -0
  130. package/src/devices/servicelocator/android/index.js +23 -0
  131. package/src/{validation → devices/validation}/EnvironmentValidatorBase.js +1 -0
  132. package/src/{validation → devices/validation}/android/GenycloudEnvValidator.js +2 -2
  133. package/src/{validation → devices/validation}/factories/index.js +1 -1
  134. package/src/{validation → devices/validation}/ios/IosSimulatorEnvValidator.js +2 -2
  135. package/src/environmentFactory.js +1 -11
  136. package/src/invoke.js +0 -2
  137. package/src/ios/expectTwo.js +28 -11
  138. package/src/ios/web.js +302 -0
  139. package/src/ipc/IPCClient.js +22 -1
  140. package/src/ipc/IPCServer.js +42 -1
  141. package/src/ipc/SessionState.js +1 -0
  142. package/src/logger/DetoxLogger.js +2 -2
  143. package/src/realms/DetoxContext.js +8 -0
  144. package/src/realms/DetoxInternalsFacade.js +1 -0
  145. package/src/realms/DetoxPrimaryContext.js +49 -44
  146. package/src/realms/DetoxSecondaryContext.js +27 -0
  147. package/src/realms/symbols.js +6 -0
  148. package/src/utils/PIDService.js +27 -0
  149. package/src/utils/assertIsFunction.js +35 -0
  150. package/src/utils/environment.js +8 -15
  151. package/src/utils/errorUtils.js +3 -3
  152. package/src/utils/invocationTraceDescriptions.js +16 -0
  153. package/src/utils/isArrowFunction.js +24 -0
  154. package/src/utils/isRegExp.js +7 -0
  155. package/tsconfig.json +8 -3
  156. package/Detox-android/com/wix/detox/21.0.0-rc.0/detox-21.0.0-rc.0-javadoc.jar.md5 +0 -1
  157. package/Detox-android/com/wix/detox/21.0.0-rc.0/detox-21.0.0-rc.0-javadoc.jar.sha1 +0 -1
  158. package/Detox-android/com/wix/detox/21.0.0-rc.0/detox-21.0.0-rc.0-javadoc.jar.sha256 +0 -1
  159. package/Detox-android/com/wix/detox/21.0.0-rc.0/detox-21.0.0-rc.0-javadoc.jar.sha512 +0 -1
  160. package/Detox-android/com/wix/detox/21.0.0-rc.0/detox-21.0.0-rc.0-sources.jar.md5 +0 -1
  161. package/Detox-android/com/wix/detox/21.0.0-rc.0/detox-21.0.0-rc.0-sources.jar.sha1 +0 -1
  162. package/Detox-android/com/wix/detox/21.0.0-rc.0/detox-21.0.0-rc.0-sources.jar.sha256 +0 -1
  163. package/Detox-android/com/wix/detox/21.0.0-rc.0/detox-21.0.0-rc.0-sources.jar.sha512 +0 -1
  164. package/Detox-android/com/wix/detox/21.0.0-rc.0/detox-21.0.0-rc.0.aar +0 -0
  165. package/Detox-android/com/wix/detox/21.0.0-rc.0/detox-21.0.0-rc.0.aar.md5 +0 -1
  166. package/Detox-android/com/wix/detox/21.0.0-rc.0/detox-21.0.0-rc.0.aar.sha1 +0 -1
  167. package/Detox-android/com/wix/detox/21.0.0-rc.0/detox-21.0.0-rc.0.aar.sha256 +0 -1
  168. package/Detox-android/com/wix/detox/21.0.0-rc.0/detox-21.0.0-rc.0.aar.sha512 +0 -1
  169. package/Detox-android/com/wix/detox/21.0.0-rc.0/detox-21.0.0-rc.0.pom.md5 +0 -1
  170. package/Detox-android/com/wix/detox/21.0.0-rc.0/detox-21.0.0-rc.0.pom.sha1 +0 -1
  171. package/Detox-android/com/wix/detox/21.0.0-rc.0/detox-21.0.0-rc.0.pom.sha256 +0 -1
  172. package/Detox-android/com/wix/detox/21.0.0-rc.0/detox-21.0.0-rc.0.pom.sha512 +0 -1
  173. package/runners/jest/reporters/DetoxReporter.js +0 -36
  174. package/src/devices/DeviceRegistry.js +0 -176
  175. package/src/devices/allocation/drivers/AllocationDriverBase.js +0 -30
  176. package/src/devices/allocation/drivers/android/attached/AttachedAndroidLauncher.js +0 -13
  177. package/src/devices/allocation/drivers/android/emulator/EmulatorAllocationHelper.js +0 -72
  178. package/src/devices/allocation/drivers/android/genycloud/GenyDeviceRegistryFactory.js +0 -16
  179. package/src/devices/allocation/drivers/android/genycloud/GenyInstanceAllocationHelper.js +0 -65
  180. package/src/devices/allocation/drivers/ios/SimulatorLauncher.js +0 -21
  181. package/src/devices/common/drivers/DeviceAllocationHelper.js +0 -20
  182. package/src/devices/common/drivers/DeviceLauncher.js +0 -19
  183. package/src/devices/common/drivers/android/genycloud/services/GenyInstanceLifecycleService.js +0 -25
  184. package/src/devices/common/drivers/android/genycloud/services/GenyInstanceLookupService.js +0 -38
  185. package/src/devices/common/drivers/android/genycloud/services/GenyInstanceNaming.js +0 -14
  186. package/src/devices/common/drivers/android/genycloud/services/dto/GenyInstance.js +0 -66
  187. package/src/devices/common/drivers/android/genycloud/services/dto/GenyRecipe.js +0 -13
  188. package/src/devices/cookies/AndroidDeviceCookie.js +0 -13
  189. package/src/devices/cookies/AndroidEmulatorCookie.js +0 -6
  190. package/src/devices/cookies/AttachedAndroidDeviceCookie.js +0 -12
  191. package/src/devices/cookies/DeviceCookie.js +0 -4
  192. package/src/devices/cookies/GenycloudEmulatorCookie.js +0 -20
  193. package/src/devices/cookies/IosCookie.js +0 -6
  194. package/src/devices/cookies/IosSimulatorCookie.js +0 -10
  195. package/src/devices/lifecycle/GenyGlobalLifecycleHandler.js +0 -71
  196. package/src/devices/lifecycle/factories/GenyGlobalLifecycleHandlerFactory.js +0 -18
  197. package/src/invoke/EarlGrey.js +0 -8
  198. package/src/servicelocator/android/genycloudServiceLocator.js +0 -21
  199. package/src/servicelocator/android/index.js +0 -25
  200. package/src/servicelocator/ios.js +0 -7
  201. /package/src/devices/{common → allocation}/drivers/android/genycloud/exec/GenyCloudExec.js +0 -0
  202. /package/src/devices/{common → allocation}/drivers/android/genycloud/services/GenyAuthService.js +0 -0
@@ -70,7 +70,14 @@ class DetoxCircusEnvironment extends NodeEnvironment {
70
70
  await this.initDetox();
71
71
  }
72
72
 
73
+ // @ts-expect-error TS2425
73
74
  async handleTestEvent(event, state) {
75
+ if (detox.session.unsafe_earlyTeardown) {
76
+ if (event.name === 'test_fn_start' || event.name === 'hook_start') {
77
+ throw new Error('Detox halted test execution due to an early teardown request');
78
+ }
79
+ }
80
+
74
81
  this._timer.schedule(state.testTimeout != null ? state.testTimeout : this.setupTimeout);
75
82
 
76
83
  if (SYNC_CIRCUS_EVENTS.has(event.name)) {
@@ -102,6 +109,10 @@ class DetoxCircusEnvironment extends NodeEnvironment {
102
109
  * @protected
103
110
  */
104
111
  async initDetox() {
112
+ if (detox.session.unsafe_earlyTeardown) {
113
+ throw new Error('Detox halted test execution due to an early teardown request');
114
+ }
115
+
105
116
  const opts = {
106
117
  global: this.global,
107
118
  workerId: `w${process.env.JEST_WORKER_ID}`,
@@ -33,7 +33,6 @@ class DetoxWorker {
33
33
  onError: this._onEmitError.bind(this),
34
34
  });
35
35
 
36
-
37
36
  /** @type {DetoxInternals.RuntimeConfig['apps']} */
38
37
  this._appsConfig = null;
39
38
  /** @type {DetoxInternals.RuntimeConfig['artifacts']} */
@@ -60,7 +59,6 @@ class DetoxWorker {
60
59
  /** @type {Detox.WebFacade} */
61
60
  this.web = null;
62
61
 
63
- this._deviceAllocator = null;
64
62
  this._deviceCookie = null;
65
63
 
66
64
  this.trace = this._context.trace;
@@ -115,14 +113,13 @@ class DetoxWorker {
115
113
  const {
116
114
  // @ts-ignore
117
115
  envValidatorFactory,
118
- deviceAllocatorFactory,
119
116
  // @ts-ignore
120
117
  artifactsManagerFactory,
121
118
  // @ts-ignore
122
119
  matchersFactory,
123
120
  // @ts-ignore
124
121
  runtimeDeviceFactory,
125
- } = environmentFactory.createFactories(this._deviceConfig);
122
+ } = environmentFactory.createFactories(deviceConfig);
126
123
 
127
124
  const envValidator = envValidatorFactory.createValidator();
128
125
  yield envValidator.validate();
@@ -135,10 +132,7 @@ class DetoxWorker {
135
132
  };
136
133
 
137
134
  this._artifactsManager = artifactsManagerFactory.createArtifactsManager(this._artifactsConfig, commonDeps);
138
- this._deviceAllocator = deviceAllocatorFactory.createDeviceAllocator(commonDeps);
139
- this._deviceCookie = yield this._deviceAllocator.allocate(this._deviceConfig);
140
-
141
- yield this._deviceAllocator.postAllocate(this._deviceCookie);
135
+ this._deviceCookie = yield this._context[symbols.allocateDevice]();
142
136
 
143
137
  this.device = runtimeDeviceFactory.createRuntimeDevice(
144
138
  this._deviceCookie,
@@ -157,6 +151,8 @@ class DetoxWorker {
157
151
  });
158
152
  Object.assign(this, matchers);
159
153
 
154
+ yield this._eventEmitter.emit('bootDevice', { deviceId: this.device.id });
155
+
160
156
  if (behaviorConfig.init.exposeGlobals) {
161
157
  const injectedGlobals = {
162
158
  ...matchers,
@@ -207,11 +203,9 @@ class DetoxWorker {
207
203
  }
208
204
 
209
205
  if (this._deviceCookie) {
210
- const shutdown = this._behaviorConfig ? this._behaviorConfig.cleanup.shutdownDevice : false;
211
- await this._deviceAllocator.free(this._deviceCookie, { shutdown });
206
+ await this._context[symbols.deallocateDevice](this._deviceCookie);
212
207
  }
213
208
 
214
- this._deviceAllocator = null;
215
209
  this._deviceCookie = null;
216
210
  this.device = null;
217
211
  }
@@ -15,39 +15,37 @@ class NativeElement {
15
15
  constructor(invocationManager, emitter, matcher) {
16
16
  this._invocationManager = invocationManager;
17
17
  this._emitter = emitter;
18
- this._originalMatcher = matcher;
19
- this._selectElementWithMatcher(this._originalMatcher);
18
+ this._matcher = matcher;
20
19
  }
21
20
 
22
- _selectElementWithMatcher(matcher) {
23
- this._call = invoke.call(invoke.Espresso, 'onView', matcher._call);
21
+ get _call() {
22
+ return invoke.call(invoke.Espresso, 'onView', this._matcher._call);
24
23
  }
25
24
 
26
25
  atIndex(index) {
27
26
  if (typeof index !== 'number') throw new DetoxRuntimeError({ message: `Element atIndex argument must be a number, got ${typeof index}` });
28
- const matcher = this._originalMatcher;
29
- this._originalMatcher._call = invoke.callDirectly(DetoxMatcherApi.matcherForAtIndex(index, matcher._call.value));
27
+ const matcher = this._matcher;
28
+ this._matcher._call = invoke.callDirectly(DetoxMatcherApi.matcherForAtIndex(index, matcher._call.value));
30
29
 
31
- this._selectElementWithMatcher(this._originalMatcher);
32
30
  return this;
33
31
  }
34
32
 
35
33
  async tap(value) {
36
34
  const action = new actions.TapAction(value);
37
35
  const traceDescription = actionDescription.tapAtPoint(value);
38
- return await new ActionInteraction(this._invocationManager, this, action, traceDescription).execute();
36
+ return await new ActionInteraction(this._invocationManager, this._matcher, action, traceDescription).execute();
39
37
  }
40
38
 
41
39
  async tapAtPoint(value) {
42
40
  const action = new actions.TapAtPointAction(value);
43
41
  const traceDescription = actionDescription.tapAtPoint(value);
44
- return await new ActionInteraction(this._invocationManager, this, action, traceDescription).execute();
42
+ return await new ActionInteraction(this._invocationManager, this._matcher, action, traceDescription).execute();
45
43
  }
46
44
 
47
45
  async longPress() {
48
46
  const action = new actions.LongPressAction();
49
47
  const traceDescription = actionDescription.longPress();
50
- return await new ActionInteraction(this._invocationManager, this, action, traceDescription).execute();
48
+ return await new ActionInteraction(this._invocationManager, this._matcher, action, traceDescription).execute();
51
49
  }
52
50
 
53
51
  async multiTap(times) {
@@ -56,61 +54,61 @@ class NativeElement {
56
54
 
57
55
  const action = new actions.MultiClickAction(times);
58
56
  const traceDescription = actionDescription.multiTap(times);
59
- return await new ActionInteraction(this._invocationManager, this, action, traceDescription).execute();
57
+ return await new ActionInteraction(this._invocationManager, this._matcher, action, traceDescription).execute();
60
58
  }
61
59
 
62
60
  async tapBackspaceKey() {
63
61
  const action = new actions.PressKeyAction(67);
64
62
  const traceDescription = actionDescription.tapBackspaceKey();
65
- return await new ActionInteraction(this._invocationManager, this, action, traceDescription).execute();
63
+ return await new ActionInteraction(this._invocationManager, this._matcher, action, traceDescription).execute();
66
64
  }
67
65
 
68
66
  async tapReturnKey() {
69
67
  const action = new actions.TypeTextAction('\n');
70
68
  const traceDescription = actionDescription.tapReturnKey();
71
- return await new ActionInteraction(this._invocationManager, this, action, traceDescription).execute();
69
+ return await new ActionInteraction(this._invocationManager, this._matcher, action, traceDescription).execute();
72
70
  }
73
71
 
74
72
  async typeText(value) {
75
73
  const action = new actions.TypeTextAction(value);
76
74
  const traceDescription = actionDescription.typeText(value);
77
- return await new ActionInteraction(this._invocationManager, this, action, traceDescription).execute();
75
+ return await new ActionInteraction(this._invocationManager, this._matcher, action, traceDescription).execute();
78
76
  }
79
77
 
80
78
  async replaceText(value) {
81
79
  const action = new actions.ReplaceTextAction(value);
82
80
  const traceDescription = actionDescription.replaceText(value);
83
- return await new ActionInteraction(this._invocationManager, this, action, traceDescription).execute();
81
+ return await new ActionInteraction(this._invocationManager, this._matcher, action, traceDescription).execute();
84
82
  }
85
83
 
86
84
  async clearText() {
87
85
  const action = new actions.ClearTextAction();
88
86
  const traceDescription = actionDescription.clearText();
89
- return await new ActionInteraction(this._invocationManager, this, action, traceDescription).execute();
87
+ return await new ActionInteraction(this._invocationManager, this._matcher, action, traceDescription).execute();
90
88
  }
91
89
 
92
90
  async scroll(amount, direction = 'down', startPositionX, startPositionY) {
93
91
  const action = new actions.ScrollAmountAction(direction, amount, startPositionX, startPositionY);
94
92
  const traceDescription = actionDescription.scroll(amount, direction, startPositionX, startPositionY);
95
- return await new ActionInteraction(this._invocationManager, this, action, traceDescription).execute();
93
+ return await new ActionInteraction(this._invocationManager, this._matcher, action, traceDescription).execute();
96
94
  }
97
95
 
98
96
  async scrollTo(edge) {
99
97
  // override the user's element selection with an extended matcher that looks for UIScrollView children
100
- this._selectElementWithMatcher(this._originalMatcher._extendToDescendantScrollViews());
98
+ this._matcher = this._matcher._extendToDescendantScrollViews();
101
99
 
102
100
  const action = new actions.ScrollEdgeAction(edge);
103
101
  const traceDescription = actionDescription.scrollTo(edge);
104
- return await new ActionInteraction(this._invocationManager, this, action, traceDescription).execute();
102
+ return await new ActionInteraction(this._invocationManager, this._matcher, action, traceDescription).execute();
105
103
  }
106
104
 
107
105
  async scrollToIndex(index) {
108
106
  // override the user's element selection with an extended matcher that looks for UIScrollView children
109
- this._selectElementWithMatcher(this._originalMatcher._extendToDescendantScrollViews());
107
+ this._matcher = this._matcher._extendToDescendantScrollViews();
110
108
 
111
109
  const action = new actions.ScrollToIndex(index);
112
110
  const traceDescription = actionDescription.scrollToIndex(index);
113
- return await new ActionInteraction(this._invocationManager, this, action, traceDescription).execute();
111
+ return await new ActionInteraction(this._invocationManager, this._matcher, action, traceDescription).execute();
114
112
  }
115
113
 
116
114
  async setDatePickerDate(rawDateString, formatString) {
@@ -120,7 +118,7 @@ class NativeElement {
120
118
 
121
119
  const action = new actions.SetDatePickerDateAction(dateString, formatString);
122
120
  const traceDescription = actionDescription.setDatePickerDate(dateString, formatString);
123
- return await new ActionInteraction(this._invocationManager, this, action, traceDescription).execute();
121
+ return await new ActionInteraction(this._invocationManager, this._matcher, action, traceDescription).execute();
124
122
  }
125
123
 
126
124
  /**
@@ -134,18 +132,18 @@ class NativeElement {
134
132
  normalizedSwipeOffset = Number.isNaN(normalizedSwipeOffset) ? 0.75 : normalizedSwipeOffset;
135
133
 
136
134
  // override the user's element selection with an extended matcher that avoids RN issues with RCTScrollView
137
- this._selectElementWithMatcher(this._originalMatcher._avoidProblematicReactNativeElements());
135
+ this._matcher = this._matcher._avoidProblematicReactNativeElements();
138
136
 
139
137
  const action = new actions.SwipeAction(direction, speed, normalizedSwipeOffset, normalizedStartingPointX, normalizedStartingPointY);
140
138
  const traceDescription = actionDescription.swipe(direction, speed, normalizedSwipeOffset, normalizedStartingPointX, normalizedStartingPointY);
141
- return await new ActionInteraction(this._invocationManager, this, action, traceDescription).execute();
139
+ return await new ActionInteraction(this._invocationManager, this._matcher, action, traceDescription).execute();
142
140
  }
143
141
 
144
142
  async takeScreenshot(screenshotName) {
145
143
  // TODO this should be moved to a lower-layer handler of this use-case
146
144
  const action = new actions.TakeElementScreenshot();
147
145
  const traceDescription = actionDescription.takeScreenshot(screenshotName);
148
- const resultBase64 = await new ActionInteraction(this._invocationManager, this, action, traceDescription).execute();
146
+ const resultBase64 = await new ActionInteraction(this._invocationManager, this._matcher, action, traceDescription).execute();
149
147
  const filePath = tempfile('detox.element-screenshot.png');
150
148
  await fs.writeFile(filePath, resultBase64, 'base64');
151
149
 
@@ -160,19 +158,18 @@ class NativeElement {
160
158
  async getAttributes() {
161
159
  const action = new actions.GetAttributes();
162
160
  const traceDescription = actionDescription.getAttributes();
163
- const result = await new ActionInteraction(this._invocationManager, this, action, traceDescription).execute();
164
- return JSON.parse(result);
161
+ return await new ActionInteraction(this._invocationManager, this._matcher, action, traceDescription).execute();
165
162
  }
166
163
 
167
164
  async adjustSliderToPosition(newPosition) {
168
165
  const action = new actions.AdjustSliderToPosition(newPosition);
169
166
  const traceDescription = actionDescription.adjustSliderToPosition(newPosition);
170
- return await new ActionInteraction(this._invocationManager, this, action, traceDescription).execute();
167
+ return await new ActionInteraction(this._invocationManager, this._matcher, action, traceDescription).execute();
171
168
  }
172
169
 
173
170
  async performAccessibilityAction(actionName) {
174
171
  const traceDescription = actionDescription.performAccessibilityAction(actionName);
175
- return await new ActionInteraction(this._invocationManager, this, new actions.AccessibilityActionAction(actionName), traceDescription).execute();
172
+ return await new ActionInteraction(this._invocationManager, this._matcher, new actions.AccessibilityActionAction(actionName), traceDescription).execute();
176
173
  }
177
174
  }
178
175
 
@@ -1,5 +1,7 @@
1
1
  const DetoxRuntimeError = require('../../errors/DetoxRuntimeError');
2
2
  const invoke = require('../../invoke');
3
+ const assertIsFunction = require('../../utils/assertIsFunction');
4
+ const isArrowFunction = require('../../utils/isArrowFunction');
3
5
  const actions = require('../actions/web');
4
6
  const EspressoWebDetoxApi = require('../espressoapi/web/EspressoWebDetox');
5
7
  const WebViewElementApi = require('../espressoapi/web/WebViewElement');
@@ -73,12 +75,14 @@ class WebElement {
73
75
  return await new ActionInteraction(this[_invocationManager], new actions.WebMoveCursorEnd(this)).execute();
74
76
  }
75
77
 
76
- async runScript(script) {
77
- return await new ActionInteraction(this[_invocationManager], new actions.WebRunScriptAction(this, script)).execute();
78
- }
78
+ async runScript(maybeFunction, args) {
79
+ const script = stringifyScript(maybeFunction);
79
80
 
80
- async runScriptWithArgs(script, args) {
81
- return await new ActionInteraction(this[_invocationManager], new actions.WebRunScriptWithArgsAction(this, script, args)).execute();
81
+ if (args) {
82
+ return await new ActionInteraction(this[_invocationManager], new actions.WebRunScriptWithArgsAction(this, script, args)).execute();
83
+ } else {
84
+ return await new ActionInteraction(this[_invocationManager], new actions.WebRunScriptAction(this, script)).execute();
85
+ }
82
86
  }
83
87
 
84
88
  async getCurrentUrl() {
@@ -116,10 +120,24 @@ class WebViewElement {
116
120
  });
117
121
  }
118
122
 
119
- throw new DetoxRuntimeError(`element() argument is invalid, expected a web matcher, but got ${typeof element}`);
123
+ throw new DetoxRuntimeError(`element() argument is invalid, expected a web matcher, but got ${typeof webMatcher}`);
120
124
  }
121
125
  }
122
126
 
127
+ function stringifyScript(maybeFunction) {
128
+ if (typeof maybeFunction !== 'string' && typeof maybeFunction !== 'function') {
129
+ return maybeFunction;
130
+ }
131
+
132
+ const script = (typeof maybeFunction === 'function' ? maybeFunction.toString() : assertIsFunction(maybeFunction)).trim();
133
+ // WebElement interactions don't support arrow functions for some reason.
134
+ if (isArrowFunction(script)) {
135
+ return `function arrowWorkaround() { return (${script}).apply(this, arguments); }`;
136
+ }
137
+
138
+ return script;
139
+ }
140
+
123
141
  module.exports = {
124
142
  WebElement,
125
143
  WebViewElement,
@@ -14,7 +14,7 @@ function sanitize_matcher(matcher) {
14
14
  return originalMatcher.type ? originalMatcher.value : originalMatcher;
15
15
  }
16
16
  class DetoxAssertion {
17
- static assertMatcher(i, m) {
17
+ static assertMatcher(viewInteraction, viewMatcher) {
18
18
  return {
19
19
  target: {
20
20
  type: "Class",
@@ -23,15 +23,15 @@ class DetoxAssertion {
23
23
  method: "assertMatcher",
24
24
  args: [{
25
25
  type: "Invocation",
26
- value: i
26
+ value: viewInteraction
27
27
  }, {
28
28
  type: "Invocation",
29
- value: sanitize_matcher(m)
29
+ value: sanitize_matcher(viewMatcher)
30
30
  }]
31
31
  };
32
32
  }
33
33
 
34
- static assertNotVisible(i) {
34
+ static assertNotVisible(viewInteraction) {
35
35
  return {
36
36
  target: {
37
37
  type: "Class",
@@ -40,12 +40,12 @@ class DetoxAssertion {
40
40
  method: "assertNotVisible",
41
41
  args: [{
42
42
  type: "Invocation",
43
- value: i
43
+ value: viewInteraction
44
44
  }]
45
45
  };
46
46
  }
47
47
 
48
- static assertNotExists(i) {
48
+ static assertNotExists(viewInteraction) {
49
49
  return {
50
50
  target: {
51
51
  type: "Class",
@@ -54,12 +54,12 @@ class DetoxAssertion {
54
54
  method: "assertNotExists",
55
55
  args: [{
56
56
  type: "Invocation",
57
- value: i
57
+ value: viewInteraction
58
58
  }]
59
59
  };
60
60
  }
61
61
 
62
- static waitForAssertMatcher(i, m, timeoutSeconds) {
62
+ static waitForAssertMatcher(viewInteraction, viewMatcher, timeoutSeconds) {
63
63
  if (typeof timeoutSeconds !== "number") throw new Error("timeoutSeconds should be a number, but got " + (timeoutSeconds + (" (" + (typeof timeoutSeconds + ")"))));
64
64
  return {
65
65
  target: {
@@ -69,10 +69,10 @@ class DetoxAssertion {
69
69
  method: "waitForAssertMatcher",
70
70
  args: [{
71
71
  type: "Invocation",
72
- value: i
72
+ value: viewInteraction
73
73
  }, {
74
74
  type: "Invocation",
75
- value: sanitize_matcher(m)
75
+ value: sanitize_matcher(viewMatcher)
76
76
  }, {
77
77
  type: "Double",
78
78
  value: timeoutSeconds
@@ -80,7 +80,8 @@ class DetoxAssertion {
80
80
  };
81
81
  }
82
82
 
83
- static waitForAssertMatcherWithSearchAction(i, vm, searchAction, searchMatcher) {
83
+ static waitForAssertMatcherWithSearchAction(viewInteraction, viewMatcher, searchAction, searchMatcher
84
+ ) {
84
85
  return {
85
86
  target: {
86
87
  type: "Class",
@@ -89,13 +90,14 @@ class DetoxAssertion {
89
90
  method: "waitForAssertMatcherWithSearchAction",
90
91
  args: [{
91
92
  type: "Invocation",
92
- value: i
93
+ value: viewInteraction
93
94
  }, {
94
95
  type: "Invocation",
95
- value: sanitize_matcher(vm)
96
+ value: sanitize_matcher(viewMatcher)
96
97
  }, searchAction, {
97
98
  type: "Invocation",
98
- value: sanitize_matcher(searchMatcher)
99
+ value: sanitize_matcher(searchMatcher
100
+ )
99
101
  }]
100
102
  };
101
103
  }
@@ -14,39 +14,51 @@ function sanitize_matcher(matcher) {
14
14
  return originalMatcher.type ? originalMatcher.value : originalMatcher;
15
15
  }
16
16
  class DetoxMatcher {
17
- static matcherForText(text) {
17
+ static matcherForText(text, isRegex) {
18
18
  if (typeof text !== "string") throw new Error("text should be a string, but got " + (text + (" (" + (typeof text + ")"))));
19
+ if (typeof isRegex !== "boolean") throw new Error("isRegex should be a boolean, but got " + (isRegex + (" (" + (typeof isRegex + ")"))));
19
20
  return {
20
21
  target: {
21
22
  type: "Class",
22
23
  value: "com.wix.detox.espresso.DetoxMatcher"
23
24
  },
24
25
  method: "matcherForText",
25
- args: [text]
26
+ args: [text, {
27
+ type: "boolean",
28
+ value: isRegex
29
+ }]
26
30
  };
27
31
  }
28
32
 
29
- static matcherForAccessibilityLabel(label) {
33
+ static matcherForAccessibilityLabel(label, isRegex) {
30
34
  if (typeof label !== "string") throw new Error("label should be a string, but got " + (label + (" (" + (typeof label + ")"))));
35
+ if (typeof isRegex !== "boolean") throw new Error("isRegex should be a boolean, but got " + (isRegex + (" (" + (typeof isRegex + ")"))));
31
36
  return {
32
37
  target: {
33
38
  type: "Class",
34
39
  value: "com.wix.detox.espresso.DetoxMatcher"
35
40
  },
36
41
  method: "matcherForAccessibilityLabel",
37
- args: [label]
42
+ args: [label, {
43
+ type: "boolean",
44
+ value: isRegex
45
+ }]
38
46
  };
39
47
  }
40
48
 
41
- static matcherForShallowAccessibilityLabel(label) {
49
+ static matcherForShallowAccessibilityLabel(label, isRegex) {
42
50
  if (typeof label !== "string") throw new Error("label should be a string, but got " + (label + (" (" + (typeof label + ")"))));
51
+ if (typeof isRegex !== "boolean") throw new Error("isRegex should be a boolean, but got " + (isRegex + (" (" + (typeof isRegex + ")"))));
43
52
  return {
44
53
  target: {
45
54
  type: "Class",
46
55
  value: "com.wix.detox.espresso.DetoxMatcher"
47
56
  },
48
57
  method: "matcherForShallowAccessibilityLabel",
49
- args: [label]
58
+ args: [label, {
59
+ type: "boolean",
60
+ value: isRegex
61
+ }]
50
62
  };
51
63
  }
52
64
 
@@ -62,15 +74,19 @@ class DetoxMatcher {
62
74
  };
63
75
  }
64
76
 
65
- static matcherForTestId(testId) {
77
+ static matcherForTestId(testId, isRegex) {
66
78
  if (typeof testId !== "string") throw new Error("testId should be a string, but got " + (testId + (" (" + (typeof testId + ")"))));
79
+ if (typeof isRegex !== "boolean") throw new Error("isRegex should be a boolean, but got " + (isRegex + (" (" + (typeof isRegex + ")"))));
67
80
  return {
68
81
  target: {
69
82
  type: "Class",
70
83
  value: "com.wix.detox.espresso.DetoxMatcher"
71
84
  },
72
85
  method: "matcherForTestId",
73
- args: [testId]
86
+ args: [testId, {
87
+ type: "boolean",
88
+ value: isRegex
89
+ }]
74
90
  };
75
91
  }
76
92
 
@@ -5,9 +5,16 @@
5
5
  */
6
6
 
7
7
 
8
+ function sanitize_matcher(matcher) {
9
+ if (!matcher._call) {
10
+ return matcher;
11
+ }
8
12
 
13
+ const originalMatcher = typeof matcher._call === 'function' ? matcher._call() : matcher._call;
14
+ return originalMatcher.type ? originalMatcher.value : originalMatcher;
15
+ }
9
16
  class EspressoDetox {
10
- static perform(interaction, action) {
17
+ static perform(matcher, action) {
11
18
  return {
12
19
  target: {
13
20
  type: "Class",
@@ -16,7 +23,7 @@ class EspressoDetox {
16
23
  method: "perform",
17
24
  args: [{
18
25
  type: "Invocation",
19
- value: interaction
26
+ value: sanitize_matcher(matcher)
20
27
  }, action]
21
28
  };
22
29
  }
@@ -76,10 +76,7 @@ class WebElement {
76
76
  return {
77
77
  target: element,
78
78
  method: "runScriptWithArgs",
79
- args: [script, {
80
- type: "ArrayList<Object>",
81
- value: args
82
- }]
79
+ args: [script, args]
83
80
  };
84
81
  }
85
82
 
@@ -25,9 +25,9 @@ class Interaction {
25
25
  }
26
26
 
27
27
  class ActionInteraction extends Interaction {
28
- constructor(invocationManager, element, action, traceDescription) {
28
+ constructor(invocationManager, matcher, action, traceDescription) {
29
29
  super(invocationManager, traceDescription);
30
- this._call = EspressoDetoxApi.perform(call(element._call), action._call);
30
+ this._call = EspressoDetoxApi.perform(matcher, action._call);
31
31
  // TODO: move this.execute() here from the caller
32
32
  }
33
33
  }
@@ -48,7 +48,6 @@ class WaitForInteraction extends Interaction {
48
48
  super(invocationManager, expectTraceDescription);
49
49
  this._element = element;
50
50
  this._assertionMatcher = assertionMatcher;
51
- this._element._selectElementWithMatcher(this._element._originalMatcher);
52
51
  }
53
52
 
54
53
  async withTimeout(timeout) {
@@ -10,6 +10,7 @@ module.exports = {
10
10
  type: (value) => new native.TypeMatcher(value),
11
11
  value: (value) => new native.ValueMatcher(value),
12
12
 
13
+ // label, type and value not supported
13
14
  web: {
14
15
  id: (value) => new web.IdMatcher(value),
15
16
  className: (value) => new web.ClassNameMatcher(value),
@@ -19,5 +20,8 @@ module.exports = {
19
20
  xpath: (value) => new web.XPathMatcher(value),
20
21
  href: (value) => new web.LinkTextMatcher(value),
21
22
  hrefContains: (value) => new web.PartialLinkTextMatcher(value),
23
+ label: (value) => new web.LabelMatcher(value),
24
+ value: (value) => new web.ValueMatcher(value),
25
+ accessibilityType: (value) => new web.AccessibilityTypeMatcher(value),
22
26
  },
23
27
  };
@@ -1,26 +1,30 @@
1
1
  const DetoxRuntimeError = require('../../errors/DetoxRuntimeError');
2
2
  const invoke = require('../../invoke');
3
+ const { isRegExp } = require('../../utils/isRegExp');
3
4
  const { NativeMatcher } = require('../core/NativeMatcher');
4
5
  const DetoxMatcherApi = require('../espressoapi/DetoxMatcher');
5
6
 
6
7
  class LabelMatcher extends NativeMatcher {
7
8
  constructor(value) {
8
9
  super();
9
- this._call = invoke.callDirectly(DetoxMatcherApi.matcherForAccessibilityLabel(value));
10
+ const isRegex = isRegExp(value);
11
+ this._call = invoke.callDirectly(DetoxMatcherApi.matcherForAccessibilityLabel(isRegex ? value.toString() : value, isRegex));
10
12
  }
11
13
  }
12
14
 
13
15
  class ShallowLabelMatcher extends NativeMatcher {
14
16
  constructor(value) {
15
17
  super();
16
- this._call = invoke.callDirectly(DetoxMatcherApi.matcherForShallowAccessibilityLabel(value));
18
+ const isRegex = isRegExp(value);
19
+ this._call = invoke.callDirectly(DetoxMatcherApi.matcherForShallowAccessibilityLabel(isRegex ? value.toString() : value, isRegex));
17
20
  }
18
21
  }
19
22
 
20
23
  class IdMatcher extends NativeMatcher {
21
24
  constructor(value) {
22
25
  super();
23
- this._call = invoke.callDirectly(DetoxMatcherApi.matcherForTestId(value));
26
+ const isRegex = isRegExp(value);
27
+ this._call = invoke.callDirectly(DetoxMatcherApi.matcherForTestId(isRegex ? value.toString() : value, isRegex));
24
28
  }
25
29
  }
26
30
 
@@ -53,7 +57,8 @@ class ExistsMatcher extends NativeMatcher {
53
57
  class TextMatcher extends NativeMatcher {
54
58
  constructor(value) {
55
59
  super();
56
- this._call = invoke.callDirectly(DetoxMatcherApi.matcherForText(value));
60
+ const isRegex = isRegExp(value);
61
+ this._call = invoke.callDirectly(DetoxMatcherApi.matcherForText(isRegex ? value.toString() : value, isRegex));
57
62
  }
58
63
  }
59
64
 
@@ -1,6 +1,7 @@
1
1
  const invoke = require('../../invoke');
2
2
  const { WebMatcher } = require('../core/WebMatcher');
3
3
  const DetoxWebMatcherApi = require('../espressoapi/web/DetoxWebAtomMatcher');
4
+ const DetoxRuntimeError = require('../../errors/DetoxRuntimeError');
4
5
 
5
6
  class IdMatcher extends WebMatcher {
6
7
  constructor(id) {
@@ -51,6 +52,27 @@ class PartialLinkTextMatcher extends WebMatcher {
51
52
  }
52
53
  }
53
54
 
55
+ class LabelMatcher extends WebMatcher {
56
+ constructor(_) {
57
+ super();
58
+ throw new DetoxRuntimeError('Label matching is not supported on Android');
59
+ }
60
+ }
61
+
62
+ class ValueMatcher extends WebMatcher {
63
+ constructor(_) {
64
+ super();
65
+ throw new DetoxRuntimeError('Label matching is not supported on Android');
66
+ }
67
+ }
68
+
69
+ class AccessibilityTypeMatcher extends WebMatcher {
70
+ constructor(_) {
71
+ super();
72
+ throw new DetoxRuntimeError('Accessibility-type matching is not supported on Android');
73
+ }
74
+ }
75
+
54
76
  class TagNameMatcher extends WebMatcher {
55
77
  constructor(tag) {
56
78
  super();
@@ -66,5 +88,8 @@ module.exports = {
66
88
  XPathMatcher,
67
89
  LinkTextMatcher,
68
90
  PartialLinkTextMatcher,
69
- TagNameMatcher
91
+ TagNameMatcher,
92
+ LabelMatcher,
93
+ ValueMatcher,
94
+ AccessibilityTypeMatcher,
70
95
  };