@appium/universal-xml-plugin 1.0.3 → 1.0.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/LICENSE +2 -2
- package/build/lib/attr-map.d.ts +58 -0
- package/build/lib/attr-map.d.ts.map +1 -0
- package/build/lib/attr-map.js +1 -1
- package/build/lib/attr-map.js.map +1 -0
- package/build/lib/index.d.ts +5 -0
- package/build/lib/index.d.ts.map +1 -0
- package/build/lib/index.js +26 -0
- package/build/lib/index.js.map +1 -0
- package/build/lib/logger.d.ts +3 -0
- package/build/lib/logger.d.ts.map +1 -0
- package/build/lib/logger.js +2 -2
- package/build/lib/logger.js.map +1 -0
- package/build/lib/node-map.d.ts +200 -0
- package/build/lib/node-map.d.ts.map +1 -0
- package/build/lib/node-map.js +15 -57
- package/build/lib/node-map.js.map +1 -0
- package/build/lib/plugin.d.ts +8 -0
- package/build/lib/plugin.d.ts.map +1 -0
- package/build/lib/plugin.js +16 -8
- package/build/lib/plugin.js.map +1 -0
- package/build/lib/source.d.ts +24 -0
- package/build/lib/source.d.ts.map +1 -0
- package/build/lib/source.js +24 -10
- package/build/lib/source.js.map +1 -0
- package/build/lib/transformers.d.ts +8 -0
- package/build/lib/transformers.d.ts.map +1 -0
- package/build/lib/transformers.js +1 -1
- package/build/lib/transformers.js.map +1 -0
- package/build/lib/xpath.d.ts +4 -0
- package/build/lib/xpath.d.ts.map +1 -0
- package/build/lib/xpath.js +3 -2
- package/build/lib/xpath.js.map +1 -0
- package/build/tsconfig.tsbuildinfo +1 -1
- package/index.js +3 -17
- package/lib/attr-map.js +1 -1
- package/lib/index.js +19 -0
- package/lib/logger.js +1 -1
- package/lib/node-map.js +14 -58
- package/lib/plugin.js +36 -25
- package/lib/source.js +30 -13
- package/lib/transformers.js +3 -3
- package/lib/xpath.js +7 -6
- package/package.json +48 -23
- package/tsconfig.json +2 -6
- package/build/index.js +0 -25
- package/build/test/fixtures/android-transformed-path.xml +0 -39
- package/build/test/fixtures/android-transformed.xml +0 -39
- package/build/test/fixtures/android.xml +0 -39
- package/build/test/fixtures/index.js +0 -25
- package/build/test/fixtures/ios-edge.xml +0 -16
- package/build/test/fixtures/ios-transformed-edge.xml +0 -16
- package/build/test/fixtures/ios-transformed-path.xml +0 -54
- package/build/test/fixtures/ios-transformed.xml +0 -54
- package/build/test/fixtures/ios.xml +0 -51
- package/build/test/unit/plugin-specs.js +0 -59
- package/build/test/unit/source-specs.js +0 -82
- package/build/test/unit/xpath-specs.js +0 -46
- package/test/fixtures/android-transformed-path.xml +0 -39
- package/test/fixtures/android-transformed.xml +0 -39
- package/test/fixtures/android.xml +0 -39
- package/test/fixtures/index.js +0 -14
- package/test/fixtures/ios-edge.xml +0 -16
- package/test/fixtures/ios-transformed-edge.xml +0 -16
- package/test/fixtures/ios-transformed-path.xml +0 -54
- package/test/fixtures/ios-transformed.xml +0 -54
- package/test/fixtures/ios.xml +0 -51
- package/test/unit/plugin-specs.js +0 -57
- package/test/unit/source-specs.js +0 -79
- package/test/unit/xpath-specs.js +0 -43
package/lib/node-map.js
CHANGED
|
@@ -64,23 +64,14 @@ export default {
|
|
|
64
64
|
'XCUIElementTypeStatusItem',
|
|
65
65
|
'XCUIElementTypeTimeline',
|
|
66
66
|
],
|
|
67
|
-
android: [
|
|
68
|
-
'android.widget.Space',
|
|
69
|
-
'android.widget.TwoLineListItem',
|
|
70
|
-
],
|
|
67
|
+
android: ['android.widget.Space', 'android.widget.TwoLineListItem'],
|
|
71
68
|
},
|
|
72
69
|
Grid: {
|
|
73
70
|
ios: 'XCUIElementTypeGrid',
|
|
74
|
-
android: [
|
|
75
|
-
'android.widget.GridLayout',
|
|
76
|
-
'android.widget.GridView',
|
|
77
|
-
],
|
|
71
|
+
android: ['android.widget.GridLayout', 'android.widget.GridView'],
|
|
78
72
|
},
|
|
79
73
|
Icon: {
|
|
80
|
-
ios: [
|
|
81
|
-
'XCUIElementTypeIcon',
|
|
82
|
-
'XCUIElementTypeDockItem',
|
|
83
|
-
],
|
|
74
|
+
ios: ['XCUIElementTypeIcon', 'XCUIElementTypeDockItem'],
|
|
84
75
|
},
|
|
85
76
|
Image: {
|
|
86
77
|
ios: 'XCUIElementTypeImage',
|
|
@@ -94,17 +85,11 @@ export default {
|
|
|
94
85
|
'XCUIElementTypeRelevanceIndicator',
|
|
95
86
|
'XCUIElementTypeValueIndicator',
|
|
96
87
|
],
|
|
97
|
-
android: [
|
|
98
|
-
'android.widget.RatingBar',
|
|
99
|
-
'android.widget.ProgressBar',
|
|
100
|
-
],
|
|
88
|
+
android: ['android.widget.RatingBar', 'android.widget.ProgressBar'],
|
|
101
89
|
},
|
|
102
90
|
Input: {
|
|
103
|
-
ios: [
|
|
104
|
-
|
|
105
|
-
],
|
|
106
|
-
android: [
|
|
107
|
-
]
|
|
91
|
+
ios: ['XCUIElementTypeColorWell'],
|
|
92
|
+
android: [],
|
|
108
93
|
},
|
|
109
94
|
List: {
|
|
110
95
|
android: [
|
|
@@ -112,18 +97,13 @@ export default {
|
|
|
112
97
|
'android.widget.ExpandableListView',
|
|
113
98
|
'android.widget.Gallery',
|
|
114
99
|
],
|
|
115
|
-
ios: [
|
|
116
|
-
'XCUIElementTypeCollectionView'
|
|
117
|
-
],
|
|
100
|
+
ios: ['XCUIElementTypeCollectionView'],
|
|
118
101
|
},
|
|
119
102
|
Map: {
|
|
120
103
|
ios: 'XCUIElementTypeMap',
|
|
121
104
|
},
|
|
122
105
|
Menu: {
|
|
123
|
-
ios: [
|
|
124
|
-
'XCUIElementTypeMenu',
|
|
125
|
-
'XCUIElementTypeMenuBar',
|
|
126
|
-
],
|
|
106
|
+
ios: ['XCUIElementTypeMenu', 'XCUIElementTypeMenuBar'],
|
|
127
107
|
android: ['android.widget.ActionMenuView', 'android.widget.PopupMenu'],
|
|
128
108
|
},
|
|
129
109
|
Modal: {
|
|
@@ -133,11 +113,7 @@ export default {
|
|
|
133
113
|
'android.widget.SlidingDrawer',
|
|
134
114
|
'android.widget.Magnifier',
|
|
135
115
|
],
|
|
136
|
-
ios: [
|
|
137
|
-
'XCUIElementTypeDrawer',
|
|
138
|
-
'XCUIElementTypeDialog',
|
|
139
|
-
'XCUIElementTypePopover',
|
|
140
|
-
],
|
|
116
|
+
ios: ['XCUIElementTypeDrawer', 'XCUIElementTypeDialog', 'XCUIElementTypePopover'],
|
|
141
117
|
},
|
|
142
118
|
Nav: {
|
|
143
119
|
ios: 'XCUIElementTypeNavigationBar',
|
|
@@ -173,11 +149,7 @@ export default {
|
|
|
173
149
|
},
|
|
174
150
|
SliderInput: {
|
|
175
151
|
android: 'android.widget.SeekBar',
|
|
176
|
-
ios: [
|
|
177
|
-
'XCUIElementTypeSlider',
|
|
178
|
-
'XCUIElementTypeStepper',
|
|
179
|
-
'XCUIElementTypeScrollBar',
|
|
180
|
-
],
|
|
152
|
+
ios: ['XCUIElementTypeSlider', 'XCUIElementTypeStepper', 'XCUIElementTypeScrollBar'],
|
|
181
153
|
},
|
|
182
154
|
Spinner: {
|
|
183
155
|
ios: 'XCUIElementTypeActivityIndicator',
|
|
@@ -192,23 +164,11 @@ export default {
|
|
|
192
164
|
android: 'android.widget.TableLayout',
|
|
193
165
|
},
|
|
194
166
|
Text: {
|
|
195
|
-
ios: [
|
|
196
|
-
|
|
197
|
-
'XCUIElementTypeTextView',
|
|
198
|
-
'XCUIElementTypeHelpTag',
|
|
199
|
-
],
|
|
200
|
-
android: [
|
|
201
|
-
'android.widget.TextView',
|
|
202
|
-
'android.widget.Chronometer',
|
|
203
|
-
'android.widget.TextClock',
|
|
204
|
-
],
|
|
167
|
+
ios: ['XCUIElementTypeStaticText', 'XCUIElementTypeTextView', 'XCUIElementTypeHelpTag'],
|
|
168
|
+
android: ['android.widget.TextView', 'android.widget.Chronometer', 'android.widget.TextClock'],
|
|
205
169
|
},
|
|
206
170
|
TextInput: {
|
|
207
|
-
ios: [
|
|
208
|
-
'XCUIElementTypeTextField',
|
|
209
|
-
'XCUIElementTypeSecureTextField',
|
|
210
|
-
'XCUIElementTypeComboBox',
|
|
211
|
-
],
|
|
171
|
+
ios: ['XCUIElementTypeTextField', 'XCUIElementTypeSecureTextField', 'XCUIElementTypeComboBox'],
|
|
212
172
|
android: [
|
|
213
173
|
'android.widget.EditText',
|
|
214
174
|
'android.widget.AutoCompleteTextView',
|
|
@@ -217,11 +177,7 @@ export default {
|
|
|
217
177
|
},
|
|
218
178
|
ToggleInput: {
|
|
219
179
|
ios: 'XCUIElementTypeToggle',
|
|
220
|
-
android: [
|
|
221
|
-
'android.widget.CheckedTextView',
|
|
222
|
-
'android.widget.ToggleButton',
|
|
223
|
-
],
|
|
224
|
-
|
|
180
|
+
android: ['android.widget.CheckedTextView', 'android.widget.ToggleButton'],
|
|
225
181
|
},
|
|
226
182
|
Toolbar: {
|
|
227
183
|
ios: 'XCUIElementTypeToolbar',
|
package/lib/plugin.js
CHANGED
|
@@ -1,49 +1,59 @@
|
|
|
1
1
|
/* eslint-disable no-case-declarations */
|
|
2
2
|
|
|
3
|
-
import BasePlugin from '
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
3
|
+
import BasePlugin from 'appium/plugin';
|
|
4
|
+
import {errors} from 'appium/driver';
|
|
5
|
+
import {transformSourceXml} from './source';
|
|
6
|
+
import {transformQuery} from './xpath';
|
|
7
7
|
import log from './logger';
|
|
8
8
|
|
|
9
9
|
export default class UniversalXMLPlugin extends BasePlugin {
|
|
10
|
+
commands = [
|
|
11
|
+
'getPageSource',
|
|
12
|
+
'findElement',
|
|
13
|
+
'findElements',
|
|
14
|
+
'findElementFromElement',
|
|
15
|
+
'findElementsFromElement',
|
|
16
|
+
];
|
|
10
17
|
|
|
11
|
-
|
|
12
|
-
'findElementsFromElement'];
|
|
13
|
-
|
|
14
|
-
async getPageSource (next, driver, sessId, addIndexPath = false) {
|
|
18
|
+
async getPageSource(next, driver, sessId, addIndexPath = false) {
|
|
15
19
|
const source = next ? await next() : await driver.getPageSource();
|
|
16
20
|
const metadata = {};
|
|
17
21
|
const {platformName} = driver.caps;
|
|
18
22
|
if (platformName.toLowerCase() === 'android') {
|
|
19
23
|
metadata.appPackage = driver.opts.appPackage;
|
|
20
24
|
}
|
|
21
|
-
const {xml, unknowns} = transformSourceXml(source,
|
|
22
|
-
|
|
25
|
+
const {xml, unknowns} = transformSourceXml(source, platformName.toLowerCase(), {
|
|
26
|
+
metadata,
|
|
27
|
+
addIndexPath,
|
|
28
|
+
});
|
|
23
29
|
if (unknowns.nodes.length) {
|
|
24
|
-
log.warn(
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
30
|
+
log.warn(
|
|
31
|
+
`The XML mapper found ${unknowns.nodes.length} node(s) / ` +
|
|
32
|
+
`tag name(s) that it didn't know about. These should be ` +
|
|
33
|
+
`reported to improve the quality of the plugin: ` +
|
|
34
|
+
unknowns.nodes.join(', ')
|
|
35
|
+
);
|
|
28
36
|
}
|
|
29
37
|
if (unknowns.attrs.length) {
|
|
30
|
-
log.warn(
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
38
|
+
log.warn(
|
|
39
|
+
`The XML mapper found ${unknowns.attrs.length} attributes ` +
|
|
40
|
+
`that it didn't know about. These should be reported to ` +
|
|
41
|
+
`improve the quality of the plugin: ` +
|
|
42
|
+
unknowns.attrs.join(', ')
|
|
43
|
+
);
|
|
34
44
|
}
|
|
35
45
|
return xml;
|
|
36
46
|
}
|
|
37
47
|
|
|
38
|
-
async findElement
|
|
48
|
+
async findElement(...args) {
|
|
39
49
|
return await this._find(false, ...args);
|
|
40
50
|
}
|
|
41
51
|
|
|
42
|
-
async findElements
|
|
52
|
+
async findElements(...args) {
|
|
43
53
|
return await this._find(true, ...args);
|
|
44
54
|
}
|
|
45
55
|
|
|
46
|
-
async _find
|
|
56
|
+
async _find(multiple, next, driver, strategy, selector) {
|
|
47
57
|
const {platformName} = driver.caps;
|
|
48
58
|
if (strategy.toLowerCase() !== 'xpath') {
|
|
49
59
|
return await next();
|
|
@@ -54,8 +64,10 @@ export default class UniversalXMLPlugin extends BasePlugin {
|
|
|
54
64
|
// if the selector was not able to be transformed, that means no elements were found that
|
|
55
65
|
// matched, so do the appropriate thing based on element vs elements
|
|
56
66
|
if (newSelector === null) {
|
|
57
|
-
log.warn(
|
|
58
|
-
|
|
67
|
+
log.warn(
|
|
68
|
+
`Selector was not able to be translated to underlying XML. Either the requested ` +
|
|
69
|
+
`element does not exist or there was an error in translation`
|
|
70
|
+
);
|
|
59
71
|
if (multiple) {
|
|
60
72
|
return [];
|
|
61
73
|
}
|
|
@@ -74,7 +86,6 @@ export default class UniversalXMLPlugin extends BasePlugin {
|
|
|
74
86
|
const finder = multiple ? 'findElements' : 'findElement';
|
|
75
87
|
return await driver[finder](strategy, newSelector);
|
|
76
88
|
}
|
|
77
|
-
|
|
78
89
|
}
|
|
79
90
|
|
|
80
|
-
export {
|
|
91
|
+
export {UniversalXMLPlugin};
|
package/lib/source.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import _ from 'lodash';
|
|
2
|
-
import parser, {
|
|
2
|
+
import parser, {j2xParser} from 'fast-xml-parser';
|
|
3
3
|
import NODE_MAP from './node-map';
|
|
4
|
-
import {
|
|
4
|
+
import {ATTR_MAP, REMOVE_ATTRS} from './attr-map';
|
|
5
5
|
import TRANSFORMS from './transformers';
|
|
6
6
|
|
|
7
7
|
const PARSE_OPTS = {
|
|
@@ -22,19 +22,23 @@ export const IDX_PREFIX = `${ATTR_PREFIX}index`;
|
|
|
22
22
|
const isAttr = (k) => k.substring(0, 2) === ATTR_PREFIX;
|
|
23
23
|
const isNode = (k) => !isAttr(k);
|
|
24
24
|
|
|
25
|
-
export function transformSourceXml
|
|
25
|
+
export function transformSourceXml(xmlStr, platform, {metadata = {}, addIndexPath = false} = {}) {
|
|
26
26
|
// first thing we want to do is modify the ios source root node, because it doesn't include the
|
|
27
27
|
// necessary index attribute, so we add it if it's not there
|
|
28
28
|
xmlStr = xmlStr.replace('<AppiumAUT>', '<AppiumAUT index="0">');
|
|
29
29
|
const xmlObj = parser.parse(xmlStr, PARSE_OPTS);
|
|
30
|
-
const unknowns = transformNode(xmlObj, platform, {
|
|
30
|
+
const unknowns = transformNode(xmlObj, platform, {
|
|
31
|
+
metadata,
|
|
32
|
+
addIndexPath,
|
|
33
|
+
parentPath: '',
|
|
34
|
+
});
|
|
31
35
|
const jParser = new j2xParser(GEN_OPTS);
|
|
32
36
|
let transformedXml = jParser.parse(xmlObj).trim();
|
|
33
37
|
transformedXml = `<?xml version="1.0" encoding="UTF-8"?>\n${transformedXml}`;
|
|
34
38
|
return {xml: transformedXml, unknowns};
|
|
35
39
|
}
|
|
36
40
|
|
|
37
|
-
function getUniversalName
|
|
41
|
+
function getUniversalName(nameMap, name, platform) {
|
|
38
42
|
for (const translatedName of Object.keys(nameMap)) {
|
|
39
43
|
const sourceNodes = nameMap[translatedName]?.[platform];
|
|
40
44
|
if (_.isArray(sourceNodes) && sourceNodes.includes(name)) {
|
|
@@ -47,15 +51,15 @@ function getUniversalName (nameMap, name, platform) {
|
|
|
47
51
|
return null;
|
|
48
52
|
}
|
|
49
53
|
|
|
50
|
-
export function getUniversalNodeName
|
|
54
|
+
export function getUniversalNodeName(nodeName, platform) {
|
|
51
55
|
return getUniversalName(NODE_MAP, nodeName, platform);
|
|
52
56
|
}
|
|
53
57
|
|
|
54
|
-
export function getUniversalAttrName
|
|
58
|
+
export function getUniversalAttrName(attrName, platform) {
|
|
55
59
|
return getUniversalName(ATTR_MAP, attrName, platform);
|
|
56
60
|
}
|
|
57
61
|
|
|
58
|
-
export function transformNode
|
|
62
|
+
export function transformNode(nodeObj, platform, {metadata, addIndexPath, parentPath}) {
|
|
59
63
|
const unknownNodes = [];
|
|
60
64
|
const unknownAttrs = [];
|
|
61
65
|
if (_.isPlainObject(nodeObj)) {
|
|
@@ -76,14 +80,18 @@ export function transformNode (nodeObj, platform, {metadata, addIndexPath, paren
|
|
|
76
80
|
TRANSFORMS[platform]?.(nodeObj, metadata);
|
|
77
81
|
unknownAttrs.push(...transformAttrs(nodeObj, attrs, platform));
|
|
78
82
|
const unknowns = transformChildNodes(nodeObj, childNodeNames, platform, {
|
|
79
|
-
metadata,
|
|
83
|
+
metadata,
|
|
84
|
+
addIndexPath,
|
|
85
|
+
parentPath: thisIndexPath,
|
|
80
86
|
});
|
|
81
87
|
unknownAttrs.push(...unknowns.attrs);
|
|
82
88
|
unknownNodes.push(...unknowns.nodes);
|
|
83
89
|
} else if (_.isArray(nodeObj)) {
|
|
84
90
|
for (const childObj of nodeObj) {
|
|
85
91
|
const {nodes, attrs} = transformNode(childObj, platform, {
|
|
86
|
-
metadata,
|
|
92
|
+
metadata,
|
|
93
|
+
addIndexPath,
|
|
94
|
+
parentPath,
|
|
87
95
|
});
|
|
88
96
|
unknownNodes.push(...nodes);
|
|
89
97
|
unknownAttrs.push(...attrs);
|
|
@@ -95,12 +103,21 @@ export function transformNode (nodeObj, platform, {metadata, addIndexPath, paren
|
|
|
95
103
|
};
|
|
96
104
|
}
|
|
97
105
|
|
|
98
|
-
export function transformChildNodes
|
|
106
|
+
export function transformChildNodes(
|
|
107
|
+
nodeObj,
|
|
108
|
+
childNodeNames,
|
|
109
|
+
platform,
|
|
110
|
+
{metadata, addIndexPath, parentPath}
|
|
111
|
+
) {
|
|
99
112
|
const unknownNodes = [];
|
|
100
113
|
const unknownAttrs = [];
|
|
101
114
|
for (const nodeName of childNodeNames) {
|
|
102
115
|
// before modifying the name of this child node, recurse down and modify the subtree
|
|
103
|
-
const {nodes, attrs} = transformNode(nodeObj[nodeName], platform, {
|
|
116
|
+
const {nodes, attrs} = transformNode(nodeObj[nodeName], platform, {
|
|
117
|
+
metadata,
|
|
118
|
+
addIndexPath,
|
|
119
|
+
parentPath,
|
|
120
|
+
});
|
|
104
121
|
unknownNodes.push(...nodes);
|
|
105
122
|
unknownAttrs.push(...attrs);
|
|
106
123
|
|
|
@@ -127,7 +144,7 @@ export function transformChildNodes (nodeObj, childNodeNames, platform, {metadat
|
|
|
127
144
|
return {nodes: unknownNodes, attrs: unknownAttrs};
|
|
128
145
|
}
|
|
129
146
|
|
|
130
|
-
export function transformAttrs
|
|
147
|
+
export function transformAttrs(nodeObj, attrs, platform) {
|
|
131
148
|
const unknownAttrs = [];
|
|
132
149
|
for (const attr of attrs) {
|
|
133
150
|
const cleanAttr = attr.substring(2);
|
package/lib/transformers.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {ATTR_PREFIX} from './source';
|
|
2
2
|
|
|
3
|
-
function ios
|
|
3
|
+
function ios(nodeObj /*, metadata*/) {
|
|
4
4
|
return nodeObj;
|
|
5
5
|
}
|
|
6
6
|
|
|
7
|
-
function android
|
|
7
|
+
function android(nodeObj, metadata) {
|
|
8
8
|
// strip android:id from front of id
|
|
9
9
|
const resId = nodeObj[`${ATTR_PREFIX}resource-id`];
|
|
10
10
|
if (resId && metadata.appPackage) {
|
package/lib/xpath.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import {select as xpathQuery} from 'xpath';
|
|
2
|
+
import {DOMParser} from '@xmldom/xmldom';
|
|
3
3
|
|
|
4
|
-
export function runQuery
|
|
4
|
+
export function runQuery(query, xmlStr) {
|
|
5
5
|
const dom = new DOMParser().parseFromString(xmlStr);
|
|
6
6
|
const nodes = xpathQuery(query, dom);
|
|
7
7
|
return nodes;
|
|
8
8
|
}
|
|
9
9
|
|
|
10
|
-
export function transformQuery
|
|
10
|
+
export function transformQuery(query, xmlStr, multiple) {
|
|
11
11
|
const nodes = runQuery(query, xmlStr);
|
|
12
12
|
|
|
13
13
|
const newQueries = nodes.map((node) => {
|
|
@@ -16,7 +16,8 @@ export function transformQuery (query, xmlStr, multiple) {
|
|
|
16
16
|
let newQuery = indexPath
|
|
17
17
|
.substring(1) // remove leading / so we can split
|
|
18
18
|
.split('/') // split into idnexes
|
|
19
|
-
.map((indexStr) => {
|
|
19
|
+
.map((indexStr) => {
|
|
20
|
+
// map to xpath node indexes (1-based)
|
|
20
21
|
const xpathIndex = parseInt(indexStr, 10) + 1;
|
|
21
22
|
return `*[${xpathIndex}]`;
|
|
22
23
|
})
|
|
@@ -37,7 +38,7 @@ export function transformQuery (query, xmlStr, multiple) {
|
|
|
37
38
|
return newSelector;
|
|
38
39
|
}
|
|
39
40
|
|
|
40
|
-
export function getNodeAttrVal
|
|
41
|
+
export function getNodeAttrVal(node, attr) {
|
|
41
42
|
const attrObjs = Object.values(node.attributes).filter((obj) => obj.name === attr);
|
|
42
43
|
if (!attrObjs.length) {
|
|
43
44
|
throw new Error(`Tried to retrieve a node attribute '${attr}' but the node didn't have it`);
|
package/package.json
CHANGED
|
@@ -1,38 +1,63 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@appium/universal-xml-plugin",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.4",
|
|
4
4
|
"description": "Appium plugin for making XML source and XPath queries the same across iOS and Android",
|
|
5
|
-
"
|
|
5
|
+
"keywords": [
|
|
6
|
+
"automation",
|
|
7
|
+
"javascript",
|
|
8
|
+
"selenium",
|
|
9
|
+
"webdriver",
|
|
10
|
+
"ios",
|
|
11
|
+
"android",
|
|
12
|
+
"firefoxos",
|
|
13
|
+
"testing"
|
|
14
|
+
],
|
|
15
|
+
"homepage": "https://appium.io",
|
|
16
|
+
"bugs": {
|
|
17
|
+
"url": "https://github.com/appium/appium/issues"
|
|
18
|
+
},
|
|
6
19
|
"repository": {
|
|
7
20
|
"type": "git",
|
|
8
21
|
"url": "git+https://github.com/appium/appium-plugins.git"
|
|
9
22
|
},
|
|
10
|
-
"appium": {
|
|
11
|
-
"pluginName": "universal-xml",
|
|
12
|
-
"mainClass": "UniversalXMLPlugin"
|
|
13
|
-
},
|
|
14
|
-
"keywords": [
|
|
15
|
-
"appium",
|
|
16
|
-
"automation",
|
|
17
|
-
"xml",
|
|
18
|
-
"webdriver"
|
|
19
|
-
],
|
|
20
|
-
"author": "Appium <maintainers@appium.io>",
|
|
21
23
|
"license": "Apache-2.0",
|
|
22
|
-
"
|
|
23
|
-
|
|
24
|
+
"author": "https://github.com/appium",
|
|
25
|
+
"types": "./build/lib/plugin.d.ts",
|
|
26
|
+
"files": [
|
|
27
|
+
"index.js",
|
|
28
|
+
"build",
|
|
29
|
+
"lib",
|
|
30
|
+
"tsconfig.json"
|
|
31
|
+
],
|
|
32
|
+
"scripts": {
|
|
33
|
+
"test": "npm run test:unit",
|
|
34
|
+
"test:smoke": "node ./build/lib/index.js",
|
|
35
|
+
"test:unit": "mocha \"./test/unit/**/*.spec.js\""
|
|
24
36
|
},
|
|
25
|
-
"homepage": "https://github.com/appium/appium-plugins#readme",
|
|
26
37
|
"dependencies": {
|
|
27
|
-
"@
|
|
28
|
-
"@
|
|
38
|
+
"@types/xmldom": "0.1.31",
|
|
39
|
+
"@xmldom/xmldom": "0.8.6",
|
|
29
40
|
"fast-xml-parser": "3.21.1",
|
|
30
|
-
"
|
|
41
|
+
"lodash": "4.17.21",
|
|
42
|
+
"source-map-support": "0.5.21",
|
|
31
43
|
"xpath": "0.0.32"
|
|
32
44
|
},
|
|
33
|
-
"
|
|
34
|
-
"
|
|
35
|
-
|
|
45
|
+
"peerDependencies": {
|
|
46
|
+
"appium": "^2.0.0-beta.35"
|
|
47
|
+
},
|
|
48
|
+
"engines": {
|
|
49
|
+
"node": "^14.17.0 || ^16.13.0 || >=18.0.0",
|
|
50
|
+
"npm": ">=8"
|
|
51
|
+
},
|
|
52
|
+
"appium": {
|
|
53
|
+
"pluginName": "universal-xml",
|
|
54
|
+
"mainClass": "UniversalXMLPlugin"
|
|
55
|
+
},
|
|
56
|
+
"publishConfig": {
|
|
57
|
+
"access": "public"
|
|
36
58
|
},
|
|
37
|
-
"gitHead": "
|
|
59
|
+
"gitHead": "67c9bdfbceeb049aa134bf1d9b107543ff0a80b0",
|
|
60
|
+
"typedoc": {
|
|
61
|
+
"entryPoint": "./lib/index.js"
|
|
62
|
+
}
|
|
38
63
|
}
|
package/tsconfig.json
CHANGED
package/build/index.js
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.UniversalXMLPlugin = void 0;
|
|
7
|
-
const plugin_1 = __importDefault(require("./lib/plugin"));
|
|
8
|
-
exports.UniversalXMLPlugin = plugin_1.default;
|
|
9
|
-
exports.default = plugin_1.default;
|
|
10
|
-
if (module === require.main) {
|
|
11
|
-
const { transformSourceXml } = require('./lib/source');
|
|
12
|
-
const fs = require('fs');
|
|
13
|
-
const [, , xmlDataPath, platform, optsJson] = process.argv;
|
|
14
|
-
const xmlData = fs.readFileSync(xmlDataPath, 'utf8');
|
|
15
|
-
let opts = {};
|
|
16
|
-
if (optsJson) {
|
|
17
|
-
opts = JSON.parse(optsJson);
|
|
18
|
-
}
|
|
19
|
-
const { xml, unknowns } = transformSourceXml(xmlData, platform, opts);
|
|
20
|
-
console.log(xml); // eslint-disable-line no-console
|
|
21
|
-
if (unknowns.nodes.length || unknowns.attrs.length) {
|
|
22
|
-
console.error(unknowns); // eslint-disable-line no-console
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9pbmRleC5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7QUFBQSwwREFBOEM7QUFFckMsNkJBRkYsZ0JBQWtCLENBRUU7QUFEM0Isa0JBQWUsZ0JBQWtCLENBQUM7QUFHbEMsSUFBSSxNQUFNLEtBQUssT0FBTyxDQUFDLElBQUksRUFBRTtJQUMzQixNQUFNLEVBQUUsa0JBQWtCLEVBQUUsR0FBRyxPQUFPLENBQUMsY0FBYyxDQUFDLENBQUM7SUFDdkQsTUFBTSxFQUFFLEdBQUcsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQ3pCLE1BQU0sQ0FBQyxFQUFDLEVBQUUsV0FBVyxFQUFFLFFBQVEsRUFBRSxRQUFRLENBQUMsR0FBRyxPQUFPLENBQUMsSUFBSSxDQUFDO0lBQzFELE1BQU0sT0FBTyxHQUFHLEVBQUUsQ0FBQyxZQUFZLENBQUMsV0FBVyxFQUFFLE1BQU0sQ0FBQyxDQUFDO0lBQ3JELElBQUksSUFBSSxHQUFHLEVBQUUsQ0FBQztJQUNkLElBQUksUUFBUSxFQUFFO1FBQ1osSUFBSSxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsUUFBUSxDQUFDLENBQUM7S0FDN0I7SUFDRCxNQUFNLEVBQUMsR0FBRyxFQUFFLFFBQVEsRUFBQyxHQUFHLGtCQUFrQixDQUFDLE9BQU8sRUFBRSxRQUFRLEVBQUUsSUFBSSxDQUFDLENBQUM7SUFDcEUsT0FBTyxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLGlDQUFpQztJQUNuRCxJQUFJLFFBQVEsQ0FBQyxLQUFLLENBQUMsTUFBTSxJQUFJLFFBQVEsQ0FBQyxLQUFLLENBQUMsTUFBTSxFQUFFO1FBQ2xELE9BQU8sQ0FBQyxLQUFLLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxpQ0FBaUM7S0FDM0Q7Q0FDRiJ9
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
-
<UI width="1080" height="1920" indexPath="/0">
|
|
3
|
-
<View text="" indexPath="/0/0" x="0" y="0" width="1080" height="1920" visible="true">
|
|
4
|
-
<View text="" indexPath="/0/0/0" x="0" y="0" width="1080" height="1920" visible="true">
|
|
5
|
-
<View text="" indexPath="/0/0/0/0" x="0" y="72" width="1080" height="1848" visible="true">
|
|
6
|
-
<View text="" indexPath="/0/0/0/0/0" x="0" y="72" width="1080" height="1848" id="action_bar_root" visible="true">
|
|
7
|
-
<View text="" indexPath="/0/0/0/0/0/0" x="0" y="72" width="1080" height="1848" id="android:id/content" visible="true">
|
|
8
|
-
<View text="" indexPath="/0/0/0/0/0/0/0" x="0" y="72" width="1080" height="1848" visible="true">
|
|
9
|
-
<View text="" indexPath="/0/0/0/0/0/0/0/0" x="0" y="72" width="1080" height="1848" visible="true"></View>
|
|
10
|
-
<View text="" indexPath="/0/0/0/0/0/0/0/1" x="0" y="72" width="1080" height="1848" visible="true">
|
|
11
|
-
<View text="" indexPath="/0/0/0/0/0/0/0/1/0" x="0" y="72" width="1080" height="168" visible="true">
|
|
12
|
-
<View text="" indexPath="/0/0/0/0/0/0/0/1/0/0" x="0" y="72" width="1080" height="168" visible="true">
|
|
13
|
-
<View text="" indexPath="/0/0/0/0/0/0/0/1/0/0/0" x="0" y="72" width="1080" height="168" visible="true">
|
|
14
|
-
<Button text="" indexPath="/0/0/0/0/0/0/0/1/0/0/0/0" x="0" y="72" width="168" height="168" visible="true"></Button>
|
|
15
|
-
</View>
|
|
16
|
-
</View>
|
|
17
|
-
</View>
|
|
18
|
-
<View text="" indexPath="/0/0/0/0/0/0/0/1/1" x="0" y="240" width="1080" height="1680" visible="true">
|
|
19
|
-
<Text text="Login" indexPath="/0/0/0/0/0/0/0/1/1/0" x="413" y="360" width="255" height="136" visible="true"></Text>
|
|
20
|
-
<View text="" indexPath="/0/0/0/0/0/0/0/1/1/1" x="150" y="496" width="780" height="120" visible="true">
|
|
21
|
-
<TextInput text="alice" indexPath="/0/0/0/0/0/0/0/1/1/1/0" x="150" y="504" width="780" height="112" axId="username" visible="true"></TextInput>
|
|
22
|
-
</View>
|
|
23
|
-
<View text="" indexPath="/0/0/0/0/0/0/0/1/1/2" x="150" y="616" width="780" height="120" visible="true">
|
|
24
|
-
<TextInput text="•••••••••" indexPath="/0/0/0/0/0/0/0/1/1/2/0" x="150" y="624" width="780" height="112" axId="password" visible="true"></TextInput>
|
|
25
|
-
</View>
|
|
26
|
-
<View text="" indexPath="/0/0/0/0/0/0/0/1/1/3" x="456" y="736" width="168" height="113" visible="true">
|
|
27
|
-
<View text="" indexPath="/0/0/0/0/0/0/0/1/1/3/0" x="456" y="736" width="168" height="113" axId="loginBtn" visible="true">
|
|
28
|
-
<Text text="Login" indexPath="/0/0/0/0/0/0/0/1/1/3/0/0" x="456" y="736" width="168" height="113" visible="true"></Text>
|
|
29
|
-
</View>
|
|
30
|
-
</View>
|
|
31
|
-
</View>
|
|
32
|
-
</View>
|
|
33
|
-
</View>
|
|
34
|
-
</View>
|
|
35
|
-
</View>
|
|
36
|
-
</View>
|
|
37
|
-
</View>
|
|
38
|
-
</View>
|
|
39
|
-
</UI>
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
-
<UI width="1080" height="1920">
|
|
3
|
-
<View text="" x="0" y="0" width="1080" height="1920" visible="true">
|
|
4
|
-
<View text="" x="0" y="0" width="1080" height="1920" visible="true">
|
|
5
|
-
<View text="" x="0" y="72" width="1080" height="1848" visible="true">
|
|
6
|
-
<View text="" x="0" y="72" width="1080" height="1848" id="action_bar_root" visible="true">
|
|
7
|
-
<View text="" x="0" y="72" width="1080" height="1848" id="android:id/content" visible="true">
|
|
8
|
-
<View text="" x="0" y="72" width="1080" height="1848" visible="true">
|
|
9
|
-
<View text="" x="0" y="72" width="1080" height="1848" visible="true"></View>
|
|
10
|
-
<View text="" x="0" y="72" width="1080" height="1848" visible="true">
|
|
11
|
-
<View text="" x="0" y="72" width="1080" height="168" visible="true">
|
|
12
|
-
<View text="" x="0" y="72" width="1080" height="168" visible="true">
|
|
13
|
-
<View text="" x="0" y="72" width="1080" height="168" visible="true">
|
|
14
|
-
<Button text="" x="0" y="72" width="168" height="168" visible="true"></Button>
|
|
15
|
-
</View>
|
|
16
|
-
</View>
|
|
17
|
-
</View>
|
|
18
|
-
<View text="" x="0" y="240" width="1080" height="1680" visible="true">
|
|
19
|
-
<Text text="Login" x="413" y="360" width="255" height="136" visible="true"></Text>
|
|
20
|
-
<View text="" x="150" y="496" width="780" height="120" visible="true">
|
|
21
|
-
<TextInput text="alice" x="150" y="504" width="780" height="112" axId="username" visible="true"></TextInput>
|
|
22
|
-
</View>
|
|
23
|
-
<View text="" x="150" y="616" width="780" height="120" visible="true">
|
|
24
|
-
<TextInput text="•••••••••" x="150" y="624" width="780" height="112" axId="password" visible="true"></TextInput>
|
|
25
|
-
</View>
|
|
26
|
-
<View text="" x="456" y="736" width="168" height="113" visible="true">
|
|
27
|
-
<View text="" x="456" y="736" width="168" height="113" axId="loginBtn" visible="true">
|
|
28
|
-
<Text text="Login" x="456" y="736" width="168" height="113" visible="true"></Text>
|
|
29
|
-
</View>
|
|
30
|
-
</View>
|
|
31
|
-
</View>
|
|
32
|
-
</View>
|
|
33
|
-
</View>
|
|
34
|
-
</View>
|
|
35
|
-
</View>
|
|
36
|
-
</View>
|
|
37
|
-
</View>
|
|
38
|
-
</View>
|
|
39
|
-
</UI>
|