dojo
Version:
Dojo core is a powerful, lightweight library that makes common tasks quicker and easier. Animate elements, manipulate the DOM, and query with easy CSS syntax, all without sacrificing performance.
308 lines (260 loc) • 8.54 kB
JavaScript
define([
'intern!object',
'intern/chai!assert',
'../../../store/Observable',
'../../../_base/declare',
'dojo/_base/lang',
'dojo/_base/array',
'../../../store/Memory',
'sinon'
], function (registerSuite, assert, Observable, declare, lang, array, Memory, sinon) {
function createMyStore() {
var MyStore = declare([ Memory ], {
get: function () {
// need to make sure that this.inherited still works with Observable
return this.inherited(arguments);
}
});
var storeData = [
{ id: 0, name: 'zero', even: true, prime: false },
{ id: 1, name: 'one', prime: false },
{ id: 2, name: 'two', even: true, prime: true },
{ id: 3, name: 'three', prime: true },
{ id: 4, name: 'four', even: true, prime: false },
{ id: 5, name: 'five', prime: true }
];
return new Observable(new MyStore({ data: storeData }));
}
function createBigStore() {
var data = [], i;
for (i = 1; i <= 100; i++) {
data.push({ id: i, name: 'item ' + i, order: i });
}
/* jshint newcap:false */
return Observable(new Memory({ data: data }));
}
registerSuite({
name: 'dojo/store/Observable',
'.get': function () {
var store = createMyStore();
assert.equal(store.get(1).name, 'one');
assert.equal(store.get(4).name, 'four');
assert.isTrue(store.get(5).prime);
},
'.query': {
'empty query options': function () {
var store = createMyStore();
var results = store.query({});
assert.lengthOf(results, 6);
}
},
'.observe': (function () {
var store, handlerStub, results, observer;
return {
beforeEach: function () {
store = createMyStore();
handlerStub = sinon.stub();
results = store.query({ prime: true });
observer = results.observe(handlerStub);
},
'handler receives updates': {
'update an existing matching record to no longer match query': function () {
var record = results[0];
record.prime = false;
store.put(record);
assert.deepEqual(handlerStub.firstCall.args[0], {
id: 2,
name: 'two',
even: true,
prime: false
});
assert.equal(handlerStub.firstCall.args[1], 0);
assert.equal(handlerStub.firstCall.args[2], -1);
assert.lengthOf(results, 2);
},
'updating an existing non-matching record to match the query': function () {
var record = store.get(1);
record.prime = true;
store.put(record);
assert.deepEqual(handlerStub.firstCall.args[0], {
id: 1,
name: 'one',
prime: true
});
assert.equal(handlerStub.firstCall.args[1], -1);
assert.equal(handlerStub.firstCall.args[2], 3);
assert.lengthOf(results, 4);
},
'does not receive updates from non-matching additions': function () {
assert.lengthOf(results, 3);
store.add({ id: 6, name: 'six' });
assert.lengthOf(results, 3);
assert.isFalse(handlerStub.called);
},
'adding new matching record': function () {
var record = { id: 7, name: 'seven', prime: true };
store.add(record);
assert.isTrue(handlerStub.called);
assert.deepEqual(handlerStub.firstCall.args[0], record);
assert.equal(handlerStub.firstCall.args[1], -1);
assert.equal(handlerStub.firstCall.args[2], 3);
assert.lengthOf(results, 4);
},
'add new record with options.before and query': function () {
var item2 = store.get(2);
var item7 = {
id: 7,
name: 'seven',
prime: true
};
var item11 = {
id: 11,
name: 'eleven',
prime: true
};
store.add(item7, {
before: item2
});
store.add(item11, {
before: null
});
assert.strictEqual(results[0].id, item7.id);
assert.strictEqual(results[1].id, item2.id);
assert.strictEqual(results[results.length - 1].id, item11.id);
},
'add new record with options.before and no query': function () {
observer.cancel();
results = store.query();
observer = results.observe(handlerStub);
var item0 = store.get(0);
var item7 = {
id: 7,
name: 'seven',
prime: true
};
var item8 = {
id: 8,
name: 'eight',
prime: false
};
store.put(item7, {
before: item0
});
store.put(item8, {
before: null
});
assert.strictEqual(results[0].id, item7.id);
assert.strictEqual(results[1].id, item0.id);
assert.strictEqual(results[results.length - 1].id, item8.id);
},
'update existing record with options.before and query': function () {
var item2 = store.get(2);
var item3 = store.get(3);
var item5 = store.get(5);
store.put(item5, {
before: item3
});
store.put(item2, {
before: null
});
assert.strictEqual(results[0].id, item5.id);
assert.strictEqual(results[1].id, item3.id);
assert.strictEqual(results[results.length - 1].id, item2.id);
},
'update existing record with options.before and no query': function () {
observer.cancel();
results = store.query();
observer = results.observe(handlerStub);
var item0 = store.get(0);
var item1 = store.get(1);
var item5 = store.get(5);
store.put(item5, {
before: item1
});
store.put(item0, {
before: null
});
assert.strictEqual(results[0].id, item5.id);
assert.strictEqual(results[1].id, item1.id);
assert.strictEqual(results[results.length - 1].id, item0.id);
},
includeObjectUpdates: {
beforeEach: function () {
observer.cancel();
},
'is false; does not notify about object updates': function () {
var record = results[0];
results.observe(handlerStub, false);
record.name = 'newName';
store.put(record);
assert.equal(handlerStub.callCount, 0);
},
'is true, notifies about object updates': function () {
var record = results[0];
results.observe(handlerStub, true);
record.name = 'newName';
store.put(record);
assert.equal(handlerStub.callCount, 1);
assert.equal(handlerStub.firstCall.args[1], handlerStub.firstCall.args[2]);
}
}
},
'observer#cancel() halts further updates': function () {
var record = results[0];
// Assert the expected length before altering the data set
assert.lengthOf(results, 3);
// updating the record will change the observed results
record.prime = false;
store.put(record);
assert.lengthOf(results, 2);
assert.lengthOf(store.query({ prime: true }), 2);
assert.equal(handlerStub.callCount, 1);
// cancel observation and the handler is no longer called
// and the results are no longer updated
observer.cancel();
record.prime = true;
store.put(record);
assert.lengthOf(results, 2);
assert.equal(handlerStub.callCount, 1);
// verify that the change did happen but was not tracked
assert.lengthOf(store.query({ prime: true }), 3);
},
'observer#remove() is observer#cancel()': function () {
assert.isFunction(observer.cancel);
assert.equal(observer.cancel, observer.remove);
}
};
})(),
'behaves as a mixin wrapper': function () {
assert.notInstanceOf(createMyStore(), Observable);
assert.notInstanceOf(createBigStore(), Observable);
},
'paging tests': function () {
var options = { count: 25, sort: [{ attribute: 'order' }] };
var bigStore = createBigStore();
var results = [
bigStore.query({}, lang.delegate(options, { start: 0 })),
bigStore.query({}, lang.delegate(options, { start: 25 })),
bigStore.query({}, lang.delegate(options, { start: 50 })),
bigStore.query({}, lang.delegate(options, { start: 75 }))
];
var observeHandler = sinon.stub();
array.forEach(results, function (result) {
result.observe(observeHandler, true);
});
bigStore.add({ id: 101, name: 'one oh one', order: 2.5 });
assert.lengthOf(results[0], 26);
assert.lengthOf(results[1], 25);
assert.lengthOf(results[2], 25);
assert.lengthOf(results[3], 25);
bigStore.remove(101);
assert.equal(observeHandler.callCount, 2);
assert.lengthOf(results[0], 25);
bigStore.add({ id: 102, name: 'one oh two', order: 26.5 });
assert.lengthOf(results[0], 25);
assert.lengthOf(results[1], 26);
assert.lengthOf(results[2], 25);
assert.equal(observeHandler.callCount, 3);
}
});
});