Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

mockyeah

Package Overview
Dependencies
Maintainers
1
Versions
52
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

mockyeah - npm Package Compare versions

Comparing version 0.15.9 to 0.16.0

.editorconfig

59

app/index.js

@@ -5,2 +5,4 @@ 'use strict';

const bodyParser = require('body-parser');
const proxy = require('http-proxy-middleware');
const async = require('async');
const Logger = require('./lib/Logger');

@@ -26,4 +28,8 @@ const RouteManager = require('./lib/RouteManager');

const globalConfig = {};
if (global.MOCKYEAH_SUPPRESS_OUTPUT !== undefined) globalConfig.output = !global.MOCKYEAH_SUPPRESS_OUTPUT;
if (global.MOCKYEAH_VERBOSE_OUTPUT !== undefined) globalConfig.verbose = !!global.MOCKYEAH_VERBOSE_OUTPUT;
if (global.MOCKYEAH_SUPPRESS_OUTPUT !== undefined) {
globalConfig.output = !global.MOCKYEAH_SUPPRESS_OUTPUT;
}
if (global.MOCKYEAH_VERBOSE_OUTPUT !== undefined) {
globalConfig.verbose = !!global.MOCKYEAH_VERBOSE_OUTPUT;
}

@@ -46,12 +52,53 @@ // Prepare configuration. Merge configuration with global and default configuration

