detox 20.0.6-breaking.new-global-lifecycle.0 → 20.0.7-prerelease.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (68) hide show
  1. package/Detox-android/com/wix/detox/{20.0.6-breaking.new-global-lifecycle.0/detox-20.0.6-breaking.new-global-lifecycle.0-javadoc.jar → 20.0.7-prerelease.0/detox-20.0.7-prerelease.0-javadoc.jar} +0 -0
  2. package/Detox-android/com/wix/detox/20.0.7-prerelease.0/detox-20.0.7-prerelease.0-javadoc.jar.md5 +1 -0
  3. package/Detox-android/com/wix/detox/20.0.7-prerelease.0/detox-20.0.7-prerelease.0-javadoc.jar.sha1 +1 -0
  4. package/Detox-android/com/wix/detox/20.0.7-prerelease.0/detox-20.0.7-prerelease.0-javadoc.jar.sha256 +1 -0
  5. package/Detox-android/com/wix/detox/20.0.7-prerelease.0/detox-20.0.7-prerelease.0-javadoc.jar.sha512 +1 -0
  6. package/Detox-android/com/wix/detox/{20.0.6-breaking.new-global-lifecycle.0/detox-20.0.6-breaking.new-global-lifecycle.0-sources.jar → 20.0.7-prerelease.0/detox-20.0.7-prerelease.0-sources.jar} +0 -0
  7. package/Detox-android/com/wix/detox/20.0.7-prerelease.0/detox-20.0.7-prerelease.0-sources.jar.md5 +1 -0
  8. package/Detox-android/com/wix/detox/20.0.7-prerelease.0/detox-20.0.7-prerelease.0-sources.jar.sha1 +1 -0
  9. package/Detox-android/com/wix/detox/20.0.7-prerelease.0/detox-20.0.7-prerelease.0-sources.jar.sha256 +1 -0
  10. package/Detox-android/com/wix/detox/20.0.7-prerelease.0/detox-20.0.7-prerelease.0-sources.jar.sha512 +1 -0
  11. package/Detox-android/com/wix/detox/20.0.7-prerelease.0/detox-20.0.7-prerelease.0.aar +0 -0
  12. package/Detox-android/com/wix/detox/20.0.7-prerelease.0/detox-20.0.7-prerelease.0.aar.md5 +1 -0
  13. package/Detox-android/com/wix/detox/20.0.7-prerelease.0/detox-20.0.7-prerelease.0.aar.sha1 +1 -0
  14. package/Detox-android/com/wix/detox/20.0.7-prerelease.0/detox-20.0.7-prerelease.0.aar.sha256 +1 -0
  15. package/Detox-android/com/wix/detox/20.0.7-prerelease.0/detox-20.0.7-prerelease.0.aar.sha512 +1 -0
  16. package/Detox-android/com/wix/detox/{20.0.6-breaking.new-global-lifecycle.0/detox-20.0.6-breaking.new-global-lifecycle.0.pom → 20.0.7-prerelease.0/detox-20.0.7-prerelease.0.pom} +1 -1
  17. package/Detox-android/com/wix/detox/20.0.7-prerelease.0/detox-20.0.7-prerelease.0.pom.md5 +1 -0
  18. package/Detox-android/com/wix/detox/20.0.7-prerelease.0/detox-20.0.7-prerelease.0.pom.sha1 +1 -0
  19. package/Detox-android/com/wix/detox/20.0.7-prerelease.0/detox-20.0.7-prerelease.0.pom.sha256 +1 -0
  20. package/Detox-android/com/wix/detox/20.0.7-prerelease.0/detox-20.0.7-prerelease.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/proguard-rules-app.pro +4 -0
  29. package/android/detox/src/full/java/com/wix/detox/DetoxCrashHandler.kt +1 -1
  30. package/android/detox/src/full/java/com/wix/detox/LaunchArgs.java +9 -0
  31. package/android/detox/src/full/java/com/wix/detox/TestEngineFacade.kt +1 -1
  32. package/android/detox/src/full/java/com/wix/detox/reactnative/ReactNativeExtension.kt +15 -2
  33. package/android/detox/src/full/java/com/wix/detox/reactnative/ReactNativeIdlingResources.kt +43 -38
  34. package/index.d.ts +10 -1
  35. package/package.json +2 -2
  36. package/runners/jest/testEnvironment/index.js +3 -2
  37. package/src/DetoxWorker.js +0 -6
  38. package/src/android/core/NativeElement.js +56 -20
  39. package/src/android/core/NativeExpect.js +28 -9
  40. package/src/android/interactions/native.js +24 -18
  41. package/src/artifacts/timeline/TimelineContextTypes.js +7 -0
  42. package/src/client/Client.js +18 -1
  43. package/src/devices/common/drivers/android/tools/MonitoredInstrumentation.js +1 -1
  44. package/src/devices/common/drivers/ios/tools/AppleSimUtils.js +3 -1
  45. package/src/devices/runtime/RuntimeDevice.js +2 -4
  46. package/src/devices/runtime/drivers/android/AndroidDriver.js +9 -1
  47. package/src/ios/expectTwo.js +152 -67
  48. package/src/logger/DetoxLogger.js +5 -1
  49. package/src/logger/utils/tracerLegacy.js +24 -1
  50. package/src/utils/errorUtils.js +4 -3
  51. package/src/utils/invocationTraceDescriptions.js +43 -0
  52. package/Detox-android/com/wix/detox/20.0.6-breaking.new-global-lifecycle.0/detox-20.0.6-breaking.new-global-lifecycle.0-javadoc.jar.md5 +0 -1
  53. package/Detox-android/com/wix/detox/20.0.6-breaking.new-global-lifecycle.0/detox-20.0.6-breaking.new-global-lifecycle.0-javadoc.jar.sha1 +0 -1
  54. package/Detox-android/com/wix/detox/20.0.6-breaking.new-global-lifecycle.0/detox-20.0.6-breaking.new-global-lifecycle.0-javadoc.jar.sha256 +0 -1
  55. package/Detox-android/com/wix/detox/20.0.6-breaking.new-global-lifecycle.0/detox-20.0.6-breaking.new-global-lifecycle.0-javadoc.jar.sha512 +0 -1
  56. package/Detox-android/com/wix/detox/20.0.6-breaking.new-global-lifecycle.0/detox-20.0.6-breaking.new-global-lifecycle.0-sources.jar.md5 +0 -1
  57. package/Detox-android/com/wix/detox/20.0.6-breaking.new-global-lifecycle.0/detox-20.0.6-breaking.new-global-lifecycle.0-sources.jar.sha1 +0 -1
  58. package/Detox-android/com/wix/detox/20.0.6-breaking.new-global-lifecycle.0/detox-20.0.6-breaking.new-global-lifecycle.0-sources.jar.sha256 +0 -1
  59. package/Detox-android/com/wix/detox/20.0.6-breaking.new-global-lifecycle.0/detox-20.0.6-breaking.new-global-lifecycle.0-sources.jar.sha512 +0 -1
  60. package/Detox-android/com/wix/detox/20.0.6-breaking.new-global-lifecycle.0/detox-20.0.6-breaking.new-global-lifecycle.0.aar +0 -0
  61. package/Detox-android/com/wix/detox/20.0.6-breaking.new-global-lifecycle.0/detox-20.0.6-breaking.new-global-lifecycle.0.aar.md5 +0 -1
  62. package/Detox-android/com/wix/detox/20.0.6-breaking.new-global-lifecycle.0/detox-20.0.6-breaking.new-global-lifecycle.0.aar.sha1 +0 -1
  63. package/Detox-android/com/wix/detox/20.0.6-breaking.new-global-lifecycle.0/detox-20.0.6-breaking.new-global-lifecycle.0.aar.sha256 +0 -1
  64. package/Detox-android/com/wix/detox/20.0.6-breaking.new-global-lifecycle.0/detox-20.0.6-breaking.new-global-lifecycle.0.aar.sha512 +0 -1
  65. package/Detox-android/com/wix/detox/20.0.6-breaking.new-global-lifecycle.0/detox-20.0.6-breaking.new-global-lifecycle.0.pom.md5 +0 -1
  66. package/Detox-android/com/wix/detox/20.0.6-breaking.new-global-lifecycle.0/detox-20.0.6-breaking.new-global-lifecycle.0.pom.sha1 +0 -1
  67. package/Detox-android/com/wix/detox/20.0.6-breaking.new-global-lifecycle.0/detox-20.0.6-breaking.new-global-lifecycle.0.pom.sha256 +0 -1
  68. package/Detox-android/com/wix/detox/20.0.6-breaking.new-global-lifecycle.0/detox-20.0.6-breaking.new-global-lifecycle.0.pom.sha512 +0 -1
