Skip to content

Commit

Permalink
feat(fixtures): init fixtures support
Browse files Browse the repository at this point in the history
  • Loading branch information
Raphaël Benitte authored and Raphaël Benitte committed Jul 2, 2017
1 parent 3738972 commit db0c460
Show file tree
Hide file tree
Showing 16 changed files with 247 additions and 8 deletions.
48 changes: 45 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,10 @@ It's also the perfect companion for testing CLI applications built with commande
- [Running a simple command](#running-a-simple-command-and-checking-its-exit-code)
- [Testing a command error](#testing-a-command-error)
- [Extensions](#extensions)
- [**state**](#state-extension) [Installation](#state-installation) | [gherkin expressions](#state-gherkin-expressions) | [low level API](#state-low-level-api)
- [**http API**](#http-api-extension) [Installation](#http-api-installation) | [gherkin expressions](#http-api-gherkin-expressions) | [low level API](#http-api-low-level-api)
- [**CLI**](#cli-extension) [Installation](#cli-installation) | [gherkin expressions](#cli-gherkin-expressions) | [low level API](#cli-low-level-api)
- [**state**](#state-extension) [install](#state-installation) | [gherkin expressions](#state-gherkin-expressions) | [low level API](#state-low-level-api)
- [**fixtures**](#fixtures-extension) [install](#fixtures-installation) | [low level API](#fixtures-low-level-api)
- [**http API**](#http-api-extension) [install](#http-api-installation) | [gherkin expressions](#http-api-gherkin-expressions) | [low level API](#http-api-low-level-api)
- [**CLI**](#cli-extension) [install](#cli-installation) | [gherkin expressions](#cli-gherkin-expressions) | [low level API](#cli-low-level-api)
- [Examples](#examples)

## Installation
Expand Down Expand Up @@ -283,6 +284,46 @@ defineSupportCode(({ When }) => {
})
```

### Fixtures extension

The fixtures extension can be used to load data from files during testing.

#### Fixtures installation

To install the extension, you should add the following snippet to your `world` file:

```javascript
// /support/world.js

const { defineSupportCode } = require('cucumber')
const { fixtures } = require('@ekino/veggies')

defineSupportCode(({ setWorldConstructor }) => {
setWorldConstructor(function() {
fixtures.extendWorld(this)
})
})

fixtures.install(defineSupportCode)
```

#### Fixtures low level API

When installed, you can access it from the global cucumber context in your own step definitions.
For available methods on the fixtures loader, please refer to its own
[documentation](https://ekino.github.io/veggies/module-extensions_fixtures_FixturesLoader.html).

```javascript
defineSupportCode(({ When }) => {
When(/^I do something useful with fixtures$/, function() {
return this.fixtures.load('whatever')
.then(fixture => {
//
})
})
})
```

### http API extension

#### http API installation
Expand Down Expand Up @@ -318,6 +359,7 @@ Given:
- /^(?:I )?set request headers$/
- /^(?:I )?set ([a-zA-Z0-9-]+) request header to (.+)$/
- /^(?:I )?set request json body$/
- /^(?:I )?set request json body from (.+)$/
- /^(?:I )?set request form body$/
- /^(?:I )?set request query$/
- /^(?:I )?pick response json (.+) as (.+)$/
Expand Down
47 changes: 44 additions & 3 deletions doc/README.tpl.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,10 @@ It's also the perfect companion for testing CLI applications built with commande
- [Running a simple command](#running-a-simple-command-and-checking-its-exit-code)
- [Testing a command error](#testing-a-command-error)
- [Extensions](#extensions)
- [**state**](#state-extension) [Installation](#state-installation) | [gherkin expressions](#state-gherkin-expressions) | [low level API](#state-low-level-api)
- [**http API**](#http-api-extension) [Installation](#http-api-installation) | [gherkin expressions](#http-api-gherkin-expressions) | [low level API](#http-api-low-level-api)
- [**CLI**](#cli-extension) [Installation](#cli-installation) | [gherkin expressions](#cli-gherkin-expressions) | [low level API](#cli-low-level-api)
- [**state**](#state-extension) [install](#state-installation) | [gherkin expressions](#state-gherkin-expressions) | [low level API](#state-low-level-api)
- [**fixtures**](#fixtures-extension) [install](#fixtures-installation) | [low level API](#fixtures-low-level-api)
- [**http API**](#http-api-extension) [install](#http-api-installation) | [gherkin expressions](#http-api-gherkin-expressions) | [low level API](#http-api-low-level-api)
- [**CLI**](#cli-extension) [install](#cli-installation) | [gherkin expressions](#cli-gherkin-expressions) | [low level API](#cli-low-level-api)
- [Examples](#examples)

## Installation
Expand Down Expand Up @@ -280,6 +281,46 @@ defineSupportCode(({ When }) => {
})
```

### Fixtures extension

The fixtures extension can be used to load data from files during testing.

#### Fixtures installation

To install the extension, you should add the following snippet to your `world` file:

```javascript
// /support/world.js

const { defineSupportCode } = require('cucumber')
const { fixtures } = require('@ekino/veggies')

defineSupportCode(({ setWorldConstructor }) => {
setWorldConstructor(function() {
fixtures.extendWorld(this)
})
})

fixtures.install(defineSupportCode)
```

#### Fixtures low level API

When installed, you can access it from the global cucumber context in your own step definitions.
For available methods on the fixtures loader, please refer to its own
[documentation](https://ekino.github.io/veggies/module-extensions_fixtures_FixturesLoader.html).

```javascript
defineSupportCode(({ When }) => {
When(/^I do something useful with fixtures$/, function() {
return this.fixtures.load('whatever')
.then(fixture => {
//
})
})
})
```

### http API extension

#### http API installation
Expand Down
5 changes: 5 additions & 0 deletions examples/features/http_api/fixtures.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
@http_api @fixtures
Feature: Using fixtures

Scenario: Whatever 1
Given I set request json body from user
Empty file.
Empty file.
Empty file.
Empty file.
6 changes: 4 additions & 2 deletions examples/support/world.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
'use strict'

const { defineSupportCode } = require('cucumber')
const { state, httpApi, cli } = require('../../src')
const { state, fixtures, httpApi, cli } = require('../../src')

defineSupportCode(({ setWorldConstructor }) => {
setWorldConstructor(function() {
state.extendWorld(this)
fixtures.extendWorld(this)
httpApi.extendWorld(this)
cli.extendWorld(this)
})
})

state.install(defineSupportCode)
httpApi.install({})(defineSupportCode)
fixtures.install(defineSupportCode)
httpApi.install()(defineSupportCode)
cli.install(defineSupportCode)
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
"engineStrict": true,
"dependencies": {
"chai": "^4.0.2",
"glob": "^7.1.2",
"lodash": "^4.17.4",
"request": "^2.81.0"
},
Expand Down
10 changes: 10 additions & 0 deletions src/extensions/fixtures/extend_world.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
'use strict'

const Helper = require('../../helper')
const Loader = require('./fixtures_loader')

module.exports = (world, options) => {
Loader.configure(options)
world.fixtures = Loader
Helper.registerExtension(world, 'fixtures')
}
64 changes: 64 additions & 0 deletions src/extensions/fixtures/fixtures_loader.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
'use strict'

/**
* @module extensions/fixtures/FixturesLoader
*/

const path = require('path')
const glob = require('glob')
const chalk = require('chalk')
const _ = require('lodash')

let fixturesDir = 'fixtures'
let featureUri = null

exports.configure = ({ fixturesDir: _fixturesDir = 'fixtures' } = {}) => {
fixturesDir = _fixturesDir
}

exports.setFeatureUri = _featureUri => {
featureUri = _featureUri
}

/**
* Tries to load a fixture from current feature directory.
* Will search for the following file extensions:
* - yaml
* - yml
* - js
* - json
* - txt
*
* @param {string} fixture - Fixture file name without extension
* @return {Promise.<Object|string>} Fixture content
*/
exports.load = fixture => {
if (featureUri === null) return Promise.reject()

const relativePath = path.relative(process.cwd(), path.dirname(featureUri))
const pattern = `${relativePath}/${fixturesDir}/${fixture}.@(yaml|yml|js|json|txt)`

return new Promise((resolve, reject) => {
glob(pattern, (err, files) => {
const fixturesCount = files.length

if (fixturesCount === 0) return reject(`No fixtures found for: ${fixture} (${pattern})`)
if (fixturesCount > 1) {
return reject(
[
`Found ${fixturesCount} matching fixture files, `,
`you should have only one matching '${fixture}':\n `,
`- ${files.join('\n - ')}`
].join('')
)
}
})
})
}

/**
* Resets fixtures loader.
*/
exports.reset = () => {
featureUri = null
}
14 changes: 14 additions & 0 deletions src/extensions/fixtures/hooks.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
'use strict'

/**
* Registers hooks for the fixtures extension.
*
* @module extensions/fixtures/hooks
*/

module.exports = ({ Before }) => {
Before(function(scenarioResult) {
this.fixtures.reset()
this.fixtures.setFeatureUri(scenarioResult.scenario.feature.uri)
})
}
51 changes: 51 additions & 0 deletions src/extensions/fixtures/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
'use strict'

/**
* @module extensions/fixtures
*/

const hooks = require('./hooks')

/**
* Extends cucumber world object.
* Must be used inside customWorldConstructor.
*
* @example
* // /support/world.js
*
* const { defineSupportCode } = require('cucumber')
* const { fixtures } = require('@ekino/veggies')
*
* defineSupportCode(({ setWorldConstructor }) => {
* setWorldConstructor(function() {
* fixtures.extendWorld(this)
* })
* })
*
* @function
* @param {Object} world - The cucumber world object
*/
exports.extendWorld = require('./extend_world')

/**
* Installs the extension.
*
* @example
* // /support/world.js
*
* const { defineSupportCode } = require('cucumber')
* const { fixtures } = require('@ekino/veggies')
*
* defineSupportCode(({ setWorldConstructor }) => {
* setWorldConstructor(function() {
* fixtures.extendWorld(this)
* })
* })
*
* fixtures.install(defineSupportCode)
*
* @param {Function} define - The `defineSupportCode` helper from cucumber
*/
exports.install = define => {
define(hooks)
}
7 changes: 7 additions & 0 deletions src/extensions/http_api/definitions.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,13 @@ module.exports = ({ baseUrl = '' } = {}) => ({ Given, When, Then }) => {
this.httpApiClient.setJsonBody(Cast.object(this.state.populateObject(step.rowsHash())))
})

/**
* Setting json payload from fixture file
*/
Given(/^(?:I )?set request json body from (.+)$/, function(fixture) {
return this.fixtures.load(fixture)
})

/**
* Setting form data
*/
Expand Down
1 change: 1 addition & 0 deletions src/fixtures_loader.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
'use strict'
1 change: 1 addition & 0 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
'use strict'

exports.state = require('./extensions/state')
exports.fixtures = require('./extensions/fixtures')
exports.httpApi = require('./extensions/http_api')
exports.cli = require('./extensions/cli')

0 comments on commit db0c460

Please sign in to comment.