detox 20.0.4-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.
- package/Detox-android/com/wix/detox/{20.0.4-breaking.new-global-lifecycle.0/detox-20.0.4-breaking.new-global-lifecycle.0-javadoc.jar → 20.0.7-prerelease.0/detox-20.0.7-prerelease.0-javadoc.jar} +0 -0
- package/Detox-android/com/wix/detox/20.0.7-prerelease.0/detox-20.0.7-prerelease.0-javadoc.jar.md5 +1 -0
- package/Detox-android/com/wix/detox/20.0.7-prerelease.0/detox-20.0.7-prerelease.0-javadoc.jar.sha1 +1 -0
- package/Detox-android/com/wix/detox/20.0.7-prerelease.0/detox-20.0.7-prerelease.0-javadoc.jar.sha256 +1 -0
- package/Detox-android/com/wix/detox/20.0.7-prerelease.0/detox-20.0.7-prerelease.0-javadoc.jar.sha512 +1 -0
- package/Detox-android/com/wix/detox/{20.0.4-breaking.new-global-lifecycle.0/detox-20.0.4-breaking.new-global-lifecycle.0-sources.jar → 20.0.7-prerelease.0/detox-20.0.7-prerelease.0-sources.jar} +0 -0
- package/Detox-android/com/wix/detox/20.0.7-prerelease.0/detox-20.0.7-prerelease.0-sources.jar.md5 +1 -0
- package/Detox-android/com/wix/detox/20.0.7-prerelease.0/detox-20.0.7-prerelease.0-sources.jar.sha1 +1 -0
- package/Detox-android/com/wix/detox/20.0.7-prerelease.0/detox-20.0.7-prerelease.0-sources.jar.sha256 +1 -0
- package/Detox-android/com/wix/detox/20.0.7-prerelease.0/detox-20.0.7-prerelease.0-sources.jar.sha512 +1 -0
- package/Detox-android/com/wix/detox/20.0.7-prerelease.0/detox-20.0.7-prerelease.0.aar +0 -0
- package/Detox-android/com/wix/detox/20.0.7-prerelease.0/detox-20.0.7-prerelease.0.aar.md5 +1 -0
- package/Detox-android/com/wix/detox/20.0.7-prerelease.0/detox-20.0.7-prerelease.0.aar.sha1 +1 -0
- package/Detox-android/com/wix/detox/20.0.7-prerelease.0/detox-20.0.7-prerelease.0.aar.sha256 +1 -0
- package/Detox-android/com/wix/detox/20.0.7-prerelease.0/detox-20.0.7-prerelease.0.aar.sha512 +1 -0
- package/Detox-android/com/wix/detox/{20.0.4-breaking.new-global-lifecycle.0/detox-20.0.4-breaking.new-global-lifecycle.0.pom → 20.0.7-prerelease.0/detox-20.0.7-prerelease.0.pom} +1 -1
- package/Detox-android/com/wix/detox/20.0.7-prerelease.0/detox-20.0.7-prerelease.0.pom.md5 +1 -0
- package/Detox-android/com/wix/detox/20.0.7-prerelease.0/detox-20.0.7-prerelease.0.pom.sha1 +1 -0
- package/Detox-android/com/wix/detox/20.0.7-prerelease.0/detox-20.0.7-prerelease.0.pom.sha256 +1 -0
- package/Detox-android/com/wix/detox/20.0.7-prerelease.0/detox-20.0.7-prerelease.0.pom.sha512 +1 -0
- package/Detox-android/com/wix/detox/maven-metadata.xml +4 -4
- package/Detox-android/com/wix/detox/maven-metadata.xml.md5 +1 -1
- package/Detox-android/com/wix/detox/maven-metadata.xml.sha1 +1 -1
- package/Detox-android/com/wix/detox/maven-metadata.xml.sha256 +1 -1
- package/Detox-android/com/wix/detox/maven-metadata.xml.sha512 +1 -1
- package/Detox-ios-src.tbz +0 -0
- package/Detox-ios.tbz +0 -0
- package/android/detox/proguard-rules-app.pro +4 -0
- package/android/detox/src/full/java/com/wix/detox/DetoxCrashHandler.kt +1 -1
- package/android/detox/src/full/java/com/wix/detox/LaunchArgs.java +9 -0
- package/android/detox/src/full/java/com/wix/detox/TestEngineFacade.kt +1 -1
- package/android/detox/src/full/java/com/wix/detox/reactnative/ReactNativeExtension.kt +15 -2
- package/android/detox/src/full/java/com/wix/detox/reactnative/ReactNativeIdlingResources.kt +43 -38
- package/index.d.ts +58 -40
- package/internals.d.ts +63 -15
- package/local-cli/cli.js +1 -1
- package/local-cli/rebuild-framework-cache.js +1 -1
- package/local-cli/test.js +3 -2
- package/local-cli/test.test.js +1 -1
- package/local-cli/testCommand/TestRunnerCommand.js +10 -7
- package/package.json +5 -4
- package/runners/jest/globalSetup.js +1 -1
- package/runners/jest/globalTeardown.js +1 -1
- package/runners/jest/testEnvironment/index.js +36 -18
- package/runners/jest/testEnvironment/listeners/DetoxCoreListener.js +76 -41
- package/runners/jest/testEnvironment/listeners/SpecReporter.js +1 -1
- package/runners/jest/testEnvironment/listeners/WorkerAssignReporter.js +1 -1
- package/src/DetoxWorker.js +4 -7
- package/src/android/core/NativeElement.js +56 -20
- package/src/android/core/NativeExpect.js +28 -9
- package/src/android/interactions/native.js +24 -18
- package/src/artifacts/ArtifactsManager.js +8 -23
- package/src/artifacts/instruments/ios/SimulatorInstrumentsRecording.js +3 -3
- package/src/artifacts/log/ios/SimulatorLogRecording.js +1 -1
- package/src/artifacts/screenshot/SimulatorScreenshotPlugin.js +1 -1
- package/src/artifacts/templates/artifact/Artifact.js +1 -1
- package/src/artifacts/templates/plugin/ArtifactPlugin.js +1 -1
- package/src/artifacts/timeline/TimelineContextTypes.js +7 -0
- package/src/artifacts/utils/temporaryPath.js +18 -7
- package/src/artifacts/video/SimulatorRecordVideoPlugin.js +1 -1
- package/src/client/AsyncWebSocket.js +8 -17
- package/src/client/Client.js +19 -2
- package/src/configuration/collectCliConfig.js +1 -1
- package/src/configuration/composeDeviceConfig.js +1 -1
- package/src/configuration/composeLoggerConfig.js +17 -8
- package/src/configuration/composeRunnerConfig.js +1 -1
- package/src/configuration/index.js +5 -1
- package/src/configuration/loadExternalConfig.js +1 -1
- package/src/devices/allocation/DeviceAllocator.js +3 -2
- package/src/devices/allocation/drivers/android/emulator/AVDValidator.js +1 -1
- package/src/devices/allocation/drivers/android/emulator/EmulatorAllocDriver.js +3 -2
- package/src/devices/allocation/drivers/android/emulator/EmulatorAllocationHelper.js +1 -1
- package/src/devices/allocation/drivers/android/emulator/EmulatorLauncher.js +3 -2
- package/src/devices/allocation/drivers/android/emulator/EmulatorVersionResolver.js +4 -6
- package/src/devices/allocation/drivers/android/emulator/launchEmulatorProcess.js +1 -1
- package/src/devices/allocation/drivers/android/genycloud/GenyInstanceAllocationHelper.js +1 -1
- package/src/devices/common/drivers/android/genycloud/services/GenyInstanceNaming.js +3 -3
- package/src/devices/common/drivers/android/genycloud/services/GenyRecipesService.js +1 -1
- package/src/devices/common/drivers/android/tools/EmulatorTelnet.js +1 -1
- package/src/devices/common/drivers/android/tools/FreeDeviceFinder.js +1 -1
- package/src/devices/common/drivers/android/tools/MonitoredInstrumentation.js +1 -1
- package/src/devices/common/drivers/ios/tools/AppleSimUtils.js +4 -2
- package/src/devices/lifecycle/GenyGlobalLifecycleHandler.js +9 -13
- package/src/devices/runtime/RuntimeDevice.js +9 -12
- package/src/devices/runtime/drivers/DeviceDriverBase.js +1 -1
- package/src/devices/runtime/drivers/android/AndroidDriver.js +10 -2
- package/src/devices/runtime/drivers/ios/SimulatorDriver.js +1 -1
- package/src/ios/expectTwo.js +152 -67
- package/src/ipc/IPCClient.js +3 -8
- package/src/ipc/IPCServer.js +11 -11
- package/src/ipc/{state.js → SessionState.js} +23 -50
- package/src/logger/DetoxLogger.js +268 -155
- package/src/logger/index.js +4 -0
- package/src/logger/utils/BunyanLogger.js +72 -0
- package/src/logger/utils/CategoryThreadDispatcher.js +58 -0
- package/src/logger/utils/MessageStack.js +24 -0
- package/src/logger/{TraceThreadDispatcher.js → utils/ThreadDispatcher.js} +34 -5
- package/src/logger/{customConsoleLogger.js → utils/customConsoleLogger.js} +4 -4
- package/src/logger/utils/sanitizeBunyanContext.js +28 -0
- package/src/logger/utils/tracerLegacy.js +48 -0
- package/src/realms/DetoxContext.js +65 -57
- package/src/realms/DetoxInternalsFacade.js +7 -5
- package/src/realms/DetoxPrimaryContext.js +125 -40
- package/src/realms/DetoxSecondaryContext.js +24 -29
- package/src/server/DetoxConnection.js +18 -23
- package/src/server/DetoxServer.js +7 -10
- package/src/server/DetoxSession.js +6 -6
- package/src/server/DetoxSessionManager.js +1 -1
- package/src/server/handlers/RegisteredConnectionHandler.js +1 -2
- package/src/symbols.js +12 -8
- package/src/utils/childProcess/exec.js +1 -1
- package/src/utils/childProcess/spawn.js +1 -1
- package/src/utils/errorUtils.js +4 -3
- package/src/utils/invocationTraceDescriptions.js +43 -0
- package/src/utils/streamUtils.js +10 -11
- package/src/utils/trace.js +2 -18
- package/src/utils/traceMethods.js +15 -0
- package/Detox-android/com/wix/detox/20.0.4-breaking.new-global-lifecycle.0/detox-20.0.4-breaking.new-global-lifecycle.0-javadoc.jar.md5 +0 -1
- package/Detox-android/com/wix/detox/20.0.4-breaking.new-global-lifecycle.0/detox-20.0.4-breaking.new-global-lifecycle.0-javadoc.jar.sha1 +0 -1
- package/Detox-android/com/wix/detox/20.0.4-breaking.new-global-lifecycle.0/detox-20.0.4-breaking.new-global-lifecycle.0-javadoc.jar.sha256 +0 -1
- package/Detox-android/com/wix/detox/20.0.4-breaking.new-global-lifecycle.0/detox-20.0.4-breaking.new-global-lifecycle.0-javadoc.jar.sha512 +0 -1
- package/Detox-android/com/wix/detox/20.0.4-breaking.new-global-lifecycle.0/detox-20.0.4-breaking.new-global-lifecycle.0-sources.jar.md5 +0 -1
- package/Detox-android/com/wix/detox/20.0.4-breaking.new-global-lifecycle.0/detox-20.0.4-breaking.new-global-lifecycle.0-sources.jar.sha1 +0 -1
- package/Detox-android/com/wix/detox/20.0.4-breaking.new-global-lifecycle.0/detox-20.0.4-breaking.new-global-lifecycle.0-sources.jar.sha256 +0 -1
- package/Detox-android/com/wix/detox/20.0.4-breaking.new-global-lifecycle.0/detox-20.0.4-breaking.new-global-lifecycle.0-sources.jar.sha512 +0 -1
- package/Detox-android/com/wix/detox/20.0.4-breaking.new-global-lifecycle.0/detox-20.0.4-breaking.new-global-lifecycle.0.aar +0 -0
- package/Detox-android/com/wix/detox/20.0.4-breaking.new-global-lifecycle.0/detox-20.0.4-breaking.new-global-lifecycle.0.aar.md5 +0 -1
- package/Detox-android/com/wix/detox/20.0.4-breaking.new-global-lifecycle.0/detox-20.0.4-breaking.new-global-lifecycle.0.aar.sha1 +0 -1
- package/Detox-android/com/wix/detox/20.0.4-breaking.new-global-lifecycle.0/detox-20.0.4-breaking.new-global-lifecycle.0.aar.sha256 +0 -1
- package/Detox-android/com/wix/detox/20.0.4-breaking.new-global-lifecycle.0/detox-20.0.4-breaking.new-global-lifecycle.0.aar.sha512 +0 -1
- package/Detox-android/com/wix/detox/20.0.4-breaking.new-global-lifecycle.0/detox-20.0.4-breaking.new-global-lifecycle.0.pom.md5 +0 -1
- package/Detox-android/com/wix/detox/20.0.4-breaking.new-global-lifecycle.0/detox-20.0.4-breaking.new-global-lifecycle.0.pom.sha1 +0 -1
- package/Detox-android/com/wix/detox/20.0.4-breaking.new-global-lifecycle.0/detox-20.0.4-breaking.new-global-lifecycle.0.pom.sha256 +0 -1
- package/Detox-android/com/wix/detox/20.0.4-breaking.new-global-lifecycle.0/detox-20.0.4-breaking.new-global-lifecycle.0.pom.sha512 +0 -1
- package/src/logger/DetoxTraceEventBuilder.js +0 -21
- package/src/logger/DetoxTracer.js +0 -133
- package/src/utils/ChromeTracingExporter.js +0 -54
@@ -5,6 +5,7 @@ const tempfile = require('tempfile');
|
|
5
5
|
|
6
6
|
const DetoxRuntimeError = require('../../errors/DetoxRuntimeError');
|
7
7
|
const invoke = require('../../invoke');
|
8
|
+
const { actionDescription } = require('../../utils/invocationTraceDescriptions');
|
8
9
|
const actions = require('../actions/native');
|
9
10
|
const DetoxMatcherApi = require('../espressoapi/DetoxMatcher');
|
10
11
|
const { ActionInteraction } = require('../interactions/native');
|
@@ -18,12 +19,11 @@ class NativeElement {
|
|
18
19
|
}
|
19
20
|
|
20
21
|
_selectElementWithMatcher(matcher) {
|
21
|
-
// if (!(matcher instanceof NativeMatcher)) throw new DetoxRuntimeError(`Element _selectElementWithMatcher argument must be a valid NativeMatcher, got ${typeof matcher}`);
|
22
22
|
this._call = invoke.call(invoke.Espresso, 'onView', matcher._call);
|
23
23
|
}
|
24
24
|
|
25
25
|
atIndex(index) {
|
26
|
-
if (typeof index !== 'number') throw new DetoxRuntimeError(`Element atIndex argument must be a number, got ${typeof index}`);
|
26
|
+
if (typeof index !== 'number') throw new DetoxRuntimeError({ message: `Element atIndex argument must be a number, got ${typeof index}` });
|
27
27
|
const matcher = this._originalMatcher;
|
28
28
|
this._originalMatcher._call = invoke.callDirectly(DetoxMatcherApi.matcherForAtIndex(index, matcher._call.value));
|
29
29
|
|
@@ -32,56 +32,84 @@ class NativeElement {
|
|
32
32
|
}
|
33
33
|
|
34
34
|
async tap(value) {
|
35
|
-
|
35
|
+
const action = new actions.TapAction(value);
|
36
|
+
const traceDescription = actionDescription.tapAtPoint(value);
|
37
|
+
return await new ActionInteraction(this._invocationManager, this, action, traceDescription).execute();
|
36
38
|
}
|
37
39
|
|
38
40
|
async tapAtPoint(value) {
|
39
|
-
|
41
|
+
const action = new actions.TapAtPointAction(value);
|
42
|
+
const traceDescription = actionDescription.tapAtPoint(value);
|
43
|
+
return await new ActionInteraction(this._invocationManager, this, action, traceDescription).execute();
|
40
44
|
}
|
41
45
|
|
42
46
|
async longPress() {
|
43
|
-
|
47
|
+
const action = new actions.LongPressAction();
|
48
|
+
const traceDescription = actionDescription.longPress();
|
49
|
+
return await new ActionInteraction(this._invocationManager, this, action, traceDescription).execute();
|
44
50
|
}
|
45
51
|
|
46
52
|
async multiTap(times) {
|
47
|
-
|
53
|
+
if (typeof times !== 'number') throw new Error('times should be a number, but got ' + (times + (' (' + (typeof times + ')'))));
|
54
|
+
if (times < 1) throw new Error('times should be greater than 0, but got ' + times);
|
55
|
+
|
56
|
+
const action = new actions.MultiClickAction(times);
|
57
|
+
const traceDescription = actionDescription.multiTap(times);
|
58
|
+
return await new ActionInteraction(this._invocationManager, this, action, traceDescription).execute();
|
48
59
|
}
|
49
60
|
|
50
61
|
async tapBackspaceKey() {
|
51
|
-
|
62
|
+
const action = new actions.PressKeyAction(67);
|
63
|
+
const traceDescription = actionDescription.tapBackspaceKey();
|
64
|
+
return await new ActionInteraction(this._invocationManager, this, action, traceDescription).execute();
|
52
65
|
}
|
53
66
|
|
54
67
|
async tapReturnKey() {
|
55
|
-
|
68
|
+
const action = new actions.TypeTextAction('\n');
|
69
|
+
const traceDescription = actionDescription.tapReturnKey();
|
70
|
+
return await new ActionInteraction(this._invocationManager, this, action, traceDescription).execute();
|
56
71
|
}
|
57
72
|
|
58
73
|
async typeText(value) {
|
59
|
-
|
74
|
+
const action = new actions.TypeTextAction(value);
|
75
|
+
const traceDescription = actionDescription.typeText(value);
|
76
|
+
return await new ActionInteraction(this._invocationManager, this, action, traceDescription).execute();
|
60
77
|
}
|
61
78
|
|
62
79
|
async replaceText(value) {
|
63
|
-
|
80
|
+
const action = new actions.ReplaceTextAction(value);
|
81
|
+
const traceDescription = actionDescription.replaceText(value);
|
82
|
+
return await new ActionInteraction(this._invocationManager, this, action, traceDescription).execute();
|
64
83
|
}
|
65
84
|
|
66
85
|
async clearText() {
|
67
|
-
|
86
|
+
const action = new actions.ClearTextAction();
|
87
|
+
const traceDescription = actionDescription.clearText();
|
88
|
+
return await new ActionInteraction(this._invocationManager, this, action, traceDescription).execute();
|
68
89
|
}
|
69
90
|
|
70
91
|
async scroll(amount, direction = 'down', startPositionX, startPositionY) {
|
71
|
-
|
72
|
-
|
73
|
-
return await new ActionInteraction(this._invocationManager, this,
|
92
|
+
const action = new actions.ScrollAmountAction(direction, amount, startPositionX, startPositionY);
|
93
|
+
const traceDescription = actionDescription.scroll(amount, direction, startPositionX, startPositionY);
|
94
|
+
return await new ActionInteraction(this._invocationManager, this, action, traceDescription).execute();
|
74
95
|
}
|
75
96
|
|
76
97
|
async scrollTo(edge) {
|
77
98
|
// override the user's element selection with an extended matcher that looks for UIScrollView children
|
78
99
|
this._selectElementWithMatcher(this._originalMatcher._extendToDescendantScrollViews());
|
79
|
-
|
100
|
+
|
101
|
+
const action = new actions.ScrollEdgeAction(edge);
|
102
|
+
const traceDescription = actionDescription.scrollTo(edge);
|
103
|
+
return await new ActionInteraction(this._invocationManager, this, action, traceDescription).execute();
|
80
104
|
}
|
81
105
|
|
82
106
|
async scrollToIndex(index) {
|
107
|
+
// override the user's element selection with an extended matcher that looks for UIScrollView children
|
83
108
|
this._selectElementWithMatcher(this._originalMatcher._extendToDescendantScrollViews());
|
84
|
-
|
109
|
+
|
110
|
+
const action = new actions.ScrollToIndex(index);
|
111
|
+
const traceDescription = actionDescription.scrollToIndex(index);
|
112
|
+
return await new ActionInteraction(this._invocationManager, this, action, traceDescription).execute();
|
85
113
|
}
|
86
114
|
|
87
115
|
/**
|
@@ -96,13 +124,17 @@ class NativeElement {
|
|
96
124
|
|
97
125
|
// override the user's element selection with an extended matcher that avoids RN issues with RCTScrollView
|
98
126
|
this._selectElementWithMatcher(this._originalMatcher._avoidProblematicReactNativeElements());
|
127
|
+
|
99
128
|
const action = new actions.SwipeAction(direction, speed, normalizedSwipeOffset, normalizedStartingPointX, normalizedStartingPointY);
|
100
|
-
|
129
|
+
const traceDescription = actionDescription.swipe(direction, speed, normalizedSwipeOffset, normalizedStartingPointX, normalizedStartingPointY);
|
130
|
+
return await new ActionInteraction(this._invocationManager, this, action, traceDescription).execute();
|
101
131
|
}
|
102
132
|
|
103
133
|
async takeScreenshot(screenshotName) {
|
104
134
|
// TODO this should be moved to a lower-layer handler of this use-case
|
105
|
-
const
|
135
|
+
const action = new actions.TakeElementScreenshot();
|
136
|
+
const traceDescription = actionDescription.takeScreenshot(screenshotName);
|
137
|
+
const resultBase64 = await new ActionInteraction(this._invocationManager, this, action, traceDescription).execute();
|
106
138
|
const filePath = tempfile('detox.element-screenshot.png');
|
107
139
|
await fs.writeFile(filePath, resultBase64, 'base64');
|
108
140
|
|
@@ -115,12 +147,16 @@ class NativeElement {
|
|
115
147
|
}
|
116
148
|
|
117
149
|
async getAttributes() {
|
118
|
-
const
|
150
|
+
const action = new actions.GetAttributes();
|
151
|
+
const traceDescription = actionDescription.getAttributes();
|
152
|
+
const result = await new ActionInteraction(this._invocationManager, this, action, traceDescription).execute();
|
119
153
|
return JSON.parse(result);
|
120
154
|
}
|
121
155
|
|
122
156
|
async adjustSliderToPosition(newPosition) {
|
123
|
-
|
157
|
+
const action = new actions.AdjustSliderToPosition(newPosition);
|
158
|
+
const traceDescription = actionDescription.adjustSliderToPosition(newPosition);
|
159
|
+
return await new ActionInteraction(this._invocationManager, this, action, traceDescription).execute();
|
124
160
|
}
|
125
161
|
}
|
126
162
|
|
@@ -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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
19
|
-
|
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
|
-
|
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
|
-
|
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
|
}
|
@@ -1,14 +1,13 @@
|
|
1
1
|
const EventEmitter = require('events');
|
2
2
|
const path = require('path');
|
3
|
-
const util = require('util');
|
4
3
|
|
5
4
|
const fs = require('fs-extra');
|
6
5
|
const _ = require('lodash');
|
7
6
|
|
8
7
|
const DetoxRuntimeError = require('../errors/DetoxRuntimeError');
|
9
|
-
const log = require('../utils/logger').child({
|
8
|
+
const log = require('../utils/logger').child({ cat: 'artifacts-manager,artifact' });
|
10
9
|
const resolveModuleFromPath = require('../utils/resolveModuleFromPath');
|
11
|
-
const
|
10
|
+
const traceMethods = require('../utils/traceMethods');
|
12
11
|
|
13
12
|
const FileArtifact = require('./templates/artifact/FileArtifact');
|
14
13
|
const ArtifactPathBuilder = require('./utils/ArtifactPathBuilder');
|
@@ -23,7 +22,7 @@ class ArtifactsManager extends EventEmitter {
|
|
23
22
|
this._artifactPlugins = {};
|
24
23
|
this._pathBuilder = this._resolveArtifactsPathBuilder(pathBuilder, rootDir);
|
25
24
|
|
26
|
-
traceMethods(
|
25
|
+
traceMethods(log, this, [
|
27
26
|
'onAppReady',
|
28
27
|
'onBeforeCleanup',
|
29
28
|
'onBeforeLaunchApp',
|
@@ -228,27 +227,21 @@ class ArtifactsManager extends EventEmitter {
|
|
228
227
|
}
|
229
228
|
|
230
229
|
async _callSinglePlugin(pluginId, methodName, ...args) {
|
231
|
-
const callSignature = this._composeCallSignature('artifactsManager', methodName, args);
|
232
|
-
log.trace(Object.assign({ event: 'ARTIFACTS_LIFECYCLE', fn: methodName }, ...args), callSignature);
|
233
|
-
|
234
230
|
const plugin = this._artifactPlugins[pluginId];
|
235
231
|
try {
|
236
232
|
await plugin[methodName](...args);
|
237
233
|
} catch (e) {
|
238
|
-
this._unhandledPluginExceptionHandler(e, { plugin, methodName
|
234
|
+
this._unhandledPluginExceptionHandler(e, { plugin, methodName });
|
239
235
|
}
|
240
236
|
}
|
241
237
|
|
242
238
|
async _callPlugins(strategy, methodName, ...args) {
|
243
|
-
const callSignature = this._composeCallSignature('artifactsManager', methodName, args);
|
244
|
-
log.trace(Object.assign({ event: 'ARTIFACTS_LIFECYCLE', fn: methodName }, ...args), callSignature);
|
245
|
-
|
246
239
|
for (const pluginGroup of this._groupPlugins(strategy)) {
|
247
240
|
await Promise.all(pluginGroup.map(async (plugin) => {
|
248
241
|
try {
|
249
242
|
await plugin[methodName](...args);
|
250
243
|
} catch (e) {
|
251
|
-
this._unhandledPluginExceptionHandler(e, { plugin, methodName
|
244
|
+
this._unhandledPluginExceptionHandler(e, { plugin, methodName });
|
252
245
|
}
|
253
246
|
}));
|
254
247
|
}
|
@@ -278,28 +271,20 @@ class ArtifactsManager extends EventEmitter {
|
|
278
271
|
}
|
279
272
|
}
|
280
273
|
|
281
|
-
|
282
|
-
const argsString = args.map(arg => util.inspect(arg)).join(', ');
|
283
|
-
return `${object}.${methodName}(${argsString})`;
|
284
|
-
}
|
285
|
-
|
286
|
-
_unhandledPluginExceptionHandler(err, { plugin, methodName, args }) {
|
274
|
+
_unhandledPluginExceptionHandler(err, { plugin, methodName }) {
|
287
275
|
const logObject = {
|
288
|
-
event: 'ERROR',
|
289
276
|
plugin: plugin.name,
|
290
|
-
err,
|
291
277
|
methodName,
|
278
|
+
err,
|
292
279
|
};
|
293
280
|
|
294
|
-
|
295
|
-
log.warn(logObject, `Suppressed error inside function call: ${callSignature}`);
|
281
|
+
log.warn(logObject, `Suppressed error inside function call.`);
|
296
282
|
}
|
297
283
|
|
298
284
|
_idleCallbackErrorHandle(err, caller) {
|
299
285
|
this._unhandledPluginExceptionHandler(err, {
|
300
286
|
plugin: caller,
|
301
287
|
methodName: 'onIdleCallback',
|
302
|
-
args: []
|
303
288
|
});
|
304
289
|
}
|
305
290
|
}
|
@@ -2,7 +2,7 @@
|
|
2
2
|
const fs = require('fs-extra');
|
3
3
|
const _ = require('lodash');
|
4
4
|
|
5
|
-
const log = require('../../../utils/logger').child({
|
5
|
+
const log = require('../../../utils/logger').child({ cat: 'artifact' });
|
6
6
|
const FileArtifact = require('../../templates/artifact/FileArtifact');
|
7
7
|
const InstrumentsArtifactRecording = require('../InstrumentsArtifactRecording');
|
8
8
|
|
@@ -37,9 +37,9 @@ class SimulatorInstrumentsRecording extends InstrumentsArtifactRecording {
|
|
37
37
|
SimulatorInstrumentsRecording.hintAboutDetoxInstruments = _.once(() => {
|
38
38
|
log.warn(`Make sure either:
|
39
39
|
1. You have installed Detox Instruments:
|
40
|
-
https://github.com/wix/DetoxInstruments#installation
|
40
|
+
https://github.com/wix/DetoxInstruments#installation
|
41
41
|
2. You have integrated Detox Instruments in your app:
|
42
|
-
https://github.com/wix/DetoxInstruments/blob/master/Documentation/XcodeIntegrationGuide.md
|
42
|
+
https://github.com/wix/DetoxInstruments/blob/master/Documentation/XcodeIntegrationGuide.md
|
43
43
|
3. You have set the environment variable with your custom Detox Instruments location:
|
44
44
|
export DETOX_INSTRUMENTS_PATH="/path/to/Detox Instruments.app"`);
|
45
45
|
});
|
@@ -2,7 +2,7 @@
|
|
2
2
|
const fs = require('fs-extra');
|
3
3
|
|
4
4
|
const childProcess = require('../../../utils/childProcess');
|
5
|
-
const log = require('../../../utils/logger').child({
|
5
|
+
const log = require('../../../utils/logger').child({ cat: 'artifact' });
|
6
6
|
const sleep = require('../../../utils/sleep');
|
7
7
|
const Artifact = require('../../templates/artifact/Artifact');
|
8
8
|
const FileArtifact = require('../../templates/artifact/FileArtifact');
|
@@ -1,7 +1,7 @@
|
|
1
1
|
const path = require('path');
|
2
2
|
|
3
3
|
const fs = require('../../utils/fsext');
|
4
|
-
const log = require('../../utils/logger').child({
|
4
|
+
const log = require('../../utils/logger').child({ cat: 'artifacts-plugin,artifacts' });
|
5
5
|
const FileArtifact = require('../templates/artifact/FileArtifact');
|
6
6
|
const temporaryPath = require('../utils/temporaryPath');
|
7
7
|
|
@@ -3,7 +3,7 @@
|
|
3
3
|
|
4
4
|
const _ = require('lodash');
|
5
5
|
|
6
|
-
const log = require('../../../utils/logger').child({
|
6
|
+
const log = require('../../../utils/logger').child({ cat: 'artifacts-plugin,artifacts' });
|
7
7
|
|
8
8
|
/***
|
9
9
|
* Almost non-opinionated building block for any artifact type
|
@@ -2,15 +2,26 @@ const path = require('path');
|
|
2
2
|
|
3
3
|
const tempfile = require('tempfile');
|
4
4
|
|
5
|
+
function createTempFileBuilderFn(fileExtension) {
|
6
|
+
/**
|
7
|
+
* @param {string} [basename]
|
8
|
+
*/
|
9
|
+
return (basename) => {
|
10
|
+
return basename
|
11
|
+
? path.join(path.dirname(tempfile()), `${basename}.detox.${fileExtension}`)
|
12
|
+
: tempfile(`.detox.${fileExtension}`);
|
13
|
+
};
|
14
|
+
}
|
15
|
+
|
5
16
|
module.exports = {
|
6
17
|
for: {
|
7
|
-
json: (
|
8
|
-
jsonl: (
|
9
|
-
png: (
|
10
|
-
log: (
|
11
|
-
mp4: (
|
12
|
-
dtxrec: (
|
13
|
-
viewhierarchy: (
|
18
|
+
json: createTempFileBuilderFn('json'),
|
19
|
+
jsonl: createTempFileBuilderFn('jsonl'),
|
20
|
+
png: createTempFileBuilderFn('png'),
|
21
|
+
log: createTempFileBuilderFn('log'),
|
22
|
+
mp4: createTempFileBuilderFn('mp4'),
|
23
|
+
dtxrec: createTempFileBuilderFn('dtxrec'),
|
24
|
+
viewhierarchy: createTempFileBuilderFn('viewhierarchy'),
|
14
25
|
},
|
15
26
|
mask: () => path.join(tempfile(), '..') + path.sep + '*.detox.*',
|
16
27
|
};
|
@@ -1,7 +1,7 @@
|
|
1
1
|
const fs = require('fs-extra');
|
2
2
|
|
3
3
|
const { interruptProcess } = require('../../utils/childProcess');
|
4
|
-
const log = require('../../utils/logger').child({
|
4
|
+
const log = require('../../utils/logger').child({ cat: 'artifacts-plugin,artifact' });
|
5
5
|
const Artifact = require('../templates/artifact/Artifact');
|
6
6
|
const FileArtifact = require('../templates/artifact/FileArtifact');
|
7
7
|
const temporaryPath = require('../utils/temporaryPath');
|
@@ -5,25 +5,16 @@ const WebSocket = require('ws');
|
|
5
5
|
const DetoxInternalError = require('../errors/DetoxInternalError');
|
6
6
|
const DetoxRuntimeError = require('../errors/DetoxRuntimeError');
|
7
7
|
const Deferred = require('../utils/Deferred');
|
8
|
-
const log = require('../utils/logger').child({
|
8
|
+
const log = require('../utils/logger').child({ cat: 'ws-client,ws' });
|
9
9
|
|
10
10
|
const InflightRequest = require('./InflightRequest');
|
11
11
|
|
12
|
-
const EVENTS = {
|
13
|
-
OPEN: Object.freeze({ event: 'WS_OPEN' }),
|
14
|
-
ERROR: Object.freeze({ event: 'WS_ERROR' }),
|
15
|
-
MESSAGE: Object.freeze({ event: 'WS_MESSAGE' }),
|
16
|
-
SEND: Object.freeze({ event: 'WS_SEND' }),
|
17
|
-
LATE_RESPONSE: Object.freeze({ event: 'WS_LATE_RESPONSE' }),
|
18
|
-
};
|
19
|
-
|
20
12
|
const DEFAULT_SEND_OPTIONS = {
|
21
13
|
timeout: 0,
|
22
14
|
};
|
23
15
|
|
24
16
|
class AsyncWebSocket {
|
25
17
|
constructor(url) {
|
26
|
-
this._log = log.child({ url });
|
27
18
|
this._url = url;
|
28
19
|
this._ws = null;
|
29
20
|
this._eventCallbacks = {};
|
@@ -99,9 +90,9 @@ class AsyncWebSocket {
|
|
99
90
|
|
100
91
|
this.handleMultipleNonAtomicPendingActions();
|
101
92
|
|
102
|
-
const
|
103
|
-
|
104
|
-
this._ws.send(
|
93
|
+
const payload = JSON.stringify(message);
|
94
|
+
log.trace({ data: payload }, 'send message');
|
95
|
+
this._ws.send(payload);
|
105
96
|
|
106
97
|
return inFlight.promise;
|
107
98
|
}
|
@@ -157,7 +148,7 @@ class AsyncWebSocket {
|
|
157
148
|
}
|
158
149
|
|
159
150
|
if (!hasPendingActions) {
|
160
|
-
log.error(
|
151
|
+
log.error({ error });
|
161
152
|
}
|
162
153
|
}
|
163
154
|
|
@@ -186,7 +177,7 @@ class AsyncWebSocket {
|
|
186
177
|
* @private
|
187
178
|
*/
|
188
179
|
_onOpen(event) { // eslint-disable-line no-unused-vars
|
189
|
-
|
180
|
+
log.trace(`opened web socket to: ${this._url}`);
|
190
181
|
this._opening.resolve();
|
191
182
|
this._opening = null;
|
192
183
|
}
|
@@ -234,7 +225,7 @@ class AsyncWebSocket {
|
|
234
225
|
const data = event && event.data || null;
|
235
226
|
|
236
227
|
try {
|
237
|
-
|
228
|
+
log.trace({ data }, 'get message');
|
238
229
|
|
239
230
|
const json = JSON.parse(data);
|
240
231
|
if (!json || !json.type) {
|
@@ -259,7 +250,7 @@ class AsyncWebSocket {
|
|
259
250
|
|
260
251
|
if (!handled) {
|
261
252
|
if (this._abortedMessageIds.has(json.messageId)) {
|
262
|
-
log.debug(
|
253
|
+
log.debug({ messageId: json.messageId }, `late response`);
|
263
254
|
} else {
|
264
255
|
throw new DetoxRuntimeError('Unexpected message received over the web socket: ' + json.type);
|
265
256
|
}
|