@@ -1,3 +1,4 @@
1
+ const { expectDescription } = require('../../utils/invocationTraceDescriptions');
1
2
  const { MatcherAssertionInteraction } = require('../interactions/native');
2
3
  const matchers = require('../matchers/native');
3
4
 
@@ -19,7 +20,9 @@ class NativeExpectElement extends NativeExpect {
19
20
  }
20
21
 
21
22
  async toBeVisible(pct) {
22
- return await new MatcherAssertionInteraction(this._invocationManager, this._element, this._notCondition ? new matchers.VisibleMatcher(pct).not : new matchers.VisibleMatcher(pct)).execute();
23
+ const matcher = new matchers.VisibleMatcher(pct);
24
+ const traceDescription = expectDescription.toBeVisible(pct);
25
+ return await new MatcherAssertionInteraction(this._invocationManager, this._element, matcher, this._notCondition, traceDescription).execute();
23
26
  }
24
27
 
25
28
  async toBeNotVisible() {
@@ -27,7 +30,9 @@ class NativeExpectElement extends NativeExpect {
27
30
  }
28
31
 
29
32
  async toExist() {
30
- return await new MatcherAssertionInteraction(this._invocationManager, this._element, this._notCondition ? new matchers.ExistsMatcher().not : new matchers.ExistsMatcher()).execute();
33
+ const matcher = new matchers.ExistsMatcher();
34
+ const traceDescription = expectDescription.toExist();
35
+ return await new MatcherAssertionInteraction(this._invocationManager, this._element, matcher, this._notCondition, traceDescription).execute();
31
36
  }
32
37
 
33
38
  async toNotExist() {
@@ -35,7 +40,9 @@ class NativeExpectElement extends NativeExpect {
35
40
  }
36
41
 
37
42
  async toHaveText(text) {
38
- return await new MatcherAssertionInteraction(this._invocationManager, this._element, this._notCondition ? new matchers.TextMatcher(text).not : new matchers.TextMatcher(text)).execute();
43
+ const matcher = new matchers.TextMatcher(text);
44
+ const traceDescription = expectDescription.toHaveText(text);
45
+ return await new MatcherAssertionInteraction(this._invocationManager, this._element, matcher, this._notCondition, traceDescription).execute();
39
46
  }
40
47
 
41
48
  async toNotHaveText(text) {
@@ -43,7 +50,9 @@ class NativeExpectElement extends NativeExpect {
43
50
  }
44
51
 
45
52
  async toHaveLabel(value) {
46
- return await new MatcherAssertionInteraction(this._invocationManager, this._element, this._notCondition ? new matchers.LabelMatcher(value).not : new matchers.LabelMatcher(value)).execute();
53
+ const matcher = new matchers.LabelMatcher(value);
54
+ const traceDescription = expectDescription.toHaveLabel(value);
55
+ return await new MatcherAssertionInteraction(this._invocationManager, this._element, matcher, this._notCondition, traceDescription).execute();
47
56
  }
48
57
 
49
58
  async toNotHaveLabel(value) {
@@ -51,7 +60,9 @@ class NativeExpectElement extends NativeExpect {
51
60
  }
52
61
 
53
62
  async toHaveId(value) {
54
- return await new MatcherAssertionInteraction(this._invocationManager, this._element, this._notCondition ? new matchers.IdMatcher(value).not : new matchers.IdMatcher(value)).execute();
63
+ const matcher = new matchers.IdMatcher(value);
64
+ const traceDescription = expectDescription.toHaveId(value);
65
+ return await new MatcherAssertionInteraction(this._invocationManager, this._element, matcher, this._notCondition, traceDescription).execute();
55
66
  }
56
67
 
57
68
  async toNotHaveId(value) {
@@ -59,7 +70,9 @@ class NativeExpectElement extends NativeExpect {
59
70
  }
60
71
 
61
72
  async toHaveValue(value) {
62
- return await new MatcherAssertionInteraction(this._invocationManager, this._element, this._notCondition ? new matchers.ValueMatcher(value).not : new matchers.ValueMatcher(value)).execute();
73
+ const matcher = new matchers.ValueMatcher(value);
74
+ const traceDescription = expectDescription.toHaveValue(value);
75
+ return await new MatcherAssertionInteraction(this._invocationManager, this._element, matcher, this._notCondition, traceDescription).execute();
63
76
  }
64
77
 
65
78
  async toNotHaveValue(value) {
@@ -67,15 +80,21 @@ class NativeExpectElement extends NativeExpect {
67
80
  }
68
81
 
69
82
  async toHaveToggleValue(value) {
70
- return await new MatcherAssertionInteraction(this._invocationManager, this._element, this._notCondition ? new matchers.ToggleMatcher(value).not : new matchers.ToggleMatcher(value)).execute();
83
+ const matcher = new matchers.ToggleMatcher(value);
84
+ const traceDescription = expectDescription.toHaveToggleValue(value);
85
+ return await new MatcherAssertionInteraction(this._invocationManager, this._element, matcher, this._notCondition, traceDescription).execute();
71
86
  }
72
87
 
73
88
  async toHaveSliderPosition(value, tolerance = 0) {
74
- return await new MatcherAssertionInteraction(this._invocationManager, this._element, this._notCondition ? new matchers.SliderPositionMatcher(value, tolerance).not : new matchers.SliderPositionMatcher(value, tolerance)).execute();
89
+ const matcher = new matchers.SliderPositionMatcher(value, tolerance);
90
+ const traceDescription = expectDescription.toHaveSliderPosition(value, tolerance);
91
+ return await new MatcherAssertionInteraction(this._invocationManager, this._element, matcher, this._notCondition, traceDescription).execute();
75
92
  }
76
93
 
77
94
  async toBeFocused() {
78
- return await new MatcherAssertionInteraction(this._invocationManager, this._element, this._notCondition ? new matchers.FocusMatcher().not : new matchers.FocusMatcher()).execute();
95
+ const matcher = new matchers.FocusMatcher();
96
+ const traceDescription = expectDescription.toBeFocused();
97
+ return await new MatcherAssertionInteraction(this._invocationManager, this._element, matcher, this._notCondition, traceDescription).execute();
79
98
  }
80
99
 
81
100
  async toBeNotFocused() {
@@ -1,4 +1,6 @@
1
1
  const DetoxRuntimeError = require('../../errors/DetoxRuntimeError');
2
+ const { expectDescription, actionDescription } = require('../../utils/invocationTraceDescriptions');
3
+ const { trace } = require('../../utils/trace');
2
4
  const { ScrollAmountStopAtEdgeAction } = require('../actions/native');
3
5
  const { NativeMatcher } = require('../core/NativeMatcher');
4
6
  const DetoxAssertionApi = require('../espressoapi/DetoxAssertion');
@@ -9,45 +11,50 @@ function call(maybeAFunction) {
9
11
  }
10
12
 
11
13
  class Interaction {
12
- constructor(invocationManager) {
14
+ constructor(invocationManager, traceDescription) {
13
15
  this._call = undefined;
16
+ this._traceDescription = traceDescription;
14
17
  this._invocationManager = invocationManager;
15
18
  }
16
19
 
17
20
  async execute() {
18
- const resultObj = await this._invocationManager.execute(this._call);
19
- return resultObj ? resultObj.result : undefined;
21
+ return trace.invocationCall(this._traceDescription, this._call,
22
+ this._invocationManager.execute(this._call).then((resultObj) => resultObj ? resultObj.result : undefined));
20
23
  }
21
24
  }
22
25
 
23
26
  class ActionInteraction extends Interaction {
24
- constructor(invocationManager, element, action) {
25
- super(invocationManager);
27
+ constructor(invocationManager, element, action, traceDescription) {
28
+ super(invocationManager, traceDescription);
26
29
  this._call = EspressoDetoxApi.perform(call(element._call), action._call);
27
30
  // TODO: move this.execute() here from the caller
28
31
  }
29
32
  }
30
33
 
31
34
  class MatcherAssertionInteraction extends Interaction {
32
- constructor(invocationManager, element, matcher) {
33
- super(invocationManager);
35
+ constructor(invocationManager, element, matcher, notCondition, traceDescription) {
36
+ traceDescription = expectDescription.full(traceDescription, notCondition);
37
+ super(invocationManager, traceDescription);
38
+
39
+ matcher = notCondition ? matcher.not : matcher;
34
40
  this._call = DetoxAssertionApi.assertMatcher(call(element._call), matcher._call.value);
35
41
  // TODO: move this.execute() here from the caller
36
42
  }
37
43
  }
38
44
 
39
45
  class WaitForInteraction extends Interaction {
40
- constructor(invocationManager, element, assertionMatcher) {
41
- super(invocationManager);
46
+ constructor(invocationManager, element, assertionMatcher, expectTraceDescription) {
47
+ super(invocationManager, expectTraceDescription);
42
48
  this._element = element;
43
49
  this._assertionMatcher = assertionMatcher;
44
50
  this._element._selectElementWithMatcher(this._element._originalMatcher);
45
51
  }
46
52
 
47
53
  async withTimeout(timeout) {
48
- if (typeof timeout !== 'number') throw new DetoxRuntimeError(`WaitForInteraction withTimeout argument must be a number, got ${typeof timeout}`);
49
- if (timeout < 0) throw new DetoxRuntimeError('timeout must be larger than 0');
54
+ if (typeof timeout !== 'number') throw new DetoxRuntimeError({ message: `WaitForInteraction withTimeout argument must be a number, got ${typeof timeout}` });
55
+ if (timeout < 0) throw new DetoxRuntimeError({ message: 'timeout must be larger than 0' });
50
56
 
57
+ this._traceDescription = expectDescription.waitForWithTimeout(this._traceDescription, timeout);
51
58
  this._call = DetoxAssertionApi.waitForAssertMatcher(call(this._element._call), this._assertionMatcher._call.value, timeout / 1000);
52
59
  await this.execute();
53
60
  }
@@ -58,20 +65,18 @@ class WaitForInteraction extends Interaction {
58
65
  }
59
66
 
60
67
  class WaitForActionInteractionBase extends Interaction {
61
- constructor(invocationManager, element, matcher, searchMatcher) {
62
- super(invocationManager);
63
- //if (!(element instanceof NativeElement)) throw new DetoxRuntimeError(`WaitForActionInteraction ctor 1st argument must be a valid NativeElement, got ${typeof element}`);
64
- //if (!(matcher instanceof NativeMatcher)) throw new DetoxRuntimeError(`WaitForActionInteraction ctor 2nd argument must be a valid NativeMatcher, got ${typeof matcher}`);
68
+ constructor(invocationManager, element, matcher, searchMatcher, traceDescription) {
69
+ super(invocationManager, traceDescription);
70
+
65
71
  if (!(searchMatcher instanceof NativeMatcher))
66
- throw new DetoxRuntimeError(`WaitForActionInteraction ctor 3rd argument must be a valid NativeMatcher, got ${typeof searchMatcher}`);
72
+ throw new DetoxRuntimeError({ message: `WaitForActionInteraction ctor 3rd argument must be a valid NativeMatcher, got ${typeof searchMatcher}` });
73
+
67
74
  this._element = element;
68
75
  this._originalMatcher = matcher;
69
76
  this._searchMatcher = searchMatcher;
70
77
  }
71
78
 
72
79
  _prepare(searchAction) {
73
- //if (!searchAction instanceof Action) throw new DetoxRuntimeError(`WaitForActionInteraction _execute argument must be a valid Action, got ${typeof searchAction}`);
74
-
75
80
  this._call = DetoxAssertionApi.waitForAssertMatcherWithSearchAction(
76
81
  call(this._element._call),
77
82
  call(this._originalMatcher._call).value,
@@ -83,6 +88,7 @@ class WaitForActionInteractionBase extends Interaction {
83
88
 
84
89
  class WaitForActionInteraction extends WaitForActionInteractionBase {
85
90
  async scroll(amount, direction = 'down', scrollPositionX, scrollPositionY) {
91
+ this._traceDescription = expectDescription.waitFor(actionDescription.scroll(amount, direction, scrollPositionX, scrollPositionY));
86
92
  this._prepare(new ScrollAmountStopAtEdgeAction(direction, amount, scrollPositionX, scrollPositionY));
87
93
  await this.execute();
88
94
  }
@@ -0,0 +1,7 @@
1
+ const TIMELINE_CONTEXT_TYPES = {
2
+ TEST: 'test',
3
+ DESCRIBE: 'describe',
4
+ INVOCATION: 'invocation'
5
+ };
6
+
7
+ module.exports = TIMELINE_CONTEXT_TYPES;
@@ -34,6 +34,7 @@ class Client {
34
34
  this._slowInvocationStatusHandle = null;
35
35
  this._whenAppIsConnected = this._invalidState('before connecting to the app');
36
36
  this._whenAppIsReady = this._whenAppIsConnected;
37
+ this._whenAppDisconnected = Deferred.resolved();
37
38
  this._isCleaningUp = false;
38
39
  this._pendingAppCrash = null;
39
40
  this._appTerminationHandle = null;
@@ -201,6 +202,11 @@ class Client {
201
202
  }
202
203
  }
203
204
 
205
+ /** @async */
206
+ waitUntilDisconnected() {
207
+ return this._whenAppDisconnected.promise;
208
+ }
209
+
204
210
  async waitForBackground() {
205
211
  await this.sendAction(new actions.WaitForBackground());
206
212
  }
@@ -301,6 +307,8 @@ class Client {
301
307
  } else {
302
308
  this._whenAppIsConnected = Deferred.resolved();
303
309
  }
310
+
311
+ this._whenAppDisconnected = new Deferred();
304
312
  }
305
313
 
306
314
  _onAppReady() {
@@ -320,6 +328,10 @@ class Client {
320
328
  }
321
329
 
322
330
  _onBeforeAppCrash({ params }) {
331
+ if (this._pendingAppCrash) {
332
+ return;
333
+ }
334
+
323
335
  this._pendingAppCrash = new DetoxRuntimeError({
324
336
  message: 'The app has crashed, see the details below:',
325
337
  debugInfo: params.errorDetails,
@@ -338,10 +350,15 @@ class Client {
338
350
  this._whenAppIsReady = this._whenAppIsConnected;
339
351
 
340
352
  if (this._pendingAppCrash) {
353
+ this._whenAppDisconnected.reject(this._pendingAppCrash);
341
354
  this._asyncWebSocket.rejectAll(this._pendingAppCrash);
342
355
  this._pendingAppCrash = null;
343
356
  } else if (this._asyncWebSocket.hasPendingActions()) {
344
- this._asyncWebSocket.rejectAll(new DetoxRuntimeError('The app has unexpectedly disconnected from Detox server.'));
357
+ const error = new DetoxRuntimeError('The app has unexpectedly disconnected from Detox server.');
358
+ this._asyncWebSocket.rejectAll(error);
359
+ this._whenAppDisconnected.resolve();
360
+ } else {
361
+ this._whenAppDisconnected.resolve();
345
362
  }
346
363
  }
347
364
 
@@ -77,7 +77,7 @@ class MonitoredInstrumentation {
77
77
  'while it was waiting for "ready" message (over WebSocket) ' +
78
78
  'from the instrumentation process.',
79
79
  debugInfo: this.instrumentationStackTrace
80
- ? `Native stacktrace dump: ${this.instrumentationStackTrace}`
80
+ ? `Native stacktrace dump:\n${this.instrumentationStackTrace}`
81
81
  : '',
82
82
  });
83
83
  }
@@ -271,7 +271,9 @@ class AppleSimUtils {
271
271
  // ```
272
272
  // This workaround is done to ignore the error above, as we do not care if the app was running before, we just
273
273
  // want to make sure it isn't now.
274
- if (err.code === 3 && err.stderr.includes(`the app is not currently running`)) {
274
+ if (err.code === 3 &&
275
+ (err.stderr.includes(`the app is not currently running`) ||
276
+ err.stderr.includes(`The operation couldn’t be completed. found nothing to terminate`))) {
275
277
  return;
276
278
  }
277
279
 
@@ -248,14 +248,12 @@ class RuntimeDevice {
248
248
  async installUtilBinaries() {
249
249
  const paths = this._deviceConfig.utilBinaryPaths;
250
250
  if (paths) {
251
- await traceCall('installUtilBinaries', () =>
252
- this.deviceDriver.installUtilBinaries(paths));
251
+ await traceCall('installUtilBinaries', this.deviceDriver.installUtilBinaries(paths));
253
252
  }
254
253
  }
255
254
 
256
255
  async reloadReactNative() {
257
- await traceCall('reloadRN', () =>
258
- this.deviceDriver.reloadReactNative());
256
+ await traceCall('reload React Native', this.deviceDriver.reloadReactNative());
259
257
  }
260
258
 
261
259
  async openURL(params) {
@@ -148,7 +148,15 @@ class AndroidDriver extends DeviceDriverBase {
148
148
 
149
149
  async waitUntilReady() {
150
150
  try {
151
- await Promise.race([super.waitUntilReady(), this.instrumentation.waitForCrash()]);
151
+ await Promise.race([
152
+ super.waitUntilReady(),
153
+ this.instrumentation.waitForCrash()
154
+ ]);
155
+ } catch (e) {
156
+ log.warn({ error: e }, 'An error occurred while waiting for the app to become ready. Waiting for disconnection...');
157
+ await this.client.waitUntilDisconnected();
158
+ log.warn('The app disconnected.');
159
+ throw e;
152
160
  } finally {
153
161
  this.instrumentation.abortWaitForCrash();
154
162
  }