"use strict";
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 __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.HotTesterMocha = void 0;
const mocha_1 = __importDefault(require("mocha"));
const mocha_2 = require("mocha");
const HotTester_1 = require("./HotTester");
const HotTestDriver_1 = require("./HotTestDriver");
/**
 * The tester that uses Mocha to executes all tests.
 */
class HotTesterMocha extends HotTester_1.HotTester {
    constructor(processor, name, baseUrl, testMaps = {}, beforeAll = null, afterAll = null) {
        super(processor, name, baseUrl, new HotTestDriver_1.HotTestDriver(processor), testMaps);
        this.mocha = null;
        this.suite = null;
        this.beforeAll = beforeAll;
        this.afterAll = afterAll;
    }
    /**
     * Setup the Mocha/Selenium frameworks.
     *
     * @param tester The
     * @param url If this is set, this url will be used instead of the url associated with this
     * tester.
     */
    setup(isWebRoute_1) {
        return __awaiter(this, arguments, void 0, function* (isWebRoute, url = "", destinationKey = "") {
        });
    }
    /**
     * Executed when destroying this tester.
     */
    destroy() {
        return __awaiter(this, void 0, void 0, function* () {
            if (this.driver != null)
                yield this.driver.destroy();
        });
    }
    /**
     * Executed when tests are started.
     */
    onTestStart(destination_1, url_1) {
        return __awaiter(this, arguments, void 0, function* (destination, url, destinationKey = "") {
            let destinationName = "";
            if (destinationKey !== "")
                destinationName = ` - ${destinationKey}`;
            this.processor.logger.verbose(`HotTesterMocha: Setting up Mocha and creating test suite...`);
            this.mocha = new mocha_1.default();
            this.suite = mocha_1.default.Suite.create(this.mocha.suite, `${url} ${destinationName} Tests`);
            this.suite.timeout(this.timeout);
            if (this.beforeAll != null)
                this.suite.beforeAll(this.beforeAll);
            return (true);
        });
    }
    onTestPagePathStart(destination_1, stop_1) {
        return __awaiter(this, arguments, void 0, function* (destination, stop, continueWhenTestIsComplete = false) {
            let testPathName = stop.path;
            this.processor.logger.verbose(`HotTesterMocha: Adding Web test path ${testPathName}`);
            /*if (continueWhenTestIsComplete === true)
            {
                await new Promise<void> ((resolve, reject) =>
                    {
                        this.suite.addTest (new Test (testPathName, async () =>
                            {
                                this.processor.logger.verbose (() => `HotTesterMocha: Executing ${testPathName} destination ${JSON.stringify (destination)} with stop ${stop}`);
    
                                // The true is a dumb hack to prevent any recursion.
                                await this.executeTestPagePath (destination, stop, true);
                                resolve ();
                            }));
                    });
            }
            else
            {*/
            this.suite.addTest(new mocha_2.Test(testPathName, () => __awaiter(this, void 0, void 0, function* () {
                this.processor.logger.verbose(() => `HotTesterMocha: Executing ${testPathName} destination ${JSON.stringify(destination)} with stop ${stop}`);
                // The true is a dumb hack to prevent any recursion.
                yield this.executeTestPagePath(destination, stop, true);
            })));
            //}
            return (false);
        });
    }
    onTestAPIPathStart(destination, method, testName, continueWhenTestIsComplete) {
        return __awaiter(this, void 0, void 0, function* () {
            let testPathName = `${method.getRouteUrl()} -> ${testName}`;
            this.processor.logger.verbose(`HotTesterMocha: Adding API test path ${testPathName}`);
            /*if (continueWhenTestIsComplete === true)
            {
                await new Promise<void> ((resolve, reject) =>
                    {
                        this.suite.addTest (new Test (testPathName, async () =>
                            {
                                this.processor.logger.verbose (() => `HotTesterMocha: Executing ${testPathName} destination ${JSON.stringify (destination)}`);
    
                                // The true is a dumb hack to prevent any recursion.
                                await this.executeTestAPIPath (destination, method, testName, true);
                                resolve ();
                            }));
                    });
            }
            else
            {*/
            this.suite.addTest(new mocha_2.Test(testPathName, () => __awaiter(this, void 0, void 0, function* () {
                this.processor.logger.verbose(() => `HotTesterMocha: Executing ${testPathName} destination ${JSON.stringify(destination)}`);
                // The true is a dumb hack to prevent any recursion.
                yield this.executeTestAPIPath(destination, method, testName, true);
            })));
            //}
            return (false);
        });
    }
    onCommand(destination, stop, cmd, args, cmdFunc) {
        return __awaiter(this, void 0, void 0, function* () {
            this.suite.addTest(new mocha_2.Test(cmd, () => __awaiter(this, void 0, void 0, function* () {
                this.processor.logger.verbose(() => `HotTesterMocha: Executing command ${cmd} with arguments ${JSON.stringify(args)}`);
                yield cmdFunc(args);
            })));
        });
    }
    onTestEnd(destination) {
        return __awaiter(this, void 0, void 0, function* () {
            return (new Promise((resolve, reject) => {
                if (this.afterAll != null)
                    this.suite.afterAll(this.afterAll);
                this.processor.logger.verbose(`HotTesterMocha: Starting Mocha and running tests...`);
                // Mocha installs `uncaughtException` and `unhandledRejection`
                // listeners on the `process` object every time .run() is
                // invoked. Without disposing the runner, each test
                // destination leaks two listeners — and after ~5 destinations
                // the EventEmitter MaxListenersExceededWarning fires (default
                // limit is 10), tests start hanging on mocha's 10s timeout,
                // and CI runs all the way to the job timeout. dispose()
                // removes the listeners cleanly.
                const runner = this.mocha.run((failures) => {
                    this.numFailures += failures;
                    this.processor.logger.verbose(`HotTesterMocha: Tests complete!`);
                    try {
                        runner.dispose();
                    }
                    catch (e) { /* mocha < 8 lacks dispose */ }
                    resolve();
                });
            }));
        });
    }
}
exports.HotTesterMocha = HotTesterMocha;
//# sourceMappingURL=HotTesterMocha.js.map