Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 43 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -1262,6 +1262,48 @@ publishBatchMessage(config)(options)

This library also ships with test helpers available through a separate module `@quickcase/node-toolkit/test` under the `@quickcase/node-toolkit` package.

#### givenMiddleware(middleware).then(req).expect[Response|Next]()

Asynchronous function encapsulating the execution of an Express middleware for test purpose.

##### Arguments

| Name | Type | Description |
|------|------|-------------|
| middleware | function | Required. Express middleware function taking 3 parameters: req, res, next |
| req | object | Required. Request object to be passed to middleware |

##### Returns

When executed with `.expectResponse()`:
- returns a `Promise` resolved with the response details if a response was sent with `res.send()` or `res.json()`
- returns a `Promise` rejected with the value of `next()` if the `next()` callback was called

When executed with `.expectNext()`:
- returns a `Promise` resolved with the value of `next()` if the `next()` callback was called
- returns a `Promise` rejected with the response details if a response was sent with `res.send()` or `res.json()`

##### Example

```js
import {givenMiddleware} from '@quickcase/node-toolkit/test';

test('should resolve with response when response expected', async () => {
const middleware = (req, res) => res.status(201).json({foo: 'bar'});
const res = await givenMiddleware(middleware).when({}).expectResponse();
expect(res).toEqual({
status: 201,
body: {foo: 'bar'},
});
});

test('should resolve with next when next expected', async () => {
const middleware = (req, res, next) => next('error');
const next = await givenMiddleware(middleware).when({}).expectNext();
expect(next).toEqual('error');
});
```

#### stubConfig(config)

Programatically creates a stub of a [lorenwest/node-config](https://github.com/lorenwest/node-config) config instance.
Expand All @@ -1271,7 +1313,7 @@ The stub comes with support for the following methods:
- `get(property)`
- `has(property)`

#### Example
##### Example

```js
import {stubConfig} from '@quickcase/node-toolkit/test';
Expand Down
44 changes: 44 additions & 0 deletions src/test-modules/express.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/**
* Asynchronous function encapsulating the execution of an Express middleware for test purpose.
* @param {function} middleware Express middleware function taking 3 parameters: req, res, next
* @param {object} req Express request object
* @param {boolean} expectResponse Whether a response is expected, defaults to
* `false` which implies a call to next is expected instead
* @return Promise resolved or rejected depending on whether a response or next was expected
*/
export const expectMiddleware = (middleware, req, expectResponse = false) => new Promise((resolve, reject) => {
const resolveResponse = expectResponse ? resolve : reject;
const next = expectResponse ? (error) => reject({
message: 'Unexpected call to next()',
error,
}) : resolve;

let response = {status: 200};

const res = {};
res.status = (code) => (response.status = code, res);
res.json = (body) => (response.body = body, resolveResponse(response));
res.send = () => resolveResponse(response);

middleware(req, res, next);
});

/**
* Syntactic sugar over {@link expectMiddleware} to provide arguments in a
* given/when/expect fashion.
* @param {function} middleware Express middleware function acception 3 parameters: req, res, next
* @return {object} Object with `when` property containing function {@link whenMiddleware}
*/
export const givenMiddleware = (middleware) => ({when: whenMiddleware(middleware)});

/**
* Syntactic sugar over {@link expectMiddleware} to provide arguments in a
* when/expect fashion.
* @param {function} middleware Express middleware function acception 3 parameters: req, res, next
* @param {object} req Express request object
* @return {object} Object with `expectResponse` and `expectNext` functions, both executing {@link expectMiddleware}
*/
export const whenMiddleware = (middleware) => (req) => ({
expectResponse: () => expectMiddleware(middleware, req, true),
expectNext: () => expectMiddleware(middleware, req, false),
});
61 changes: 61 additions & 0 deletions src/test-modules/express.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import {expectMiddleware, givenMiddleware} from './express';

describe('expectMiddleware', () => {
test('should resolve with response when response expected', async () => {
const middleware = (req, res) => res.status(201).json({foo: 'bar'});
const res = await expectMiddleware(middleware, {}, true);
expect(res).toEqual({
status: 201,
body: {foo: 'bar'},
});
});

test('should reject with response when response not expected', async () => {
const middleware = (req, res) => res.send();
await expect(expectMiddleware(middleware, {}, false)).rejects.toEqual({status: 200});
});

test('should resolve with next when next expected', async () => {
const middleware = (req, res, next) => next('error');
const next = await expectMiddleware(middleware, {});
expect(next).toEqual('error');
});

test('should reject with next when next not expected', async () => {
const middleware = (req, res, next) => next('next-error');
await expect(expectMiddleware(middleware, {}, true)).rejects.toEqual({
error: 'next-error',
message: 'Unexpected call to next()',
});
});
});

describe('givenMiddleware', () => {
test('should resolve with response when response expected', async () => {
const middleware = (req, res) => res.status(201).json({foo: 'bar'});
const res = await givenMiddleware(middleware).when({}).expectResponse();
expect(res).toEqual({
status: 201,
body: {foo: 'bar'},
});
});

test('should reject with response when response not expected', async () => {
const middleware = (req, res) => res.send();
await expect(givenMiddleware(middleware).when({}).expectNext()).rejects.toEqual({status: 200});
});

test('should resolve with next when next expected', async () => {
const middleware = (req, res, next) => next('error');
const next = await givenMiddleware(middleware).when({}).expectNext();
expect(next).toEqual('error');
});

test('should reject with next when next not expected', async () => {
const middleware = (req, res, next) => next('next-error');
await expect(givenMiddleware(middleware).when({}).expectResponse()).rejects.toEqual({
error: 'next-error',
message: 'Unexpected call to next()',
});
});
});
1 change: 1 addition & 0 deletions src/test-modules/index.js
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export * from './express';
export * from './node-config';