"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
/**
 * Test the delta generated from two key/value stores
 *
 *  Copyright (C) 2010-2019 R-T Specialty, LLC.
 *
 *  This file is part of liza.
 *
 *  liza is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 */
var delta_1 = require("../../src/bucket/delta");
var chai_1 = require("chai");
chai_1.use(require('chai-as-promised'));
describe('Delta', function () {
    describe('#createDelta', function () {
        [
            {
                label: 'No changes are made, key is dropped',
                src_data: { foo: ['bar', 'baz'] },
                dest_data: { foo: ['bar', 'baz'] },
                expected: {},
            },
            {
                label: 'Only the unchanged key is dropped',
                src_data: { foo: ['bar', 'baz'], bar: ['qwe'] },
                dest_data: { foo: ['bar', 'baz'], bar: ['asd'] },
                expected: { bar: ['asd'] },
            },
            {
                label: 'Changed values are updated by index with old value',
                src_data: { foo: ['bar', 'baz', 'quux'] },
                dest_data: { foo: ['bar', 'quuux'], moo: ['cow'] },
                expected: { foo: [undefined, 'quuux', null], moo: ['cow'] },
            },
            {
                label: 'The keys are null when they do not exist in first set',
                src_data: {},
                dest_data: { foo: ['bar', 'quuux'], moo: ['cow'] },
                expected: { foo: ['bar', 'quuux'], moo: ['cow'] },
            },
            {
                label: 'Removed keys in new set show up',
                src_data: { foo: ['bar'] },
                dest_data: {},
                expected: { foo: null },
            },
            {
                label: 'Indexes after a null terminator are not included',
                src_data: { foo: ['one', 'two', 'three', 'four'] },
                dest_data: { foo: ['one', 'done'] },
                expected: { foo: [undefined, 'done', null] },
            },
            {
                label: 'Consider nested arrays to be scalar values',
                src_data: { foo: [['one'], ['two', 'three']] },
                dest_data: { foo: [['one'], ['two']] },
                expected: { foo: [undefined, ['two']] },
            },
            {
                label: 'Do not evaluate zeros as falsy',
                src_data: { foo: [0] },
                dest_data: { foo: [0] },
                expected: {},
            },
            {
                label: 'Do not evaluate empty strings as falsy',
                src_data: { foo: [''] },
                dest_data: { foo: [''] },
                expected: {},
            },
        ].forEach(function (_a) {
            var label = _a.label, src_data = _a.src_data, dest_data = _a.dest_data, expected = _a.expected;
            it(label, function () {
                chai_1.expect(delta_1.createDelta(src_data, dest_data)).to.deep.equal(expected);
            });
        });
    });
    describe('#applyDelta', function () {
        [
            {
                label: 'Empty delta changes nothing',
                bucket: { foo: ['bar', 'baz'] },
                delta: {},
                expected: { foo: ['bar', 'baz'] },
            },
            {
                label: 'Undefined delta changes nothing',
                bucket: { foo: ['bar', 'baz'] },
                delta: undefined,
                expected: { foo: ['bar', 'baz'] },
            },
            {
                label: 'Field not in delta is unchanged',
                bucket: { foo: ['bar', 'baz'], bar: ['qwe'] },
                delta: { bar: ['asd'] },
                expected: { foo: ['bar', 'baz'], bar: ['asd'] },
            },
            {
                label: 'Undefined does not affect its corresponding index',
                bucket: { foo: ['bar', 'baz', 'quux'] },
                delta: { foo: [undefined, 'quuux', null], moo: ['cow'] },
                expected: { foo: ['bar', 'quuux'], moo: ['cow'] },
            },
            {
                label: 'Delta applys correctly on empty bucket',
                bucket: {},
                delta: { foo: ['bar', 'quuux'], moo: ['cow'] },
                expected: { foo: ['bar', 'quuux'], moo: ['cow'] },
            },
            {
                label: 'Keys are removed properly',
                bucket: { foo: ['bar'] },
                delta: { foo: null },
                expected: {},
            },
            {
                label: 'Indexes after a null terminator are not included',
                bucket: { foo: ['one', 'two', 'three', 'four'] },
                delta: { foo: [undefined, 'done', null] },
                expected: { foo: ['one', 'done'] },
            },
            {
                label: 'Consider nested arrays to be scalar values',
                bucket: { foo: [['one'], ['two', 'three']] },
                delta: { foo: [undefined, ['two']] },
                expected: { foo: [['one'], ['two']] },
            },
            {
                label: 'Do not evaluate zeros as falsy',
                bucket: { foo: [0] },
                delta: {},
                expected: { foo: [0] },
            },
            {
                label: 'Do not evaluate empty strings as falsy',
                bucket: { foo: [''] },
                delta: {},
                expected: { foo: [''] },
            },
        ].forEach(function (_a) {
            var label = _a.label, bucket = _a.bucket, delta = _a.delta, expected = _a.expected;
            it(label, function () {
                chai_1.expect(delta_1.applyDelta(bucket, delta)).to.deep.equal(expected);
            });
        });
    });
    describe('mergeSimilarDeltas', function () {
        [
            {
                label: 'Empty delta array returns null',
                deltas: [],
                expected: null,
            },
            {
                label: 'The most recent timestamp is used',
                deltas: [
                    {
                        type: 'data',
                        concluding_save: false,
                        timestamp: 234,
                        step_id: 1,
                        data: { foo: [''] },
                    },
                    {
                        type: 'data',
                        concluding_save: false,
                        timestamp: 123,
                        step_id: 1,
                        data: { foo: [''] },
                    },
                ],
                expected: {
                    type: 'data',
                    concluding_save: false,
                    timestamp: 234,
                    step_id: 1,
                    data: {},
                },
            },
            {
                label: 'The last occuring type is used',
                deltas: [
                    {
                        type: 'foo',
                        concluding_save: false,
                        timestamp: 234,
                        step_id: 1,
                        data: { foo: [''] },
                    },
                    {
                        type: 'bar',
                        concluding_save: false,
                        timestamp: 123,
                        step_id: 1,
                        data: { foo: [''] },
                    },
                ],
                expected: {
                    type: 'bar',
                    concluding_save: false,
                    timestamp: 234,
                    step_id: 1,
                    data: {},
                },
            },
            {
                label: 'The highest step id is used',
                deltas: [
                    {
                        type: 'data',
                        concluding_save: false,
                        timestamp: 123,
                        step_id: 2,
                        data: { foo: [''] },
                    },
                    {
                        type: 'data',
                        concluding_save: false,
                        timestamp: 123,
                        step_id: 1,
                        data: { foo: [''] },
                    },
                ],
                expected: {
                    type: 'data',
                    concluding_save: false,
                    timestamp: 123,
                    step_id: 2,
                    data: {},
                },
            },
            {
                label: 'A single concluding save marks the result as saved',
                deltas: [
                    {
                        type: 'data',
                        concluding_save: false,
                        timestamp: 123,
                        step_id: 1,
                        data: { foo: [''] },
                    },
                    {
                        type: 'data',
                        concluding_save: true,
                        timestamp: 234,
                        step_id: 1,
                        data: { foo: [''] },
                    },
                    {
                        type: 'data',
                        concluding_save: false,
                        timestamp: 234,
                        step_id: 1,
                        data: { foo: [''] },
                    },
                ],
                expected: {
                    type: 'data',
                    concluding_save: true,
                    timestamp: 234,
                    step_id: 1,
                    data: {},
                },
            },
        ].forEach(function (_a) {
            var label = _a.label, deltas = _a.deltas, expected = _a.expected;
            it(label, function () {
                var apply = function (bucket, _) { return bucket; };
                chai_1.expect(delta_1.mergeSimilarDeltas(deltas, apply)).to.deep.equal(expected);
            });
        });
    });
    describe('differentiateDeltas', function () {
        [
            {
                label: 'Empty delta array returns empty array',
                deltas: [],
                expected: [],
            },
            {
                label: 'Two similar types are merged',
                deltas: [
                    {
                        type: 'data',
                        concluding_save: false,
                        timestamp: 123,
                        step_id: 1,
                        data: {},
                    },
                    {
                        type: 'data',
                        concluding_save: false,
                        timestamp: 123,
                        step_id: 1,
                        data: {},
                    },
                ],
                expected: [
                    {
                        type: 'data',
                        concluding_save: false,
                        timestamp: 123,
                        step_id: 1,
                        data: {},
                    },
                ],
            },
            {
                label: 'Two different types are not merged',
                deltas: [
                    {
                        type: 'foo',
                        concluding_save: false,
                        timestamp: 123,
                        step_id: 1,
                        data: {},
                    },
                    {
                        type: 'bar',
                        concluding_save: false,
                        timestamp: 123,
                        step_id: 1,
                        data: {},
                    },
                ],
                expected: [
                    {
                        type: 'foo',
                        concluding_save: false,
                        timestamp: 123,
                        step_id: 1,
                        data: {},
                    },
                    {
                        type: 'bar',
                        concluding_save: false,
                        timestamp: 123,
                        step_id: 1,
                        data: {},
                    },
                ],
            },
            {
                label: 'Two different steps are not merged',
                deltas: [
                    {
                        type: 'foo',
                        concluding_save: false,
                        timestamp: 123,
                        step_id: 2,
                        data: {},
                    },
                    {
                        type: 'foo',
                        concluding_save: false,
                        timestamp: 123,
                        step_id: 1,
                        data: {},
                    },
                ],
                expected: [
                    {
                        type: 'foo',
                        concluding_save: false,
                        timestamp: 123,
                        step_id: 2,
                        data: {},
                    },
                    {
                        type: 'foo',
                        concluding_save: false,
                        timestamp: 123,
                        step_id: 1,
                        data: {},
                    },
                ],
            },
            {
                label: 'Two inner deltas are merged',
                deltas: [
                    {
                        type: 'foo',
                        concluding_save: false,
                        timestamp: 123,
                        step_id: 1,
                        data: {},
                    },
                    {
                        type: 'bar',
                        concluding_save: false,
                        timestamp: 123,
                        step_id: 1,
                        data: {},
                    },
                    {
                        type: 'bar',
                        concluding_save: false,
                        timestamp: 234,
                        step_id: 1,
                        data: {},
                    },
                    {
                        type: 'foo',
                        concluding_save: false,
                        timestamp: 123,
                        step_id: 1,
                        data: {},
                    },
                ],
                expected: [
                    {
                        type: 'foo',
                        concluding_save: false,
                        timestamp: 123,
                        step_id: 1,
                        data: {},
                    },
                    {
                        type: 'bar',
                        concluding_save: false,
                        timestamp: 123,
                        step_id: 1,
                        data: {},
                    },
                    {
                        type: 'foo',
                        concluding_save: false,
                        timestamp: 123,
                        step_id: 1,
                        data: {},
                    },
                ],
            },
            {
                label: 'Two different steps are not merged',
                deltas: [
                    {
                        type: 'foo',
                        concluding_save: false,
                        timestamp: 123,
                        step_id: 1,
                        data: {},
                    },
                    {
                        type: 'foo',
                        concluding_save: false,
                        timestamp: 234,
                        step_id: 2,
                        data: {},
                    },
                    {
                        type: 'foo',
                        concluding_save: false,
                        timestamp: 345,
                        step_id: 2,
                        data: {},
                    },
                    {
                        type: 'foo',
                        concluding_save: false,
                        timestamp: 456,
                        step_id: 1,
                        data: {},
                    },
                ],
                expected: [
                    {
                        type: 'foo',
                        concluding_save: false,
                        timestamp: 123,
                        step_id: 1,
                        data: {},
                    },
                    {
                        type: 'foo',
                        concluding_save: false,
                        timestamp: 234,
                        step_id: 2,
                        data: {},
                    },
                    {
                        type: 'foo',
                        concluding_save: false,
                        timestamp: 456,
                        step_id: 1,
                        data: {},
                    },
                ],
            },
        ].forEach(function (_a) {
            var label = _a.label, deltas = _a.deltas, expected = _a.expected;
            it(label, function () {
                // We don't care about merge logic here so just return the first
                var mergeSimilar = function (deltas) {
                    return deltas.length > 0 ? deltas[0] : null;
                };
                chai_1.expect(delta_1.differentiateDeltas(deltas, mergeSimilar)).to.deep.equal(expected);
            });
        });
    });
    describe('mergeDeltas', function () {
        [
            {
                label: 'Empty delta array returns empty array',
                deltas: [],
                expected: [],
            },
            {
                label: 'Multiple deltas are merged correctly',
                deltas: [
                    {
                        type: 'data',
                        concluding_save: false,
                        timestamp: 1592574639,
                        step_id: 1,
                        data: {
                            hired_non_owned_auto: [''],
                        },
                    },
                    {
                        type: 'data',
                        concluding_save: false,
                        timestamp: 1592574641,
                        step_id: 1,
                        data: {
                            blanket_ai: [''],
                        },
                    },
                    {
                        type: 'data',
                        concluding_save: false,
                        timestamp: 1592574642,
                        step_id: 1,
                        data: {
                            scheduled_ai: [''],
                        },
                    },
                    {
                        type: 'data',
                        concluding_save: false,
                        timestamp: 1592574643,
                        step_id: 1,
                        data: {
                            blanket_ai_type_chosen: ['0'],
                            scheduled_ai_type_chosen: ['0'],
                            __tmp_trigger_helper: ['0'],
                            blanket_ai_type: ['0'],
                            blanket_ai_type_desc: ['(Please select)'],
                            blanket_ai_type_chosen_label: ['(Please select)'],
                            scheduled_ai_type: ['0'],
                            scheduled_ai_type_desc: ['(Please select)'],
                            scheduled_ai_type_chosen_label: ['(Please select)'],
                        },
                    },
                ],
                expected: [
                    {
                        type: 'data',
                        concluding_save: false,
                        timestamp: 1592574643,
                        step_id: 1,
                        data: {
                            hired_non_owned_auto: [''],
                            blanket_ai: [''],
                            scheduled_ai: [''],
                            blanket_ai_type_chosen: ['0'],
                            scheduled_ai_type_chosen: ['0'],
                            __tmp_trigger_helper: ['0'],
                            blanket_ai_type: ['0'],
                            blanket_ai_type_desc: ['(Please select)'],
                            blanket_ai_type_chosen_label: ['(Please select)'],
                            scheduled_ai_type: ['0'],
                            scheduled_ai_type_desc: ['(Please select)'],
                            scheduled_ai_type_chosen_label: ['(Please select)'],
                        },
                    },
                ],
            },
        ].forEach(function (_a) {
            var label = _a.label, deltas = _a.deltas, expected = _a.expected;
            it(label, function () {
                chai_1.expect(delta_1.mergeDeltas(deltas)).to.deep.equal(expected);
            });
        });
    });
});
//# sourceMappingURL=data:application/json;base64, 