detox 20.0.11-prerelease.0 → 20.0.13-prerelease.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (71) hide show
  1. package/Detox-android/com/wix/detox/{20.0.11-prerelease.0/detox-20.0.11-prerelease.0-javadoc.jar → 20.0.13-prerelease.0/detox-20.0.13-prerelease.0-javadoc.jar} +0 -0
  2. package/Detox-android/com/wix/detox/20.0.13-prerelease.0/detox-20.0.13-prerelease.0-javadoc.jar.md5 +1 -0
  3. package/Detox-android/com/wix/detox/20.0.13-prerelease.0/detox-20.0.13-prerelease.0-javadoc.jar.sha1 +1 -0
  4. package/Detox-android/com/wix/detox/20.0.13-prerelease.0/detox-20.0.13-prerelease.0-javadoc.jar.sha256 +1 -0
  5. package/Detox-android/com/wix/detox/20.0.13-prerelease.0/detox-20.0.13-prerelease.0-javadoc.jar.sha512 +1 -0
  6. package/Detox-android/com/wix/detox/{20.0.11-prerelease.0/detox-20.0.11-prerelease.0-sources.jar → 20.0.13-prerelease.0/detox-20.0.13-prerelease.0-sources.jar} +0 -0
  7. package/Detox-android/com/wix/detox/20.0.13-prerelease.0/detox-20.0.13-prerelease.0-sources.jar.md5 +1 -0
  8. package/Detox-android/com/wix/detox/20.0.13-prerelease.0/detox-20.0.13-prerelease.0-sources.jar.sha1 +1 -0
  9. package/Detox-android/com/wix/detox/20.0.13-prerelease.0/detox-20.0.13-prerelease.0-sources.jar.sha256 +1 -0
  10. package/Detox-android/com/wix/detox/20.0.13-prerelease.0/detox-20.0.13-prerelease.0-sources.jar.sha512 +1 -0
  11. package/Detox-android/com/wix/detox/{20.0.11-prerelease.0/detox-20.0.11-prerelease.0.aar → 20.0.13-prerelease.0/detox-20.0.13-prerelease.0.aar} +0 -0
  12. package/Detox-android/com/wix/detox/{20.0.11-prerelease.0/detox-20.0.11-prerelease.0.aar.md5 → 20.0.13-prerelease.0/detox-20.0.13-prerelease.0.aar.md5} +0 -0
  13. package/Detox-android/com/wix/detox/{20.0.11-prerelease.0/detox-20.0.11-prerelease.0.aar.sha1 → 20.0.13-prerelease.0/detox-20.0.13-prerelease.0.aar.sha1} +0 -0
  14. package/Detox-android/com/wix/detox/{20.0.11-prerelease.0/detox-20.0.11-prerelease.0.aar.sha256 → 20.0.13-prerelease.0/detox-20.0.13-prerelease.0.aar.sha256} +0 -0
  15. package/Detox-android/com/wix/detox/{20.0.11-prerelease.0/detox-20.0.11-prerelease.0.aar.sha512 → 20.0.13-prerelease.0/detox-20.0.13-prerelease.0.aar.sha512} +0 -0
  16. package/Detox-android/com/wix/detox/{20.0.11-prerelease.0/detox-20.0.11-prerelease.0.pom → 20.0.13-prerelease.0/detox-20.0.13-prerelease.0.pom} +1 -1
  17. package/Detox-android/com/wix/detox/20.0.13-prerelease.0/detox-20.0.13-prerelease.0.pom.md5 +1 -0
  18. package/Detox-android/com/wix/detox/20.0.13-prerelease.0/detox-20.0.13-prerelease.0.pom.sha1 +1 -0
  19. package/Detox-android/com/wix/detox/20.0.13-prerelease.0/detox-20.0.13-prerelease.0.pom.sha256 +1 -0
  20. package/Detox-android/com/wix/detox/20.0.13-prerelease.0/detox-20.0.13-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 -2
  29. package/index.d.ts +22 -6
  30. package/internals.d.ts +106 -28
  31. package/local-cli/cli.js +7 -5
  32. package/local-cli/init.js +1 -1
  33. package/local-cli/reset-lock-file.js +16 -0
  34. package/local-cli/test.js +4 -4
  35. package/local-cli/test.test.js +85 -37
  36. package/local-cli/testCommand/TestRunnerCommand.js +45 -30
  37. package/local-cli/utils/jestInternals.js +4 -1
  38. package/package.json +3 -3
  39. package/runners/jest/reporters/DetoxReporter.js +22 -2
  40. package/runners/jest/testEnvironment/index.js +83 -82
  41. package/runners/jest/testEnvironment/listeners/DetoxCoreListener.js +9 -24
  42. package/runners/jest/testEnvironment/listeners/DetoxPlatformFilterListener.js +1 -1
  43. package/src/DetoxWorker.js +0 -6
  44. package/src/artifacts/ArtifactsManager.js +0 -18
  45. package/src/configuration/composeLoggerConfig.js +2 -2
  46. package/src/configuration/composeRunnerConfig.js +7 -4
  47. package/src/devices/allocation/drivers/android/emulator/AVDValidator.js +4 -4
  48. package/src/devices/allocation/drivers/android/emulator/EmulatorAllocDriver.js +1 -1
  49. package/src/ipc/IPCClient.js +9 -5
  50. package/src/ipc/IPCServer.js +17 -13
  51. package/src/ipc/SessionState.js +3 -5
  52. package/src/logger/DetoxLogger.js +4 -6
  53. package/src/realms/DetoxContext.js +2 -8
  54. package/src/realms/DetoxInternalsFacade.js +1 -1
  55. package/src/realms/DetoxPrimaryContext.js +6 -8
  56. package/src/realms/DetoxSecondaryContext.js +2 -2
  57. package/src/symbols.js +2 -14
  58. package/src/utils/Timer.js +55 -38
  59. package/src/utils/errorUtils.js +20 -0
  60. package/Detox-android/com/wix/detox/20.0.11-prerelease.0/detox-20.0.11-prerelease.0-javadoc.jar.md5 +0 -1
  61. package/Detox-android/com/wix/detox/20.0.11-prerelease.0/detox-20.0.11-prerelease.0-javadoc.jar.sha1 +0 -1
  62. package/Detox-android/com/wix/detox/20.0.11-prerelease.0/detox-20.0.11-prerelease.0-javadoc.jar.sha256 +0 -1
  63. package/Detox-android/com/wix/detox/20.0.11-prerelease.0/detox-20.0.11-prerelease.0-javadoc.jar.sha512 +0 -1
  64. package/Detox-android/com/wix/detox/20.0.11-prerelease.0/detox-20.0.11-prerelease.0-sources.jar.md5 +0 -1
  65. package/Detox-android/com/wix/detox/20.0.11-prerelease.0/detox-20.0.11-prerelease.0-sources.jar.sha1 +0 -1
  66. package/Detox-android/com/wix/detox/20.0.11-prerelease.0/detox-20.0.11-prerelease.0-sources.jar.sha256 +0 -1
  67. package/Detox-android/com/wix/detox/20.0.11-prerelease.0/detox-20.0.11-prerelease.0-sources.jar.sha512 +0 -1
  68. package/Detox-android/com/wix/detox/20.0.11-prerelease.0/detox-20.0.11-prerelease.0.pom.md5 +0 -1
  69. package/Detox-android/com/wix/detox/20.0.11-prerelease.0/detox-20.0.11-prerelease.0.pom.sha1 +0 -1
  70. package/Detox-android/com/wix/detox/20.0.11-prerelease.0/detox-20.0.11-prerelease.0.pom.sha256 +0 -1
  71. package/Detox-android/com/wix/detox/20.0.11-prerelease.0/detox-20.0.11-prerelease.0.pom.sha512 +0 -1
