topological-nodered-wdio 0.5.0 → 0.5.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/LICENSE +20 -20
- package/README.md +15 -15
- package/examples/basic.json +332 -332
- package/package.json +44 -43
- package/src/alert-action.html +79 -79
- package/src/alert-action.js +52 -52
- package/src/browser-action.html +114 -114
- package/src/browser-action.js +70 -70
- package/src/delete-session.html +26 -26
- package/src/delete-session.js +29 -29
- package/src/document-helper.html +46 -0
- package/src/document-helper.js +21 -0
- package/src/dropdown-action.html +124 -124
- package/src/dropdown-action.js +50 -50
- package/src/element-action.html +133 -133
- package/src/element-action.js +105 -105
- package/src/element-check.html +90 -90
- package/src/element-check.js +62 -62
- package/src/execute-script.html +92 -92
- package/src/execute-script.js +40 -40
- package/src/explicit-wait.html +126 -126
- package/src/explicit-wait.js +48 -48
- package/src/frame-action.html +67 -67
- package/src/frame-action.js +38 -38
- package/src/implicit-wait-config.html +85 -85
- package/src/implicit-wait-config.js +41 -41
- package/src/new-session.html +96 -96
- package/src/new-session.js +108 -107
- package/src/wdio-common.js +162 -155
- package/src/window-action.html +91 -91
- package/src/window-action.js +43 -43
package/src/new-session.js
CHANGED
|
@@ -1,107 +1,108 @@
|
|
|
1
|
-
const common = require('./wdio-common')
|
|
2
|
-
|
|
3
|
-
module.exports = function(RED) {
|
|
4
|
-
function newSession(config) {
|
|
5
|
-
RED.nodes.createNode(this, config)
|
|
6
|
-
const node = this
|
|
7
|
-
|
|
8
|
-
common.clearStatus(node)
|
|
9
|
-
|
|
10
|
-
node.on('input', async (msg) => {
|
|
11
|
-
try {
|
|
12
|
-
const webdriverConfig = Object.assign(
|
|
13
|
-
{ logLevel: config.logLevel },
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
config.
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
await common.
|
|
24
|
-
common.
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
common.
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
let
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
common.
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
}
|
|
1
|
+
const common = require('./wdio-common')
|
|
2
|
+
|
|
3
|
+
module.exports = function(RED) {
|
|
4
|
+
function newSession(config) {
|
|
5
|
+
RED.nodes.createNode(this, config)
|
|
6
|
+
const node = this
|
|
7
|
+
|
|
8
|
+
common.clearStatus(node)
|
|
9
|
+
|
|
10
|
+
node.on('input', async (msg) => {
|
|
11
|
+
try {
|
|
12
|
+
const webdriverConfig = Object.assign(
|
|
13
|
+
{ logLevel: config.logLevel },
|
|
14
|
+
{ baseUrl: config.webdriverUri || msg.webdriverUri },
|
|
15
|
+
//parseUri(config.webdriverUri || msg.webdriverUri, node),
|
|
16
|
+
getCapabilities(
|
|
17
|
+
config.webdriverProvider,
|
|
18
|
+
config.webdriverBrowser,
|
|
19
|
+
msg
|
|
20
|
+
)
|
|
21
|
+
)
|
|
22
|
+
node.log = `Open new browser.`
|
|
23
|
+
let b = await common.newSession(webdriverConfig, node, node.context())
|
|
24
|
+
await common.log(node)
|
|
25
|
+
common.connectedStatus(node)
|
|
26
|
+
msg.payload = b.sessionId
|
|
27
|
+
node.send(msg)
|
|
28
|
+
} catch (e) {
|
|
29
|
+
await common.log(node)
|
|
30
|
+
common.handleError(e, node, msg)
|
|
31
|
+
}
|
|
32
|
+
})
|
|
33
|
+
|
|
34
|
+
node.on('close', async (done) => {
|
|
35
|
+
try {
|
|
36
|
+
if (config.killSession) {
|
|
37
|
+
let b = await common.deleteSession(node.context())
|
|
38
|
+
let sessionId = ''
|
|
39
|
+
if (b && b.sessionId) sessionId = b.sessionId
|
|
40
|
+
common.disconnectedStatus(node)
|
|
41
|
+
node.log('Disconnected webdriver session ' + sessionId)
|
|
42
|
+
}
|
|
43
|
+
} catch (e) {
|
|
44
|
+
await common.log(node)
|
|
45
|
+
common.handleError(e, node, msg)
|
|
46
|
+
}
|
|
47
|
+
done()
|
|
48
|
+
})
|
|
49
|
+
}
|
|
50
|
+
RED.nodes.registerType('new-session', newSession)
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const parseUri = (uri, node) => {
|
|
54
|
+
let uriComponents
|
|
55
|
+
try {
|
|
56
|
+
if (uri[uri.length - 1] !== '/') uri += '/'
|
|
57
|
+
let parsed = uri.match(/(\w+):\/\/(.+):(\d+)(\/.*)/)
|
|
58
|
+
uriComponents = {
|
|
59
|
+
protocol: parsed[1],
|
|
60
|
+
hostname: parsed[2],
|
|
61
|
+
port: parseInt(parsed[3]),
|
|
62
|
+
path: parsed[4]
|
|
63
|
+
}
|
|
64
|
+
} catch (e) {
|
|
65
|
+
common.handleError(
|
|
66
|
+
new Error(
|
|
67
|
+
'Invalid URI, expected format "<protocol>://<host>:<port>/<path>'
|
|
68
|
+
),
|
|
69
|
+
node
|
|
70
|
+
)
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
return uriComponents
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
const getCapabilities = (vendor, browser, msg) => {
|
|
77
|
+
let capabilities
|
|
78
|
+
|
|
79
|
+
if(browser == 'custom'){
|
|
80
|
+
capabilities = msg.capabilities
|
|
81
|
+
}
|
|
82
|
+
else if (vendor === 'browserless.io') {
|
|
83
|
+
capabilities = {
|
|
84
|
+
browserName: browser,
|
|
85
|
+
'goog:chromeOptions': {
|
|
86
|
+
args: ['--headless', '--no-sandbox']
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
} else if (vendor === 'local' && browser === 'chromium') {
|
|
90
|
+
capabilities = {
|
|
91
|
+
browserName: 'chrome',
|
|
92
|
+
'goog:chromeOptions': {
|
|
93
|
+
args: ['--headless', '--no-sandbox'],
|
|
94
|
+
w3c: false
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
} else if (vendor === 'local') {
|
|
98
|
+
capabilities = {
|
|
99
|
+
browserName: browser,
|
|
100
|
+
//platformName: 'Linux',
|
|
101
|
+
'goog:chromeOptions': {
|
|
102
|
+
w3c: false
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
return { capabilities }
|
|
108
|
+
}
|
package/src/wdio-common.js
CHANGED
|
@@ -1,155 +1,162 @@
|
|
|
1
|
-
const wdio = require('webdriverio')
|
|
2
|
-
let newSessionNode
|
|
3
|
-
|
|
4
|
-
module.exports.getBrowser = (context) => {
|
|
5
|
-
let browser = context.flow.get('wdio_browser')
|
|
6
|
-
if (!browser || !browser.sessionId)
|
|
7
|
-
throw new Error('No session defined - call newSession first')
|
|
8
|
-
|
|
9
|
-
return browser
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
/*
|
|
13
|
-
config = {
|
|
14
|
-
logLevel: 'error',
|
|
15
|
-
protocol: 'https',
|
|
16
|
-
hostname: '<key>@chrome.browserless.io',
|
|
17
|
-
port: 443,
|
|
18
|
-
path: '/webdriver',
|
|
19
|
-
capabilities: {
|
|
20
|
-
browserName: 'chrome',
|
|
21
|
-
chromeOptions: {
|
|
22
|
-
args: ['--headless', '--no-sandbox']
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
*/
|
|
27
|
-
module.exports.newSession = async (config, node, context) => {
|
|
28
|
-
let browser
|
|
29
|
-
try {
|
|
30
|
-
browser = await wdio.remote(config)
|
|
31
|
-
context.flow.set('wdio_browser', browser)
|
|
32
|
-
newSessionNode = node
|
|
33
|
-
} catch (e) {
|
|
34
|
-
throw e
|
|
35
|
-
}
|
|
36
|
-
return browser
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
module.exports.deleteSession = async (context) => {
|
|
40
|
-
let b
|
|
41
|
-
let browser = context.flow.get('wdio_browser')
|
|
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)
|
|
48
|
-
} catch (e) {}
|
|
49
|
-
return b
|
|
50
|
-
}
|
|
51
|
-
|
|
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
|
|
69
|
-
}
|
|
70
|
-
return elementId
|
|
71
|
-
}
|
|
72
|
-
|
|
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
|
-
}
|
|
106
|
-
|
|
107
|
-
module.exports.handleError = (e, node, msg) => {
|
|
108
|
-
console.log(e)
|
|
109
|
-
module.exports.errorStatus(node)
|
|
110
|
-
node.error(e, msg)
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
module.exports.clearStatus = (node) => {
|
|
114
|
-
node.status({})
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
module.exports.connectedStatus = (node) => {
|
|
118
|
-
node.status({
|
|
119
|
-
fill: 'green',
|
|
120
|
-
shape: 'dot',
|
|
121
|
-
text: 'connected'
|
|
122
|
-
})
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
module.exports.disconnectedStatus = (node) => {
|
|
126
|
-
node.status({
|
|
127
|
-
fill: 'green',
|
|
128
|
-
shape: 'ring',
|
|
129
|
-
text: 'disconnected'
|
|
130
|
-
})
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
module.exports.successStatus = (node) => {
|
|
134
|
-
node.status({
|
|
135
|
-
fill: 'green',
|
|
136
|
-
shape: 'ring',
|
|
137
|
-
text: 'done'
|
|
138
|
-
})
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
module.exports.errorStatus = (node) => {
|
|
142
|
-
node.status({
|
|
143
|
-
fill: 'red',
|
|
144
|
-
shape: 'ring',
|
|
145
|
-
text: 'error'
|
|
146
|
-
})
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
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}\n${stepCount}. Node: ${node.name} - ${node.log}`)
|
|
154
|
-
await context.global.set('stepCount', stepCount)
|
|
155
|
-
}
|
|
1
|
+
const wdio = require('webdriverio')
|
|
2
|
+
let newSessionNode
|
|
3
|
+
|
|
4
|
+
module.exports.getBrowser = (context) => {
|
|
5
|
+
let browser = context.flow.get('wdio_browser')
|
|
6
|
+
if (!browser || !browser.sessionId)
|
|
7
|
+
throw new Error('No session defined - call newSession first')
|
|
8
|
+
|
|
9
|
+
return browser
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/*
|
|
13
|
+
config = {
|
|
14
|
+
logLevel: 'error',
|
|
15
|
+
protocol: 'https',
|
|
16
|
+
hostname: '<key>@chrome.browserless.io',
|
|
17
|
+
port: 443,
|
|
18
|
+
path: '/webdriver',
|
|
19
|
+
capabilities: {
|
|
20
|
+
browserName: 'chrome',
|
|
21
|
+
chromeOptions: {
|
|
22
|
+
args: ['--headless', '--no-sandbox']
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
*/
|
|
27
|
+
module.exports.newSession = async (config, node, context) => {
|
|
28
|
+
let browser
|
|
29
|
+
try {
|
|
30
|
+
browser = await wdio.remote(config)
|
|
31
|
+
context.flow.set('wdio_browser', browser)
|
|
32
|
+
newSessionNode = node
|
|
33
|
+
} catch (e) {
|
|
34
|
+
throw e
|
|
35
|
+
}
|
|
36
|
+
return browser
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
module.exports.deleteSession = async (context) => {
|
|
40
|
+
let b
|
|
41
|
+
let browser = context.flow.get('wdio_browser')
|
|
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)
|
|
48
|
+
} catch (e) {}
|
|
49
|
+
return b
|
|
50
|
+
}
|
|
51
|
+
|
|
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
|
|
69
|
+
}
|
|
70
|
+
return elementId
|
|
71
|
+
}
|
|
72
|
+
|
|
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
|
+
}
|
|
106
|
+
|
|
107
|
+
module.exports.handleError = (e, node, msg) => {
|
|
108
|
+
console.log(e)
|
|
109
|
+
module.exports.errorStatus(node)
|
|
110
|
+
node.error(e, msg)
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
module.exports.clearStatus = (node) => {
|
|
114
|
+
node.status({})
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
module.exports.connectedStatus = (node) => {
|
|
118
|
+
node.status({
|
|
119
|
+
fill: 'green',
|
|
120
|
+
shape: 'dot',
|
|
121
|
+
text: 'connected'
|
|
122
|
+
})
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
module.exports.disconnectedStatus = (node) => {
|
|
126
|
+
node.status({
|
|
127
|
+
fill: 'green',
|
|
128
|
+
shape: 'ring',
|
|
129
|
+
text: 'disconnected'
|
|
130
|
+
})
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
module.exports.successStatus = (node) => {
|
|
134
|
+
node.status({
|
|
135
|
+
fill: 'green',
|
|
136
|
+
shape: 'ring',
|
|
137
|
+
text: 'done'
|
|
138
|
+
})
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
module.exports.errorStatus = (node) => {
|
|
142
|
+
node.status({
|
|
143
|
+
fill: 'red',
|
|
144
|
+
shape: 'ring',
|
|
145
|
+
text: 'error'
|
|
146
|
+
})
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
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}\n${stepCount}. Node: ${node.name} - ${node.log}`)
|
|
154
|
+
await context.global.set('stepCount', stepCount)
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
module.exports.document = async (node) => {
|
|
158
|
+
let context = node.context()
|
|
159
|
+
let name = node.name
|
|
160
|
+
let document = await context.global.get('document') || ''
|
|
161
|
+
await context.global.set('document', `${document}\n********************\n${name}\n********************`)
|
|
162
|
+
}
|