egima egima - 1 month ago 14
Node.js Question

No request body in swagger-test

After a long search, I finally found swagger-test to be the best framework to test my REST services from a swagger spec. I followed the read me and the example in the Repo. This is my first

xamples
request/response pair.

"x-amples": [{
"description": "should save an object",
"request": {
"params": {
"app_id": "bengi",
"table_name": "Student",
"body": {
"collectionName": "Student",
"key": "mLiJB380x9893rjlaf0"
}
}
},
"response": {
"status": 200,
"headers": {
"content-type": "application/json"
}
}}]


app_id
and
table_name
are substituted very well in the
url
.

My problem is that the parameter
body
is never included in the http request. I know this because I have inspected the traffic from wireshark.

I am quite sure my specs are very okay because I have been running successful tests manually from Swagger-UI. Here is a screen shot of my console:
when I run the tests



Meaning my request is unauthorised due to missing
key
parameter which is in the request
body
above.

This is my js.js file called by
mocha
:

var swaggerTest = require('swagger-test');
var fs = require('fs');
var preq = require('preq');
var swaggerSpec;

var buffer = fs.readFileSync('cb.json');
swaggerSpec = JSON.parse(buffer);
var xamples = swaggerTest.parse(swaggerSpec);


describe('specification-driven tests', function () {
xamples.forEach(function (xample) {
it(xample.description, function() {
this.timeout(10000);
return preq[xample.request.method](xample.request)
.then(function (response) {
assert.deepEqual(response, xample.response);
});
});
});
});



What should I do to ensure that my request
body
is seen and used by
swagger-test
?

Answer

After several hours of crawling the web and getting no solution, I tried to go through the code and the modules used. This is what I found out that solved my problem:
My x-amples JSON is wrongly formatted, especially where I have placed my body element.
From my question

app_id and table_name are substituted very well in the url.

Well that is because of this line:

 var xamples = swaggerTest.parse(swaggerSpec);


from the test file.


The main function of swagger-test Is to parse the Swagger specification file and extract all x-ample elements into an array as demonstrated by this line:

var xamples = swaggerTest.parse(swaggerSpec);

This means swagger-test does its work perfectly i.e:

  1. Retrieve all x-ample extentions into an array.
  2. Substitute the values in params element:

    "request": {
        "params": {
            "app_id": "bengi",
            "table_name": "Student",
            "body": {
                "collectionName": "Student",
                "key": "mLiJB380x9893rjlaf0"
            }
        }
    }
    

    into the url template:

e>/data/{app_id}/{table_name}

  1. Concatenate the host,basePath and params from the swagger-spec and request JSON to form a complete uri.
    All this is done in this code snippet which does the donkey work in

    function parseXample(spec, uri, method, xample) {
    var uriTemplate = template.parse(uri);
    var expandedUri = uriTemplate.expand(xample.request.params);
    xample.request.method = method;
    xample.request.uri = spec.host + spec.basePath + expandedUri;
    return {
        description: xample.description || method + ' ' + uri,
        request: xample.request,
        response: xample.response
    };
    

    }


From my question:

My problem is that the parameter body is never included in the http request

The trick was in the preq module source code in the getOptions([url],[o],[method]) method.

    if (o.body && o.body instanceof Object) {
        if (o.headers && /^application\/json/.test(o.headers['content-     type'])) {
            o.body = JSON.stringify(o.body);
        } else if (o.method === 'post') {
            o.form = o.body;
            o.body = undefined;
        }
    }


Argument o is options that is the xample.request object passed to preq from my test code: return preqxample.request.method So it becomes clear that xample.request.body was in existent in my request object since it is at xample.request.params.body and consequently the condition if (o.body && o.body instanceof Object) does not pass and hence the assignment o.body=JSON.stringify(o.body) did not happen.
The final x-ample extension should look like this:

"x-amples": [{
    "description": "should save an object",
    "request": {
        "method": "put",
        "uri": "/data/{app_id}/{table_name}",
        "headers": {
            "content-type": "application/json"
        },
        "body": {
            "collectionName": "Student",
            "key": "xxxxxx"
        },
        "params": {
            "app_id": "xxxxxx",
            "table_name": "xxxxxx"
        }
    },
    "response": {
        "status": 200,
        "headers": {
            "content-type": "application/json"
        }
    }
}]


Apart from the location of the body element, you must include the headers element, else you get an error.

Comments