"use strict";
// Copyright 2024 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
    var ownKeys = function(o) {
        ownKeys = Object.getOwnPropertyNames || function (o) {
            var ar = [];
            for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
            return ar;
        };
        return ownKeys(o);
    };
    return function (mod) {
        if (mod && mod.__esModule) return mod;
        var result = {};
        if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
        __setModuleDefault(result, mod);
        return result;
    };
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.devtoolsTestInterface = void 0;
exports.createMochaInterface = createMochaInterface;
const Mocha = __importStar(require("mocha"));
// @ts-expect-error
const commonInterface = __importStar(require("mocha/lib/interfaces/common.js"));
const mocha_interface_helpers_js_1 = require("./mocha-interface-helpers.js");
function createMochaInterface(options) {
    const devtoolsTestInterface = function (rootSuite) {
        let defaultImplementation;
        let mochaGlobals;
        let mochaRoot;
        rootSuite.on(Mocha.Suite.constants.EVENT_FILE_PRE_REQUIRE, (context, file, mocha) => {
            mochaGlobals = context;
            mochaRoot = mocha;
            // Different module outputs between tsc and esbuild.
            const defaultFactory = ('default' in commonInterface ? commonInterface.default : commonInterface);
            defaultImplementation = defaultFactory([rootSuite], context, mocha);
            if (mocha.options.delay) {
                context.run = defaultImplementation.runWithSuite(rootSuite);
            }
            mochaGlobals.describe = customDescribe(defaultImplementation.suite, file);
        });
        function customDescribe(suiteImplementation, file) {
            function withAugmentedTitle(suiteFn) {
                return function (title, describeBodyFn) {
                    const suite = suiteFn({
                        title,
                        file,
                        fn: function () {
                            const thisSuite = this;
                            const parentDefinitions = {
                                describe: mochaGlobals.describe,
                                setup: mochaGlobals.setup,
                                it: mochaGlobals.it,
                            };
                            mochaGlobals.describe = customDescribe(defaultImplementation.suite, file);
                            if (options.stateProvider?.registerSuiteSettings) {
                                mochaGlobals.setup = function (suiteSettings) {
                                    options.stateProvider.registerSuiteSettings(thisSuite, suiteSettings);
                                };
                            }
                            mochaGlobals.it = customIt(defaultImplementation.test, thisSuite, thisSuite.file || '', mochaRoot, options.stateProvider);
                            if (describeBodyFn) {
                                describeBodyFn.call(thisSuite);
                            }
                            // Restore definitions so when we come back from a nested describe
                            // we have the same definitions available as for the current block,
                            // therefore correctly handling the next describe block that is at
                            // the same level with this one.
                            mochaGlobals.describe = parentDefinitions.describe;
                            mochaGlobals.setup = parentDefinitions.setup;
                            mochaGlobals.it = parentDefinitions.it;
                        },
                    });
                    if (!suite.isPending() && options.stateProvider?.prepareSuite) {
                        suite.beforeEach(async function () {
                            this.timeout(0);
                            await options.stateProvider.prepareSuite(suite);
                        });
                    }
                    return suite;
                };
            }
            const describe = withAugmentedTitle(suiteImplementation.create.bind(suiteImplementation));
            describe.only = withAugmentedTitle(suiteImplementation.only.bind(suiteImplementation));
            describe.skip = withAugmentedTitle(suiteImplementation.skip.bind(suiteImplementation));
            return describe;
        }
    };
    devtoolsTestInterface.description = options.description;
    return devtoolsTestInterface;
}
function customIt(testImplementation, suite, file, mocha, stateProvider) {
    function createTest(title, itBodyFn) {
        const test = new Mocha.Test(title, suite.isPending() || !itBodyFn ?
            undefined :
            mocha_interface_helpers_js_1.InstrumentedTestFunction.instrument(itBodyFn, 'test', suite, stateProvider));
        test.file = file;
        // Creates a proxy that changes the duration to return
        // our own timing.
        const proxyTest = new Proxy(test, {
            get(target, property, receiver) {
                if (property === 'duration' && target.realDuration) {
                    return Reflect.get(target, 'realDuration', receiver) ?? Reflect.get(target, property, receiver);
                }
                return Reflect.get(target, property, receiver);
            },
        });
        suite.addTest(proxyTest);
        return proxyTest;
    }
    // Regular mocha it returns the test instance.
    const localIt = Object.assign(function (title, fn) {
        return createTest(title, fn);
    }, {
        skip: function (title, _fn) {
            return createTest(title);
        },
        only: function (title, fn) {
            return testImplementation.only(mocha, createTest(title, fn));
        },
    });
    return localIt;
}
exports.devtoolsTestInterface = createMochaInterface({
    description: 'DevTools test interface',
    stateProvider: mocha_interface_helpers_js_1.DefaultPuppeteerStateProvider.instance,
});
//# sourceMappingURL=mocha-interface.js.map