appium-espresso-driver 2.13.1 → 2.13.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/espresso-server/app/build/outputs/apk/androidTest/debug/app-debug-androidTest.apk +0 -0
- package/espresso-server/app/src/androidTest/java/io/appium/espressoserver/lib/helpers/ComposeNodeFinder.kt +6 -2
- package/espresso-server/app/src/androidTest/java/io/appium/espressoserver/lib/helpers/ViewFinder.kt +2 -2
- package/espresso-server/app/src/androidTest/java/io/appium/espressoserver/lib/model/SourceDocument.kt +15 -17
- package/espresso-server/app/src/androidTest/java/io/appium/espressoserver/lib/viewmatcher/WithXPath.kt +21 -2
- package/npm-shrinkwrap.json +16 -16
- package/package.json +1 -1
|
Binary file
|
|
@@ -26,6 +26,7 @@ import io.appium.espressoserver.lib.handlers.exceptions.StaleElementException
|
|
|
26
26
|
import io.appium.espressoserver.lib.model.Locator
|
|
27
27
|
import io.appium.espressoserver.lib.model.SourceDocument
|
|
28
28
|
import io.appium.espressoserver.lib.model.AttributesEnum
|
|
29
|
+
import io.appium.espressoserver.lib.model.compileXpathExpression
|
|
29
30
|
import io.appium.espressoserver.lib.viewmatcher.fetchIncludedAttributes
|
|
30
31
|
|
|
31
32
|
/**
|
|
@@ -63,9 +64,12 @@ fun semanticsMatcherForLocator(locator: Locator): SemanticsMatcher =
|
|
|
63
64
|
}
|
|
64
65
|
|
|
65
66
|
private fun hasXpath(locator: Locator): SemanticsMatcher {
|
|
67
|
+
val xpath = locator.value!!
|
|
68
|
+
val expression = compileXpathExpression(xpath)
|
|
69
|
+
val attributes = fetchIncludedAttributes(xpath)
|
|
66
70
|
val matchingIds = SourceDocument(
|
|
67
|
-
locator.elementId?.let { getSemanticsNode(it) },
|
|
68
|
-
).
|
|
71
|
+
locator.elementId?.let { getSemanticsNode(it) }, attributes
|
|
72
|
+
).findMatchingNodeIds(expression, AttributesEnum.RESOURCE_ID.toString())
|
|
69
73
|
|
|
70
74
|
return SemanticsMatcher("Matches Xpath ${locator.value}") {
|
|
71
75
|
matchingIds.contains(it.id)
|
package/espresso-server/app/src/androidTest/java/io/appium/espressoserver/lib/helpers/ViewFinder.kt
CHANGED
|
@@ -168,8 +168,8 @@ object ViewFinder {
|
|
|
168
168
|
// If we're only looking for one item that matches xpath, pass it index 0 or else
|
|
169
169
|
// Espresso throws an AmbiguousMatcherException
|
|
170
170
|
return getViews(
|
|
171
|
-
|
|
172
|
-
|
|
171
|
+
withXPath(parent, selector, if (findOne) 0 else null),
|
|
172
|
+
findOne,
|
|
173
173
|
parent
|
|
174
174
|
).map { ViewState(it) }
|
|
175
175
|
Strategy.VIEW_TAG ->
|
|
@@ -80,6 +80,12 @@ private fun toXmlNodeName(className: String?): String {
|
|
|
80
80
|
return fixedName
|
|
81
81
|
}
|
|
82
82
|
|
|
83
|
+
fun compileXpathExpression(selector: String): XPathExpression =
|
|
84
|
+
try {
|
|
85
|
+
XPATH.compile(selector)
|
|
86
|
+
} catch (xe: XPathExpressionException) {
|
|
87
|
+
throw XPathLookupException(selector, xe.message!!)
|
|
88
|
+
}
|
|
83
89
|
|
|
84
90
|
class SourceDocument constructor(
|
|
85
91
|
private val root: Any? = null,
|
|
@@ -324,8 +330,8 @@ class SourceDocument constructor(
|
|
|
324
330
|
throw AppiumException(lastError!!)
|
|
325
331
|
}
|
|
326
332
|
|
|
327
|
-
private fun rootSemanticNodes(): List<SemanticsNode>
|
|
328
|
-
|
|
333
|
+
private fun rootSemanticNodes(): List<SemanticsNode> =
|
|
334
|
+
try {
|
|
329
335
|
listOf(EspressoServerRunnerTest.composeTestRule.onRoot(useUnmergedTree = true).fetchSemanticsNode())
|
|
330
336
|
} catch (e: AssertionError) {
|
|
331
337
|
// Ideally there should be on `root` node but on some cases e.g:overlays screen, there can be more than 1 root.
|
|
@@ -337,7 +343,6 @@ class SourceDocument constructor(
|
|
|
337
343
|
} as SelectionResult
|
|
338
344
|
result.selectedNodes
|
|
339
345
|
}
|
|
340
|
-
}
|
|
341
346
|
|
|
342
347
|
private fun performCleanup() {
|
|
343
348
|
tmpXmlName?.let {
|
|
@@ -346,8 +351,8 @@ class SourceDocument constructor(
|
|
|
346
351
|
}
|
|
347
352
|
}
|
|
348
353
|
|
|
349
|
-
fun toXMLString(): String
|
|
350
|
-
|
|
354
|
+
fun toXMLString(): String =
|
|
355
|
+
RESOURCES_GUARD.withPermit({
|
|
351
356
|
toStream().use { xmlStream ->
|
|
352
357
|
val sb = StringBuilder()
|
|
353
358
|
val reader = BufferedReader(InputStreamReader(xmlStream, XML_ENCODING))
|
|
@@ -359,24 +364,17 @@ class SourceDocument constructor(
|
|
|
359
364
|
sb.toString()
|
|
360
365
|
}
|
|
361
366
|
}, { performCleanup() })
|
|
362
|
-
}
|
|
363
367
|
|
|
364
|
-
fun findViewsByXPath(
|
|
365
|
-
|
|
368
|
+
fun findViewsByXPath(expression: XPathExpression): List<View> =
|
|
369
|
+
findMatchingNodeIds(expression, VIEW_INDEX).map { viewMap.get(it) }
|
|
366
370
|
|
|
367
|
-
fun
|
|
368
|
-
|
|
369
|
-
XPATH.compile(xpathSelector)
|
|
370
|
-
} catch (xe: XPathExpressionException) {
|
|
371
|
-
throw XPathLookupException(xpathSelector, xe.message!!)
|
|
372
|
-
}
|
|
373
|
-
return RESOURCES_GUARD.withPermit({
|
|
371
|
+
fun findMatchingNodeIds(expression: XPathExpression, attributeName: String): List<Int> =
|
|
372
|
+
RESOURCES_GUARD.withPermit({
|
|
374
373
|
toStream().use { xmlStream ->
|
|
375
|
-
val list =
|
|
374
|
+
val list = expression.evaluate(InputSource(xmlStream), XPathConstants.NODESET) as NodeList
|
|
376
375
|
(0 until list.length).map { index ->
|
|
377
376
|
list.item(index).attributes.getNamedItem(attributeName).nodeValue.toInt()
|
|
378
377
|
}
|
|
379
378
|
}
|
|
380
379
|
}, { performCleanup() })
|
|
381
|
-
}
|
|
382
380
|
}
|
|
@@ -16,12 +16,15 @@
|
|
|
16
16
|
package io.appium.espressoserver.lib.viewmatcher
|
|
17
17
|
|
|
18
18
|
import android.view.View
|
|
19
|
+
import io.appium.espressoserver.lib.helpers.extensions.withPermit
|
|
19
20
|
import io.appium.espressoserver.lib.model.SourceDocument
|
|
20
21
|
import io.appium.espressoserver.lib.model.AttributesEnum
|
|
21
22
|
import io.appium.espressoserver.lib.model.EspressoAttributes
|
|
23
|
+
import io.appium.espressoserver.lib.model.compileXpathExpression
|
|
22
24
|
import org.hamcrest.Description
|
|
23
25
|
import org.hamcrest.Matcher
|
|
24
26
|
import org.hamcrest.TypeSafeMatcher
|
|
27
|
+
import java.util.concurrent.Semaphore
|
|
25
28
|
|
|
26
29
|
fun fetchIncludedAttributes(xpath: String): Set<AttributesEnum>? {
|
|
27
30
|
if (xpath.contains("@*")) {
|
|
@@ -37,10 +40,26 @@ fun fetchIncludedAttributes(xpath: String): Set<AttributesEnum>? {
|
|
|
37
40
|
}
|
|
38
41
|
|
|
39
42
|
fun withXPath(root: View?, xpath: String, index: Int? = null): Matcher<View> {
|
|
40
|
-
|
|
41
|
-
val
|
|
43
|
+
val expression = compileXpathExpression(xpath)
|
|
44
|
+
val attributes = fetchIncludedAttributes(xpath)
|
|
45
|
+
val matchedXPathViews = mutableListOf<View>()
|
|
46
|
+
var didLookup = false
|
|
47
|
+
val lookupGuard = Semaphore(1)
|
|
42
48
|
return object : TypeSafeMatcher<View>() {
|
|
43
49
|
override fun matchesSafely(item: View): Boolean {
|
|
50
|
+
lookupGuard.withPermit {
|
|
51
|
+
if (!didLookup) {
|
|
52
|
+
matchedXPathViews.addAll(
|
|
53
|
+
SourceDocument(root ?: item.rootView, attributes).findViewsByXPath(expression)
|
|
54
|
+
)
|
|
55
|
+
didLookup = true
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
if (matchedXPathViews.isEmpty()) {
|
|
60
|
+
return false
|
|
61
|
+
}
|
|
62
|
+
|
|
44
63
|
return if (index != null) {
|
|
45
64
|
// If index is not null, match it with the xpath in the list at the provided index
|
|
46
65
|
index < matchedXPathViews.size && matchedXPathViews[index] == item
|
package/npm-shrinkwrap.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "appium-espresso-driver",
|
|
3
|
-
"version": "2.13.
|
|
3
|
+
"version": "2.13.3",
|
|
4
4
|
"lockfileVersion": 2,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "appium-espresso-driver",
|
|
9
|
-
"version": "2.13.
|
|
9
|
+
"version": "2.13.3",
|
|
10
10
|
"license": "Apache-2.0",
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"@babel/runtime": "^7.4.3",
|
|
@@ -304,7 +304,7 @@
|
|
|
304
304
|
}
|
|
305
305
|
},
|
|
306
306
|
"node_modules/@babel/parser": {
|
|
307
|
-
"version": "7.
|
|
307
|
+
"version": "7.20.0",
|
|
308
308
|
"extraneous": true,
|
|
309
309
|
"license": "MIT",
|
|
310
310
|
"bin": {
|
|
@@ -315,10 +315,10 @@
|
|
|
315
315
|
}
|
|
316
316
|
},
|
|
317
317
|
"node_modules/@babel/runtime": {
|
|
318
|
-
"version": "7.
|
|
318
|
+
"version": "7.20.0",
|
|
319
319
|
"license": "MIT",
|
|
320
320
|
"dependencies": {
|
|
321
|
-
"regenerator-runtime": "^0.13.
|
|
321
|
+
"regenerator-runtime": "^0.13.10"
|
|
322
322
|
},
|
|
323
323
|
"engines": {
|
|
324
324
|
"node": ">=6.9.0"
|
|
@@ -1000,7 +1000,7 @@
|
|
|
1000
1000
|
}
|
|
1001
1001
|
},
|
|
1002
1002
|
"node_modules/@types/node": {
|
|
1003
|
-
"version": "18.11.
|
|
1003
|
+
"version": "18.11.7",
|
|
1004
1004
|
"license": "MIT"
|
|
1005
1005
|
},
|
|
1006
1006
|
"node_modules/@types/normalize-package-data": {
|
|
@@ -1252,7 +1252,7 @@
|
|
|
1252
1252
|
}
|
|
1253
1253
|
},
|
|
1254
1254
|
"node_modules/appium-android-driver": {
|
|
1255
|
-
"version": "5.
|
|
1255
|
+
"version": "5.7.0",
|
|
1256
1256
|
"license": "Apache-2.0",
|
|
1257
1257
|
"dependencies": {
|
|
1258
1258
|
"@babel/runtime": "^7.0.0",
|
|
@@ -1316,7 +1316,7 @@
|
|
|
1316
1316
|
}
|
|
1317
1317
|
},
|
|
1318
1318
|
"node_modules/appium-chromedriver": {
|
|
1319
|
-
"version": "5.2.
|
|
1319
|
+
"version": "5.2.5",
|
|
1320
1320
|
"hasInstallScript": true,
|
|
1321
1321
|
"license": "Apache-2.0",
|
|
1322
1322
|
"dependencies": {
|
|
@@ -2755,7 +2755,7 @@
|
|
|
2755
2755
|
}
|
|
2756
2756
|
},
|
|
2757
2757
|
"node_modules/io.appium.settings": {
|
|
2758
|
-
"version": "4.2.
|
|
2758
|
+
"version": "4.2.2",
|
|
2759
2759
|
"license": "Apache-2.0",
|
|
2760
2760
|
"engines": {
|
|
2761
2761
|
"node": ">=14",
|
|
@@ -5383,13 +5383,13 @@
|
|
|
5383
5383
|
}
|
|
5384
5384
|
},
|
|
5385
5385
|
"@babel/parser": {
|
|
5386
|
-
"version": "7.
|
|
5386
|
+
"version": "7.20.0",
|
|
5387
5387
|
"extraneous": true
|
|
5388
5388
|
},
|
|
5389
5389
|
"@babel/runtime": {
|
|
5390
|
-
"version": "7.
|
|
5390
|
+
"version": "7.20.0",
|
|
5391
5391
|
"requires": {
|
|
5392
|
-
"regenerator-runtime": "^0.13.
|
|
5392
|
+
"regenerator-runtime": "^0.13.10"
|
|
5393
5393
|
}
|
|
5394
5394
|
},
|
|
5395
5395
|
"@colors/colors": {
|
|
@@ -5863,7 +5863,7 @@
|
|
|
5863
5863
|
}
|
|
5864
5864
|
},
|
|
5865
5865
|
"@types/node": {
|
|
5866
|
-
"version": "18.11.
|
|
5866
|
+
"version": "18.11.7"
|
|
5867
5867
|
},
|
|
5868
5868
|
"@types/normalize-package-data": {
|
|
5869
5869
|
"version": "2.4.1"
|
|
@@ -6039,7 +6039,7 @@
|
|
|
6039
6039
|
}
|
|
6040
6040
|
},
|
|
6041
6041
|
"appium-android-driver": {
|
|
6042
|
-
"version": "5.
|
|
6042
|
+
"version": "5.7.0",
|
|
6043
6043
|
"requires": {
|
|
6044
6044
|
"@babel/runtime": "^7.0.0",
|
|
6045
6045
|
"appium-adb": "^9.10.9",
|
|
@@ -6087,7 +6087,7 @@
|
|
|
6087
6087
|
}
|
|
6088
6088
|
},
|
|
6089
6089
|
"appium-chromedriver": {
|
|
6090
|
-
"version": "5.2.
|
|
6090
|
+
"version": "5.2.5",
|
|
6091
6091
|
"requires": {
|
|
6092
6092
|
"@babel/runtime": "^7.0.0",
|
|
6093
6093
|
"@xmldom/xmldom": "^0.x",
|
|
@@ -7035,7 +7035,7 @@
|
|
|
7035
7035
|
}
|
|
7036
7036
|
},
|
|
7037
7037
|
"io.appium.settings": {
|
|
7038
|
-
"version": "4.2.
|
|
7038
|
+
"version": "4.2.2"
|
|
7039
7039
|
},
|
|
7040
7040
|
"ipaddr.js": {
|
|
7041
7041
|
"version": "1.9.1",
|