"use strict";
var __assign = (this && this.__assign) || function () {
    __assign = Object.assign || function(t) {
        for (var s, i = 1, n = arguments.length; i < n; i++) {
            s = arguments[i];
            for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
                t[p] = s[p];
        }
        return t;
    };
    return __assign.apply(this, arguments);
};
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
var __generator = (this && this.__generator) || function (thisArg, body) {
    var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
    return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
    function verb(n) { return function (v) { return step([n, v]); }; }
    function step(op) {
        if (f) throw new TypeError("Generator is already executing.");
        while (_) try {
            if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
            if (y = 0, t) op = [op[0] & 2, t.value];
            switch (op[0]) {
                case 0: case 1: t = op; break;
                case 4: _.label++; return { value: op[1], done: false };
                case 5: _.label++; y = op[1]; op = [0]; continue;
                case 7: op = _.ops.pop(); _.trys.pop(); continue;
                default:
                    if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
                    if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
                    if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
                    if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
                    if (t[2]) _.ops.pop();
                    _.trys.pop(); continue;
            }
            op = body.call(thisArg, _);
        } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
        if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
    }
};
exports.__esModule = true;
// import * as sinon from "chai";
var chai_1 = require("chai");
require("mocha");
var utils = require("../utils");
var mocks = require("./mocks");
describe("utils", function () {
    describe("typecastFn", function () {
        var fn = utils.typecastFn;
        it("typecase string", function () {
            var castString = fn("string");
            chai_1.expect(castString("some_string")).to.equal("some_string");
            chai_1.expect(castString("123")).to.equal("123");
            chai_1.expect(castString("true")).to.equal("true");
        });
        it("typecase number", function () {
            var castNumber = fn("number");
            chai_1.expect(castNumber("123")).to.equal(123);
            chai_1.expect(castNumber("-123")).to.equal(-123);
            chai_1.expect(castNumber("12.34")).to.equal(12.34);
            chai_1.expect(castNumber("-0.978")).to.equal(-0.978);
            chai_1.expect(castNumber("0b110011010")).to.equal(410);
            chai_1.expect(castNumber("0o4732")).to.equal(2522);
            chai_1.expect(castNumber("0xb7e8")).to.equal(47080);
            chai_1.expect(castNumber("2e3")).to.equal(2000);
            chai_1.expect(castNumber("2e-3")).to.equal(0.002);
            chai_1.expect(isNaN(castNumber("some_string"))).to.equal(true);
        });
        it("typecase boolean", function () {
            var castBoolean = fn("boolean");
            chai_1.expect(castBoolean("")).to.equal(false);
            chai_1.expect(castBoolean("0")).to.equal(false);
            chai_1.expect(castBoolean("f")).to.equal(false);
            chai_1.expect(castBoolean("false")).to.equal(false);
            chai_1.expect(castBoolean("true")).to.equal(true);
        });
        it("typecase other", function () {
            var fnArg = function () { return true; };
            var args = [
                "some_string",
                "123",
                "true",
                "123",
                "-123",
                "12.34",
                "-0.978",
                "0b110011010",
                "0o4732",
                "0xb7e8",
                "2e3",
                "2e-3",
                "some_string",
                "",
                "0",
                "f",
                "false",
                "true",
                null,
                undefined,
                Infinity,
                fnArg,
            ];
            args.forEach(function (arg) {
                chai_1.expect(fn("{}")(arg)).to.equal(arg);
                chai_1.expect(fn("null")(arg)).to.equal(arg);
                chai_1.expect(fn("")(arg)).to.equal(arg);
            });
        });
    });
    describe("validator modifications", function () {
        var original = mocks.testKeyedTable;
        var bizarro = utils.modifyValidator(original, "read");
        var alpha = "string";
        var bravo = 123;
        var charlie = true;
        var mike = "a string";
        var recordValid = { alpha: alpha, bravo: bravo, charlie: charlie, mike: mike };
        var recordBadTypes = { alpha: 123, bravo: false, charlie: "some string" };
        var getMessage = function (item) { return item.error.details[0].message; };
        it("original works as expected", function () {
            var noAlpha = original.validate({ bravo: bravo, charlie: charlie });
            chai_1.expect(noAlpha.error).to.equal(undefined);
            var noBravo = original.validate({ alpha: alpha, charlie: charlie });
            chai_1.expect(noBravo.error).to.equal(undefined);
            var noCharlie = original.validate({ alpha: alpha, bravo: bravo });
            chai_1.expect(noCharlie.error).to.equal(undefined);
            var success = original.validate(recordValid);
            chai_1.expect(success.error).to.equal(undefined);
            var failure1 = original.validate(__assign({}, recordBadTypes));
            chai_1.expect(getMessage(failure1)).to.equal('"alpha" must be a string');
            var failure2 = original.validate(__assign(__assign({}, recordBadTypes), { alpha: alpha }));
            chai_1.expect(getMessage(failure2)).to.equal('"bravo" must be a number');
            var failure3 = original.validate(__assign(__assign({}, recordBadTypes), { alpha: alpha, bravo: bravo }));
            chai_1.expect(getMessage(failure3)).to.equal('"charlie" must be a boolean');
        });
        it("modified (requirements removed)", function () {
            var noAlpha = bizarro.validate({ bravo: bravo, charlie: charlie });
            chai_1.expect(getMessage(noAlpha)).to.equal('"alpha" is required');
            var noBravo = bizarro.validate({ alpha: alpha, charlie: charlie });
            chai_1.expect(getMessage(noBravo)).to.equal('"bravo" is required');
            var noCharlie = bizarro.validate({ alpha: alpha, bravo: bravo });
            chai_1.expect(getMessage(noCharlie)).to.equal('"charlie" is required');
            var success = bizarro.validate(recordValid);
            chai_1.expect(success.error).to.equal(undefined);
            var failure1 = bizarro.validate(__assign({}, recordBadTypes));
            chai_1.expect(getMessage(failure1)).to.equal('"alpha" must be a string');
            var failure2 = bizarro.validate(__assign(__assign({}, recordBadTypes), { alpha: alpha }));
            chai_1.expect(getMessage(failure2)).to.equal('"bravo" must be a number');
            var failure3 = bizarro.validate(__assign(__assign({}, recordBadTypes), { alpha: alpha, bravo: bravo }));
            chai_1.expect(getMessage(failure3)).to.equal('"charlie" must be a boolean');
        });
    });
    describe("some validatorInspector", function () {
        var fn = utils.validatorInspector;
        it("inspect original validator", function () { return __awaiter(void 0, void 0, void 0, function () {
            var describeOriginal;
            return __generator(this, function (_a) {
                describeOriginal = fn(utils.modifyValidator(mocks.testKeyedTable, "read"), []);
                Object.entries(mocks.initDescribeOriginal).forEach(function (_a) {
                    var key = _a[0], value = _a[1];
                    return __awaiter(void 0, void 0, void 0, function () {
                        var type, required, geoqueryType, softDeleteFlag, validation;
                        return __generator(this, function (_b) {
                            switch (_b.label) {
                                case 0:
                                    type = value.type, required = value.required, geoqueryType = value.geoqueryType, softDeleteFlag = value.softDeleteFlag;
                                    chai_1.expect(describeOriginal[key].type).to.equal(type);
                                    chai_1.expect(describeOriginal[key].required).to.equal(required);
                                    chai_1.expect(describeOriginal[key].geoqueryType).to.equal(geoqueryType);
                                    chai_1.expect(describeOriginal[key].softDeleteFlag).to.equal(softDeleteFlag);
                                    chai_1.expect(describeOriginal[key].typecast).to.equal(utils.typecastFn(type));
                                    return [4 /*yield*/, describeOriginal[key].validate(mocks.validationInputs.input[type])];
                                case 1:
                                    validation = _b.sent();
                                    chai_1.expect(validation).to.equal(mocks.validationInputs.output[type]);
                                    return [2 /*return*/];
                            }
                        });
                    });
                });
                return [2 /*return*/];
            });
        }); });
        it("inspect mutated validator", function () { return __awaiter(void 0, void 0, void 0, function () {
            var describeBizarro;
            return __generator(this, function (_a) {
                describeBizarro = fn(mocks.testKeyedTable, []);
                Object.entries(mocks.initDescribeBizarro).forEach(function (_a) {
                    var key = _a[0], value = _a[1];
                    return __awaiter(void 0, void 0, void 0, function () {
                        var type, required, geoqueryType, softDeleteFlag, validation;
                        return __generator(this, function (_b) {
                            switch (_b.label) {
                                case 0:
                                    type = value.type, required = value.required, geoqueryType = value.geoqueryType, softDeleteFlag = value.softDeleteFlag;
                                    chai_1.expect(describeBizarro[key].type).to.equal(type);
                                    chai_1.expect(describeBizarro[key].required).to.equal(required);
                                    chai_1.expect(describeBizarro[key].geoqueryType).to.equal(geoqueryType);
                                    chai_1.expect(describeBizarro[key].softDeleteFlag).to.equal(softDeleteFlag);
                                    chai_1.expect(describeBizarro[key].typecast).to.equal(utils.typecastFn(type));
                                    return [4 /*yield*/, describeBizarro[key].validate(mocks.validationInputs.input[type])];
                                case 1:
                                    validation = _b.sent();
                                    chai_1.expect(validation).to.equal(mocks.validationInputs.output[type]);
                                    return [2 /*return*/];
                            }
                        });
                    });
                });
                return [2 /*return*/];
            });
        }); });
    });
    describe("errorMessageInvalidValue", function () {
        it("replaces `value` with field", function () {
            var field = "atlanta";
            var message = "go braves";
            var fn = utils.errorMessageInvalidValue;
            chai_1.expect(fn(field, message)).to.equal("'atlanta': go braves");
        });
    });
    describe("generateSearchQueryError", function () {
        var fn = utils.generateSearchQueryError;
        var error = "play ball";
        var field = "braves";
        var type = "type";
        var operation = "operation";
        var payload = { error: error, field: field, type: type, operation: operation };
        it("thrown error", function () {
            var message = fn(payload);
            chai_1.expect(message).to.equal("'braves': play ball");
        });
        it("unsupported field", function () {
            var message = fn(__assign(__assign({}, payload), { error: undefined, type: undefined }));
            chai_1.expect(message).to.equal("'braves' is not a supported property on this resource");
        });
        it("unsupported operation", function () {
            var message = fn(__assign(__assign({}, payload), { error: undefined }));
            chai_1.expect(message).to.equal("'operation' operation not supported");
        });
    });
    describe("badArgsLengthError", function () {
        it("enforces defined arg lengths", function () {
            var fn = utils.badArgsLengthError;
            chai_1.expect(fn("range", [1, 2, 3])).to.equal("'range' operation requires 2 args. 3 were provided.");
        });
    });
    describe("validArgsforOperation", function () {
        it("reports defined arg lengths", function () {
            var fn = utils.validArgsforOperation;
            chai_1.expect(fn("range", [1, 2, 3])).to.equal(false);
            chai_1.expect(fn("range", [1, 2])).to.equal(true);
            chai_1.expect(fn("not a real operation", [1, 2])).to.equal(true);
        });
    });
    describe("supportMultipleValues", function () {
        it("reports defined arg lengths", function () {
            var fn = utils.supportMultipleValues;
            chai_1.expect(fn("does not support multiple values")).to.equal(false);
            chai_1.expect(fn("in")).to.equal(true);
        });
    });
    describe("supportedOperation", function () {
        it("reports supported operations", function () {
            var fn = utils.supportedOperation;
            chai_1.expect(fn("does not support multiple values")).to.equal(false);
            chai_1.expect(fn("in")).to.equal(true);
        });
    });
    describe("parseFieldAndOperation", function () {
        it("parses field and operations", function () {
            var fn = utils.parseFieldAndOperation;
            var product1 = fn("field");
            chai_1.expect(product1.field).to.equal("field");
            chai_1.expect(product1.operation).to.equal("equal");
            var product2 = fn("field.in");
            chai_1.expect(product2.field).to.equal("field");
            chai_1.expect(product2.operation).to.equal("in");
        });
    });
    describe("searchQueryParser", function () {
        var fn = utils.searchQueryParser;
        it("produces errors and components as expected (now async!)", function () { return __awaiter(void 0, void 0, void 0, function () {
            var _a, errors, components, checkForMocksinTestResults;
            return __generator(this, function (_b) {
                switch (_b.label) {
                    case 0: return [4 /*yield*/, fn(mocks.testTable, mocks.exampleSearchQuery, mocks.apiType01)];
                    case 1:
                        _a = _b.sent(), errors = _a.errors, components = _a.components;
                        checkForMocksinTestResults = function (mockedEntries, testResults) {
                            var testResultsStringified = testResults.map(function (item) {
                                return JSON.stringify(item);
                            });
                            mockedEntries.forEach(function (entry) {
                                chai_1.expect(testResultsStringified.includes(entry)).to.equal(true);
                            });
                        };
                        // ensure all expected mocks are present in the retults
                        checkForMocksinTestResults(mocks.exampleParsedSearchQuery.errors, errors);
                        checkForMocksinTestResults(mocks.exampleParsedSearchQuery.components, components);
                        return [2 /*return*/];
                }
            });
        }); });
    });
});
//# sourceMappingURL=utils.spec.js.map