test: extract hook-monitor helper

This commit is contained in:
Miroslav Bajtoš 2016-04-12 15:06:42 +02:00
parent 90f04181a4
commit 7d7662bfef
2 changed files with 56 additions and 40 deletions

View File

@ -0,0 +1,30 @@
// Copyright IBM Corp. 2016. All Rights Reserved.
// Node module: loopback-datasource-juggler
// This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT
module.exports = HookMonitor;
function HookMonitor(opts) {
if (!(this instanceof HookMonitor)) {
return new HookMonitor();
}
this.options = opts || {};
this.names = [];
};
HookMonitor.prototype.install = function(ObservedModel, hookNames) {
var monitor = this;
this.names = [];
ObservedModel._notify = ObservedModel.notifyObserversOf;
ObservedModel.notifyObserversOf = function(operation, context, callback) {
if (!Array.isArray(hookNames) || hookNames.indexOf(operation) !== -1) {
var item = monitor.options.includeModelName ?
ObservedModel.modelName + ':' + operation :
operation;
monitor.names.push(item);
}
this._notify.apply(this, arguments);
};
};

View File

@ -13,23 +13,24 @@ var aCtxForModel = contextTestHelpers.aCtxForModel;
var uid = require('./helpers/uid-generator'); var uid = require('./helpers/uid-generator');
var getLastGeneratedUid = uid.last; var getLastGeneratedUid = uid.last;
var HookMonitor = require('./helpers/hook-monitor');
module.exports = function(dataSource, should, connectorCapabilities) { module.exports = function(dataSource, should, connectorCapabilities) {
if (!connectorCapabilities) connectorCapabilities = {}; if (!connectorCapabilities) connectorCapabilities = {};
if (connectorCapabilities.replaceOrCreateReportsNewInstance === undefined) { if (connectorCapabilities.replaceOrCreateReportsNewInstance === undefined) {
console.warn('The connector does not support a recently added feature: replaceOrCreateReportsNewInstance'); console.warn('The connector does not support a recently added feature: replaceOrCreateReportsNewInstance');
} }
describe('Persistence hooks', function() { describe('Persistence hooks', function() {
var ctxRecorder, expectedError, observersCalled; var ctxRecorder, hookMonitor, expectedError;
var TestModel, existingInstance; var TestModel, existingInstance;
var migrated = false; var migrated = false;
var triggered;
var undefinedValue = undefined; var undefinedValue = undefined;
beforeEach(function setupDatabase(done) { beforeEach(function setupDatabase(done) {
ctxRecorder = new ContextRecorder('hook not called'); ctxRecorder = new ContextRecorder('hook not called');
hookMonitor = new HookMonitor({ includeModelName: false });
expectedError = new Error('test error'); expectedError = new Error('test error');
observersCalled = [];
TestModel = dataSource.createModel('TestModel', { TestModel = dataSource.createModel('TestModel', {
// Set id.generated to false to honor client side values // Set id.generated to false to honor client side values
@ -76,7 +77,7 @@ module.exports = function(dataSource, should, connectorCapabilities) {
function(err, list) { function(err, list) {
if (err) return done(err); if (err) return done(err);
triggered.should.eql([ hookMonitor.names.should.eql([
'access', 'access',
'loaded' 'loaded'
]); ]);
@ -186,7 +187,7 @@ module.exports = function(dataSource, should, connectorCapabilities) {
function(err, record, created) { function(err, record, created) {
if (err) return done(err); if (err) return done(err);
triggered.should.eql([ hookMonitor.names.should.eql([
'before save', 'before save',
'persist', 'persist',
'loaded', 'loaded',
@ -552,7 +553,7 @@ module.exports = function(dataSource, should, connectorCapabilities) {
{ name: 'new-record' }, { name: 'new-record' },
function(err, record, created) { function(err, record, created) {
if (err) return done(err); if (err) return done(err);
triggered.should.eql([ hookMonitor.names.should.eql([
'access', 'access',
'before save', 'before save',
'persist', 'persist',
@ -573,14 +574,14 @@ module.exports = function(dataSource, should, connectorCapabilities) {
if (err) return done(err); if (err) return done(err);
if (dataSource.connector.findOrCreate) { if (dataSource.connector.findOrCreate) {
triggered.should.eql([ hookMonitor.names.should.eql([
'access', 'access',
'before save', 'before save',
'persist', 'persist',
'loaded' 'loaded'
]); ]);
} else { } else {
triggered.should.eql([ hookMonitor.names.should.eql([
'access', 'access',
'loaded' 'loaded'
]); ]);
@ -931,7 +932,7 @@ module.exports = function(dataSource, should, connectorCapabilities) {
existingInstance.save( existingInstance.save(
function(err, record, created) { function(err, record, created) {
if (err) return done(err); if (err) return done(err);
triggered.should.eql([ hookMonitor.names.should.eql([
'before save', 'before save',
'persist', 'persist',
'loaded', 'loaded',
@ -1143,7 +1144,7 @@ module.exports = function(dataSource, should, connectorCapabilities) {
{ name: 'changed' }, { name: 'changed' },
function(err, record, created) { function(err, record, created) {
if (err) return done(err); if (err) return done(err);
triggered.should.eql([ hookMonitor.names.should.eql([
'before save', 'before save',
'persist', 'persist',
'loaded', 'loaded',
@ -1399,7 +1400,7 @@ module.exports = function(dataSource, should, connectorCapabilities) {
{ name: 'replaced' }, { name: 'replaced' },
function(err, record, created) { function(err, record, created) {
if (err) return done(err); if (err) return done(err);
triggered.should.eql([ hookMonitor.names.should.eql([
'before save', 'before save',
'persist', 'persist',
'loaded', 'loaded',
@ -1642,7 +1643,7 @@ module.exports = function(dataSource, should, connectorCapabilities) {
{ id: 'not-found', name: 'not found' }, { id: 'not-found', name: 'not found' },
function(err, record, created) { function(err, record, created) {
if (err) return done(err); if (err) return done(err);
triggered.should.eql([ hookMonitor.names.should.eql([
'access', 'access',
'before save', 'before save',
'persist', 'persist',
@ -1661,7 +1662,7 @@ module.exports = function(dataSource, should, connectorCapabilities) {
function(err, record, created) { function(err, record, created) {
if (err) return done(err); if (err) return done(err);
if (dataSource.connector.updateOrCreate) { if (dataSource.connector.updateOrCreate) {
triggered.should.eql([ hookMonitor.names.should.eql([
'access', 'access',
'before save', 'before save',
'persist', 'persist',
@ -1669,7 +1670,7 @@ module.exports = function(dataSource, should, connectorCapabilities) {
'after save' 'after save'
]); ]);
} else { } else {
triggered.should.eql([ hookMonitor.names.should.eql([
'access', 'access',
'loaded', 'loaded',
'before save', 'before save',
@ -1766,8 +1767,7 @@ module.exports = function(dataSource, should, connectorCapabilities) {
}); });
it('triggers hooks only once', function(done) { it('triggers hooks only once', function(done) {
TestModel.observe('access', pushNameAndNext('access')); monitorHookExecution(['access', 'before save']);
TestModel.observe('before save', pushNameAndNext('before save'));
TestModel.observe('access', function(ctx, next) { TestModel.observe('access', function(ctx, next) {
ctx.query = { where: { id: { neq: existingInstance.id } } }; ctx.query = { where: { id: { neq: existingInstance.id } } };
@ -1778,7 +1778,7 @@ module.exports = function(dataSource, should, connectorCapabilities) {
{ id: 'ignored', name: 'new name' }, { id: 'ignored', name: 'new name' },
function(err, instance) { function(err, instance) {
if (err) return done(err); if (err) return done(err);
observersCalled.should.eql(['access', 'before save']); hookMonitor.names.should.eql(['access', 'before save']);
done(); done();
}); });
}); });
@ -2097,7 +2097,7 @@ module.exports = function(dataSource, should, connectorCapabilities) {
{ id: 'not-found', name: 'not found' }, { id: 'not-found', name: 'not found' },
function(err, record, created) { function(err, record, created) {
if (err) return done(err); if (err) return done(err);
triggered.should.eql([ hookMonitor.names.should.eql([
'access', 'access',
'before save', 'before save',
'persist', 'persist',
@ -2116,7 +2116,7 @@ module.exports = function(dataSource, should, connectorCapabilities) {
function(err, record, created) { function(err, record, created) {
if (err) return done(err); if (err) return done(err);
if (dataSource.connector.replaceOrCreate) { if (dataSource.connector.replaceOrCreate) {
triggered.should.eql([ hookMonitor.names.should.eql([
'access', 'access',
'before save', 'before save',
'persist', 'persist',
@ -2133,7 +2133,7 @@ module.exports = function(dataSource, should, connectorCapabilities) {
// loopback-datasource-juggler/issues#836. // loopback-datasource-juggler/issues#836.
// 2) It, also, gets triggered in "replaceAttributes()" // 2) It, also, gets triggered in "replaceAttributes()"
// in this chain replaceORCreate()->replaceAttributes() // in this chain replaceORCreate()->replaceAttributes()
triggered.should.eql([ hookMonitor.names.should.eql([
'access', 'access',
'loaded', 'loaded',
'before save', 'before save',
@ -2230,8 +2230,7 @@ module.exports = function(dataSource, should, connectorCapabilities) {
}); });
it('triggers hooks only once', function(done) { it('triggers hooks only once', function(done) {
TestModel.observe('access', pushNameAndNext('access')); monitorHookExecution(['access', 'before save']);
TestModel.observe('before save', pushNameAndNext('before save'));
TestModel.observe('access', function(ctx, next) { TestModel.observe('access', function(ctx, next) {
ctx.query = { where: { id: { neq: existingInstance.id } } }; ctx.query = { where: { id: { neq: existingInstance.id } } };
@ -2242,7 +2241,7 @@ module.exports = function(dataSource, should, connectorCapabilities) {
{ id: 'ignored', name: 'new name' }, { id: 'ignored', name: 'new name' },
function(err, instance) { function(err, instance) {
if (err) return done(err); if (err) return done(err);
observersCalled.should.eql(['access', 'before save']); hookMonitor.names.should.eql(['access', 'before save']);
done(); done();
}); });
}); });
@ -2802,8 +2801,7 @@ module.exports = function(dataSource, should, connectorCapabilities) {
}); });
it('triggers hooks only once', function(done) { it('triggers hooks only once', function(done) {
TestModel.observe('access', pushNameAndNext('access')); monitorHookExecution();
TestModel.observe('after delete', pushNameAndNext('after delete'));
TestModel.observe('access', function(ctx, next) { TestModel.observe('access', function(ctx, next) {
ctx.query = { where: { id: { neq: existingInstance.id } } }; ctx.query = { where: { id: { neq: existingInstance.id } } };
next(); next();
@ -2811,7 +2809,7 @@ module.exports = function(dataSource, should, connectorCapabilities) {
existingInstance.delete(function(err) { existingInstance.delete(function(err) {
if (err) return done(err); if (err) return done(err);
observersCalled.should.eql(['access', 'after delete']); hookMonitor.names.should.eql(['access', 'before delete', 'after delete']);
done(); done();
}); });
}); });
@ -2973,13 +2971,6 @@ module.exports = function(dataSource, should, connectorCapabilities) {
}); });
function pushNameAndNext(name) {
return function(context, next) {
observersCalled.push(name);
next();
};
}
function nextWithError(err) { function nextWithError(err) {
return function(context, next) { return function(context, next) {
next(err); next(err);
@ -3010,13 +3001,8 @@ module.exports = function(dataSource, should, connectorCapabilities) {
TestModel.findOne({ where: { id: id } }, { notify: false }, cb); TestModel.findOne({ where: { id: id } }, { notify: false }, cb);
} }
function monitorHookExecution() { function monitorHookExecution(hookNames) {
triggered = []; hookMonitor.install(TestModel, hookNames);
TestModel._notify = TestModel.notifyObserversOf;
TestModel.notifyObserversOf = function(operation, context, callback) {
triggered.push(operation);
this._notify.apply(this, arguments);
};
} }
}); });