var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    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) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
var __importStar = (this && this.__importStar) || function (mod) {
    if (mod && mod.__esModule) return mod;
    var result = {};
    if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
    result["default"] = mod;
    return result;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
define(["require", "exports", "chai", "expect-rejection", "sinon", "sinon-chai", "wed/mode-loader"], function (require, exports, chai_1, expect_rejection_1, sinon, sinon_chai_1, mode_loader_1) {
    "use strict";
    Object.defineProperty(exports, "__esModule", { value: true });
    sinon = __importStar(sinon);
    sinon_chai_1 = __importDefault(sinon_chai_1);
    chai_1.use(sinon_chai_1.default);
    // tslint:disable-next-line:completed-docs
    class FakeMode {
        // tslint:disable-next-line:no-any
        constructor(editor, options) {
            this.editor = editor;
            this.options = options;
            this.initialized = false;
        }
        init() {
            this.initialized = true;
            return Promise.resolve();
        }
    }
    // tslint:disable-next-line:missing-jsdoc
    describe("ModeLoader", () => {
        let loader;
        // tslint:disable-next-line:no-any
        let runtime;
        // Yes, we cheat with a typecast.
        // tslint:disable-next-line:no-any mocha-no-side-effect-code
        const editor = { editor: true };
        const options = { options: true };
        beforeEach(() => {
            const runtime_ = sinon.stub({
                // tslint:disable-next-line:no-empty
                resolveModules: () => { },
            });
            runtime = runtime_;
            loader = new mode_loader_1.ModeLoader(editor, runtime);
        });
        describe("#initMode", () => {
            it("fails if we cannot load", () => __awaiter(this, void 0, void 0, function* () {
                runtime.resolveModules.throws(new Error("cannot load"));
                yield expect_rejection_1.expectRejection(loader.initMode("moo", options), Error, "cannot load");
            }));
            it("by default, tries multiple module names", () => __awaiter(this, void 0, void 0, function* () {
                runtime.resolveModules.throws(new Error("cannot load"));
                try {
                    yield loader.initMode("moo", {});
                }
                // tslint:disable-next-line:no-empty
                catch (ex) { }
                chai_1.expect(runtime).to.have.property("resolveModules").to.have.callCount(4);
                chai_1.expect(runtime.resolveModules.firstCall).to.have.been.calledWith("moo");
                chai_1.expect(runtime.resolveModules.secondCall)
                    .to.have.been.calledWith("wed/modes/moo/moo");
                chai_1.expect(runtime.resolveModules.thirdCall)
                    .to.have.been.calledWith("wed/modes/moo/moo-mode");
                chai_1.expect(runtime.resolveModules.lastCall)
                    .to.have.been.calledWith("wed/modes/moo/moo_mode");
            }));
            it("fails on first attempt if the path has a forward slash", () => __awaiter(this, void 0, void 0, function* () {
                runtime.resolveModules.throws(new Error("cannot load"));
                try {
                    yield loader.initMode("moo/foo", options);
                }
                // tslint:disable-next-line:no-empty
                catch (ex) { }
                chai_1.expect(runtime).to.have.property("resolveModules").to.have.callCount(1);
                chai_1.expect(runtime.resolveModules).to.have.been.calledWith("moo/foo");
            }));
            it("initializes the module after loading it", () => __awaiter(this, void 0, void 0, function* () {
                runtime.resolveModules.returns([{
                        Mode: FakeMode,
                    }]);
                const loaded = yield loader.initMode("moo/foo", options);
                chai_1.expect(loaded).to.be.instanceof(FakeMode);
                chai_1.expect(loaded).to.have.property("initialized").be.true;
            }));
            it("creates the mode with correct parameters", () => __awaiter(this, void 0, void 0, function* () {
                // tslint:disable-next-line:variable-name
                const ModeConstructor = sinon.spy(function Mode() {
                    return sinon.createStubInstance(FakeMode);
                });
                runtime.resolveModules.returns([{
                        Mode: ModeConstructor,
                    }]);
                yield loader.initMode("moo/foo", options);
                chai_1.expect(ModeConstructor).to.have.been.calledOnce;
                chai_1.expect(ModeConstructor).to.have.been.calledWith(editor, options);
            }));
            it("fails if the module fails to init", () => __awaiter(this, void 0, void 0, function* () {
                runtime.resolveModules.returns([{
                        Mode: function Mode() {
                            const ret = sinon.createStubInstance(FakeMode);
                            ret.init.returns(Promise.reject(new Error("failed")));
                            return ret;
                        },
                    }]);
                yield expect_rejection_1.expectRejection(loader.initMode("moo/foo", options), Error, "failed");
            }));
        });
    });
});
//# sourceMappingURL=mode-loader-test.js.map