Skip to content

Commit 655202f

Browse files
committed
feat: e2e nightwatch
1 parent 0688e88 commit 655202f

File tree

12 files changed

+570
-28
lines changed

12 files changed

+570
-28
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
module.exports = api => {
2+
api.render('./template', {
3+
hasTS: api.hasPlugin('typescript')
4+
})
5+
6+
api.extendPackage({
7+
scripts: {
8+
e2e: 'vue-cli-service e2e'
9+
}
10+
})
11+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// A custom Nightwatch assertion.
2+
// The assertion name is the filename.
3+
// Example usage:
4+
//
5+
// browser.assert.elementCount(selector, count)
6+
//
7+
// For more information on custom assertions see:
8+
// http://nightwatchjs.org/guide#writing-custom-assertions
9+
10+
exports.assertion = function (selector, count) {
11+
this.message = `Testing if element <${selector}> has count: ${count}`
12+
this.expected = count
13+
this.pass = val => val === count
14+
this.value = res => res.value
15+
this.command = cb => this.api.execute(function (selector) {
16+
return document.querySelectorAll(selector).length
17+
}, [selector], cb)
18+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// For authoring Nightwatch tests, see
2+
// http://nightwatchjs.org/guide#usage
3+
4+
module.exports = {
5+
'default e2e tests': browser => {
6+
browser
7+
.url(process.env.VUE_DEV_SERVER_URL)
8+
.waitForElementVisible('#app', 5000)
9+
.assert.elementPresent('.hello')
10+
.assert.containsText('h1', 'Welcome to Your Vue.js <%- hasTS ? '+ TypeScript ' : '' %>App')
11+
.assert.elementCount('img', 1)
12+
.end()
13+
}
14+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
module.exports = (api, options) => {
2+
api.registerCommand('e2e', {
3+
description: 'run e2e tests with nightwatch',
4+
options: {
5+
'--url': 'run e2e tests against given url instead of auto-starting dev server',
6+
'-e, --env': 'specify comma-delimited browser envs to run in (default: chrome)',
7+
'-t, --test': 'sepcify a test to run by name',
8+
'-f, --filter': 'glob to filter tests by filename'
9+
},
10+
usage: 'vue-cli-service e2e [options]'
11+
}, (args, rawArgs) => {
12+
if (args.url) {
13+
const i = rawArgs.findIndex(arg => /^--url/.test(arg))
14+
rawArgs = rawArgs.splice(i, 2)
15+
}
16+
17+
const serverPromise = args.url
18+
? Promise.resolve({ url: args.url })
19+
: api.service.run('serve', { mode: 'production' })
20+
21+
return serverPromise.then(({ server, url }) => {
22+
// expose dev server url to tests
23+
process.env.VUE_DEV_SERVER_URL = url
24+
// expose user options to config file
25+
process.env.VUE_NIGHTWATCH_USER_OPTIONS = JSON.stringify(options.nightwatch || {})
26+
27+
rawArgs.push('--config', require.resolve('./nightwatch.config.js'))
28+
if (rawArgs.indexOf('--env') === -1) {
29+
rawArgs.push('--env', 'chrome')
30+
}
31+
32+
const execa = require('execa')
33+
const nightWatchBinPath = require.resolve('nightwatch/bin/nightwatch')
34+
const runner = execa(nightWatchBinPath, rawArgs, { stdio: 'inherit' })
35+
if (server) {
36+
runner.on('exit', () => server.close())
37+
runner.on('error', () => server.close())
38+
}
39+
return runner
40+
})
41+
})
42+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
// http://nightwatchjs.org/gettingstarted#settings-file
2+
3+
const deepmerge = require('deepmerge')
4+
const userOptions = JSON.parse(process.env.VUE_NIGHTWATCH_USER_OPTIONS || '{}')
5+
6+
module.exports = deepmerge({
7+
src_folders: ['test/e2e/specs'],
8+
output_folder: 'test/e2e/reports',
9+
custom_assertions_path: ['test/e2e/custom-assertions'],
10+
11+
selenium: {
12+
start_process: true,
13+
server_path: require('selenium-server').path,
14+
host: '127.0.0.1',
15+
port: 4444,
16+
cli_args: {
17+
'webdriver.chrome.driver': require('chromedriver').path
18+
}
19+
},
20+
21+
test_settings: {
22+
default: {
23+
selenium_port: 4444,
24+
selenium_host: 'localhost',
25+
silent: true
26+
},
27+
28+
chrome: {
29+
desiredCapabilities: {
30+
browserName: 'chrome',
31+
javascriptEnabled: true,
32+
acceptSslCerts: true
33+
}
34+
}
35+
}
36+
}, userOptions)

packages/@vue/cli-plugin-e2e-nightwatch/package.json

+7
Original file line numberDiff line numberDiff line change
@@ -20,5 +20,12 @@
2020
"homepage": "https://github.com/vuejs/vue-cli/packages/@vue/cli-plugin-e2e-nightwatch#readme",
2121
"publishConfig": {
2222
"access": "public"
23+
},
24+
"dependencies": {
25+
"chromedriver": "^2.34.1",
26+
"deepmerge": "^2.0.1",
27+
"execa": "^0.9.0",
28+
"nightwatch": "^0.9.19",
29+
"selenium-server": "^3.8.1"
2330
}
2431
}

packages/@vue/cli-plugin-typescript/generator/index.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -109,10 +109,11 @@ module.exports = (api, {
109109
// delete all js files that have a ts file of the same name
110110
// and simply rename other js files to ts
111111
const jsRE = /\.js$/
112+
const e2eRE = /^test\/e2e\//
112113
const convertLintFlags = require('../lib/convertLintFlags')
113114
api.postProcessFiles(files => {
114115
for (const file in files) {
115-
if (jsRE.test(file)) {
116+
if (jsRE.test(file) && !e2eRE.test(file)) {
116117
const tsFile = file.replace(jsRE, '.ts')
117118
if (!files[tsFile]) {
118119
files[tsFile] = convertLintFlags(files[file])

packages/@vue/cli-service/generator/template/.gitignore

+1-6
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,7 @@
11
.DS_Store
22
node_modules
33
/dist
4-
<%_ if (options.coverage) { _%>
5-
6-
# test coverage files
7-
/test/unit/coverage/
8-
<%_ } _%>
9-
<%_ if (options.e2e === 'nightwatch') { _%>
4+
<%_ if (rootOptions.plugins && rootOptions.plugins['@vue/cli-plugin-e2e-nightwatch']) { _%>
105

116
# e2e reports & log
127
/test/e2e/reports/

packages/@vue/cli-service/lib/commands/serve.js

+10-6
Original file line numberDiff line numberDiff line change
@@ -47,11 +47,8 @@ module.exports = (api, options) => {
4747
const host = args.host || process.env.HOST || projectDevServerOptions.host || defaults.host
4848
portfinder.basePort = args.port || process.env.PORT || projectDevServerOptions.port || defaults.port
4949

50-
portfinder.getPort((err, port) => {
51-
if (err) {
52-
return error(err)
53-
}
54-
50+
const portPromise = portfinder.getPortPromise()
51+
return portPromise.then(port => new Promise((resolve, reject) => {
5552
const webpackConfig = api.resolveWebpackConfig()
5653

5754
const urls = prepareURLs(
@@ -114,6 +111,13 @@ module.exports = (api, options) => {
114111
if (args.open || projectDevServerOptions.open) {
115112
openBrowser(urls.localUrlForBrowser)
116113
}
114+
115+
// resolve returned Promise
116+
// so other commands can do api.service.run('serve').then(...)
117+
resolve({
118+
server,
119+
url: urls.localUrlForBrowser
120+
})
117121
} else if (process.env.VUE_CLI_TEST) {
118122
// signal for test to check HMR
119123
console.log('App updated')
@@ -182,7 +186,7 @@ module.exports = (api, options) => {
182186
return error(err)
183187
}
184188
})
185-
})
189+
}))
186190
})
187191
}
188192

packages/@vue/cli/lib/Creator.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,7 @@ module.exports = class Creator {
184184
saveOptions(options, true /* replace */)
185185
}
186186

187-
debug('vue:cli-ptions')(options)
187+
debug('vue:cli-options')(options)
188188
return options
189189
}
190190

+32
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,34 @@
11
module.exports = cli => {
2+
cli.injectFeature({
3+
name: 'E2E Testing',
4+
value: 'e2e',
5+
short: 'E2E'
6+
})
7+
8+
cli.injectPrompt({
9+
name: 'e2e',
10+
when: answers => answers.features.includes('e2e'),
11+
type: 'list',
12+
message: 'Pick a E2E testing solution:',
13+
choices: [
14+
{
15+
name: 'Cypress (Chrome only)',
16+
value: 'cypress',
17+
short: 'Cypress'
18+
},
19+
{
20+
name: 'Nightwatch (Selenium-based)',
21+
value: 'nightwatch',
22+
short: 'Nightwatch'
23+
}
24+
]
25+
})
26+
27+
cli.onPromptComplete((answers, options) => {
28+
if (answers.e2e === 'cypress') {
29+
options.plugins['@vue/cli-plugin-e2e-cypress'] = {}
30+
} else if (answers.e2e === 'nightwatch') {
31+
options.plugins['@vue/cli-plugin-e2e-nightwatch'] = {}
32+
}
33+
})
234
}

0 commit comments

Comments
 (0)