Skip to content

Commit

Permalink
feat: Support asserting redirect responses
Browse files Browse the repository at this point in the history
Updated the "receive status" step to not follow redirects if that is the status
code that is expected
  • Loading branch information
Philip Mander committed Aug 28, 2019
1 parent 2e4ba73 commit f1183c5
Show file tree
Hide file tree
Showing 6 changed files with 69 additions and 9 deletions.
8 changes: 8 additions & 0 deletions docs/step-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,14 @@ And I set the placeholder 'id' using the json path '$.[0].id' from the last 'GET
Ensure the response was received with a given status.
This should always be the first "Then" assertion.

#### Redirects
Normally, HTTP redirects will be handled opaquely; the redirect is followed and the resulting response is
asserted. However, if the status code to be asserted is a
[redirect status code](https://en.wikipedia.org/wiki/URL_redirection#HTTP_status_codes_3xx) the redirect
will not be followed.

To assert to response header for the "location" use the appropriate separate step

**Example**
```js
Then I should receive a response with the status 200
Expand Down
10 changes: 8 additions & 2 deletions src/steps-fn.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ const { expect } = chai;

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

const redirectStatuses = [ 301, 302, 303, 307, 308 ];

function defaultContentType(contentType) {
this.defaultContentType = contentType;
}
Expand Down Expand Up @@ -180,12 +182,16 @@ function populatePlaceholder(placeHolder, jsonPath, previousMethod, previousPath
});
}

async function receiveRequestWithStatus(status) {
async function receiveResponseWithStatus(status) {
// this sends the request
// (await will implictly call `then()` on the SuperAgent request object,
// which will implicitly send the request)
const startAt = process.hrtime();
try {
// don't follow redirects if that's what is expected
if(redirectStatuses.includes(status)) {
this.req.redirects(0);
}
this.req.use(this.replaceVariablesInitiator());
const res = await this.getResponse();
this.saveCurrentResponse();
Expand Down Expand Up @@ -298,7 +304,7 @@ module.exports = {
setRequestCookies,
setRequestHeaders,
populatePlaceholder,
receiveRequestWithStatus,
receiveResponseWithStatus,
receiveWithinTime,
receiveText,
responseHeaderEquals,
Expand Down
12 changes: 10 additions & 2 deletions src/steps.js
Original file line number Diff line number Diff line change
Expand Up @@ -387,6 +387,14 @@ function registerSteps({ Given, When, Then }) {
* Ensure the response was received with a given status.
* This should always be the first "Then" assertion.
*
* #### Redirects
* Normally, HTTP redirects will be handled opaquely; the redirect is followed and the resulting response is
* asserted. However, if the status code to be asserted is a
* [redirect status code](https://en.wikipedia.org/wiki/URL_redirection#HTTP_status_codes_3xx) the redirect
* will not be followed.
*
* To assert to response header for the "location" use the appropriate separate step
*
* @example
* Then I should receive a response with the status 200
*
Expand All @@ -395,10 +403,10 @@ function registerSteps({ Given, When, Then }) {
*
* @function receiveRequestWithStatus
*/
Then('I should receive a response with the status {int}', fn.receiveRequestWithStatus);
Then('I should receive a response with the status {int}', fn.receiveResponseWithStatus);

// short form
Then('receive status {int}', fn.receiveRequestWithStatus);
Then('receive status {int}', fn.receiveResponseWithStatus);

/**
* ### Then I should receive a response within {int}ms
Expand Down
13 changes: 13 additions & 0 deletions test/features/test-steps-short.feature
Original file line number Diff line number Diff line change
Expand Up @@ -242,3 +242,16 @@ Feature: API Testing Steps
"""
Then receive status 200
And json path at "$.data.addPet.id" should equal "3000"

@short
Scenario Outline: Scenario Outline name: Testing redirects
When GET "{base}/redirect/<status>"
Then receive status <status>

Examples:
| status |
| 301 |
| 302 |
| 303 |
| 307 |
| 308 |
28 changes: 23 additions & 5 deletions test/features/test-steps.feature
Original file line number Diff line number Diff line change
Expand Up @@ -223,10 +223,28 @@ Feature: API Testing Steps
And json path at "$.data.addPet.id" should equal "3000"

@long
Scenario: Testing errors
When GET "{base}/error/500"
Then receive status 500
Scenario Outline: Testing errors
When GET "{base}/error/<status>"
Then receive status <status>
And I should receive the text:
"""
{"message":"This is a 500 status"}
"""
{"message":"This is a <status> status"}
"""
Examples:
| status |
| 404 |
| 500 |


@long
Scenario Outline: Testing redirects
When GET "{base}/redirect/<status>"
Then I should receive a response with the status <status>

Examples:
| status |
| 301 |
| 302 |
| 303 |
| 307 |
| 308 |
7 changes: 7 additions & 0 deletions test/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,13 @@ app.get('/reset', function (req, res) {
res.send();
});

app.get('/redirect/:code', function (req, res, next) {
const { code } = req.params;
console.log(`Sending redirect: ${code}`)

res.redirect(parseInt(code, 10), `/redirect/${code}/redirected`);
});

app.get('/error/:code', function (req, res, next) {
const { code } = req.params;
const err = new Error(`This is a ${code} status`);
Expand Down

0 comments on commit f1183c5

Please sign in to comment.