Update CI/test set up (#9499)
* Disable concurrency for tests * Add browser instance sharing * Bump concurrency and install chromedriver smoother * Fix config typo * Fix local test * Limit azure concurrency again * Add delay for empty-object-test * Make sure to use open port for chromedriver * Move browser closing to jest-environment * Re-enable concurrency for Azure * bump * Disable concurrency for Azure again * Re-enable concurrency for Azure * bump
This commit is contained in:
parent
77c4b4de12
commit
b058427b76
9 changed files with 78 additions and 161 deletions
|
@ -38,9 +38,11 @@ commands:
|
|||
command: yarn install --frozen-lockfile --check-files
|
||||
- run:
|
||||
name: Install correct Chrome Driver version
|
||||
command: yarn add chromedriver@76 -W && git checkout yarn.lock package.json
|
||||
command: node node_modules/chromedriver/install.js
|
||||
environment:
|
||||
CHROMEDRIVER_VERSION: '76.0.3809.68'
|
||||
- run: google-chrome --version
|
||||
- run: chromedriver --version
|
||||
- run: yarn chromedriver --version
|
||||
yarn_lint:
|
||||
steps:
|
||||
- run:
|
||||
|
|
|
@ -39,9 +39,9 @@ steps:
|
|||
displayName: 'Install dependencies'
|
||||
|
||||
- script: |
|
||||
yarn add chromedriver@76 -W
|
||||
node node_modules/chromedriver/install.js
|
||||
displayName: 'Install correct Chrome Driver version'
|
||||
|
||||
- script: |
|
||||
node run-tests.js -c 2 -g $(group)
|
||||
node run-tests.js -g $(group)
|
||||
displayName: 'Run tests'
|
||||
|
|
|
@ -8,8 +8,8 @@
|
|||
"lerna": "lerna",
|
||||
"dev": "lerna run build --stream --parallel",
|
||||
"dev2": "while true; do yarn --check-files && yarn dev; done",
|
||||
"testonly": "jest",
|
||||
"testall": "yarn run testonly -- --ci --reporters=default --reporters=jest-junit --forceExit --runInBand",
|
||||
"testonly": "jest --runInBand",
|
||||
"testall": "yarn run testonly -- --ci --reporters=default --reporters=jest-junit --forceExit",
|
||||
"pretest": "yarn run lint",
|
||||
"git-reset": "git reset --hard HEAD",
|
||||
"git-clean": "git clean -d -x -e node_modules -e packages -f",
|
||||
|
|
|
@ -49,6 +49,7 @@ describe('Empty Project', () => {
|
|||
|
||||
it('should show empty object warning during client transition', async () => {
|
||||
const browser = await webdriver(appPort, '/static')
|
||||
await waitFor(1000)
|
||||
await browser.eval(`(function() {
|
||||
window.gotWarn = false
|
||||
const origWarn = console.warn
|
||||
|
@ -60,7 +61,7 @@ describe('Empty Project', () => {
|
|||
}
|
||||
window.next.router.replace('/another')
|
||||
})()`)
|
||||
await waitFor(300)
|
||||
await waitFor(1000)
|
||||
const gotWarn = await browser.eval(`window.gotWarn`)
|
||||
expect(gotWarn).toBe(true)
|
||||
await browser.close()
|
||||
|
|
|
@ -36,7 +36,9 @@ describe('future.excludeDefaultMomentLocales', () => {
|
|||
const browser = await webdriver(appPort, '/')
|
||||
await waitFor(5000)
|
||||
expect(await browser.elementByCss('h1').text()).toMatch(/current time/i)
|
||||
expect(await browser.eval('moment.locales()')).toStrictEqual(['en'])
|
||||
const locales = await browser.eval('moment.locales()')
|
||||
expect(locales).toEqual(['en'])
|
||||
expect(locales.length).toBe(1)
|
||||
await browser.close()
|
||||
})
|
||||
})
|
||||
|
|
|
@ -4,6 +4,8 @@ const os = require('os')
|
|||
const http = require('http')
|
||||
const fetch = require('node-fetch')
|
||||
const getPort = require('get-port')
|
||||
const waitPort = require('wait-port')
|
||||
const chromedriver = require('chromedriver')
|
||||
const NodeEnvironment = require('jest-environment-node')
|
||||
const {
|
||||
BROWSER_NAME,
|
||||
|
@ -16,8 +18,14 @@ let browser
|
|||
let initialWindow
|
||||
let browserOptions = {
|
||||
browserName: BROWSER_NAME || 'chrome',
|
||||
...(process.env.HEADLESS === 'true'
|
||||
? {
|
||||
chromeOptions: { args: ['--headless'] },
|
||||
}
|
||||
: {}),
|
||||
}
|
||||
let deviceIP = 'localhost'
|
||||
let driverPort = '9515'
|
||||
|
||||
const isIE = BROWSER_NAME === 'ie'
|
||||
const isSafari = BROWSER_NAME === 'safari'
|
||||
|
@ -75,38 +83,52 @@ const newTabPg = `
|
|||
class CustomEnvironment extends NodeEnvironment {
|
||||
async createBrowser() {
|
||||
// always create new browser session if not BrowserStack
|
||||
if (!browser && isBrowserStack) {
|
||||
if (!browser) {
|
||||
if (!isBrowserStack) {
|
||||
driverPort = await getPort()
|
||||
chromedriver.start([`--port=${driverPort}`])
|
||||
|
||||
// https://github.com/giggio/node-chromedriver/issues/117
|
||||
await waitPort({
|
||||
port: driverPort,
|
||||
timeout: 1000 * 60 * 2, // 2 Minutes
|
||||
})
|
||||
}
|
||||
|
||||
browser = wd.promiseChainRemote(
|
||||
'hub-cloud.browserstack.com', // seleniumHost
|
||||
80, // seleniumPort
|
||||
BROWSERSTACK_USERNAME,
|
||||
BROWSERSTACK_ACCESS_KEY
|
||||
...(isBrowserStack
|
||||
? [
|
||||
'hub-cloud.browserstack.com', // seleniumHost
|
||||
80, // seleniumPort
|
||||
BROWSERSTACK_USERNAME,
|
||||
BROWSERSTACK_ACCESS_KEY,
|
||||
]
|
||||
: [`http://localhost:${driverPort}`])
|
||||
)
|
||||
|
||||
// Setup the browser instance
|
||||
await browser.init(browserOptions)
|
||||
initialWindow = await browser.windowHandle()
|
||||
global.bsBrowser = browser
|
||||
}
|
||||
|
||||
if (isBrowserStack) {
|
||||
// disable browser.close and we handle it manually
|
||||
browser.origClose = browser.close
|
||||
browser.close = () => {}
|
||||
// Since ie11 doesn't like dataURIs we have to spin up a
|
||||
// server to handle the new tab page
|
||||
this.server = http.createServer((req, res) => {
|
||||
res.statusCode = 200
|
||||
res.end(newTabPg)
|
||||
})
|
||||
this.newTabPort = await getPort()
|
||||
await new Promise((resolve, reject) => {
|
||||
this.server.listen(this.newTabPort, err => {
|
||||
if (err) return reject(err)
|
||||
resolve()
|
||||
})
|
||||
// disable browser.close and we handle it manually
|
||||
browser.origClose = browser.close
|
||||
browser.close = () => {}
|
||||
// Since ie11 doesn't like dataURIs we have to spin up a
|
||||
// server to handle the new tab page
|
||||
this.server = http.createServer((req, res) => {
|
||||
res.statusCode = 200
|
||||
res.end(newTabPg)
|
||||
})
|
||||
this.newTabPort = await getPort()
|
||||
await new Promise((resolve, reject) => {
|
||||
this.server.listen(this.newTabPort, err => {
|
||||
if (err) return reject(err)
|
||||
resolve()
|
||||
})
|
||||
})
|
||||
|
||||
if (isBrowserStack) {
|
||||
const networkIntfs = os.networkInterfaces()
|
||||
// find deviceIP to use with BrowserStack
|
||||
for (const intf of Object.keys(networkIntfs)) {
|
||||
|
@ -124,13 +146,14 @@ class CustomEnvironment extends NodeEnvironment {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.global.browserName = browserOptions.browserName
|
||||
this.global.isBrowserStack = isBrowserStack
|
||||
|
||||
// Mock current browser set up
|
||||
this.global.bsWd = async (appPort, pathname) => {
|
||||
this.global.sharedWD = async (appPort, pathname) => {
|
||||
const url = `http://${deviceIP}:${appPort}${pathname}`
|
||||
console.log(`\n> Loading browser with ${url}\n`)
|
||||
if (isBrowserStack) await this.freshWindow()
|
||||
await this.freshWindow()
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
let timedOut = false
|
||||
|
@ -199,6 +222,19 @@ class CustomEnvironment extends NodeEnvironment {
|
|||
async teardown() {
|
||||
await super.teardown()
|
||||
if (this.server) this.server.close()
|
||||
if (browser) {
|
||||
// Close all remaining browser windows
|
||||
try {
|
||||
const windows = await browser.windowHandles()
|
||||
for (const window of windows) {
|
||||
if (!window) continue
|
||||
await browser.window(window)
|
||||
await browser.origClose()
|
||||
await browser.quit()
|
||||
}
|
||||
} catch (_) {}
|
||||
}
|
||||
chromedriver.stop()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
let globalSetup
|
||||
let globalSetup = () => {}
|
||||
|
||||
if (process.env.BROWSERSTACK) {
|
||||
const { Local } = require('browserstack-local')
|
||||
|
@ -18,19 +18,6 @@ if (process.env.BROWSERSTACK) {
|
|||
})
|
||||
})
|
||||
}
|
||||
} else {
|
||||
const chromedriver = require('chromedriver')
|
||||
const waitPort = require('wait-port')
|
||||
|
||||
globalSetup = async function globalSetup() {
|
||||
chromedriver.start()
|
||||
|
||||
// https://github.com/giggio/node-chromedriver/issues/117
|
||||
await waitPort({
|
||||
port: 9515,
|
||||
timeout: 1000 * 60 * 2, // 2 Minutes
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = () => globalSetup()
|
||||
module.exports = globalSetup
|
||||
|
|
|
@ -1,24 +1,9 @@
|
|||
let globalTeardown = () => {}
|
||||
const browser = global.bsBrowser
|
||||
|
||||
if (process.env.BROWSERSTACK) {
|
||||
globalTeardown = () => global.browserStackLocal.killAllProcesses(() => {})
|
||||
}
|
||||
|
||||
module.exports = async () => {
|
||||
if (browser) {
|
||||
// Close all remaining browser windows
|
||||
try {
|
||||
const windows = await browser.windowHandles()
|
||||
for (const window of windows) {
|
||||
if (!window) continue
|
||||
await browser.window(window)
|
||||
await browser.origClose()
|
||||
await browser.quit()
|
||||
await globalTeardown()
|
||||
}
|
||||
} catch (_) {}
|
||||
} else {
|
||||
await globalTeardown()
|
||||
}
|
||||
await globalTeardown()
|
||||
}
|
||||
|
|
|
@ -1,97 +1 @@
|
|||
import wd from 'wd'
|
||||
import getPort from 'get-port'
|
||||
import waitPort from 'wait-port'
|
||||
|
||||
const doHeadless = process.env.HEADLESS !== 'false'
|
||||
let driverPort = 9515
|
||||
|
||||
let webdriver = async function(appPort, pathname) {
|
||||
if (typeof appPort === 'undefined') {
|
||||
throw new Error('appPort is undefined')
|
||||
}
|
||||
|
||||
const url = `http://localhost:${appPort}${pathname}`
|
||||
console.log(`> Start loading browser with url: ${url}`)
|
||||
|
||||
// Sometimes browser won't initialize due to some random issues.
|
||||
// So, we need to timeout the initialization and retry again.
|
||||
for (let lc = 0; lc < 5; lc++) {
|
||||
try {
|
||||
const browser = await getBrowser(url, 5000)
|
||||
console.log(`> Complete loading browser with url: ${url}`)
|
||||
return browser
|
||||
} catch (ex) {
|
||||
console.warn(`> Error when loading browser with url: ${url}`)
|
||||
|
||||
// Try restarting chromedriver max twice
|
||||
if (lc < 2) {
|
||||
const chromedriver = require('chromedriver')
|
||||
console.log('Trying to restart chromedriver with random port')
|
||||
driverPort = await getPort()
|
||||
chromedriver.stop()
|
||||
chromedriver.start([`--port=${driverPort}`])
|
||||
// https://github.com/giggio/node-chromedriver/issues/117
|
||||
await waitPort({
|
||||
port: driverPort,
|
||||
timeout: 1000 * 30, // 30 seconds
|
||||
})
|
||||
continue
|
||||
}
|
||||
|
||||
if (ex.message === 'TIMEOUT') continue
|
||||
throw ex
|
||||
}
|
||||
}
|
||||
|
||||
console.error(`> Tried 5 times. Cannot load the browser for url: ${url}`)
|
||||
throw new Error(`Couldn't start the browser for url: ${url}`)
|
||||
}
|
||||
|
||||
function getBrowser(url, timeout) {
|
||||
const browser = wd.promiseChainRemote(`http://localhost:${driverPort}/`)
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
let timeouted = false
|
||||
const timeoutHandler = setTimeout(() => {
|
||||
timeouted = true
|
||||
const error = new Error('TIMEOUT')
|
||||
reject(error)
|
||||
}, timeout)
|
||||
|
||||
browser
|
||||
.init({
|
||||
browserName: 'chrome',
|
||||
...(doHeadless
|
||||
? {
|
||||
chromeOptions: { args: ['--headless'] },
|
||||
}
|
||||
: {}),
|
||||
})
|
||||
.get(url, err => {
|
||||
if (timeouted) {
|
||||
try {
|
||||
browser.close(() => {
|
||||
// Ignore errors
|
||||
})
|
||||
} catch (err) {
|
||||
// Ignore
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
clearTimeout(timeoutHandler)
|
||||
|
||||
if (err) {
|
||||
reject(err)
|
||||
return
|
||||
}
|
||||
|
||||
resolve(browser)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
if (global.isBrowserStack) {
|
||||
webdriver = (...args) => global.bsWd(...args)
|
||||
}
|
||||
export default webdriver
|
||||
export default global.sharedWD
|
||||
|
|
Loading…
Reference in a new issue