detox 20.12.0-smoke.0 → 20.12.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (133) hide show
  1. package/Detox-android/com/wix/detox/{20.12.0-smoke.0/detox-20.12.0-smoke.0-javadoc.jar → 20.12.0/detox-20.12.0-javadoc.jar} +0 -0
  2. package/Detox-android/com/wix/detox/20.12.0/detox-20.12.0-javadoc.jar.md5 +1 -0
  3. package/Detox-android/com/wix/detox/20.12.0/detox-20.12.0-javadoc.jar.sha1 +1 -0
  4. package/Detox-android/com/wix/detox/20.12.0/detox-20.12.0-javadoc.jar.sha256 +1 -0
  5. package/Detox-android/com/wix/detox/20.12.0/detox-20.12.0-javadoc.jar.sha512 +1 -0
  6. package/Detox-android/com/wix/detox/{20.12.0-smoke.0/detox-20.12.0-smoke.0-sources.jar → 20.12.0/detox-20.12.0-sources.jar} +0 -0
  7. package/Detox-android/com/wix/detox/20.12.0/detox-20.12.0-sources.jar.md5 +1 -0
  8. package/Detox-android/com/wix/detox/20.12.0/detox-20.12.0-sources.jar.sha1 +1 -0
  9. package/Detox-android/com/wix/detox/20.12.0/detox-20.12.0-sources.jar.sha256 +1 -0
  10. package/Detox-android/com/wix/detox/20.12.0/detox-20.12.0-sources.jar.sha512 +1 -0
  11. package/Detox-android/com/wix/detox/20.12.0/detox-20.12.0.aar +0 -0
  12. package/Detox-android/com/wix/detox/20.12.0/detox-20.12.0.aar.md5 +1 -0
  13. package/Detox-android/com/wix/detox/20.12.0/detox-20.12.0.aar.sha1 +1 -0
  14. package/Detox-android/com/wix/detox/20.12.0/detox-20.12.0.aar.sha256 +1 -0
  15. package/Detox-android/com/wix/detox/20.12.0/detox-20.12.0.aar.sha512 +1 -0
  16. package/Detox-android/com/wix/detox/{20.12.0-smoke.0/detox-20.12.0-smoke.0.pom → 20.12.0/detox-20.12.0.pom} +1 -1
  17. package/Detox-android/com/wix/detox/20.12.0/detox-20.12.0.pom.md5 +1 -0
  18. package/Detox-android/com/wix/detox/20.12.0/detox-20.12.0.pom.sha1 +1 -0
  19. package/Detox-android/com/wix/detox/20.12.0/detox-20.12.0.pom.sha256 +1 -0
  20. package/Detox-android/com/wix/detox/20.12.0/detox-20.12.0.pom.sha512 +1 -0
  21. package/Detox-android/com/wix/detox/maven-metadata.xml +4 -4
  22. package/Detox-android/com/wix/detox/maven-metadata.xml.md5 +1 -1
  23. package/Detox-android/com/wix/detox/maven-metadata.xml.sha1 +1 -1
  24. package/Detox-android/com/wix/detox/maven-metadata.xml.sha256 +1 -1
  25. package/Detox-android/com/wix/detox/maven-metadata.xml.sha512 +1 -1
  26. package/Detox-ios-src.tbz +0 -0
  27. package/Detox-ios.tbz +0 -0
  28. package/android/detox/build.gradle +1 -1
  29. package/android/detox/src/full/java/com/wix/detox/espresso/DetoxAssertion.java +44 -25
  30. package/android/detox/src/full/java/com/wix/detox/espresso/EspressoDetox.java +6 -7
  31. package/android/detox/src/full/java/com/wix/detox/espresso/action/GetAttributesAction.kt +4 -4
  32. package/android/detox/src/full/java/com/wix/detox/espresso/performer/MultipleViewsActionPerformer.kt +43 -0
  33. package/android/detox/src/full/java/com/wix/detox/espresso/performer/SingleViewActionPerformer.kt +19 -0
  34. package/android/detox/src/full/java/com/wix/detox/espresso/performer/ViewActionPerformer.kt +24 -0
  35. package/android/detox/src/full/java/com/wix/invoke/types/Invocation.java +5 -4
  36. package/android/detox/src/main/java/com/wix/detox/espresso/MultipleViewsAction.kt +4 -0
  37. package/android/detox/src/main/java/com/wix/detox/espresso/UiControllerSpy.kt +0 -1
  38. package/android/detox/src/main/java/com/wix/detox/espresso/ViewActionWithResult.kt +2 -1
  39. package/android/detox/src/testFull/java/com/wix/detox/espresso/action/GetAttributesActionTest.kt +6 -5
  40. package/android/detox/src/testFull/java/com/wix/detox/espresso/performer/ViewActionPerformerSpec.kt +37 -0
  41. package/index.d.ts +4 -3
  42. package/local-cli/reset-lock-file.js +9 -5
  43. package/package.json +6 -6
  44. package/src/DetoxWorker.js +9 -5
  45. package/src/android/core/NativeElement.js +26 -29
  46. package/src/android/espressoapi/DetoxAssertion.js +16 -14
  47. package/src/android/espressoapi/EspressoDetox.js +9 -2
  48. package/src/android/interactions/native.js +2 -3
  49. package/src/artifacts/providers/index.js +3 -3
  50. package/src/artifacts/screenshot/SimulatorScreenshotPlugin.js +17 -0
  51. package/src/devices/DeviceRegistry.js +176 -0
  52. package/src/devices/allocation/DeviceAllocator.js +15 -50
  53. package/src/devices/allocation/drivers/AllocationDriverBase.js +4 -10
  54. package/src/devices/allocation/drivers/android/attached/AttachedAndroidAllocDriver.js +6 -7
  55. package/src/devices/allocation/drivers/android/attached/AttachedAndroidLauncher.js +13 -0
  56. package/src/devices/allocation/drivers/android/emulator/EmulatorAllocDriver.js +26 -108
  57. package/src/devices/allocation/drivers/android/emulator/EmulatorAllocationHelper.js +72 -0
  58. package/src/devices/allocation/drivers/android/emulator/EmulatorLauncher.js +43 -33
  59. package/src/devices/allocation/drivers/android/emulator/FreeEmulatorFinder.js +1 -1
  60. package/src/devices/allocation/drivers/android/emulator/launchEmulatorProcess.js +3 -3
  61. package/src/devices/allocation/drivers/android/genycloud/GenyAllocDriver.js +27 -87
  62. package/src/devices/allocation/drivers/android/genycloud/GenyDeviceRegistryFactory.js +16 -0
  63. package/src/devices/allocation/drivers/android/genycloud/GenyInstanceAllocationHelper.js +65 -0
  64. package/src/devices/allocation/drivers/android/genycloud/GenyInstanceLauncher.js +28 -39
  65. package/src/devices/allocation/drivers/ios/SimulatorAllocDriver.js +40 -70
  66. package/src/devices/allocation/drivers/ios/SimulatorLauncher.js +7 -11
  67. package/src/devices/allocation/factories/android.js +35 -29
  68. package/src/devices/allocation/factories/ios.js +5 -7
  69. package/src/devices/common/drivers/DeviceAllocationHelper.js +20 -0
  70. package/src/devices/common/drivers/DeviceLauncher.js +19 -0
  71. package/src/devices/common/drivers/android/emulator/exec/EmulatorExec.js +5 -17
  72. package/src/devices/common/drivers/android/exec/ADB.js +0 -1
  73. package/src/devices/common/drivers/android/genycloud/services/GenyInstanceLifecycleService.js +25 -0
  74. package/src/devices/common/drivers/android/genycloud/services/GenyInstanceLookupService.js +38 -0
  75. package/src/devices/common/drivers/android/genycloud/services/GenyInstanceNaming.js +14 -0
  76. package/src/devices/{allocation → common}/drivers/android/genycloud/services/GenyRecipesService.js +1 -1
  77. package/src/devices/{allocation → common}/drivers/android/genycloud/services/dto/GenyInstance.js +1 -6
  78. package/src/devices/{allocation/drivers/android → common/drivers/android/tools}/FreeDeviceFinder.js +10 -11
  79. package/src/devices/common/drivers/ios/tools/AppleSimUtils.js +1 -1
  80. package/src/devices/cookies/AndroidDeviceCookie.js +0 -4
  81. package/src/devices/cookies/GenycloudEmulatorCookie.js +5 -3
  82. package/src/devices/cookies/IosSimulatorCookie.js +0 -4
  83. package/src/devices/lifecycle/GenyGlobalLifecycleHandler.js +71 -0
  84. package/src/devices/lifecycle/factories/GenyGlobalLifecycleHandlerFactory.js +18 -0
  85. package/src/devices/runtime/drivers/android/genycloud/GenyCloudDriver.js +2 -2
  86. package/src/devices/runtime/factories/android.js +1 -1
  87. package/src/devices/runtime/factories/ios.js +2 -3
  88. package/src/environmentFactory.js +11 -1
  89. package/src/ipc/IPCClient.js +1 -17
  90. package/src/ipc/IPCServer.js +1 -25
  91. package/src/realms/DetoxContext.js +0 -6
  92. package/src/realms/DetoxPrimaryContext.js +42 -42
  93. package/src/realms/DetoxSecondaryContext.js +0 -19
  94. package/src/realms/symbols.js +0 -4
  95. package/src/{devices/servicelocator → servicelocator}/android/emulatorServiceLocator.js +1 -1
  96. package/src/servicelocator/android/genycloudServiceLocator.js +21 -0
  97. package/src/servicelocator/android/index.js +25 -0
  98. package/src/servicelocator/ios.js +7 -0
  99. package/src/utils/environment.js +15 -8
  100. package/src/utils/errorUtils.js +2 -2
  101. package/src/{devices/validation → validation}/android/GenycloudEnvValidator.js +2 -2
  102. package/src/{devices/validation → validation}/factories/index.js +1 -1
  103. package/src/{devices/validation → validation}/ios/IosSimulatorEnvValidator.js +2 -2
  104. package/Detox-android/com/wix/detox/20.12.0-smoke.0/detox-20.12.0-smoke.0-javadoc.jar.md5 +0 -1
  105. package/Detox-android/com/wix/detox/20.12.0-smoke.0/detox-20.12.0-smoke.0-javadoc.jar.sha1 +0 -1
  106. package/Detox-android/com/wix/detox/20.12.0-smoke.0/detox-20.12.0-smoke.0-javadoc.jar.sha256 +0 -1
  107. package/Detox-android/com/wix/detox/20.12.0-smoke.0/detox-20.12.0-smoke.0-javadoc.jar.sha512 +0 -1
  108. package/Detox-android/com/wix/detox/20.12.0-smoke.0/detox-20.12.0-smoke.0-sources.jar.md5 +0 -1
  109. package/Detox-android/com/wix/detox/20.12.0-smoke.0/detox-20.12.0-smoke.0-sources.jar.sha1 +0 -1
  110. package/Detox-android/com/wix/detox/20.12.0-smoke.0/detox-20.12.0-smoke.0-sources.jar.sha256 +0 -1
  111. package/Detox-android/com/wix/detox/20.12.0-smoke.0/detox-20.12.0-smoke.0-sources.jar.sha512 +0 -1
  112. package/Detox-android/com/wix/detox/20.12.0-smoke.0/detox-20.12.0-smoke.0.aar +0 -0
  113. package/Detox-android/com/wix/detox/20.12.0-smoke.0/detox-20.12.0-smoke.0.aar.md5 +0 -1
  114. package/Detox-android/com/wix/detox/20.12.0-smoke.0/detox-20.12.0-smoke.0.aar.sha1 +0 -1
  115. package/Detox-android/com/wix/detox/20.12.0-smoke.0/detox-20.12.0-smoke.0.aar.sha256 +0 -1
  116. package/Detox-android/com/wix/detox/20.12.0-smoke.0/detox-20.12.0-smoke.0.aar.sha512 +0 -1
  117. package/Detox-android/com/wix/detox/20.12.0-smoke.0/detox-20.12.0-smoke.0.pom.md5 +0 -1
  118. package/Detox-android/com/wix/detox/20.12.0-smoke.0/detox-20.12.0-smoke.0.pom.sha1 +0 -1
  119. package/Detox-android/com/wix/detox/20.12.0-smoke.0/detox-20.12.0-smoke.0.pom.sha256 +0 -1
  120. package/Detox-android/com/wix/detox/20.12.0-smoke.0/detox-20.12.0-smoke.0.pom.sha512 +0 -1
  121. package/src/devices/allocation/DeviceList.js +0 -44
  122. package/src/devices/allocation/DeviceRegistry.js +0 -186
  123. package/src/devices/allocation/drivers/android/emulator/FreePortFinder.js +0 -16
  124. package/src/devices/allocation/drivers/android/genycloud/GenyRegistry.js +0 -93
  125. package/src/devices/allocation/drivers/android/genycloud/services/GenyInstanceLifecycleService.js +0 -24
  126. package/src/devices/allocation/drivers/ios/SimulatorQuery.js +0 -24
  127. package/src/devices/servicelocator/android/genycloudServiceLocator.js +0 -17
  128. package/src/devices/servicelocator/android/index.js +0 -23
  129. package/src/utils/PIDService.js +0 -27
  130. /package/src/devices/{allocation → common}/drivers/android/genycloud/exec/GenyCloudExec.js +0 -0
  131. /package/src/devices/{allocation → common}/drivers/android/genycloud/services/GenyAuthService.js +0 -0
  132. /package/src/devices/{allocation → common}/drivers/android/genycloud/services/dto/GenyRecipe.js +0 -0
  133. /package/src/{devices/validation → validation}/EnvironmentValidatorBase.js +0 -0
