"use strict";
var errors_1 = require("../../errors");
var yok_1 = require("../../yok");
var chai_1 = require("chai");
var options_1 = require("../../options");
var isExecutionStopped = false;
var knownOpts = {
    "path1": { type: options_1.OptionType.String },
    "help": { type: options_1.OptionType.Boolean },
    "verbose": { type: options_1.OptionType.Boolean, alias: "v" },
    "profileDir": { type: options_1.OptionType.String },
    "someDashedValue": { type: options_1.OptionType.String },
    "aBCDEFG": { type: options_1.OptionType.String },
    "arr": { type: options_1.OptionType.Array },
    "specialDashedV": { type: options_1.OptionType.Boolean }
};
function createTestInjector() {
    var testInjector = new yok_1.Yok();
    testInjector.register("options", {});
    testInjector.register("staticConfig", {
        CLIENT_NAME: ""
    });
    testInjector.register("hostInfo", {});
    return testInjector;
}
function createOptions(testInjector) {
    var options = testInjector.resolve(options_1.OptionsBase, { options: knownOpts, defaultProfileDir: "1" });
    return options;
}
describe("common options", function () {
    var testInjector;
    beforeEach(function () {
        testInjector = createTestInjector();
        var errors = new errors_1.Errors(testInjector);
        errors.failWithoutHelp = function (message) {
            var args = [];
            for (var _i = 1; _i < arguments.length; _i++) {
                args[_i - 1] = arguments[_i];
            }
            isExecutionStopped = true;
        };
        errors.fail = function (message) {
            var args = [];
            for (var _i = 1; _i < arguments.length; _i++) {
                args[_i - 1] = arguments[_i];
            }
            isExecutionStopped = true;
        };
        testInjector.register("errors", errors);
        isExecutionStopped = false;
    });
    describe("validateOptions", function () {
        it("breaks execution when option is not valid", function () {
            process.argv.push('--pathr');
            process.argv.push("incorrect argument");
            var options = createOptions(testInjector);
            options.validateOptions();
            process.argv.pop();
            process.argv.pop();
            chai_1.assert.isTrue(isExecutionStopped);
        });
        it("breaks execution when valid option does not have value", function () {
            process.argv.push('--path1');
            var options = createOptions(testInjector);
            options.validateOptions();
            process.argv.pop();
            chai_1.assert.isTrue(isExecutionStopped);
        });
        it("does not break execution when valid option has correct value", function () {
            process.argv.push('--path1');
            process.argv.push("SomeDir");
            var options = createOptions(testInjector);
            options.validateOptions();
            process.argv.pop();
            process.argv.pop();
            chai_1.assert.isFalse(isExecutionStopped);
        });
        it("breaks execution when valid option has empty string value", function () {
            process.argv.push('--path');
            var options = createOptions(testInjector);
            options.validateOptions();
            process.argv.pop();
            chai_1.assert.isTrue(isExecutionStopped);
        });
        it("breaks execution when valid option has value with spaces only", function () {
            process.argv.push('--path');
            process.argv.push('  ');
            var options = createOptions(testInjector);
            options.validateOptions();
            process.argv.pop();
            process.argv.pop();
            chai_1.assert.isTrue(isExecutionStopped);
        });
        it("breaks execution when shorthand option is not valid", function () {
            process.argv.push('-j');
            process.argv.push('incorrect shorthand');
            var options = createOptions(testInjector);
            options.validateOptions();
            process.argv.pop();
            process.argv.pop();
            chai_1.assert.isTrue(isExecutionStopped);
        });
        it("does not break execution when valid shorthand option has correct value", function () {
            process.argv.push('-v');
            var options = createOptions(testInjector);
            options.validateOptions();
            process.argv.pop();
            chai_1.assert.isFalse(isExecutionStopped);
            chai_1.assert.isTrue(options.verbose);
        });
        it("does not break execution when valid option has number value", function () {
            process.argv.push('--path');
            process.argv.push('1');
            var options = createOptions(testInjector);
            options.validateOptions();
            process.argv.pop();
            process.argv.pop();
            chai_1.assert.isFalse(isExecutionStopped);
        });
        it("throws error when valid option has array value", function () {
            process.argv.push('--path');
            process.argv.push("value 1");
            process.argv.push('--path');
            process.argv.push("value 2");
            var options = createOptions(testInjector);
            options.validateOptions();
            process.argv.pop();
            process.argv.pop();
            process.argv.pop();
            process.argv.pop();
            chai_1.assert.isTrue(isExecutionStopped);
        });
        it("converts string value to array when option type is array", function () {
            var options = createOptions(testInjector);
            process.argv.push("--test1");
            process.argv.push("value");
            options.validateOptions({ test1: { type: options_1.OptionType.Array } });
            process.argv.pop();
            process.argv.pop();
            chai_1.assert.isFalse(isExecutionStopped);
            chai_1.assert.deepEqual(["value"], options["test1"]);
        });
        it("does not break execution when valid commandSpecificOptions are passed", function () {
            process.argv.push("--test1");
            process.argv.push("value");
            var options = createOptions(testInjector);
            options.validateOptions({ test1: { type: options_1.OptionType.String } });
            process.argv.pop();
            process.argv.pop();
            chai_1.assert.isFalse(isExecutionStopped);
        });
        it("does not break execution when valid commandSpecificOptions are passed and user specifies globally valid option", function () {
            var options = createOptions(testInjector);
            process.argv.push("--version");
            options.validateOptions({ test1: { type: options_1.OptionType.String } });
            process.argv.pop();
            chai_1.assert.isFalse(isExecutionStopped);
        });
        it("breaks execution when valid array option has value with length 0", function () {
            process.argv.push('--arr');
            var options = createOptions(testInjector);
            options.validateOptions();
            process.argv.pop();
            chai_1.assert.isTrue(isExecutionStopped);
        });
        describe("when commandSpecificOptions are passed", function () {
            it("breaks execution when commandSpecificOptions are passed and user tries to use invalid option", function () {
                process.argv.push("--invalidOption");
                var options = testInjector.resolve(options_1.OptionsBase, { options: knownOpts, defaultProfileDir: "1" });
                options.validateOptions({ test1: { type: options_1.OptionType.String } });
                process.argv.pop();
                chai_1.assert.isTrue(isExecutionStopped);
            });
            it("breaks execution when commandSpecificOptions are passed and user tries to use option valid for CLI, but not for this command", function () {
                process.argv.push("--json");
                var options = testInjector.resolve(options_1.OptionsBase, { options: knownOpts, defaultProfileDir: "1" });
                options.validateOptions({ test1: { type: options_1.OptionType.String } });
                process.argv.pop();
                chai_1.assert.isTrue(isExecutionStopped);
            });
            it("uses profile-dir from yargs when it exists and commandSpecificOptions are passed", function () {
                var expectedProfileDir = "TestDir";
                process.argv.push("--profile-dir");
                process.argv.push(expectedProfileDir);
                var options = testInjector.resolve(options_1.OptionsBase, { options: knownOpts, defaultProfileDir: "1" });
                options.validateOptions({ test1: { type: options_1.OptionType.String } });
                chai_1.assert.equal(options.profileDir, expectedProfileDir);
                process.argv.pop();
                process.argv.pop();
                chai_1.assert.isFalse(isExecutionStopped);
            });
        });
        describe("validates dashed options correctly", function () {
            it("does not break execution when dashed option with single dash is passed", function () {
                process.argv.push("profile-dir");
                process.argv.push("some dir");
                var options = createOptions(testInjector);
                options.validateOptions();
                process.argv.pop();
                process.argv.pop();
                chai_1.assert.isFalse(isExecutionStopped, "Dashed options should be validated in specific way. Make sure validation allows yargs specific behavior:" +
                    "Dashed options (profile-dir) are added to yargs.argv in two ways: profile-dir and profileDir");
            });
            it("does not break execution when dashed option with two dashes is passed", function () {
                process.argv.push("some-dashed-value");
                process.argv.push("some dir");
                var options = createOptions(testInjector);
                options.validateOptions();
                process.argv.pop();
                process.argv.pop();
                chai_1.assert.isFalse(isExecutionStopped, "Dashed options should be validated in specific way. Make sure validation allows yargs specific behavior:" +
                    "Dashed options (some-dashed-value) are added to yargs.argv in two ways: some-dashed-value and someDashedValue");
            });
            it("does not break execution when dashed option with a lot of dashes is passed", function () {
                process.argv.push("a-b-c-d-e-f-g");
                process.argv.push("some dir");
                var options = createOptions(testInjector);
                options.validateOptions();
                process.argv.pop();
                process.argv.pop();
                chai_1.assert.isFalse(isExecutionStopped, "Dashed options should be validated in specific way. Make sure validation allows yargs specific behavior:" +
                    "Dashed options (a-b-c-d-e-f-g) are added to yargs.argv in two ways: a-b-c-d-e-f-g and aBCDEFG.");
            });
            it("does not break execution when dashed option with two dashes is passed", function () {
                process.argv.push("--special-dashed-v");
                var options = createOptions(testInjector);
                options.validateOptions();
                process.argv.pop();
                chai_1.assert.isFalse(isExecutionStopped, "Dashed options should be validated in specific way. Make sure validation allows yargs specific behavior:" +
                    "Dashed options (special-dashed-v) are added to yargs.argv in two ways: special-dashed-v and specialDashedV");
            });
        });
    });
});
function createOptionsWithProfileDir(profileDir) {
    var testInjector = new yok_1.Yok();
    testInjector.register("errors", {});
    testInjector.register("staticConfig", {});
    var options = testInjector.resolve(options_1.OptionsBase, { options: {}, defaultProfileDir: profileDir });
    return options;
}
describe("common options profile-dir tests", function () {
    describe("setProfileDir", function () {
        it("uses profile-dir from yargs when it exists", function () {
            var expectedProfileDir = "TestDir";
            process.argv.push("--profile-dir");
            process.argv.push(expectedProfileDir);
            var options = createOptionsWithProfileDir("");
            options.validateOptions();
            process.argv.pop();
            process.argv.pop();
            chai_1.assert.equal(options.profileDir, expectedProfileDir);
        });
        it("sets default profile-dir when it is not passed on command line", function () {
            var profileDir = "TestDir";
            var options = createOptionsWithProfileDir("TestDir");
            options.validateOptions();
            chai_1.assert.equal(options.profileDir, profileDir);
        });
        it("uses profile-dir from yargs when it exists even if default one has non-empty value", function () {
            var expectedProfileDir = "TestDir";
            process.argv.push("--profile-dir");
            process.argv.push(expectedProfileDir);
            var options = createOptionsWithProfileDir("TestDir123");
            options.validateOptions();
            process.argv.pop();
            process.argv.pop();
            chai_1.assert.equal(options.profileDir, expectedProfileDir);
        });
        it("uses profileDir from yargs when it exists", function () {
            var expectedProfileDir = "TestDir";
            process.argv.push("--profileDir");
            process.argv.push(expectedProfileDir);
            var options = createOptionsWithProfileDir("");
            options.validateOptions();
            process.argv.pop();
            process.argv.pop();
            chai_1.assert.equal(options.profileDir, expectedProfileDir);
        });
    });
});
