Skip to content

Commit

Permalink
feature: Add support for filtering and skipping multiple tags
Browse files Browse the repository at this point in the history
closes #170
  • Loading branch information
Igor Muchychka committed Aug 12, 2017
1 parent 8ba8e0b commit 4d25edc
Show file tree
Hide file tree
Showing 7 changed files with 156 additions and 41 deletions.
4 changes: 4 additions & 0 deletions .all-contributorsrc
Expand Up @@ -153,6 +153,10 @@
"avatar_url": "https://avatars3.githubusercontent.com/u/2751776?v=3",
"profile": "https://github.com/dmerc",
"contributions": []
},
{
"name": "\terikmellum",
"contributions": []
}
]
}
39 changes: 14 additions & 25 deletions README.md
Expand Up @@ -2,7 +2,7 @@

[![npm version](https://badge.fury.io/js/nightwatch-cucumber.svg)](https://badge.fury.io/js/nightwatch-cucumber)
[![Build Status](https://travis-ci.org/mucsi96/nightwatch-cucumber.svg?branch=master)](https://travis-ci.org/mucsi96/nightwatch-cucumber)
[![All Contributors](https://img.shields.io/badge/all_contributors-21-orange.svg?style=flat-square)](#contributors)
[![All Contributors](https://img.shields.io/badge/all_contributors-22-orange.svg?style=flat-square)](#contributors)
[![Coverage Status](https://coveralls.io/repos/github/mucsi96/nightwatch-cucumber/badge.svg?branch=master)](https://coveralls.io/github/mucsi96/nightwatch-cucumber?branch=master)
[![semantic-release](https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg)](https://github.com/semantic-release/semantic-release)
[![Greenkeeper badge](https://badges.greenkeeper.io/mucsi96/nightwatch-cucumber.svg)](https://greenkeeper.io/)
Expand All @@ -12,8 +12,6 @@
[![Twitter Follow](https://img.shields.io/twitter/follow/mucsi96.svg?style=social&label=Follow&maxAge=2592000)](https://twitter.com/mucsi96)
[Ask question](https://stackoverflow.com/questions/tagged/nightwatch.js+cucumber)

[![NPM](https://nodei.co/npm-dl/nightwatch-cucumber.png)](https://nodei.co/npm/nightwatch-cucumber/)

This module enables to use a BDD-style approach for cross-browser testing:
- Describe user stories in [Cucumber](https://cucumber.io/) using [Gherkin syntax](https://cucumber.io/docs/reference)
- Map them to browser operations and assertions in [Nightwatch.js](http://nightwatchjs.org/)
Expand Down Expand Up @@ -402,15 +400,16 @@ defineSupportCode(({Given, Then, When}) => {
You can selectively run features based on groups. To group features together just place them in the same sub-folder. The folder name is the name of the group.
You can use Nightwatch CLI `--group`, `--skipgroup` flags. [More details ](http://nightwatchjs.org/guide#test-groups)

### Feature Tags
### Feature and Scenario Tags

You can selectively run features based on tags. [More details ](http://nightwatchjs.org/guide#test-tags)
You can selectively run features and scenarios based on tags. [More details ](http://nightwatchjs.org/guide#test-tags)
```gherkin
# google.feature
@google @search
@google
Feature: Google Search
@search
Scenario: Searching Google
Given I open Google's search page
Expand All @@ -420,32 +419,21 @@ Scenario: Searching Google
```
$ node nightwatch.js --tag google
```
or for more matches
```
$ node nightwatch.js --tag google --tag yahoo
```
You can also skip features based on tags
```
node nightwatch.js --skiptags google
```

### Scenario Tags

You can selectively run scenarios based on tags.
```gherkin
# google.feature
Feature: Google Search
@google @search
Scenario: Searching Google
Given I open Google's search page
Then the title is "Google"
And the Google search form exists
```
or for skipping multiple tags
```
$ node nightwatch.js --tag google
node nightwatch.js --skiptags google,yahoo
```
You can also skip scenarios based on tags
and all together :)
```
node nightwatch.js --skiptags google
node nightwatch.js --tag google --tag yahoo --skiptags search,login
```

### Parallel execution
Expand Down Expand Up @@ -626,6 +614,7 @@ Thanks goes to these wonderful people ([emoji key](https://github.com/kentcdodds
| :---: | :---: | :---: | :---: | :---: | :---: | :---: |
| [<img src="https://avatars.githubusercontent.com/u/7160445?v=3" width="100px;"/><br /><sub>Fabio Quinzi</sub>](http://fabioquinzi.com)<br /> | [<img src="https://avatars.githubusercontent.com/u/7831710?v=3" width="100px;"/><br /><sub>Jeffrey Effendy</sub>](https://github.com/jeffrey-effendy)<br /> | [<img src="https://avatars.githubusercontent.com/u/1711610?v=3" width="100px;"/><br /><sub>Lawrence</sub>](http://ldabiralai.me)<br /> | [<img src="https://avatars.githubusercontent.com/u/1260402?v=3" width="100px;"/><br /><sub>Domenico Gemoli</sub>](http://domenicogemoli.com)<br /> | [<img src="https://avatars.githubusercontent.com/u/8973021?v=3" width="100px;"/><br /><sub>Klokov Anton</sub>](https://github.com/klokovas)<br /> | [<img src="https://avatars.githubusercontent.com/u/2287663?v=3" width="100px;"/><br /><sub>Arnaud gueras</sub>](https://github.com/arnogues)<br /> | [<img src="https://avatars.githubusercontent.com/u/2906107?v=3" width="100px;"/><br /><sub>Lukas Eipert</sub>](http://leipert.io)<br /> |
| [<img src="https://avatars.githubusercontent.com/u/4364107?v=3" width="100px;"/><br /><sub>Paulo</sub>](http://madrov.com)<br /> | [<img src="https://avatars.githubusercontent.com/u/6282473?v=3" width="100px;"/><br /><sub>Tylor Steinberger</sub>](https://github.com/TylorS)<br /> | [<img src="https://avatars.githubusercontent.com/u/1476974?v=3" width="100px;"/><br /><sub>Eric Chan</sub>](https://github.com/kinyat)<br /> | [<img src="https://avatars.githubusercontent.com/u/1476502?v=3" width="100px;"/><br /><sub>Mykolas</sub>](http://www.myk.lt)<br /> | [<img src="https://avatars.githubusercontent.com/u/5993909?v=3" width="100px;"/><br /><sub>Jon Wallsten</sub>](https://github.com/JonWallsten)<br /> | [<img src="https://avatars2.githubusercontent.com/u/6979207?v=3" width="100px;"/><br /><sub>Julien Viala</sub>](https://github.com/mr-wildcard)<br /> | [<img src="https://avatars3.githubusercontent.com/u/2751776?v=3" width="100px;"/><br /><sub>dmerc</sub>](https://github.com/dmerc)<br /> |
| [<img src="" width="100px;"/><br /><sub> erikmellum</sub>]()<br /> |
<!-- ALL-CONTRIBUTORS-LIST:END -->
This project follows the [all-contributors](https://github.com/kentcdodds/all-contributors) specification. Contributions of any kind welcome!
Expand Down
16 changes: 12 additions & 4 deletions lib/cucumber-api.js
Expand Up @@ -113,7 +113,7 @@ module.exports = class CucumberAPI {
return featureFiles
}

getAdjustedArgs ({args, featureFiles, jsonReport, tags}) {
getAdjustedArgs ({args, featureFiles, jsonReport, tags, skipTags}) {
const result = []
let i = 0
while (i < args.length) {
Expand All @@ -134,10 +134,18 @@ module.exports = class CucumberAPI {
}
}

tags.forEach((tag) => {
if (tags.length || skipTags.length) {
result.push('--tags')
result.push(tag)
})
const joinedTags = tags.join(' or ')
const joinedSkipTags = skipTags.map(tag => `(not ${tag})`).join(' and ')
if (joinedTags && joinedSkipTags) {
result.push(`(${joinedTags}) and ${joinedSkipTags}`)
} else if (joinedTags) {
result.push(`${joinedTags}`)
} else if (joinedSkipTags) {
result.push(`${joinedSkipTags}`)
}
}

featureFiles.forEach((featureFile) => {
result.push(featureFile)
Expand Down
12 changes: 4 additions & 8 deletions lib/runner.js
Expand Up @@ -38,13 +38,9 @@ module.exports = class Runner {
}

getSkipTags (nightwatchArgv) {
let result = nightwatchArgv.skiptags || []
if (!nightwatchArgv.skiptags) return []

if (typeof result === 'string') {
result = [result]
}

return result.map((tag) => `not @${tag}`)
return nightwatchArgv.skiptags.split(',').map((tag) => `@${tag}`)
}

featurePathToDummyPath (featureFile) {
Expand Down Expand Up @@ -72,7 +68,6 @@ module.exports = class Runner {

* executeTestModules (dummyTestModules) {
const featureFiles = dummyTestModules.map((dummyTestModule) => this.dummyPathToFeaturePath(dummyTestModule))
const tags = this.getTags(this.nightwatchApi.nightwatchArgv).concat(this.getSkipTags(this.nightwatchApi.nightwatchArgv))

if (this.nightwatchApi.isRunningInParallel()) {
const workerIndex = this.nightwatchApi.getWorkerIndex()
Expand All @@ -86,7 +81,8 @@ module.exports = class Runner {
args: this.options.cucumberArgs,
featureFiles,
jsonReport: this.jsonReport,
tags
tags: this.getTags(this.nightwatchApi.nightwatchArgv),
skipTags: this.getSkipTags(this.nightwatchApi.nightwatchArgv)
})
return yield * this.cucumberApi.run(cucumberArgs)
}
Expand Down
16 changes: 13 additions & 3 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

108 changes: 108 additions & 0 deletions test/cli.test.js
Expand Up @@ -253,6 +253,114 @@ describe('CLI', () => {
})
})

it('should handle multiple scenario tag filtering', () => {
return testCaseFactory
.create('multipleFeatureTagSkippingTest')
.feature('positive addition', ['positive', 'addition'])
.scenario('small numbers', ['smallPositiveNumbers'])
.given('User is on the simple calculator page', () => client.init())
.and('User enter 4 in A field', () => client.setValue('#a', 4))
.and('User enter 5 in B field', () => client.setValue('#b', 5))
.when('User press Add button', () => client.click('#add'))
.then('The result should contain 9', () => client.assert.containsText('#result', 9))
.scenario('big numbers', ['bigPositiveNumbers'])
.given('User is on the simple calculator page')
.and('User enter 4 in A field')
.and('User enter 5 in B field')
.when('User press Add button')
.then('The result should contain 9')
.feature('negative addition', ['negative', 'addition'])
.scenario('small numbers', ['smallNegativeNumbers'])
.given('User is on the simple calculator page')
.and('User enter -4 in A field', () => client.setValue('#a', -4))
.and('User enter -5 in B field', () => client.setValue('#b', -5))
.when('User press Add button')
.then('The result should contain -9', () => client.assert.containsText('#result', -9))
.scenario('big numbers', ['bigNegativeNumbers'])
.given('User is on the simple calculator page')
.and('User enter -4 in A field')
.and('User enter -5 in B field')
.when('User press Add button')
.then('The result should contain -9')
.run(['--tag', 'smallPositiveNumbers', '--tag', 'bigNegativeNumbers'])
.then((result) => {
result.features[0].scenarios[0].name.should.equal('big numbers')
result.features[1].scenarios[0].name.should.equal('small numbers')
})
})

it('should handle multiple scenario tag skipping', () => {
return testCaseFactory
.create('multipleFeatureTagSkippingTest')
.feature('positive addition', ['positive', 'addition'])
.scenario('small numbers', ['smallPositiveNumbers'])
.given('User is on the simple calculator page', () => client.init())
.and('User enter 4 in A field', () => client.setValue('#a', 4))
.and('User enter 5 in B field', () => client.setValue('#b', 5))
.when('User press Add button', () => client.click('#add'))
.then('The result should contain 9', () => client.assert.containsText('#result', 9))
.scenario('big numbers', ['bigPositiveNumbers'])
.given('User is on the simple calculator page')
.and('User enter 4 in A field')
.and('User enter 5 in B field')
.when('User press Add button')
.then('The result should contain 9')
.feature('negative addition', ['negative', 'addition'])
.scenario('small numbers', ['smallNegativeNumbers'])
.given('User is on the simple calculator page')
.and('User enter -4 in A field', () => client.setValue('#a', -4))
.and('User enter -5 in B field', () => client.setValue('#b', -5))
.when('User press Add button')
.then('The result should contain -9', () => client.assert.containsText('#result', -9))
.scenario('big numbers', ['bigNegativeNumbers'])
.given('User is on the simple calculator page')
.and('User enter -4 in A field')
.and('User enter -5 in B field')
.when('User press Add button')
.then('The result should contain -9')
.run(['--skiptags', 'smallPositiveNumbers,bigNegativeNumbers'])
.then((result) => {
result.features[0].scenarios[0].name.should.equal('small numbers')
result.features[1].scenarios[0].name.should.equal('big numbers')
})
})

it('should handle multiple scenario tag filtering and skipping', () => {
return testCaseFactory
.create('multipleFeatureTagFilteringAndSkippingTest')
.feature('positive addition')
.scenario('small numbers', ['smallPositiveNumbers', 'positive', 'addition'])
.given('User is on the simple calculator page', () => client.init())
.and('User enter 4 in A field', () => client.setValue('#a', 4))
.and('User enter 5 in B field', () => client.setValue('#b', 5))
.when('User press Add button', () => client.click('#add'))
.then('The result should contain 9', () => client.assert.containsText('#result', 9))
.scenario('big numbers', ['bigPositiveNumbers', 'positive', 'addition'])
.given('User is on the simple calculator page')
.and('User enter 4 in A field')
.and('User enter 5 in B field')
.when('User press Add button')
.then('The result should contain 9')
.feature('negative addition', ['negative', 'addition'])
.scenario('small numbers', ['smallNegativeNumbers'])
.given('User is on the simple calculator page')
.and('User enter -4 in A field', () => client.setValue('#a', -4))
.and('User enter -5 in B field', () => client.setValue('#b', -5))
.when('User press Add button')
.then('The result should contain -9', () => client.assert.containsText('#result', -9))
.scenario('big numbers', ['bigNegativeNumbers'])
.given('User is on the simple calculator page')
.and('User enter -4 in A field')
.and('User enter -5 in B field')
.when('User press Add button')
.then('The result should contain -9')
.run(['--tag', 'positive', '--tag', 'negative', '--skiptags', 'smallPositiveNumbers,bigNegativeNumbers'])
.then((result) => {
result.features[0].scenarios[0].name.should.equal('small numbers')
result.features[1].scenarios[0].name.should.equal('big numbers')
})
})

it('should handle specified features execution', () => {
return testCaseFactory
.create('specified-features-execution-test')
Expand Down
2 changes: 1 addition & 1 deletion test/test-case-factory.js
Expand Up @@ -151,7 +151,7 @@ class TestCaseFactory {
_buildScenario (featureFile, scenario) {
if (scenario.tags) {
const tagDecleration = scenario.tags.map((tag) => `@${tag}`).join(' ')
fs.writeFileSync(featureFile, `${tagDecleration}\n`, { flag: 'a' })
fs.writeFileSync(featureFile, `\n${tagDecleration}`, { flag: 'a' })
}

if (scenario.examples) {
Expand Down

0 comments on commit 4d25edc

Please sign in to comment.