bitter-apple
Advanced tools
Comparing version 1.7.0 to 1.7.1
@@ -148,2 +148,18 @@ /* jslint node: true */ | ||
this.Then(/^response body at path (.*) should be a json array$/, function(path, callback) { | ||
if (this.bitterapple.assertResponseBodyIsArray(path)) { | ||
callback(); | ||
} else { | ||
callback(new Error('response body is ' + this.bitterapple.getRealValue())); | ||
} | ||
}); | ||
this.Then(/^response body at path (.*) should be an array of length (\d+)$/, function(path, value, callback) { | ||
if (this.bitterapple.assertResponseBodyIsArrayOfLength(path, value)) { | ||
callback(); | ||
} else { | ||
callback(new Error('response body is ' + this.bitterapple.getRealValue())); | ||
} | ||
}); | ||
this.Then(/^response code should be (\d+)$/, function(responseCode, callback) { | ||
@@ -150,0 +166,0 @@ if (this.bitterapple.assertResponseCode(responseCode)) { |
@@ -5,3 +5,3 @@ /* jslint node: true */ | ||
var request = require('request'); | ||
var jsonPath = require('JSONPath'); | ||
var jsonPath = require('jsonpath-plus'); | ||
var select = require('xpath.js'); | ||
@@ -30,3 +30,3 @@ var dom = require('xmldom').DOMParser; | ||
BitterApple.prototype.getRealValue = function() { | ||
var valueAsString = util.inspect(this.realValue) | ||
var valueAsString = util.inspect(this.realValue); | ||
return '\x1b[31m ' + valueAsString + ' \x1b[0m ' ; // ANSI COLOR codes for red and reset attributes | ||
@@ -75,3 +75,3 @@ }; | ||
BitterApple.prototype.get = function(resource, callback) { // callback(error, response) | ||
BitterApple.prototype.get = function(resource, callback) { | ||
resource = replaceVariables(resource, this.scenarioVariables); | ||
@@ -81,3 +81,4 @@ var self = this; | ||
url: this.domain + resource, | ||
headers: this.headers | ||
headers: this.headers, | ||
followRedirect: false | ||
}, | ||
@@ -95,3 +96,3 @@ function(error, response) { | ||
BitterApple.prototype.post = function(resource, callback) { // callback(error, response) | ||
BitterApple.prototype.post = function(resource, callback) { | ||
resource = replaceVariables(resource, this.scenarioVariables); | ||
@@ -103,2 +104,3 @@ var self = this; | ||
body: this.requestBody, | ||
followRedirect: false, | ||
method: 'POST' | ||
@@ -116,3 +118,3 @@ }, | ||
BitterApple.prototype.put = function(resource, callback) { // callback(error, response) | ||
BitterApple.prototype.put = function(resource, callback) { | ||
resource = replaceVariables(resource, this.scenarioVariables); | ||
@@ -123,2 +125,3 @@ var self = this; | ||
headers: this.headers, | ||
followRedirect: false, | ||
body: this.requestBody, | ||
@@ -137,3 +140,3 @@ method: 'PUT' | ||
BitterApple.prototype.delete = function(resource, callback) { // callback(error, response) | ||
BitterApple.prototype.delete = function(resource, callback) { | ||
resource = replaceVariables(resource, this.scenarioVariables); | ||
@@ -144,2 +147,3 @@ var self = this; | ||
headers: this.headers, | ||
followRedirect: false, | ||
body: this.requestBody, | ||
@@ -158,3 +162,3 @@ method: 'DELETE' | ||
BitterApple.prototype.patch = function(resource, callback) { // callback(error, response) | ||
BitterApple.prototype.patch = function(resource, callback) { | ||
resource = replaceVariables(resource, this.scenarioVariables); | ||
@@ -165,2 +169,3 @@ var self = this; | ||
headers: this.headers, | ||
followRedirect: false, | ||
body: this.requestBody, | ||
@@ -235,2 +240,13 @@ method: 'PATCH' | ||
BitterApple.prototype.assertResponseBodyIsArray = function(path) { | ||
this.realValue = this.getResponseObject().body; | ||
return Array.isArray(evaluatePath(path, this.realValue)); | ||
}; | ||
BitterApple.prototype.assertResponseBodyIsArrayOfLength = function(path, value) { | ||
this.realValue = this.getResponseObject().body; | ||
var evaluatedValue = evaluatePath(path, this.realValue); | ||
return Array.isArray(evaluatedValue) && evaluatedValue.length === 2; | ||
}; | ||
BitterApple.prototype.evaluatePathInResponseBody = function(path) { | ||
@@ -355,3 +371,3 @@ return evaluatePath(path, this.getResponseObject().body); | ||
var contentJson = JSON.parse(content); | ||
return jsonPath.eval(contentJson, path); | ||
return jsonPath({ flatten: true, json: contentJson, path: path }); | ||
case 'xml': | ||
@@ -358,0 +374,0 @@ var xmlDocument = new dom().parseFromString(content); |
{ | ||
"name": "bitter-apple", | ||
"version": "1.7.0", | ||
"version": "1.7.1", | ||
"description": "Collection of utility functions and a gherkin framework for WEB API integration testing based on cucumber.js", | ||
@@ -24,6 +24,6 @@ "main": "bitter-apple.js", | ||
"dependencies": { | ||
"JSONPath": "^0.10.0", | ||
"request": "^2.55.0", | ||
"xmldom": "^0.1.19", | ||
"xpath.js": "^1.0.6" | ||
"xpath.js": "^1.0.6", | ||
"jsonpath-plus": "^0.13.0" | ||
}, | ||
@@ -30,0 +30,0 @@ "devDependencies": { |
201
README.md
@@ -60,8 +60,8 @@ # bitterapple - REST API integration testing framework with cucumber.js | ||
{ | ||
"name": "myapi-test", | ||
"version": "1.0.0", | ||
"description": "Integration testing for myapi v1", | ||
"dependencies": { | ||
"bitterapple": "latest" | ||
} | ||
"name": "myapi-test", | ||
"version": "1.0.0", | ||
"description": "Integration testing for myapi v1", | ||
"dependencies": { | ||
"bitterapple": "latest" | ||
} | ||
} | ||
@@ -84,9 +84,9 @@ ``` | ||
Feature: | ||
Httpbin.org exposes various resources for HTTP request testing | ||
As Httpbin client I want to verify that all API resources are working as they should | ||
Httpbin.org exposes various resources for HTTP request testing | ||
As Httpbin client I want to verify that all API resources are working as they should | ||
Scenario: Setting headers in GET request | ||
Given I set User-Agent header to bitterapple | ||
When I GET /get | ||
Then response body path $.headers.User-Agent should be bitterapple | ||
Scenario: Setting headers in GET request | ||
Given I set User-Agent header to bitterapple | ||
When I GET /get | ||
Then response body path $.headers.User-Agent should be bitterapple | ||
``` | ||
@@ -109,7 +109,7 @@ | ||
module.exports = function() { | ||
// cleanup before every scenario | ||
this.Before(function(callback) { | ||
this.bitterapple = new bitterapple.BitterApple('http', 'httpbin.org'); | ||
callback(); | ||
}); | ||
// cleanup before every scenario | ||
this.Before(function(scenario, callback) { | ||
this.bitterapple = new bitterapple.BitterApple('http', 'httpbin.org'); | ||
callback(); | ||
}); | ||
}; | ||
@@ -129,2 +129,5 @@ ``` | ||
## Step timeout | ||
Cucumber.js default step timeout is 5000ms. Follow [this guide](https://github.com/cucumber/cucumber-js#timeouts) to change it for your steps. | ||
## Grunt integration | ||
@@ -140,14 +143,14 @@ | ||
module.exports = function(grunt) { | ||
grunt.initConfig({ | ||
cucumberjs: { | ||
src: 'features', | ||
options: { | ||
format: 'pretty', | ||
steps: 'features/step_definitions' | ||
} | ||
} | ||
}); | ||
grunt.initConfig({ | ||
cucumberjs: { | ||
src: 'features', | ||
options: { | ||
format: 'pretty', | ||
steps: 'features/step_definitions' | ||
} | ||
} | ||
}); | ||
grunt.loadNpmTasks('grunt-cucumber'); | ||
grunt.registerTask('tests', ['cucumberjs']); | ||
grunt.loadNpmTasks('grunt-cucumber'); | ||
grunt.registerTask('tests', ['cucumberjs']); | ||
} | ||
@@ -159,9 +162,9 @@ ``` | ||
```json | ||
... | ||
"dependencies": { | ||
"bitterapple": "latest", | ||
"grunt": "latest", | ||
"grunt-cucumber": "latest" | ||
} | ||
... | ||
... | ||
"dependencies": { | ||
"bitterapple": "latest", | ||
"grunt": "latest", | ||
"grunt-cucumber": "latest" | ||
} | ||
... | ||
``` | ||
@@ -208,6 +211,6 @@ | ||
return gulp.src('features/*') | ||
.pipe(cucumber({ | ||
'steps': 'features/step_definitions/*.js', | ||
'format': 'pretty' | ||
})); | ||
.pipe(cucumber({ | ||
'steps': 'features/step_definitions/*.js', | ||
'format': 'pretty' | ||
})); | ||
}); | ||
@@ -219,4 +222,4 @@ ``` | ||
... | ||
"gulp": "latest", | ||
"gulp-cucumber": "latest" | ||
"gulp": "latest", | ||
"gulp-cucumber": "latest" | ||
... | ||
@@ -246,61 +249,63 @@ ``` | ||
``` | ||
GIVEN: | ||
I set (.*) header to (.*) | ||
I set body to (.*) | ||
I pipe contents of file (.*) to body | ||
I have basic authentication credentials (.*) and (.*) | ||
I set bearer token | ||
I set (.*) header to scenario variable (.*) | ||
I set (.*) header to global variable (.*) | ||
WHEN: | ||
I GET $resource | ||
I POST to $resource | ||
I PUT $resource | ||
I PATCH $resource | ||
I DELETE $resource | ||
I POST to $resource with body | ||
""" | ||
(.*) | ||
""" | ||
I PUT $resource with body | ||
""" | ||
(.*) | ||
""" | ||
I PATCH $resource with body | ||
""" | ||
(.*) | ||
""" | ||
I DELETE $resource with body | ||
""" | ||
(.*) | ||
""" | ||
GIVEN: | ||
I set (.*) header to (.*) | ||
I set body to (.*) | ||
I pipe contents of file (.*) to body | ||
I have basic authentication credentials (.*) and (.*) | ||
I set bearer token | ||
I set (.*) header to scenario variable (.*) | ||
I set (.*) header to global variable (.*) | ||
THEN: | ||
response header (.*) should exist | ||
response header (.*) should not exist | ||
response body should be valid (xml|json) | ||
response code should be (\d+) | ||
response code should not be (\d+) | ||
response header (.*) should be (.*) | ||
response header (.*) should not be (.*) | ||
response body should contain (.*) | ||
response body should not contain (.*) | ||
response body path (.*) should be (.*) | ||
response body path (.*) should not be (.*) | ||
I store the value of body path (.*) as access token | ||
I store the value of header (.*) as access token | ||
I store the value of response header (.*) as (.*) in scenario scope | ||
I store the value of body path (.*) as (.*) in scenario scope | ||
value of scenario variable (.*) should be (.*) | ||
value of global variable (.*) should be (.*) | ||
I store the value of response header (.*) as (.*) in global scope | ||
I store the value of body path (.*) as (.*) in global scope | ||
the JSON should be | ||
""" | ||
(.*) | ||
""" | ||
``` | ||
WHEN: | ||
I GET $resource | ||
I POST to $resource | ||
I PUT $resource | ||
I PATCH $resource | ||
I DELETE $resource | ||
I POST to $resource with body | ||
""" | ||
(.*) | ||
""" | ||
I PUT $resource with body | ||
""" | ||
(.*) | ||
""" | ||
I PATCH $resource with body | ||
""" | ||
(.*) | ||
""" | ||
I DELETE $resource with body | ||
""" | ||
(.*) | ||
""" | ||
THEN: | ||
response header (.*) should exist | ||
response header (.*) should not exist | ||
response body should be valid (xml|json) | ||
response code should be (\d+) | ||
response code should not be (\d+) | ||
response header (.*) should be (.*) | ||
response header (.*) should not be (.*) | ||
response body should contain (.*) | ||
response body should not contain (.*) | ||
response body at path (.*) should be a json array | ||
response body at path (.*) should be an array of length (\d+) | ||
response body path (.*) should be (.*) | ||
response body path (.*) should not be (.*) | ||
I store the value of body path (.*) as access token | ||
I store the value of header (.*) as access token | ||
I store the value of response header (.*) as (.*) in scenario scope | ||
I store the value of body path (.*) as (.*) in scenario scope | ||
value of scenario variable (.*) should be (.*) | ||
value of global variable (.*) should be (.*) | ||
I store the value of response header (.*) as (.*) in global scope | ||
I store the value of body path (.*) as (.*) in global scope | ||
the JSON should be | ||
""" | ||
(.*) | ||
""" | ||
The simplest way to adopt these expressions is to create a symlink from node_modules/bitterapple/bitterapple-gherkin.js to features/step_definitions/bitterapple-gherkin.js | ||
@@ -312,4 +317,6 @@ | ||
If using Windows, follow this guide to create a symlink: [How-To Geek Guide](http://www.howtogeek.com/howto/16226/complete-guide-to-symbolic-links-symlinks-on-windows-or-linux/). | ||
## Contributing | ||
If you have any comments or suggestions, feel free to raise [an issue](https://github.com/bitterapple/bitterapple/issues) or fork the project and issue a pull request with suggested improvements. |
33463
596
313
+ Addedjsonpath-plus@^0.13.0
+ Addedjsonpath-plus@0.13.1(transitive)
- RemovedJSONPath@^0.10.0
- RemovedJSONPath@0.10.0(transitive)
- Removedunderscore@1.13.6(transitive)