detox 21.0.0-rc.2 → 21.0.0-rc.4
Sign up to get free protection for your applications and to get access to all the features.
- package/.eslintignore +2 -0
- package/.eslintrc.js +1 -40
- package/Detox-android/com/wix/detox/{21.0.0-rc.2/detox-21.0.0-rc.2-javadoc.jar → 21.0.0-rc.4/detox-21.0.0-rc.4-javadoc.jar} +0 -0
- package/Detox-android/com/wix/detox/21.0.0-rc.4/detox-21.0.0-rc.4-javadoc.jar.md5 +1 -0
- package/Detox-android/com/wix/detox/21.0.0-rc.4/detox-21.0.0-rc.4-javadoc.jar.sha1 +1 -0
- package/Detox-android/com/wix/detox/21.0.0-rc.4/detox-21.0.0-rc.4-javadoc.jar.sha256 +1 -0
- package/Detox-android/com/wix/detox/21.0.0-rc.4/detox-21.0.0-rc.4-javadoc.jar.sha512 +1 -0
- package/Detox-android/com/wix/detox/{21.0.0-rc.2/detox-21.0.0-rc.2-sources.jar → 21.0.0-rc.4/detox-21.0.0-rc.4-sources.jar} +0 -0
- package/Detox-android/com/wix/detox/21.0.0-rc.4/detox-21.0.0-rc.4-sources.jar.md5 +1 -0
- package/Detox-android/com/wix/detox/21.0.0-rc.4/detox-21.0.0-rc.4-sources.jar.sha1 +1 -0
- package/Detox-android/com/wix/detox/21.0.0-rc.4/detox-21.0.0-rc.4-sources.jar.sha256 +1 -0
- package/Detox-android/com/wix/detox/21.0.0-rc.4/detox-21.0.0-rc.4-sources.jar.sha512 +1 -0
- package/Detox-android/com/wix/detox/21.0.0-rc.4/detox-21.0.0-rc.4.aar +0 -0
- package/Detox-android/com/wix/detox/21.0.0-rc.4/detox-21.0.0-rc.4.aar.md5 +1 -0
- package/Detox-android/com/wix/detox/21.0.0-rc.4/detox-21.0.0-rc.4.aar.sha1 +1 -0
- package/Detox-android/com/wix/detox/21.0.0-rc.4/detox-21.0.0-rc.4.aar.sha256 +1 -0
- package/Detox-android/com/wix/detox/21.0.0-rc.4/detox-21.0.0-rc.4.aar.sha512 +1 -0
- package/Detox-android/com/wix/detox/{21.0.0-rc.2/detox-21.0.0-rc.2.pom → 21.0.0-rc.4/detox-21.0.0-rc.4.pom} +1 -1
- package/Detox-android/com/wix/detox/21.0.0-rc.4/detox-21.0.0-rc.4.pom.md5 +1 -0
- package/Detox-android/com/wix/detox/21.0.0-rc.4/detox-21.0.0-rc.4.pom.sha1 +1 -0
- package/Detox-android/com/wix/detox/21.0.0-rc.4/detox-21.0.0-rc.4.pom.sha256 +1 -0
- package/Detox-android/com/wix/detox/21.0.0-rc.4/detox-21.0.0-rc.4.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-framework.tbz +0 -0
- package/Detox-ios-src.tbz +0 -0
- package/Detox-ios-xcuitest.tbz +0 -0
- package/android/build.gradle +20 -10
- package/android/detox/build.gradle +11 -4
- package/android/detox/src/full/java/com/wix/detox/espresso/DetoxMatcher.java +12 -12
- package/android/detox/src/full/java/com/wix/detox/espresso/common/SliderHelper.kt +2 -2
- package/android/detox/src/full/java/com/wix/detox/espresso/matcher/RegexMatcher.kt +56 -0
- package/android/detox/src/full/java/com/wix/detox/espresso/matcher/ViewMatchers.kt +16 -4
- package/android/detox/src/testFull/java/com/wix/detox/espresso/matcher/RegexMatcherTest.kt +52 -0
- package/android/gradle/wrapper/gradle-wrapper.properties +1 -1
- package/android/rninfo.gradle +25 -0
- package/android/settings.gradle +2 -1
- package/index.d.ts +40 -6
- package/local-cli/startCommand/AppStartCommand.js +4 -1
- package/package.json +14 -10
- package/src/android/espressoapi/DetoxMatcher.js +24 -8
- package/src/android/matchers/index.js +3 -0
- package/src/android/matchers/native.js +9 -4
- package/src/android/matchers/web.js +18 -1
- package/src/devices/runtime/drivers/ios/XCUITestUtils.js +3 -4
- package/src/invoke.js +0 -2
- package/src/ios/expectTwo.js +28 -11
- package/src/ios/web.js +280 -0
- package/src/realms/DetoxPrimaryContext.js +1 -2
- package/src/utils/invocationTraceDescriptions.js +16 -0
- package/src/utils/isRegExp.js +7 -0
- package/Detox-android/com/wix/detox/21.0.0-rc.2/detox-21.0.0-rc.2-javadoc.jar.md5 +0 -1
- package/Detox-android/com/wix/detox/21.0.0-rc.2/detox-21.0.0-rc.2-javadoc.jar.sha1 +0 -1
- package/Detox-android/com/wix/detox/21.0.0-rc.2/detox-21.0.0-rc.2-javadoc.jar.sha256 +0 -1
- package/Detox-android/com/wix/detox/21.0.0-rc.2/detox-21.0.0-rc.2-javadoc.jar.sha512 +0 -1
- package/Detox-android/com/wix/detox/21.0.0-rc.2/detox-21.0.0-rc.2-sources.jar.md5 +0 -1
- package/Detox-android/com/wix/detox/21.0.0-rc.2/detox-21.0.0-rc.2-sources.jar.sha1 +0 -1
- package/Detox-android/com/wix/detox/21.0.0-rc.2/detox-21.0.0-rc.2-sources.jar.sha256 +0 -1
- package/Detox-android/com/wix/detox/21.0.0-rc.2/detox-21.0.0-rc.2-sources.jar.sha512 +0 -1
- package/Detox-android/com/wix/detox/21.0.0-rc.2/detox-21.0.0-rc.2.aar +0 -0
- package/Detox-android/com/wix/detox/21.0.0-rc.2/detox-21.0.0-rc.2.aar.md5 +0 -1
- package/Detox-android/com/wix/detox/21.0.0-rc.2/detox-21.0.0-rc.2.aar.sha1 +0 -1
- package/Detox-android/com/wix/detox/21.0.0-rc.2/detox-21.0.0-rc.2.aar.sha256 +0 -1
- package/Detox-android/com/wix/detox/21.0.0-rc.2/detox-21.0.0-rc.2.aar.sha512 +0 -1
- package/Detox-android/com/wix/detox/21.0.0-rc.2/detox-21.0.0-rc.2.pom.md5 +0 -1
- package/Detox-android/com/wix/detox/21.0.0-rc.2/detox-21.0.0-rc.2.pom.sha1 +0 -1
- package/Detox-android/com/wix/detox/21.0.0-rc.2/detox-21.0.0-rc.2.pom.sha256 +0 -1
- package/Detox-android/com/wix/detox/21.0.0-rc.2/detox-21.0.0-rc.2.pom.sha512 +0 -1
- package/src/invoke/EarlGrey.js +0 -8
package/index.d.ts
CHANGED
@@ -790,7 +790,7 @@ declare global {
|
|
790
790
|
setLocation(lat: number, lon: number): Promise<void>;
|
791
791
|
|
792
792
|
/**
|
793
|
-
* Disable
|
793
|
+
* Disable network synchronization mechanism on preferred endpoints. Useful if you want to on skip over synchronizing on certain URLs.
|
794
794
|
*
|
795
795
|
* @example await device.setURLBlacklist(['.*127.0.0.1.*']);
|
796
796
|
*/
|
@@ -971,20 +971,25 @@ declare global {
|
|
971
971
|
* <TouchableOpacity testID={'tap_me'}>
|
972
972
|
* // Then match with by.id:
|
973
973
|
* await element(by.id('tap_me'));
|
974
|
+
* await element(by.id(/^tap_[a-z]+$/));
|
974
975
|
*/
|
975
|
-
id(id: string): NativeMatcher;
|
976
|
+
id(id: string | RegExp): NativeMatcher;
|
976
977
|
|
977
978
|
/**
|
978
979
|
* Find an element by text, useful for text fields, buttons.
|
979
|
-
* @example
|
980
|
+
* @example
|
981
|
+
* await element(by.text('Tap Me'));
|
982
|
+
* await element(by.text(/^Tap .*$/));
|
980
983
|
*/
|
981
|
-
text(text: string): NativeMatcher;
|
984
|
+
text(text: string | RegExp): NativeMatcher;
|
982
985
|
|
983
986
|
/**
|
984
987
|
* Find an element by accessibilityLabel on iOS, or by contentDescription on Android.
|
985
|
-
* @example
|
988
|
+
* @example
|
989
|
+
* await element(by.label('Welcome'));
|
990
|
+
* await element(by.label(/[a-z]+/i));
|
986
991
|
*/
|
987
|
-
label(label: string): NativeMatcher;
|
992
|
+
label(label: string | RegExp): NativeMatcher;
|
988
993
|
|
989
994
|
/**
|
990
995
|
* Find an element by native view type.
|
@@ -1006,6 +1011,7 @@ declare global {
|
|
1006
1011
|
|
1007
1012
|
interface ByWebFacade {
|
1008
1013
|
/**
|
1014
|
+
* (Android Only)
|
1009
1015
|
* Find an element on the DOM tree by its id
|
1010
1016
|
* @param id
|
1011
1017
|
* @example
|
@@ -1014,6 +1020,7 @@ declare global {
|
|
1014
1020
|
id(id: string): WebMatcher;
|
1015
1021
|
|
1016
1022
|
/**
|
1023
|
+
* (Android Only)
|
1017
1024
|
* Find an element on the DOM tree by its CSS class
|
1018
1025
|
* @param className
|
1019
1026
|
* @example
|
@@ -1022,6 +1029,7 @@ declare global {
|
|
1022
1029
|
className(className: string): WebMatcher;
|
1023
1030
|
|
1024
1031
|
/**
|
1032
|
+
* (Android Only)
|
1025
1033
|
* Find an element on the DOM tree matching the given CSS selector
|
1026
1034
|
* @param cssSelector
|
1027
1035
|
* @example
|
@@ -1030,6 +1038,7 @@ declare global {
|
|
1030
1038
|
cssSelector(cssSelector: string): WebMatcher;
|
1031
1039
|
|
1032
1040
|
/**
|
1041
|
+
* (Android Only)
|
1033
1042
|
* Find an element on the DOM tree by its "name" attribute
|
1034
1043
|
* @param name
|
1035
1044
|
* @example
|
@@ -1038,6 +1047,7 @@ declare global {
|
|
1038
1047
|
name(name: string): WebMatcher;
|
1039
1048
|
|
1040
1049
|
/**
|
1050
|
+
* (Android Only)
|
1041
1051
|
* Find an element on the DOM tree by its XPath
|
1042
1052
|
* @param xpath
|
1043
1053
|
* @example
|
@@ -1046,6 +1056,7 @@ declare global {
|
|
1046
1056
|
xpath(xpath: string): WebMatcher;
|
1047
1057
|
|
1048
1058
|
/**
|
1059
|
+
* (Android Only)
|
1049
1060
|
* Find an <a> element on the DOM tree by its link text (href content)
|
1050
1061
|
* @param linkText
|
1051
1062
|
* @example
|
@@ -1054,6 +1065,7 @@ declare global {
|
|
1054
1065
|
href(linkText: string): WebMatcher;
|
1055
1066
|
|
1056
1067
|
/**
|
1068
|
+
* (Android Only)
|
1057
1069
|
* Find an <a> element on the DOM tree by its partial link text (href content)
|
1058
1070
|
* @param linkTextFragment
|
1059
1071
|
* @example
|
@@ -1062,12 +1074,31 @@ declare global {
|
|
1062
1074
|
hrefContains(linkTextFragment: string): WebMatcher;
|
1063
1075
|
|
1064
1076
|
/**
|
1077
|
+
* (Android Only)
|
1065
1078
|
* Find an element on the DOM tree by its tag name
|
1066
1079
|
* @param tag
|
1067
1080
|
* @example
|
1068
1081
|
* web.element(by.web.tag('mark'))
|
1069
1082
|
*/
|
1070
1083
|
tag(tagName: string): WebMatcher;
|
1084
|
+
|
1085
|
+
/**
|
1086
|
+
* (iOS Only)
|
1087
|
+
* Find an element on the web-view by its text content
|
1088
|
+
* @param label
|
1089
|
+
* @example
|
1090
|
+
* web.element(by.web.label('Welcome'))
|
1091
|
+
*/
|
1092
|
+
label(label: string): WebMatcher;
|
1093
|
+
|
1094
|
+
/**
|
1095
|
+
* (iOS Only)
|
1096
|
+
* Find an element on the web-view by its content description
|
1097
|
+
* @param value
|
1098
|
+
* @example
|
1099
|
+
* web.element(by.web.value('Write a comment...'))
|
1100
|
+
*/
|
1101
|
+
value(value: string): WebMatcher;
|
1071
1102
|
}
|
1072
1103
|
|
1073
1104
|
interface NativeMatcher {
|
@@ -1477,6 +1508,9 @@ declare global {
|
|
1477
1508
|
}
|
1478
1509
|
|
1479
1510
|
interface WebElementActions {
|
1511
|
+
/**
|
1512
|
+
* Taps the element
|
1513
|
+
*/
|
1480
1514
|
tap(): Promise<void>;
|
1481
1515
|
|
1482
1516
|
/**
|
@@ -36,7 +36,10 @@ class AppStartCommand {
|
|
36
36
|
}
|
37
37
|
};
|
38
38
|
|
39
|
-
this._cpHandle = execa.command(cmd, {
|
39
|
+
this._cpHandle = execa.command(cmd, {
|
40
|
+
stdio: ['ignore', 'inherit', 'inherit'],
|
41
|
+
shell: true
|
42
|
+
});
|
40
43
|
this._cpHandle.on('error', onError);
|
41
44
|
this._cpHandle.on('exit', (code, signal) => {
|
42
45
|
const reason = code == null ? `signal ${signal}` : `code ${code}`;
|
package/package.json
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
{
|
2
2
|
"name": "detox",
|
3
3
|
"description": "E2E tests and automation for mobile",
|
4
|
-
"version": "21.0.0-rc.
|
4
|
+
"version": "21.0.0-rc.4",
|
5
5
|
"bin": {
|
6
6
|
"detox": "local-cli/cli.js"
|
7
7
|
},
|
@@ -41,19 +41,20 @@
|
|
41
41
|
"@types/node": "^14.18.33",
|
42
42
|
"@types/node-ipc": "^9.2.0",
|
43
43
|
"@types/ws": "^7.4.0",
|
44
|
-
"@typescript-eslint/eslint-plugin": "^5.
|
45
|
-
"@typescript-eslint/parser": "^5.
|
44
|
+
"@typescript-eslint/eslint-plugin": "^5.59.8",
|
45
|
+
"@typescript-eslint/parser": "^5.59.8",
|
46
46
|
"cross-env": "^7.0.3",
|
47
|
-
"eslint": "^8.
|
48
|
-
"eslint-plugin-
|
49
|
-
"eslint-plugin-
|
47
|
+
"eslint": "^8.41.0",
|
48
|
+
"eslint-plugin-ecmascript-compat": "^3.0.0",
|
49
|
+
"eslint-plugin-import": "^2.27.5",
|
50
|
+
"eslint-plugin-no-only-tests": "^3.1.0",
|
50
51
|
"eslint-plugin-node": "^11.1.0",
|
51
|
-
"eslint-plugin-unicorn": "^
|
52
|
+
"eslint-plugin-unicorn": "^47.0.0",
|
52
53
|
"jest": "^28.1.3",
|
53
54
|
"jest-allure2-reporter": "^1.2.1",
|
54
55
|
"mockdate": "^2.0.1",
|
55
|
-
"prettier": "
|
56
|
-
"react-native": "0.
|
56
|
+
"prettier": "^2.4.1",
|
57
|
+
"react-native": "0.71.10",
|
57
58
|
"react-native-codegen": "^0.0.8",
|
58
59
|
"typescript": "^4.5.2",
|
59
60
|
"wtfnode": "^0.9.1"
|
@@ -203,5 +204,8 @@
|
|
203
204
|
}
|
204
205
|
}
|
205
206
|
},
|
206
|
-
"
|
207
|
+
"browserslist": [
|
208
|
+
"node 14"
|
209
|
+
],
|
210
|
+
"gitHead": "72ae4a95d8115737031a400ba44243b3ae7a42e0"
|
207
211
|
}
|
@@ -14,39 +14,51 @@ function sanitize_matcher(matcher) {
|
|
14
14
|
return originalMatcher.type ? originalMatcher.value : originalMatcher;
|
15
15
|
}
|
16
16
|
class DetoxMatcher {
|
17
|
-
static matcherForText(text) {
|
17
|
+
static matcherForText(text, isRegex) {
|
18
18
|
if (typeof text !== "string") throw new Error("text should be a string, but got " + (text + (" (" + (typeof text + ")"))));
|
19
|
+
if (typeof isRegex !== "boolean") throw new Error("isRegex should be a boolean, but got " + (isRegex + (" (" + (typeof isRegex + ")"))));
|
19
20
|
return {
|
20
21
|
target: {
|
21
22
|
type: "Class",
|
22
23
|
value: "com.wix.detox.espresso.DetoxMatcher"
|
23
24
|
},
|
24
25
|
method: "matcherForText",
|
25
|
-
args: [text
|
26
|
+
args: [text, {
|
27
|
+
type: "boolean",
|
28
|
+
value: isRegex
|
29
|
+
}]
|
26
30
|
};
|
27
31
|
}
|
28
32
|
|
29
|
-
static matcherForAccessibilityLabel(label) {
|
33
|
+
static matcherForAccessibilityLabel(label, isRegex) {
|
30
34
|
if (typeof label !== "string") throw new Error("label should be a string, but got " + (label + (" (" + (typeof label + ")"))));
|
35
|
+
if (typeof isRegex !== "boolean") throw new Error("isRegex should be a boolean, but got " + (isRegex + (" (" + (typeof isRegex + ")"))));
|
31
36
|
return {
|
32
37
|
target: {
|
33
38
|
type: "Class",
|
34
39
|
value: "com.wix.detox.espresso.DetoxMatcher"
|
35
40
|
},
|
36
41
|
method: "matcherForAccessibilityLabel",
|
37
|
-
args: [label
|
42
|
+
args: [label, {
|
43
|
+
type: "boolean",
|
44
|
+
value: isRegex
|
45
|
+
}]
|
38
46
|
};
|
39
47
|
}
|
40
48
|
|
41
|
-
static matcherForShallowAccessibilityLabel(label) {
|
49
|
+
static matcherForShallowAccessibilityLabel(label, isRegex) {
|
42
50
|
if (typeof label !== "string") throw new Error("label should be a string, but got " + (label + (" (" + (typeof label + ")"))));
|
51
|
+
if (typeof isRegex !== "boolean") throw new Error("isRegex should be a boolean, but got " + (isRegex + (" (" + (typeof isRegex + ")"))));
|
43
52
|
return {
|
44
53
|
target: {
|
45
54
|
type: "Class",
|
46
55
|
value: "com.wix.detox.espresso.DetoxMatcher"
|
47
56
|
},
|
48
57
|
method: "matcherForShallowAccessibilityLabel",
|
49
|
-
args: [label
|
58
|
+
args: [label, {
|
59
|
+
type: "boolean",
|
60
|
+
value: isRegex
|
61
|
+
}]
|
50
62
|
};
|
51
63
|
}
|
52
64
|
|
@@ -62,15 +74,19 @@ class DetoxMatcher {
|
|
62
74
|
};
|
63
75
|
}
|
64
76
|
|
65
|
-
static matcherForTestId(testId) {
|
77
|
+
static matcherForTestId(testId, isRegex) {
|
66
78
|
if (typeof testId !== "string") throw new Error("testId should be a string, but got " + (testId + (" (" + (typeof testId + ")"))));
|
79
|
+
if (typeof isRegex !== "boolean") throw new Error("isRegex should be a boolean, but got " + (isRegex + (" (" + (typeof isRegex + ")"))));
|
67
80
|
return {
|
68
81
|
target: {
|
69
82
|
type: "Class",
|
70
83
|
value: "com.wix.detox.espresso.DetoxMatcher"
|
71
84
|
},
|
72
85
|
method: "matcherForTestId",
|
73
|
-
args: [testId
|
86
|
+
args: [testId, {
|
87
|
+
type: "boolean",
|
88
|
+
value: isRegex
|
89
|
+
}]
|
74
90
|
};
|
75
91
|
}
|
76
92
|
|
@@ -10,6 +10,7 @@ module.exports = {
|
|
10
10
|
type: (value) => new native.TypeMatcher(value),
|
11
11
|
value: (value) => new native.ValueMatcher(value),
|
12
12
|
|
13
|
+
// label and value not supported
|
13
14
|
web: {
|
14
15
|
id: (value) => new web.IdMatcher(value),
|
15
16
|
className: (value) => new web.ClassNameMatcher(value),
|
@@ -19,5 +20,7 @@ module.exports = {
|
|
19
20
|
xpath: (value) => new web.XPathMatcher(value),
|
20
21
|
href: (value) => new web.LinkTextMatcher(value),
|
21
22
|
hrefContains: (value) => new web.PartialLinkTextMatcher(value),
|
23
|
+
label: (value) => new web.LabelMatcher(value),
|
24
|
+
value: (value) => new web.ValueMatcher(value),
|
22
25
|
},
|
23
26
|
};
|
@@ -1,26 +1,30 @@
|
|
1
1
|
const DetoxRuntimeError = require('../../errors/DetoxRuntimeError');
|
2
2
|
const invoke = require('../../invoke');
|
3
|
+
const { isRegExp } = require('../../utils/isRegExp');
|
3
4
|
const { NativeMatcher } = require('../core/NativeMatcher');
|
4
5
|
const DetoxMatcherApi = require('../espressoapi/DetoxMatcher');
|
5
6
|
|
6
7
|
class LabelMatcher extends NativeMatcher {
|
7
8
|
constructor(value) {
|
8
9
|
super();
|
9
|
-
|
10
|
+
const isRegex = isRegExp(value);
|
11
|
+
this._call = invoke.callDirectly(DetoxMatcherApi.matcherForAccessibilityLabel(isRegex ? value.toString() : value, isRegex));
|
10
12
|
}
|
11
13
|
}
|
12
14
|
|
13
15
|
class ShallowLabelMatcher extends NativeMatcher {
|
14
16
|
constructor(value) {
|
15
17
|
super();
|
16
|
-
|
18
|
+
const isRegex = isRegExp(value);
|
19
|
+
this._call = invoke.callDirectly(DetoxMatcherApi.matcherForShallowAccessibilityLabel(isRegex ? value.toString() : value, isRegex));
|
17
20
|
}
|
18
21
|
}
|
19
22
|
|
20
23
|
class IdMatcher extends NativeMatcher {
|
21
24
|
constructor(value) {
|
22
25
|
super();
|
23
|
-
|
26
|
+
const isRegex = isRegExp(value);
|
27
|
+
this._call = invoke.callDirectly(DetoxMatcherApi.matcherForTestId(isRegex ? value.toString() : value, isRegex));
|
24
28
|
}
|
25
29
|
}
|
26
30
|
|
@@ -53,7 +57,8 @@ class ExistsMatcher extends NativeMatcher {
|
|
53
57
|
class TextMatcher extends NativeMatcher {
|
54
58
|
constructor(value) {
|
55
59
|
super();
|
56
|
-
|
60
|
+
const isRegex = isRegExp(value);
|
61
|
+
this._call = invoke.callDirectly(DetoxMatcherApi.matcherForText(isRegex ? value.toString() : value, isRegex));
|
57
62
|
}
|
58
63
|
}
|
59
64
|
|
@@ -1,6 +1,7 @@
|
|
1
1
|
const invoke = require('../../invoke');
|
2
2
|
const { WebMatcher } = require('../core/WebMatcher');
|
3
3
|
const DetoxWebMatcherApi = require('../espressoapi/web/DetoxWebAtomMatcher');
|
4
|
+
const DetoxRuntimeError = require('../../errors/DetoxRuntimeError');
|
4
5
|
|
5
6
|
class IdMatcher extends WebMatcher {
|
6
7
|
constructor(id) {
|
@@ -51,6 +52,20 @@ class PartialLinkTextMatcher extends WebMatcher {
|
|
51
52
|
}
|
52
53
|
}
|
53
54
|
|
55
|
+
class LabelMatcher extends WebMatcher {
|
56
|
+
constructor(_) {
|
57
|
+
super();
|
58
|
+
throw new DetoxRuntimeError('Label matching is not supported on Android');
|
59
|
+
}
|
60
|
+
}
|
61
|
+
|
62
|
+
class ValueMatcher extends WebMatcher {
|
63
|
+
constructor(_) {
|
64
|
+
super();
|
65
|
+
throw new DetoxRuntimeError('Label matching is not supported on Android');
|
66
|
+
}
|
67
|
+
}
|
68
|
+
|
54
69
|
class TagNameMatcher extends WebMatcher {
|
55
70
|
constructor(tag) {
|
56
71
|
super();
|
@@ -66,5 +81,7 @@ module.exports = {
|
|
66
81
|
XPathMatcher,
|
67
82
|
LinkTextMatcher,
|
68
83
|
PartialLinkTextMatcher,
|
69
|
-
TagNameMatcher
|
84
|
+
TagNameMatcher,
|
85
|
+
LabelMatcher,
|
86
|
+
ValueMatcher
|
70
87
|
};
|
@@ -101,9 +101,8 @@ function runXCUITest(
|
|
101
101
|
};
|
102
102
|
|
103
103
|
const options = {
|
104
|
-
maxBuffer: 1024 * 1024 *
|
104
|
+
maxBuffer: 1024 * 1024 * 10, // 10MB
|
105
105
|
retries: 1,
|
106
|
-
verbosity: 'high',
|
107
106
|
};
|
108
107
|
|
109
108
|
const command = `${env.TEST_RUNNER_IS_DETOX_ACTIVE ? Object.keys(env).map(key => `${key}=${env[key]}`).join(' ') : ''} ${xcodebuildBinary} ${flags.map(flag => flag.includes(' ') ? `"${flag}"` : flag).join(' ')}`;
|
@@ -124,9 +123,9 @@ function runXCUITest(
|
|
124
123
|
}
|
125
124
|
|
126
125
|
function _runCommandInTerminal(command, options) {
|
127
|
-
const escapedCommand = command.replace(/"/g, '\\"');
|
126
|
+
const escapedCommand = command.replace(/"/g, '\\"');
|
128
127
|
|
129
|
-
//
|
128
|
+
// Opens the Terminal app and runs the command in a new window, then closes the window when the command is done running.
|
130
129
|
const appleScript = `
|
131
130
|
tell application "Terminal"
|
132
131
|
if not running then
|
package/src/invoke.js
CHANGED
@@ -1,4 +1,3 @@
|
|
1
|
-
const EarlGrey = require('./invoke/EarlGrey');
|
2
1
|
const Espresso = require('./invoke/Espresso');
|
3
2
|
const EspressoWeb = require('./invoke/EspressoWeb');
|
4
3
|
const Invoke = require('./invoke/Invoke');
|
@@ -15,7 +14,6 @@ class InvocationManager {
|
|
15
14
|
|
16
15
|
module.exports = {
|
17
16
|
InvocationManager,
|
18
|
-
EarlGrey,
|
19
17
|
Espresso: Espresso.target,
|
20
18
|
EspressoWeb: EspressoWeb.target,
|
21
19
|
IOS: Invoke.genericInvokeObject,
|
package/src/ios/expectTwo.js
CHANGED
@@ -6,12 +6,16 @@ const fs = require('fs-extra');
|
|
6
6
|
const _ = require('lodash');
|
7
7
|
const tempfile = require('tempfile');
|
8
8
|
|
9
|
+
|
9
10
|
const { assertEnum, assertNormalized } = require('../utils/assertArgument');
|
10
11
|
const { removeMilliseconds } = require('../utils/dateUtils');
|
11
12
|
const { actionDescription, expectDescription } = require('../utils/invocationTraceDescriptions');
|
13
|
+
const { isRegExp } = require('../utils/isRegExp');
|
12
14
|
const log = require('../utils/logger').child({ cat: 'ws-client, ws' });
|
13
15
|
const traceInvocationCall = require('../utils/traceInvocationCall').bind(null, log);
|
14
16
|
|
17
|
+
const { webElement, webMatcher, webExpect, isWebElement } = require('./web');
|
18
|
+
|
15
19
|
const assertDirection = assertEnum(['left', 'right', 'up', 'down']);
|
16
20
|
const assertSpeed = assertEnum(['fast', 'slow']);
|
17
21
|
|
@@ -231,7 +235,7 @@ class Element {
|
|
231
235
|
|
232
236
|
performAccessibilityAction(actionName) {
|
233
237
|
if (typeof actionName !== 'string') throw new Error('actionName should be a string, but got ' + (actionName + (' (' + (typeof actionName + ')'))));
|
234
|
-
|
238
|
+
|
235
239
|
const traceDescription = actionDescription.performAccessibilityAction(actionName);
|
236
240
|
return this.withAction('accessibilityAction', traceDescription, actionName);
|
237
241
|
}
|
@@ -399,7 +403,7 @@ class By {
|
|
399
403
|
}
|
400
404
|
|
401
405
|
get web() {
|
402
|
-
|
406
|
+
return webMatcher();
|
403
407
|
}
|
404
408
|
}
|
405
409
|
|
@@ -409,14 +413,14 @@ class Matcher {
|
|
409
413
|
}
|
410
414
|
|
411
415
|
label(label) {
|
412
|
-
if (typeof label !== 'string') throw new Error('label should be a string, but got ' + (label + (' (' + (typeof label + ')'))));
|
413
|
-
this.predicate = { type: 'label', value: label };
|
416
|
+
if (typeof label !== 'string' && !isRegExp(label)) throw new Error('label should be a string or regex, but got ' + (label + (' (' + (typeof label + ')'))));
|
417
|
+
this.predicate = { type: 'label', value: label.toString(), isRegex: isRegExp(label) };
|
414
418
|
return this;
|
415
419
|
}
|
416
420
|
|
417
421
|
id(id) {
|
418
|
-
if (typeof id !== 'string') throw new Error('id should be a string, but got ' + (id + (' (' + (typeof id + ')'))));
|
419
|
-
this.predicate = { type: 'id', value: id };
|
422
|
+
if (typeof id !== 'string' && !isRegExp(id)) throw new Error('id should be a string or regex, but got ' + (id + (' (' + (typeof id + ')'))));
|
423
|
+
this.predicate = { type: 'id', value: id.toString(), isRegex: isRegExp(id) };
|
420
424
|
return this;
|
421
425
|
}
|
422
426
|
|
@@ -439,8 +443,8 @@ class Matcher {
|
|
439
443
|
}
|
440
444
|
|
441
445
|
text(text) {
|
442
|
-
if (typeof text !== 'string') throw new Error(
|
443
|
-
this.predicate = { type: 'text', value: text };
|
446
|
+
if (typeof text !== 'string' && !isRegExp(text)) throw new Error(`text should be a string or regex, but got ` + (text + (' (' + (typeof text + ')'))));
|
447
|
+
this.predicate = { type: 'text', value: text.toString(), isRegex: isRegExp(text) };
|
444
448
|
return this;
|
445
449
|
}
|
446
450
|
|
@@ -754,7 +758,7 @@ class IosExpect {
|
|
754
758
|
this.waitFor = this.waitFor.bind(this);
|
755
759
|
this.by = new By();
|
756
760
|
this.web = this.web.bind(this);
|
757
|
-
this.web.element = this.web;
|
761
|
+
this.web.element = this.web().element;
|
758
762
|
}
|
759
763
|
|
760
764
|
element(matcher) {
|
@@ -762,6 +766,10 @@ class IosExpect {
|
|
762
766
|
}
|
763
767
|
|
764
768
|
expect(element) {
|
769
|
+
if (isWebElement(element)) {
|
770
|
+
return webExpect(this._invocationManager, element);
|
771
|
+
}
|
772
|
+
|
765
773
|
return expect(this._invocationManager, element);
|
766
774
|
}
|
767
775
|
|
@@ -769,8 +777,17 @@ class IosExpect {
|
|
769
777
|
return waitFor(this._invocationManager, this._emitter, element);
|
770
778
|
}
|
771
779
|
|
772
|
-
web(
|
773
|
-
|
780
|
+
web(matcher) {
|
781
|
+
return {
|
782
|
+
element: webMatcher => {
|
783
|
+
if (!(matcher instanceof Matcher) && matcher !== undefined) {
|
784
|
+
throwMatcherError(matcher);
|
785
|
+
}
|
786
|
+
|
787
|
+
const webViewElement = matcher ? element(this._invocationManager, this._emitter, matcher) : undefined;
|
788
|
+
return webElement(this._invocationManager, this._emitter, webViewElement, webMatcher);
|
789
|
+
}
|
790
|
+
};
|
774
791
|
}
|
775
792
|
}
|
776
793
|
|