detox 20.21.0 → 20.21.1-smoke.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.21.0/detox-20.21.0-sources.jar → 20.21.1-smoke.0/detox-20.21.1-smoke.0-sources.jar} +0 -0
- package/Detox-android/com/wix/detox/20.21.1-smoke.0/detox-20.21.1-smoke.0-sources.jar.md5 +1 -0
- package/Detox-android/com/wix/detox/20.21.1-smoke.0/detox-20.21.1-smoke.0-sources.jar.sha1 +1 -0
- package/Detox-android/com/wix/detox/20.21.1-smoke.0/detox-20.21.1-smoke.0-sources.jar.sha256 +1 -0
- package/Detox-android/com/wix/detox/20.21.1-smoke.0/detox-20.21.1-smoke.0-sources.jar.sha512 +1 -0
- package/Detox-android/com/wix/detox/{20.21.0/detox-20.21.0.pom → 20.21.1-smoke.0/detox-20.21.1-smoke.0.pom} +1 -1
- package/Detox-android/com/wix/detox/20.21.1-smoke.0/detox-20.21.1-smoke.0.pom.md5 +1 -0
- package/Detox-android/com/wix/detox/20.21.1-smoke.0/detox-20.21.1-smoke.0.pom.sha1 +1 -0
- package/Detox-android/com/wix/detox/20.21.1-smoke.0/detox-20.21.1-smoke.0.pom.sha256 +1 -0
- package/Detox-android/com/wix/detox/20.21.1-smoke.0/detox-20.21.1-smoke.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-android/com/wix/detox-legacy/{20.21.0/detox-legacy-20.21.0-sources.jar → 20.21.1-smoke.0/detox-legacy-20.21.1-smoke.0-sources.jar} +0 -0
- package/Detox-android/com/wix/detox-legacy/20.21.1-smoke.0/detox-legacy-20.21.1-smoke.0-sources.jar.md5 +1 -0
- package/Detox-android/com/wix/detox-legacy/20.21.1-smoke.0/detox-legacy-20.21.1-smoke.0-sources.jar.sha1 +1 -0
- package/Detox-android/com/wix/detox-legacy/20.21.1-smoke.0/detox-legacy-20.21.1-smoke.0-sources.jar.sha256 +1 -0
- package/Detox-android/com/wix/detox-legacy/20.21.1-smoke.0/detox-legacy-20.21.1-smoke.0-sources.jar.sha512 +1 -0
- package/Detox-android/com/wix/detox-legacy/{20.21.0/detox-legacy-20.21.0.pom → 20.21.1-smoke.0/detox-legacy-20.21.1-smoke.0.pom} +1 -1
- package/Detox-android/com/wix/detox-legacy/20.21.1-smoke.0/detox-legacy-20.21.1-smoke.0.pom.md5 +1 -0
- package/Detox-android/com/wix/detox-legacy/20.21.1-smoke.0/detox-legacy-20.21.1-smoke.0.pom.sha1 +1 -0
- package/Detox-android/com/wix/detox-legacy/20.21.1-smoke.0/detox-legacy-20.21.1-smoke.0.pom.sha256 +1 -0
- package/Detox-android/com/wix/detox-legacy/20.21.1-smoke.0/detox-legacy-20.21.1-smoke.0.pom.sha512 +1 -0
- package/Detox-android/com/wix/detox-legacy/maven-metadata.xml +4 -4
- package/Detox-android/com/wix/detox-legacy/maven-metadata.xml.md5 +1 -1
- package/Detox-android/com/wix/detox-legacy/maven-metadata.xml.sha1 +1 -1
- package/Detox-android/com/wix/detox-legacy/maven-metadata.xml.sha256 +1 -1
- package/Detox-android/com/wix/detox-legacy/maven-metadata.xml.sha512 +1 -1
- package/Detox-ios-framework.tbz +0 -0
- package/Detox-ios-src.tbz +0 -0
- package/Detox-ios-xcuitest.tbz +0 -0
- package/detox.d.ts +78 -1
- package/globals.d.ts +2 -0
- package/local-cli/build-framework-cache.js +19 -11
- package/local-cli/clean-framework-cache.js +19 -14
- package/local-cli/rebuild-framework-cache.js +20 -16
- package/local-cli/utils/frameworkUtils.js +77 -0
- package/package.json +4 -4
- package/scripts/build_framework.ios.sh +26 -60
- package/scripts/build_local_framework.ios.sh +62 -0
- package/scripts/build_local_xcuitest.ios.sh +53 -0
- package/scripts/build_xcuitest.ios.sh +18 -0
- package/scripts/pack_ios.sh +18 -9
- package/scripts/postinstall.js +11 -4
- package/src/android/AndroidExpect.js +5 -0
- package/src/android/matchers/index.js +7 -0
- package/src/ios/XCUITestRunner.js +52 -0
- package/src/ios/expectTwo.js +49 -28
- package/src/ios/system.js +124 -0
- package/src/ios/web.js +3 -4
- package/src/matchers/factories/index.js +15 -8
- package/src/utils/assertArgument.js +11 -2
- package/src/utils/environment.js +34 -14
- package/src/utils/invocationTraceDescriptions.js +4 -0
- package/Detox-android/com/wix/detox/20.21.0/detox-20.21.0-sources.jar.md5 +0 -1
- package/Detox-android/com/wix/detox/20.21.0/detox-20.21.0-sources.jar.sha1 +0 -1
- package/Detox-android/com/wix/detox/20.21.0/detox-20.21.0-sources.jar.sha256 +0 -1
- package/Detox-android/com/wix/detox/20.21.0/detox-20.21.0-sources.jar.sha512 +0 -1
- package/Detox-android/com/wix/detox/20.21.0/detox-20.21.0.pom.md5 +0 -1
- package/Detox-android/com/wix/detox/20.21.0/detox-20.21.0.pom.sha1 +0 -1
- package/Detox-android/com/wix/detox/20.21.0/detox-20.21.0.pom.sha256 +0 -1
- package/Detox-android/com/wix/detox/20.21.0/detox-20.21.0.pom.sha512 +0 -1
- package/Detox-android/com/wix/detox-legacy/20.21.0/detox-legacy-20.21.0-sources.jar.md5 +0 -1
- package/Detox-android/com/wix/detox-legacy/20.21.0/detox-legacy-20.21.0-sources.jar.sha1 +0 -1
- package/Detox-android/com/wix/detox-legacy/20.21.0/detox-legacy-20.21.0-sources.jar.sha256 +0 -1
- package/Detox-android/com/wix/detox-legacy/20.21.0/detox-legacy-20.21.0-sources.jar.sha512 +0 -1
- package/Detox-android/com/wix/detox-legacy/20.21.0/detox-legacy-20.21.0.pom.md5 +0 -1
- package/Detox-android/com/wix/detox-legacy/20.21.0/detox-legacy-20.21.0.pom.sha1 +0 -1
- package/Detox-android/com/wix/detox-legacy/20.21.0/detox-legacy-20.21.0.pom.sha256 +0 -1
- package/Detox-android/com/wix/detox-legacy/20.21.0/detox-legacy-20.21.0.pom.sha512 +0 -1
- package/Detox-ios.tbz +0 -0
- package/scripts/build_universal_framework.sh +0 -14
- package/scripts/build_universal_framework_legacy.sh +0 -76
- package/scripts/build_universal_framework_modern.sh +0 -28
- /package/Detox-android/com/wix/detox/{20.21.0/detox-20.21.0.aar → 20.21.1-smoke.0/detox-20.21.1-smoke.0.aar} +0 -0
- /package/Detox-android/com/wix/detox/{20.21.0/detox-20.21.0.aar.md5 → 20.21.1-smoke.0/detox-20.21.1-smoke.0.aar.md5} +0 -0
- /package/Detox-android/com/wix/detox/{20.21.0/detox-20.21.0.aar.sha1 → 20.21.1-smoke.0/detox-20.21.1-smoke.0.aar.sha1} +0 -0
- /package/Detox-android/com/wix/detox/{20.21.0/detox-20.21.0.aar.sha256 → 20.21.1-smoke.0/detox-20.21.1-smoke.0.aar.sha256} +0 -0
- /package/Detox-android/com/wix/detox/{20.21.0/detox-20.21.0.aar.sha512 → 20.21.1-smoke.0/detox-20.21.1-smoke.0.aar.sha512} +0 -0
- /package/Detox-android/com/wix/detox-legacy/{20.21.0/detox-legacy-20.21.0.aar → 20.21.1-smoke.0/detox-legacy-20.21.1-smoke.0.aar} +0 -0
- /package/Detox-android/com/wix/detox-legacy/{20.21.0/detox-legacy-20.21.0.aar.md5 → 20.21.1-smoke.0/detox-legacy-20.21.1-smoke.0.aar.md5} +0 -0
- /package/Detox-android/com/wix/detox-legacy/{20.21.0/detox-legacy-20.21.0.aar.sha1 → 20.21.1-smoke.0/detox-legacy-20.21.1-smoke.0.aar.sha1} +0 -0
- /package/Detox-android/com/wix/detox-legacy/{20.21.0/detox-legacy-20.21.0.aar.sha256 → 20.21.1-smoke.0/detox-legacy-20.21.1-smoke.0.aar.sha256} +0 -0
- /package/Detox-android/com/wix/detox-legacy/{20.21.0/detox-legacy-20.21.0.aar.sha512 → 20.21.1-smoke.0/detox-legacy-20.21.1-smoke.0.aar.sha512} +0 -0
@@ -0,0 +1,62 @@
|
|
1
|
+
#!/bin/bash -e
|
2
|
+
|
3
|
+
# Ensure Xcode is installed or print a warning message and return.
|
4
|
+
xcodebuild -version &>/dev/null || { echo "WARNING: Xcode is not installed on this machine. Skipping iOS framework build phase"; exit 0; }
|
5
|
+
|
6
|
+
detoxRootPath="$(dirname "$(dirname "$0")")"
|
7
|
+
detoxVersion=`node -p "require('${detoxRootPath}/package.json').version"`
|
8
|
+
|
9
|
+
sha1=`(echo "${detoxVersion}" && xcodebuild -version) | shasum | awk '{print $1}' #"${2}"`
|
10
|
+
detoxFrameworkDirPath="$HOME/Library/Detox/ios/framework/${sha1}"
|
11
|
+
detoxFrameworkPath="${detoxFrameworkDirPath}/Detox.framework"
|
12
|
+
|
13
|
+
|
14
|
+
function prepareAndBuildFramework () {
|
15
|
+
if [ -d "$detoxRootPath"/ios ]; then
|
16
|
+
detoxSourcePath="${detoxRootPath}"/ios
|
17
|
+
echo "Dev mode, building from ${detoxSourcePath}"
|
18
|
+
buildFramework "${detoxSourcePath}"
|
19
|
+
else
|
20
|
+
extractFramework
|
21
|
+
fi
|
22
|
+
}
|
23
|
+
|
24
|
+
function extractFramework () {
|
25
|
+
echo "Extracting Detox framework..."
|
26
|
+
mkdir -p "${detoxFrameworkDirPath}"
|
27
|
+
tar -xjf "${detoxRootPath}"/Detox-ios-framework.tbz -C "${detoxFrameworkDirPath}"
|
28
|
+
}
|
29
|
+
|
30
|
+
function buildFramework () {
|
31
|
+
detoxSourcePath="${1}"
|
32
|
+
echo "Building Detox.framework from ${detoxSourcePath} into ${detoxFrameworkDirPath}"
|
33
|
+
mkdir -p "${detoxFrameworkDirPath}"
|
34
|
+
logPath="${detoxFrameworkDirPath}"/detox_ios.log
|
35
|
+
echo "Build log: ${logPath}"
|
36
|
+
echo -n "" > "${logPath}"
|
37
|
+
"${detoxRootPath}"/scripts/build_framework.ios.sh "${detoxSourcePath}"/Detox.xcodeproj "${detoxFrameworkDirPath}" &> "${logPath}" || {
|
38
|
+
echo -e "#################################\nError building Detox.framework:\n----------------------------------\n"
|
39
|
+
cat "${logPath}"
|
40
|
+
echo "#################################"
|
41
|
+
exit 1
|
42
|
+
}
|
43
|
+
}
|
44
|
+
|
45
|
+
function main () {
|
46
|
+
if [ -d "${detoxFrameworkDirPath}" ]; then
|
47
|
+
if [ ! -d "${detoxFrameworkPath}" ]; then
|
48
|
+
echo "${detoxFrameworkDirPath} was found, but could not find Detox.framework inside it. This means that the Detox framework build process was interrupted.
|
49
|
+
deleting ${detoxFrameworkDirPath} and trying to rebuild."
|
50
|
+
rm -rf "${detoxFrameworkDirPath}"
|
51
|
+
prepareAndBuildFramework
|
52
|
+
else
|
53
|
+
echo "Detox.framework exists, skipping..."
|
54
|
+
fi
|
55
|
+
else
|
56
|
+
prepareAndBuildFramework
|
57
|
+
fi
|
58
|
+
|
59
|
+
echo "Done"
|
60
|
+
}
|
61
|
+
|
62
|
+
main
|
@@ -0,0 +1,53 @@
|
|
1
|
+
#!/bin/bash -e
|
2
|
+
|
3
|
+
# Ensure Xcode is installed or print a warning message and return.
|
4
|
+
xcodebuild -version &>/dev/null || { echo "WARNING: Xcode is not installed on this machine. Skipping iOS xctest runner build phase"; exit 0; }
|
5
|
+
|
6
|
+
detoxRootPath="$(dirname "$(dirname "$0")")"
|
7
|
+
detoxVersion=`node -p "require('${detoxRootPath}/package.json').version"`
|
8
|
+
|
9
|
+
sha1=`(echo "${detoxVersion}" && xcodebuild -version) | shasum | awk '{print $1}' #"${2}"`
|
10
|
+
detoxXctestRunnerDirPath="$HOME/Library/Detox/ios/xcuitest-runner/${sha1}"
|
11
|
+
|
12
|
+
function prepareAndBuildXctestRunner () {
|
13
|
+
if [ -d "$detoxRootPath"/ios ]; then
|
14
|
+
detoxSourcePath="${detoxRootPath}"/ios
|
15
|
+
echo "Dev mode, building XCUITest runner from ${detoxSourcePath}"
|
16
|
+
buildXctestRunner "${detoxSourcePath}"
|
17
|
+
else
|
18
|
+
extractXctestRunner
|
19
|
+
fi
|
20
|
+
}
|
21
|
+
|
22
|
+
function extractXctestRunner () {
|
23
|
+
echo "Extracting Detox XCUITest runner..."
|
24
|
+
mkdir -p "${detoxXctestRunnerDirPath}"
|
25
|
+
tar -xjf "${detoxRootPath}"/Detox-ios-xcuitest.tbz -C "${detoxXctestRunnerDirPath}"
|
26
|
+
}
|
27
|
+
|
28
|
+
function buildXctestRunner () {
|
29
|
+
detoxSourcePath="${1}"
|
30
|
+
echo "Building XCUITest runner from ${detoxSourcePath} into ${detoxXctestRunnerDirPath}"
|
31
|
+
mkdir -p "${detoxXctestRunnerDirPath}"
|
32
|
+
logPath="${detoxXctestRunnerDirPath}"/detox_ios_xcuitest.log
|
33
|
+
echo "Build log: ${logPath}"
|
34
|
+
echo -n "" > "${logPath}"
|
35
|
+
"${detoxRootPath}"/scripts/build_xcuitest.ios.sh "${detoxSourcePath}"/DetoxXCUITestRunner/DetoxXCUITestRunner.xcodeproj "${detoxXctestRunnerDirPath}" &> "${logPath}" || {
|
36
|
+
echo -e "#################################\nError building DetoxXCUITestRunner.xctestrun:\n----------------------------------\n"
|
37
|
+
cat "${logPath}"
|
38
|
+
echo "#################################"
|
39
|
+
exit 1
|
40
|
+
}
|
41
|
+
}
|
42
|
+
|
43
|
+
function main () {
|
44
|
+
if [ ! -d "${detoxXctestRunnerDirPath}" ]; then
|
45
|
+
prepareAndBuildXctestRunner
|
46
|
+
else
|
47
|
+
echo "XCUITest-runner exists, skipping..."
|
48
|
+
fi
|
49
|
+
|
50
|
+
echo "Done"
|
51
|
+
}
|
52
|
+
|
53
|
+
main
|
@@ -0,0 +1,18 @@
|
|
1
|
+
#!/bin/bash -e
|
2
|
+
|
3
|
+
XCODEPROJ=$1
|
4
|
+
XCUITEST_OUTPUT_DIR=$2
|
5
|
+
CONFIGURATION=Release
|
6
|
+
PROJECT_NAME=DetoxXCUITestRunner
|
7
|
+
|
8
|
+
# Clean up the output directory
|
9
|
+
|
10
|
+
rm -fr "${XCUITEST_OUTPUT_DIR}"
|
11
|
+
|
12
|
+
# Make sure the output directory exists
|
13
|
+
|
14
|
+
mkdir -p "${XCUITEST_OUTPUT_DIR}"
|
15
|
+
|
16
|
+
# Build Simulator version
|
17
|
+
|
18
|
+
xcodebuild -project "${XCODEPROJ}" -scheme "${PROJECT_NAME}" -UseNewBuildSystem="YES" -configuration "${CONFIGURATION}" -sdk iphonesimulator -destination 'generic/platform=iOS Simulator' -derivedDataPath "${XCUITEST_OUTPUT_DIR}" build-for-testing -quiet
|
package/scripts/pack_ios.sh
CHANGED
@@ -1,23 +1,32 @@
|
|
1
1
|
#!/bin/bash -e
|
2
2
|
|
3
3
|
rm -rf Detox-ios-src.tbz
|
4
|
-
rm -rf Detox-ios.tbz
|
4
|
+
rm -rf Detox-ios-framework.tbz
|
5
|
+
rm -rf Detox-ios-xcuitest.tbz
|
5
6
|
rm -rf build_temp
|
6
7
|
|
7
8
|
find ./ios -name Build -type d -exec rm -rf {} \;
|
8
9
|
|
9
|
-
#Package sources
|
10
|
-
pushd . &> /dev/null
|
10
|
+
# Package sources
|
11
11
|
cd ios
|
12
12
|
tar --exclude-from=.tbzignore -cjf ../Detox-ios-src.tbz .
|
13
|
-
|
13
|
+
cd ..
|
14
14
|
|
15
|
-
|
15
|
+
echo "Packaging iOS sources and prebuilt frameworks"
|
16
|
+
|
17
|
+
# Create temp build directory
|
16
18
|
mkdir build_temp
|
17
|
-
|
18
|
-
|
19
|
+
|
20
|
+
# Package prebuilt framework
|
21
|
+
scripts/build_framework.ios.sh "ios/Detox.xcodeproj" "build_temp"
|
22
|
+
|
23
|
+
# Package prebuilt XCUITest runner
|
24
|
+
scripts/build_xcuitest.ios.sh "ios/DetoxXCUITestRunner/DetoxXCUITestRunner.xcodeproj" "build_temp"
|
25
|
+
|
19
26
|
cd build_temp
|
20
|
-
tar --exclude-from=../ios/.tbzignore -cjf ../Detox-ios.tbz .
|
21
|
-
|
27
|
+
tar --exclude-from=../ios/.tbzignore -cjf ../Detox-ios-xcuitest.tbz .
|
28
|
+
tar --exclude-from=../ios/.tbzignore -cjf ../Detox-ios-framework.tbz .
|
29
|
+
cd ..
|
22
30
|
|
31
|
+
# Cleanup
|
23
32
|
rm -fr build_temp
|
package/scripts/postinstall.js
CHANGED
@@ -1,8 +1,15 @@
|
|
1
|
+
const { platform, env } = process;
|
2
|
+
|
1
3
|
const { setGradleVersionByRNVersion } = require('./updateGradle');
|
2
|
-
if (process.platform === 'darwin' && !process.env.DETOX_DISABLE_POSTINSTALL) {
|
3
|
-
require('child_process').execFileSync(`${__dirname}/build_framework.ios.sh`, {
|
4
|
-
stdio: 'inherit'
|
5
|
-
});
|
6
4
|
|
5
|
+
const isDarwin = platform === 'darwin';
|
6
|
+
const shouldInstallDetox = !env.DETOX_DISABLE_POSTINSTALL;
|
7
|
+
|
8
|
+
if (isDarwin && shouldInstallDetox) {
|
9
|
+
const execFileSync = require('child_process').execFileSync;
|
10
|
+
|
11
|
+
execFileSync(`${__dirname}/build_local_framework.ios.sh`, { stdio: 'inherit' });
|
12
|
+
execFileSync(`${__dirname}/build_local_xcuitest.ios.sh`, { stdio: 'inherit' });
|
7
13
|
}
|
14
|
+
|
8
15
|
setGradleVersionByRNVersion();
|
@@ -21,6 +21,7 @@ class AndroidExpect {
|
|
21
21
|
this.waitFor = this.waitFor.bind(this);
|
22
22
|
this.web = this.web.bind(this);
|
23
23
|
this.web.element = (...args) => this.web().element(...args);
|
24
|
+
this.system = { element: (...args) => this.systemElement(...args) };
|
24
25
|
}
|
25
26
|
|
26
27
|
element(matcher) {
|
@@ -45,6 +46,10 @@ class AndroidExpect {
|
|
45
46
|
throw new DetoxRuntimeError(`web() argument is invalid, expected a native matcher, but got ${typeof element}`);
|
46
47
|
}
|
47
48
|
|
49
|
+
systemElement(_matcher) {
|
50
|
+
throw new DetoxRuntimeError('System interactions are not supported on Android, use UiDevice APIs directly instead');
|
51
|
+
}
|
52
|
+
|
48
53
|
expect(element) {
|
49
54
|
if (element instanceof WebElement) return new WebExpectElement(this._invocationManager, element);
|
50
55
|
if (element instanceof NativeElement) return new NativeExpectElement(this._invocationManager, element);
|
@@ -1,3 +1,5 @@
|
|
1
|
+
const { DetoxRuntimeError } = require('../../errors');
|
2
|
+
|
1
3
|
const native = require('./native');
|
2
4
|
const web = require('./web');
|
3
5
|
|
@@ -20,4 +22,9 @@ module.exports = {
|
|
20
22
|
href: (value) => new web.LinkTextMatcher(value),
|
21
23
|
hrefContains: (value) => new web.PartialLinkTextMatcher(value),
|
22
24
|
},
|
25
|
+
|
26
|
+
system: {
|
27
|
+
label: (_value) => { throw new DetoxRuntimeError('System interactions are not supported on Android, use UiDevice APIs directly instead'); },
|
28
|
+
type: (_value) => { throw new DetoxRuntimeError('System interactions are not supported on Android, use UiDevice APIs directly instead'); },
|
29
|
+
}
|
23
30
|
};
|
@@ -0,0 +1,52 @@
|
|
1
|
+
const { exec } = require('child-process-promise');
|
2
|
+
|
3
|
+
const DetoxRuntimeError = require('../errors/DetoxRuntimeError');
|
4
|
+
const environment = require('../utils/environment');
|
5
|
+
const log = require('../utils/logger').child({ cat: 'xcuitest-runner' });
|
6
|
+
|
7
|
+
class XCUITestRunner {
|
8
|
+
constructor({ simulatorId }) {
|
9
|
+
this.simulatorId = simulatorId;
|
10
|
+
}
|
11
|
+
|
12
|
+
async execute(invocationParams) {
|
13
|
+
log.trace(
|
14
|
+
{ event: 'XCUITEST_RUNNER' },
|
15
|
+
'invocation params: %j, simulator id: %s', invocationParams, this.simulatorId
|
16
|
+
);
|
17
|
+
|
18
|
+
const base64InvocationParams = Buffer.from(JSON.stringify(invocationParams)).toString('base64');
|
19
|
+
|
20
|
+
const runnerPath = await environment.getXCUITestRunnerPath();
|
21
|
+
if (!runnerPath) {
|
22
|
+
throw new DetoxRuntimeError({
|
23
|
+
message: 'XCUITest runner path could not be found',
|
24
|
+
hint: DetoxRuntimeError.reportIssue,
|
25
|
+
});
|
26
|
+
}
|
27
|
+
|
28
|
+
const flags = [
|
29
|
+
'-xctestrun', runnerPath,
|
30
|
+
'-sdk', 'iphonesimulator',
|
31
|
+
'-destination', `"platform=iOS Simulator,id=${this.simulatorId}"`,
|
32
|
+
'test-without-building',
|
33
|
+
];
|
34
|
+
|
35
|
+
try {
|
36
|
+
return await exec(`TEST_RUNNER_PARAMS="${base64InvocationParams}" xcodebuild ${flags.join(' ')}`);
|
37
|
+
} catch (e) {
|
38
|
+
const stdout = e.stdout.toString();
|
39
|
+
const innerError = this.findInnerError(stdout);
|
40
|
+
throw new DetoxRuntimeError(innerError);
|
41
|
+
}
|
42
|
+
}
|
43
|
+
|
44
|
+
findInnerError(stdout) {
|
45
|
+
const match = stdout.match(/DTXError: .*/);
|
46
|
+
return match ?
|
47
|
+
match[0].split('DTXError: ')[1] :
|
48
|
+
`XCUITest runner failed with no error message. Runner stdout: ${stdout}`;
|
49
|
+
}
|
50
|
+
}
|
51
|
+
|
52
|
+
module.exports = XCUITestRunner;
|
package/src/ios/expectTwo.js
CHANGED
@@ -1,13 +1,11 @@
|
|
1
1
|
// @ts-nocheck
|
2
|
-
const assert = require('assert');
|
3
2
|
const path = require('path');
|
4
3
|
|
5
4
|
const fs = require('fs-extra');
|
6
5
|
const _ = require('lodash');
|
7
6
|
const tempfile = require('tempfile');
|
8
7
|
|
9
|
-
|
10
|
-
const { assertEnum, assertNormalized } = require('../utils/assertArgument');
|
8
|
+
const { assertTraceDescription, assertEnum, assertNormalized } = require('../utils/assertArgument');
|
11
9
|
const { removeMilliseconds } = require('../utils/dateUtils');
|
12
10
|
const { actionDescription, expectDescription } = require('../utils/invocationTraceDescriptions');
|
13
11
|
const { isRegExp } = require('../utils/isRegExp');
|
@@ -15,8 +13,10 @@ const log = require('../utils/logger').child({ cat: 'ws-client, ws' });
|
|
15
13
|
const mapLongPressArguments = require('../utils/mapLongPressArguments');
|
16
14
|
const traceInvocationCall = require('../utils/traceInvocationCall').bind(null, log);
|
17
15
|
|
16
|
+
const { systemElement, systemMatcher, systemExpect, isSystemElement } = require('./system');
|
18
17
|
const { webElement, webMatcher, webExpect, isWebElement } = require('./web');
|
19
18
|
|
19
|
+
|
20
20
|
const assertDirection = assertEnum(['left', 'right', 'up', 'down']);
|
21
21
|
const assertSpeed = assertEnum(['fast', 'slow']);
|
22
22
|
|
@@ -27,6 +27,11 @@ class Expect {
|
|
27
27
|
this.modifiers = [];
|
28
28
|
}
|
29
29
|
|
30
|
+
get not() {
|
31
|
+
this.modifiers.push('not');
|
32
|
+
return this;
|
33
|
+
}
|
34
|
+
|
30
35
|
toBeVisible(percent) {
|
31
36
|
if (percent !== undefined && (!Number.isSafeInteger(percent) || percent < 1 || percent > 100)) {
|
32
37
|
throw new Error('`percent` must be an integer between 1 and 100, but got '
|
@@ -104,11 +109,6 @@ class Expect {
|
|
104
109
|
return this.toHaveValue(`${Number(value)}`);
|
105
110
|
}
|
106
111
|
|
107
|
-
get not() {
|
108
|
-
this.modifiers.push('not');
|
109
|
-
return this;
|
110
|
-
}
|
111
|
-
|
112
112
|
createInvocation(expectation, ...params) {
|
113
113
|
const definedParams = _.without(params, undefined);
|
114
114
|
return {
|
@@ -122,7 +122,7 @@ class Expect {
|
|
122
122
|
}
|
123
123
|
|
124
124
|
expect(expectation, traceDescription, ...params) {
|
125
|
-
|
125
|
+
assertTraceDescription(traceDescription);
|
126
126
|
|
127
127
|
const invocation = this.createInvocation(expectation, ...params);
|
128
128
|
traceDescription = expectDescription.full(traceDescription, this.modifiers.includes('not'));
|
@@ -374,6 +374,14 @@ class InternalElement extends Element {
|
|
374
374
|
}
|
375
375
|
|
376
376
|
class By {
|
377
|
+
get web() {
|
378
|
+
return webMatcher();
|
379
|
+
}
|
380
|
+
|
381
|
+
get system() {
|
382
|
+
return systemMatcher();
|
383
|
+
}
|
384
|
+
|
377
385
|
id(id) {
|
378
386
|
return new Matcher().id(id);
|
379
387
|
}
|
@@ -401,13 +409,18 @@ class By {
|
|
401
409
|
value(value) {
|
402
410
|
return new Matcher().value(value);
|
403
411
|
}
|
404
|
-
|
405
|
-
get web() {
|
406
|
-
return webMatcher();
|
407
|
-
}
|
408
412
|
}
|
409
413
|
|
410
414
|
class Matcher {
|
415
|
+
/** @private */
|
416
|
+
static *predicates(matcher) {
|
417
|
+
if (matcher.predicate.type === 'and') {
|
418
|
+
yield* matcher.predicate.predicates;
|
419
|
+
} else {
|
420
|
+
yield matcher.predicate;
|
421
|
+
}
|
422
|
+
}
|
423
|
+
|
411
424
|
accessibilityLabel(label) {
|
412
425
|
return this.label(label);
|
413
426
|
}
|
@@ -477,15 +490,6 @@ class Matcher {
|
|
477
490
|
|
478
491
|
return result;
|
479
492
|
}
|
480
|
-
|
481
|
-
/** @private */
|
482
|
-
static *predicates(matcher) {
|
483
|
-
if (matcher.predicate.type === 'and') {
|
484
|
-
yield* matcher.predicate.predicates;
|
485
|
-
} else {
|
486
|
-
yield matcher.predicate;
|
487
|
-
}
|
488
|
-
}
|
489
493
|
}
|
490
494
|
|
491
495
|
class WaitFor {
|
@@ -496,6 +500,11 @@ class WaitFor {
|
|
496
500
|
this._emitter = emitter;
|
497
501
|
}
|
498
502
|
|
503
|
+
get not() {
|
504
|
+
this.expectation.not;
|
505
|
+
return this;
|
506
|
+
}
|
507
|
+
|
499
508
|
toBeVisible(percent) {
|
500
509
|
this.expectation = this.expectation.toBeVisible(percent);
|
501
510
|
return this;
|
@@ -566,11 +575,6 @@ class WaitFor {
|
|
566
575
|
return this;
|
567
576
|
}
|
568
577
|
|
569
|
-
get not() {
|
570
|
-
this.expectation.not;
|
571
|
-
return this;
|
572
|
-
}
|
573
|
-
|
574
578
|
withTimeout(timeout) {
|
575
579
|
if (typeof timeout !== 'number') throw new Error('text should be a number, but got ' + (timeout + (' (' + (typeof timeout + ')'))));
|
576
580
|
if (timeout < 0) throw new Error('timeout must be larger than 0');
|
@@ -735,6 +739,7 @@ function element(invocationManager, emitter, matcher) {
|
|
735
739
|
if (!(matcher instanceof Matcher)) {
|
736
740
|
throwMatcherError(matcher);
|
737
741
|
}
|
742
|
+
|
738
743
|
return new Element(invocationManager, emitter, matcher);
|
739
744
|
}
|
740
745
|
|
@@ -742,6 +747,7 @@ function expect(invocationManager, element) {
|
|
742
747
|
if (!(element instanceof Element)) {
|
743
748
|
throwMatcherError(element);
|
744
749
|
}
|
750
|
+
|
745
751
|
return new Expect(invocationManager, element);
|
746
752
|
}
|
747
753
|
|
@@ -753,8 +759,9 @@ function waitFor(invocationManager, emitter, element) {
|
|
753
759
|
}
|
754
760
|
|
755
761
|
class IosExpect {
|
756
|
-
constructor({ invocationManager, emitter }) {
|
762
|
+
constructor({ invocationManager, xcuitestRunner, emitter }) {
|
757
763
|
this._invocationManager = invocationManager;
|
764
|
+
this._xcuitestRunner = xcuitestRunner;
|
758
765
|
this._emitter = emitter;
|
759
766
|
this.element = this.element.bind(this);
|
760
767
|
this.expect = this.expect.bind(this);
|
@@ -762,6 +769,8 @@ class IosExpect {
|
|
762
769
|
this.by = new By();
|
763
770
|
this.web = this.web.bind(this);
|
764
771
|
this.web.element = this.web().element;
|
772
|
+
this.system = this.system.bind(this);
|
773
|
+
this.system.element = this.system().element;
|
765
774
|
}
|
766
775
|
|
767
776
|
element(matcher) {
|
@@ -769,6 +778,10 @@ class IosExpect {
|
|
769
778
|
}
|
770
779
|
|
771
780
|
expect(element) {
|
781
|
+
if (isSystemElement(element)) {
|
782
|
+
return systemExpect(this._xcuitestRunner, element);
|
783
|
+
}
|
784
|
+
|
772
785
|
if (isWebElement(element)) {
|
773
786
|
return webExpect(this._invocationManager, element);
|
774
787
|
}
|
@@ -798,6 +811,14 @@ class IosExpect {
|
|
798
811
|
}
|
799
812
|
};
|
800
813
|
}
|
814
|
+
|
815
|
+
system() {
|
816
|
+
return {
|
817
|
+
element: systemMatcher => {
|
818
|
+
return systemElement(this._xcuitestRunner, systemMatcher);
|
819
|
+
}
|
820
|
+
};
|
821
|
+
}
|
801
822
|
}
|
802
823
|
|
803
824
|
function _assertValidPoint(point) {
|
@@ -0,0 +1,124 @@
|
|
1
|
+
const { DetoxRuntimeError } = require('../errors');
|
2
|
+
const { assertTraceDescription } = require('../utils/assertArgument');
|
3
|
+
const { systemActionDescription, expectDescription } = require('../utils/invocationTraceDescriptions');
|
4
|
+
const log = require('../utils/logger').child({ cat: 'ws-client, ws' });
|
5
|
+
const traceInvocationCall = require('../utils/traceInvocationCall').bind(null, log);
|
6
|
+
|
7
|
+
|
8
|
+
class SystemExpect {
|
9
|
+
constructor(xcuitestRunner, element) {
|
10
|
+
this._xcuitestRunner = xcuitestRunner;
|
11
|
+
this.element = element;
|
12
|
+
this.modifiers = [];
|
13
|
+
}
|
14
|
+
|
15
|
+
toExist() {
|
16
|
+
const traceDescription = expectDescription.toExist();
|
17
|
+
return this.expect('toExist', traceDescription);
|
18
|
+
}
|
19
|
+
|
20
|
+
get not() {
|
21
|
+
this.modifiers.push('not');
|
22
|
+
return this;
|
23
|
+
}
|
24
|
+
|
25
|
+
createInvocation(systemExpectation) {
|
26
|
+
return {
|
27
|
+
type: 'systemExpectation',
|
28
|
+
systemPredicate: this.element.matcher.predicate,
|
29
|
+
...(this.element.index !== undefined && { systemAtIndex: this.element.index }),
|
30
|
+
...(this.modifiers.length !== 0 && { systemModifiers: this.modifiers }),
|
31
|
+
systemExpectation
|
32
|
+
};
|
33
|
+
}
|
34
|
+
|
35
|
+
expect(expectation, traceDescription) {
|
36
|
+
assertTraceDescription(traceDescription);
|
37
|
+
|
38
|
+
const invocation = this.createInvocation(expectation);
|
39
|
+
traceDescription = expectDescription.full(traceDescription, this.modifiers.includes('not'));
|
40
|
+
return _executeInvocation(this._xcuitestRunner, invocation, traceDescription);
|
41
|
+
}
|
42
|
+
}
|
43
|
+
|
44
|
+
class SystemElement {
|
45
|
+
constructor(xcuitestRunner, matcher, index) {
|
46
|
+
this._xcuitestRunner = xcuitestRunner;
|
47
|
+
this.matcher = matcher;
|
48
|
+
this.index = index;
|
49
|
+
}
|
50
|
+
|
51
|
+
atIndex(index) {
|
52
|
+
if (typeof index !== 'number' || index < 0) throw new DetoxRuntimeError(`index should be an integer, got ${index} (${typeof index})`);
|
53
|
+
this.index = index;
|
54
|
+
return this;
|
55
|
+
}
|
56
|
+
|
57
|
+
tap() {
|
58
|
+
const traceDescription = systemActionDescription.tap();
|
59
|
+
return this.withAction('tap', traceDescription);
|
60
|
+
}
|
61
|
+
|
62
|
+
withAction(action, traceDescription) {
|
63
|
+
assertTraceDescription(traceDescription);
|
64
|
+
|
65
|
+
const invocation = {
|
66
|
+
type: 'systemAction',
|
67
|
+
systemPredicate: this.matcher.predicate,
|
68
|
+
...(this.index !== undefined && { systemAtIndex: this.index }),
|
69
|
+
systemAction: action
|
70
|
+
};
|
71
|
+
traceDescription = systemActionDescription.full(traceDescription);
|
72
|
+
return _executeInvocation(this._xcuitestRunner, invocation, traceDescription);
|
73
|
+
}
|
74
|
+
}
|
75
|
+
|
76
|
+
class SystemElementMatcher {
|
77
|
+
label(label) {
|
78
|
+
if (typeof label !== 'string') throw new DetoxRuntimeError('label should be a string, but got ' + (label + (' (' + typeof label + ')')));
|
79
|
+
this.predicate = { type: 'label', value: label.toString() };
|
80
|
+
return this;
|
81
|
+
}
|
82
|
+
|
83
|
+
type(type) {
|
84
|
+
if (typeof type !== 'string') throw new DetoxRuntimeError('type should be a string, but got ' + (type + (' (' + typeof type + ')')));
|
85
|
+
this.predicate = { type: 'type', value: type.toString() };
|
86
|
+
return this;
|
87
|
+
}
|
88
|
+
}
|
89
|
+
|
90
|
+
function systemMatcher() {
|
91
|
+
return new SystemElementMatcher();
|
92
|
+
}
|
93
|
+
|
94
|
+
function systemElement(xcuitestRunner, matcher) {
|
95
|
+
if (!(matcher instanceof SystemElementMatcher)) {
|
96
|
+
throwSystemMatcherError(matcher);
|
97
|
+
}
|
98
|
+
|
99
|
+
return new SystemElement(xcuitestRunner, matcher);
|
100
|
+
}
|
101
|
+
|
102
|
+
function throwSystemMatcherError(param) {
|
103
|
+
const paramDescription = JSON.stringify(param);
|
104
|
+
throw new DetoxRuntimeError(`${paramDescription} is not a Detox system matcher. More about system matchers here: https://wix.github.io/Detox/docs/api/system`);
|
105
|
+
}
|
106
|
+
|
107
|
+
function systemExpect(xcuitestRunner, element) {
|
108
|
+
return new SystemExpect(xcuitestRunner, element);
|
109
|
+
}
|
110
|
+
|
111
|
+
function _executeInvocation(xcuitestRunner, invocation, traceDescription) {
|
112
|
+
return traceInvocationCall(traceDescription, invocation, xcuitestRunner.execute(invocation));
|
113
|
+
}
|
114
|
+
|
115
|
+
function isSystemElement(element) {
|
116
|
+
return element instanceof SystemElement;
|
117
|
+
}
|
118
|
+
|
119
|
+
module.exports = {
|
120
|
+
systemMatcher,
|
121
|
+
systemElement,
|
122
|
+
systemExpect,
|
123
|
+
isSystemElement
|
124
|
+
};
|
package/src/ios/web.js
CHANGED
@@ -1,8 +1,7 @@
|
|
1
|
-
const assert = require('assert');
|
2
|
-
|
3
1
|
const _ = require('lodash');
|
4
2
|
|
5
3
|
const { DetoxRuntimeError } = require('../errors');
|
4
|
+
const { assertTraceDescription } = require('../utils/assertArgument');
|
6
5
|
const { webViewActionDescription, expectDescription } = require('../utils/invocationTraceDescriptions');
|
7
6
|
const log = require('../utils/logger').child({ cat: 'ws-client, ws' });
|
8
7
|
const traceInvocationCall = require('../utils/traceInvocationCall').bind(null, log);
|
@@ -48,7 +47,7 @@ class WebExpect {
|
|
48
47
|
}
|
49
48
|
|
50
49
|
expect(expectation, traceDescription, ...params) {
|
51
|
-
|
50
|
+
assertTraceDescription(traceDescription);
|
52
51
|
|
53
52
|
const invocation = this.createInvocation(expectation, ...params);
|
54
53
|
traceDescription = expectDescription.full(traceDescription, this.modifiers.includes('not'));
|
@@ -170,7 +169,7 @@ class WebElement {
|
|
170
169
|
}
|
171
170
|
|
172
171
|
withAction(action, traceDescription, ...params) {
|
173
|
-
|
172
|
+
assertTraceDescription(traceDescription);
|
174
173
|
|
175
174
|
const invocation = {
|
176
175
|
type: 'webAction',
|
@@ -12,19 +12,20 @@ class Android extends MatchersFactory {
|
|
12
12
|
}
|
13
13
|
|
14
14
|
class Ios extends MatchersFactory {
|
15
|
-
createMatchers({ invocationManager, eventEmitter }) {
|
15
|
+
createMatchers({ invocationManager, runtimeDevice, eventEmitter }) {
|
16
16
|
const IosExpect = require('../../ios/expectTwo');
|
17
|
-
|
17
|
+
const XCUITestRunner = require('../../ios/XCUITestRunner');
|
18
|
+
const xcuitestRunner = new XCUITestRunner({ simulatorId: runtimeDevice.id });
|
19
|
+
|
20
|
+
return new IosExpect({
|
21
|
+
invocationManager,
|
22
|
+
xcuitestRunner,
|
23
|
+
emitter: eventEmitter
|
24
|
+
});
|
18
25
|
}
|
19
26
|
}
|
20
27
|
|
21
28
|
class External extends MatchersFactory {
|
22
|
-
static validateModule(module, path) {
|
23
|
-
if (!module.ExpectClass) {
|
24
|
-
throw new DetoxRuntimeError(`The custom driver at '${path}' does not export the ExpectClass property`);
|
25
|
-
}
|
26
|
-
}
|
27
|
-
|
28
29
|
constructor(module, path) {
|
29
30
|
super();
|
30
31
|
External.validateModule(module, path);
|
@@ -32,6 +33,12 @@ class External extends MatchersFactory {
|
|
32
33
|
this._module = module;
|
33
34
|
}
|
34
35
|
|
36
|
+
static validateModule(module, path) {
|
37
|
+
if (!module.ExpectClass) {
|
38
|
+
throw new DetoxRuntimeError(`The custom driver at '${path}' does not export the ExpectClass property`);
|
39
|
+
}
|
40
|
+
}
|
41
|
+
|
35
42
|
createMatchers(deps) {
|
36
43
|
return new this._module.ExpectClass(deps);
|
37
44
|
}
|