detox 12.11.2 → 12.11.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Detox-android/com/wix/detox/12.11.3/detox-12.11.3-javadoc.jar +0 -0
- package/Detox-android/com/wix/detox/12.11.3/detox-12.11.3-javadoc.jar.md5 +1 -0
- package/Detox-android/com/wix/detox/12.11.3/detox-12.11.3-javadoc.jar.sha1 +1 -0
- package/Detox-android/com/wix/detox/{12.11.2/detox-12.11.2-sources.jar → 12.11.3/detox-12.11.3-sources.jar} +0 -0
- package/Detox-android/com/wix/detox/12.11.3/detox-12.11.3-sources.jar.md5 +1 -0
- package/Detox-android/com/wix/detox/12.11.3/detox-12.11.3-sources.jar.sha1 +1 -0
- package/Detox-android/com/wix/detox/12.11.3/detox-12.11.3.aar +0 -0
- package/Detox-android/com/wix/detox/12.11.3/detox-12.11.3.aar.md5 +1 -0
- package/Detox-android/com/wix/detox/12.11.3/detox-12.11.3.aar.sha1 +1 -0
- package/Detox-android/com/wix/detox/{12.11.2/detox-12.11.2.pom → 12.11.3/detox-12.11.3.pom} +1 -1
- package/Detox-android/com/wix/detox/12.11.3/detox-12.11.3.pom.md5 +1 -0
- package/Detox-android/com/wix/detox/12.11.3/detox-12.11.3.pom.sha1 +1 -0
- package/Detox-android/com/wix/detox/maven-metadata.xml +3 -3
- 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-ios-src.tbz +0 -0
- package/android/detox/src/main/java/com/wix/detox/espresso/DetoxAssertion.java +15 -23
- package/android/detox/src/main/java/com/wix/detox/espresso/DetoxMatcher.java +10 -48
- package/android/detox/src/main/java/com/wix/detox/espresso/assertion/ViewAssertions.java +61 -0
- package/android/detox/src/main/java/com/wix/detox/espresso/matcher/NullableTypeSafeMatcher.java +61 -0
- package/android/detox/src/main/java/com/wix/detox/espresso/matcher/ViewAtIndexMatcher.kt +26 -0
- package/android/detox/src/main/java/com/wix/detox/espresso/matcher/ViewMatchers.kt +35 -0
- package/package.json +1 -1
- package/scripts/postinstall.js +1 -1
- package/src/android/expect.js +5 -6
- package/src/devices/android/ADB.js +21 -1
- package/Detox-android/com/wix/detox/12.11.2/detox-12.11.2-javadoc.jar +0 -0
- package/Detox-android/com/wix/detox/12.11.2/detox-12.11.2-javadoc.jar.md5 +0 -1
- package/Detox-android/com/wix/detox/12.11.2/detox-12.11.2-javadoc.jar.sha1 +0 -1
- package/Detox-android/com/wix/detox/12.11.2/detox-12.11.2-sources.jar.md5 +0 -1
- package/Detox-android/com/wix/detox/12.11.2/detox-12.11.2-sources.jar.sha1 +0 -1
- package/Detox-android/com/wix/detox/12.11.2/detox-12.11.2.aar +0 -0
- package/Detox-android/com/wix/detox/12.11.2/detox-12.11.2.aar.md5 +0 -1
- package/Detox-android/com/wix/detox/12.11.2/detox-12.11.2.aar.sha1 +0 -1
- package/Detox-android/com/wix/detox/12.11.2/detox-12.11.2.pom.md5 +0 -1
- package/Detox-android/com/wix/detox/12.11.2/detox-12.11.2.pom.sha1 +0 -1
|
Binary file
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
e637ce306f39bdbbe8210666fff25b76
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
9c5b5e52c4511a8ddbfd77df7d539b9e28af9cc8
|
|
Binary file
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
e5656dd9d2d320318fc203353dc0c3b3
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
fd69a2a3594590cf52ff0241b95c9a5d082ea580
|
|
Binary file
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
c47892438651668c6ac8c936fd2afead
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
de51cf945e93c7a27482aec046f7f2d516a2d0d4
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
<modelVersion>4.0.0</modelVersion>
|
|
4
4
|
<groupId>com.wix</groupId>
|
|
5
5
|
<artifactId>detox</artifactId>
|
|
6
|
-
<version>12.11.
|
|
6
|
+
<version>12.11.3</version>
|
|
7
7
|
<packaging>aar</packaging>
|
|
8
8
|
<name>Detox</name>
|
|
9
9
|
<description>Gray box end-to-end testing and automation library for mobile apps</description>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
f5dcd19ce4124ad9b8d676d499f1491d
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
29b7ee14afac9b7a7a3181ea32d72b3107e1c744
|
|
@@ -3,10 +3,10 @@
|
|
|
3
3
|
<groupId>com.wix</groupId>
|
|
4
4
|
<artifactId>detox</artifactId>
|
|
5
5
|
<versioning>
|
|
6
|
-
<release>12.11.
|
|
6
|
+
<release>12.11.3</release>
|
|
7
7
|
<versions>
|
|
8
|
-
<version>12.11.
|
|
8
|
+
<version>12.11.3</version>
|
|
9
9
|
</versions>
|
|
10
|
-
<lastUpdated>
|
|
10
|
+
<lastUpdated>20190625112308</lastUpdated>
|
|
11
11
|
</versioning>
|
|
12
12
|
</metadata>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
b8cac3012aba3f51f777d4f754bec7c6
|
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
bff95bd2751fb2ba959c488527b867e5fddbbe5f
|
package/Detox-ios-src.tbz
CHANGED
|
Binary file
|
|
@@ -2,20 +2,20 @@ package com.wix.detox.espresso;
|
|
|
2
2
|
|
|
3
3
|
import android.view.View;
|
|
4
4
|
|
|
5
|
+
import com.wix.detox.espresso.DetoxErrors.DetoxRuntimeException;
|
|
5
6
|
import com.wix.detox.espresso.DetoxErrors.StaleActionException;
|
|
6
7
|
|
|
7
8
|
import junit.framework.AssertionFailedError;
|
|
8
9
|
|
|
9
10
|
import org.hamcrest.Matcher;
|
|
10
11
|
|
|
11
|
-
import androidx.test.espresso.EspressoException;
|
|
12
12
|
import androidx.test.espresso.ViewAction;
|
|
13
13
|
import androidx.test.espresso.ViewInteraction;
|
|
14
14
|
|
|
15
15
|
import static androidx.test.espresso.Espresso.onView;
|
|
16
16
|
import static androidx.test.espresso.assertion.ViewAssertions.doesNotExist;
|
|
17
|
-
import static androidx.test.espresso.assertion.ViewAssertions.matches;
|
|
18
17
|
import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed;
|
|
18
|
+
import static com.wix.detox.espresso.assertion.ViewAssertions.matches;
|
|
19
19
|
import static org.hamcrest.Matchers.not;
|
|
20
20
|
|
|
21
21
|
/**
|
|
@@ -48,25 +48,21 @@ public class DetoxAssertion {
|
|
|
48
48
|
}
|
|
49
49
|
|
|
50
50
|
public static void waitForAssertMatcher(final ViewInteraction i, final Matcher<View> m, double timeoutSeconds) {
|
|
51
|
-
long originTime = System.nanoTime();
|
|
52
|
-
long currentTime;
|
|
51
|
+
final long originTime = System.nanoTime();
|
|
53
52
|
|
|
54
53
|
while (true) {
|
|
55
|
-
currentTime = System.nanoTime();
|
|
54
|
+
long currentTime = System.nanoTime();
|
|
56
55
|
long elapsed = currentTime - originTime;
|
|
57
|
-
double seconds = (double)elapsed / 1000000000.0;
|
|
56
|
+
double seconds = (double) elapsed / 1000000000.0;
|
|
58
57
|
if (seconds >= timeoutSeconds) {
|
|
59
|
-
|
|
58
|
+
throw new DetoxRuntimeException("" + timeoutSeconds + "sec timeout expired without matching of given matcher: " + m);
|
|
60
59
|
}
|
|
60
|
+
|
|
61
61
|
try {
|
|
62
62
|
i.check(matches(m));
|
|
63
63
|
break;
|
|
64
|
-
} catch (
|
|
65
|
-
|
|
66
|
-
UiAutomatorHelper.espressoSync();
|
|
67
|
-
} else {
|
|
68
|
-
throw e;
|
|
69
|
-
}
|
|
64
|
+
} catch (AssertionFailedError err) {
|
|
65
|
+
UiAutomatorHelper.espressoSync(20);
|
|
70
66
|
}
|
|
71
67
|
}
|
|
72
68
|
}
|
|
@@ -81,16 +77,12 @@ public class DetoxAssertion {
|
|
|
81
77
|
try {
|
|
82
78
|
assertMatcher(i, vm);
|
|
83
79
|
break;
|
|
84
|
-
} catch (
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
break;
|
|
91
|
-
}
|
|
92
|
-
} else {
|
|
93
|
-
throw e;
|
|
80
|
+
} catch (AssertionFailedError err) {
|
|
81
|
+
try {
|
|
82
|
+
onView(searchMatcher).perform(searchAction);
|
|
83
|
+
} catch (StaleActionException exStaleAction) {
|
|
84
|
+
assertMatcher(i, vm);
|
|
85
|
+
break;
|
|
94
86
|
}
|
|
95
87
|
}
|
|
96
88
|
}
|
|
@@ -2,11 +2,8 @@ package com.wix.detox.espresso;
|
|
|
2
2
|
|
|
3
3
|
import android.view.View;
|
|
4
4
|
|
|
5
|
-
import org.hamcrest.BaseMatcher;
|
|
6
|
-
import org.hamcrest.Description;
|
|
7
5
|
import org.hamcrest.Matcher;
|
|
8
6
|
|
|
9
|
-
import androidx.test.espresso.matcher.ViewMatchers;
|
|
10
7
|
import androidx.test.espresso.matcher.ViewMatchers.Visibility;
|
|
11
8
|
|
|
12
9
|
import static androidx.test.espresso.matcher.ViewMatchers.hasDescendant;
|
|
@@ -15,8 +12,11 @@ import static androidx.test.espresso.matcher.ViewMatchers.isDescendantOfA;
|
|
|
15
12
|
import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed;
|
|
16
13
|
import static androidx.test.espresso.matcher.ViewMatchers.isDisplayingAtLeast;
|
|
17
14
|
import static androidx.test.espresso.matcher.ViewMatchers.withContentDescription;
|
|
15
|
+
import static androidx.test.espresso.matcher.ViewMatchers.withEffectiveVisibility;
|
|
18
16
|
import static androidx.test.espresso.matcher.ViewMatchers.withTagValue;
|
|
19
17
|
import static androidx.test.espresso.matcher.ViewMatchers.withText;
|
|
18
|
+
import static com.wix.detox.espresso.matcher.ViewMatchersKt.isMatchingAtIndex;
|
|
19
|
+
import static com.wix.detox.espresso.matcher.ViewMatchersKt.isOfClassName;
|
|
20
20
|
import static org.hamcrest.Matchers.allOf;
|
|
21
21
|
import static org.hamcrest.Matchers.anyOf;
|
|
22
22
|
import static org.hamcrest.Matchers.is;
|
|
@@ -36,15 +36,15 @@ public class DetoxMatcher {
|
|
|
36
36
|
|
|
37
37
|
public static Matcher<View> matcherForText(String text) {
|
|
38
38
|
// return anyOf(withText(text), withContentDescription(text));
|
|
39
|
-
return allOf(withText(text),
|
|
39
|
+
return allOf(withText(text), withEffectiveVisibility(Visibility.VISIBLE));
|
|
40
40
|
}
|
|
41
41
|
|
|
42
42
|
public static Matcher<View> matcherForContentDescription(String contentDescription) {
|
|
43
|
-
return allOf(withContentDescription(contentDescription),
|
|
43
|
+
return allOf(withContentDescription(contentDescription), withEffectiveVisibility(Visibility.VISIBLE));
|
|
44
44
|
}
|
|
45
45
|
|
|
46
46
|
public static Matcher<View> matcherForTestId(String testId) {
|
|
47
|
-
return allOf(withTagValue(is((Object) testId)),
|
|
47
|
+
return allOf(withTagValue(is((Object) testId)), withEffectiveVisibility(Visibility.VISIBLE));
|
|
48
48
|
}
|
|
49
49
|
|
|
50
50
|
public static Matcher<View> matcherForAnd(Matcher<View> m1, Matcher<View> m2) {
|
|
@@ -67,34 +67,16 @@ public class DetoxMatcher {
|
|
|
67
67
|
return allOf(m, hasDescendant(descendantMatcher));
|
|
68
68
|
}
|
|
69
69
|
|
|
70
|
-
public static Matcher<View> matcherForClass(
|
|
71
|
-
|
|
72
|
-
Class cls = Class.forName(className);
|
|
73
|
-
return allOf(isAssignableFrom(cls), ViewMatchers.withEffectiveVisibility(Visibility.VISIBLE));
|
|
74
|
-
} catch (ClassNotFoundException e) {
|
|
75
|
-
// empty
|
|
76
|
-
}
|
|
77
|
-
return new BaseMatcher<View>() {
|
|
78
|
-
@Override
|
|
79
|
-
public boolean matches(Object item) {
|
|
80
|
-
return false;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
@Override
|
|
84
|
-
public void describeTo(Description description) {
|
|
85
|
-
description.appendText("Class " + className + " not found on classpath. Are you using full class name?");
|
|
86
|
-
}
|
|
87
|
-
};
|
|
70
|
+
public static Matcher<View> matcherForClass(String className) {
|
|
71
|
+
return isOfClassName(className);
|
|
88
72
|
}
|
|
89
73
|
|
|
90
74
|
public static Matcher<View> matcherForSufficientlyVisible() {
|
|
91
75
|
return isDisplayingAtLeast(75);
|
|
92
76
|
}
|
|
93
77
|
|
|
94
|
-
// Special ViewAssertion is needed for GONE views
|
|
95
|
-
@Deprecated
|
|
96
78
|
public static Matcher<View> matcherForNotVisible() {
|
|
97
|
-
return not(isDisplayed());
|
|
79
|
+
return anyOf(nullValue(), not(isDisplayed()));
|
|
98
80
|
}
|
|
99
81
|
|
|
100
82
|
public static Matcher<View> matcherForNotNull() {
|
|
@@ -106,27 +88,7 @@ public class DetoxMatcher {
|
|
|
106
88
|
}
|
|
107
89
|
|
|
108
90
|
public static Matcher<View> matcherForAtIndex(final int index, final Matcher<View> innerMatcher) {
|
|
109
|
-
return
|
|
110
|
-
boolean foundMatch = false;
|
|
111
|
-
int count = 0;
|
|
112
|
-
|
|
113
|
-
@Override
|
|
114
|
-
public boolean matches(Object item) {
|
|
115
|
-
if (!innerMatcher.matches(item) || foundMatch) return false;
|
|
116
|
-
|
|
117
|
-
if (count == index) {
|
|
118
|
-
foundMatch = true;
|
|
119
|
-
return true;
|
|
120
|
-
}
|
|
121
|
-
++count;
|
|
122
|
-
return false;
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
@Override
|
|
126
|
-
public void describeTo(Description description) {
|
|
127
|
-
description.appendText("matches " + index + "th view.");
|
|
128
|
-
}
|
|
129
|
-
};
|
|
91
|
+
return isMatchingAtIndex(index, innerMatcher);
|
|
130
92
|
}
|
|
131
93
|
|
|
132
94
|
public static Matcher<View> matcherForAnything() {
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
package com.wix.detox.espresso.assertion;
|
|
2
|
+
|
|
3
|
+
import android.support.annotation.NonNull;
|
|
4
|
+
import android.view.View;
|
|
5
|
+
|
|
6
|
+
import org.hamcrest.Matcher;
|
|
7
|
+
import org.hamcrest.StringDescription;
|
|
8
|
+
|
|
9
|
+
import androidx.test.espresso.NoMatchingViewException;
|
|
10
|
+
import androidx.test.espresso.ViewAssertion;
|
|
11
|
+
|
|
12
|
+
import static androidx.test.espresso.core.internal.deps.guava.base.Preconditions.checkNotNull;
|
|
13
|
+
import static androidx.test.espresso.matcher.ViewMatchers.assertThat;
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* A custom extension of {@link androidx.test.espresso.assertion.ViewAssertions}.
|
|
17
|
+
*
|
|
18
|
+
* <p/>Perhaps in the future we could extend Espresso's using Kotlin's extension functions.
|
|
19
|
+
*/
|
|
20
|
+
public class ViewAssertions {
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* An alternative to Espresso's {@link androidx.test.espresso.assertion.ViewAssertions#matches(Matcher)},
|
|
24
|
+
* which is more suitable for Detox' separated interaction-matcher architecture.
|
|
25
|
+
* See {@link MatchesViewAssertion} for more details.
|
|
26
|
+
*/
|
|
27
|
+
public static ViewAssertion matches(final Matcher<? super View> viewMatcher) {
|
|
28
|
+
return new MatchesViewAssertion(checkNotNull(viewMatcher));
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Identical to Espresso's {@link androidx.test.espresso.assertion.ViewAssertions}#MatchesViewAssertion
|
|
33
|
+
* typically created by {@link androidx.test.espresso.assertion.ViewAssertions#matches(Matcher)}, except
|
|
34
|
+
* that instead of throwing the {@link NoMatchingViewException} (given to the matcher by the <b>interaction</b>
|
|
35
|
+
* when the view wasn't in the hierarchy), it invokes the matcher nonetheless (i.e. with a <i>null</i> as the item).
|
|
36
|
+
*/
|
|
37
|
+
private static class MatchesViewAssertion implements ViewAssertion {
|
|
38
|
+
final Matcher<? super View> viewMatcher;
|
|
39
|
+
|
|
40
|
+
private MatchesViewAssertion(final Matcher<? super View> viewMatcher) {
|
|
41
|
+
this.viewMatcher = viewMatcher;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
@Override
|
|
45
|
+
public void check(View view, NoMatchingViewException noViewException) {
|
|
46
|
+
StringDescription description = new StringDescription();
|
|
47
|
+
description.appendText("'");
|
|
48
|
+
viewMatcher.describeTo(description);
|
|
49
|
+
|
|
50
|
+
description.appendText("' doesn't match the selected view.");
|
|
51
|
+
|
|
52
|
+
assertThat(description.toString(), noViewException != null ? null : view, viewMatcher);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
@NonNull
|
|
56
|
+
@Override
|
|
57
|
+
public String toString() {
|
|
58
|
+
return String.format("MatchesViewAssertion(Detox){viewMatcher=%s}", viewMatcher);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
package/android/detox/src/main/java/com/wix/detox/espresso/matcher/NullableTypeSafeMatcher.java
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
package com.wix.detox.espresso.matcher;
|
|
2
|
+
|
|
3
|
+
import org.hamcrest.BaseMatcher;
|
|
4
|
+
import org.hamcrest.Description;
|
|
5
|
+
import org.hamcrest.internal.ReflectiveTypeFinder;
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Identical to Espresso's {@link org.hamcrest.TypeSafeMatcher}, but allows nulls (in which case
|
|
9
|
+
* the "item" is passed-in into the sub-class nonetheless, as a null).
|
|
10
|
+
*/
|
|
11
|
+
public abstract class NullableTypeSafeMatcher<T> extends BaseMatcher<T> {
|
|
12
|
+
private static final ReflectiveTypeFinder TYPE_FINDER = new ReflectiveTypeFinder("matchesSafely", 1, 0);
|
|
13
|
+
|
|
14
|
+
final private Class<?> expectedType;
|
|
15
|
+
|
|
16
|
+
protected NullableTypeSafeMatcher() {
|
|
17
|
+
this(TYPE_FINDER);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
protected NullableTypeSafeMatcher(Class<?> expectedType) {
|
|
21
|
+
this.expectedType = expectedType;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
private NullableTypeSafeMatcher(ReflectiveTypeFinder typeFinder) {
|
|
25
|
+
this.expectedType = typeFinder.findExpectedType(getClass());
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Subclasses should implement this. The item will already have been checked for
|
|
30
|
+
* the specific type and will never be null.
|
|
31
|
+
*/
|
|
32
|
+
abstract boolean matchesSafely(T item);
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Subclasses should override this. The item will already have been checked for
|
|
36
|
+
* the specific type and will never be null.
|
|
37
|
+
*/
|
|
38
|
+
void describeMismatchSafely(T item, Description mismatchDescription) {
|
|
39
|
+
super.describeMismatch(item, mismatchDescription);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
@Override
|
|
43
|
+
@SuppressWarnings({"unchecked"})
|
|
44
|
+
public final boolean matches(Object item) {
|
|
45
|
+
return (item == null || expectedType.isInstance(item)) && matchesSafely((T) item);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
@SuppressWarnings("unchecked")
|
|
49
|
+
@Override
|
|
50
|
+
final public void describeMismatch(Object item, Description description) {
|
|
51
|
+
if (!expectedType.isInstance(item)) {
|
|
52
|
+
description.appendText("was a ")
|
|
53
|
+
.appendText(item.getClass().getName())
|
|
54
|
+
.appendText(" (")
|
|
55
|
+
.appendValue(item)
|
|
56
|
+
.appendText(")");
|
|
57
|
+
} else {
|
|
58
|
+
describeMismatchSafely((T) item, description);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
package com.wix.detox.espresso.matcher
|
|
2
|
+
|
|
3
|
+
import android.view.View
|
|
4
|
+
import org.hamcrest.BaseMatcher
|
|
5
|
+
import org.hamcrest.Description
|
|
6
|
+
import org.hamcrest.Matcher
|
|
7
|
+
|
|
8
|
+
class ViewAtIndexMatcher(private val index: Int, private val innerMatcher: Matcher<View>) : BaseMatcher<View>() {
|
|
9
|
+
private var foundMatch = false
|
|
10
|
+
private var count = 0
|
|
11
|
+
|
|
12
|
+
override fun matches(item: Any): Boolean {
|
|
13
|
+
if (!innerMatcher.matches(item) || foundMatch) return false
|
|
14
|
+
|
|
15
|
+
if (count == index) {
|
|
16
|
+
foundMatch = true
|
|
17
|
+
return true
|
|
18
|
+
}
|
|
19
|
+
++count
|
|
20
|
+
return false
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
override fun describeTo(description: Description) {
|
|
24
|
+
description.appendText("matches " + index + "th view.")
|
|
25
|
+
}
|
|
26
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
package com.wix.detox.espresso.matcher
|
|
2
|
+
|
|
3
|
+
import android.view.View
|
|
4
|
+
import androidx.test.espresso.matcher.ViewMatchers
|
|
5
|
+
import androidx.test.espresso.matcher.ViewMatchers.*
|
|
6
|
+
import org.hamcrest.BaseMatcher
|
|
7
|
+
import org.hamcrest.Description
|
|
8
|
+
|
|
9
|
+
import org.hamcrest.Matcher
|
|
10
|
+
import org.hamcrest.Matchers.*
|
|
11
|
+
|
|
12
|
+
/*
|
|
13
|
+
* An extension of [androidx.test.espresso.matcher.ViewMatchers].
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
fun isOfClassName(className: String): Matcher<View> {
|
|
17
|
+
try {
|
|
18
|
+
val cls = Class.forName(className)
|
|
19
|
+
return allOf(isAssignableFrom(cls as Class<out View>?), withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE))
|
|
20
|
+
} catch (e: ClassNotFoundException) {
|
|
21
|
+
// empty
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
return object : BaseMatcher<View>() {
|
|
25
|
+
override fun matches(item: Any): Boolean {
|
|
26
|
+
return false
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
override fun describeTo(description: Description) {
|
|
30
|
+
description.appendText("Class $className not found on classpath. Are you using full class name?")
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
fun isMatchingAtIndex(index: Int, innerMatcher: Matcher<View>): Matcher<View> = ViewAtIndexMatcher(index, innerMatcher)
|
package/package.json
CHANGED
package/scripts/postinstall.js
CHANGED
package/src/android/expect.js
CHANGED
|
@@ -146,24 +146,23 @@ class MatcherAssertionInteraction extends Interaction {
|
|
|
146
146
|
}
|
|
147
147
|
|
|
148
148
|
class WaitForInteraction extends Interaction {
|
|
149
|
-
constructor(invocationManager, element,
|
|
149
|
+
constructor(invocationManager, element, assertionMatcher) {
|
|
150
150
|
super(invocationManager);
|
|
151
151
|
this._element = element;
|
|
152
|
-
this.
|
|
153
|
-
|
|
154
|
-
this._element._selectElementWithMatcher(this._element._originalMatcher.and(this._originalMatcher));
|
|
152
|
+
this._assertionMatcher = assertionMatcher;
|
|
153
|
+
this._element._selectElementWithMatcher(this._element._originalMatcher);
|
|
155
154
|
}
|
|
156
155
|
|
|
157
156
|
async withTimeout(timeout) {
|
|
158
157
|
if (typeof timeout !== 'number') throw new Error(`WaitForInteraction withTimeout argument must be a number, got ${typeof timeout}`);
|
|
159
158
|
if (timeout < 0) throw new Error('timeout must be larger than 0');
|
|
160
159
|
|
|
161
|
-
this._call = DetoxAssertionApi.waitForAssertMatcher(call(this._element._call), this.
|
|
160
|
+
this._call = DetoxAssertionApi.waitForAssertMatcher(call(this._element._call), this._assertionMatcher._call.value, timeout / 1000);
|
|
162
161
|
await this.execute();
|
|
163
162
|
}
|
|
164
163
|
|
|
165
164
|
whileElement(searchMatcher) {
|
|
166
|
-
return new WaitForActionInteraction(this._invocationManager, this._element, this.
|
|
165
|
+
return new WaitForActionInteraction(this._invocationManager, this._element, this._assertionMatcher, searchMatcher);
|
|
167
166
|
}
|
|
168
167
|
}
|
|
169
168
|
|
|
@@ -66,6 +66,10 @@ class ADB {
|
|
|
66
66
|
let device;
|
|
67
67
|
if (this.isEmulator(deviceAdbName)) {
|
|
68
68
|
const port = _.split(deviceAdbName, '-')[1];
|
|
69
|
+
if (!port) {
|
|
70
|
+
_reportTelnetPortResolutionError(input, devicesList, deviceAdbName, port);
|
|
71
|
+
}
|
|
72
|
+
|
|
69
73
|
const telnet = new EmulatorTelnet();
|
|
70
74
|
await telnet.connect(port);
|
|
71
75
|
const name = await telnet.avdName();
|
|
@@ -103,7 +107,7 @@ class ADB {
|
|
|
103
107
|
|
|
104
108
|
async install(deviceId, apkPath) {
|
|
105
109
|
apkPath = `"${escape.inQuotedString(apkPath)}"`;
|
|
106
|
-
|
|
110
|
+
|
|
107
111
|
const apiLvl = await this.apiLevel(deviceId);
|
|
108
112
|
|
|
109
113
|
let childProcess;
|
|
@@ -283,4 +287,20 @@ class ADB {
|
|
|
283
287
|
}
|
|
284
288
|
}
|
|
285
289
|
|
|
290
|
+
function _reportTelnetPortResolutionError(input, devicesList, deviceAdbName, port) {
|
|
291
|
+
const {encodeBase64} = require('../../utils/encoding');
|
|
292
|
+
const errorMessage = [
|
|
293
|
+
`Failed to determine telnet port for emulator device '${deviceAdbName}'!`,
|
|
294
|
+
`Please help us out by reporting dump below in: https://github.com/wix/Detox/issues/1427`,
|
|
295
|
+
`------ BEGIN DUMP ------`,
|
|
296
|
+
`adb devices base64: ${encodeBase64(input)}`,
|
|
297
|
+
`adb devices: ${input}`,
|
|
298
|
+
`devicesList: ${devicesList}`,
|
|
299
|
+
`port: ${port}`,
|
|
300
|
+
`------ END DUMP ------`,
|
|
301
|
+
].join('\n');
|
|
302
|
+
|
|
303
|
+
throw new Error(errorMessage);
|
|
304
|
+
}
|
|
305
|
+
|
|
286
306
|
module.exports = ADB;
|
|
Binary file
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
2ffc142c41adab57c69b5734d7365c04
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
76015cb8e56dedd347bbaaf4d0086365514eaf71
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
b221b88bb3ca15e4fffa4ff7ec7859f2
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
82510015f66a4183ed32e936580c2540faf3d8ab
|
|
Binary file
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
33bd91bd0ebde41adf798e01136d1284
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
d4450848b274ac5fe0bcecbeff8067fe2c9b5931
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
4b13101aba4d44277dcfcdee0d6e0a3f
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
cf53b31d8541c0e04fcc2207722c53c76c7f7b98
|