mirror of
https://github.com/vuejs/vue-cli.git
synced 2026-09-29 16:57:06 +08:00
feat(e2e-webdriverio): add e2e plugin for WebdriverIO (#5479)
This commit is contained in:
@@ -184,7 +184,8 @@ module.exports = {
|
||||
'/core-plugins/unit-jest.md',
|
||||
'/core-plugins/unit-mocha.md',
|
||||
'/core-plugins/e2e-cypress.md',
|
||||
'/core-plugins/e2e-nightwatch.md'
|
||||
'/core-plugins/e2e-nightwatch.md',
|
||||
'/core-plugins/e2e-webdriverio.md'
|
||||
]
|
||||
}],
|
||||
|
||||
|
||||
@@ -446,3 +446,7 @@ See [@vue/cli-plugin-e2e-cypress](https://github.com/vuejs/vue-cli/tree/dev/pack
|
||||
### Nightwatch
|
||||
|
||||
See [@vue/cli-plugin-e2e-nightwatch](https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-e2e-nightwatch) for more details.
|
||||
|
||||
### WebdriverIO
|
||||
|
||||
See [@vue/cli-plugin-e2e-webdriverio](https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-e2e-webdriverio) for more details.
|
||||
|
||||
@@ -12,3 +12,4 @@ This section contains documentation for core Vue CLI plugins:
|
||||
- [Mocha](unit-mocha.md)
|
||||
- [Cypress](e2e-cypress.md)
|
||||
- [Nightwatch](e2e-nightwatch.md)
|
||||
- [WebdriverIO](e2e-webdriverio.md)
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
# @vue/cli-plugin-e2e-nightwatch
|
||||
|
||||
> e2e-webdriverio plugin for vue-cli
|
||||
|
||||
## Injected Commands
|
||||
|
||||
- **`vue-cli-service test:e2e`**
|
||||
|
||||
Run end-to-end tests with [WebdriverIO](https://webdriver.io/).
|
||||
|
||||
Options:
|
||||
|
||||
```
|
||||
--url run the tests against given url instead of auto-starting dev server
|
||||
--headless use chrome or firefox in headless mode
|
||||
--remote run e2e tests on a cloud provider
|
||||
```
|
||||
|
||||
Additionally, all [WebdriverIO CLI options](https://webdriver.io/docs/clioptions.html) are also supported.
|
||||
E.g.: `--spec`, `--watch` etc.
|
||||
|
||||
|
||||
## Project Structure
|
||||
|
||||
The following structure will be generated when installing this plugin. It includes a spec file a page object definition for the Vue.js app as example.
|
||||
|
||||
```
|
||||
tests/e2e/
|
||||
├── pageobjects/
|
||||
| └── app.page.js
|
||||
├── specs/
|
||||
| ├── app.spec.js
|
||||
└── .eslintrc.js
|
||||
```
|
||||
|
||||
#### `pageobjects`
|
||||
Working with page objects is a popular methodology in end-to-end UI testing. See [working with page objects](https://webdriver.io/docs/pageobjects.html) section for details.
|
||||
|
||||
#### `specs`
|
||||
The main location where tests are located. You can specify specific tests or define suites to run various subsets of these tests. [More info](https://webdriver.io/docs/organizingsuites.html).
|
||||
|
||||
## Installing in an Already Created Project
|
||||
|
||||
``` sh
|
||||
vue add e2e-webdriverio
|
||||
```
|
||||
|
||||
## Running Tests
|
||||
|
||||
By default, all tests inside the `specs` folder will be run using Chrome. If you'd like to run end-to-end tests against Chrome (or Firefox) in headless mode, simply pass the `--headless` argument.
|
||||
|
||||
```sh
|
||||
$ vue-cli-service test:e2e
|
||||
```
|
||||
|
||||
This will run the tests automatically in parallel on Firefox and Chrome.
|
||||
|
||||
**Running a single test**
|
||||
|
||||
To run a single test supply the filename path. E.g.:
|
||||
|
||||
```sh
|
||||
$ vue-cli-service test:e2e --spec tests/e2e/specs/test.js
|
||||
```
|
||||
@@ -0,0 +1,2 @@
|
||||
__tests__
|
||||
__mocks__
|
||||
@@ -0,0 +1,81 @@
|
||||
# @vue/cli-plugin-e2e-webdriverio
|
||||
|
||||
> e2e-webdriverio plugin for vue-cli
|
||||
|
||||
## Injected Commands
|
||||
|
||||
- **`vue-cli-service test:e2e`**
|
||||
|
||||
Run end-to-end tests with [WebdriverIO](https://webdriver.io/).
|
||||
|
||||
Options:
|
||||
|
||||
```
|
||||
--remote Run tests remotely on SauceLabs
|
||||
|
||||
All WebdriverIO CLI options are also supported.
|
||||
|
||||
```
|
||||
|
||||
Additionally, all [WebdriverIO CLI options](https://webdriver.io/docs/clioptions.html) are also supported.
|
||||
E.g.: `--baseUrl`, `--bail` etc.
|
||||
|
||||
|
||||
## Project Structure
|
||||
|
||||
The following structure will be generated when installing this plugin:
|
||||
|
||||
```
|
||||
tests/e2e/
|
||||
├── pageobjects/
|
||||
| └── app.js
|
||||
├── specs/
|
||||
| ├── app.spec.js
|
||||
└── globals.js
|
||||
```
|
||||
|
||||
In addition to that there will be 3 configuration files generated:
|
||||
|
||||
- `wdio.shared.conf.js`: a shared configuration with all options defined for all environments
|
||||
- `wdio.local.conf.js`: a local configuration for local testing
|
||||
- `wdio.sauce.conf.js`: a remote configuration for testing on a cloud provider like [Sauce Labs](https://saucelabs.com/)
|
||||
|
||||
The directories contain:
|
||||
|
||||
#### `pageobjects`
|
||||
Contains an example for an page object. Read more on using [PageObjects](https://webdriver.io/docs/pageobjects.html) with WebdriverIO.
|
||||
|
||||
#### `specs`
|
||||
Your e2e tests.
|
||||
|
||||
## Installing in an Already Created Project
|
||||
|
||||
``` sh
|
||||
vue add e2e-webdriverio
|
||||
```
|
||||
|
||||
For users with older CLI versions you may need to run `vue add @vue/e2e-webdriverio`.
|
||||
|
||||
## Running Tests
|
||||
|
||||
By default, all tests inside the `specs` folder will be run using Chrome. If you'd like to run end-to-end tests against Chrome (or Firefox) in headless mode, simply pass the `--headless` argument. Tests will be automatically run in parallel when executed in the cloud.
|
||||
|
||||
```sh
|
||||
$ vue-cli-service test:e2e
|
||||
```
|
||||
|
||||
**Running a single test**
|
||||
|
||||
To run a single test supply the filename path. E.g.:
|
||||
|
||||
```sh
|
||||
$ vue-cli-service test:e2e --spec tests/e2e/specs/test.js
|
||||
```
|
||||
|
||||
**Skip Dev server auto-start**
|
||||
|
||||
If the development server is already running and you want to skip starting it automatically, pass the `--url` argument:
|
||||
|
||||
```sh
|
||||
$ vue-cli-service test:e2e --baseUrl=http://localhost:8080/
|
||||
```
|
||||
@@ -0,0 +1,41 @@
|
||||
jest.setTimeout(process.env.APPVEYOR ? 120000 : 60000)
|
||||
|
||||
const create = require('@vue/cli-test-utils/createTestProject')
|
||||
|
||||
test('should work', async () => {
|
||||
const project = await create('e2e-webdriverio', {
|
||||
plugins: {
|
||||
'@vue/cli-plugin-babel': {},
|
||||
'@vue/cli-plugin-e2e-webdriverio': {},
|
||||
'@vue/cli-plugin-eslint': {
|
||||
config: 'airbnb',
|
||||
lintOn: 'save'
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
if (!process.env.CI) {
|
||||
await project.run(`vue-cli-service test:e2e`)
|
||||
} else if (!process.env.APPVEYOR) {
|
||||
await project.run(`vue-cli-service test:e2e --headless`)
|
||||
}
|
||||
})
|
||||
|
||||
test('should work with TS', async () => {
|
||||
const project = await create('e2e-webdriverio-ts', {
|
||||
plugins: {
|
||||
'@vue/cli-plugin-typescript': {
|
||||
'classComponent': true,
|
||||
'tsLint': true,
|
||||
'lintOn': ['save']
|
||||
},
|
||||
'@vue/cli-plugin-e2e-webdriverio': {}
|
||||
}
|
||||
})
|
||||
|
||||
if (!process.env.CI) {
|
||||
await project.run(`vue-cli-service test:e2e`)
|
||||
} else if (!process.env.APPVEYOR) {
|
||||
await project.run(`vue-cli-service test:e2e --headless`)
|
||||
}
|
||||
})
|
||||
@@ -0,0 +1,35 @@
|
||||
const { installedBrowsers } = require('@vue/cli-shared-utils')
|
||||
|
||||
module.exports = (api, { webdrivers }) => {
|
||||
api.render('./template', {
|
||||
hasTS: api.hasPlugin('typescript'),
|
||||
hasESLint: api.hasPlugin('eslint')
|
||||
})
|
||||
|
||||
const devDependencies = {}
|
||||
|
||||
// Use devDependencies to store latest version number so as to automate update
|
||||
const pluginDeps = require('../package.json').devDependencies
|
||||
|
||||
if (webdrivers && webdrivers.includes('firefox')) {
|
||||
devDependencies.geckodriver = pluginDeps.geckodriver
|
||||
devDependencies['wdio-geckodriver-service'] = pluginDeps['wdio-geckodriver-service']
|
||||
}
|
||||
if (webdrivers && webdrivers.includes('chrome')) {
|
||||
// chromedriver major version bumps every 6 weeks following Chrome
|
||||
// so there may be a mismatch between
|
||||
// user's installed browser version and the default provided version
|
||||
// fallback to the devDependencies version in case detection fails
|
||||
devDependencies['wdio-chromedriver-service'] = pluginDeps['wdio-chromedriver-service']
|
||||
devDependencies.chromedriver = installedBrowsers.chrome
|
||||
? installedBrowsers.chrome.match(/^(\d+)\./)[1]
|
||||
: pluginDeps.chromedriver
|
||||
}
|
||||
|
||||
api.extendPackage({
|
||||
scripts: {
|
||||
'test:e2e': 'vue-cli-service test:e2e'
|
||||
},
|
||||
devDependencies
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
<%_ if (hasESLint) { _%>
|
||||
module.exports = {
|
||||
plugins: ['wdio'],
|
||||
extends: 'plugin:wdio/recommended',
|
||||
env: {
|
||||
mocha: true
|
||||
},
|
||||
rules: {
|
||||
strict: 'off'
|
||||
}
|
||||
}
|
||||
<%_ } _%>
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
class App {
|
||||
/**
|
||||
* elements
|
||||
*/
|
||||
get heading () { return $('h1') }
|
||||
|
||||
/**
|
||||
* methods
|
||||
*/
|
||||
open (path = '/') {
|
||||
browser.url(path)
|
||||
}
|
||||
}
|
||||
|
||||
<%- hasTS ? 'export default new App()' : 'module.exports = new App()' %>
|
||||
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
<%- hasTS ? 'import App from \'../pageobjects/app.page\'' : 'const App = require(\'../pageobjects/app.page\')' %>
|
||||
|
||||
describe('Vue.js app', () => {
|
||||
it('should open and render', () => {
|
||||
App.open()
|
||||
expect(App.heading).toHaveText('Welcome to Your Vue.js <%- hasTS ? '+ TypeScript ' : '' %>App')
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,25 @@
|
||||
<%- hasTS ? 'const { config } = require(\'./wdio.shared.conf.ts\')' : 'const { config } = require(\'./wdio.shared.conf\')' %>
|
||||
|
||||
exports.config = {
|
||||
/**
|
||||
* base config
|
||||
*/
|
||||
...config,
|
||||
/**
|
||||
* config for local testing
|
||||
*/
|
||||
maxInstances: 1,
|
||||
services: ['chromedriver', 'geckodriver'],
|
||||
capabilities: [{
|
||||
browserName: 'chrome',
|
||||
acceptInsecureCerts: true,
|
||||
'goog:chromeOptions': {
|
||||
args: process.argv.includes('--headless')
|
||||
? ['--headless', '--disable-gpu']
|
||||
: []
|
||||
}
|
||||
}, {
|
||||
browserName: 'firefox',
|
||||
acceptInsecureCerts: true
|
||||
}]
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
<%- hasTS ? 'import { config } from \'./wdio.shared.conf.ts\'' : 'const { config } = require(\'./wdio.shared.conf\')' %>
|
||||
|
||||
const BUILD_ID = Math.ceil(Date.now() / 1000)
|
||||
|
||||
exports.config = {
|
||||
/**
|
||||
* base config
|
||||
*/
|
||||
...config,
|
||||
/**
|
||||
* config for testing on Sauce Labs
|
||||
*/
|
||||
user: process.env.SAUCE_USERNAME,
|
||||
key: process.env.SAUCE_ACCESS_KEY,
|
||||
region: 'us',
|
||||
headless: process.argv.includes('--headless'),
|
||||
|
||||
services: [
|
||||
['sauce', {
|
||||
sauceConnect: true,
|
||||
tunnelIdentifier: 'Vue.js Integration tests'
|
||||
}]
|
||||
],
|
||||
|
||||
maxInstances: 10,
|
||||
capabilities: [{
|
||||
browserName: 'firefox',
|
||||
browserVersion: 'latest',
|
||||
platformName: 'Windows 10',
|
||||
'sauce:options': {
|
||||
build: `Build ${BUILD_ID}`
|
||||
}
|
||||
}, {
|
||||
browserName: 'chrome',
|
||||
browserVersion: 'latest',
|
||||
platformName: 'Windows 10',
|
||||
'sauce:options': {
|
||||
build: `Build ${BUILD_ID}`
|
||||
}
|
||||
}]
|
||||
}
|
||||
@@ -0,0 +1,211 @@
|
||||
/* eslint-disable no-unused-vars */
|
||||
const path = require('path')
|
||||
|
||||
exports.config = {
|
||||
// ==================
|
||||
// Specify Test Files
|
||||
// ==================
|
||||
// Define which test specs should run. The pattern is relative to the directory
|
||||
// from which `wdio` was called. Notice that, if you are calling `wdio` from an
|
||||
// NPM script (see https://docs.npmjs.com/cli/run-script) then the current working
|
||||
// directory is where your package.json resides, so `wdio` will be called from there.
|
||||
//
|
||||
specs: [
|
||||
path.join(__dirname, '/tests/e2e/**/*.spec.js')
|
||||
],
|
||||
// Patterns to exclude.
|
||||
exclude: [
|
||||
// 'test/spec/multibrowser/**',
|
||||
// 'test/spec/mobile/**'
|
||||
],
|
||||
//
|
||||
// ===================
|
||||
// Test Configurations
|
||||
// ===================
|
||||
// Define all options that are relevant for the WebdriverIO instance here
|
||||
//
|
||||
// Level of logging verbosity: trace | debug | info | warn | error | silent
|
||||
logLevel: 'trace',
|
||||
//
|
||||
// Set directory to store all logs into
|
||||
outputDir: path.join(__dirname, '/logs'),
|
||||
//
|
||||
// If you only want to run your tests until a specific amount of tests have failed use
|
||||
// bail (default is 0 - don't bail, run all tests).
|
||||
bail: 0,
|
||||
//
|
||||
// Default timeout for all waitFor* commands.
|
||||
waitforTimeout: 1000,
|
||||
//
|
||||
// Framework you want to run your specs with.
|
||||
// The following are supported: Mocha, Jasmine, and Cucumber
|
||||
// see also: https://webdriver.io/docs/frameworks.html
|
||||
//
|
||||
// Make sure you have the wdio adapter package for the specific framework
|
||||
// installed before running any tests.
|
||||
framework: 'mocha',
|
||||
//
|
||||
// The number of times to retry the entire specfile when it fails as a whole
|
||||
specFileRetries: 1,
|
||||
//
|
||||
// Retried specfiles are inserted at the beginning of the queue and retried immediately
|
||||
specFileRetriesDeferred: false,
|
||||
//
|
||||
// Test reporter for stdout.
|
||||
// The only one supported by default is 'dot'
|
||||
// see also: https://webdriver.io/docs/dot-reporter.html
|
||||
reporters: ['spec'],
|
||||
//
|
||||
// Options to be passed to Mocha.
|
||||
// See the full list at http://mochajs.org/
|
||||
mochaOpts: {
|
||||
ui: 'bdd',
|
||||
timeout: 30000,
|
||||
<%- hasTS ? 'require: \'ts-node/register\'' : '' %>
|
||||
},
|
||||
//
|
||||
// =====
|
||||
// Hooks
|
||||
// =====
|
||||
// WebdriverIO provides several hooks you can use to interfere with the test process in order to enhance
|
||||
// it and to build services around it. You can either apply a single function or an array of
|
||||
// methods to it. If one of them returns with a promise, WebdriverIO will wait until that promise got
|
||||
// resolved to continue.
|
||||
//
|
||||
/**
|
||||
* Gets executed once before all workers get launched.
|
||||
* @param {Object} config wdio configuration object
|
||||
* @param {Array.<Object>} capabilities list of capabilities details
|
||||
*/
|
||||
onPrepare: function (config, capabilities) {
|
||||
},
|
||||
/**
|
||||
* Gets executed before a worker process is spawned and can be used to initialise specific service
|
||||
* for that worker as well as modify runtime environments in an async fashion.
|
||||
* @param {String} cid capability id (e.g 0-0)
|
||||
* @param {[type]} caps object containing capabilities for session that will be spawn in the worker
|
||||
* @param {[type]} specs specs to be run in the worker process
|
||||
* @param {[type]} args object that will be merged with the main configuration once worker is initialised
|
||||
* @param {[type]} execArgv list of string arguments passed to the worker process
|
||||
*/
|
||||
onWorkerStart: function (cid, caps, specs, args, execArgv) {
|
||||
},
|
||||
/**
|
||||
* Gets executed just before initialising the webdriver session and test framework. It allows you
|
||||
* to manipulate configurations depending on the capability or spec.
|
||||
* @param {Object} config wdio configuration object
|
||||
* @param {Array.<Object>} capabilities list of capabilities details
|
||||
* @param {Array.<String>} specs List of spec file paths that are to be run
|
||||
*/
|
||||
beforeSession: function (config, capabilities, specs) {
|
||||
},
|
||||
/**
|
||||
* Gets executed before test execution begins. At this point you can access to all global
|
||||
* variables like `browser`. It is the perfect place to define custom commands.
|
||||
* @param {Array.<Object>} capabilities list of capabilities details
|
||||
* @param {Array.<String>} specs List of spec file paths that are to be run
|
||||
*/
|
||||
before: function (capabilities, specs) {
|
||||
},
|
||||
/**
|
||||
* Hook that gets executed before the suite starts
|
||||
* @param {Object} suite suite details
|
||||
*/
|
||||
beforeSuite: function (suite) {
|
||||
},
|
||||
/**
|
||||
* Hook that gets executed _before_ a hook within the suite starts (e.g. runs before calling
|
||||
* beforeEach in Mocha)
|
||||
* stepData and world are Cucumber framework specific
|
||||
*/
|
||||
beforeHook: function (test, context/*, stepData, world*/) {
|
||||
},
|
||||
/**
|
||||
* Hook that gets executed _after_ a hook within the suite ends (e.g. runs after calling
|
||||
* afterEach in Mocha)
|
||||
* stepData and world are Cucumber framework specific
|
||||
*/
|
||||
afterHook: function (test, context, { error, result, duration, passed, retries }/*, stepData, world*/) {
|
||||
},
|
||||
/**
|
||||
* Function to be executed before a test (in Mocha/Jasmine) starts.
|
||||
*/
|
||||
beforeTest: function (test, context) {
|
||||
},
|
||||
//
|
||||
/**
|
||||
* Runs before a WebdriverIO command gets executed.
|
||||
* @param {String} commandName command name
|
||||
* @param {Array} args arguments that command would receive
|
||||
*/
|
||||
beforeCommand: function (commandName, args) {
|
||||
},
|
||||
/**
|
||||
* Runs after a WebdriverIO command gets executed.
|
||||
* @param {String} commandName hook command name
|
||||
* @param {Array} args arguments that command would receive
|
||||
* @param {Number} result 0 - command success, 1 - command error
|
||||
* @param {Object} error error object if any
|
||||
*/
|
||||
afterCommand: function (commandName, args, result, error) {
|
||||
},
|
||||
/**
|
||||
* Function to be executed after a test (in Mocha/Jasmine) ends.
|
||||
*/
|
||||
afterTest: function (test, context, { error, result, duration, passed, retries }) {
|
||||
},
|
||||
/**
|
||||
* Hook that gets executed after the suite has ended
|
||||
* @param {Object} suite suite details
|
||||
*/
|
||||
afterSuite: function (suite) {
|
||||
},
|
||||
/**
|
||||
* Gets executed after all tests are done. You still have access to all global variables from
|
||||
* the test.
|
||||
* @param {Number} result 0 - test pass, 1 - test fail
|
||||
* @param {Array.<Object>} capabilities list of capabilities details
|
||||
* @param {Array.<String>} specs List of spec file paths that ran
|
||||
*/
|
||||
after: function (result, capabilities, specs) {
|
||||
},
|
||||
/**
|
||||
* Gets executed right after terminating the webdriver session.
|
||||
* @param {Object} config wdio configuration object
|
||||
* @param {Array.<Object>} capabilities list of capabilities details
|
||||
* @param {Array.<String>} specs List of spec file paths that ran
|
||||
*/
|
||||
afterSession: function (config, capabilities, specs) {
|
||||
},
|
||||
/**
|
||||
* Gets executed after all workers got shut down and the process is about to exit. An error
|
||||
* thrown in the onComplete hook will result in the test run failing.
|
||||
* @param {Object} exitCode 0 - success, 1 - fail
|
||||
* @param {Object} config wdio configuration object
|
||||
* @param {Array.<Object>} capabilities list of capabilities details
|
||||
* @param {<Object>} results object containing test results
|
||||
*/
|
||||
onComplete: function (exitCode, config, capabilities, results) {
|
||||
},
|
||||
/**
|
||||
* Gets executed when a refresh happens.
|
||||
* @param {String} oldSessionId session ID of the old session
|
||||
* @param {String} newSessionId session ID of the new session
|
||||
*/
|
||||
onReload: function(oldSessionId, newSessionId) {
|
||||
},
|
||||
//
|
||||
// Cucumber specific hooks
|
||||
beforeFeature: function (uri, feature, scenarios) {
|
||||
},
|
||||
beforeScenario: function (uri, feature, scenario, sourceLocation) {
|
||||
},
|
||||
beforeStep: function ({ uri, feature, step }, context) {
|
||||
},
|
||||
afterStep: function ({ uri, feature, step }, context, { error, result, duration, passed, retries }) {
|
||||
},
|
||||
afterScenario: function (uri, feature, scenario, result, sourceLocation) {
|
||||
},
|
||||
afterFeature: function (uri, feature, scenarios) {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
|
||||
const { info, chalk, execa } = require('@vue/cli-shared-utils')
|
||||
const { cmdArgs } = require('@wdio/cli/build/commands/run')
|
||||
|
||||
const CLI_OPTIONS = Object.entries(cmdArgs).reduce((obj, [param, { desc }]) => {
|
||||
obj[`--${param}`] = desc
|
||||
return obj
|
||||
}, {})
|
||||
|
||||
module.exports = (api, options) => {
|
||||
api.registerCommand('test:e2e', {
|
||||
description: 'run end-to-end tests with WebdriverIO',
|
||||
usage: 'vue-cli-service test:e2e [options]',
|
||||
options: {
|
||||
'--remote': 'Run tests remotely on SauceLabs',
|
||||
'--headless': 'Run tests headless',
|
||||
...CLI_OPTIONS
|
||||
},
|
||||
details:
|
||||
`All WebdriverIO CLI options are also supported.\n` +
|
||||
chalk.yellow(`https://webdriver.io/docs/clioptions.html`)
|
||||
}, (args, rawArgs) => {
|
||||
return Promise.all([
|
||||
startDevServer(args, api)
|
||||
]).then((results) => {
|
||||
const { server, url } = results[0]
|
||||
info(`Running end-to-end tests...`)
|
||||
|
||||
// expose dev server url to tests
|
||||
if (!args.baseUrl) {
|
||||
rawArgs.push(`--baseUrl=${url}`)
|
||||
}
|
||||
|
||||
const isTS = fs.existsSync(path.join(process.cwd(), 'tsconfig.json'))
|
||||
const configFile = !args.remote
|
||||
? path.join(process.cwd(), 'wdio.local.conf.' + (isTS ? 'ts' : 'js'))
|
||||
: path.join(process.cwd(), 'wdio.sauce.conf.' + (isTS ? 'ts' : 'js'))
|
||||
const wdioBinPath = require.resolve('@wdio/cli/bin/wdio')
|
||||
|
||||
const runArgs = ['run', configFile, ...rawArgs]
|
||||
info(`Start WebdriverIO: $ wdio ${runArgs.join(' ')}`)
|
||||
const runner = execa(wdioBinPath, runArgs, { stdio: 'inherit' })
|
||||
if (server) {
|
||||
runner.on('exit', () => server.close())
|
||||
runner.on('error', () => server.close())
|
||||
}
|
||||
|
||||
if (process.env.VUE_CLI_TEST) {
|
||||
runner.on('exit', code => {
|
||||
process.exit(code)
|
||||
})
|
||||
}
|
||||
|
||||
return runner
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
module.exports.defaultModes = {
|
||||
'test:e2e': 'production'
|
||||
}
|
||||
|
||||
function startDevServer (args, api) {
|
||||
const { baseUrl } = args
|
||||
|
||||
if (baseUrl) {
|
||||
return Promise.resolve({ baseUrl })
|
||||
}
|
||||
|
||||
return api.service.run('serve')
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
{
|
||||
"name": "@vue/cli-plugin-e2e-webdriverio",
|
||||
"version": "4.3.1",
|
||||
"description": "e2e-webdriverio plugin for vue-cli",
|
||||
"main": "index.js",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/vuejs/vue-cli.git",
|
||||
"directory": "packages/@vue/cli-plugin-e2e-webdriverio"
|
||||
},
|
||||
"keywords": [
|
||||
"vue",
|
||||
"cli",
|
||||
"wdio",
|
||||
"webdriverio",
|
||||
"e2e-webdriverio"
|
||||
],
|
||||
"author": "Christian Bromann <christian@saucelabs.com>",
|
||||
"license": "MIT",
|
||||
"bugs": {
|
||||
"url": "https://github.com/vuejs/vue-cli/issues"
|
||||
},
|
||||
"homepage": "https://github.com/vuejs/vue-cli/tree/dev/packages/@vue/cli-plugin-e2e-webdriverio#readme",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"dependencies": {
|
||||
"@vue/cli-shared-utils": "^4.3.1",
|
||||
"@wdio/cli": "^6.1.11",
|
||||
"@wdio/local-runner": "^6.1.11",
|
||||
"@wdio/mocha-framework": "^6.1.8",
|
||||
"@wdio/sauce-service": "^6.1.9",
|
||||
"@wdio/spec-reporter": "^6.1.9",
|
||||
"@wdio/sync": "^6.1.8",
|
||||
"eslint-plugin-wdio": "^6.0.12",
|
||||
"webdriverio": "^6.1.11"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"chromedriver": "84.0.1",
|
||||
"geckodriver": "1.19.1",
|
||||
"wdio-chromedriver-service": "^6.0.3",
|
||||
"wdio-geckodriver-service": "^1.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"chromedriver": "84.0.1",
|
||||
"geckodriver": "1.19.1",
|
||||
"wdio-chromedriver-service": "^6.0.3",
|
||||
"wdio-geckodriver-service": "^1.1.0"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
const { installedBrowsers } = require('@vue/cli-shared-utils')
|
||||
|
||||
module.exports = [
|
||||
{
|
||||
name: 'webdrivers',
|
||||
type: `checkbox`,
|
||||
message: `Pick browsers to run end-to-end test on!!!!!`,
|
||||
choices: [
|
||||
{
|
||||
name: `Chrome`,
|
||||
value: 'chrome',
|
||||
checked: true
|
||||
},
|
||||
{
|
||||
name: 'Firefox',
|
||||
value: 'firefox',
|
||||
// check the "Firefox" option if user has installed it
|
||||
checked: !!installedBrowsers.firefox
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,9 @@
|
||||
module.exports = api => {
|
||||
api.describeTask({
|
||||
match: /vue-cli-service test:e2e/,
|
||||
description: 'org.vue.webdriverio.tasks.test.description',
|
||||
link: 'https://github.com/vuejs/vue-cli',
|
||||
prompts: [],
|
||||
onBeforeRun: () => {}
|
||||
})
|
||||
}
|
||||
@@ -6,6 +6,7 @@ const officialPlugins = [
|
||||
'babel',
|
||||
'e2e-cypress',
|
||||
'e2e-nightwatch',
|
||||
'e2e-webdriverio',
|
||||
'eslint',
|
||||
'pwa',
|
||||
'router',
|
||||
|
||||
@@ -14,7 +14,7 @@ test('cypress', async () => {
|
||||
},
|
||||
{
|
||||
message: 'Pick an E2E testing solution',
|
||||
choices: ['Cypress', 'Nightwatch'],
|
||||
choices: ['Cypress', 'Nightwatch', 'WebdriverIO'],
|
||||
choose: 0
|
||||
}
|
||||
]
|
||||
@@ -42,7 +42,7 @@ test('nightwatch', async () => {
|
||||
},
|
||||
{
|
||||
message: 'Pick an E2E testing solution',
|
||||
choices: ['Cypress', 'Nightwatch'],
|
||||
choices: ['Cypress', 'Nightwatch', 'WebdriverIO'],
|
||||
choose: 1
|
||||
},
|
||||
{
|
||||
@@ -65,3 +65,36 @@ test('nightwatch', async () => {
|
||||
{ pluginsOnly: true }
|
||||
)
|
||||
})
|
||||
|
||||
test('webdriverio', async () => {
|
||||
const expectedPrompts = [
|
||||
{
|
||||
message: 'features',
|
||||
choices: ['E2E Testing'],
|
||||
check: [0]
|
||||
},
|
||||
{
|
||||
message: 'Pick an E2E testing solution',
|
||||
choices: ['Cypress', 'Nightwatch', 'WebdriverIO'],
|
||||
choose: 2
|
||||
},
|
||||
{
|
||||
message: 'Pick browsers to run end-to-end test on',
|
||||
choice: ['Chrome', 'Firefox'],
|
||||
check: [0, 1]
|
||||
}
|
||||
]
|
||||
|
||||
const expectedOptions = {
|
||||
plugins: {
|
||||
'@vue/cli-plugin-e2e-webdriverio': {}
|
||||
}
|
||||
}
|
||||
|
||||
await assertPromptModule(
|
||||
moduleToTest,
|
||||
expectedPrompts,
|
||||
expectedOptions,
|
||||
{ pluginsOnly: true }
|
||||
)
|
||||
})
|
||||
|
||||
@@ -7,7 +7,7 @@ module.exports = cli => {
|
||||
short: 'E2E',
|
||||
description: 'Add an End-to-End testing solution to the app like Cypress or Nightwatch',
|
||||
link: 'https://github.com/vuejs/vue-cli/tree/dev/docs#e2e-testing',
|
||||
plugins: ['e2e-cypress', 'e2e-nightwatch']
|
||||
plugins: ['e2e-cypress', 'e2e-nightwatch', 'e2e-webdriverio']
|
||||
})
|
||||
|
||||
cli.injectPrompt({
|
||||
@@ -25,13 +25,18 @@ module.exports = cli => {
|
||||
name: 'Nightwatch (WebDriver-based)',
|
||||
value: 'nightwatch',
|
||||
short: 'Nightwatch'
|
||||
},
|
||||
{
|
||||
name: 'WebdriverIO (WebDriver/DevTools based)',
|
||||
value: 'webdriverio',
|
||||
short: 'WebdriverIO'
|
||||
}
|
||||
]
|
||||
})
|
||||
|
||||
cli.injectPrompt({
|
||||
name: 'webdrivers',
|
||||
when: answers => answers.e2e === 'nightwatch',
|
||||
when: answers => ['nightwatch', 'webdriverio'].includes(answers.e2e),
|
||||
type: `checkbox`,
|
||||
message: `Pick browsers to run end-to-end test on`,
|
||||
choices: [
|
||||
@@ -54,6 +59,8 @@ module.exports = cli => {
|
||||
options.plugins['@vue/cli-plugin-e2e-cypress'] = {}
|
||||
} else if (answers.e2e === 'nightwatch') {
|
||||
options.plugins['@vue/cli-plugin-e2e-nightwatch'] = {}
|
||||
} else if (answers.e2e === 'webdriverio') {
|
||||
options.plugins['@vue/cli-plugin-e2e-webdriverio'] = {}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user