@@ -1,6 +1,6 @@
1
1
  const resolveFrom = require('resolve-from');
2
2
  const maybeNodeEnvironment = require(resolveFrom(process.cwd(), 'jest-environment-node'));
3
- // @ts-ignore
3
+ /** @type {typeof import('@jest/environment').JestEnvironment} */
4
4
  const NodeEnvironment = maybeNodeEnvironment.default || maybeNodeEnvironment;
5
5
 
6
6
  const detox = require('../../../internals');
@@ -33,110 +33,98 @@ class DetoxCircusEnvironment extends NodeEnvironment {
33
33
  constructor(config, context) {
34
34
  super(assertJestCircus27(config), assertExistingContext(context));
35
35
 
36
- /** @private */
37
- this._timer = null;
38
- /** @private */
39
- this._listenerFactories = {
40
- DetoxInitErrorListener,
41
- DetoxPlatformFilterListener,
42
- DetoxCoreListener,
43
- SpecReporter,
44
- WorkerAssignReporter,
45
- };
46
36
  /** @private */
47
37
  this._shouldManageDetox = detox.getStatus() === 'inactive';
48
38
  /** @private */
49
- this._setupFailed = false;
39
+ this._timer = new Timer();
40
+
50
41
  /** @internal */
51
42
  this.testPath = context.testPath;
52
43
  /** @protected */
53
44
  this.testEventListeners = [];
54
45
  /** @protected */
55
- this.initTimeout = detox.config.testRunner.jest.initTimeout;
56
- /** @internal */
46
+ this.setupTimeout = detox.config.testRunner.jest.setupTimeout;
47
+ /** @protected */
48
+ this.teardownTimeout = detox.config.testRunner.jest.teardownTimeout;
49
+
57
50
  log.trace.begin(this.testPath);
58
51
 
59
- this.setup = log.trace.complete.bind(null, 'set up environment', this.setup.bind(this));
52
+ const _setup = this.setup.bind(this);
53
+ this.setup = async () => {
54
+ await log.trace.complete('set up environment', async () => {
55
+ try {
56
+ this._timer.schedule(this.setupTimeout);
57
+ await this._handleTestEventAsync({ name: 'environment_setup_start' });
58
+ await this._timer.run(`setting up Detox environment`, _setup);
59
+ await this._handleTestEventAsync({ name: 'environment_setup_success' });
60
+ } catch (error) {
61
+ this._timer.schedule(this.teardownTimeout);
62
+ await this._handleTestEventAsync({ name: 'environment_setup_failure', error });
63
+ throw error;
64
+ } finally {
65
+ this._timer.clear();
66
+ }
67
+ });
68
+ };
69
+
60
70
  const _teardown = this.teardown.bind(this);
61
71
  this.teardown = async () => {
62
- try {
63
- await log.trace.complete('tear down environment', _teardown);
64
- } finally {
65
- await log.trace.end();
66
- }
72
+ await log.trace.complete('tear down environment', async () => {
73
+ try {
74
+ this._timer.schedule(this.teardownTimeout);
75
+ await this._handleTestEventAsync({ name: 'environment_teardown_start' });
76
+ await this._timer.run(`tearing down Detox environment`, _teardown);
77
+ await this._handleTestEventAsync({ name: 'environment_teardown_success' });
78
+ } catch (error) {
79
+ if (this._timer.expired) {
80
+ this._timer.schedule(this.teardownTimeout);
81
+ }
82
+
83
+ await this._handleTestEventAsync({ name: 'environment_teardown_failure', error });
84
+ throw error;
85
+ } finally {
86
+ this._timer.clear();
87
+ log.trace.end();
88
+ }
89
+ });
67
90
  };
91
+
92
+ this.registerListeners({
93
+ DetoxInitErrorListener,
94
+ DetoxPlatformFilterListener,
95
+ DetoxCoreListener,
96
+ SpecReporter,
97
+ WorkerAssignReporter,
98
+ });
68
99
  }
69
100
 
70
101
  /** @override */
71
102
  async setup() {
72
- try {
73
- await super.setup();
74
- await Timer.run({
75
- description: `setting up Detox environment`,
76
- timeout: this.initTimeout,
77
- fn: async () => {
78
- await this.initDetox();
79
- this._instantiateListeners();
80
- },
81
- });
82
- } catch (e) {
83
- this._setupFailed = true;
84
- throw e;
85
- }
103
+ await this.initDetox();
86
104
  }
87
105
 
88
- /** @override */
89
- async handleTestEvent(event, state) {
90
- const { name } = event;
106
+ handleTestEvent = async (event, state) => {
107
+ this._timer.schedule(state.testTimeout != null ? state.testTimeout : this.setupTimeout);
91
108
 
92
- if (SYNC_CIRCUS_EVENTS.has(name)) {
93
- return this._handleTestEventSync(event, state);
94
- }
95
-
96
- this._timer = new Timer({
97
- description: `handling jest-circus "${name}" event`,
98
- timeout: state.testTimeout != null ? state.testTimeout : this.initTimeout,
99
- });
100
-
101
- try {
102
- for (const listener of this.testEventListeners) {
103
- if (typeof listener[name] !== 'function') {
104
- continue;
105
- }
106
-
107
- try {
108
- await this._timer.run(() => listener[name](event, state));
109
- } catch (listenerError) {
110
- log.error(listenerError);
111
- break;
112
- }
113
- }
114
- } finally {
115
- this._timer.dispose();
116
- this._timer = null;
109
+ if (SYNC_CIRCUS_EVENTS.has(event.name)) {
110
+ this._handleTestEventSync(event, state);
111
+ } else {
112
+ await this._handleTestEventAsync(event, state);
117
113
  }
118
- }
114
+ };
119
115
 
120
116
  /** @override */
121
117
  async teardown() {
122
- await Timer.run({
123
- description: `tearing down Detox environment`,
124
- timeout: this.initTimeout,
125
- fn: async () => {
126
- try {
127
- if (this._setupFailed) {
128
- await detox.reportFailedTests([this.testPath], false);
129
- }
130
- } finally {
131
- await this.cleanupDetox();
132
- }
133
- },
134
- });
118
+ await this.cleanupDetox();
135
119
  }
136
120
 
137
121
  /** @protected */
138
122
  registerListeners(map) {
139
- Object.assign(this._listenerFactories, map);
123
+ for (const Listener of Object.values(map)) {
124
+ this.testEventListeners.push(new Listener({
125
+ env: this,
126
+ }));
127
+ }
140
128
  }
141
129
 
142
130
  /**
@@ -153,6 +141,8 @@ class DetoxCircusEnvironment extends NodeEnvironment {
153
141
  } else {
154
142
  await detox.installWorker(opts);
155
143
  }
144
+
145
+ return detox.worker;
156
146
  }
157
147
 
158
148
  /** @protected */
@@ -176,11 +166,22 @@ class DetoxCircusEnvironment extends NodeEnvironment {
176
166
  }
177
167
 
178
168
  /** @private */
179
- _instantiateListeners() {
180
- for (const Listener of Object.values(this._listenerFactories)) {
181
- this.testEventListeners.push(new Listener({
182
- env: this,
183
- }));
169
+ async _handleTestEventAsync(event, state = null) {
170
+ const description = `handling ${state ? 'jest-circus' : 'jest-environment'} "${event.name}" event`;
171
+
172
+ for (const listener of this.testEventListeners) {
173
+ if (typeof listener[event.name] !== 'function') {
174
+ continue;
175
+ }
176
+
177
+ try {
178
+ await this._timer.run(description, () => listener[event.name](event, state));
179
+ } catch (listenerError) {
180
+ log.error(listenerError);
181
+ if (this._timer.expired) {
182
+ break;
183
+ }
184
+ }
184
185
  }
185
186
  }
186
187
  }
@@ -14,7 +14,7 @@ class DetoxCoreListener {
14
14
  this._startedTests = new WeakSet();
15
15
  this._testsFailedBeforeStart = new WeakSet();
16
16
  this._env = env;
17
- this._testRunTimes = 1;
17
+ this._circusRetryTimes = 1;
18
18
  }
19
19
 
20
20
  async setup() {
@@ -46,7 +46,7 @@ class DetoxCoreListener {
46
46
  }
47
47
 
48
48
  const circusRetryTimes = +this._env.global[RETRY_TIMES];
49
- this._testRunTimes = isNaN(circusRetryTimes) ? 1 : 1 + circusRetryTimes;
49
+ this._circusRetryTimes = isNaN(circusRetryTimes) ? 1 : 1 + circusRetryTimes;
50
50
  }
51
51
 
52
52
  async hook_start(event, state) {
@@ -58,7 +58,12 @@ class DetoxCoreListener {
58
58
  log.trace.end({ success: true });
59
59
  }
60
60
 
61
- async hook_failure({ error }) {
61
+ async hook_failure({ error, hook }) {
62
+ await detoxInternals.onHookFailure({
63
+ error,
64
+ hook: hook.type,
65
+ });
66
+
62
67
  log.trace.end({ success: false, error });
63
68
  }
64
69
 
@@ -94,14 +99,6 @@ class DetoxCoreListener {
94
99
  }
95
100
  }
96
101
 
97
- async run_finish(_event, state) {
98
- const hasFailedTests = this._hasFailedTests(state.rootDescribeBlock);
99
- if (hasFailedTests) {
100
- const handledByJestCircus = this._testRunTimes > 1 && !detoxInternals.config.testRunner.jest.retryAfterCircusRetries;
101
- await detoxInternals.reportFailedTests([this._env.testPath], handledByJestCircus);
102
- }
103
- }
104
-
105
102
  async _onBeforeActualTestStart(test) {
106
103
  if (!test || test.status === 'skip' || this._startedTests.has(test) || this._testsFailedBeforeStart.has(test)) {
107
104
  return false;
@@ -127,19 +124,7 @@ class DetoxCoreListener {
127
124
 
128
125
  _getTestInvocations(test) {
129
126
  const { testSessionIndex } = detoxInternals.session;
130
- return testSessionIndex * this._testRunTimes + test.invocations;
131
- }
132
-
133
- _hasFailedTests(block) {
134
- if (block.children) {
135
- for (const child of block.children) {
136
- if (this._hasFailedTests(child)) {
137
- return true;
138
- }
139
- }
140
- }
141
-
142
- return block.errors ? block.errors.length > 0 : false;
127
+ return testSessionIndex * this._circusRetryTimes + test.invocations;
143
128
  }
144
129
 
145
130
  _getTestMetadata(test) {
@@ -5,7 +5,7 @@ const { device } = require('../../../..');
5
5
  const PLATFORM_REGEXP = /^:([^:]+):/;
6
6
 
7
7
  class DetoxPlatformFilterListener {
8
- constructor() {
8
+ setup() {
9
9
  this._platform = device.getPlatform();
10
10
  }
11
11
 
@@ -190,7 +190,6 @@ class DetoxWorker {
190
190
  return this._context.log;
191
191
  }
192
192
 
193
- onRunStart = async (...args) => this._artifactsManager.onRunStart(...args);
194
193
  onRunDescribeStart = async (...args) => this._artifactsManager.onRunDescribeStart(...args);
195
194
  onTestStart = async (testSummary) => {
196
195
  if (this._isCleaningUp) return;
@@ -205,12 +204,8 @@ class DetoxWorker {
205
204
  if (this._isCleaningUp) return;
206
205
  await this._artifactsManager.onTestStart(testSummary);
207
206
  };
208
- onHookStart = async (...args) => this._artifactsManager.onHookStart(...args);
209
207
  onHookFailure = async (...args) => this._artifactsManager.onHookFailure(...args);
210
- onHookSuccess = async (...args) => this._artifactsManager.onHookSuccess(...args);
211
- onTestFnStart = async (...args) => this._artifactsManager.onTestFnStart(...args);
212
208
  onTestFnFailure = async (...args) => this._artifactsManager.onTestFnFailure(...args);
213
- onTestFnSuccess = async (...args) => this._artifactsManager.onTestFnSuccess(...args);
214
209
  onTestDone = async (testSummary) => {
215
210
  if (this._isCleaningUp) return;
216
211
  this._validateTestSummary('afterEach', testSummary);
@@ -225,7 +220,6 @@ class DetoxWorker {
225
220
  });
226
221
  };
227
222
  onRunDescribeFinish = async (...args) => this._artifactsManager.onRunDescribeFinish(...args);
228
- onRunFinish = async (...args) => this._artifactsManager.onRunFinish(...args);
229
223
 
230
224
  async _reinstallAppsOnDevice() {
231
225
  const appNames = _(this._appsConfig)
@@ -32,19 +32,13 @@ class ArtifactsManager extends EventEmitter {
32
32
  'onBootDevice',
33
33
  'onCreateExternalArtifact',
34
34
  'onHookFailure',
35
- 'onHookStart',
36
- 'onHookSuccess',
37
35
  'onLaunchApp',
38
36
  'onRunDescribeFinish',
39
37
  'onRunDescribeStart',
40
- 'onRunFinish',
41
- 'onRunStart',
42
38
  'onShutdownDevice',
43
39
  'onTerminateApp',
44
40
  'onTestDone',
45
41
  'onTestFnFailure',
46
- 'onTestFnStart',
47
- 'onTestFnSuccess',
48
42
  'onTestStart',
49
43
  ]);
50
44
  }
@@ -185,8 +179,6 @@ class ArtifactsManager extends EventEmitter {
185
179
  });
186
180
  }
187
181
 
188
- async onRunStart() {}
189
-
190
182
  async onRunDescribeStart(suite) {
191
183
  await this._callPlugins('ascending', 'onRunDescribeStart', suite);
192
184
  }
@@ -195,22 +187,14 @@ class ArtifactsManager extends EventEmitter {
195
187
  await this._callPlugins('ascending', 'onTestStart', testSummary);
196
188
  }
197
189
 
198
- async onHookStart() {}
199
-
200
190
  async onHookFailure(testSummary) {
201
191
  await this._callPlugins('plain', 'onHookFailure', testSummary);
202
192
  }
203
193
 
204
- async onHookSuccess() {}
205
-
206
- async onTestFnStart() {}
207
-
208
194
  async onTestFnFailure(testSummary) {
209
195
  await this._callPlugins('plain', 'onTestFnFailure', testSummary);
210
196
  }
211
197
 
212
- async onTestFnSuccess() {}
213
-
214
198
  async onTestDone(testSummary) {
215
199
  await this._callPlugins('descending', 'onTestDone', testSummary);
216
200
  }
@@ -219,8 +203,6 @@ class ArtifactsManager extends EventEmitter {
219
203
  await this._callPlugins('descending', 'onRunDescribeFinish', suite);
220
204
  }
221
205
 
222
- async onRunFinish() {}
223
-
224
206
  async onBeforeCleanup() {
225
207
  await this._callPlugins('descending', 'onBeforeCleanup');
226
208
  await this._idlePromise;
@@ -14,7 +14,7 @@ function composeLoggerConfig(opts) {
14
14
  const items = [
15
15
  {
16
16
  level: 'info',
17
- overrideConsole: 'sandbox',
17
+ overrideConsole: true,
18
18
  options: defaultOptions,
19
19
  },
20
20
  globalConfig.logger,
@@ -46,7 +46,7 @@ function adaptCLI(cliConfig) {
46
46
  }
47
47
 
48
48
  if (cliConfig.useCustomLogger !== undefined) {
49
- result.overrideConsole = cliConfig.useCustomLogger ? 'all' : 'none';
49
+ result.overrideConsole = cliConfig.useCustomLogger;
50
50
  }
51
51
 
52
52
  if (cliConfig.noColor) {
@@ -32,8 +32,10 @@ function composeRunnerConfig(opts) {
32
32
  retries: 0,
33
33
  inspectBrk: inspectBrkHookDefault,
34
34
  forwardEnv: false,
35
+ bail: false,
35
36
  jest: {
36
- initTimeout: 300000,
37
+ setupTimeout: 300000,
38
+ teardownTimeout: 30000,
37
39
  retryAfterCircusRetries: false,
38
40
  reportSpecs: undefined,
39
41
  reportWorkerAssign: true,
@@ -54,11 +56,12 @@ function composeRunnerConfig(opts) {
54
56
 
55
57
  if (typeof merged.inspectBrk === 'function') {
56
58
  if (cliConfig.inspectBrk) {
59
+ merged.retries = 0;
60
+ merged.forwardEnv = true;
57
61
  merged.inspectBrk(merged);
58
- merged.inspectBrk = true;
59
- } else {
60
- merged.inspectBrk = false;
61
62
  }
63
+
64
+ delete merged.inspectBrk;
62
65
  }
63
66
 
64
67
  return merged;
@@ -12,11 +12,11 @@ class AVDValidator {
12
12
  this._emulatorVersionResolver = emulatorVersionResolver;
13
13
  }
14
14
 
15
- async validate(avdName) {
15
+ async validate(avdName, isHeadless) {
16
16
  const avds = await this._avdsResolver.resolve(avdName);
17
17
  this._assertAVDs(avds);
18
18
  await this._assertAVDMatch(avds, avdName);
19
- await this._validateEmulatorVer();
19
+ await this._validateEmulatorVer(isHeadless);
20
20
  }
21
21
 
22
22
  _assertAVDs(avds) {
@@ -37,8 +37,8 @@ class AVDValidator {
37
37
  }
38
38
  }
39
39
 
40
- async _validateEmulatorVer() {
41
- const emulatorVersion = await this._emulatorVersionResolver.resolve();
40
+ async _validateEmulatorVer(isHeadless) {
41
+ const emulatorVersion = await this._emulatorVersionResolver.resolve(isHeadless);
42
42
  if (!emulatorVersion) {
43
43
  logger.warn({ event: 'AVD_VALIDATION' }, 'Emulator version detection failed (See previous logs)');
44
44
  return;
@@ -34,7 +34,7 @@ class EmulatorAllocDriver extends AllocationDriverBase {
34
34
  async allocate(deviceConfig) {
35
35
  const avdName = deviceConfig.device.avdName;
36
36
 
37
- await this._avdValidator.validate(avdName);
37
+ await this._avdValidator.validate(avdName, deviceConfig.headless);
38
38
  await this._fixAvdConfigIniSkinNameIfNeeded(avdName, deviceConfig.headless);
39
39
 
40
40
  const allocResult = await this._allocationHelper.allocateDevice(avdName);
@@ -1,6 +1,7 @@
1
1
  const { IPC } = require('node-ipc');
2
2
 
3
3
  const { DetoxInternalError } = require('../errors');
4
+ const { serializeObjectWithError } = require('../utils/errorUtils');
4
5
 
5
6
  class IPCClient {
6
7
  constructor({ id, logger, state }) {
@@ -47,15 +48,18 @@ class IPCClient {
47
48
  }
48
49
 
49
50
  async registerWorker(workerId) {
50
- await this._emit('registerWorker', { workerId });
51
+ const sessionState = await this._emit('registerWorker', { workerId });
52
+ this._state.patch(sessionState);
51
53
  }
52
54
 
53
55
  /**
54
- * @param {string[]} testFilePaths
55
- * @param {Boolean} permanent
56
+ * @param {DetoxInternals.DetoxTestFileReport[]} testResults
56
57
  */
57
- async reportFailedTests(testFilePaths, permanent) {
58
- await this._emit('failedTests', { testFilePaths, permanent });
58
+ async reportTestResults(testResults) {
59
+ const sessionState = await this._emit('reportTestResults', {
60
+ testResults: testResults.map(r => serializeObjectWithError(r, 'testExecError')),
61
+ });
62
+ this._state.patch(sessionState);
59
63
  }
60
64
 
61
65
  async _connectToServer() {
@@ -1,5 +1,8 @@
1
+ const { uniqBy } = require('lodash');
1
2
  const { IPC } = require('node-ipc');
2
3
 
4
+ const { serializeObjectWithError } = require('../utils/errorUtils');
5
+
3
6
  class IPCServer {
4
7
  /**
5
8
  * @param {object} options
@@ -27,12 +30,12 @@ class IPCServer {
27
30
  this._ipc.config.appspace = 'detox.';
28
31
  this._ipc.config.logger = (msg) => this._logger.trace(msg);
29
32
 
30
- await new Promise((resolve) => {
33
+ await new Promise((resolve) => {
31
34
  // TODO: handle reject
32
35
  this._ipc.serve(() => resolve());
33
36
  this._ipc.server.on('registerContext', this.onRegisterContext.bind(this));
34
37
  this._ipc.server.on('registerWorker', this.onRegisterWorker.bind(this));
35
- this._ipc.server.on('failedTests', this.onFailedTests.bind(this));
38
+ this._ipc.server.on('reportTestResults', this.onReportTestResults.bind(this));
36
39
  this._ipc.server.start();
37
40
  });
38
41
  }
@@ -53,8 +56,7 @@ class IPCServer {
53
56
  this._sessionState.contexts.push(id);
54
57
 
55
58
  this._ipc.server.emit(socket, 'registerContextDone', {
56
- failedTestFiles: this._sessionState.failedTestFiles,
57
- testFilesToRetry: this._sessionState.testFilesToRetry,
59
+ testResults: this._sessionState.testResults,
58
60
  testSessionIndex: this._sessionState.testSessionIndex,
59
61
  });
60
62
  }
@@ -73,20 +75,22 @@ class IPCServer {
73
75
  }
74
76
  }
75
77
 
76
- onFailedTests({ testFilePaths, permanent }, socket = null) {
77
- if (permanent) {
78
- this._sessionState.failedTestFiles.push(...testFilePaths);
79
- } else {
80
- this._sessionState.testFilesToRetry.push(...testFilePaths);
81
- }
78
+ onReportTestResults({ testResults }, socket = null) {
79
+ const merged = uniqBy([
80
+ ...testResults.map(r => serializeObjectWithError(r, 'testExecError')),
81
+ ...this._sessionState.testResults
82
+ ], 'testFilePath');
83
+
84
+ this._sessionState.testResults.splice(0, Infinity, ...merged);
82
85
 
83
86
  if (socket) {
84
- this._ipc.server.emit(socket, 'failedTestsDone', {});
87
+ this._ipc.server.emit(socket, 'reportTestResultsDone', {
88
+ testResults: this._sessionState.testResults,
89
+ });
85
90
  }
86
91
 
87
92
  this._ipc.server.broadcast('sessionStateUpdate', {
88
- failedTestFiles: this._sessionState.failedTestFiles,
89
- testFilesToRetry: this._sessionState.testFilesToRetry,
93
+ testResults: this._sessionState.testResults,
90
94
  });
91
95
  }
92
96
  }
@@ -9,8 +9,7 @@ class SessionState {
9
9
  detoxConfigSnapshotPath = '',
10
10
  detoxConfig = null,
11
11
  detoxIPCServer = '',
12
- failedTestFiles = [],
13
- testFilesToRetry = [],
12
+ testResults = [],
14
13
  testSessionIndex = 0,
15
14
  workersCount = 0
16
15
  }) {
@@ -19,8 +18,7 @@ class SessionState {
19
18
  this.detoxConfigSnapshotPath = detoxConfigSnapshotPath;
20
19
  this.detoxConfig = detoxConfig;
21
20
  this.detoxIPCServer = detoxIPCServer;
22
- this.failedTestFiles = failedTestFiles;
23
- this.testFilesToRetry = testFilesToRetry;
21
+ this.testResults = testResults;
24
22
  this.testSessionIndex = testSessionIndex;
25
23
  this.workersCount = workersCount;
26
24
  }
@@ -43,7 +41,7 @@ class SessionState {
43
41
  }
44
42
 
45
43
  static reviver(key, val) {
46
- if (typeof val === 'object' && typeof val.$fn == 'string') {
44
+ if (typeof val === 'object' && val !== null && typeof val.$fn == 'string') {
47
45
  return eval(val.$fn);
48
46
  } else {
49
47
  return val;
@@ -55,7 +55,7 @@ class DetoxLogger {
55
55
 
56
56
  this._sharedConfig.userConfig = this._sharedConfig.userConfig || {
57
57
  level: 'info',
58
- overrideConsole: 'none',
58
+ overrideConsole: false,
59
59
  options: {
60
60
  showDate: false,
61
61
  showLoggerName: false,
@@ -143,14 +143,12 @@ class DetoxLogger {
143
143
  * @internal
144
144
  */
145
145
  overrideConsole(sandbox) {
146
- const option = this.config.overrideConsole;
147
- if (option === 'none') {
146
+ const enabled = this.config.overrideConsole;
147
+ if (!enabled) {
148
148
  return;
149
149
  }
150
150
 
151
- if ((option === 'sandbox' && sandbox) || option === 'all') {
152
- customConsoleLogger.overrideConsoleMethods((sandbox || global).console, this);
153
- }
151
+ customConsoleLogger.overrideConsoleMethods((sandbox || global).console, this);
154
152
  }
155
153
 
156
154
  /**
@@ -36,7 +36,7 @@ class DetoxContext {
36
36
  };
37
37
 
38
38
  this[symbols.getStatus] = this[symbols.getStatus].bind(this);
39
- this[symbols.reportFailedTests] = this[symbols.reportFailedTests].bind(this);
39
+ this[symbols.reportTestResults] = this[symbols.reportTestResults].bind(this);
40
40
  this[symbols.resolveConfig] = this[symbols.resolveConfig].bind(this);
41
41
  this[symbols.installWorker] = this[symbols.installWorker].bind(this);
42
42
  this[symbols.uninstallWorker] = this[symbols.uninstallWorker].bind(this);
@@ -80,18 +80,12 @@ class DetoxContext {
80
80
  //#endregion
81
81
 
82
82
  //#region Internal members
83
- [symbols.onRunStart] = (...args) => this[symbols.worker].onRunStart(...args);
84
83
  [symbols.onRunDescribeStart] = (...args) => this[symbols.worker].onRunDescribeStart(...args);
85
84
  [symbols.onTestStart] = (...args) => this[symbols.worker].onTestStart(...args);
86
- [symbols.onHookStart] = (...args) => this[symbols.worker].onHookStart(...args);
87
85
  [symbols.onHookFailure] = (...args) => this[symbols.worker].onHookFailure(...args);
88
- [symbols.onHookSuccess] = (...args) => this[symbols.worker].onHookSuccess(...args);
89
- [symbols.onTestFnStart] = (...args) => this[symbols.worker].onTestFnStart(...args);
90
86
  [symbols.onTestFnFailure] = (...args) => this[symbols.worker].onTestFnFailure(...args);
91
- [symbols.onTestFnSuccess] = (...args) => this[symbols.worker].onTestFnSuccess(...args);
92
87
  [symbols.onTestDone] = (...args) => this[symbols.worker].onTestDone(...args);
93
88
  [symbols.onRunDescribeFinish] = (...args) => this[symbols.worker].onRunDescribeFinish(...args);
94
- [symbols.onRunFinish] = (...args) => this[symbols.worker].onRunFinish(...args);
95
89
  [symbols.config] = funpermaproxy(() => this[symbols.session].detoxConfig);
96
90
  [symbols.session] = funpermaproxy(() => this[$sessionState]);
97
91
  [symbols.tracing] = Object.freeze({
@@ -103,7 +97,7 @@ class DetoxContext {
103
97
  },
104
98
  });
105
99
  /** @abstract */
106
- [symbols.reportFailedTests](_testFilePaths, _permanent) {}
100
+ [symbols.reportTestResults](_testResults) {}
107
101
  /**
108
102
  * @abstract
109
103
  * @param {Partial<DetoxInternals.DetoxInitOptions>} _opts
@@ -26,7 +26,7 @@ class DetoxInternalsFacade {
26
26
  this.onTestFnStart = context[symbols.onTestFnStart];
27
27
  this.onTestFnSuccess = context[symbols.onTestFnSuccess];
28
28
  this.onTestStart = context[symbols.onTestStart];
29
- this.reportFailedTests = context[symbols.reportFailedTests];
29
+ this.reportTestResults = context[symbols.reportTestResults];
30
30
  this.resolveConfig = context[symbols.resolveConfig];
31
31
  this.session = context[symbols.session];
32
32
  this.tracing = context[symbols.tracing];