Skip to content

Instantly share code, notes, and snippets.

@der-On
Last active August 29, 2015 14:12
Show Gist options
  • Save der-On/9a7576503632f15950e5 to your computer and use it in GitHub Desktop.
Save der-On/9a7576503632f15950e5 to your computer and use it in GitHub Desktop.
Geddy unit testing mocks and helpers
"use strict";
var exec = require('child_process').exec;
var sqlAdapters = ['mysql', 'sqlite', 'postgres'];
var utils = require('utilities');
function noop() {}
function getAdapter()
{
var name = geddy.config.model.defaultAdapter;
return geddy.model.adapters[name];
}
function getTables(adapter, cb)
{
adapter.exec('SHOW TABLES', function(err, result) {
if (err) throw err;
var tables = result.map(function(item) {
return item['Tables_in_' + adapter.config.database];
});
cb(null, tables);
});
}
/**
* Removes all tables and data from DB
*/
var reset = module.exports.reset = function(cb)
{
cb = cb || noop;
if (sqlAdapters.indexOf(geddy.config.model.defaultAdapter) !== -1) {
console.log('reseting database ...');
var adapter = getAdapter();
getTables(adapter, function(err, tables) {
dropNext();
function dropNext() {
if (tables.length === 0) {
cb(null);
return;
}
var sql = 'DROP TABLE IF EXISTS ' + tables.shift() + ';';
adapter.exec(sql, function(err) {
if (err) throw err;
dropNext();
});
}
});
}
else {
cb();
}
};
/**
* Removes all data from all tables
*/
var empty = module.exports.empty = function(cb)
{
cb = cb || noop;
if (sqlAdapters.indexOf(geddy.config.model.defaultAdapter) !== -1) {
console.log('emptying database ...');
var adapter = getAdapter();
getTables(adapter, function(err, tables) {
emptyNext();
function emptyNext() {
if (tables.length === 0) {
cb(null);
return;
}
var sql = 'TRUNCATE TABLE ' + tables.shift() + ';';
adapter.exec(sql, function(err) {
if (err) throw err;
emptyNext();
});
}
});
}
else {
cb();
}
};
/**
* Migrates database
*/
var migrate = module.exports.migrate = function(cb)
{
cb = cb || noop;
if (sqlAdapters.indexOf(geddy.config.model.defaultAdapter) !== -1) {
console.log('migrating database ...');
exec('geddy jake db:migrate', function(err) {
if (err) throw err;
cb();
});
}
else {
cb();
}
};
/**
* Inits an empty database (with no tables)
*/
var init = module.exports.init = function(cb)
{
cb = cb || noop;
if (sqlAdapters.indexOf(geddy.config.model.defaultAdapter) !== -1) {
console.log('initing database ...');
exec('geddy jake db:init', function(err) {
if (err) throw err;
cb();
});
}
else {
cb();
}
};
"use strict";
var assert = require('assert');
var mocks = require('../../lib/test/mocks');
var db = require('../../lib/test/db');
var sendMail = geddy.mailer.sendMail;
var tests = module.exports = {
// start with a clean DB
'before': function(next) {
db.reset(function() {
db.init(function() {
db.migrate(next);
});
});
},
'beforeEach': function(next) {
// restore sendMail method
geddy.mailer.sendMail = sendMail;
// empty database
db.empty(next);
},
'Create new user': function(next) {
var timeout = setTimeout(function() {
assert.fail('User creation has not finished in time.');
}, 2000);
// check if confirmation email has been send
geddy.mailer.sendMail = function(opts, cb) {
// do your assertions here
// do not forget to call the callback
cb();
});
mocks.executeControllerAction('Users', 'create', params, function(data, options) {
clearTimeout(timeout);
// do your assertions here
});
}
};
function noop() {};
/**
* Mock Request
* You won't need this
*/
function Request(ctrl) {
ctrl = ctrl || {};
this.headers = {};
this.body = null;
this.format = null;
this.method = ctrl.method || 'GET';
this.params = ctrl.params || {};
}
module.exports.Request = Request;
/**
* Mock Response
* You won't need this
*/
function Response(ctrl) {
ctrl = ctrl || {};
this.headers = {};
this.body = null;
this.setHeaders = noop;
this.finalize = noop;
this.writeBody = noop;
this.finish = noop;
}
module.exports.Response = Response;
/**
* Creates an instance of a controller
* @param name {String} - Controller name
* @returns {Object}
*/
function createController(name)
{
var ctrl = geddy.controller.create(name);
ctrl.name = name;
ctrl.params = {};
ctrl.method = 'GET';
ctrl.request = new Request(ctrl);
ctrl.response = new Response(ctrl);
ctrl.session = new Session(ctrl);
return ctrl;
}
module.exports.createController = createController;
/**
* Executes a controller action
* @param ctrl {String|Object} - if string, the controller name, if object a controller instance
* @param method {String} - Request method
* @param action {String} - controller action
* @param params {Object] - Request parameters
* @param cb {Function} - Response callback, basically controller.respond()
* @returns {Object} - the controller
*/
module.exports.executeControllerAction = function(ctrl, method, action, params, cb)
{
if (typeof ctrl === 'string') {
ctrl = createController(ctrl);
}
ctrl.params = ctrl.request.params = params;
ctrl.method = ctrl.request.method = method;
var respond = ctrl.respond;
ctrl.respond = function() {
// reset respond method
ctrl.respond = respond;
cb.apply(null, arguments);
};
if (typeof ctrl[action] !== 'function') throw new Error(ctrl.name + ' controller has no ' + action + ' action.');
ctrl[action](ctrl.request, ctrl.response, ctrl.params);
return ctrl;
};
/**
* mocked Session store used by all mocked controllers
*/
var sessionStore = module.exports.sessionStore = {};
/**
* Mock Session
* You will not need this
*/
function Session(ctrl)
{
ctrl = ctrl || {};
var data = sessionStore;
this.set = function(key, value) {
data[key] = value;
};
this.get = function(key) {
return data[key] || null;
};
}
module.exports.Session = Session;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment