mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 17:28:26 -04:00
Included more tests for the doc source, expanded the capabilities and configurability of the StubbedClient.
This commit is contained in:
parent
41083d6ff2
commit
b4917b7dbd
4 changed files with 292 additions and 36 deletions
|
@ -1,9 +1,177 @@
|
|||
define(function (require) {
|
||||
var createCourier = require('test_utils/create_courier');
|
||||
var stubbedClient = require('test_utils/stubbed_client');
|
||||
var sinon = require('test_utils/auto_release_sinon');
|
||||
var _ = require('lodash');
|
||||
|
||||
return function extendCourierSuite() {
|
||||
describe('DocSource class', function () {
|
||||
it('tracks the version of the document');
|
||||
it('can be used without saving the doc');
|
||||
it('provides a way to keep two objects synced between tabs');
|
||||
it('tracks the version of the document', function (done) {
|
||||
var version = 51;
|
||||
var courier = createCourier(stubbedClient(function (method, params, cb) {
|
||||
cb(void 0, stubbedClient.doc({ _version: version }));
|
||||
}));
|
||||
|
||||
var source = courier
|
||||
.createSource('doc').index('fake').type('fake').id('fake')
|
||||
.on('results', function (doc) {
|
||||
expect(source._getVersion()).to.eql(version);
|
||||
expect(courier._getRefFor(source).version).to.eql(version);
|
||||
done();
|
||||
});
|
||||
|
||||
courier.start();
|
||||
});
|
||||
|
||||
it('updates to a doc will propogate to other docs with the same index/type/id', function (done) {
|
||||
var client = (function () {
|
||||
// fake server state
|
||||
var version = 0;
|
||||
var doc = { hi: 'fallacy' };
|
||||
|
||||
return stubbedClient({
|
||||
update: function (params, cb) {
|
||||
_.assign(doc, params.body.doc);
|
||||
version++;
|
||||
cb(void 0, { ok: true });
|
||||
},
|
||||
default: function (method, params, cb) {
|
||||
cb(void 0, stubbedClient.doc({ _source: doc, _version: version }));
|
||||
}
|
||||
});
|
||||
}());
|
||||
var courier = createCourier(client);
|
||||
|
||||
var update = { hi: 'truth' };
|
||||
|
||||
// updating this
|
||||
var pitcher = courier.createSource('doc').index('fake').type('fake').id('fake')
|
||||
.doUpdate(update);
|
||||
|
||||
// should update this
|
||||
var catcher = courier.createSource('doc').index('fake').type('fake').id('fake')
|
||||
.on('results', function (doc) {
|
||||
expect(doc._source).to.eql(update);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('clears the stored version when a document has been deleted', function (done) {
|
||||
var client = (function () {
|
||||
// fake server state
|
||||
var doc = { hi: 'fallacy' };
|
||||
|
||||
return stubbedClient({
|
||||
delete: function (params, cb) {
|
||||
doc = null;
|
||||
cb(void 0, { ok: true });
|
||||
},
|
||||
default: function (method, params, cb) {
|
||||
if (doc) {
|
||||
cb(void 0, stubbedClient.doc({ _source: doc }));
|
||||
} else {
|
||||
cb(void 0, stubbedClient.doc({ found: false, _source: null, _version: null }));
|
||||
}
|
||||
}
|
||||
});
|
||||
}());
|
||||
var courier = createCourier(client);
|
||||
|
||||
var source = courier.createSource('doc')
|
||||
.index('fake')
|
||||
.type('fake')
|
||||
.id('fake')
|
||||
.on('results', function (doc) {
|
||||
if (doc.found) {
|
||||
client.delete({}, function () {
|
||||
source.fetch();
|
||||
});
|
||||
} else {
|
||||
expect(courier._getRefFor(source).version).to.be(void 0);
|
||||
expect(source._getVersion()).to.be(void 0);
|
||||
done();
|
||||
}
|
||||
});
|
||||
|
||||
courier.start();
|
||||
});
|
||||
|
||||
it('checks localStorage for changes to the stored version, which will trigger the doc to be refetched', function (done) {
|
||||
var version = 11234;
|
||||
var courier = createCourier(stubbedClient(function (method, params, cb) {
|
||||
cb(void 0, stubbedClient.doc({ _version: version }));
|
||||
}));
|
||||
|
||||
var count = 0;
|
||||
courier.docInterval(10);
|
||||
|
||||
var source = courier.createSource('doc')
|
||||
.index('fake')
|
||||
.type('fake')
|
||||
.id('fake')
|
||||
.on('results', function (doc) {
|
||||
switch (count++) {
|
||||
case 0:
|
||||
// simulate removing the version in another tab
|
||||
localStorage.removeItem(source._versionKey());
|
||||
// get version should now be returning undefined
|
||||
expect(source._getVersion()).to.eql(void 0);
|
||||
// tell the courier to check docs 1 ms now
|
||||
courier.docInterval(1);
|
||||
break;
|
||||
case 1:
|
||||
// doc version should now be populated
|
||||
expect(source._getVersion()).to.eql(version);
|
||||
done();
|
||||
}
|
||||
});
|
||||
|
||||
courier.start();
|
||||
});
|
||||
|
||||
describe('#doIndex', function () {
|
||||
it('reindexes the doc using the hash passed in', function (done) {
|
||||
var client = (function () {
|
||||
var version = 1;
|
||||
var doc = { initial: true };
|
||||
|
||||
return stubbedClient({
|
||||
index: function (params, cb) {
|
||||
doc = _.clone(params.body);
|
||||
version ++;
|
||||
cb(void 0, { ok: true });
|
||||
},
|
||||
mget: function (params, cb) {
|
||||
cb(void 0, stubbedClient.doc({ _version: version, _source: doc }));
|
||||
}
|
||||
});
|
||||
}());
|
||||
var courier = createCourier(client);
|
||||
|
||||
var count = 0;
|
||||
courier.docInterval(10);
|
||||
|
||||
var source = courier.createSource('doc')
|
||||
.index('fake')
|
||||
.type('fake')
|
||||
.id('fake')
|
||||
.on('results', function (doc) {
|
||||
switch (count ++) {
|
||||
case 0:
|
||||
expect(doc._source).to.have.property('initial', true);
|
||||
source.doIndex({ second: true });
|
||||
break;
|
||||
case 1:
|
||||
expect(doc._source).to.not.have.property('initial');
|
||||
expect(doc._source).to.have.property('second', true);
|
||||
done();
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
courier.start();
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
||||
});
|
|
@ -6,13 +6,12 @@ define(function (require) {
|
|||
describe('events', function () {
|
||||
describe('error', function () {
|
||||
it('emits when the client fails', function (done) {
|
||||
var err = new Error('Error!');
|
||||
var courier = createCourier({
|
||||
client: stubbedClient(function (method, params, cb) { cb(err); })
|
||||
client: stubbedClient(function (method, params, cb) { cb(new Error()); })
|
||||
});
|
||||
|
||||
courier.on('error', function (emittedError) {
|
||||
expect(emittedError).to.be(err);
|
||||
expect(emittedError).to.be.an(Error);
|
||||
done();
|
||||
});
|
||||
|
||||
|
|
|
@ -1,10 +1,26 @@
|
|||
define(function (require) {
|
||||
|
||||
var Courier = require('courier/courier');
|
||||
var EsTransport = require('bower_components/elasticsearch/elasticsearch').Transport;
|
||||
var StubbedClient = require('test_utils/stubbed_client');
|
||||
var _ = require('lodash');
|
||||
|
||||
var activeCouriers = [];
|
||||
function createCourier(opts) {
|
||||
// allow passing in a client directly
|
||||
if (
|
||||
opts
|
||||
&& (
|
||||
opts instanceof StubbedClient
|
||||
|| opts.transport instanceof EsTransport
|
||||
)
|
||||
)
|
||||
{
|
||||
opts = {
|
||||
client: opts
|
||||
};
|
||||
}
|
||||
|
||||
var courier = new Courier(opts);
|
||||
|
||||
// after each test this list is cleared
|
||||
|
|
|
@ -1,9 +1,97 @@
|
|||
define(function (require) {
|
||||
|
||||
var _ = require('lodash');
|
||||
|
||||
var nativeSetTimeout = window.setTimeout;
|
||||
var nativeClearTimeout = window.clearTimeout;
|
||||
var methodsToStub = [
|
||||
'msearch',
|
||||
'mget',
|
||||
'index',
|
||||
'update',
|
||||
'delete'
|
||||
];
|
||||
|
||||
var defaultResponses = {
|
||||
msearch: function (params, cb) {
|
||||
cb(null, responses(countMultiRequests(params)));
|
||||
},
|
||||
mget: function (params, cb) {
|
||||
cb(null, responses(countMultiRequests(params)));
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a "client" that will mock several functions
|
||||
* but really just defers to the `respond` method. In many cases
|
||||
* (so far) very simple logic is required to push empty/irrelevent
|
||||
* responses back (which is more than fine for the courier)
|
||||
*
|
||||
* @param {[type]} respond - a function that will be called after a short
|
||||
* timeout to respond in place of a stubbed method.
|
||||
* @return {[type]} [description]
|
||||
*/
|
||||
function StubbedClient(responder) {
|
||||
if (!(this instanceof StubbedClient)) return new StubbedClient(responder);
|
||||
|
||||
var stub = this;
|
||||
|
||||
stub.__responder = responder || defaultResponses;
|
||||
|
||||
if (typeof this.__responder === 'object') {
|
||||
// transform the responder object into a function that can be called like the others
|
||||
stub.__responder = (function (options) {
|
||||
return function (method, params, cb) {
|
||||
if (options[method]) return options[method](params, cb);
|
||||
if (options.default) return options.default(method, params, cb);
|
||||
throw new Error('responder for "default" or "' + method + '" required');
|
||||
};
|
||||
})(stub.__responder);
|
||||
}
|
||||
|
||||
stub.callCount = 0;
|
||||
stub.abortCalled = 0;
|
||||
|
||||
methodsToStub.forEach(function (method) {
|
||||
// count every call to this method
|
||||
stub[method].callCount = 0;
|
||||
});
|
||||
|
||||
return stub;
|
||||
}
|
||||
|
||||
methodsToStub.forEach(function (method) {
|
||||
// create a stub for each method
|
||||
StubbedClient.prototype[method] = function (params, cb) {
|
||||
var stub = this;
|
||||
|
||||
// increment global counters
|
||||
stub.callCount ++;
|
||||
// inc this method's counter
|
||||
stub[method].callCount++;
|
||||
|
||||
if (typeof params === 'function') {
|
||||
// allow calling with just a callback
|
||||
cb = params;
|
||||
params = {};
|
||||
}
|
||||
|
||||
// call the responder after 3 ms to simulate a very quick response
|
||||
var id = nativeSetTimeout(_.partial(stub.__responder, method, params, cb), 3);
|
||||
|
||||
// return an aborter, that has a short but reasonable amount of time to be called
|
||||
return {
|
||||
abort: function () {
|
||||
nativeClearTimeout(id);
|
||||
stub.abortCalled ++;
|
||||
}
|
||||
};
|
||||
};
|
||||
});
|
||||
|
||||
// cound the number of requests in a multi request bulk body
|
||||
function countMultiRequests(params) {
|
||||
return (params.body) ? Math.floor(params.body.split('\n').length / 2) : 0;
|
||||
}
|
||||
|
||||
// create a generic response for N requests
|
||||
function responses(n) {
|
||||
|
@ -27,39 +115,24 @@ define(function (require) {
|
|||
return { responses: resp };
|
||||
}
|
||||
|
||||
function stubbedClient(respond) {
|
||||
respond = respond || function (method, params, cb) {
|
||||
var n = (params.body) ? Math.floor(params.body.split('\n').length / 2) : 0;
|
||||
cb(null, responses(n));
|
||||
};
|
||||
|
||||
var stub = {
|
||||
callCount: 0,
|
||||
abortCalled: 0
|
||||
};
|
||||
|
||||
_.each(['msearch', 'mget'], function (method) {
|
||||
stub[method] = function (params, cb) {
|
||||
stub[method].callCount++;
|
||||
stub.callCount ++;
|
||||
|
||||
var id = nativeSetTimeout(_.partial(respond, method, params, cb), 3);
|
||||
return {
|
||||
abort: function () {
|
||||
nativeClearTimeout(id);
|
||||
stub.abortCalled ++;
|
||||
}
|
||||
};
|
||||
};
|
||||
stub[method].callCount = 0;
|
||||
// create a generic response with a single doc, that uses
|
||||
// the passed in response but fills in some defaults
|
||||
function doc(d) {
|
||||
d = _.defaults(d || {}, {
|
||||
found: true,
|
||||
_version: 1,
|
||||
_source: {}
|
||||
});
|
||||
|
||||
return stub;
|
||||
return {
|
||||
docs: [ d ]
|
||||
};
|
||||
}
|
||||
|
||||
stubbedClient.errorReponses = errorReponses;
|
||||
stubbedClient.responses = responses;
|
||||
StubbedClient.errorReponses = errorReponses;
|
||||
StubbedClient.responses = responses;
|
||||
StubbedClient.doc = doc;
|
||||
|
||||
return stubbedClient;
|
||||
return StubbedClient;
|
||||
|
||||
});
|
Loading…
Add table
Add a link
Reference in a new issue