Home Reference Source Test

test/generic/TransactionInMemory.spec.js

describe('Transaction with InMemoryBackend', () => {
    let objectStore, tx, allKeys, allValues;

    const setEqual = function(actual, expected) {
        return expected.equals(actual);
    };

    function subValue(result) {
        const subResult = new Set();
        if (result) {
            for (const v of result) {
                subResult.add(v.sub);
            }
        }
        return subResult;
    }

    beforeEach((done) => {
        objectStore = new ObjectStore(new UnsynchronousBackend(new InMemoryBackend()), null);
        allKeys = new Set();
        allValues = new Set();

        (async function () {
            objectStore.createIndex('i');

            // Add 10 objects.
            for (let i=0; i<10; ++i) {
                await objectStore.put(`key${i}`, { i: i, sub: `value${i}` });
                if (i > 0 && i < 5) {
                    allKeys.add(`key${i}`);
                    allValues.add(`value${i}`);
                }
            }

            tx = objectStore.transaction();

            for (let i=5; i<15; ++i) {
                await tx.put(`key${i}`, { i: i, sub: `newValue${i}` });
                allKeys.add(`key${i}`);
                allValues.add(`newValue${i}`);
            }

            await tx.remove('key0');
        })().then(done, done.fail);

        jasmine.addCustomEqualityTester(setEqual);
    });

    it('correctly processes keys/values queries', (done) => {
        (async function () {
            // Ordering on strings might not be as expected!
            expect(await tx.keys()).toEqual(allKeys);
            expect(await tx.keys(KeyRange.upperBound('key5'))).toEqual(new Set(['key1', 'key2', 'key3', 'key4', 'key5', 'key10', 'key11', 'key12', 'key13', 'key14']));
            expect(await tx.keys(KeyRange.lowerBound('key1', true))).toEqual(allKeys.difference(['key1']));
            expect(await tx.keys(KeyRange.lowerBound('key5', true))).toEqual(new Set(['key6', 'key7', 'key8', 'key9']));

            expect(subValue(await tx.values())).toEqual(allValues);
        })().then(done, done.fail);
    });

    it('correctly processes min/max queries', (done) => {
        (async function () {
            expect(await tx.minKey()).toBe('key1');
            expect(await tx.maxKey()).toBe('key9');
            expect(await tx.minKey(KeyRange.upperBound('key5'))).toBe('key1');
            expect(await tx.minKey(KeyRange.lowerBound('key1', true))).toBe('key10');
            expect(await tx.minKey(KeyRange.lowerBound('key5', true))).toBe('key6');

            expect((await tx.minValue()).sub).toBe('value1');
            expect((await tx.maxValue()).sub).toBe('newValue9');
            expect((await tx.minValue(KeyRange.upperBound('key5'))).sub).toBe('value1');
            expect((await tx.minValue(KeyRange.lowerBound('key1', true))).sub).toBe('newValue10');
            expect((await tx.minValue(KeyRange.lowerBound('key5', true))).sub).toBe('newValue6');
        })().then(done, done.fail);
    });

    it('does not allow changes after abort', (done) => {
        (async function () {
            await tx.abort();

            try {
                await tx.put('test', 'fail');
                done.fail('did not throw');
            } catch (e) {
                // all ok
                expect(true).toBe(true);
            }

            try {
                await tx.remove('test');
                done.fail('did not throw');
            } catch (e) {
                // all ok
                expect(true).toBe(true);
            }
        })().then(done, done.fail);
    });

    it('does not allow changes after commit', (done) => {
        (async function () {
            await tx.commit();

            try {
                await tx.put('test', 'fail');
                done.fail('did not throw');
            } catch (e) {
                // all ok
                expect(true).toBe(true);
            }

            try {
                await tx.remove('test');
                done.fail('did not throw');
            } catch (e) {
                // all ok
                expect(true).toBe(true);
            }
        })().then(done, done.fail);
    });

    it('correctly processes min/max index queries', (done) => {
        (async function () {
            const index = tx.index('i');
            expect(await index.minKeys()).toEqual(new Set(['key1']));
            expect(await index.maxKeys()).toEqual(new Set(['key14']));
            expect(await index.minKeys(KeyRange.upperBound(5))).toEqual(new Set(['key1']));
            expect(await index.minKeys(KeyRange.lowerBound(1, true))).toEqual(new Set(['key2']));
            expect(await index.minKeys(KeyRange.lowerBound(5, true))).toEqual(new Set(['key6']));

            expect(subValue(await index.minValues())).toEqual(new Set(['value1']));
            expect(subValue(await index.maxValues())).toEqual(new Set(['newValue14']));
            expect(subValue(await index.minValues(KeyRange.upperBound(5)))).toEqual(new Set(['value1']));
            expect(subValue(await index.minValues(KeyRange.lowerBound(1, true)))).toEqual(new Set(['value2']));
            expect(subValue(await index.minValues(KeyRange.lowerBound(5, true)))).toEqual(new Set(['newValue6']));
        })().then(done, done.fail);
    });
});