topological-nodered-wdio 1.1.0 → 1.1.1
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.js +0 -1
- package/src/element-action.html +2 -2
- package/src/element-action.js +104 -77
- package/src/wdio-common.js +103 -111
package/package.json
CHANGED
package/src/dropdown-action.js
CHANGED
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();
|
|
8
|
+
common.clearStatus(node);
|
|
9
9
|
|
|
10
10
|
var getTypeInputValue = async (msg, type, value) => {
|
|
11
|
-
var r =
|
|
11
|
+
var r = "";
|
|
12
12
|
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
|
|
13
|
+
case "msg":
|
|
14
|
+
r = RED.util.getMessageProperty(msg, value);
|
|
15
|
+
break;
|
|
16
|
+
case "flow":
|
|
17
|
+
r = context.flow.get(value);
|
|
18
|
+
break;
|
|
19
|
+
case "global":
|
|
20
|
+
r = context.global.get(value);
|
|
21
|
+
break;
|
|
22
|
+
case "str":
|
|
23
23
|
try {
|
|
24
|
-
r = unescape(JSON.parse('"' + value + '"'))
|
|
24
|
+
r = unescape(JSON.parse('"' + value + '"'));
|
|
25
25
|
} catch (e) {
|
|
26
|
-
r = value
|
|
26
|
+
r = value;
|
|
27
27
|
}
|
|
28
|
-
break
|
|
29
|
-
case
|
|
30
|
-
r = parseFloat(value)
|
|
31
|
-
break
|
|
32
|
-
case
|
|
33
|
-
if (value !==
|
|
34
|
-
r = JSON.parse(value)
|
|
28
|
+
break;
|
|
29
|
+
case "num":
|
|
30
|
+
r = parseFloat(value);
|
|
31
|
+
break;
|
|
32
|
+
case "json":
|
|
33
|
+
if (value !== "") {
|
|
34
|
+
r = JSON.parse(value);
|
|
35
35
|
} else {
|
|
36
|
-
r = undefined
|
|
36
|
+
r = undefined;
|
|
37
37
|
}
|
|
38
38
|
}
|
|
39
|
-
return r
|
|
40
|
-
}
|
|
39
|
+
return r;
|
|
40
|
+
};
|
|
41
41
|
|
|
42
|
-
node.on(
|
|
42
|
+
node.on("input", async (msg) => {
|
|
43
43
|
try {
|
|
44
|
-
let multiple = config.locateType || msg.locateType
|
|
45
|
-
let locateValues = config.locateValues || msg.locateValues
|
|
46
|
-
let locateUsing =
|
|
47
|
-
let locateValue =
|
|
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
|
-
)
|
|
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/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
|
+
};
|