UNPKG

@worldbrain/storex-sync

Version:

Offline-first syncing between multiple databases using Storex

145 lines 9.3 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var storex_1 = require("@worldbrain/storex"); var expect = require("expect"); var default_1 = require("./default"); function test(_a) { var logEntries = _a.logEntries, expectedOperations = _a.expectedOperations; var storageRegistry = new storex_1.StorageRegistry(); storageRegistry.registerCollections({ list: { version: new Date('2019-02-02'), fields: { title: { type: 'string' }, } }, listEntry: { version: new Date('2019-02-02'), fields: { title: { type: 'string' }, url: { type: 'string' }, } } }); var reconciled = default_1.reconcileSyncLog(logEntries, { storageRegistry: storageRegistry }); if (expectedOperations) { expect(reconciled).toEqual(expectedOperations); } } describe('Reconciliation', function () { it('should choose the newest write when finding two entries for the same object field', function () { var logEntries = [ { operation: 'modify', createdOn: 2, sharedOn: null, needsIntegration: true, collection: 'list', pk: 'list-one', field: 'title', value: 'second' }, { operation: 'modify', createdOn: 1, sharedOn: null, needsIntegration: true, collection: 'list', pk: 'list-one', field: 'title', value: 'first' }, ]; test({ logEntries: logEntries, expectedOperations: [ { operation: 'updateOneObject', collection: 'list', args: [{ id: 'list-one' }, { title: 'second' }] } ] }); }); it('should choose the newest write when finding more than two entries for the same object field', function () { var logEntries = [ { operation: 'modify', createdOn: 2, sharedOn: null, needsIntegration: true, collection: 'list', pk: 'list-one', field: 'title', value: 'second' }, { operation: 'modify', createdOn: 3, sharedOn: null, needsIntegration: true, collection: 'list', pk: 'list-one', field: 'title', value: 'third' }, { operation: 'modify', createdOn: 1, sharedOn: null, needsIntegration: true, collection: 'list', pk: 'list-one', field: 'title', value: 'first' }, ]; test({ logEntries: logEntries, expectedOperations: [ { operation: 'updateOneObject', collection: 'list', args: [{ id: 'list-one' }, { title: 'third' }] } ] }); }); it('should ignore writes to an object that needs deletion', function () { var logEntries = [ { operation: 'modify', createdOn: 2, sharedOn: null, needsIntegration: true, collection: 'list', pk: 'list-one', field: 'title', value: 'second' }, { operation: 'delete', createdOn: 1, sharedOn: null, needsIntegration: true, collection: 'list', pk: 'list-one' }, ]; test({ logEntries: logEntries, expectedOperations: [ { operation: 'deleteOneObject', collection: 'list', args: [{ id: 'list-one' }] } ] }); }); it('should ignore writes to an already deleted object', function () { var logEntries = [ { operation: 'modify', createdOn: 2, sharedOn: null, needsIntegration: true, collection: 'list', pk: 'list-one', field: 'title', value: 'second' }, { operation: 'delete', createdOn: 4, sharedOn: 3, needsIntegration: true, collection: 'list', pk: 'list-one' }, { operation: 'delete', createdOn: 1, sharedOn: 3, needsIntegration: true, collection: 'list', pk: 'list-one' }, ]; test({ logEntries: logEntries, expectedOperations: [] }); }); it('should work with only one delete', function () { var logEntries = [ { operation: 'delete', createdOn: 1, sharedOn: null, needsIntegration: true, collection: 'list', pk: 'list-one' }, ]; test({ logEntries: logEntries, expectedOperations: [ { operation: 'deleteOneObject', collection: 'list', args: [{ id: 'list-one' }] } ] }); }); it('should ignore double deletes', function () { var logEntries = [ { operation: 'delete', createdOn: 4, sharedOn: null, needsIntegration: true, collection: 'list', pk: 'list-one' }, { operation: 'delete', createdOn: 1, sharedOn: null, needsIntegration: true, collection: 'list', pk: 'list-one' }, ]; test({ logEntries: logEntries, expectedOperations: [ { operation: 'deleteOneObject', collection: 'list', args: [{ id: 'list-one' }] } ] }); }); it('should work with deletes having compound keys', function () { var logEntries = [ { operation: 'delete', createdOn: 4, sharedOn: null, needsIntegration: true, collection: 'listEntry', pk: ['list-one', 3] }, ]; test({ logEntries: logEntries, expectedOperations: [ { operation: 'deleteOneObject', collection: 'listEntry', args: [{ id: ['list-one', 3] }] } ] }); }); it('should ignore writes that are already synced', function () { var logEntries = [ { operation: 'modify', createdOn: 1, sharedOn: null, needsIntegration: true, collection: 'list', pk: 'list-one', field: 'title', value: 'second' }, { operation: 'modify', createdOn: 2, sharedOn: 3, needsIntegration: true, collection: 'list', pk: 'list-one', field: 'title', value: 'second' }, ]; test({ logEntries: logEntries, expectedOperations: [] }); }); it('should create objects', function () { var logEntries = [ { operation: 'create', createdOn: 1, sharedOn: null, needsIntegration: true, collection: 'list', pk: 'list-one', value: { title: 'first' } } ]; test({ logEntries: logEntries, expectedOperations: [ { operation: 'createObject', collection: 'list', args: { id: 'list-one', title: 'first' } } ] }); }); it('should consolidate object creation with object updates', function () { var logEntries = [ { operation: 'modify', createdOn: 2, sharedOn: null, needsIntegration: true, collection: 'list', pk: 'list-one', field: 'title', value: 'second' }, { operation: 'create', createdOn: 1, sharedOn: null, needsIntegration: true, collection: 'list', pk: 'list-one', value: { title: 'first', prio: 5 } }, ]; test({ logEntries: logEntries, expectedOperations: [ { operation: 'createObject', collection: 'list', args: { id: 'list-one', title: 'second', prio: 5 } } ] }); }); it('should consolidate object creation with object deletion', function () { var logEntries = [ { operation: 'modify', createdOn: 2, sharedOn: null, needsIntegration: true, collection: 'list', pk: 'list-one', field: 'title', value: 'second' }, { operation: 'create', createdOn: 1, sharedOn: null, needsIntegration: true, collection: 'list', pk: 'list-one', value: { pk: 'list-one', title: 'first', prio: 5 } }, { operation: 'delete', createdOn: 3, sharedOn: null, needsIntegration: true, collection: 'list', pk: 'list-one' }, ]; test({ logEntries: logEntries, expectedOperations: [] }); }); it('should complain about double creates', function () { var logEntries = [ { operation: 'create', createdOn: 1, sharedOn: 1, needsIntegration: true, collection: 'list', pk: 'list-one', value: { pk: 'list-one', title: 'first', prio: 5 } }, { operation: 'create', createdOn: 2, sharedOn: null, needsIntegration: true, collection: 'list', pk: 'list-one', value: { pk: 'list-one', title: 'first', prio: 5 } }, ]; expect(function () { return test({ logEntries: logEntries }); }).toThrow("Detected double create in collection 'list', pk '\"list-one\"'"); }); it('should complain about modifications made to an object before creation', function () { var logEntries = [ { operation: 'modify', createdOn: 1, sharedOn: null, needsIntegration: true, collection: 'list', pk: 'list-one', field: 'title', value: 'second' }, { operation: 'create', createdOn: 2, sharedOn: null, needsIntegration: true, collection: 'list', pk: 'list-one', value: { pk: 'list-one', title: 'first', prio: 5 } }, ]; expect(function () { return test({ logEntries: logEntries }); }).toThrow("Detected modification to collection 'list', pk '\"list-one\"' before it was created (likely pk collision)"); }); it('should complain about modifications made to an object before creation even if received in the right order', function () { var logEntries = [ { operation: 'create', createdOn: 2, sharedOn: null, needsIntegration: true, collection: 'list', pk: 'list-one', value: { pk: 'list-one', title: 'first', prio: 5 } }, { operation: 'modify', createdOn: 1, sharedOn: null, needsIntegration: true, collection: 'list', pk: 'list-one', field: 'title', value: 'second' }, ]; expect(function () { return test({ logEntries: logEntries }); }).toThrow("Detected modification to collection 'list', pk '\"list-one\"' before it was created (likely pk collision)"); }); }); //# sourceMappingURL=default.test.js.map