apiaryio / dredd

Language-agnostic HTTP API Testing Tool
https://dredd.org
MIT License
4.2k stars 280 forks source link

How to use blueprint for resource creates when id is provisioned by server? #96

Closed gobengo closed 9 years ago

gobengo commented 10 years ago

Hey, I have the following in my blueprint.

I'm trying to 'create a new app'. When I do this, the server provisions and id and includes it in the response body JSON. It also includes a location header in the response which is a relative URL to the newly created app resource. This location header should be considered opaque, but happens to be using the newly provisioned id.

### Create New App [POST]

Create a new app

Requires authorization to create apps. App creator is the subject of the access
token.

+ Request

    + Headers

            Content-Type: application/json

    + Body

            {
                "name": "example-map",
                "version": "0.0.0"
            }

+ Request

    + Headers

            Content-Type: application/json

    + Body

            {
                "version": "0.0.0"
                "elements": [{
                    "component": {
                        "name": "streamhub-wall"
                    }
                }]
            }

+ Response 201

    + Headers

            location: /apps/5408ddd782f3910000000004

    + Body

            {
                "id": "5408ddbb82f3910000000002",
                "url": "/apps/5408ddbb82f3910000000002"
            }

Whenever I run dredd against this, it fails because the location header in practice is some id other than what's in the blueprint.

Is there any way to author my blueprint to ensure that the location header is present in the response, but not fail the thing just because it's a new unique id?

fail: headers: Value of the ‘location’ must be /apps/5408ddd782f3910000000004.

request: 
body: 
{
  "name": "example-map",
  "version": "0.0.0"
}
headers: 
    Content-Type: application/json
    User-Agent: Dredd/0.3.9 (Darwin 13.3.0; x64)
    Content-Length: 54

uri: /apps/
method: POST

expected: 
headers: 
    location: /apps/5408ddd782f3910000000004

body: 
{
    "id": "5408ddbb82f3910000000002",
    "url": "/apps/5408ddbb82f3910000000002"
}

statusCode: 201

actual: 
statusCode: 201
headers: 
    access-control-allow-origin: *
    location: /apps/5408e0ec82f3910000000012
    content-type: application/json; charset=utf-8
    content-length: 81
    date: Thu, 04 Sep 2014 22:00:12 GMT
    connection: keep-alive

body: 
{
  "id": "5408e0ec82f3910000000012",
  "url": "/apps/5408e0ec82f3910000000012"
}
netmilk commented 10 years ago

HI, this will be solve in next release of Dredd respectively Gavel which is used in Dredd for validating HTTP messages. Only value of content-type headers will be validated. Other header values will not be validated, so your location header will pass.

gobengo commented 10 years ago

@netmilk Would that help at all with trying to do a flow where I create a resource, the server provisions an id and responds with it, and another endpoint is exposed at a path that needs that dynamic ID passed to it?

ghost commented 10 years ago

+1 to this feature. It'll very useful.

when is the next version scheduled?

surtich commented 10 years ago

+1 I would like this too. Other similar things can be solved with hooks. But I think hooks are not useful in this case.

netmilk commented 10 years ago

Hi, this can be solved by creating response stash in hooks and replacing expected header value in the transaction before its execution.

netmilk commented 9 years ago

Reopening after discussion in #108

stephanheinze commented 9 years ago

:+1:

netmilk commented 9 years ago

Hi,

we recently changed the way how we validate headers in Gavel, please refer to: https://github.com/apiaryio/gavel.js/pull/53. Only values of content-negotiation significant headers are treated as constants. This functionality is in Dredd > 0.4.8.

For example: value of the Location header can be different in real response then given in blueprint.

This should fix this issue when you rely on data provisioned by server and you have no way how to retrieve it and modify expectation in before hooks.

Adam