@@ -33,6 +33,7 @@ class DetoxWorker {
33
33
  onError: this._onEmitError.bind(this),
34
34
  });
35
35
 
36
+
36
37
  /** @type {DetoxInternals.RuntimeConfig['apps']} */
37
38
  this._appsConfig = null;
38
39
  /** @type {DetoxInternals.RuntimeConfig['artifacts']} */
@@ -114,13 +115,14 @@ class DetoxWorker {
114
115
  const {
115
116
  // @ts-ignore
116
117
  envValidatorFactory,
118
+ deviceAllocatorFactory,
117
119
  // @ts-ignore
118
120
  artifactsManagerFactory,
119
121
  // @ts-ignore
120
122
  matchersFactory,
121
123
  // @ts-ignore
122
124
  runtimeDeviceFactory,
123
- } = environmentFactory.createFactories(deviceConfig);
125
+ } = environmentFactory.createFactories(this._deviceConfig);
124
126
 
125
127
  const envValidator = envValidatorFactory.createValidator();
126
128
  yield envValidator.validate();
@@ -133,7 +135,10 @@ class DetoxWorker {
133
135
  };
134
136
 
135
137
  this._artifactsManager = artifactsManagerFactory.createArtifactsManager(this._artifactsConfig, commonDeps);
136
- this._deviceCookie = yield this._context[symbols.allocateDevice]();
138
+ this._deviceAllocator = deviceAllocatorFactory.createDeviceAllocator(commonDeps);
139
+ this._deviceCookie = yield this._deviceAllocator.allocate(this._deviceConfig);
140
+
141
+ yield this._deviceAllocator.postAllocate(this._deviceCookie);
137
142
 
