detox 21.0.0-rc.1 → 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.1/detox-21.0.0-rc.1-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.1/detox-21.0.0-rc.1-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.1/detox-21.0.0-rc.1.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 +5 -4
  125. package/src/devices/runtime/drivers/ios/XCUITestUtils.js +21 -11
  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.1/detox-21.0.0-rc.1-javadoc.jar.md5 +0 -1
  157. package/Detox-android/com/wix/detox/21.0.0-rc.1/detox-21.0.0-rc.1-javadoc.jar.sha1 +0 -1
  158. package/Detox-android/com/wix/detox/21.0.0-rc.1/detox-21.0.0-rc.1-javadoc.jar.sha256 +0 -1
  159. package/Detox-android/com/wix/detox/21.0.0-rc.1/detox-21.0.0-rc.1-javadoc.jar.sha512 +0 -1
  160. package/Detox-android/com/wix/detox/21.0.0-rc.1/detox-21.0.0-rc.1-sources.jar.md5 +0 -1
  161. package/Detox-android/com/wix/detox/21.0.0-rc.1/detox-21.0.0-rc.1-sources.jar.sha1 +0 -1
  162. package/Detox-android/com/wix/detox/21.0.0-rc.1/detox-21.0.0-rc.1-sources.jar.sha256 +0 -1
  163. package/Detox-android/com/wix/detox/21.0.0-rc.1/detox-21.0.0-rc.1-sources.jar.sha512 +0 -1
  164. package/Detox-android/com/wix/detox/21.0.0-rc.1/detox-21.0.0-rc.1.aar +0 -0
  165. package/Detox-android/com/wix/detox/21.0.0-rc.1/detox-21.0.0-rc.1.aar.md5 +0 -1
  166. package/Detox-android/com/wix/detox/21.0.0-rc.1/detox-21.0.0-rc.1.aar.sha1 +0 -1
  167. package/Detox-android/com/wix/detox/21.0.0-rc.1/detox-21.0.0-rc.1.aar.sha256 +0 -1
  168. package/Detox-android/com/wix/detox/21.0.0-rc.1/detox-21.0.0-rc.1.aar.sha512 +0 -1
  169. package/Detox-android/com/wix/detox/21.0.0-rc.1/detox-21.0.0-rc.1.pom.md5 +0 -1
  170. package/Detox-android/com/wix/detox/21.0.0-rc.1/detox-21.0.0-rc.1.pom.sha1 +0 -1
  171. package/Detox-android/com/wix/detox/21.0.0-rc.1/detox-21.0.0-rc.1.pom.sha256 +0 -1
  172. package/Detox-android/com/wix/detox/21.0.0-rc.1/detox-21.0.0-rc.1.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
@@ -0,0 +1,11 @@
1
+ /* eslint-disable import/no-unresolved,node/no-missing-import,node/no-unsupported-features/es-syntax */
2
+ import GenyInstance from '../../../allocation/drivers/android/genycloud/services/dto/GenyInstance';
3
+ import { DeviceCookie } from '../DeviceCookie';
4
+
5
+ interface AndroidDeviceCookie extends DeviceCookie {
6
+ adbName: string;
7
+ }
8
+
9
+ interface GenycloudEmulatorCookie extends AndroidDeviceCookie {
10
+ instance: GenyInstance;
11
+ }
@@ -32,19 +32,31 @@ class QueryVersionCommand extends ExecCommand {
32
32
  }
33
33
 
