tribe.storage
Version:
Efficient, portable, extensible object storage.
268 lines (245 loc) • 10.6 kB
JavaScript
module.exports = function (options, suite, test, expect, teardown) {
require('./integration.expressions')(options, suite, test, expect, teardown);
suite('tribe.storage.integration.' + options.type, function () {
var storage = require('tribe.storage'),
db;
test("basic store and retrieve", function () {
return open(['p1', 'p2'],
[
{ p1: 1, p2: 'test' },
{ p1: 2, p2: 'test2' }
])
.then(function (container) {
return container.retrieve({ p: 'p1', v: 1 });
})
.then(function (rows) {
expect(rows.length).to.equal(1);
expect(rows[0]).to.deep.equal({ p1: 1, p2: 'test' });
});
});
test("multiple key index store and retrieve", function () {
return open([['p1', 'p2']],
[
{ p1: 'test', p2: 1 },
{ p1: 'test', p2: 2 },
{ p1: 'test', p2: 3 },
{ p1: 'test2', p2: 2 },
])
.then(function (container) {
return container.retrieve([{ p: 'p1', v: 'test' }, { p: 'p2', o: '>=', v: 2 }]);
})
.then(function (rows) {
expect(rows.length).to.equal(2);
});
});
test("complex object store and retrieve", function () {
return open([['p1.p2', 'p3']],
[
{ p1: { p2: 'test' }, p3: 1 },
{ p1: { p2: 'test' }, p3: 1 },
{ p1: { p2: 'test2' }, p3: 1 }
])
.then(function (container) {
return container.retrieve([{ p: 'p1.p2', v: 'test' }, { p: 'p3', v: 1 }]);
})
.then(function (rows) {
expect(rows.length).to.equal(2);
});
});
test("keyPath can be queried", function () {
return open([],
[
{ p2: 'test1' },
{ p2: 'test2' },
{ p2: 'test3' }
], 'p1')
.then(function (container) {
return container.retrieve({ p: 'p1', o: '>=', v: 2 });
})
.then(function (rows) {
expect(rows.length).to.equal(2);
expect(rows).to.deep.equal([{ p1: 2, p2: 'test2' }, { p1: 3, p2: 'test3' }]);
});
});
test("store operation returns entity with autoIncrement keyPath property set", function () {
return open([], [], 'id')
.then(function (container) {
return container.store({});
})
.then(function (updatedEntity) {
expect(updatedEntity).to.deep.equal({ id: 1 });
});
});
test("multiple store operation returns entities with autoIncrement keyPath property set", function () {
return open([], [], 'id')
.then(function (container) {
return container.store([{}, {}]);
})
.then(function (updatedEntity) {
expect(updatedEntity).to.deep.equal([{ id: 1 }, { id: 2 }]);
});
});
test("stored entity has autoIncrement keyPath property set", function () {
var container;
return open([], [], 'id')
.then(function (db) {
container = db;
return container.store({});
})
.then(function () {
return container.retrieve({ p: 'id', v: 1 });
})
.then(function (entities) {
expect(entities.length).to.equal(1);
expect(entities[0]).to.deep.equal({ id: 1 });
});
});
test("single property indexes can be specified and requested as arrays or individually", function () {
var container;
return open(['p1', ['p2']], [
{ p1: 1, p2: 1 },
{ p1: 2, p2: 2 }
])
.then(function (result) {
container = result;
return container.retrieve({ p: 'p1', v: 2 });
})
.then(function (results) {
expect(results.length).to.equal(1);
})
.then(function (result) {
return container.retrieve([{ p: 'p1', v: 2 }]);
})
.then(function (results) {
expect(results.length).to.equal(1);
})
.then(function (result) {
return container.retrieve({ p: 'p2', v: 2 });
})
.then(function (results) {
expect(results.length).to.equal(1);
})
.then(function (result) {
return container.retrieve([{ p: 'p2', v: 2 }]);
})
.then(function (results) {
expect(results.length).to.equal(1);
});
});
test("retrieve sorts by index properties", function () {
var container;
return open([['p1', 'p2.value'], ['p2.value', 'p1']], [
{ p1: 4, p2: { value: 1 } },
{ p1: 3, p2: { value: 2 } },
{ p1: 1, p2: { value: 1 } },
{ p1: 2, p2: { value: 2 } }
])
.then(function (result) {
container = result;
return container.retrieve([{ p: 'p1', o: '>', v: 0 }, { p: 'p2.value', o: '>', v: 0 }]);
})
.then(function (results) {
expect(results).to.deep.equal([
{ p1: 1, p2: { value: 1 } },
{ p1: 2, p2: { value: 2 } },
{ p1: 3, p2: { value: 2 } },
{ p1: 4, p2: { value: 1 } }
]);
return container.retrieve([{ p: 'p2.value', o: '>', v: 0 }, { p: 'p1', o: '>', v: 0 }]);
})
.then(function (results) {
expect(results).to.deep.equal([
{ p1: 1, p2: { value: 1 } },
{ p1: 4, p2: { value: 1 } },
{ p1: 2, p2: { value: 2 } },
{ p1: 3, p2: { value: 2 } }
]);
});
});
test("clear deletes all entities", function () {
var container;
return open(['p1'], [{ p1: 1, p2: 1 }])
.then(function (result) {
container = result;
container.clear();
})
.then(function () {
return container.retrieve({ p: 'p1', v: 1 });
})
.then(function (messages) {
expect(messages.length).to.equal(0);
});
});
test("writes are atomic", function () {
return open(['p1'], [{ p1: 1, p2: 1 }])
.then(function (entity) {
entity.store({ p1: 1, p2: 'test2' });
return entity.retrieve({ p: 'p1', v: 1 });
})
.then(function (results) {
expect(results.length).to.equal(2);
});
});
test("indexes with array values can be queried by individual value", function () {
return open(['p1'],
[
{ p1: [1, 2], p2: 'test' },
{ p1: [2, 3], p2: 'test2' }
])
.then(function (container) {
return container.retrieve({ p: 'p1', v: 1 }).then(function (rows) {
expect(rows.length).to.equal(1);
expect(rows[0]).to.deep.equal({ p1: [1, 2], p2: 'test' });
return container.retrieve({ p: 'p1', v: 2 });
})
.then(function (rows) {
expect(rows.length).to.equal(2);
});
});
});
test("indexes with multiple array values can be queried by individual value", function () {
return open([['p1', 'p2']],
[
{ p1: [1, 2], p2: [1, 3] },
{ p1: [2, 3], p2: [2, 1] },
{ p1: [3, 1], p2: [3, 2] }
])
.then(function (container) {
return container.retrieve([{ p: 'p1', v: 2 }, { p: 'p2', v: 1 }]);
})
.then(function (rows) {
expect(rows.length).to.equal(2);
});
});
test("indexes can handle undefined values", function () {
return open(['p1'],
[
{ p1: 1, p2: 'test' },
{ p2: 'test2' }
])
.then(function (container) {
return container.retrieve({ p: 'p1', v: undefined });
})
.then(function (rows) {
expect(rows.length).to.equal(1);
expect(rows[0]).to.deep.equal({ p2: 'test2' });
});
});
function open(indexes, entities, keyPath) {
var entity;
// simplified behavior is to always autoIncrement
return storage.open([{ name: 'test', indexes: indexes, keyPath: keyPath, autoIncrement: true }], options)
.then(function (provider) {
db = provider;
entity = provider.entity('test');
return entity.store(entities);
})
.then(function () {
return entity;
});
}
teardown(function () {
db.close();
});
});
};