/**
 * Tests MongoServerDao
 *
 *  Copyright (C) 2010-2019 R-T Specialty, LLC.
 *
 *  This file is part of the Liza Data Collection Framework.
 *
 *  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/>.
 */
'use strict';
Object.defineProperty(exports, "__esModule", { value: true });
var MongoServerDao_1 = require("../../../src/server/db/MongoServerDao");
var chai_1 = require("chai");
chai_1.use(require('chai-as-promised'));
describe('MongoServerDao', function () {
    describe('#saveQuote', function () {
        [
            {
                label: 'will not unset last updated by user when session data is unavailable',
                username: '',
                expected_set_username: undefined,
            },
            {
                label: 'will set last updated by user when session data is available',
                username: 'foo',
                expected_set_username: ['foo'],
            },
        ].forEach(function (_a) {
            var label = _a.label, username = _a.username, expected_set_username = _a.expected_set_username;
            it(label, function (done) {
                var quote = createStubQuote({});
                quote.getUserName = function () { return username; };
                var sut = new MongoServerDao_1.MongoServerDao(createStubCollection(
                // update
                function (_selector, data) {
                    chai_1.expect(data.$set['meta.last_updated_by_username']).to.deep.equal(expected_set_username);
                    done();
                }), createStubCollection(), 'test', function () { return 123; });
                sut.init(function () {
                    return sut.saveQuote(quote, function () { }, function () { });
                });
            });
        });
        describe('with no save data or push data', function () {
            it('saves initial rated (and other fields) individually', function (done) {
                var expected = 123321;
                var expected_username = 'foo@foo.com';
                var expected_agency_num = 'AGT123';
                var expected_start_date = 246;
                var expected_agent_id = '123';
                var expected_agent_name = 'foo';
                var expected_agent_entity_id = 456;
                var quote = createStubQuote({});
                quote.getRatedDate = function () {
                    return expected;
                };
                quote.getUserName = function () { return expected_username; };
                quote.getAgencyNumber = function () { return expected_agency_num; };
                var sut = new MongoServerDao_1.MongoServerDao(createStubCollection(
                // update
                function (_selector, data) {
                    chai_1.expect(data.$set['meta.liza_timestamp_initial_rated']).to.deep.equal([expected]);
                    chai_1.expect(data.$set['startDate']).to.deep.equal(expected_start_date);
                    chai_1.expect(data.$set['agentId']).to.deep.equal(expected_agent_id);
                    chai_1.expect(data.$set['agentName']).to.deep.equal(expected_agent_name);
                    chai_1.expect(data.$set['agentEntityId']).to.deep.equal(expected_agent_entity_id);
                    chai_1.expect(data.$setOnInsert['meta.created_by_username']).to.deep.equal([expected_username]);
                    chai_1.expect(data.$setOnInsert['meta.retail_agency']).to.deep.equal([
                        expected_agency_num,
                    ]);
                    chai_1.expect(data.$push).to.equal(undefined);
                    done();
                }), createStubCollection(), 'test', function () {
                    return 123;
                });
                sut.init(function () {
                    return sut.saveQuote(quote, function () { }, function () { });
                });
            });
        });
        describe('bound by username', function () {
            [
                {
                    label: 'will set bound_by_username when quote is imported',
                    username: 'foo@foo.com',
                    expected_bound_username: ['foo@foo.com'],
                    is_imported: true,
                },
                {
                    label: 'will not set bound_by_username when quote is not imported',
                    username: 'foo@foo.com',
                    expected_bound_username: undefined,
                    is_imported: false,
                },
            ].forEach(function (_a) {
                var label = _a.label, username = _a.username, expected_bound_username = _a.expected_bound_username, is_imported = _a.is_imported;
                it(label, function (done) {
                    var quote = createStubQuote({});
                    quote.getUserName = function () { return username; };
                    quote.isImported = function () { return is_imported; };
                    var sut = new MongoServerDao_1.MongoServerDao(createStubCollection(
                    // update
                    function (_selector, data) {
                        chai_1.expect(data.$set['meta.bound_by_username']).to.deep.equal(expected_bound_username);
                        done();
                    }), createStubCollection(), 'test', function () {
                        return 123;
                    });
                    sut.init(function () {
                        return sut.saveQuote(quote, function () { }, function () { });
                    });
                });
            });
        });
        it('non-persistent fields are not saved', function (done) {
            var bucket_data = {
                foo: ['bar'],
                __internal_user: ['0'],
            };
            var quote = createStubQuote({}, bucket_data);
            var sut = new MongoServerDao_1.MongoServerDao(createStubCollection(
            // update
            function (_selector, data) {
                chai_1.expect(data.$set['data.foo']).to.deep.equal(['bar']);
                chai_1.expect(data.$set['data.__internal_user']).to.be.undefined;
                done();
            }), createStubCollection(), 'test', function () {
                return 123;
            });
            sut.init(function () {
                return sut.saveQuote(quote, function () { }, function () { });
            });
        });
        describe('with force_publish', function () {
            it('forced_reset resets published indicator', function (done) {
                var expected_ts = 12345;
                var quote = createStubQuote({ published: true });
                var sut = new MongoServerDao_1.MongoServerDao(createStubCollection(
                // update
                function (_selector, data) {
                    chai_1.expect(data.$set['published']).to.deep.equal(false);
                    chai_1.expect(data.$set['publishResetTs']).to.deep.equal(expected_ts);
                    done();
                }), createStubCollection(), 'test', function () {
                    return expected_ts;
                });
                sut.init(function () {
                    return sut.saveQuote(quote, function () { }, function () { }, undefined, {}, true);
                });
            });
            it('not forced will not change published indicator', function (done) {
                var quote = createStubQuote({ published: true });
                var sut = new MongoServerDao_1.MongoServerDao(createStubCollection(
                // update
                function (_selector, data) {
                    chai_1.expect(data.$set['published']).to.not.exist;
                    chai_1.expect(data.$set['publishResetTs']).to.not.exist;
                    done();
                }), createStubCollection(), 'test', function () {
                    return 123;
                });
                sut.init(function () {
                    return sut.saveQuote(quote, function () { }, function () { }, undefined, {}, false);
                });
            });
        });
        describe('with push data', function () {
            it('adds push data to the collection', function (done) {
                var push_data = {
                    foo: ['bar', 'baz'],
                    bar: [{ quux: 'quuux' }],
                };
                var quote = createStubQuote({});
                var sut = new MongoServerDao_1.MongoServerDao(createStubCollection(
                // update
                function (_selector, data) {
                    chai_1.expect(data.$push['foo']).to.deep.equal(push_data.foo);
                    chai_1.expect(data.$push['bar']).to.deep.equal(push_data.bar);
                    done();
                }), createStubCollection(), 'test', function () {
                    return 123;
                });
                sut.init(function () {
                    return sut.saveQuote(quote, function () { }, function () { }, undefined, push_data);
                });
            });
            it('skips push data when it is an empty object', function (done) {
                var push_data = {};
                var quote = createStubQuote({});
                var sut = new MongoServerDao_1.MongoServerDao(createStubCollection(
                // update
                function (_selector, data) {
                    chai_1.expect(data.$push).to.equal(undefined);
                    done();
                }), createStubCollection(), 'test', function () {
                    return 123;
                });
                sut.init(function () {
                    return sut.saveQuote(quote, function () { }, function () { }, undefined, push_data);
                });
            });
        });
    });
    describe('#saveQuoteMetaDirect', function () {
        [
            {
                label: 'Merges existing meta data when new meta is not provided',
                new_meta: undefined,
                existing_meta: { old: ['meta data'] },
                expected: { 'meta.old': ['meta data'] },
            },
            {
                label: 'Merges new meta data if provided',
                new_meta: { foo: ['bar'] },
                existing_meta: { this: ['is', 'ignored'] },
                expected: { 'meta.foo': ['bar'] },
            },
            {
                label: 'Merges all indexes of the new meta data',
                new_meta: { foo: ['bar', 'baz', 'qux'] },
                existing_meta: {},
                expected: { 'meta.foo': ['bar', 'baz', 'qux'] },
            },
        ].forEach(function (_a) {
            var label = _a.label, new_meta = _a.new_meta, existing_meta = _a.existing_meta, expected = _a.expected;
            it(label, function (done) {
                var quote = createStubQuote(existing_meta);
                var sut = new MongoServerDao_1.MongoServerDao(createStubCollection(
                // update
                function (_selector, data) {
                    chai_1.expect(data.$set).to.deep.equal(expected);
                    done();
                }), createStubCollection(), 'test', function () { return 123; });
                sut.init(function () {
                    return sut.saveQuoteMetaDirect(quote, new_meta, undefined, undefined);
                });
            });
        });
    });
    describe('#publishQuote', function () {
        [
            {
                label: 'sets quote published',
                publish: true,
                meta_retail_agency: ['AGT23690'],
                expected_liza_access_groups: ['AGT23690'],
            },
            {
                label: 'sets quote not published',
                publish: false,
                meta_retail_agency: ['AGT23690'],
                expected_liza_access_groups: [],
            },
            {
                label: 'set published with blank retail agency',
                publish: true,
                meta_retail_agency: [''],
                expected_liza_access_groups: [''],
            },
            {
                label: 'set published with NO retail_agency',
                publish: true,
                meta_retail_agency: undefined,
                expected_liza_access_groups: undefined,
            },
        ].forEach(function (_a) {
            var label = _a.label, publish = _a.publish, meta_retail_agency = _a.meta_retail_agency, expected_liza_access_groups = _a.expected_liza_access_groups;
            it(label, function (done) {
                var quote = createStubQuote({ retail_agency: meta_retail_agency });
                var published_ts = [123];
                var sut = new MongoServerDao_1.MongoServerDao(createStubCollection(
                // update
                function (_selector, data) {
                    chai_1.expect(data.$set['meta.liza_access_groups']).to.deep.equal(expected_liza_access_groups);
                    chai_1.expect(data.$set['meta.liza_timestamp_owner_vis_updated']).to.deep.equal(published_ts);
                    done();
                }), createStubCollection(), 'test', function () { return 123; });
                sut.init(function () { return sut.publishQuote(quote, publish); });
            });
        });
    });
    describe('#saveState', function () {
        [
            {
                label: 'does not set field state if undefined',
                given: undefined,
                expected: undefined,
            },
            {
                label: 'does not set field state if empty',
                given: {},
                expected: undefined,
            },
            {
                label: 'sets field state if non-empty',
                given: { foo: 1 },
                expected: { foo: 1 },
            },
        ].forEach(function (_a) {
            var label = _a.label, given = _a.given, expected = _a.expected;
            return it(label, function (done) {
                var update_data = { __not: 'updated' };
                var sut = new MongoServerDao_1.MongoServerDao(createStubCollection(
                // update
                function (_selector, data, _options, callback) {
                    update_data = data;
                    callback(null, null);
                }), createStubCollection(), 'test', function () { return 123; });
                var quote = createStubQuote({});
                quote.getFieldState = function () { return given; };
                var success = function () {
                    chai_1.expect(update_data['$set'].fieldState).to.deep.equal(expected);
                    if (expected === undefined) {
                        chai_1.expect(Object.prototype.hasOwnProperty.call(update_data, 'fieldState')).to.be.false;
                    }
                    done();
                };
                var failure = function (e) {
                    throw e;
                };
                sut.saveQuoteState(quote, success, failure);
            });
        });
    });
});
function createStubCollection(onUpdate, result) {
    if (onUpdate === void 0) { onUpdate = function () { }; }
    if (result === void 0) { result = 1; }
    var cursor = createMockCursor(result);
    return {
        update: onUpdate,
        updateOne: onUpdate,
        insertOne: onUpdate,
        find: function () { return cursor; },
    };
}
function createMockCursor(result) {
    if (result === void 0) { result = 1; }
    var cursor = {
        limit: function () { return cursor; },
        project: function () { return cursor; },
        next: function (c) {
            c(null, result);
        },
    };
    return cursor;
}
function createStubQuote(metadata, data) {
    if (data === void 0) { data = {}; }
    var program = {
        clearNaFields: false,
        naFieldValue: '',
        getId: function () { return '1'; },
        ineligibleLockCount: 0,
        cretain: {},
        defaults: {},
        apis: {},
        internal: {},
        autosave: false,
        whens: {},
        groupWhens: {},
        meta: {
            arefs: {},
            fields: {},
            groups: {},
            qdata: {},
            qtypes: {},
        },
        mapis: {},
        rateSteps: [],
        dapi: function () { return ({}); },
        initQuote: function () { },
        getClassifierKnownFields: function () { return ({}); },
        classify: function () { return ({}); },
        hasNaField: function () { return false; },
        hasKnownType: function () { return true; },
        getFirstStepId: function () { return 0; },
        groupExclusiveFields: {},
        processNaFields: function () { },
        groupIndexField: {},
    };
    var quote = {
        getBucket: function () {
            return ({
                getData: function () {
                    return data;
                },
            });
        },
        getMetabucket: function () {
            return ({
                getData: function () { return metadata; },
            });
        },
        getId: function () { return 123; },
        getProgramVersion: function () { return 'Foo'; },
        getLastPremiumDate: function () { return 0; },
        getStartDate: function () { return 246; },
        getAgentId: function () { return 123; },
        getAgentName: function () { return 'foo'; },
        getAgentEntityId: function () { return 456; },
        getUserName: function () { return 'foo@foo.com'; },
        getAgencyNumber: function () { return ''; },
        getRatedDate: function () { return 0; },
        getExplicitLockReason: function () { return ''; },
        getExplicitLockStep: function () { return 1; },
        isImported: function () { return false; },
        isBound: function () { return false; },
        getTopVisitedStepId: function () { return 1; },
        getTopSavedStepId: function () { return 1; },
        setTopSavedStepId: function () { return quote; },
        getMetaUpdatedDate: function () { return 0; },
        setRatedDate: function () { return quote; },
        setRateBucket: function () { return quote; },
        setRatingData: function () { return quote; },
        getRatingData: function () { return ({ _unavailable_all: '0' }); },
        getProgram: function () { return program; },
        setExplicitLock: function () { return quote; },
        getProgramId: function () { return 'Foo'; },
        getCurrentStepId: function () { return 0; },
        setCurrentStepId: function () { return quote; },
        setLastPremiumDate: function () { return quote; },
        setRetryAttempts: function () { return quote; },
        getRetryAttempts: function () { return 1; },
        retryAttempted: function () { return quote; },
        setMetadata: function () { return quote; },
        setInitialRatedDate: function () { return quote; },
        getExpirationDate: function () { return 123; },
    };
    return quote;
}
//# sourceMappingURL=data:application/json;base64, 