1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
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
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
|
const fs = require('fs')
const mkdirp = require('mkdirp')
const pify = require('pify')
const assert = require('assert')
const { delay } = require('../func')
const { until } = require('selenium-webdriver')
module.exports = {
assertElementNotPresent,
checkBrowserForConsoleErrors,
closeAllWindowHandlesExcept,
findElement,
findElements,
loadExtension,
openNewPage,
switchToWindowWithTitle,
verboseReportOnFailure,
waitUntilXWindowHandles,
}
async function loadExtension (driver, extensionId) {
switch (process.env.SELENIUM_BROWSER) {
case 'chrome': {
await driver.get(`chrome-extension://${extensionId}/home.html`)
break
}
case 'firefox': {
await driver.get(`moz-extension://${extensionId}/home.html`)
break
}
}
}
async function checkBrowserForConsoleErrors (driver) {
const ignoredLogTypes = ['WARNING']
const ignoredErrorMessages = [
// React throws error warnings on "dataset", but still sets the data-* properties correctly
'Warning: Unknown prop `dataset` on ',
// Third-party Favicon 404s show up as errors
'favicon.ico - Failed to load resource: the server responded with a status of 404 (Not Found)',
// React Development build - known issue blocked by test build sys
'Warning: It looks like you\'re using a minified copy of the development build of React.',
// Redux Development build - known issue blocked by test build sys
'This means that you are running a slower development build of Redux.',
]
const browserLogs = await driver.manage().logs().get('browser')
const errorEntries = browserLogs.filter(entry => !ignoredLogTypes.includes(entry.level.toString()))
const errorObjects = errorEntries.map(entry => entry.toJSON())
return errorObjects.filter(entry => !ignoredErrorMessages.some(message => entry.message.includes(message)))
}
async function verboseReportOnFailure (driver, test) {
let artifactDir
if (process.env.SELENIUM_BROWSER === 'chrome') {
artifactDir = `./test-artifacts/chrome/${test.title}`
} else if (process.env.SELENIUM_BROWSER === 'firefox') {
artifactDir = `./test-artifacts/firefox/${test.title}`
}
const filepathBase = `${artifactDir}/test-failure`
await pify(mkdirp)(artifactDir)
const screenshot = await driver.takeScreenshot()
await pify(fs.writeFile)(`${filepathBase}-screenshot.png`, screenshot, { encoding: 'base64' })
const htmlSource = await driver.getPageSource()
await pify(fs.writeFile)(`${filepathBase}-dom.html`, htmlSource)
}
async function findElement (driver, by, timeout = 10000) {
return driver.wait(until.elementLocated(by), timeout)
}
async function findElements (driver, by, timeout = 10000) {
return driver.wait(until.elementsLocated(by), timeout)
}
async function openNewPage (driver, url) {
await driver.executeScript('window.open()')
await delay(1000)
const handles = await driver.getAllWindowHandles()
const lastHandle = handles[handles.length - 1]
await driver.switchTo().window(lastHandle)
await driver.get(url)
await delay(1000)
}
async function waitUntilXWindowHandles (driver, x) {
const windowHandles = await driver.getAllWindowHandles()
if (windowHandles.length === x) return
await delay(1000)
return await waitUntilXWindowHandles(driver, x)
}
async function switchToWindowWithTitle (driver, title, windowHandles) {
if (!windowHandles) {
windowHandles = await driver.getAllWindowHandles()
} else if (windowHandles.length === 0) {
throw new Error('No window with title: ' + title)
}
const firstHandle = windowHandles[0]
await driver.switchTo().window(firstHandle)
const handleTitle = await driver.getTitle()
if (handleTitle === title) {
return firstHandle
} else {
return await switchToWindowWithTitle(driver, title, windowHandles.slice(1))
}
}
async function closeAllWindowHandlesExcept (driver, exceptions, windowHandles) {
exceptions = typeof exceptions === 'string' ? [ exceptions ] : exceptions
windowHandles = windowHandles || await driver.getAllWindowHandles()
const lastWindowHandle = windowHandles.pop()
if (!exceptions.includes(lastWindowHandle)) {
await driver.switchTo().window(lastWindowHandle)
await delay(1000)
await driver.close()
await delay(1000)
}
return windowHandles.length && await closeAllWindowHandlesExcept(driver, exceptions, windowHandles)
}
async function assertElementNotPresent (webdriver, driver, by) {
try {
const dataTab = await findElement(driver, by, 4000)
if (dataTab) {
assert(false, 'Data tab should not be present')
}
} catch (err) {
assert(err instanceof webdriver.error.NoSuchElementError)
}
}
|