topological-nodered-wdio 1.1.0 → 1.1.2
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/package.json +1 -1
- package/src/dropdown-action.html +49 -19
- package/src/dropdown-action.js +45 -13
- package/src/element-action.html +2 -2
- package/src/element-action.js +105 -78
- package/src/element-check.html +49 -17
- package/src/element-check.js +50 -22
- package/src/execute-script.html +49 -16
- package/src/execute-script.js +40 -12
- package/src/explicit-wait.html +7 -10
- package/src/explicit-wait.js +1 -2
- package/src/wdio-common.js +103 -111
package/package.json
CHANGED
package/src/dropdown-action.html
CHANGED
|
@@ -22,8 +22,10 @@
|
|
|
22
22
|
color: '#a6bbcf',
|
|
23
23
|
defaults: {
|
|
24
24
|
name: { value: '' },
|
|
25
|
+
locateType: { value: false },
|
|
25
26
|
locateUsing: { value: 'xpath' },
|
|
26
27
|
locateValue: { value: '' },
|
|
28
|
+
locateValues: { value: [] },
|
|
27
29
|
action: { value: 'selectByAttr' },
|
|
28
30
|
text: { value: '' },
|
|
29
31
|
attribute: { value: '' },
|
|
@@ -37,30 +39,37 @@
|
|
|
37
39
|
return this.name || 'dropdown action'
|
|
38
40
|
},
|
|
39
41
|
oneditprepare: function () {
|
|
42
|
+
var that = this
|
|
40
43
|
setDropdownAction()
|
|
41
|
-
|
|
44
|
+
showSelectors()
|
|
45
|
+
multiSelectorsUI(that)
|
|
46
|
+
},
|
|
47
|
+
oneditsave: function () {
|
|
48
|
+
var node = this
|
|
49
|
+
var locateType = $('#node-input-locateType').prop('checked')
|
|
50
|
+
node.locateType = locateType
|
|
51
|
+
if (locateType) {
|
|
52
|
+
var locateValues = $('#node-input-locateValues-container').editableList('items')
|
|
53
|
+
node.locateValues = []
|
|
54
|
+
locateValues.each(function () {
|
|
55
|
+
var using = $(this).find('.node-input-locateValues-using').val()
|
|
56
|
+
var value = $(this).find('.node-input-locateValues-value').val()
|
|
57
|
+
node.locateValues.push({ using, value })
|
|
58
|
+
})
|
|
59
|
+
} else {
|
|
60
|
+
node.locateValues = []
|
|
61
|
+
node.locateValue = $('#node-input-locateValue').val()
|
|
62
|
+
node.locateUsing = $('#node-input-locateUsing').val()
|
|
63
|
+
}
|
|
64
|
+
}
|
|
42
65
|
})
|
|
43
66
|
</script>
|
|
44
67
|
|
|
45
68
|
<script type="text/x-red" data-template-name="dropdown-action">
|
|
46
69
|
<div class="form-row">
|
|
47
|
-
<label for="node-input-
|
|
48
|
-
<
|
|
49
|
-
<option value="id">id</option>
|
|
50
|
-
<option value="name">name</option>
|
|
51
|
-
<option value="className">Class Name</option>
|
|
52
|
-
<option value="css selector">CSS selector</option>
|
|
53
|
-
<option value="link text">Link text</option>
|
|
54
|
-
<option value="partial link text">Partial link text</option>
|
|
55
|
-
<option value="tag name">Tag name</option>
|
|
56
|
-
<option value="xpath" selected>XPath</option>
|
|
57
|
-
</select>
|
|
58
|
-
</div>
|
|
59
|
-
<div class="form-row">
|
|
60
|
-
<label for="node-input-locateValue"><i class="fa fa-tasks"></i> Selector</label>
|
|
61
|
-
<input id="node-input-locateValue" type="text">
|
|
70
|
+
<label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
|
|
71
|
+
<input id="node-input-name" type="text">
|
|
62
72
|
</div>
|
|
63
|
-
|
|
64
73
|
<div class="form-row">
|
|
65
74
|
<label for="node-input-action"><i class="fa fa-tasks"></i> Action</label>
|
|
66
75
|
<select type="text" id="node-input-action" style="width:70%;" onchange="setDropdownAction()">
|
|
@@ -87,8 +96,29 @@
|
|
|
87
96
|
<input id="node-input-index" type="text">
|
|
88
97
|
</div>
|
|
89
98
|
<div class="form-row">
|
|
90
|
-
<label for="node-input-
|
|
91
|
-
<input id="node-input-
|
|
99
|
+
<label for="node-input-locateType"><i class="fa fa-tasks"></i> Multiple Selector?</label>
|
|
100
|
+
<input id="node-input-locateType" type="checkbox" style="width:30px;" onchange="showSelectors()">
|
|
101
|
+
</div>
|
|
102
|
+
<div class="form-row">
|
|
103
|
+
<label for="node-input-locateUsing"><i class="fa fa-tasks"></i> Locate Method</label>
|
|
104
|
+
<select type="text" id="node-input-locateUsing" style="width:70%;">
|
|
105
|
+
<option value="id">id</option>
|
|
106
|
+
<option value="name">name</option>
|
|
107
|
+
<option value="className">Class Name</option>
|
|
108
|
+
<option value="css selector">CSS selector</option>
|
|
109
|
+
<option value="link text">Link text</option>
|
|
110
|
+
<option value="partial link text">Partial link text</option>
|
|
111
|
+
<option value="tag name">Tag name</option>
|
|
112
|
+
<option value="xpath" selected>XPath</option>
|
|
113
|
+
</select>
|
|
114
|
+
</div>
|
|
115
|
+
<div class="form-row">
|
|
116
|
+
<label for="node-input-locateValue"><i class="fa fa-tasks"></i> Selector</label>
|
|
117
|
+
<input id="node-input-locateValue" type="text">
|
|
118
|
+
</div>
|
|
119
|
+
<div class="form-row node-input-locateValues-container-row" style="position:relative">
|
|
120
|
+
<h4 style="margin-bottom: 3px;">Selectors :</h4>
|
|
121
|
+
<ol id="node-input-locateValues-container"></ol>
|
|
92
122
|
</div>
|
|
93
123
|
</script>
|
|
94
124
|
|
package/src/dropdown-action.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
const common = require('./wdio-common')
|
|
2
2
|
|
|
3
|
-
module.exports = function(RED) {
|
|
3
|
+
module.exports = function (RED) {
|
|
4
4
|
function dropdownAction(config) {
|
|
5
5
|
RED.nodes.createNode(this, config)
|
|
6
6
|
const node = this
|
|
@@ -8,16 +8,48 @@ module.exports = function(RED) {
|
|
|
8
8
|
|
|
9
9
|
node.on('input', async (msg) => {
|
|
10
10
|
try {
|
|
11
|
-
|
|
12
|
-
let
|
|
11
|
+
common.clearStatus(node);
|
|
12
|
+
let multiple = config.locateType || msg.locateType;
|
|
13
|
+
let locateValues = config.locateValues || msg.locateValues;
|
|
14
|
+
let locateUsing = config.locateUsing || msg.locateUsing;
|
|
15
|
+
let locateValue = config.locateValue || msg.locateValue;
|
|
16
|
+
let element = null;
|
|
17
|
+
node.log = "";
|
|
13
18
|
|
|
14
19
|
let browser = await common.getBrowser(node.context())
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
20
|
+
if(!multiple){
|
|
21
|
+
let locator = await common.getLocator(
|
|
22
|
+
locateUsing,
|
|
23
|
+
locateValue
|
|
24
|
+
)
|
|
25
|
+
element = await browser.$(locator)
|
|
26
|
+
if (!element) {
|
|
27
|
+
throw new Error(`Element not found using ${locateUsing}: ${locateValue}`);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
else{
|
|
31
|
+
for(let i = 0; i <locateValues.length; i++){
|
|
32
|
+
const { using, value } = locateValues[i];
|
|
33
|
+
let locator = await common.getLocator(
|
|
34
|
+
locateUsing,
|
|
35
|
+
locateValue
|
|
36
|
+
)
|
|
37
|
+
element = await browser.$(locator)
|
|
38
|
+
if (element) {
|
|
39
|
+
node.log += `Attempt ${i + 1}: Element found using ${using}: ${value}\n`;
|
|
40
|
+
locateUsing = using
|
|
41
|
+
locateValue = value
|
|
42
|
+
break;
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
node.log += `Attempt ${i + 1}: Element not found using ${using}: ${value}\n`;
|
|
46
|
+
node.warn(`Element not found using ${using}: ${value}`);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
if (!element) {
|
|
50
|
+
throw new Error(`Element not found using all selector values`);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
21
53
|
|
|
22
54
|
let text = config.text || msg.text
|
|
23
55
|
let attribute = config.attribute || msg.attribute
|
|
@@ -25,16 +57,16 @@ module.exports = function(RED) {
|
|
|
25
57
|
let value = config.value || msg.value
|
|
26
58
|
|
|
27
59
|
if (config.action === 'selectByAttr') {
|
|
28
|
-
node.log
|
|
60
|
+
node.log += `Select the dropdown value using Attribute: ${attribute} with Value: ${value}.`
|
|
29
61
|
await element.selectByAttribute(attribute, value)
|
|
30
62
|
} else if (config.action === 'selectByIndex') {
|
|
31
|
-
node.log
|
|
63
|
+
node.log += `Select the dropdown value using Index: ${index}.`
|
|
32
64
|
await element.selectByIndex(parseInt(index))
|
|
33
65
|
} else if (config.action === 'selectByText') {
|
|
34
|
-
node.log
|
|
66
|
+
node.log += `Select the dropdown value using Visible text: ${text}.`
|
|
35
67
|
await element.selectByVisibleText(text)
|
|
36
68
|
} else if (config.action === 'getValue') {
|
|
37
|
-
node.log
|
|
69
|
+
node.log += 'Get selected drop down value.'
|
|
38
70
|
msg.payload = await element.getValue()
|
|
39
71
|
}
|
|
40
72
|
await common.log(node)
|
package/src/element-action.html
CHANGED
|
@@ -144,7 +144,7 @@
|
|
|
144
144
|
<input id="node-input-locateType" type="checkbox" style="width:30px;" onchange="showSelectors()">
|
|
145
145
|
</div>
|
|
146
146
|
<div class="form-row">
|
|
147
|
-
<label for="node-input-locateUsing"><i class="fa fa-tasks"></i> Locate
|
|
147
|
+
<label for="node-input-locateUsing"><i class="fa fa-tasks"></i> Locate Using</label>
|
|
148
148
|
<select type="text" id="node-input-locateUsing" style="width:70%;">
|
|
149
149
|
<option value="id">id</option>
|
|
150
150
|
<option value="name">name</option>
|
|
@@ -160,7 +160,7 @@
|
|
|
160
160
|
<input id="node-input-locateValue" type="text">
|
|
161
161
|
</div>
|
|
162
162
|
<div class="form-row node-input-locateValues-container-row" style="position:relative">
|
|
163
|
-
<h4 style="margin-bottom:
|
|
163
|
+
<h4 style="margin-bottom: 3px;">Selectors :</h4>
|
|
164
164
|
<ol id="node-input-locateValues-container"></ol>
|
|
165
165
|
</div>
|
|
166
166
|
</script>
|
package/src/element-action.js
CHANGED
|
@@ -1,107 +1,134 @@
|
|
|
1
|
-
const common = require(
|
|
1
|
+
const common = require("./wdio-common");
|
|
2
2
|
|
|
3
|
-
module.exports = function(RED) {
|
|
3
|
+
module.exports = function (RED) {
|
|
4
4
|
function elementAction(config) {
|
|
5
|
-
RED.nodes.createNode(this, config)
|
|
6
|
-
const node = this
|
|
7
|
-
const context = node.context()
|
|
8
|
-
common.clearStatus(node)
|
|
5
|
+
RED.nodes.createNode(this, config);
|
|
6
|
+
const node = this;
|
|
7
|
+
const context = node.context();
|
|
9
8
|
|
|
10
9
|
var getTypeInputValue = async (msg, type, value) => {
|
|
11
|
-
var r =
|
|
10
|
+
var r = "";
|
|
12
11
|
switch (type) {
|
|
13
|
-
case
|
|
14
|
-
r = RED.util.getMessageProperty(msg, value)
|
|
15
|
-
break
|
|
16
|
-
case
|
|
17
|
-
r = context.flow.get(value)
|
|
18
|
-
break
|
|
19
|
-
case
|
|
20
|
-
r = context.global.get(value)
|
|
21
|
-
break
|
|
22
|
-
case
|
|
12
|
+
case "msg":
|
|
13
|
+
r = RED.util.getMessageProperty(msg, value);
|
|
14
|
+
break;
|
|
15
|
+
case "flow":
|
|
16
|
+
r = context.flow.get(value);
|
|
17
|
+
break;
|
|
18
|
+
case "global":
|
|
19
|
+
r = context.global.get(value);
|
|
20
|
+
break;
|
|
21
|
+
case "str":
|
|
23
22
|
try {
|
|
24
|
-
r = unescape(JSON.parse('"' + value + '"'))
|
|
23
|
+
r = unescape(JSON.parse('"' + value + '"'));
|
|
25
24
|
} catch (e) {
|
|
26
|
-
r = value
|
|
25
|
+
r = value;
|
|
27
26
|
}
|
|
28
|
-
break
|
|
29
|
-
case
|
|
30
|
-
r = parseFloat(value)
|
|
31
|
-
break
|
|
32
|
-
case
|
|
33
|
-
if (value !==
|
|
34
|
-
r = JSON.parse(value)
|
|
27
|
+
break;
|
|
28
|
+
case "num":
|
|
29
|
+
r = parseFloat(value);
|
|
30
|
+
break;
|
|
31
|
+
case "json":
|
|
32
|
+
if (value !== "") {
|
|
33
|
+
r = JSON.parse(value);
|
|
35
34
|
} else {
|
|
36
|
-
r = undefined
|
|
35
|
+
r = undefined;
|
|
37
36
|
}
|
|
38
37
|
}
|
|
39
|
-
return r
|
|
40
|
-
}
|
|
38
|
+
return r;
|
|
39
|
+
};
|
|
41
40
|
|
|
42
|
-
node.on(
|
|
43
|
-
try {
|
|
44
|
-
|
|
45
|
-
let
|
|
46
|
-
let
|
|
47
|
-
let
|
|
48
|
-
|
|
49
|
-
let browser = await common.getBrowser(context)
|
|
50
|
-
let capabilities = browser.capabilities
|
|
51
|
-
let elementId = await common.getElementId(
|
|
52
|
-
browser,
|
|
53
|
-
locateUsing,
|
|
54
|
-
locateValue
|
|
55
|
-
)
|
|
41
|
+
node.on("input", async (msg) => {
|
|
42
|
+
try {
|
|
43
|
+
common.clearStatus(node);
|
|
44
|
+
let multiple = config.locateType || msg.locateType;
|
|
45
|
+
let locateValues = config.locateValues || msg.locateValues;
|
|
46
|
+
let locateUsing = config.locateUsing || msg.locateUsing;
|
|
47
|
+
let locateValue = config.locateValue || msg.locateValue;
|
|
56
48
|
|
|
57
|
-
let
|
|
49
|
+
let browser = await common.getBrowser(context);
|
|
50
|
+
let capabilities = browser.capabilities;
|
|
51
|
+
let elementId = null;
|
|
52
|
+
node.log = "";
|
|
58
53
|
|
|
59
|
-
if (
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
54
|
+
if (!multiple) {
|
|
55
|
+
elementId = await common.getElementId(
|
|
56
|
+
browser,
|
|
57
|
+
locateUsing,
|
|
58
|
+
locateValue
|
|
59
|
+
);
|
|
60
|
+
if (!elementId) {
|
|
61
|
+
throw new Error(`Element not found using ${locateUsing}: ${locateValue}`);
|
|
62
|
+
}
|
|
63
|
+
} else {
|
|
64
|
+
for (let i = 0; i < locateValues.length; i++) {
|
|
65
|
+
const { using, value } = locateValues[i];
|
|
66
|
+
elementId = await common.getElementId(browser, using, value);
|
|
67
|
+
if (elementId) {
|
|
68
|
+
node.log += `Attempt ${i + 1}: Element found using ${using}: ${value}\n`;
|
|
69
|
+
locateUsing = using
|
|
70
|
+
locateValue = value
|
|
71
|
+
break;
|
|
72
|
+
}
|
|
73
|
+
else {
|
|
74
|
+
node.log += `Attempt ${i + 1}: Element not found using ${using}: ${value}\n`;
|
|
75
|
+
node.warn(`Element not found using ${using}: ${value}`);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
if (!elementId) {
|
|
79
|
+
throw new Error(`Element not found using all selector values`);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
let attribute = config.attribute || msg.attribute;
|
|
84
|
+
|
|
85
|
+
if (config.action === "click") {
|
|
86
|
+
node.log += `Click on the webelement identified using ${locateUsing}: "${locateValue}".`;
|
|
87
|
+
await browser.elementClick(elementId);
|
|
88
|
+
} else if (config.action === "clear") {
|
|
89
|
+
node.log += `Clear the Value of the webelement identified using ${locateUsing}: "${locateValue}".`;
|
|
90
|
+
await browser.elementClear(elementId);
|
|
91
|
+
} else if (config.action === "sendKeys") {
|
|
66
92
|
let value = await getTypeInputValue(
|
|
67
93
|
msg,
|
|
68
94
|
config.object,
|
|
69
95
|
config.sendKeys
|
|
70
|
-
)
|
|
71
|
-
node.log
|
|
96
|
+
);
|
|
97
|
+
node.log += `Enter the Value: "${value}" to the webelement identified using ${locateUsing}: "${locateValue}".`;
|
|
72
98
|
await browser.elementSendKeys(
|
|
73
99
|
elementId,
|
|
74
100
|
capabilities.version ? Array.from(value) : value
|
|
75
|
-
)
|
|
76
|
-
} else if (config.action ===
|
|
77
|
-
node.log
|
|
78
|
-
msg.payload = await browser.getElementAttribute(elementId,
|
|
79
|
-
} else if (config.action ===
|
|
80
|
-
node.log
|
|
81
|
-
msg.payload = await browser.getElementText(elementId)
|
|
82
|
-
} else if (config.action ===
|
|
83
|
-
node.log
|
|
84
|
-
msg.payload = await browser.getElementAttribute(elementId, attribute)
|
|
85
|
-
} else if (config.action ===
|
|
86
|
-
node.log
|
|
87
|
-
msg.payload = await browser.takeElementScreenshot(elementId)
|
|
88
|
-
} else if (config.action ===
|
|
101
|
+
);
|
|
102
|
+
} else if (config.action === "getValue") {
|
|
103
|
+
node.log += `Get the Value of webelement identified using ${locateUsing}: "${locateValue}".`;
|
|
104
|
+
msg.payload = await browser.getElementAttribute(elementId, "value");
|
|
105
|
+
} else if (config.action === "getText") {
|
|
106
|
+
node.log += `Get the Text of webelement identified using ${locateUsing}: "${locateValue}".`;
|
|
107
|
+
msg.payload = await browser.getElementText(elementId);
|
|
108
|
+
} else if (config.action === "getAttribute") {
|
|
109
|
+
node.log += `Get the Attribute: "${attribute}" of webelement identified using ${locateUsing}: "${locateValue}".`;
|
|
110
|
+
msg.payload = await browser.getElementAttribute(elementId, attribute);
|
|
111
|
+
} else if (config.action === "takeScreenShot") {
|
|
112
|
+
node.log += "Take the screenshot of the webelement.";
|
|
113
|
+
msg.payload = await browser.takeElementScreenshot(elementId);
|
|
114
|
+
} else if (config.action === "hover") {
|
|
89
115
|
let element = await common.getElement(
|
|
90
116
|
browser,
|
|
91
117
|
locateUsing,
|
|
92
118
|
locateValue
|
|
93
|
-
)
|
|
94
|
-
node.log
|
|
95
|
-
msg.payload = await element.moveTo()
|
|
119
|
+
);
|
|
120
|
+
node.log += `Hover on the webelement identified using ${locateUsing}: "${locateValue}".`;
|
|
121
|
+
msg.payload = await element.moveTo();
|
|
96
122
|
}
|
|
97
|
-
await common.log(node)
|
|
98
|
-
common.successStatus(node)
|
|
99
|
-
node.send(msg)
|
|
123
|
+
await common.log(node);
|
|
124
|
+
common.successStatus(node);
|
|
125
|
+
node.send(msg);
|
|
100
126
|
} catch (e) {
|
|
101
|
-
|
|
102
|
-
common.
|
|
127
|
+
node.log = `Error: ${e.message}`;
|
|
128
|
+
await common.log(node);
|
|
129
|
+
common.handleError(e, node, msg);
|
|
103
130
|
}
|
|
104
|
-
})
|
|
131
|
+
});
|
|
105
132
|
}
|
|
106
|
-
RED.nodes.registerType(
|
|
107
|
-
}
|
|
133
|
+
RED.nodes.registerType("element-action", elementAction);
|
|
134
|
+
};
|
package/src/element-check.html
CHANGED
|
@@ -4,8 +4,10 @@
|
|
|
4
4
|
color: '#a6bbcf',
|
|
5
5
|
defaults: {
|
|
6
6
|
name: { value: '' },
|
|
7
|
+
locateType: { value: false },
|
|
7
8
|
locateUsing: { value: 'xpath' },
|
|
8
9
|
locateValue: { value: '' },
|
|
10
|
+
locateValues: { value: [] },
|
|
9
11
|
check: { value: 'selected' }
|
|
10
12
|
},
|
|
11
13
|
inputs: 1,
|
|
@@ -13,11 +15,54 @@
|
|
|
13
15
|
icon: 'white-globe.png',
|
|
14
16
|
label: function() {
|
|
15
17
|
return this.name || 'element check'
|
|
16
|
-
}
|
|
18
|
+
},
|
|
19
|
+
oneditprepare: function () {
|
|
20
|
+
var that = this
|
|
21
|
+
showSelectors()
|
|
22
|
+
multiSelectorsUI(that)
|
|
23
|
+
},
|
|
24
|
+
oneditsave: function () {
|
|
25
|
+
var node = this
|
|
26
|
+
var locateType = $('#node-input-locateType').prop('checked')
|
|
27
|
+
node.locateType = locateType
|
|
28
|
+
if (locateType) {
|
|
29
|
+
var locateValues = $('#node-input-locateValues-container').editableList('items')
|
|
30
|
+
node.locateValues = []
|
|
31
|
+
locateValues.each(function () {
|
|
32
|
+
var using = $(this).find('.node-input-locateValues-using').val()
|
|
33
|
+
var value = $(this).find('.node-input-locateValues-value').val()
|
|
34
|
+
node.locateValues.push({ using, value })
|
|
35
|
+
})
|
|
36
|
+
} else {
|
|
37
|
+
node.locateValues = []
|
|
38
|
+
node.locateValue = $('#node-input-locateValue').val()
|
|
39
|
+
node.locateUsing = $('#node-input-locateUsing').val()
|
|
40
|
+
}
|
|
41
|
+
}
|
|
17
42
|
})
|
|
18
43
|
</script>
|
|
19
44
|
|
|
20
45
|
<script type="text/x-red" data-template-name="element-check">
|
|
46
|
+
<div class="form-row">
|
|
47
|
+
<label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
|
|
48
|
+
<input id="node-input-name" type="text">
|
|
49
|
+
</div>
|
|
50
|
+
<div class="form-row">
|
|
51
|
+
<label for="node-input-check"><i class="fa fa-tasks"></i> Check</label>
|
|
52
|
+
<select type="text" id="node-input-check" style="width:70%;">
|
|
53
|
+
<option value="clickable">Is Clickable</option>
|
|
54
|
+
<option value="displayed">Is Displayed</option>
|
|
55
|
+
<option value="displayedInView">Is Displayed in Viewport</option>
|
|
56
|
+
<option value="enabled">Is Enabled</option>
|
|
57
|
+
<option value="existing">Is Existing</option>
|
|
58
|
+
<option value="focused">Is Focused</option>
|
|
59
|
+
<option value="selected">Is Selected</option>
|
|
60
|
+
</select>
|
|
61
|
+
</div>
|
|
62
|
+
<div class="form-row">
|
|
63
|
+
<label for="node-input-locateType"><i class="fa fa-tasks"></i> Multiple Selector?</label>
|
|
64
|
+
<input id="node-input-locateType" type="checkbox" style="width:30px;" onchange="showSelectors()">
|
|
65
|
+
</div>
|
|
21
66
|
<div class="form-row">
|
|
22
67
|
<label for="node-input-locateUsing"><i class="fa fa-tasks"></i> Locate Method</label>
|
|
23
68
|
<select type="text" id="node-input-locateUsing" style="width:70%;">
|
|
@@ -34,22 +79,9 @@
|
|
|
34
79
|
<label for="node-input-locateValue"><i class="fa fa-tasks"></i> Selector</label>
|
|
35
80
|
<input id="node-input-locateValue" type="text">
|
|
36
81
|
</div>
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
<select type="text" id="node-input-check" style="width:70%;">
|
|
41
|
-
<option value="clickable">Is Clickable</option>
|
|
42
|
-
<option value="displayed">Is Displayed</option>
|
|
43
|
-
<option value="displayedInView">Is Displayed in Viewport</option>
|
|
44
|
-
<option value="enabled">Is Enabled</option>
|
|
45
|
-
<option value="existing">Is Existing</option>
|
|
46
|
-
<option value="focused">Is Focused</option>
|
|
47
|
-
<option value="selected">Is Selected</option>
|
|
48
|
-
</select>
|
|
49
|
-
</div>
|
|
50
|
-
<div class="form-row">
|
|
51
|
-
<label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
|
|
52
|
-
<input id="node-input-name" type="text">
|
|
82
|
+
<div class="form-row node-input-locateValues-container-row" style="position:relative">
|
|
83
|
+
<h4 style="margin-bottom: 3px;">Selectors :</h4>
|
|
84
|
+
<ol id="node-input-locateValues-container"></ol>
|
|
53
85
|
</div>
|
|
54
86
|
</script>
|
|
55
87
|
|
package/src/element-check.js
CHANGED
|
@@ -4,40 +4,68 @@ module.exports = function (RED) {
|
|
|
4
4
|
function elementCheck(config) {
|
|
5
5
|
RED.nodes.createNode(this, config)
|
|
6
6
|
const node = this
|
|
7
|
-
common.clearStatus(node)
|
|
8
7
|
|
|
9
8
|
node.on('input', async (msg) => {
|
|
10
9
|
try {
|
|
11
|
-
|
|
12
|
-
let
|
|
10
|
+
common.clearStatus(node)
|
|
11
|
+
let multiple = config.locateType || msg.locateType;
|
|
12
|
+
let locateValues = config.locateValues || msg.locateValues;
|
|
13
|
+
let locateUsing = config.locateUsing || msg.locateUsing;
|
|
14
|
+
let locateValue = config.locateValue || msg.locateValue;
|
|
13
15
|
|
|
14
|
-
let browser = await common.getBrowser(
|
|
15
|
-
let
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
16
|
+
let browser = await common.getBrowser(context);
|
|
17
|
+
let elementId = null;
|
|
18
|
+
node.log = "";
|
|
19
|
+
|
|
20
|
+
if (!multiple) {
|
|
21
|
+
elementId = await common.getElementId(
|
|
22
|
+
browser,
|
|
23
|
+
locateUsing,
|
|
24
|
+
locateValue
|
|
25
|
+
);
|
|
26
|
+
if (!elementId) {
|
|
27
|
+
throw new Error(`Element not found using ${locateUsing}: ${locateValue}`);
|
|
28
|
+
}
|
|
29
|
+
} else {
|
|
30
|
+
for (let i = 0; i < locateValues.length; i++) {
|
|
31
|
+
const { using, value } = locateValues[i];
|
|
32
|
+
elementId = await common.getElementId(browser, using, value);
|
|
33
|
+
if (elementId) {
|
|
34
|
+
node.log += `Attempt ${i + 1}: Element found using ${using}: ${value}\n`;
|
|
35
|
+
locateUsing = using
|
|
36
|
+
locateValue = value
|
|
37
|
+
break;
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
node.log += `Attempt ${i + 1}: Element not found using ${using}: ${value}\n`;
|
|
41
|
+
node.warn(`Element not found using ${using}: ${value}`);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
if (!elementId) {
|
|
45
|
+
throw new Error(`Element not found using all selector values`);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
20
48
|
|
|
21
49
|
if (config.check === 'clickable') {
|
|
22
|
-
node.log
|
|
50
|
+
node.log += `Check the webelement is clickable, identified using ${locateUsing}: "${locateValue}".`
|
|
23
51
|
msg.payload = await browser.$(locator).isClickable()
|
|
24
52
|
} else if (config.check === 'displayed') {
|
|
25
|
-
node.log
|
|
26
|
-
msg.payload =
|
|
53
|
+
node.log += `Check the webelement is displayed, identified using ${locateUsing}: "${locateValue}".`
|
|
54
|
+
msg.payload = await browser.$(locator).isDisplayed()
|
|
27
55
|
} else if (config.check === 'displayedInView') {
|
|
28
|
-
node.log
|
|
56
|
+
node.log += `Check the webelement is displayed in view port, identified using ${locateUsing}: "${locateValue}".`
|
|
29
57
|
msg.payload = await browser.$(locator).isDisplayedInViewport()
|
|
30
58
|
} else if (config.check === 'enabled') {
|
|
31
|
-
node.log
|
|
32
|
-
msg.payload =
|
|
59
|
+
node.log += `Check the webelement is enabled, identified using ${locateUsing}: "${locateValue}".`
|
|
60
|
+
msg.payload = await browser.$(locator).isEnabled()
|
|
33
61
|
} else if (config.check === 'existing') {
|
|
34
|
-
node.log
|
|
62
|
+
node.log += `Check the webelement is existing, identified using ${locateUsing}: "${locateValue}".`
|
|
35
63
|
msg.payload = await browser.$(locator).isExisting()
|
|
36
64
|
} else if (config.check === 'focused') {
|
|
37
|
-
node.log
|
|
38
|
-
msg.payload =
|
|
65
|
+
node.log += `Check the webelement is focused, identified using ${locateUsing}: "${locateValue}".`
|
|
66
|
+
msg.payload = await browser.$(locator).isFocused()
|
|
39
67
|
} else if (config.check === 'selected') {
|
|
40
|
-
node.log
|
|
68
|
+
node.log += `Check the webelement is selected, identified using ${locateUsing}: "${locateValue}".`
|
|
41
69
|
msg.payload = await browser.$(locator).isSelected()
|
|
42
70
|
}
|
|
43
71
|
await common.log(node)
|
|
@@ -52,9 +80,9 @@ module.exports = function (RED) {
|
|
|
52
80
|
// node.send(msg)
|
|
53
81
|
// }
|
|
54
82
|
// else{
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
83
|
+
await common.log(node)
|
|
84
|
+
common.handleError(e, node, msg)
|
|
85
|
+
}
|
|
58
86
|
//}
|
|
59
87
|
})
|
|
60
88
|
}
|
package/src/execute-script.html
CHANGED
|
@@ -4,8 +4,10 @@
|
|
|
4
4
|
color: '#a6bbcf',
|
|
5
5
|
defaults: {
|
|
6
6
|
name: { value: '' },
|
|
7
|
+
locateType: { value: false },
|
|
7
8
|
locateUsing: { value: 'xpath' },
|
|
8
9
|
locateValue: { value: '' },
|
|
10
|
+
locateValues: { value: [] },
|
|
9
11
|
action: { value: 'sync' },
|
|
10
12
|
script: { value: '' }
|
|
11
13
|
},
|
|
@@ -14,11 +16,53 @@
|
|
|
14
16
|
icon: 'white-globe.png',
|
|
15
17
|
label: function() {
|
|
16
18
|
return this.name || 'execute script'
|
|
17
|
-
}
|
|
19
|
+
},
|
|
20
|
+
oneditprepare: function () {
|
|
21
|
+
var that = this
|
|
22
|
+
showSelectors()
|
|
23
|
+
multiSelectorsUI(that)
|
|
24
|
+
},
|
|
25
|
+
oneditsave: function () {
|
|
26
|
+
var node = this
|
|
27
|
+
var locateType = $('#node-input-locateType').prop('checked')
|
|
28
|
+
node.locateType = locateType
|
|
29
|
+
if (locateType) {
|
|
30
|
+
var locateValues = $('#node-input-locateValues-container').editableList('items')
|
|
31
|
+
node.locateValues = []
|
|
32
|
+
locateValues.each(function () {
|
|
33
|
+
var using = $(this).find('.node-input-locateValues-using').val()
|
|
34
|
+
var value = $(this).find('.node-input-locateValues-value').val()
|
|
35
|
+
node.locateValues.push({ using, value })
|
|
36
|
+
})
|
|
37
|
+
} else {
|
|
38
|
+
node.locateValues = []
|
|
39
|
+
node.locateValue = $('#node-input-locateValue').val()
|
|
40
|
+
node.locateUsing = $('#node-input-locateUsing').val()
|
|
41
|
+
}
|
|
42
|
+
}
|
|
18
43
|
})
|
|
19
44
|
</script>
|
|
20
45
|
|
|
21
46
|
<script type="text/x-red" data-template-name="execute-script">
|
|
47
|
+
<div class="form-row">
|
|
48
|
+
<label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
|
|
49
|
+
<input id="node-input-name" type="text">
|
|
50
|
+
</div>
|
|
51
|
+
<div class="form-row">
|
|
52
|
+
<label for="node-input-action"><i class="fa fa-tasks"></i> Action</label>
|
|
53
|
+
<select type="text" id="node-input-action" style="width:70%;">
|
|
54
|
+
<option value="sync">Sync</option>
|
|
55
|
+
<option value="aSync">Async</option>
|
|
56
|
+
</select>
|
|
57
|
+
</div>
|
|
58
|
+
<div class="form-row">
|
|
59
|
+
<label for="node-input-script"><i class="fa fa-tasks"></i> Script</label>
|
|
60
|
+
<input id="node-input-script" type="text" placeholder="javascript in string">
|
|
61
|
+
</div>
|
|
62
|
+
<div class="form-row">
|
|
63
|
+
<label for="node-input-locateType"><i class="fa fa-tasks"></i> Multiple Selector?</label>
|
|
64
|
+
<input id="node-input-locateType" type="checkbox" style="width:30px;" onchange="showSelectors()">
|
|
65
|
+
</div>
|
|
22
66
|
<div class="form-row">
|
|
23
67
|
<label for="node-input-locateUsing"><i class="fa fa-tasks"></i> Locate Method</label>
|
|
24
68
|
<select type="text" id="node-input-locateUsing" style="width:70%;">
|
|
@@ -35,21 +79,10 @@
|
|
|
35
79
|
<label for="node-input-locateValue"><i class="fa fa-tasks"></i> Selector</label>
|
|
36
80
|
<input id="node-input-locateValue" type="text">
|
|
37
81
|
</div>
|
|
38
|
-
<div class="form-row">
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
<option value="aSync">Async</option>
|
|
43
|
-
</select>
|
|
44
|
-
</div>
|
|
45
|
-
<div class="form-row">
|
|
46
|
-
<label for="node-input-script"><i class="fa fa-tasks"></i> Script</label>
|
|
47
|
-
<input id="node-input-script" type="text" placeholder="javascript in string">
|
|
48
|
-
</div>
|
|
49
|
-
<div class="form-row">
|
|
50
|
-
<label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
|
|
51
|
-
<input id="node-input-name" type="text">
|
|
52
|
-
</div>
|
|
82
|
+
<div class="form-row node-input-locateValues-container-row" style="position:relative">
|
|
83
|
+
<h4 style="margin-bottom: 3px;">Selectors :</h4>
|
|
84
|
+
<ol id="node-input-locateValues-container"></ol>
|
|
85
|
+
</div>
|
|
53
86
|
</script>
|
|
54
87
|
|
|
55
88
|
<script type="text/x-red" data-help-name="execute-script">
|
package/src/execute-script.js
CHANGED
|
@@ -1,30 +1,58 @@
|
|
|
1
1
|
const common = require('./wdio-common')
|
|
2
2
|
|
|
3
|
-
module.exports = function(RED) {
|
|
3
|
+
module.exports = function (RED) {
|
|
4
4
|
function executeScript(config) {
|
|
5
5
|
RED.nodes.createNode(this, config)
|
|
6
6
|
const node = this
|
|
7
|
-
common.clearStatus(node)
|
|
8
7
|
|
|
9
8
|
node.on('input', async (msg) => {
|
|
10
9
|
try {
|
|
11
|
-
|
|
12
|
-
let
|
|
10
|
+
common.clearStatus(node);
|
|
11
|
+
let multiple = config.locateType || msg.locateType;
|
|
12
|
+
let locateValues = config.locateValues || msg.locateValues;
|
|
13
|
+
let locateUsing = config.locateUsing || msg.locateUsing;
|
|
14
|
+
let locateValue = config.locateValue || msg.locateValue;
|
|
13
15
|
|
|
14
|
-
let browser = await common.getBrowser(
|
|
15
|
-
let
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
16
|
+
let browser = await common.getBrowser(context);
|
|
17
|
+
let elementId = null;
|
|
18
|
+
node.log = "";
|
|
19
|
+
|
|
20
|
+
if (!multiple) {
|
|
21
|
+
elementId = await common.getElementId(
|
|
22
|
+
browser,
|
|
23
|
+
locateUsing,
|
|
24
|
+
locateValue
|
|
25
|
+
);
|
|
26
|
+
if (!elementId) {
|
|
27
|
+
throw new Error(`Element not found using ${locateUsing}: ${locateValue}`);
|
|
28
|
+
}
|
|
29
|
+
} else {
|
|
30
|
+
for (let i = 0; i < locateValues.length; i++) {
|
|
31
|
+
const { using, value } = locateValues[i];
|
|
32
|
+
elementId = await common.getElementId(browser, using, value);
|
|
33
|
+
if (elementId) {
|
|
34
|
+
node.log += `Attempt ${i + 1}: Element found using ${using}: ${value}\n`;
|
|
35
|
+
locateUsing = using
|
|
36
|
+
locateValue = value
|
|
37
|
+
break;
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
node.log += `Attempt ${i + 1}: Element not found using ${using}: ${value}\n`;
|
|
41
|
+
node.warn(`Element not found using ${using}: ${value}`);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
if (!elementId) {
|
|
45
|
+
throw new Error(`Element not found using all selector values`);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
20
48
|
|
|
21
49
|
let script = config.script || msg.script
|
|
22
50
|
|
|
23
51
|
if (config.action === 'sync') {
|
|
24
|
-
node.log
|
|
52
|
+
node.log += `Execute synchronous Javascript: "${script}"${element ? ` By passing the webelement identified using ${locateUsing}: "${locateValue}"` : ''}.`
|
|
25
53
|
await browser.executeScript(script, Array.from(element))
|
|
26
54
|
} else if (config.action === 'aSync') {
|
|
27
|
-
node.log
|
|
55
|
+
node.log += `Execute the asynchronous Javascript: "${script}"${element ? ` By passing the webelement identified using ${locateUsing}: "${locateValue}"` : ''}.`
|
|
28
56
|
await browser.executeAsyncScript(script, Array.from(element))
|
|
29
57
|
}
|
|
30
58
|
await common.log(node)
|
package/src/explicit-wait.html
CHANGED
|
@@ -26,16 +26,20 @@
|
|
|
26
26
|
inputs: 1,
|
|
27
27
|
outputs: 1,
|
|
28
28
|
icon: 'white-globe.png',
|
|
29
|
-
label: function() {
|
|
29
|
+
label: function () {
|
|
30
30
|
return this.name || 'explicit wait'
|
|
31
31
|
},
|
|
32
|
-
oneditprepare: function() {
|
|
32
|
+
oneditprepare: function () {
|
|
33
33
|
setExplicitAction()
|
|
34
34
|
}
|
|
35
35
|
})
|
|
36
36
|
</script>
|
|
37
37
|
|
|
38
38
|
<script type="text/x-red" data-template-name="explicit-wait">
|
|
39
|
+
<div class="form-row">
|
|
40
|
+
<label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
|
|
41
|
+
<input id="node-input-name" type="text">
|
|
42
|
+
</div>
|
|
39
43
|
<div class="form-row">
|
|
40
44
|
<label for="node-input-locateUsing"><i class="fa fa-tasks"></i> Locate Method</label>
|
|
41
45
|
<select type="text" id="node-input-locateUsing" style="width:70%;">
|
|
@@ -76,11 +80,7 @@
|
|
|
76
80
|
<div class="form-row" id="actionError" >
|
|
77
81
|
<label for="node-input-error"><i class="fa fa-tasks"></i> Error Message</label>
|
|
78
82
|
<input id="node-input-error" type="text" placeholder="error message">
|
|
79
|
-
</div>
|
|
80
|
-
<div class="form-row">
|
|
81
|
-
<label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
|
|
82
|
-
<input id="node-input-name" type="text">
|
|
83
|
-
</div>
|
|
83
|
+
</div>
|
|
84
84
|
</script>
|
|
85
85
|
|
|
86
86
|
<script type="text/x-red" data-help-name="explicit-wait">
|
|
@@ -121,7 +121,4 @@
|
|
|
121
121
|
<p><b>Time to Wait</b> Set time to wait in milliseconds. <br></p>
|
|
122
122
|
<p><b>Reverse</b> If set to true, webdriver will wait for the <i>opposite</i> of the action selected. <br></p>
|
|
123
123
|
<p><b>Error Message</b> If an error exists this error message overrides the default error message. <br></p>
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
124
|
</script>
|
package/src/explicit-wait.js
CHANGED
|
@@ -13,7 +13,6 @@ module.exports = function(RED) {
|
|
|
13
13
|
|
|
14
14
|
let browser = await common.getBrowser(node.context())
|
|
15
15
|
let locator = await common.getLocator(
|
|
16
|
-
browser,
|
|
17
16
|
locateUsing,
|
|
18
17
|
locateValue
|
|
19
18
|
)
|
|
@@ -45,4 +44,4 @@ module.exports = function(RED) {
|
|
|
45
44
|
})
|
|
46
45
|
}
|
|
47
46
|
RED.nodes.registerType('explicit-wait', explicitWait)
|
|
48
|
-
}
|
|
47
|
+
}
|
package/src/wdio-common.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
const wdio = require(
|
|
2
|
-
let newSessionNode
|
|
1
|
+
const wdio = require("webdriverio");
|
|
2
|
+
let newSessionNode;
|
|
3
3
|
|
|
4
4
|
module.exports.getBrowser = (context) => {
|
|
5
|
-
let browser = context.flow.get(
|
|
5
|
+
let browser = context.flow.get("wdio_browser");
|
|
6
6
|
if (!browser || !browser.sessionId)
|
|
7
|
-
throw new Error(
|
|
7
|
+
throw new Error("No session defined - call newSession first");
|
|
8
8
|
|
|
9
|
-
return browser
|
|
10
|
-
}
|
|
9
|
+
return browser;
|
|
10
|
+
};
|
|
11
11
|
|
|
12
12
|
/*
|
|
13
13
|
config = {
|
|
@@ -25,139 +25,131 @@ config = {
|
|
|
25
25
|
}
|
|
26
26
|
*/
|
|
27
27
|
module.exports.newSession = async (config, node, context) => {
|
|
28
|
-
let browser
|
|
28
|
+
let browser;
|
|
29
29
|
try {
|
|
30
|
-
browser = await wdio.remote(config)
|
|
31
|
-
context.flow.set(
|
|
32
|
-
newSessionNode = node
|
|
30
|
+
browser = await wdio.remote(config);
|
|
31
|
+
context.flow.set("wdio_browser", browser);
|
|
32
|
+
newSessionNode = node;
|
|
33
33
|
} catch (e) {
|
|
34
|
-
throw e
|
|
34
|
+
throw e;
|
|
35
35
|
}
|
|
36
|
-
return browser
|
|
37
|
-
}
|
|
36
|
+
return browser;
|
|
37
|
+
};
|
|
38
38
|
|
|
39
39
|
module.exports.deleteSession = async (context) => {
|
|
40
|
-
let b
|
|
41
|
-
let browser = context.flow.get(
|
|
40
|
+
let b;
|
|
41
|
+
let browser = context.flow.get("wdio_browser");
|
|
42
42
|
try {
|
|
43
|
-
b = { sessionId: browser.sessionId }
|
|
44
|
-
await browser.closeWindow()
|
|
45
|
-
await browser.deleteSession()
|
|
46
|
-
context.flow.set(
|
|
47
|
-
if (newSessionNode) module.exports.disconnected(newSessionNode)
|
|
43
|
+
b = { sessionId: browser.sessionId };
|
|
44
|
+
await browser.closeWindow();
|
|
45
|
+
await browser.deleteSession();
|
|
46
|
+
context.flow.set("wdio_browser", null);
|
|
47
|
+
if (newSessionNode) module.exports.disconnected(newSessionNode);
|
|
48
48
|
} catch (e) {}
|
|
49
|
-
return b
|
|
50
|
-
}
|
|
49
|
+
return b;
|
|
50
|
+
};
|
|
51
51
|
|
|
52
52
|
module.exports.getElementId = async (browser, using, value) => {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
53
|
+
const element = await browser.findElement(using, value);
|
|
54
|
+
return element.ELEMENT ?? "";
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
module.exports.getLocator = async (using, value) => {
|
|
58
|
+
let locator = "";
|
|
59
|
+
switch (using) {
|
|
60
|
+
case "id":
|
|
61
|
+
locator = `#${value}`;
|
|
62
|
+
break;
|
|
63
|
+
case "name":
|
|
64
|
+
locator = `[name='${value}']`;
|
|
65
|
+
break;
|
|
66
|
+
case "className":
|
|
67
|
+
locator = `.${value}`;
|
|
68
|
+
break;
|
|
69
|
+
case "tagName":
|
|
70
|
+
locator = value;
|
|
71
|
+
break;
|
|
72
|
+
case "cssSelector":
|
|
73
|
+
locator = value;
|
|
74
|
+
break;
|
|
75
|
+
case "text":
|
|
76
|
+
locator = `=${value}`;
|
|
77
|
+
break;
|
|
78
|
+
case "partialText":
|
|
79
|
+
locator = `*=${value}`;
|
|
80
|
+
break;
|
|
81
|
+
case "xPath":
|
|
82
|
+
locator = value;
|
|
83
|
+
break;
|
|
84
|
+
default:
|
|
85
|
+
locator = value;
|
|
69
86
|
}
|
|
70
|
-
return elementId
|
|
71
|
-
}
|
|
72
87
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
switch (using) {
|
|
76
|
-
case 'id':
|
|
77
|
-
locator = `#${value}`
|
|
78
|
-
break
|
|
79
|
-
case 'name':
|
|
80
|
-
locator = `[name='${value}']`
|
|
81
|
-
break
|
|
82
|
-
case 'className':
|
|
83
|
-
locator = `.${value}`
|
|
84
|
-
break
|
|
85
|
-
case 'tagName':
|
|
86
|
-
locator = value
|
|
87
|
-
break
|
|
88
|
-
case 'cssSelector':
|
|
89
|
-
locator = value
|
|
90
|
-
break
|
|
91
|
-
case 'text':
|
|
92
|
-
locator = `=${value}`
|
|
93
|
-
break
|
|
94
|
-
case 'partialText':
|
|
95
|
-
locator = `*=${value}`
|
|
96
|
-
break
|
|
97
|
-
case 'xPath':
|
|
98
|
-
locator = value
|
|
99
|
-
break
|
|
100
|
-
default:
|
|
101
|
-
locator = value
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
return locator
|
|
105
|
-
}
|
|
88
|
+
return locator;
|
|
89
|
+
};
|
|
106
90
|
|
|
107
91
|
module.exports.handleError = (e, node, msg) => {
|
|
108
|
-
console.log(e)
|
|
109
|
-
module.exports.errorStatus(node)
|
|
110
|
-
node.error(e, msg)
|
|
111
|
-
}
|
|
92
|
+
console.log(e);
|
|
93
|
+
module.exports.errorStatus(node);
|
|
94
|
+
node.error(e, msg);
|
|
95
|
+
};
|
|
112
96
|
|
|
113
97
|
module.exports.clearStatus = (node) => {
|
|
114
|
-
node.status({})
|
|
115
|
-
}
|
|
98
|
+
node.status({});
|
|
99
|
+
};
|
|
116
100
|
|
|
117
101
|
module.exports.connectedStatus = (node) => {
|
|
118
102
|
node.status({
|
|
119
|
-
fill:
|
|
120
|
-
shape:
|
|
121
|
-
text:
|
|
122
|
-
})
|
|
123
|
-
}
|
|
103
|
+
fill: "green",
|
|
104
|
+
shape: "dot",
|
|
105
|
+
text: "connected",
|
|
106
|
+
});
|
|
107
|
+
};
|
|
124
108
|
|
|
125
109
|
module.exports.disconnectedStatus = (node) => {
|
|
126
110
|
node.status({
|
|
127
|
-
fill:
|
|
128
|
-
shape:
|
|
129
|
-
text:
|
|
130
|
-
})
|
|
131
|
-
}
|
|
111
|
+
fill: "green",
|
|
112
|
+
shape: "ring",
|
|
113
|
+
text: "disconnected",
|
|
114
|
+
});
|
|
115
|
+
};
|
|
132
116
|
|
|
133
117
|
module.exports.successStatus = (node) => {
|
|
134
118
|
node.status({
|
|
135
|
-
fill:
|
|
136
|
-
shape:
|
|
137
|
-
text:
|
|
138
|
-
})
|
|
139
|
-
}
|
|
119
|
+
fill: "green",
|
|
120
|
+
shape: "ring",
|
|
121
|
+
text: "done",
|
|
122
|
+
});
|
|
123
|
+
};
|
|
140
124
|
|
|
141
125
|
module.exports.errorStatus = (node) => {
|
|
142
126
|
node.status({
|
|
143
|
-
fill:
|
|
144
|
-
shape:
|
|
145
|
-
text:
|
|
146
|
-
})
|
|
147
|
-
}
|
|
127
|
+
fill: "red",
|
|
128
|
+
shape: "ring",
|
|
129
|
+
text: "error",
|
|
130
|
+
});
|
|
131
|
+
};
|
|
148
132
|
|
|
149
133
|
module.exports.log = async (node) => {
|
|
150
|
-
let context = node.context()
|
|
151
|
-
let stepCount = await (context.global.get(
|
|
152
|
-
let document = await context.global.get(
|
|
153
|
-
await context.global.set(
|
|
154
|
-
|
|
155
|
-
}
|
|
134
|
+
let context = node.context();
|
|
135
|
+
let stepCount = (await (context.global.get("stepCount") || 0)) + 1;
|
|
136
|
+
let document = (await context.global.get("document")) || "";
|
|
137
|
+
await context.global.set(
|
|
138
|
+
"document",
|
|
139
|
+
`${document}${stepCount}. Node (${node.id}): ${node.name} - ${node.log}\n`
|
|
140
|
+
);
|
|
141
|
+
await context.global.set("stepCount", stepCount);
|
|
142
|
+
};
|
|
156
143
|
|
|
157
144
|
module.exports.document = async (node) => {
|
|
158
|
-
let context = node.context()
|
|
159
|
-
let document = await context.global.get(
|
|
160
|
-
document = node.line
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
}
|
|
145
|
+
let context = node.context();
|
|
146
|
+
let document = (await context.global.get("document")) || "";
|
|
147
|
+
document = node.line
|
|
148
|
+
? `${document}\n${node.name}${
|
|
149
|
+
node.refUrl ? `\nRef: ${node.refUrl}` : ""
|
|
150
|
+
}\n\n`
|
|
151
|
+
: `${document}********************\n${node.name}${
|
|
152
|
+
node.refUrl ? `\nRef: ${node.refUrl}` : ""
|
|
153
|
+
}\n********************\n`;
|
|
154
|
+
await context.global.set("document", document.replaceAll("\\n", "\n"));
|
|
155
|
+
};
|