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 CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "topological-nodered-wdio",
3
3
  "description": "Open source WebdriverIO nodes for Node-RED",
4
- "version": "1.1.0",
4
+ "version": "1.1.1",
5
5
  "author": "topological",
6
6
  "license": "MIT",
7
7
  "repository": {
@@ -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
  )
@@ -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 Method</label>
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: -3px;">Selectors :</h4>
163
+ <h4 style="margin-bottom: 3px;">Selectors :</h4>
164
164
  <ol id="node-input-locateValues-container"></ol>
165
165
  </div>
166
166
  </script>
@@ -1,107 +1,134 @@
1
- const common = require('./wdio-common')
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 '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':
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 'num':
30
- r = parseFloat(value)
31
- break
32
- case 'json':
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('input', async (msg) => {
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 = multiple ? locateValues[0].using : config.locateUsing || msg.locateUsing
47
- let locateValue = multiple ? locateValues[0].value : config.locateValue || msg.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 attribute = config.attribute || msg.attribute
49
+ let browser = await common.getBrowser(context);
50
+ let capabilities = browser.capabilities;
51
+ let elementId = null;
52
+ node.log = "";
58
53
 
59
- if (config.action === 'click') {
60
- node.log = `Click on the webelement identified using ${locateUsing}: "${locateValue}".`
61
- await browser.elementClick(elementId)
62
- } else if (config.action === 'clear') {
63
- node.log = `Clear the Value of the webelement identified using ${locateUsing}: "${locateValue}".`
64
- await browser.elementClear(elementId)
65
- } else if (config.action === 'sendKeys') {
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 = `Enter the Value: "${value}" to the webelement identified using ${locateUsing}: "${locateValue}".`
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 === 'getValue') {
77
- node.log = `Get the Value of webelement identified using ${locateUsing}: "${locateValue}".`
78
- msg.payload = await browser.getElementAttribute(elementId, 'value')
79
- } else if (config.action === 'getText') {
80
- node.log = `Get the Text of webelement identified using ${locateUsing}: "${locateValue}".`
81
- msg.payload = await browser.getElementText(elementId)
82
- } else if (config.action === 'getAttribute') {
83
- node.log = `Get the Attribute: "${attribute}" of webelement identified using ${locateUsing}: "${locateValue}".`
84
- msg.payload = await browser.getElementAttribute(elementId, attribute)
85
- } else if (config.action === 'takeScreenShot') {
86
- node.log = 'Take the screenshot of the webelement.'
87
- msg.payload = await browser.takeElementScreenshot(elementId)
88
- } else if (config.action === 'hover') {
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 = `Hover on the webelement identified using ${locateUsing}: "${locateValue}".`
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
- await common.log(node)
102
- common.handleError(e, node, msg)
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('element-action', elementAction)
107
- }
133
+ RED.nodes.registerType("element-action", elementAction);
134
+ };
@@ -1,13 +1,13 @@
1
- const wdio = require('webdriverio')
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('wdio_browser')
5
+ let browser = context.flow.get("wdio_browser");
6
6
  if (!browser || !browser.sessionId)
7
- throw new Error('No session defined - call newSession first')
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('wdio_browser', browser)
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('wdio_browser')
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('wdio_browser', null)
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
- let elementId
54
- try {
55
- const element = await browser.findElement(using, value)
56
- if (element && Object.keys(element)) {
57
- elementId = element[Object.keys(element)[0]]
58
- } else {
59
- let e
60
- if (element && element.message) {
61
- e = element.message
62
- } else {
63
- e = 'Element not found'
64
- }
65
- throw new Error(e)
66
- }
67
- } catch (e) {
68
- throw e
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
- module.exports.getLocator = async (browser, using, value) => {
74
- let locator = ''
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: 'green',
120
- shape: 'dot',
121
- text: 'connected'
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: 'green',
128
- shape: 'ring',
129
- text: 'disconnected'
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: 'green',
136
- shape: 'ring',
137
- text: 'done'
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: 'red',
144
- shape: 'ring',
145
- text: 'error'
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('stepCount') || 0) + 1
152
- let document = await context.global.get('document') || ''
153
- await context.global.set('document', `${document}${stepCount}. Node: ${node.name} - ${node.log}\n`)
154
- await context.global.set('stepCount', stepCount)
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('document') || ''
160
- document = node.line? `${document}\n${node.name}${node.refUrl? `\nRef: ${node.refUrl}`:''}\n\n` :
161
- `${document}********************\n${node.name}${node.refUrl? `\nRef: ${node.refUrl}`:''}\n********************\n`
162
- await context.global.set('document', document.replaceAll('\\n','\n'))
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
+ };