Writing Dredd Hooks In Node.js#
Usage#
$ dredd api-description.yaml http://127.0.0.1:30000 --hookfiles=./hooks*.js
API Reference#
For
before,after,beforeValidation,beforeEach,afterEachandbeforeEachValidationa Transaction Object is passed as the first argument to the hook function.An array of Transaction Objects is passed to
beforeAllandafterAll.The second argument is an optional callback function for async execution.
Any modifications on the
transactionobject are propagated to the actual HTTP transactions.You can use
hooks.logfunction inside the hook function to print yours debug messages and other information.configuration(docs) object is populated on thehooksobject
Sync API#
var hooks = require('hooks');
hooks.beforeAll(function (transactions) {
hooks.log('before all');
});
hooks.beforeEach(function (transaction) {
hooks.log('before each');
});
hooks.before("Machines > Machines collection > Get Machines", function (transaction) {
hooks.log("before");
});
hooks.beforeEachValidation(function (transaction) {
hooks.log('before each validation');
});
hooks.beforeValidation("Machines > Machines collection > Get Machines", function (transaction) {
hooks.log("before validation");
});
hooks.after("Machines > Machines collection > Get Machines", function (transaction) {
hooks.log("after");
});
hooks.afterEach(function (transaction) {
hooks.log('after each');
});
hooks.afterAll(function (transactions) {
hooks.log('after all');
})
Async API#
When the callback is used in the hook function, callbacks can handle asynchronous function calls.
var hooks = require('hooks');
hooks.beforeAll(function (transactions, done) {
hooks.log('before all');
done();
});
hooks.beforeEach(function (transaction, done) {
hooks.log('before each');
done();
});
hooks.before("Machines > Machines collection > Get Machines", function (transaction, done) {
hooks.log("before");
done();
});
hooks.beforeEachValidation(function (transaction, done) {
hooks.log('before each validation');
done();
});
hooks.beforeValidation("Machines > Machines collection > Get Machines", function (transaction, done) {
hooks.log("before validation");
done();
});
hooks.after("Machines > Machines collection > Get Machines", function (transaction, done) {
hooks.log("after");
done();
});
hooks.afterEach(function (transaction, done) {
hooks.log('after each');
done();
});
hooks.afterAll(function (transactions, done) {
hooks.log('after all');
done();
})
Examples#
How to Skip Tests#
Any test step can be skipped by setting skip property of the transaction object to true.
var before = require('hooks').before;
before("Machines > Machines collection > Get Machines", function (transaction) {
transaction.skip = true;
});
Failing Tests Programmatically#
You can fail any step by setting fail property on transaction object to true or any string with descriptive message.
var before = require('hooks').before;
before("Machines > Machines collection > Get Machines", function (transaction) {
transaction.fail = "Some failing message";
});
Using Chai Assertions#
Inside hook files, you can require Chai and use its assert, should or expect interface in hooks and write your custom expectations. Dredd catches Chai’s expectation error in hooks and makes transaction to fail.
var hooks = require('hooks');
var before = hooks.before;
var assert = require('chai').assert;
after("Machines > Machines collection > Get Machines", function (transaction) {
assert.isBelow(transaction.real.body.length, 100);
});
Modifying Transaction Request Body Prior to Execution#
var hooks = require('hooks');
var before = hooks.before;
before("Machines > Machines collection > Get Machines", function (transaction) {
// parse request body from API description
var requestBody = JSON.parse(transaction.request.body);
// modify request body here
requestBody['someKey'] = 'someNewValue';
// stringify the new body to request
transaction.request.body = JSON.stringify(requestBody);
});
Modifying Multipart Transaction Request Body Prior to Execution#
Dependencies:
const hooks = require('hooks');
const fs = require('fs');
const Multipart = require('multi-part');
const streamToString = require('stream-to-string');
var before = hooks.before;
before("Machines > Machines collection > Create Machines", async function (transaction, done) {
const form = new Multipart();
form.append('title', 'Foo');
form.append('photo', fs.createReadStream('./bar.jpg'));
transaction.request.body = await streamToString(form.getStream());
transaction.request.headers['Content-Type'] = form.getHeaders()['content-type'];
done();
});
Adding or Changing URI Query Parameters to All Requests#
var hooks = require('hooks');
hooks.beforeEach(function (transaction) {
// add query parameter to each transaction here
var paramToAdd = "api-key=23456"
if(transaction.fullPath.indexOf('?') > -1){
transaction.fullPath += "&" + paramToAdd;
} else{
transaction.fullPath += "?" + paramToAdd;
}
});
Handling sessions#
var hooks = require('hooks');
var stash = {};
// hook to retrieve session on a login
hooks.after('Auth > /remoteauth/userpass > POST', function (transaction) {
stash['token'] = JSON.parse(transaction.real.body)['sessionId'];
});
// hook to set the session cookie in all following requests
hooks.beforeEach(function (transaction) {
if(stash['token'] != undefined){
transaction.request['headers']['Cookie'] = "id=" + stash['token'];
};
});
Remove trailing newline character in expected plain text bodies#
var hooks = require('hooks');
hooks.beforeEach(function(transaction) {
if (transaction.expected.headers['Content-Type'] === 'text/plain') {
transaction.expected.body = transaction.expected.body.replace(/^\s+|\s+$/g, "");
}
});
Using Babel#
You can use Babel for support of all the latest JS syntactic coolness in Dredd by using babel-register:
npm install -g babel-register @babel/preset-env
echo '{ "presets": [["env", { "target": { "node":6 } }]] }' > .babelrc
dredd test/fixtures/single-get.yaml http://127.0.0.1:3000 --hookfiles=./es2015.js --require=@babel/register
Using CoffeScript#
You can use CoffeeScript in hooks by registering it as a compiler.
dredd test/fixtures/single-get.yaml http://127.0.0.1:3000 --hookfiles=./hooks.coffee --require=coffeescript/register