Skip to content

Commit

Permalink
feat: Added step to assert json path values using a regex
Browse files Browse the repository at this point in the history
Added:

`the response body json path at {string} should match {string}`

and

`json path at {string} should match {string}`
  • Loading branch information
Philip Mander committed Jul 8, 2019
1 parent 91d156e commit 2718a5f
Show file tree
Hide file tree
Showing 9 changed files with 105 additions and 46 deletions.
17 changes: 17 additions & 0 deletions docs/step-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
* [~receiveText()](#module_steps..receiveText)
* [~responseHeaderEquals()](#module_steps..responseHeaderEquals)
* [~responseBodyJsonPathEquals()](#module_steps..responseBodyJsonPathEquals)
* [~responseBodyJsonPathMatches()](#module_steps..responseBodyJsonPathMatches)
* [~responseBodyJsonPathIsEmpty()](#module_steps..responseBodyJsonPathIsEmpty)
* [~responseCookieEquals()](#module_steps..responseCookieEquals)
* [~validateAgainstSpecSchema()](#module_steps..validateAgainstSpecSchema)
Expand Down Expand Up @@ -331,6 +332,18 @@ Then the response body json path at "$.[1].name" should equal "Rover"
```js
Then json path at "$.[1].name" should equal "Rover"
```
### Then the response body json path at {string} should match {string}
Ensure a JSON response body contains a given value at the JSON path.
See [http://goessner.net/articles/JsonPath/](http://goessner.net/articles/JsonPath/)

**Example**
```js
Then the response body json path at "$.[1].age" should match "\d+"
```
**Example** *(Short form)*
```js
Then json path at "$.[1].age" should match "\d+"
```
### Then the response body json path at {string} should be empty
Ensure the JSON path is empty.
See [http://goessner.net/articles/JsonPath/](http://goessner.net/articles/JsonPath/)
Expand All @@ -340,6 +353,10 @@ See [https://www.chaijs.com/api/bdd/#method_empty](https://www.chaijs.com/api/bd
```js
Then the response body json path at "$.[1].name" should be empty
```
**Example** *(Short form)*
```js
Then json path at "$.[1].name" should be empty
```
### Then I should receive a response that sets the cookie:

Asserts that a response sent a cookie to the client
Expand Down
7 changes: 4 additions & 3 deletions examples/features/hacker-news.feature
Original file line number Diff line number Diff line change
Expand Up @@ -24,16 +24,17 @@ Feature: Hacker News
@hn
Scenario: One
When GET "{base}/topstories.json"
Then I should receive a response with the status 200
Then receive status 200

@hn
Scenario: Two
And GET "{base}/item/{storyId}.json"
When GET "{base}/item/{storyId}.json"
And I set the placeholder 'storyId' using the json path '$.[0]' from the last 'GET' to '{base}/topstories.json'
Then receive status 200

@hn
Scenario: Three
And GET "{base}/user/{userId}.json"
When GET "{base}/user/{userId}.json"
And I set the placeholder 'userId' using the json path '$.by' from the last 'GET' to '{base}/item/{storyId}.json'
Then receive status 200
And json path at "$.karma" should match "\d+"
8 changes: 7 additions & 1 deletion package-lock.json

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

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
"devDependencies": {
"basic-auth": "^2.0.1",
"body-parser": "^1.18.3",
"chai-match": "^1.1.1",
"cookie-parser": "^1.4.3",
"cucumber": "^5.0.1",
"express": "^4.16.3",
Expand All @@ -51,4 +52,4 @@
"peerDependencies": {
"cucumber": "5.x"
}
}
}
13 changes: 12 additions & 1 deletion src/steps-fn.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.

const { expect } = require('chai');
const chai = require('chai');
const Ajv = require('ajv');
const cookie = require('cookie');
const JSONPath = require('jsonpath-plus');
Expand All @@ -25,6 +25,10 @@ const { promisify } = require('util');
const ql = require('superagent-graphql');
const readFileAsync = promisify(readFile);

chai.use(require('chai-match'));
const { expect } = chai;


const methodsWithBodies = ['POST', 'PUT', 'PATCH', 'DELETE'];

function defaultContentType(contentType) {
Expand Down Expand Up @@ -202,6 +206,12 @@ async function responseBodyJsonPathEquals(path, value) {
expect(actualValue).to.equal(this.replaceVars(value));
}

async function responseBodyJsonPathMatches(path, value) {
const { body } = await this.getResponse();
const actualValue = JSONPath.eval(body, path)[0];
expect(actualValue).to.match(new RegExp(value));
}

async function responseBodyJsonPathIsEmpty(path) {
const { body } = await this.getResponse();
const actualValue = JSONPath.eval(body, path)[0];
Expand Down Expand Up @@ -276,6 +286,7 @@ module.exports = {
receiveText,
responseHeaderEquals,
responseBodyJsonPathEquals,
responseBodyJsonPathMatches,
responseBodyJsonPathIsEmpty,
responseCookieEquals,
validateAgainstSpecSchema,
Expand Down
19 changes: 19 additions & 0 deletions src/steps.js
Original file line number Diff line number Diff line change
Expand Up @@ -469,6 +469,25 @@ function registerSteps({ Given, When, Then }) {
// short form
Then('json path at {string} should equal {string}', fn.responseBodyJsonPathEquals);

/**
* ### Then the response body json path at {string} should match {string}
* Ensure a JSON response body at the given JSON path, matches a regular expression.
* n.b. For simpliciy, Bat variables in regular expressions are not subsituted.
* See [http://goessner.net/articles/JsonPath/](http://goessner.net/articles/JsonPath/)
*
* @example
* Then the response body json path at "$.[1].age" should match "\d+"
*
* @example <caption>Short form</caption>
* Then json path at "$.[1].age" should match "\d+"
*
* @function responseBodyJsonPathMatches
*/
Then('the response body json path at {string} should match {string}', fn.responseBodyJsonPathMatches);

// short form
Then('json path at {string} should match {string}', fn.responseBodyJsonPathMatches);

/**
* ### Then the response body json path at {string} should be empty
* Ensure the JSON path is empty.
Expand Down
41 changes: 21 additions & 20 deletions test/features/test-steps-short.feature
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ Feature: API Testing Steps
And within 1000ms
And receive text:
"""
[{"id":"1000","type":"cat","name":"Felix"},{"id":"2000","type":"dog","name":"Rover"}]
[{"id":"1000","type":"cat","name":"Felix","age":10},{"id":"2000","type":"dog","name":"Rover","age":3}]
"""
And validate against schema
And validate against the schema:
Expand Down Expand Up @@ -83,6 +83,7 @@ Feature: API Testing Steps
}
"""
And json path at "$.[1].name" should equal "Rover"
And the response body json path at "$.[0].age" should match "\d{2}"
And the response header "Content-Language" should equal "en"

@short
Expand Down Expand Up @@ -202,41 +203,41 @@ Feature: API Testing Steps
@short
Scenario: Testing get all pets graphql query
When GraphQL:
"""
{
"""
{
pets {
id
name
type
id
name
type
}
}
}
"""
"""
Then receive status 200

@short
Scenario: Testing get single pet graphql query
When GraphQL:
"""
{
"""
{
pet (id:"1000") {
name
id
name
id
}
}
"""
}
"""
Then receive status 200
And json path at "$.data.pet.id" should equal "1000"

@short
Scenario: Testing add a new pet graphql mutation query
When GraphQL:
"""
mutation {
"""
mutation {
addPet (id:"3000", name:"bird", type:"Canary") {
name
id
name
id
}
}
"""
}
"""
Then receive status 200
And json path at "$.data.addPet.id" should equal "3000"
39 changes: 20 additions & 19 deletions test/features/test-steps.feature
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ Feature: API Testing Steps
And I should receive a response within 1000ms
And I should receive the text:
"""
[{"id":"1000","type":"cat","name":"Felix"},{"id":"2000","type":"dog","name":"Rover"}]
[{"id":"1000","type":"cat","name":"Felix","age":10},{"id":"2000","type":"dog","name":"Rover","age":3}]
"""
And the response body should validate against its schema
And the response body should validate against the schema:
Expand Down Expand Up @@ -83,6 +83,7 @@ Feature: API Testing Steps
}
"""
And the response body json path at "$.[1].name" should equal "Rover"
And the response body json path at "$.[0].age" should match "\d{2}"
And the response header "Content-Language" should equal "en"

@long
Expand Down Expand Up @@ -182,40 +183,40 @@ Feature: API Testing Steps
@long
Scenario: Testing get all pets graphql query
When I send the GraphQL query:
"""
{
"""
{
pets {
id
name
type
id
name
type
}
}
}
"""
"""
Then receive status 200

@long
Scenario: Testing get single pet graphql query
When I send the GraphQL query:
"""
{
"""
{
pet (id:"1000") {
name
id
name
id
}
}
"""
}
"""
Then receive status 200
And json path at "$.data.pet.id" should equal "1000"

@long
Scenario: Testing add a new pet graphql mutation query
When I send the GraphQL query:
"""
mutation {
"""
mutation {
addPet (id:"3000", name:"bird", type:"Canary") {
id
id
}
}
"""
}
"""
Then receive status 200
And json path at "$.data.addPet.id" should equal "3000"
4 changes: 3 additions & 1 deletion test/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ const app = express();

app.use(session({
secret: 'keyboard bat',
resave : true,
resave: true,
saveUninitialized: false,
}));

Expand All @@ -37,10 +37,12 @@ const pets = [{
id: '1000',
type: 'cat',
name: 'Felix',
age: 10,
}, {
id: '2000',
type: 'dog',
name: 'Rover',
age: 3,
}];

app.get('/pets', (req, res, next) => {
Expand Down

0 comments on commit 2718a5f

Please sign in to comment.