appium-espresso-driver 2.13.2 → 2.13.4
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/CHANGELOG.md +25 -0
- 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/model/SourceDocument.kt +15 -17
- package/espresso-server/app/src/androidTest/java/io/appium/espressoserver/lib/viewmatcher/WithXPath.kt +17 -3
- package/npm-shrinkwrap.json +28 -16
- package/package.json +4 -2
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
## [2.13.4](https://github.com/appium/appium-espresso-driver/compare/v2.13.3...v2.13.4) (2022-11-06)
|
|
2
|
+
|
|
3
|
+
## [1.0.0-beta.3](https://github.com/appium/appium-espresso-driver/compare/v1.0.0-beta.2...v1.0.0-beta.3) (2017-06-16)
|
|
4
|
+
|
|
5
|
+
### Changes
|
|
6
|
+
* Fix: Throws exception if element is stale (#56)
|
|
7
|
+
* Feature: Add text attribute to source xml (#52)
|
|
8
|
+
* Feature: Implemented the /element/:elementId/text endpoint (#53)
|
|
9
|
+
* Feature: Can match list of XPaths instead of just one (#54)
|
|
10
|
+
* Feature: Added handler for /elements endpoint (#55)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
## [1.0.0-beta.2](https://github.com/appium/appium-espresso-driver/compare/v1.0.0-beta.1...v1.0.0-beta.2) (2017-06-09)
|
|
14
|
+
|
|
15
|
+
### Changes
|
|
16
|
+
* Fix: Sanitize XML inputs. Bad characters and tag names were breaking the XML (#50)
|
|
17
|
+
|
|
18
|
+
## [1.0.0-beta.1](https://github.com/appium/appium-espresso-driver/compare/7a309d3...v1.0.0-beta.1) (2017-06-08)
|
|
19
|
+
|
|
20
|
+
### Changes
|
|
21
|
+
* Feature: Implemented NanoHTTPD Java server that runs inside of Android and follows the MJSONWP standard
|
|
22
|
+
* Feature: Implemented NodeJS driver that launches the Java server and proxies requests to that server
|
|
23
|
+
* Feature: Can locate elements with the selector strategies xpath, class, id, text, accessibility id
|
|
24
|
+
* Feature: Created /session, /status, /source, /screenshot, /back endpoints
|
|
25
|
+
* Feature: Added handling for every MJSONWP endpoint, return NotYetImplemented for unimplemented handlers
|
|
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)
|
|
@@ -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,13 +40,24 @@ fun fetchIncludedAttributes(xpath: String): Set<AttributesEnum>? {
|
|
|
37
40
|
}
|
|
38
41
|
|
|
39
42
|
fun withXPath(root: View?, xpath: String, index: Int? = null): Matcher<View> {
|
|
43
|
+
val expression = compileXpathExpression(xpath)
|
|
44
|
+
val attributes = fetchIncludedAttributes(xpath)
|
|
40
45
|
val matchedXPathViews = mutableListOf<View>()
|
|
46
|
+
var didLookup = false
|
|
47
|
+
val lookupGuard = Semaphore(1)
|
|
41
48
|
return object : TypeSafeMatcher<View>() {
|
|
42
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
|
+
|
|
43
59
|
if (matchedXPathViews.isEmpty()) {
|
|
44
|
-
|
|
45
|
-
SourceDocument(root ?: item.rootView, fetchIncludedAttributes(xpath)).findViewsByXPath(xpath)
|
|
46
|
-
)
|
|
60
|
+
return false
|
|
47
61
|
}
|
|
48
62
|
|
|
49
63
|
return if (index != null) {
|
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.4",
|
|
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.4",
|
|
10
10
|
"license": "Apache-2.0",
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"@babel/runtime": "^7.4.3",
|
|
@@ -28,6 +28,7 @@
|
|
|
28
28
|
"@babel/plugin-transform-runtime": "^7.18.10",
|
|
29
29
|
"@babel/preset-env": "^7.18.10",
|
|
30
30
|
"@babel/register": "^7.18.9",
|
|
31
|
+
"@semantic-release/changelog": "^6.0.1",
|
|
31
32
|
"@semantic-release/git": "^10.0.1",
|
|
32
33
|
"@xmldom/xmldom": "^0.x",
|
|
33
34
|
"android-apidemos": "^4.1.1",
|
|
@@ -92,6 +93,11 @@
|
|
|
92
93
|
"npm": ">=8"
|
|
93
94
|
}
|
|
94
95
|
},
|
|
96
|
+
"node_modules/@appium/base-driver/node_modules/async-lock": {
|
|
97
|
+
"version": "1.3.2",
|
|
98
|
+
"extraneous": true,
|
|
99
|
+
"license": "MIT"
|
|
100
|
+
},
|
|
95
101
|
"node_modules/@appium/base-plugin": {
|
|
96
102
|
"version": "1.10.5",
|
|
97
103
|
"extraneous": true,
|
|
@@ -304,7 +310,7 @@
|
|
|
304
310
|
}
|
|
305
311
|
},
|
|
306
312
|
"node_modules/@babel/parser": {
|
|
307
|
-
"version": "7.20.
|
|
313
|
+
"version": "7.20.2",
|
|
308
314
|
"extraneous": true,
|
|
309
315
|
"license": "MIT",
|
|
310
316
|
"bin": {
|
|
@@ -315,7 +321,7 @@
|
|
|
315
321
|
}
|
|
316
322
|
},
|
|
317
323
|
"node_modules/@babel/runtime": {
|
|
318
|
-
"version": "7.20.
|
|
324
|
+
"version": "7.20.1",
|
|
319
325
|
"license": "MIT",
|
|
320
326
|
"dependencies": {
|
|
321
327
|
"regenerator-runtime": "^0.13.10"
|
|
@@ -1000,7 +1006,7 @@
|
|
|
1000
1006
|
}
|
|
1001
1007
|
},
|
|
1002
1008
|
"node_modules/@types/node": {
|
|
1003
|
-
"version": "18.11.
|
|
1009
|
+
"version": "18.11.9",
|
|
1004
1010
|
"license": "MIT"
|
|
1005
1011
|
},
|
|
1006
1012
|
"node_modules/@types/normalize-package-data": {
|
|
@@ -1116,7 +1122,7 @@
|
|
|
1116
1122
|
}
|
|
1117
1123
|
},
|
|
1118
1124
|
"node_modules/@xmldom/xmldom": {
|
|
1119
|
-
"version": "0.8.
|
|
1125
|
+
"version": "0.8.6",
|
|
1120
1126
|
"license": "MIT",
|
|
1121
1127
|
"engines": {
|
|
1122
1128
|
"node": ">=10.0.0"
|
|
@@ -1466,7 +1472,7 @@
|
|
|
1466
1472
|
"license": "MIT"
|
|
1467
1473
|
},
|
|
1468
1474
|
"node_modules/async-lock": {
|
|
1469
|
-
"version": "1.
|
|
1475
|
+
"version": "1.4.0",
|
|
1470
1476
|
"license": "MIT"
|
|
1471
1477
|
},
|
|
1472
1478
|
"node_modules/asyncbox": {
|
|
@@ -2755,7 +2761,7 @@
|
|
|
2755
2761
|
}
|
|
2756
2762
|
},
|
|
2757
2763
|
"node_modules/io.appium.settings": {
|
|
2758
|
-
"version": "4.2.
|
|
2764
|
+
"version": "4.2.3",
|
|
2759
2765
|
"license": "Apache-2.0",
|
|
2760
2766
|
"engines": {
|
|
2761
2767
|
"node": ">=14",
|
|
@@ -3356,7 +3362,7 @@
|
|
|
3356
3362
|
}
|
|
3357
3363
|
},
|
|
3358
3364
|
"node_modules/marked": {
|
|
3359
|
-
"version": "4.
|
|
3365
|
+
"version": "4.2.2",
|
|
3360
3366
|
"extraneous": true,
|
|
3361
3367
|
"license": "MIT",
|
|
3362
3368
|
"bin": {
|
|
@@ -5227,6 +5233,12 @@
|
|
|
5227
5233
|
"source-map-support": "0.5.21",
|
|
5228
5234
|
"type-fest": "3.1.0",
|
|
5229
5235
|
"validate.js": "0.13.1"
|
|
5236
|
+
},
|
|
5237
|
+
"dependencies": {
|
|
5238
|
+
"async-lock": {
|
|
5239
|
+
"version": "1.3.2",
|
|
5240
|
+
"extraneous": true
|
|
5241
|
+
}
|
|
5230
5242
|
}
|
|
5231
5243
|
},
|
|
5232
5244
|
"@appium/base-plugin": {
|
|
@@ -5383,11 +5395,11 @@
|
|
|
5383
5395
|
}
|
|
5384
5396
|
},
|
|
5385
5397
|
"@babel/parser": {
|
|
5386
|
-
"version": "7.20.
|
|
5398
|
+
"version": "7.20.2",
|
|
5387
5399
|
"extraneous": true
|
|
5388
5400
|
},
|
|
5389
5401
|
"@babel/runtime": {
|
|
5390
|
-
"version": "7.20.
|
|
5402
|
+
"version": "7.20.1",
|
|
5391
5403
|
"requires": {
|
|
5392
5404
|
"regenerator-runtime": "^0.13.10"
|
|
5393
5405
|
}
|
|
@@ -5863,7 +5875,7 @@
|
|
|
5863
5875
|
}
|
|
5864
5876
|
},
|
|
5865
5877
|
"@types/node": {
|
|
5866
|
-
"version": "18.11.
|
|
5878
|
+
"version": "18.11.9"
|
|
5867
5879
|
},
|
|
5868
5880
|
"@types/normalize-package-data": {
|
|
5869
5881
|
"version": "2.4.1"
|
|
@@ -5949,7 +5961,7 @@
|
|
|
5949
5961
|
}
|
|
5950
5962
|
},
|
|
5951
5963
|
"@xmldom/xmldom": {
|
|
5952
|
-
"version": "0.8.
|
|
5964
|
+
"version": "0.8.6"
|
|
5953
5965
|
},
|
|
5954
5966
|
"accepts": {
|
|
5955
5967
|
"version": "1.3.8",
|
|
@@ -6200,7 +6212,7 @@
|
|
|
6200
6212
|
"version": "3.2.4"
|
|
6201
6213
|
},
|
|
6202
6214
|
"async-lock": {
|
|
6203
|
-
"version": "1.
|
|
6215
|
+
"version": "1.4.0"
|
|
6204
6216
|
},
|
|
6205
6217
|
"asyncbox": {
|
|
6206
6218
|
"version": "2.9.2",
|
|
@@ -7035,7 +7047,7 @@
|
|
|
7035
7047
|
}
|
|
7036
7048
|
},
|
|
7037
7049
|
"io.appium.settings": {
|
|
7038
|
-
"version": "4.2.
|
|
7050
|
+
"version": "4.2.3"
|
|
7039
7051
|
},
|
|
7040
7052
|
"ipaddr.js": {
|
|
7041
7053
|
"version": "1.9.1",
|
|
@@ -7425,7 +7437,7 @@
|
|
|
7425
7437
|
"requires": {}
|
|
7426
7438
|
},
|
|
7427
7439
|
"marked": {
|
|
7428
|
-
"version": "4.
|
|
7440
|
+
"version": "4.2.2",
|
|
7429
7441
|
"extraneous": true
|
|
7430
7442
|
},
|
|
7431
7443
|
"mdurl": {
|
package/package.json
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
"automated testing",
|
|
8
8
|
"android"
|
|
9
9
|
],
|
|
10
|
-
"version": "2.13.
|
|
10
|
+
"version": "2.13.4",
|
|
11
11
|
"author": "Appium Contributors",
|
|
12
12
|
"license": "Apache-2.0",
|
|
13
13
|
"repository": {
|
|
@@ -57,7 +57,8 @@
|
|
|
57
57
|
"espresso-server/build.gradle.kts",
|
|
58
58
|
"espresso-server/settings.gradle.kts",
|
|
59
59
|
"espresso-server/lint.xml",
|
|
60
|
-
"!.DS_Store"
|
|
60
|
+
"!.DS_Store",
|
|
61
|
+
"CHANGELOG.md"
|
|
61
62
|
],
|
|
62
63
|
"dependencies": {
|
|
63
64
|
"@babel/runtime": "^7.4.3",
|
|
@@ -103,6 +104,7 @@
|
|
|
103
104
|
"@babel/preset-env": "^7.18.10",
|
|
104
105
|
"@babel/register": "^7.18.9",
|
|
105
106
|
"@semantic-release/git": "^10.0.1",
|
|
107
|
+
"@semantic-release/changelog": "^6.0.1",
|
|
106
108
|
"@xmldom/xmldom": "^0.x",
|
|
107
109
|
"babel-plugin-source-map-support": "^2.2.0",
|
|
108
110
|
"android-apidemos": "^4.1.1",
|