138
143
  this.device = runtimeDeviceFactory.createRuntimeDevice(
139
144
  this._deviceCookie,
@@ -152,8 +157,6 @@ class DetoxWorker {
152
157
  });
153
158
  Object.assign(this, matchers);
154
159
 
155
- yield this._eventEmitter.emit('bootDevice', { deviceId: this.device.id });
156
-
157
160
  if (behaviorConfig.init.exposeGlobals) {
158
161
  const injectedGlobals = {
159
162
  ...matchers,
@@ -204,7 +207,8 @@ class DetoxWorker {
204
207
  }
205
208
 
206
209
  if (this._deviceCookie) {
207
- await this._context[symbols.deallocateDevice](this._deviceCookie);
210
+ const shutdown = this._behaviorConfig ? this._behaviorConfig.cleanup.shutdownDevice : false;
211
+ await this._deviceAllocator.free(this._deviceCookie, { shutdown });
208
212
  }
209
213
 
210
214
  this._deviceAllocator = null;
@@ -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
 
@@ -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
  }
@@ -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
  }
@@ -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) {
@@ -4,7 +4,7 @@ class ArtifactPluginsProvider {
4
4
 
5
5
  class AndroidArtifactPluginsProvider extends ArtifactPluginsProvider {
6
6
  declareArtifactPlugins({ client }) {
7
- const serviceLocator = require('../../devices/servicelocator/android');
7
+ const serviceLocator = require('../../servicelocator/android');
8
8
  const adb = serviceLocator.adb;
9
9
  const devicePathBuilder = serviceLocator.devicePathBuilder;
10
10
 
@@ -34,8 +34,8 @@ class IosArtifactPluginsProvider extends ArtifactPluginsProvider {
34
34
 
35
35
  class IosSimulatorArtifactPluginsProvider extends IosArtifactPluginsProvider {
36
36
  declareArtifactPlugins({ client }) {
37
- const AppleSimUtils = require('../../devices/common/drivers/ios/tools/AppleSimUtils');
38
- const appleSimUtils = new AppleSimUtils();
37
+ const serviceLocator = require('../../servicelocator/ios');
38
+ const appleSimUtils = serviceLocator.appleSimUtils;
39
39
 
40
40
  const SimulatorInstrumentsPlugin = require('../instruments/ios/SimulatorInstrumentsPlugin');
41
41
  const SimulatorLogPlugin = require('../log/ios/SimulatorLogPlugin');
@@ -22,6 +22,23 @@ class SimulatorScreenshotPlugin extends ScreenshotArtifactPlugin {
22
22
  }
23
23
  }
24
24
 
25
+ async onBootDevice(event) {
26
+ await super.onBootDevice(event);
27
+
28
+ if (this.enabled && event.coldBoot) {
29
+ await this.appleSimUtils.takeScreenshot(event.deviceId, '/dev/null').catch(() => {
30
+ log.debug({}, `
31
+ NOTE: For an unknown yet reason, taking the first screenshot is apt
32
+ to fail when booting iOS Simulator in a hidden window mode (or on CI).
33
+ Detox applies a workaround by taking a dummy screenshot to ensure
34
+ that the future ones are going to work fine. This screenshot is not
35
+ saved anywhere, and the error above is suppressed for all log levels
36
+ except for "debug" and "trace."
37
+ `.trim());
38
+ });
39
+ }
40
+ }
41
+
25
42
  async onBeforeUninstallApp(event) {
26
43
  await this.api.requestIdleCallback(async () => {
27
44
  const snapshots = [
@@ -0,0 +1,176 @@
1
+ // @ts-nocheck
2
+ const fs = require('fs-extra');
3
+ const _ = require('lodash');
4
+
5
+ const ExclusiveLockfile = require('../utils/ExclusiveLockfile');
6
+ const environment = require('../utils/environment');
7
+ const safeAsync = require('../utils/safeAsync');
8
+
9
+ const readOptions = {
10
+ encoding: 'utf8',
11
+ };
12
+
13
+ const FIELD_NAME_ID = 'id';
14
+ const FIELD_NAME_DATA = 'data';
15
+
16
+ class DevicesList {
17
+ constructor(devices) {
18
+ this._devices = Object.freeze(devices);
19
+ }
20
+
21
+ /**
22
+ * @returns {{id: string, data: *?}[]}
23
+ */
24
+ get rawDevices() {
25
+ return this._devices;
26
+ }
27
+
28
+ /**
29
+ * @param {string} deviceId
30
+ * @returns {boolean}
31
+ */
32
+ includes(deviceId) {
33
+ return DevicesList._includes(deviceId, this._devices);
34
+ }
35
+
36
+ static _includes(deviceId, devices) {
37
+ return _.some(devices, [FIELD_NAME_ID, deviceId]);
38
+ }
39
+ }
40
+
41
+ class DeviceRegistry {
42
+ constructor({ lockfilePath }) {
43
+ /***
44
+ * @private
45
+ * @type {string}
46
+ */
47
+ this._lockfilePath = lockfilePath;
48
+
49
+ /***
50
+ * @protected
51
+ * @type {ExclusiveLockfile}
52
+ */
53
+ this._lockfile = new ExclusiveLockfile(lockfilePath, {
54
+ getInitialState: this._getInitialLockFileState.bind(this),
55
+ readOptions,
56
+ });
57
+ }
58
+
59
+ async reset() {
60
+ await this._lockfile.exclusively(() => {
61
+ const empty = this._getInitialLockFileState();
62
+ this._lockfile.write(empty);
63
+ });
64
+ }
65
+
66
+ /***
67
+ * @param {string|Function} getDeviceId
68
+ * @param {*?} data
69
+ * @returns {Promise<string>}
70
+ */
71
+ async allocateDevice(getDeviceId, data) {
72
+ return this._lockfile.exclusively(async () => {
73
+ const deviceId = await safeAsync(getDeviceId);
74
+ this._registerDevice(deviceId, data);
75
+ return deviceId;
76
+ });
77
+ }
78
+
79
+ /***
80
+ * @param {string|Function} getDeviceId
81
+ * @returns {Promise<void>}
82
+ */
83
+ async disposeDevice(getDeviceId) {
84
+ await this._lockfile.exclusively(async () => {
85
+ const deviceId = await safeAsync(getDeviceId);
86
+ if (deviceId) {
87
+ this._unregisterDevice(deviceId);
88
+ }
89
+ });
90
+ }
91
+
92
+ /***
93
+ * @param {string} deviceId
94
+ * @returns {boolean}
95
+ */
96
+ includes(deviceId) {
97
+ const devices = this._lockfile.read();
98
+ return DevicesList._includes(deviceId, devices);
99
+ }
100
+
101
+ /***
102
+ * @returns {DevicesList}
103
+ */
104
+ getRegisteredDevices() {
105
+ const devices = this._lockfile.read();
106
+ return new DevicesList(devices);
107
+ }
108
+
109
+ /***
110
+ * @returns {DevicesList}
111
+ */
112
+ async readRegisteredDevices() {
113
+ let result = null;
114
+ await this._lockfile.exclusively(() => {
115
+ result = this.getRegisteredDevices();
116
+ });
117
+ return result;
118
+ }
119
+
120
+ /***
121
+ * @returns {DevicesList}
122
+ */
123
+ readRegisteredDevicesUNSAFE() {
124
+ const contents = fs.readFileSync(this._lockfilePath, readOptions);
125
+ const devices = JSON.parse(contents);
126
+ return new DevicesList(devices);
127
+ }
128
+
129
+ /***
130
+ * @private
131
+ */
132
+ _getInitialLockFileState() {
133
+ return [];
134
+ }
135
+
136
+ /**
137
+ * @private
138
+ */
139
+ _registerDevice(deviceId, data) {
140
+ const state = this._lockfile.read();
141
+ let newState = _.reject(state, [FIELD_NAME_ID, deviceId]);
142
+
143
+ const device = {};
144
+ device[FIELD_NAME_ID] = deviceId;
145
+
146
+ if (data) {
147
+ device[FIELD_NAME_DATA] = data;
148
+ }
149
+
150
+ newState = _.concat(newState, device);
151
+ this._lockfile.write(newState);
152
+ }
153
+
154
+ /**
155
+ * @private
156
+ */
157
+ _unregisterDevice(deviceId) {
158
+ const state = this._lockfile.read();
159
+ const newState = _.reject(state, [FIELD_NAME_ID, deviceId]);
160
+ this._lockfile.write(newState);
161
+ }
162
+
163
+ static forIOS() {
164
+ return new DeviceRegistry({
165
+ lockfilePath: environment.getDeviceLockFilePathIOS(),
166
+ });
167
+ }
168
+
169
+ static forAndroid() {
170
+ return new DeviceRegistry({
171
+ lockfilePath: environment.getDeviceLockFilePathAndroid(),
172
+ });
173
+ }
174
+ }
175
+
176
+ module.exports = DeviceRegistry;