"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const assertions_1 = require("@typed/assertions");
const types_1 = require("../types");
const createTest_1 = require("./createTest");
const updateModifier_1 = require("./updateModifier");
function it(does, what) {
    const test = createTest_1.createTest(`it ${does}`, ({ timeout, skip }) => {
        return new Promise(resolve => {
            if (skip) {
                return resolve({ type: 'skip', name: does });
            }
            const { stats, assertions } = assertions_1.createAssertionsEnvironment();
            const id = setTimeout(resolve, timeout, {
                type: 'fail',
                test,
                error: new Error(`Test timed out after ${timeout}ms`),
            });
            function done(error) {
                clearTimeout(id);
                if (error || stats.count < 1) {
                    return resolve({
                        type: 'fail',
                        name: test[types_1.TYPED_TEST].name,
                        error: error
                            ? error instanceof Error
                                ? error
                                : new Error(String(error))
                            : new Error('No Assertions used'),
                    });
                }
                resolve({
                    type: 'pass',
                    name: test[types_1.TYPED_TEST].name,
                });
            }
            if (what.length === 0) {
                return done();
            }
            try {
                const returnValue = what(assertions, done);
                const isPromise = returnValue && typeof returnValue.then === 'function';
                if (!isPromise && what.length === 1) {
                    return done();
                }
                if (isPromise && what.length === 2) {
                    return done(new Error('Cannot use done callback and return Promise'));
                }
                if (isPromise) {
                    return returnValue.then(() => done(), done);
                }
            }
            catch (err) {
                done(err);
            }
        });
    });
    return test;
}
exports.it = it;
(function (it) {
    function only(does, what) {
        return updateModifier_1.updateModifier('only', it(does, what));
    }
    it.only = only;
    function skip(does, what) {
        return updateModifier_1.updateModifier('skip', it(does, what));
    }
    it.skip = skip;
})(it = exports.it || (exports.it = {}));
//# sourceMappingURL=it.js.map