34
34
  class LaunchCommand extends ExecCommand {
35
- constructor(emulatorName, options) {
35
+ constructor(options) {
36
36
  super();
37
37
  this._options = options;
38
- this._args = this._getEmulatorArgs(emulatorName);
39
- this.port = options.port;
38
+ this._args = this._getEmulatorArgs();
39
+ }
40
+
41
+ get adbName() {
42
+ return this._options.adbName;
43
+ }
44
+
45
+ get avdName() {
46
+ return this._options.avdName;
47
+ }
48
+
49
+ get port() {
50
+ return this._options.port;
40
51
  }
41
52
 
42
53
  _getArgs() {
43
54
  return this._args;
44
55
  }
45
56
 
46
- _getEmulatorArgs(emulatorName) {
57
+ _getEmulatorArgs() {
47
58
  const {
59
+ avdName,
48
60
  bootArgs,
49
61
  gpuMode = this._getDefaultGPUMode(),
50
62
  headless,
@@ -64,7 +76,7 @@ class LaunchCommand extends ExecCommand {
64
76
  port ? '-port' : '',
65
77
  port ? `${port}` : '',
66
78
  ...deviceBootArgs,
67
- `@${emulatorName}`
79
+ `@${avdName}`
68
80
  ]);
69
81
 
70
82
  return emulatorArgs;
@@ -18,6 +18,7 @@ class ADB {
18
18
 
19
19
  async devices() {
20
20
  const { stdout } = await this.adbCmd('', 'devices', { verbosity: 'high' });
21
+ /** @type {DeviceHandle[]} */
21
22
  const devices = _.chain(stdout)
22
23
  .trim()
23
24
  .split('\n')
@@ -1,6 +1,7 @@
1
1
  const _ = require('lodash');
2
2
 
3
3
  const { encodeBase64 } = require('../../../../../utils/encoding');
4
+ const { autoEscape } = require('../../../../../utils/shellUtils');
4
5
 
5
6
  const reservedInstrumentationArgs = new Set(['class', 'package', 'func', 'unit', 'size', 'perf', 'debug', 'log', 'emma', 'coverageFile']);
6
7
  const isReservedInstrumentationArg = (arg) => reservedInstrumentationArgs.has(arg);
@@ -17,7 +18,8 @@ function prepareInstrumentationArgs(args) {
17
18
  valueEncoded = encodeBase64(valueAsString);
18
19
  }
19
20
 
20
- result.push('-e', key, valueEncoded);
21
+ const valueEscaped = hasLegacyIssues(key) ? valueEncoded : autoEscape.shell(valueEncoded);
22
+ result.push('-e', key, valueEscaped);
21
23
  return result;
22
24
  }, []);
23
25
 
@@ -27,6 +29,10 @@ function prepareInstrumentationArgs(args) {
27
29
  };
28
30
  }
29
31
 
32
+ function hasLegacyIssues(key) {
33
+ return key === 'detoxURLBlacklistRegex';
34
+ }
35
+
30
36
  module.exports = {
31
37
  prepareInstrumentationArgs,
32
38
  };
@@ -0,0 +1,9 @@
1
+ /* eslint-disable import/no-unresolved,node/no-missing-import,node/no-unsupported-features/es-syntax */
2
+ import { DeviceCookie } from '../DeviceCookie';
3
+
4
+ interface IosSimulatorCookie extends DeviceCookie {
5
+ udid: string;
6
+ type?: string;
7
+ bootArgs?: string;
8
+ headless?: boolean;
9
+ }
@@ -288,7 +288,7 @@ class AppleSimUtils {
288
288
  // want to make sure it isn't now.
289
289
  if (err.code === 3 &&
290
290
  (err.stderr.includes(`the app is not currently running`) ||
291
- err.stderr.includes(`The operation couldn’t be completed. found nothing to terminate`))) {
291
+ err.stderr.includes(`found nothing to terminate`))) {
292
292
  return;
293
293
  }
294
294
 
@@ -446,6 +446,8 @@ class AppleSimUtils {
446
446
  overrides.push(`--cellularMode "${flags.cellularMode}"`);
447
447
  if (flags.cellularBars)
448
448
  overrides.push(`--cellularBars "${flags.cellularBars}"`);
449
+ if (flags.operatorName)
450
+ overrides.push(`--operatorName "${flags.operatorName}"`);
449
451
  if (flags.batteryState)
450
452
  overrides.push(`--batteryState "${flags.batteryState}"`);
451
453
  if (flags.batteryLevel)
@@ -1,6 +0,0 @@
1
- module.exports = {
2
- IosSimulatorCookie: require('./IosSimulatorCookie'),
3
- AttachedAndroidDeviceCookie: require('./AttachedAndroidDeviceCookie'),
4
- AndroidEmulatorCookie: require('./AndroidEmulatorCookie'),
5
- GenycloudEmulatorCookie: require('./GenycloudEmulatorCookie'),
6
- };
@@ -8,21 +8,22 @@ const AndroidDriver = require('../AndroidDriver');
8
8
 
9
9
  /**
10
10
  * @typedef GenycloudDriverProps
11
- * @property instance { GenyInstance } The DTO associated with the cloud instance
11
+ * @property adbName { GenyInstance } The DTO associated with the cloud instance
12
12
  */
13
13
 
14
14
  class GenyCloudDriver extends AndroidDriver {
15
15
  /**
16
16
  * @param deps { GenycloudDriverDeps }
17
- * @param props { GenycloudDriverProps }
17
+ * @param props { GenycloudEmulatorCookie }
18
18
  */
19
- constructor(deps, { instance }) {
20
- super(deps, { adbName: instance.adbName });
21
- this.instance = instance;
19
+ constructor(deps, { adbName, name }) {
20
+ super(deps, { adbName });
21
+
22
+ this._instanceName = name;
22
23
  }
23
24
 
24
25
  getDeviceName() {
25
- return this.instance.toString();
26
+ return this._instanceName;
26
27
  }
27
28
 
28
29
  async setLocation(lat, lon) {
@@ -17,7 +17,6 @@ const { launchXCUITest } = require('./XCUITestUtils');
17
17
 
18
18
  /**
19
19
  * @typedef SimulatorDriverDeps { DeviceDriverDeps }
20
- * @property simulatorLauncher { SimulatorLauncher }
21
20
  * @property applesimutils { AppleSimUtils }
22
21
  */
23
22
 
@@ -41,7 +40,6 @@ class SimulatorDriver extends IosDriver {
41
40
  this._bootArgs = bootArgs;
42
41
  this._headless = headless;
43
42
  this._deviceName = `${udid} (${this._type})`;
44
- this._simulatorLauncher = deps.simulatorLauncher;
45
43
  this._applesimutils = deps.applesimutils;
46
44
  // TODO: allocate unique-per-worker available port.
47
45
  this._testTargetServerPort = 8997 + _.random(0, 1000);
@@ -190,9 +188,12 @@ class SimulatorDriver extends IosDriver {
190
188
  }
191
189
 
192
190
  async resetContentAndSettings() {
193
- await this._simulatorLauncher.shutdown(this.udid);
191
+ await this.emitter.emit('beforeShutdownDevice', { deviceId: this.udid });
192
+ await this._applesimutils.shutdown(this.udid);
193
+ await this.emitter.emit('shutdownDevice', { deviceId: this.udid });
194
194
  await this._applesimutils.resetContentAndSettings(this.udid);
195
- await this._simulatorLauncher.launch(this.udid, this._type, this._bootArgs, this._headless);
195
+ await this._applesimutils.boot(this.udid, this._bootArgs, this._headless);
196
+ await this.emitter.emit('bootDevice', { deviceId: this.udid });
196
197
  }
197
198
 
198
199
  getLogsPaths() {
@@ -1,7 +1,6 @@
1
1
  const { exec } = require('child-process-promise');
2
2
  const osascript = require('node-osascript');
3
3
 
4
- const { execWithRetriesAndLogs } = require('../../../../utils/childProcess');
5
4
  const log = require('../../../../utils/logger').child({ cat: 'device,xcuitest' });
6
5
 
7
6
  async function launchXCUITest(
@@ -56,7 +55,7 @@ async function _runLaunchCommand(
56
55
  ).then(r => {
57
56
  log.info(`[XCUITest] XCUITest runner execution finished`);
58
57
  }).catch(e => {
59
- log.error(`[XCUITest] xcodebuild error has occurred during XCUITest execution:\n${e}`);
58
+ log.debug(`[XCUITest] XCUITest runner execution finished with message:\n${e}`);
60
59
  });
61
60
 
62
61
  // Get firewall global state (Firewall socketfilterfw):
@@ -67,7 +66,12 @@ async function _runLaunchCommand(
67
66
  }
68
67
 
69
68
  const isServerUp = await _waitForTestTargetServerToStart(testTargetServerPort, spawnedProcess);
70
- log.debug(`[XCUITest] Finished waiting for test target server to start, server is up: ${isServerUp}`);
69
+ if (!isServerUp) {
70
+ throw new Error(`[XCUITest] Test runner is not up after 90 seconds, aborting`);
71
+ } else {
72
+ const childProcess = spawnedProcess.childProcess;
73
+ log.debug(`[XCUITest] Test runner is up and running, PID: ${childProcess.pid}`);
74
+ }
71
75
  }
72
76
 
73
77
  function runXCUITest(
@@ -101,9 +105,7 @@ function runXCUITest(
101
105
  };
102
106
 
103
107
  const options = {
104
- maxBuffer: 1024 * 1024 * 1024,
105
- retries: 1,
106
- verbosity: 'high',
108
+ maxBuffer: 1024 * 1024 * 10, // 10MB
107
109
  };
108
110
 
109
111
  const command = `${env.TEST_RUNNER_IS_DETOX_ACTIVE ? Object.keys(env).map(key => `${key}=${env[key]}`).join(' ') : ''} ${xcodebuildBinary} ${flags.map(flag => flag.includes(' ') ? `"${flag}"` : flag).join(' ')}`;
@@ -120,13 +122,21 @@ function runXCUITest(
120
122
  }
121
123
  }
122
124
 
123
- return execWithRetriesAndLogs(command, options);
125
+ const result = exec(command, options);
126
+
127
+ result.childProcess.stderr.on('data', (data) => {
128
+ if (data.includes('Testing started completed')) {
129
+ result.childProcess.kill('SIGTERM');
130
+ }
131
+ });
132
+
133
+ return result;
124
134
  }
125
135
 
126
136
  function _runCommandInTerminal(command, options) {
127
- const escapedCommand = command.replace(/"/g, '\\"'); // escape double quotes
137
+ const escapedCommand = command.replace(/"/g, '\\"');
128
138
 
129
- // opens the Terminal app and runs the command in a new window, then closes the window when the command is done running.
139
+ // Opens the Terminal app and runs the command in a new window, then closes the window when the command is done running.
130
140
  const appleScript = `
131
141
  tell application "Terminal"
132
142
  if not running then
@@ -146,7 +156,7 @@ function _runCommandInTerminal(command, options) {
146
156
  end tell
147
157
  `;
148
158
 
149
- return execWithRetriesAndLogs(`osascript -e '${appleScript}'`, options);
159
+ return exec(`osascript -e '${appleScript}'`, options);
150
160
  }
151
161
 
152
162
  function _allowNetworkPermissionsXCUITest() {
@@ -174,7 +184,7 @@ function _allowNetworkPermissionsXCUITest() {
174
184
  childProcess.stdin.pause();
175
185
  childProcess.kill('SIGTERM');
176
186
 
177
- }, 30000);
187
+ }, 30000).unref();
178
188
  }
179
189
 
180
190
  async function _waitForTestTargetServerToStart(testTargetServerPort, cpPromise) {
@@ -3,7 +3,7 @@ const RuntimeDeviceFactory = require('./base');
3
3
 
4
4
  class RuntimeDriverFactoryAndroid extends RuntimeDeviceFactory {
5
5
  _createDriverDependencies(commonDeps) {
6
- const serviceLocator = require('../../../servicelocator/android');
6
+ const serviceLocator = require('../../servicelocator/android');
7
7
  const adb = serviceLocator.adb;
8
8
  const aapt = serviceLocator.aapt;
9
9
  const apkValidator = serviceLocator.apkValidator;
@@ -43,23 +43,15 @@ class AndroidEmulator extends RuntimeDriverFactoryAndroid {
43
43
 
44
44
  class AndroidAttached extends RuntimeDriverFactoryAndroid {
45
45
  _createDriver(deviceCookie, deps, configs) {
46
- const props = {
47
- adbName: deviceCookie.adbName,
48
- };
49
-
50
46
  const { AttachedAndroidRuntimeDriver } = require('../drivers');
51
- return new AttachedAndroidRuntimeDriver(deps, props);
47
+ return new AttachedAndroidRuntimeDriver(deps, deviceCookie);
52
48
  }
53
49
  }
54
50
 
55
51
  class Genycloud extends RuntimeDriverFactoryAndroid {
56
52
  _createDriver(deviceCookie, deps, configs) {
57
- const props = {
58
- instance: deviceCookie.instance,
59
- };
60
-
61
53
  const { GenycloudRuntimeDriver } = require('../drivers');
62
- return new GenycloudRuntimeDriver(deps, props);
54
+ return new GenycloudRuntimeDriver(deps, deviceCookie);
63
55
  }
64
56
  }
65
57
 
@@ -2,15 +2,14 @@ const RuntimeDeviceFactory = require('./base');
2
2
 
3
3
  class RuntimeDriverFactoryIos extends RuntimeDeviceFactory {
4
4
  _createDriverDependencies(commonDeps) {
5
- const serviceLocator = require('../../../servicelocator/ios');
6
- const applesimutils = serviceLocator.appleSimUtils;
7
5
  const { eventEmitter } = commonDeps;
8
6
 
9
- const SimulatorLauncher = require('../../allocation/drivers/ios/SimulatorLauncher');
7
+ const AppleSimUtils = require('../../../devices/common/drivers/ios/tools/AppleSimUtils');
8
+ const applesimutils = new AppleSimUtils();
9
+
10
10
  return {
11
11
  ...commonDeps,
12
12
  applesimutils,
13
- simulatorLauncher: new SimulatorLauncher({ applesimutils, eventEmitter }),
14
13
  };
15
14
  }
16
15
  }
@@ -1,4 +1,4 @@
1
- const { EmulatorExec } = require('../../devices/common/drivers/android/emulator/exec/EmulatorExec');
1
+ const { EmulatorExec } = require('../../common/drivers/android/emulator/exec/EmulatorExec');
2
2
 
3
3
  class EmulatorServiceLocator {
4
4
  constructor() {
@@ -0,0 +1,17 @@
1
+ class GenycloudServiceLocator {
2
+ constructor() {
3
+ this._exec = null;
4
+ }
5
+
6
+ // Note: important to keep lazy because of implicit validations that are sensitive (inside environment, in particular).
7
+ get exec() {
8
+ if (!this._exec) {
9
+ const Exec = require('../../allocation/drivers/android/genycloud/exec/GenyCloudExec');
10
+ const environment = require('../../../utils/environment');
11
+ this._exec = new Exec(environment.getGmsaasPath());
12
+ }
13
+ return this._exec;
14
+ }
15
+ }
16
+
17
+ module.exports = new GenycloudServiceLocator();
@@ -0,0 +1,23 @@
1
+ const AndroidDevicePathBuilder = require('../../../artifacts/utils/AndroidDevicePathBuilder');
2
+ const AAPT = require('../../common/drivers/android/exec/AAPT');
3
+ const ADB = require('../../common/drivers/android/exec/ADB');
4
+ const ApkValidator = require('../../common/drivers/android/tools/ApkValidator');
5
+ const { TempFileTransfer } = require('../../common/drivers/android/tools/TempFileTransfer');
6
+
7
+ const AndroidServiceLocator = {
8
+ get emulator() {
9
+ return require('./emulatorServiceLocator');
10
+ },
11
+
12
+ get genycloud() {
13
+ return require('./genycloudServiceLocator');
14
+ },
15
+ };
16
+
17
+ AndroidServiceLocator.adb = new ADB();
18
+ AndroidServiceLocator.aapt = new AAPT();
19
+ AndroidServiceLocator.apkValidator = new ApkValidator(AndroidServiceLocator.aapt);
20
+ AndroidServiceLocator.fileTransfer = new TempFileTransfer(AndroidServiceLocator.adb);
21
+ AndroidServiceLocator.devicePathBuilder = new AndroidDevicePathBuilder();
22
+
23
+ module.exports = AndroidServiceLocator;
@@ -1,4 +1,5 @@
1
1
  class EnvironmentValidatorBase {
2
+ /* istanbul ignore next */
2
3
  validate() {}
3
4
  }
4
5
 
@@ -1,8 +1,8 @@
1
1
  // @ts-nocheck
2
2
  const semver = require('semver');
3
3
 
4
- const DetoxRuntimeError = require('../../errors/DetoxRuntimeError');
5
- const environment = require('../../utils/environment');
4
+ const { DetoxRuntimeError } = require('../../../errors');
5
+ const environment = require('../../../utils/environment');
6
6
  const EnvironmentValidatorBase = require('../EnvironmentValidatorBase');
7
7
 
8
8
  const MIN_GMSAAS_VERSION = '1.6.0';
@@ -7,7 +7,7 @@ class Genycloud extends EnvValidatorFactory {
7
7
  const serviceLocator = require('../../servicelocator/android');
8
8
  const exec = serviceLocator.genycloud.exec;
9
9
 
10
- const GenyAuthService = require('../../devices/common/drivers/android/genycloud/services/GenyAuthService');
10
+ const GenyAuthService = require('../../allocation/drivers/android/genycloud/services/GenyAuthService');
11
11
  const authService = new GenyAuthService(exec);
12
12
 
13
13
  const GenycloudEnvValidator = require('../android/GenycloudEnvValidator');
@@ -1,7 +1,7 @@
1
1
  const fs = require('fs');
2
2
 
3
- const DetoxRuntimeError = require('../../errors/DetoxRuntimeError');
4
- const environment = require('../../utils/environment');
3
+ const DetoxRuntimeError = require('../../../errors/DetoxRuntimeError');
4
+ const environment = require('../../../utils/environment');
5
5
  const EnvironmentValidatorBase = require('../EnvironmentValidatorBase');
6
6
 
7
7
  class IosSimulatorEnvValidator extends EnvironmentValidatorBase {
@@ -2,9 +2,9 @@
2
2
  const artifactsManagerFactories = require('./artifacts/factories');
3
3
  const deviceAllocationFactories = require('./devices/allocation/factories');
4
4
  const runtimeDeviceFactories = require('./devices/runtime/factories');
5
+ const envValidationFactories = require('./devices/validation/factories');
5
6
  const matchersFactories = require('./matchers/factories');
6
7
  const resolveModuleFromPath = require('./utils/resolveModuleFromPath');
7
- const envValidationFactories = require('./validation/factories');
8
8
 
9
9
  function validateConfig(deviceConfig) {
10
10
  const classes = _getFactoryClasses(deviceConfig);
@@ -36,15 +36,6 @@ function createFactories(deviceConfig) {
36
36
  return _getExternalModuleFactories(deviceConfig);
37
37
  }
38
38
 
39
- function createGlobalLifecycleHandler(deviceConfig) {
40
- if (deviceConfig.type === 'android.genycloud') {
41
- const FactoryClass = require('./devices/lifecycle/factories/GenyGlobalLifecycleHandlerFactory');
42
- const factory = new FactoryClass();
43
- return factory.createHandler();
44
- }
45
- return null;
46
- }
47
-
48
39
  function _getFactoryClasses(deviceConfig) {
49
40
  let envValidatorFactoryClass;
50
41
  let artifactsManagerFactoryClass;
@@ -115,5 +106,4 @@ function _getExternalModuleFactories(deviceConfig) {
115
106
  module.exports = {
116
107
  validateConfig,
117
108
  createFactories,
118
- createGlobalLifecycleHandler,
119
109
  };
package/src/invoke.js CHANGED
@@ -1,4 +1,3 @@
1
- const EarlGrey = require('./invoke/EarlGrey');
2
1
  const Espresso = require('./invoke/Espresso');
3
2
  const EspressoWeb = require('./invoke/EspressoWeb');
4
3
  const Invoke = require('./invoke/Invoke');
@@ -15,7 +14,6 @@ class InvocationManager {
15
14
 
16
15
  module.exports = {
17
16
  InvocationManager,
18
- EarlGrey,
19
17
  Espresso: Espresso.target,
20
18
  EspressoWeb: EspressoWeb.target,
21
19
  IOS: Invoke.genericInvokeObject,
@@ -6,12 +6,16 @@ const fs = require('fs-extra');
6
6
  const _ = require('lodash');
7
7
  const tempfile = require('tempfile');
8
8
 
9
+
9
10
  const { assertEnum, assertNormalized } = require('../utils/assertArgument');
10
11
  const { removeMilliseconds } = require('../utils/dateUtils');
11
12
  const { actionDescription, expectDescription } = require('../utils/invocationTraceDescriptions');
13
+ const { isRegExp } = require('../utils/isRegExp');
12
14
  const log = require('../utils/logger').child({ cat: 'ws-client, ws' });
13
15
  const traceInvocationCall = require('../utils/traceInvocationCall').bind(null, log);
14
16
 
17
+ const { webElement, webMatcher, webExpect, isWebElement } = require('./web');
18
+
15
19
  const assertDirection = assertEnum(['left', 'right', 'up', 'down']);
16
20
  const assertSpeed = assertEnum(['fast', 'slow']);
17
21
 
@@ -231,7 +235,7 @@ class Element {
231
235
 
232
236
  performAccessibilityAction(actionName) {
233
237
  if (typeof actionName !== 'string') throw new Error('actionName should be a string, but got ' + (actionName + (' (' + (typeof actionName + ')'))));
234
-
238
+
235
239
  const traceDescription = actionDescription.performAccessibilityAction(actionName);
236
240
  return this.withAction('accessibilityAction', traceDescription, actionName);
237
241
  }
@@ -399,7 +403,7 @@ class By {
399
403
  }
400
404
 
401
405
  get web() {
402
- throw new Error('Detox does not support by.web matchers on iOS.');
406
+ return webMatcher();
403
407
  }
404
408
  }
405
409
 
@@ -409,14 +413,14 @@ class Matcher {
409
413
  }
410
414
 
411
415
  label(label) {
412
- if (typeof label !== 'string') throw new Error('label should be a string, but got ' + (label + (' (' + (typeof label + ')'))));
413
- this.predicate = { type: 'label', value: label };
416
+ if (typeof label !== 'string' && !isRegExp(label)) throw new Error('label should be a string or regex, but got ' + (label + (' (' + (typeof label + ')'))));
417
+ this.predicate = { type: 'label', value: label.toString(), isRegex: isRegExp(label) };
414
418
  return this;
415
419
  }
416
420
 
417
421
  id(id) {
418
- if (typeof id !== 'string') throw new Error('id should be a string, but got ' + (id + (' (' + (typeof id + ')'))));
419
- this.predicate = { type: 'id', value: id };
422
+ if (typeof id !== 'string' && !isRegExp(id)) throw new Error('id should be a string or regex, but got ' + (id + (' (' + (typeof id + ')'))));
423
+ this.predicate = { type: 'id', value: id.toString(), isRegex: isRegExp(id) };
420
424
  return this;
421
425
  }
422
426
 
@@ -439,8 +443,8 @@ class Matcher {
439
443
  }
440
444
 
441
445
  text(text) {
442
- if (typeof text !== 'string') throw new Error('text should be a string, but got ' + (text + (' (' + (typeof text + ')'))));
443
- this.predicate = { type: 'text', value: text };
446
+ if (typeof text !== 'string' && !isRegExp(text)) throw new Error(`text should be a string or regex, but got ` + (text + (' (' + (typeof text + ')'))));
447
+ this.predicate = { type: 'text', value: text.toString(), isRegex: isRegExp(text) };
444
448
  return this;
445
449
  }
446
450
 
@@ -754,7 +758,7 @@ class IosExpect {
754
758
  this.waitFor = this.waitFor.bind(this);
755
759
  this.by = new By();
756
760
  this.web = this.web.bind(this);
757
- this.web.element = this.web;
761
+ this.web.element = this.web().element;
758
762
  }
759
763
 
760
764
  element(matcher) {
@@ -762,6 +766,10 @@ class IosExpect {
762
766
  }
763
767
 
764
768
  expect(element) {
769
+ if (isWebElement(element)) {
770
+ return webExpect(this._invocationManager, element);
771
+ }
772
+
765
773
  return expect(this._invocationManager, element);
766
774
  }
767
775
 
@@ -769,8 +777,17 @@ class IosExpect {
769
777
  return waitFor(this._invocationManager, this._emitter, element);
770
778
  }
771
779
 
772
- web(_matcher) {
773
- throw new Error('Detox does not support web(), web.element() API on iOS.');
780
+ web(matcher) {
781
+ return {
782
+ element: webMatcher => {
783
+ if (!(matcher instanceof Matcher) && matcher !== undefined) {
784
+ throwMatcherError(matcher);
785
+ }
786
+
787
+ const webViewElement = matcher ? element(this._invocationManager, this._emitter, matcher) : undefined;
788
+ return webElement(this._invocationManager, this._emitter, webViewElement, webMatcher);
789
+ }
790
+ };
774
791
  }
775
792
  }
776
793