app.get('/', (req, res) => {
res.send('Hello, mockyeah!');
});
app.use(bodyParser.json());
app.middlewares = [];
// A single middleware to execute any/all consumer-configured middleware.
app.use((req, res, next) => {
async.series(app.middlewares.map(middleware => cb => middleware(req, res, cb)), err =>
next(err)
);
});
// Attach RouteManager to app object, the primary set of mockyeah API methods.
app.routeManager = new RouteManager(app);
app.use(bodyParser.json());
app.use('/', (req, res, next) => {
if (!app.proxying) {
next();
return;
}
app.get('/', (req, res) => {
res.send('Hello, mockyeah!');
const reqPath = req.path.replace(/^\//, '');
const target = reqPath;
const middleware = proxy({
target,
changeOrigin: true,
logLevel: 'silent', // TODO: Sync with mockyeah settings.
ignorePath: true
});
middleware(req, res, next);
});
app.proxy = on => {
app.proxying = typeof on !== 'undefined' ? on : true;
};
app.reset = () => {
app.routeManager.reset();
app.proxying = false;
app.middlewares = [];
};
app.use = middleware => {
app.middlewares.push(middleware);
};
return app;
};
};

6

app/lib/CapturePlayer.js

@@ -14,3 +14,3 @@ 'use strict';

const hiddenFileName = /^\./;
return fileNames.filter((fileName) => {
return fileNames.filter(fileName => {
return !hiddenFileName.test(fileName);

@@ -62,3 +62,3 @@ });

return fileNames.map((fileName) => {
return fileNames.map(fileName => {
const filePath = path.resolve(this.path, fileName);

@@ -82,2 +82,2 @@ let route;

module.exports = CapturePlayer;
module.exports = CapturePlayer;

@@ -10,3 +10,3 @@ 'use strict';

const tildify = require('tildify');
const now = () => (new Date()).getTime();
const now = () => new Date().getTime();

@@ -32,3 +32,3 @@ /**

function writeFile(filePath, data) {
function writeFile(filePath, data, cb) {
data = {

@@ -46,3 +46,3 @@ method: data.request.method,

fs.writeFile(filePath, JSON.stringify(data, null, 2));
fs.writeFile(filePath, JSON.stringify(data, null, 2), cb);
}

@@ -67,8 +67,12 @@

response.latency = now() - startTime;
writeFile(filePath, response);
this.app.log(['record', 'response', 'saved'], url);
++this.count;
writeFile(filePath, response, () => {
if (error) return this.app.log(['record', 'response', 'error'], error);
this.app.log(['record', 'response', 'saved'], url);
++this.count;
});
}).pipe(res);
};
module.exports = CaptureRecorder;
module.exports = CaptureRecorder;

@@ -20,3 +20,3 @@ 'use strict';

this.called += 1;
this.handlers.forEach((handler) => {
this.handlers.forEach(handler => {
this.assertions.push(handler.bind(this, req));

@@ -33,3 +33,10 @@ });

internal.assertions.push(() => {
assert(internal.called >= number, `${internal.prefix} Expected route to be called at least ${number} times, but it was called ${internal.called} times`);
assert(
internal.called >= number,
`${
internal.prefix
} Expected route to be called at least ${number} times, but it was called ${
internal.called
} times`
);
});

@@ -40,3 +47,10 @@ return this;

internal.assertions.push(() => {
assert(internal.called <= number, `${internal.prefix} Expected route to be called at most ${number} times, but it was called ${internal.called} times`);
assert(
internal.called <= number,
`${
internal.prefix
} Expected route to be called at most ${number} times, but it was called ${
internal.called
} times`
);
});

@@ -47,3 +61,8 @@ return this;

internal.assertions.push(() => {
assert(internal.called === 0, `${internal.prefix} Expected route to be called never, but it was called ${internal.called} times`);
assert(
internal.called === 0,
`${internal.prefix} Expected route to be called never, but it was called ${
internal.called
} times`
);
});

@@ -54,3 +73,8 @@ return this;

internal.assertions.push(() => {
assert(internal.called === 1, `${internal.prefix} Expected route to be called once, but it was called ${internal.called} times`);
assert(
internal.called === 1,
`${internal.prefix} Expected route to be called once, but it was called ${
internal.called
} times`
);
});

@@ -61,3 +85,8 @@ return this;

internal.assertions.push(() => {
assert(internal.called === 2, `${internal.prefix} Expected route to be called twice, but it was called ${internal.called} times`);
assert(
internal.called === 2,
`${internal.prefix} Expected route to be called twice, but it was called ${
internal.called
} times`
);
});

@@ -68,3 +97,8 @@ return this;

internal.assertions.push(() => {
assert(internal.called === 3, `${internal.prefix} Expected route to be called thrice, but it was called ${internal.called} times`);
assert(
internal.called === 3,
`${internal.prefix} Expected route to be called thrice, but it was called ${
internal.called
} times`
);
});

@@ -75,3 +109,8 @@ return this;

internal.assertions.push(() => {
assert(internal.called === number, `${internal.prefix} Expected route to be called ${number} times, but it was called ${internal.called} times`);
assert(
internal.called === number,
`${internal.prefix} Expected route to be called ${number} times, but it was called ${
internal.called
} times`
);
});

@@ -81,5 +120,9 @@ return this;

header: function header(name, value) {
internal.handlers.push((req) => {
internal.handlers.push(req => {
const actualValue = req.get(name);
assert.equal(actualValue, value, `${internal.prefix} Expected header value ${name}:${value}, but it was ${actualValue}`);
assert.equal(
actualValue,
value,
`${internal.prefix} Expected header value ${name}:${value}, but it was ${actualValue}`
);
});

@@ -89,4 +132,8 @@ return this;

params: function params(value) {
internal.handlers.push((req) => {
assert.deepStrictEqual(req.query, value, `${internal.prefix} Expected params did not match expected for request`);
internal.handlers.push(req => {
assert.deepStrictEqual(
req.query,
value,
`${internal.prefix} Expected params did not match expected for request`
);
});

@@ -96,4 +143,8 @@ return this;

body: function body(value) {
internal.handlers.push((req) => {
assert.deepStrictEqual(req.body, value, `${internal.prefix} Expected body to match expected for request`);
internal.handlers.push(req => {
assert.deepStrictEqual(
req.body,
value,
`${internal.prefix} Expected body to match expected for request`
);
});

@@ -103,3 +154,3 @@ return this;

verify: function verify() {
internal.assertions.forEach((assertion) => assertion());
internal.assertions.forEach(assertion => assertion());
}

@@ -106,0 +157,0 @@ };

@@ -75,3 +75,3 @@ 'use strict';

// Add timestamp to message
args.types.unshift((new Date()).toLocaleTimeString('en-US', { hour12: false }));
args.types.unshift(new Date().toLocaleTimeString('en-US', { hour12: false }));

@@ -86,2 +86,2 @@ // Prepare string of types for output

module.exports = Logger;
module.exports = Logger;

@@ -6,10 +6,10 @@ 'use strict';

const CaptureRecorder = require('./CaptureRecorder');
const RouteStore = require('./RouteStore');
const RouteResolver = require('./RouteResolver');
/**
* RouteManager
* Primary mockyeah API (i.e. get, post, put, delete, reset, record, play).
* Primary mockyeah API (i.e. get, post, put, patch, delete, reset, record, play).
*/
module.exports = function RouteManager(app) {
const routeStore = new RouteStore(app);
const routeResolver = new RouteResolver(app);

@@ -19,3 +19,3 @@ return {

app.log(['serve', 'mount', method], _path);
return routeStore.register(method, _path, response);
return routeResolver.register(method, _path, response);
},

@@ -39,2 +39,6 @@

patch: function patch(_path, response) {
return this.register('patch', _path, response);
},
delete: function _delete(_path, response) {

@@ -44,5 +48,4 @@ return this.register('delete', _path, response);

reset: function reset(/* paths 1, path 2, path 3, etc. */) {
const paths = [].slice.call(arguments);
routeStore.reset.call(routeStore, paths);
reset: function reset() {
routeResolver.reset();
},

@@ -52,3 +55,3 @@

const capture = new CaptureRecorder(app, captureName);
this.register('all', '*', capture.record.bind(capture));
app.use(capture.record.bind(capture));
},

@@ -61,3 +64,3 @@

capture.files().forEach((route) => {
capture.files().forEach(route => {
app.log(['serve', 'playing', route.method], route.originalPath, false);

@@ -64,0 +67,0 @@ app.log(['serve', 'playing', route.method], `${route.originalPath} at ${route.path}`, true);

'use strict';
const fs = require('fs');
const path = require('path');
const parse = require('url').parse;
const _ = require('lodash');
const expandPath = require('../../lib/expandPath');
const pathToRegExp = require('path-to-regexp');
const isAbsoluteUrl = require('is-absolute-url');
const Expectation = require('./Expectation');
/**
* RouteResolver
* Facilitates route registration and unregistration.
* Implements Express route middleware based on mockyeah API options.
*/
function RouteResolver(app) {
this.app = app;
const routeHandler = require('./routeHandler');
function isEqualMethod(method1, method2) {
const m1 = method1.toLowerCase();
const m2 = method2.toLowerCase();
return m1 === 'all' || m2 === 'all' || m1 === m2;
}
function validateResponse(response) {
let payloadKeysPresent = 0;
const payloadKeys = Object.keys(response);
const expectedPayloadKeys = [
'fixture',
'filePath',
'html',
'json',
'text',
'status',
'headers',
'raw',
'latency',
'type'
];
function isRouteForRequest(route, req) {
if (!isEqualMethod(req.method, route.method)) return false;
payloadKeys.forEach(key => {
expectedPayloadKeys.forEach(expectedKey => { if (key === expectedKey) ++payloadKeysPresent; });
});
const pathname = parse(req.url, true).pathname;
if (payloadKeysPresent.length > 1) {
throw new Error(`Response options must not include more than one of the following: ${expectedPayloadKeys.join(', ')}`);
}
const routePathnameIsAbsoluteUrl = isAbsoluteUrl(route.pathname.replace(/^\//, ''));
if (payloadKeys.length !== payloadKeysPresent) {
throw new Error(`Response option(s) invalid. Options must include one of the following: ${expectedPayloadKeys.join(', ')}`);
}
if (routePathnameIsAbsoluteUrl && pathname === route.pathname) return true;
if (route.pathname !== '*' && !route.pathRegExp.test(pathname)) return false;
// TODO: Later add features to match other things, like query parameters, etc.
return true;
}
function verifyFile(filePath, message) {
fs.lstat(filePath, (err) => {
if (err) this.app.log(['handler', 'error'], message);
});
function isRouteMatch(route1, route2) {
return route1.pathname === route2.pathname && route1.method === route2.method;
}
function handler(response) {
response = response || {};
function listen() {
this.app.all('*', (req, res, next) => {
const route = this.routes.find(r => isRouteForRequest(r, req));
validateResponse(response);
if (!route) {
next();
return;
}
return (req, res) => {
const start = (new Date).getTime();
let send;
const expectationNext = err => {
if (err) {
this.app.log(['record', 'expectation', 'error'], err);
res.sendStatus(500);
return;
}
if (this.app.config.journal) {
this.app.log(['request', 'journal'], JSON.stringify({
callCount: req.callCount,
url: req.url,
fullUrl: req.protocol + '://' + req.get('host') + req.originalUrl,
clientIp: req.headers['x-forwarded-for'] || req.connection.remoteAddress,
method: req.method,
headers: req.headers,
query: req.query,
body: req.body,
cookies: req.cookies
}, null, 2));
}
const match = req.path.match(route.pathRegExp);
// Default latency to 0 when undefined
response.latency = response.latency || 0;
const params = {};
// Default response status to 200 when undefined
res.status(response.status || 200);
route.matchKeys.forEach((key, i) => {
params[key.name] = match[i + 1];
params[i] = match[i + 1];
});
// set response headers, if received
if (response.headers) res.set(response.headers);
req.params = params;
if (response.filePath) { // if filePath, send file
const filePath = expandPath(response.filePath);
if (response.type) res.type(response.type);
verifyFile.call(this, filePath, '`filePath` option invalid, file not found at ' + filePath);
send = res.sendFile.bind(res, filePath);
} else if (response.fixture) { // if fixture, send fixture file
const fixturePath = this.app.config.fixturesDir + '/' + response.fixture;
if (response.type) res.type(response.type);
verifyFile.call(this, fixturePath, '`fixture` option invalid, fixture not found at ' + fixturePath);
send = res.sendFile.bind(res, path.normalize(this.app.config.fixturesDir + '/' + response.fixture));
} else if (response.html) { // if html, set Content-Type to application/html and send
res.type(response.type || 'html');
send = res.send.bind(res, response.html);
} else if (response.json) { // if json, set Content-Type to application/json and send
res.type(response.type || 'json');
send = res.send.bind(res, response.json);
} else if (response.text) { // if text, set Content-Type to text/plain and send
res.type(response.type || 'text');
send = res.send.bind(res, response.text);
} else if (response.raw) { // if raw, don't set Content-Type
send = res.send.bind(res, response.raw);
} else { // else send empty response
res.type(response.type || 'text');
send = res.send.bind(res);
}
route.response(req, res);
};
setTimeout(() => {
const duration = (new Date).getTime() - start;
send();
this.app.log(['request', req.method], `${req.url} (${duration}ms)`);
}, response.latency);
};
route.expectation.middleware(req, res, expectationNext);
});
}
RouteResolver.prototype.register = function register(route) {
/**
* RouteResolver
* Facilitates route registration and unregistration.
* Implements Express route middleware based on mockyeah API options.
*/
function RouteResolver(app) {
this.app = app;
this.routes = [];
listen.call(this);
}
RouteResolver.prototype.register = function register(method, path, response) {
const route = { method, path, response };
route.pathname = parse(route.path, true).pathname;
const matchKeys = [];
// `pathToRegExp` mutates `matchKeys` to contain a list of named parameters
route.pathRegExp = pathToRegExp(route.pathname, matchKeys);
route.matchKeys = matchKeys;
if (!_.isFunction(route.response)) {
route.response = handler.call(this, route.response);
route.response = routeHandler.call(this, route);
}
const expectation = new Expectation(route);
route.expectation = expectation;
// unregister existing matching routes
// unregister route if existing
this.unregister([route]);
this.app[route.method](route.path, expectation.middleware.bind(expectation), route.response);
this.routes.push(route);

@@ -136,9 +110,9 @@ return {

RouteResolver.prototype.unregister = function unregister(routes) {
this.app._router.stack = this.app._router.stack.filter((layer) => {
return !(layer.route && routes.some((route) => {
return route.path === layer.route.path && layer.route.methods[route.method] === true;
}));
});
this.routes = this.routes.filter(r1 => !routes.some(r2 => isRouteMatch(r1, r2)));
};
RouteResolver.prototype.reset = function reset() {
this.unregister(this.routes);
};
module.exports = RouteResolver;

@@ -6,4 +6,20 @@ # Change Log

### [Unreleased]
Nothing to report.
#### Add
- Routing changes in preparation for supporting enhanced mock service capabilities.
- An Express change forced the content-type `application/xml` response to be changed to `text/xml`.
#### Remove
- Unmounting specific services has been removed. The following will be no longer provided post 0.15.9:
```js
// unmounts only /foo-1 and /foo-2
mockyeah.reset('/foo-1', '/bar-2');
```
#### Maintenance
- Travis CI updated to execution automation against each of respective latest Node versions: 8, 6, and 4.
- Prettier added and applied to all JavaScript files.
- Yarn added.
### [0.15.9] - 2017-05-25
#### Add
- Add support for multiple HTTP verbs per route.
### [0.15.4] - 2016-12-06

@@ -94,3 +110,4 @@ #### Fix

[Unreleased]: https://github.com/ryanricard/mockyeah/compare/v0.15.4...HEAD
[Unreleased]: https://github.com/ryanricard/mockyeah/compare/v0.15.9...HEAD
[0.15.9]: https://github.com/ryanricard/mockyeah/compare/v0.15.8...v0.15.9
[0.15.4]: https://github.com/ryanricard/mockyeah/compare/v0.15.3...v0.15.4

@@ -97,0 +114,0 @@ [0.15.3]: https://github.com/ryanricard/mockyeah/compare/v0.15.2...v0.15.3

@@ -31,2 +31,2 @@ 'use strict';

module.exports = prepareConfig(config);
module.exports = prepareConfig(config);

@@ -1,5 +0,5 @@

module.exports = (res) => {
module.exports = res => {
console.log('res status: ' + res.statusCode);
console.log('res headers: ' + JSON.stringify(res.headers, null, 2));
res.on('data', (chunk) => console.log(chunk.toString()));
res.on('data', chunk => console.log(chunk.toString()));
};

@@ -15,3 +15,3 @@ const http = require('http');

http.get('http://localhost:4001', (res) => {
http.get('http://localhost:4001', res => {
try {

@@ -18,0 +18,0 @@ expectation.verify();

@@ -13,17 +13,21 @@ const http = require('http');

http.get(Object.assign(options, { method: 'GET' }), (res) => {
http.get(Object.assign(options, { method: 'GET' }), res => {
log(res);
});
http.get(Object.assign(options, { method: 'POST' }), (res) => {
http.get(Object.assign(options, { method: 'POST' }), res => {
log(res);
});
http.get(Object.assign(options, { method: 'PUT' }), (res) => {
http.get(Object.assign(options, { method: 'PUT' }), res => {
log(res);
});
http.get(Object.assign(options, { method: 'DELETE' }), (res) => {
http.get(Object.assign(options, { method: 'PATCH' }), res => {
log(res);
});
http.get(Object.assign(options, { method: 'DELETE' }), res => {
log(res);
mockyeah.close();
});

@@ -7,10 +7,13 @@ const http = require('http');

http.get({
hostname: 'localhost',
port: 4001,
path: '/',
method: 'DELETE'
}, (res) => {
log(res);
mockyeah.close();
});
http.get(
{
hostname: 'localhost',
port: 4001,
path: '/',
method: 'DELETE'
},
res => {
log(res);
mockyeah.close();
}
);

@@ -13,16 +13,19 @@ const http = require('http');

const request = http.request({
hostname: 'localhost',
port: 4001,
path: '/',
method: 'POST',
headers: {
'Content-Type': 'application/json'
const request = http.request(
{
hostname: 'localhost',
port: 4001,
path: '/',
method: 'POST',
headers: {
'Content-Type': 'application/json'
}
},
res => {
log(res);
mockyeah.close();
}
}, (res) => {
log(res);
mockyeah.close();
});
);
request.write(postData);
request.end();

@@ -7,10 +7,13 @@ const http = require('http');

http.get({
hostname: 'localhost',
port: 4001,
path: '/',
method: 'PUT'
}, (res) => {
log(res);
mockyeah.close();
});
http.get(
{
hostname: 'localhost',
port: 4001,
path: '/',
method: 'PUT'
},
res => {
log(res);
mockyeah.close();
}
);

@@ -7,5 +7,5 @@ const http = require('http');

http.get('http://localhost:4001', (res) => {
http.get('http://localhost:4001', res => {
log(res);
mockyeah.close();
});

@@ -6,8 +6,8 @@ const http = require('http');

mockyeah.get('/', (req, res) => {
res.send('I\'m an Express.js route! Customize to your heart\'s content.');
res.send("I'm an Express.js route! Customize to your heart's content.");
});
http.get('http://localhost:4001', (res) => {
http.get('http://localhost:4001', res => {
log(res);
mockyeah.close();
});

@@ -9,5 +9,5 @@ const http = require('http');

http.get('http://localhost:4001', (res) => {
http.get('http://localhost:4001', res => {
log(res);
mockyeah.close();
});

@@ -7,5 +7,5 @@ const http = require('http');

http.get('http://localhost:4001', (res) => {
http.get('http://localhost:4001', res => {
log(res);
mockyeah.close();
});

@@ -7,5 +7,5 @@ const http = require('http');

http.get('http://localhost:4001', (res) => {
http.get('http://localhost:4001', res => {
log(res);
mockyeah.close();
});

@@ -7,5 +7,5 @@ const http = require('http');

http.get('http://localhost:4001', (res) => {
http.get('http://localhost:4001', res => {
log(res);
mockyeah.close();
});

@@ -7,5 +7,5 @@ const http = require('http');

http.get('http://localhost:4001', (res) => {
http.get('http://localhost:4001', res => {
log(res);
mockyeah.close();
});

@@ -7,5 +7,5 @@ const http = require('http');

http.get('http://localhost:4001', (res) => {
http.get('http://localhost:4001', res => {
log(res);
mockyeah.close();
});

@@ -7,5 +7,5 @@ const http = require('http');

http.get('http://localhost:4001', (res) => {
http.get('http://localhost:4001', res => {
log(res);
mockyeah.close();
});

@@ -7,5 +7,5 @@ const http = require('http');

http.get('http://localhost:4001', (res) => {
http.get('http://localhost:4001', res => {
log(res);
mockyeah.close();
});

@@ -7,2 +7,2 @@ 'use strict';

module.exports = new Server(config);
module.exports = new Server(config);

@@ -8,2 +8,2 @@ 'use strict';

return path.isAbsolute(_path) ? _path : path.resolve(relativeRoot, _path);
};
};

@@ -13,3 +13,3 @@ 'use strict';

module.exports = (config) => {
module.exports = config => {
config = Object.assign({}, configDefaults, config || {});

@@ -22,2 +22,2 @@

return config;
};
};

@@ -11,2 +11,2 @@ 'use strict';

*/
module.exports = global.MOCKYEAH_ROOT ? global.MOCKYEAH_ROOT : wrappingProjectRoot;
module.exports = global.MOCKYEAH_ROOT ? global.MOCKYEAH_ROOT : wrappingProjectRoot;
{
"name": "mockyeah",
"version": "0.15.9",
"version": "0.16.0",
"description": "A powerful service mocking, recording, and playback utility.",

@@ -12,6 +12,3 @@ "main": "index.js",

},
"repository": {
"type": "git",
"url": "git@github.com:ryanricard/mockyeah.git"
},
"repository": "git@github.com:ryanricard/mockyeah.git",
"author": "Ryan Ricard",

@@ -58,3 +55,2 @@ "license": "ISC",

"devDependencies": {
"async": "^1.5.2",
"chai": "^3.4.1",

@@ -73,10 +69,15 @@ "dateformat": "^1.0.12",

"dependencies": {
"async": "^1.5.2",
"body-parser": "^1.15.2",
"cors": "^2.7.1",
"express": "^4.13.3",
"http-proxy-middleware": "^0.17.4",
"is-absolute-url": "^2.1.0",
"lodash": "^3.10.1",
"mkdirp": "^0.5.1",
"path-to-regexp": "^2.1.0",
"request": "^2.69.0",
"tildify": "^1.1.2"
}
},
"private": false
}

@@ -29,5 +29,8 @@ 'use strict';

// Expose ability to stop server via API
const close = server.close.bind(server, function callback() {
app.log(['serve', 'exit'], 'Goodbye.');
});
const close = function close(cb) {
server.close(function callback() {
app.log(['serve', 'exit'], 'Goodbye.');
if (cb) cb();
});
};

@@ -40,3 +43,8 @@ // Expose ability to implement middleware via API

// Construct and return mockyeah API
return Object.assign({ server }, app.routeManager, { use, config, close });
return Object.assign(
{ server },
app.routeManager,
{ proxy: app.proxy, reset: app.reset },
{ use, config, close }
);
};

@@ -13,3 +13,4 @@ 'use strict';

return gulp.src(PATH.scripts)
return gulp
.src(PATH.scripts)
.pipe(eslint())

@@ -30,2 +31,2 @@ .pipe(eslint.format())

gulp.watch(PATH.scripts, ['lint:watch:run']);
});
});

@@ -6,2 +6,2 @@ 'use strict';

tests: ['./test/**/*Test.js']
};
};

@@ -7,2 +7,2 @@ 'use strict';

mockyeah.play('some-custom-capture');
mockyeah.play('some-custom-capture');

@@ -17,25 +17,28 @@ 'use strict';

*/
async.series([
(cb) => request.get('/path+includes+problem+characters').expect(200, /it worked/, cb),
(cb) => request.get('/say-hello').expect(200, /hello there/, cb),
(cb) => request.get('/say-oh-noes').expect(500, /Oh noes/, cb),
(cb) => request.get('/say-your-lost').expect(404, /I\'m lost/, cb),
(cb) => request.get('/respond-with-a-file').expect(200, /Hugo/, cb),
(cb) => request.get('/respond-with-a-fixture').expect(200, /Desmond/, cb),
(cb) => {
const latency = 1000;
const threshold = latency + 200;
const start = (new Date).getTime();
async.series(
[
cb => request.get('/path+includes+problem+characters').expect(200, /it worked/, cb),
cb => request.get('/say-hello').expect(200, /hello there/, cb),
cb => request.get('/say-oh-noes').expect(500, /Oh noes/, cb),
cb => request.get('/say-your-lost').expect(404, /I\'m lost/, cb),
cb => request.get('/respond-with-a-file').expect(200, /Hugo/, cb),
cb => request.get('/respond-with-a-fixture').expect(200, /Desmond/, cb),
cb => {
const latency = 1000;
const threshold = latency + 200;
const start = new Date().getTime();
request
.get('/wait-to-respond')
.expect(200, /Oh\, hey there/, done)
.expect(() => {
const now = (new Date).getTime();
const duration = now - start;
expect(duration).to.be.within(latency, threshold);
}, cb);
}
], done);
request
.get('/wait-to-respond')
.expect(200, /Oh\, hey there/, done)
.expect(() => {
const now = new Date().getTime();
const duration = now - start;
expect(duration).to.be.within(latency, threshold);
}, cb);
}
],
done
);
});
});
});

@@ -20,24 +20,33 @@ 'use strict';

before((done) => {
async.parallel([
function(cb) {
// Instantiate proxy server for recording
proxy = MockYeahServer({
name: 'proxy',
port: 0,
capturesDir: PROXY_CAPTURES_DIR
}, cb);
},
function(cb) {
// Instantiate remote server
remote = MockYeahServer({
name: 'remote',
port: 0
}, cb);
before(done => {
async.parallel(
[
function(cb) {
// Instantiate proxy server for recording
proxy = MockYeahServer(
{
name: 'proxy',
port: 0,
capturesDir: PROXY_CAPTURES_DIR
},
cb
);
},
function(cb) {
// Instantiate remote server
remote = MockYeahServer(
{
name: 'remote',
port: 0
},
cb
);
}
],
() => {
remoteReq = supertest(remote.server);
proxyReq = supertest(proxy.server.rootUrl + '/' + remote.server.rootUrl);
done();
}
], () => {
remoteReq = supertest(remote.server);
proxyReq = supertest(proxy.server.rootUrl + '/' + remote.server.rootUrl);
done();
});
);
});

@@ -89,43 +98,70 @@

// Initiate recording and playback series
async.series([
// Initiate recording
(cb) => { proxy.record(captureName); cb(); },
async.series(
[
// Initiate recording
cb => {
proxy.record(captureName);
cb();
},
// Invoke requests to remote services through proxy
// e.g. http://localhost:4041/http://example.com/some/service
(cb) => proxyReq.get(path1).expect(200, 'first', cb),
(cb) => proxyReq.get(path2).expect(200, 'second', cb),
(cb) => proxyReq.get(path3).expect(200, 'third', cb),
(cb) => proxyReq.get(path4).expect(200, 'fourth', cb),
(cb) => proxyReq.get(path5).expect(200, 'fifth', cb),
// Invoke requests to remote services through proxy
// e.g. http://localhost:4041/http://example.com/some/service
cb => proxyReq.get(path1).expect(200, 'first', cb),
cb => proxyReq.get(path2).expect(200, 'second', cb),
cb => proxyReq.get(path3).expect(200, 'third', cb),
cb => proxyReq.get(path4).expect(200, 'fourth', cb),
cb => proxyReq.get(path5).expect(200, 'fifth', cb),
// Assert files exist
(cb) => { fs.statSync(filePath1); cb(); },
(cb) => { fs.statSync(filePath2); cb(); },
(cb) => { fs.statSync(filePath3); cb(); },
(cb) => { fs.statSync(filePath4); cb(); },
(cb) => { fs.statSync(filePath5); cb(); },
// Assert files exist
cb => {
fs.statSync(filePath1);
cb();
},
cb => {
fs.statSync(filePath2);
cb();
},
cb => {
fs.statSync(filePath3);
cb();
},
cb => {
fs.statSync(filePath4);
cb();
},
cb => {
fs.statSync(filePath5);
cb();
},
// Reset proxy services and play captured capture
(cb) => { proxy.reset(); cb(); },
(cb) => { proxy.play(captureName); cb(); },
// Reset proxy services and play captured capture
cb => {
proxy.reset();
cb();
},
cb => {
proxy.play(captureName);
cb();
},
// Test remote url paths and their sub paths route to the same services
// Assert remote url paths are routed the correct responses
// e.g. http://localhost:4041/http://example.com/some/service
(cb) => remoteReq.get(path1).expect(200, 'first', cb),
(cb) => remoteReq.get(path2).expect(200, 'second', cb),
(cb) => remoteReq.get(path3).expect(200, 'third', cb),
(cb) => remoteReq.get(path4).expect(200, 'fourth', cb),
(cb) => remoteReq.get(path5).expect(200, 'fifth', cb),
// Test remote url paths and their sub paths route to the same services
// Assert remote url paths are routed the correct responses
// e.g. http://localhost:4041/http://example.com/some/service
cb => remoteReq.get(path1).expect(200, 'first', cb),
cb => remoteReq.get(path2).expect(200, 'second', cb),
cb => remoteReq.get(path3).expect(200, 'third', cb),
cb => remoteReq.get(path4).expect(200, 'fourth', cb),
cb => remoteReq.get(path5).expect(200, 'fifth', cb),
// Assert paths are routed the correct responses
// e.g. http://localhost:4041/some/service
(cb) => proxyReq.get(path1).expect(200, 'first', cb),
(cb) => proxyReq.get(path2).expect(200, 'second', cb),
(cb) => proxyReq.get(path3).expect(200, 'third', cb),
(cb) => proxyReq.get(path4).expect(200, 'fourth', cb),
(cb) => proxyReq.get(path5).expect(200, 'fifth', cb)
], done);
// Assert paths are routed the correct responses
// e.g. http://localhost:4041/some/service
cb => proxyReq.get(path1).expect(200, 'first', cb),
cb => proxyReq.get(path2).expect(200, 'second', cb),
cb => proxyReq.get(path3).expect(200, 'third', cb),
cb => proxyReq.get(path4).expect(200, 'fourth', cb),
cb => proxyReq.get(path5).expect(200, 'fifth', cb)
],
done
);
});
});

@@ -8,30 +8,40 @@ 'use strict';

it('should write output to stdout by default', function(done) {
exec(`echo "
exec(
`echo "
const mockyeah = new require('./server')({ port: 0 }, function() { process.exit() });
" | node`, function(err, stdout, stderr) {
expect(stdout).to.include('mockyeah');
done();
});
" | node`,
function(err, stdout, stderr) {
expect(stdout).to.include('mockyeah');
done();
}
);
});
it('should write output to stdout when enabled', function(done) {
exec(`echo "
exec(
`echo "
const mockyeah = new require('./server')({ port: 0, output: true }, function() { process.exit() });
" | node`, function(err, stdout, stderr) {
expect(stdout).to.include('mockyeah');
done();
});
" | node`,
function(err, stdout, stderr) {
expect(stdout).to.include('mockyeah');
done();
}
);
});
it('should not write to stdout when disabled', function(done) {
exec(`echo "
exec(
`echo "
const mockyeah = new require('./server')({ port: 0, output: false }, function() { process.exit() });
" | node`, function(err, stdout, stderr) {
expect(stdout).to.not.include('mockyeah');
done();
});
" | node`,
function(err, stdout, stderr) {
expect(stdout).to.not.include('mockyeah');
done();
}
);
});
it('should not write verbose output to stdout by default', function(done) {
exec(`echo "
exec(
`echo "
const request = require('supertest');

@@ -43,10 +53,13 @@ const mockyeah = new require('./server')({ port: 0 });

.expect(200, /bar/, process.exit);
" | node`, function(err, stdout, stderr) {
expect(stdout).to.not.include('verbose output enabled');
done();
});
" | node`,
function(err, stdout, stderr) {
expect(stdout).to.not.include('verbose output enabled');
done();
}
);
});
it('should write verbose output to stdout when enabled', function(done) {
exec(`echo "
exec(
`echo "
const request = require('supertest');

@@ -58,10 +71,13 @@ const mockyeah = new require('./server')({ port: 0, verbose: true });

.expect(200, /bar/, process.exit);
" | node`, function(err, stdout, stderr) {
expect(stdout).to.include('verbose output enabled');
done();
});
" | node`,
function(err, stdout, stderr) {
expect(stdout).to.include('verbose output enabled');
done();
}
);
});
it('should not write verbose output to stdout when disabled', function(done) {
exec(`echo "
exec(
`echo "
const request = require('supertest');

@@ -76,10 +92,13 @@ // const mockyeah = new require('./server')({ port: 0, verbose: false });

}, 1000);
" | node`, function(err, stdout, stderr) {
expect(stdout).to.not.include('verbose output enabled');
done();
});
" | node`,
function(err, stdout, stderr) {
expect(stdout).to.not.include('verbose output enabled');
done();
}
);
});
it('should not write journaled output to stdout by default', function(done) {
exec(`echo "
exec(
`echo "
const request = require('supertest');

@@ -91,10 +110,13 @@ const mockyeah = new require('./server')({ port: 0 });

.expect(200, /bar/, process.exit);
" | node`, function(err, stdout, stderr) {
expect(stdout).to.not.include('JOURNAL');
done();
});
" | node`,
function(err, stdout, stderr) {
expect(stdout).to.not.include('JOURNAL');
done();
}
);
});
it('should write journaled output to stdout when enabled', function(done) {
exec(`echo "
exec(
`echo "
const request = require('supertest');

@@ -106,10 +128,13 @@ const mockyeah = new require('./server')({ port: 0, journal: true });

.expect(200, /bar/, process.exit);
" | node`, function(err, stdout, stderr) {
expect(stdout).to.include('JOURNAL');
done();
});
" | node`,
function(err, stdout, stderr) {
expect(stdout).to.include('JOURNAL');
done();
}
);
});
it('should not write journaled output to stdout when disabled ', function(done) {
exec(`echo "
exec(
`echo "
const request = require('supertest');

@@ -121,7 +146,9 @@ const mockyeah = new require('./server')({ port: 0, journal: false });

.expect(200, /bar/, process.exit);
" | node`, function(err, stdout, stderr) {
expect(stdout).to.not.include('JOURNAL');
done();
});
" | node`,
function(err, stdout, stderr) {
expect(stdout).to.not.include('JOURNAL');
done();
}
);
});
});

@@ -34,3 +34,3 @@ 'use strict';

it('should be exposed for external use', (done) => {
it('should be exposed for external use', done => {
mockyeah.get('/validate', validateMiddleware);

@@ -37,0 +37,0 @@

@@ -21,3 +21,3 @@ 'use strict';

it('should create a mock service that returns an internal error', (done) => {
it('should create a mock service that returns an internal error', done => {
// create failing service mock

@@ -27,8 +27,6 @@ mockyeah.get('/wondrous', { status: 500 });

// assert service mock is working
request
.get('/wondrous')
.expect(500, done);
request.get('/wondrous').expect(500, done);
});
it('should create a mock service that returns JSON', (done) => {
it('should create a mock service that returns JSON', done => {
// create service mock that returns json data

@@ -38,8 +36,6 @@ mockyeah.get('/wondrous', { json: { foo: 'bar' } });

// assert service mock is working
request
.get('/wondrous')
.expect(200, { foo: 'bar' }, done);
request.get('/wondrous').expect(200, { foo: 'bar' }, done);
});
it('should verify a mock service expectation', (done) => {
it('should verify a mock service expectation', done => {
// create service mock with expectation

@@ -46,0 +42,0 @@ const expectation = mockyeah

@@ -9,3 +9,3 @@ 'use strict';

describe('File', () => {
it('should respond with a CSV Content-Type for CSV files', (done) => {
it('should respond with a CSV Content-Type for CSV files', done => {
mockyeah.get('/service/exists', { filePath: './fixtures/some-data.csv' });

@@ -19,3 +19,3 @@

it('should respond with a JSON Content-Type for JSON files', (done) => {
it('should respond with a JSON Content-Type for JSON files', done => {
mockyeah.get('/service/exists', { filePath: './fixtures/some-data.json' });

@@ -29,3 +29,3 @@

it('should respond with a text Content-Type for text files', (done) => {
it('should respond with a text Content-Type for text files', done => {
mockyeah.get('/service/exists', { filePath: './fixtures/some-data.txt' });

@@ -39,3 +39,3 @@

it('should respond with a XML Content-Type for XML files', (done) => {
it('should respond with a XML Content-Type for XML files', done => {
mockyeah.get('/service/exists', { filePath: './fixtures/some-data.xml' });

@@ -45,7 +45,7 @@

.get('/service/exists')
.expect('Content-Type', /application\/xml/)
.expect('Content-Type', /text\/xml/)
.expect(200, done);
});
it('should allow Content-Type override', (done) => {
it('should allow Content-Type override', done => {
mockyeah.get('/service/exists', { filePath: './fixtures/some-data.json', type: 'text' });

@@ -61,3 +61,3 @@

describe('Fixture', () => {
it('should respond with a CSV Content-Type for CSV fixtures', (done) => {
it('should respond with a CSV Content-Type for CSV fixtures', done => {
mockyeah.get('/service/exists', { fixture: 'some-data.csv' });

@@ -71,3 +71,3 @@

it('should respond with a JSON Content-Type for JSON fixtures', (done) => {
it('should respond with a JSON Content-Type for JSON fixtures', done => {
mockyeah.get('/service/exists', { fixture: 'some-data.json' });

@@ -81,3 +81,3 @@

it('should respond with a text Content-Type for text fixtures', (done) => {
it('should respond with a text Content-Type for text fixtures', done => {
mockyeah.get('/service/exists', { fixture: 'some-data.txt' });

@@ -91,3 +91,3 @@

it('should respond with a XML Content-Type for XML fixtures', (done) => {
it('should respond with a XML Content-Type for XML fixtures', done => {
mockyeah.get('/service/exists', { fixture: 'some-data.xml' });

@@ -97,7 +97,7 @@

.get('/service/exists')
.expect('Content-Type', /application\/xml/)
.expect('Content-Type', /text\/xml/)
.expect(200, done);
});
it('should allow Content-Type override', (done) => {
it('should allow Content-Type override', done => {
mockyeah.get('/service/exists', { fixture: 'some-data.json', type: 'text' });

@@ -113,3 +113,3 @@

describe('HTML', () => {
it('should respond HTML Content-Type for HTML', (done) => {
it('should respond HTML Content-Type for HTML', done => {
mockyeah.get('/service/exists', { html: '<p>Hello</p>' });

@@ -123,3 +123,3 @@

it('should allow Content-Type override', (done) => {
it('should allow Content-Type override', done => {
mockyeah.get('/service/exists', { html: '<p>Hello</p>', type: 'text' });

@@ -135,3 +135,3 @@

describe('JSON', () => {
it('should respond with JSON Content-Type for JSON', (done) => {
it('should respond with JSON Content-Type for JSON', done => {
mockyeah.get('/service/exists', { json: { foo: 'bar' } });

@@ -145,3 +145,3 @@

it('should allow Content-Type override', (done) => {
it('should allow Content-Type override', done => {
mockyeah.get('/service/exists', { json: { foo: 'bar' }, type: 'text' });

@@ -157,3 +157,3 @@

describe('Text', () => {
it('should respond with text Content-Type for text', (done) => {
it('should respond with text Content-Type for text', done => {
mockyeah.get('/service/exists', { text: 'Hello' });

@@ -167,3 +167,3 @@

it('should allow Content-Type override', (done) => {
it('should allow Content-Type override', done => {
mockyeah.get('/service/exists', { text: 'Hello', type: 'html' });

@@ -177,2 +177,2 @@

});
});
});

@@ -8,3 +8,3 @@ 'use strict';

describe('Response Headers', () => {
it('should support custom headers', (done) => {
it('should support custom headers', done => {
mockyeah.get('/some/service/end/point', { text: 'Hello.', headers: { 'Foo-Bar': 'abc' } });

@@ -18,10 +18,13 @@

it('should send header Content-Type when set and raw', (done) => {
mockyeah.get('/some/service/end/point', { raw: 'Hello.', headers: { 'content-type': 'application/xml' } });
it('should send header Content-Type when set and raw', done => {
mockyeah.get('/some/service/end/point', {
raw: 'Hello.',
headers: { 'content-type': 'text/xml' }
});
request
.get('/some/service/end/point')
.expect('Content-Type', /application\/xml/)
.expect('Content-Type', /text\/xml/)
.expect(200, /Hello/, done);
});
});
});

@@ -9,3 +9,3 @@ 'use strict';

describe('Response Latency', () => {
it('should respond with latency', (done) => {
it('should respond with latency', done => {
const latency = 1000;

@@ -16,3 +16,3 @@ const threshold = latency + 200;

const start = (new Date).getTime();
const start = new Date().getTime();

@@ -23,3 +23,3 @@ request

.expect(() => {
const now = (new Date).getTime();
const now = new Date().getTime();
const duration = now - start;

@@ -30,3 +30,3 @@ expect(duration).to.be.within(latency, threshold);

it('should respond with no latency', (done) => {
it('should respond with no latency', done => {
const threshold = 25;

@@ -36,3 +36,3 @@

const start = (new Date).getTime();
const start = new Date().getTime();

@@ -43,3 +43,3 @@ request

.expect(() => {
const now = (new Date).getTime();
const now = new Date().getTime();
const duration = now - start;

@@ -49,2 +49,2 @@ expect(duration).to.be.below(threshold);

});
});
});

@@ -8,31 +8,23 @@ 'use strict';

describe('Response Status', () => {
it('should return 404 for undeclared services', (done) => {
request
.get('/some/non/existent/service/end/point')
.expect(404, done);
it('should return 404 for undeclared services', done => {
request.get('/some/non/existent/service/end/point').expect(404, done);
});
it('should return a default status code of 200', (done) => {
it('should return a default status code of 200', done => {
mockyeah.get('/service/exists');
request
.get('/service/exists')
.expect(200, done);
request.get('/service/exists').expect(200, done);
});
it('should support declarative status code 301', (done) => {
it('should support declarative status code 301', done => {
mockyeah.get('/some/service/end/point', { status: 301 });
request
.get('/some/service/end/point')
.expect(301, done);
request.get('/some/service/end/point').expect(301, done);
});
it('should support declarative status code 500', (done) => {
it('should support declarative status code 500', done => {
mockyeah.get('/some/service/end/point', { status: 500 });
request
.get('/some/service/end/point')
.expect(500, done);
request.get('/some/service/end/point').expect(500, done);
});
});
});

@@ -15,10 +15,10 @@ 'use strict';

} catch (err) {
expect(err.message).to.equal('Response option(s) invalid. Options must include one of the following: fixture, filePath, html, json, text, status, headers, raw, latency, type');
expect(err.message).to.equal(
'Response option(s) invalid. Options must include one of the following: fixture, filePath, html, json, text, status, headers, raw, latency, type'
);
done();
}
request
.get('/some/service/end/point')
.expect(404);
request.get('/some/service/end/point').expect(404);
});
});

@@ -20,3 +20,3 @@ 'use strict';

it('should implement never() expectation', (done) => {
it('should implement never() expectation', done => {
const expectation = mockyeah

@@ -27,16 +27,21 @@ .get('/foo', { text: 'bar' })

async.series([
(cb) => {
expectation.verify();
cb();
},
(cb) => request.get('/foo').end(cb),
(cb) => {
expect(expectation.verify).to.throw('Expected route to be called never, but it was called 1 times');
cb();
}
], done);
async.series(
[
cb => {
expectation.verify();
cb();
},
cb => request.get('/foo').end(cb),
cb => {
expect(expectation.verify).to.throw(
'Expected route to be called never, but it was called 1 times'
);
cb();
}
],
done
);
});
it('should implement once() expectation', (done) => {
it('should implement once() expectation', done => {
const expectation = mockyeah

@@ -47,21 +52,28 @@ .get('/foo', { text: 'bar' })

async.series([
(cb) => {
expect(expectation.verify).to.throw('Expected route to be called once, but it was called 0 times');
cb();
},
(cb) => request.get('/foo').end(cb),
(cb) => {
expectation.verify();
cb();
},
(cb) => request.get('/foo').end(cb),
(cb) => {
expect(expectation.verify).to.throw('Expected route to be called once, but it was called 2 times');
cb();
}
], done);
async.series(
[
cb => {
expect(expectation.verify).to.throw(
'Expected route to be called once, but it was called 0 times'
);
cb();
},
cb => request.get('/foo').end(cb),
cb => {
expectation.verify();
cb();
},
cb => request.get('/foo').end(cb),
cb => {
expect(expectation.verify).to.throw(
'Expected route to be called once, but it was called 2 times'
);
cb();
}
],
done
);
});
it('should implement twice() expectation', (done) => {
it('should implement twice() expectation', done => {
const expectation = mockyeah

@@ -72,22 +84,29 @@ .get('/foo', { text: 'bar' })

async.series([
(cb) => request.get('/foo').end(cb),
(cb) => {
expect(expectation.verify).to.throw('Expected route to be called twice, but it was called 1 times');
cb();
},
(cb) => request.get('/foo').end(cb),
(cb) => {
expectation.verify();
cb();
},
(cb) => request.get('/foo').end(cb),
(cb) => {
expect(expectation.verify).to.throw('Expected route to be called twice, but it was called 3 times');
cb();
}
], done);
async.series(
[
cb => request.get('/foo').end(cb),
cb => {
expect(expectation.verify).to.throw(
'Expected route to be called twice, but it was called 1 times'
);
cb();
},
cb => request.get('/foo').end(cb),
cb => {
expectation.verify();
cb();
},
cb => request.get('/foo').end(cb),
cb => {
expect(expectation.verify).to.throw(
'Expected route to be called twice, but it was called 3 times'
);
cb();
}
],
done
);
});
it('should implement thrice() expectation', (done) => {
it('should implement thrice() expectation', done => {
const expectation = mockyeah

@@ -98,23 +117,30 @@ .get('/foo', { text: 'bar' })

async.series([
(cb) => request.get('/foo').end(cb),
(cb) => request.get('/foo').end(cb),
(cb) => {
expect(expectation.verify).to.throw('Expected route to be called thrice, but it was called 2 times');
cb();
},
(cb) => request.get('/foo').end(cb),
(cb) => {
expectation.verify();
cb();
},
(cb) => request.get('/foo').end(cb),
(cb) => {
expect(expectation.verify).to.throw('Expected route to be called thrice, but it was called 4 times');
cb();
}
], done);
async.series(
[
cb => request.get('/foo').end(cb),
cb => request.get('/foo').end(cb),
cb => {
expect(expectation.verify).to.throw(
'Expected route to be called thrice, but it was called 2 times'
);
cb();
},
cb => request.get('/foo').end(cb),
cb => {
expectation.verify();
cb();
},
cb => request.get('/foo').end(cb),
cb => {
expect(expectation.verify).to.throw(
'Expected route to be called thrice, but it was called 4 times'
);
cb();
}
],
done
);
});
it('should implement exactly() expectation', (done) => {
it('should implement exactly() expectation', done => {
const expectation = mockyeah

@@ -125,27 +151,34 @@ .get('/foo', { text: 'bar' })

async.series([
(cb) => request.get('/foo').end(cb),
(cb) => request.get('/foo').end(cb),
(cb) => request.get('/foo').end(cb),
(cb) => request.get('/foo').end(cb),
(cb) => request.get('/foo').end(cb),
(cb) => request.get('/foo').end(cb),
(cb) => {
expect(expectation.verify).to.throw('Expected route to be called 7 times, but it was called 6 times');
cb();
},
(cb) => request.get('/foo').end(cb),
(cb) => {
expectation.verify();
cb();
},
(cb) => request.get('/foo').end(cb),
(cb) => {
expect(expectation.verify).to.throw('Expected route to be called 7 times, but it was called 8 times');
cb();
}
], done);
async.series(
[
cb => request.get('/foo').end(cb),
cb => request.get('/foo').end(cb),
cb => request.get('/foo').end(cb),
cb => request.get('/foo').end(cb),
cb => request.get('/foo').end(cb),
cb => request.get('/foo').end(cb),
cb => {
expect(expectation.verify).to.throw(
'Expected route to be called 7 times, but it was called 6 times'
);
cb();
},
cb => request.get('/foo').end(cb),
cb => {
expectation.verify();
cb();
},
cb => request.get('/foo').end(cb),
cb => {
expect(expectation.verify).to.throw(
'Expected route to be called 7 times, but it was called 8 times'
);
cb();
}
],
done
);
});
it('should implement atMost() expectation', (done) => {
it('should implement atMost() expectation', done => {
const expectation = mockyeah

@@ -156,31 +189,36 @@ .get('/foo', { text: 'bar' })

async.series([
(cb) => {
expectation.verify();
cb();
},
(cb) => request.get('/foo').end(cb),
(cb) => {
expectation.verify();
cb();
},
(cb) => request.get('/foo').end(cb),
(cb) => {
expectation.verify();
cb();
},
(cb) => request.get('/foo').end(cb),
(cb) => {
expectation.verify();
cb();
},
(cb) => request.get('/foo').end(cb),
(cb) => {
expect(expectation.verify).to.throw('Expected route to be called at most 3 times, but it was called 4 times');
cb();
}
], done);
async.series(
[
cb => {
expectation.verify();
cb();
},
cb => request.get('/foo').end(cb),
cb => {
expectation.verify();
cb();
},
cb => request.get('/foo').end(cb),
cb => {
expectation.verify();
cb();
},
cb => request.get('/foo').end(cb),
cb => {
expectation.verify();
cb();
},
cb => request.get('/foo').end(cb),
cb => {
expect(expectation.verify).to.throw(
'Expected route to be called at most 3 times, but it was called 4 times'
);
cb();
}
],
done
);
});
it('should implement atLeast() expectation', (done) => {
it('should implement atLeast() expectation', done => {
const expectation = mockyeah

@@ -191,23 +229,28 @@ .get('/foo', { text: 'bar' })

async.series([
(cb) => request.get('/foo').end(cb),
(cb) => request.get('/foo').end(cb),
(cb) => {
expect(expectation.verify).to.throw('Expected route to be called at least 3 times, but it was called 2 times');
cb();
},
(cb) => request.get('/foo').end(cb),
(cb) => {
expectation.verify();
cb();
},
(cb) => request.get('/foo').end(cb),
(cb) => {
expectation.verify();
cb();
}
], done);
async.series(
[
cb => request.get('/foo').end(cb),
cb => request.get('/foo').end(cb),
cb => {
expect(expectation.verify).to.throw(
'Expected route to be called at least 3 times, but it was called 2 times'
);
cb();
},
cb => request.get('/foo').end(cb),
cb => {
expectation.verify();
cb();
},
cb => request.get('/foo').end(cb),
cb => {
expectation.verify();
cb();
}
],
done
);
});
it('should implement params() expectation', (done) => {
it('should implement params() expectation', done => {
const expectation = mockyeah

@@ -220,17 +263,20 @@ .get('/foo', { text: 'bar' })

async.series([
(cb) => request.get('/foo?id=9999').end(cb),
(cb) => {
expectation.verify();
cb();
},
(cb) => request.get('/foo').end(cb),
(cb) => {
expect(expectation.verify).to.throw('Expected params did not match expected for request');
cb();
}
], done);
async.series(
[
cb => request.get('/foo?id=9999').end(cb),
cb => {
expectation.verify();
cb();
},
cb => request.get('/foo').end(cb),
cb => {
expect(expectation.verify).to.throw('Expected params did not match expected for request');
cb();
}
],
done
);
});
it('should implement body() expectation', (done) => {
it('should implement body() expectation', done => {
const expectation = mockyeah

@@ -243,17 +289,28 @@ .post('/foo', { text: 'bar' })

async.series([
(cb) => request.post('/foo').send({ foo: 'bar' }).end(cb),
(cb) => {
expectation.verify();
cb();
},
(cb) => request.post('/foo').send({ some: 'value' }).end(cb),
(cb) => {
expect(expectation.verify).to.throw('Expected body to match expected for request');
cb();
}
], done);
async.series(
[
cb =>
request
.post('/foo')
.send({ foo: 'bar' })
.end(cb),
cb => {
expectation.verify();
cb();
},
cb =>
request
.post('/foo')
.send({ some: 'value' })
.end(cb),
cb => {
expect(expectation.verify).to.throw('Expected body to match expected for request');
cb();
}
],
done
);
});
it('should implement header() expectation', (done) => {
it('should implement header() expectation', done => {
const expectation = mockyeah

@@ -264,17 +321,30 @@ .get('/foo', { text: 'bar' })

async.series([
(cb) => request.get('/foo').set('HOST', 'example.com').end(cb),
(cb) => {
expectation.verify();
cb();
},
(cb) => request.get('/foo').set('HOST', 'unknown.com').end(cb),
(cb) => {
expect(expectation.verify).to.throw('Expected header value host:example.com, but it was unknown.com');
cb();
}
], done);
async.series(
[
cb =>
request
.get('/foo')
.set('HOST', 'example.com')
.end(cb),
cb => {
expectation.verify();
cb();
},
cb =>
request
.get('/foo')
.set('HOST', 'unknown.com')
.end(cb),
cb => {
expect(expectation.verify).to.throw(
'Expected header value host:example.com, but it was unknown.com'
);
cb();
}
],
done
);
});
it('should allow composable expectations', (done) => {
it('should allow composable expectations', done => {
const expectation = mockyeah

@@ -281,0 +351,0 @@ .post('/foo', { text: 'bar' })

@@ -21,29 +21,30 @@ 'use strict';

it('should replace existing matching routes', (done) => {
it('should replace existing matching routes', done => {
mockyeah.get('/foo', { text: 'bar', status: 200 });
request
.get('/foo')
.expect(200, 'bar');
request.get('/foo').expect(200, 'bar');
mockyeah.get('/foo', { text: 'baa', status: 301 });
request
.get('/foo')
.expect(301, 'baa', done);
request.get('/foo').expect(301, 'baa', done);
});
it('should not replace existing matching routes with different http verbs', (done) => {
it('should not replace existing matching routes with different http verbs', done => {
mockyeah.get('/foo', { text: 'bar get' });
mockyeah.post('/foo', { text: 'bar post' });
mockyeah.put('/foo', { text: 'bar put' });
mockyeah.patch('/foo', { text: 'bar patch' });
mockyeah.delete('/foo', { text: 'bar delete' });
async.parallel([
(cb) => request.get('/foo').expect(200, 'bar get', cb),
(cb) => request.post('/foo').expect(200, 'bar post', cb),
(cb) => request.put('/foo').expect(200, 'bar put', cb),
(cb) => request.delete('/foo').expect(200, 'bar delete', cb)
], done);
async.parallel(
[
cb => request.get('/foo').expect(200, 'bar get', cb),
cb => request.post('/foo').expect(200, 'bar post', cb),
cb => request.put('/foo').expect(200, 'bar put', cb),
cb => request.patch('/foo').expect(200, 'bar patch', cb),
cb => request.delete('/foo').expect(200, 'bar delete', cb)
],
done
);
});
});

@@ -22,3 +22,3 @@ 'use strict';

it('should reset all routes when no paths are passed', (done) => {
it('should reset all routes when no paths are passed', done => {
mockyeah.get('/foo-1', { text: 'bar' });

@@ -29,61 +29,20 @@ mockyeah.get('/foo-2', { text: 'bar' });

async.series([
(cb) => request.get('/foo-1').expect(200, cb),
(cb) => request.get('/foo-2').expect(200, cb),
(cb) => request.get('/foo-3').expect(200, cb),
(cb) => request.get('/foo-4').expect(200, cb),
(cb) => {
mockyeah.reset();
cb();
},
(cb) => request.get('/foo-1').expect(404, cb),
(cb) => request.get('/foo-2').expect(404, cb),
(cb) => request.get('/foo-3').expect(404, cb),
(cb) => request.get('/foo-4').expect(404, cb)
], done);
async.series(
[
cb => request.get('/foo-1').expect(200, cb),
cb => request.get('/foo-2').expect(200, cb),
cb => request.get('/foo-3').expect(200, cb),
cb => request.get('/foo-4').expect(200, cb),
cb => {
mockyeah.reset();
cb();
},
cb => request.get('/foo-1').expect(404, cb),
cb => request.get('/foo-2').expect(404, cb),
cb => request.get('/foo-3').expect(404, cb),
cb => request.get('/foo-4').expect(404, cb)
],
done
);
});
it('should reset a single route when a matching path is passed', (done) => {
mockyeah.get('/foo-1', { text: 'bar' });
mockyeah.get('/foo-2', { text: 'bar' });
mockyeah.get('/foo-3', { text: 'bar' });
mockyeah.get('/foo-4', { text: 'bar' });
async.series([
(cb) => request.get('/foo-1').expect(200, cb),
(cb) => request.get('/foo-2').expect(200, cb),
(cb) => request.get('/foo-3').expect(200, cb),
(cb) => request.get('/foo-4').expect(200, cb),
(cb) => {
mockyeah.reset('/foo-2');
cb();
},
(cb) => request.get('/foo-1').expect(200, cb),
(cb) => request.get('/foo-2').expect(404, cb),
(cb) => request.get('/foo-3').expect(200, cb),
(cb) => request.get('/foo-4').expect(200, cb)
], done);
});
it('should reset multiple route when a matching paths are passed', (done) => {
mockyeah.get('/foo-1', { text: 'bar' });
mockyeah.get('/foo-2', { text: 'bar' });
mockyeah.get('/foo-3', { text: 'bar' });
mockyeah.get('/foo-4', { text: 'bar' });
async.series([
(cb) => request.get('/foo-1').expect(200, cb),
(cb) => request.get('/foo-2').expect(200, cb),
(cb) => request.get('/foo-3').expect(200, cb),
(cb) => request.get('/foo-4').expect(200, cb),
(cb) => {
mockyeah.reset('/foo-2', '/foo-3');
cb();
},
(cb) => request.get('/foo-1').expect(200, cb),
(cb) => request.get('/foo-2').expect(404, cb),
(cb) => request.get('/foo-3').expect(404, cb),
(cb) => request.get('/foo-4').expect(200, cb)
], done);
});
});

@@ -7,11 +7,9 @@ 'use strict';

describe('Server', () => {
it('should respond to root http requests', (done) => {
request
.get('/')
.expect(200, /Hello\, mockyeah\!/, done);
it('should respond to root http requests', done => {
request.get('/').expect(200, /Hello\, mockyeah\!/, done);
});
it('should respond with a 404 for unknown paths', (done) => {
it('should respond with a 404 for unknown paths', done => {
request.get('/unknown/path').expect(404, done);
});
});
});

@@ -19,2 +19,2 @@ 'use strict';

exports.mockyeah = mockyeah;
exports.request = request(mockyeah.server);
exports.request = request(mockyeah.server);

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc