Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(e2e-webdriverio): add e2e plugin for WebdriverIO #5479

Merged
merged 9 commits into from Jul 31, 2020
3 changes: 2 additions & 1 deletion docs/.vuepress/config.js
Expand Up @@ -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'
]
}],

Expand Down
4 changes: 4 additions & 0 deletions docs/config/README.md
Expand Up @@ -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.
1 change: 1 addition & 0 deletions docs/core-plugins/README.md
Expand Up @@ -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)
64 changes: 64 additions & 0 deletions docs/core-plugins/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
```
2 changes: 2 additions & 0 deletions packages/@vue/cli-plugin-e2e-webdriverio/.npmignore
@@ -0,0 +1,2 @@
__tests__
__mocks__
81 changes: 81 additions & 0 deletions packages/@vue/cli-plugin-e2e-webdriverio/README.md
@@ -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`)
}
})
35 changes: 35 additions & 0 deletions packages/@vue/cli-plugin-e2e-webdriverio/generator/index.js
@@ -0,0 +1,35 @@
const { installedBrowsers } = require('@vue/cli-shared-utils')

module.exports = (api, { webdrivers }) => {
christian-bromann marked this conversation as resolved.
Show resolved Hide resolved
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'
}
}
<%_ } _%>
@@ -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()' %>

@@ -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
}]
}
christian-bromann marked this conversation as resolved.
Show resolved Hide resolved
@@ -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}`
}
}]
}