"use strict";
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
  for (var name in all)
    __defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
  if (from && typeof from === "object" || typeof from === "function") {
    for (let key of __getOwnPropNames(from))
      if (!__hasOwnProp.call(to, key) && key !== except)
        __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
  }
  return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
  // If the importer is in node compatibility mode or this is not an ESM
  // file that has been converted to a CommonJS file using a Babel-
  // compatible transform (i.e. "__esModule" has not been set), then set
  // "default" to the CommonJS "module.exports" for node compatibility.
  isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
  mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var runner_exports = {};
__export(runner_exports, {
  TestRunner: () => TestRunner
});
module.exports = __toCommonJS(runner_exports);
var import_js_tools = require("@nacho-iot/js-tools");
var import_debug = __toESM(require("debug"), 1);
var import_promises = require("node:fs/promises");
var import_node_path = require("node:path");
var import_failure_reporter = require("./failure-reporter.js");
var import_machine_reporter = require("./machine-reporter.js");
var import_nodejs_reporter = require("./nodejs-reporter.js");
var import_nodejs = require("./nodejs.js");
var import_files = require("./util/files.js");
var import_web = require("./web.js");
/**
 * @license
 * Copyright 2022-2026 Matter.js Authors
 * SPDX-License-Identifier: Apache-2.0
 */
const HARNESS_CONFIG_FILE = "build/esm/test/test.harness.js";
class TestRunner {
  constructor(pkg, progress, options) {
    this.pkg = pkg;
    this.progress = progress;
    this.options = options;
    TestRunner.#current = this;
    if (options.machine) {
      this.reporter = new import_machine_reporter.MachineReporter(progress);
    } else {
      this.reporter = new class extends import_nodejs_reporter.NodejsReporter {
        constructor() {
          super(progress);
        }
        failRun(detail) {
          import_js_tools.std.err.write("\n");
          import_failure_reporter.FailureReporter.report(import_js_tools.std.err, detail, "Test suite crash");
          import_js_tools.std.err.write("\n");
          process.exit(1);
        }
      }();
    }
    if (options.spec === void 0) {
      this.#spec = ["test/**/*Test.ts"];
    } else if (Array.isArray(options.spec)) {
      this.#spec = options.spec;
    } else {
      this.#spec = [options.spec];
    }
    if (options.debug) {
      import_debug.default.enable("mocha:*");
    }
  }
  pkg;
  progress;
  options;
  static #current;
  static get current() {
    if (this.#current === void 0) {
      throw new Error("No test active test runner");
    }
    return this.#current;
  }
  reporter;
  #spec = Array();
  #configured = false;
  /**
   * If present the web runner will run this preprocessor on its entrypoint file.  You can modify {@link lines} to
   * add or change entrypoint logic.
   */
  entrypointPreprocessor;
  async runNode(format = "esm", repeat) {
    await this.#configure();
    return await this.#run(this.progress, () => (0, import_nodejs.testNodejs)(this, format, repeat));
  }
  async runWeb(manual = false) {
    await this.#configure();
    await this.#run(this.progress, () => (0, import_web.testWeb)(this, manual));
  }
  async #configure() {
    if (this.#configured) {
      return;
    }
    if (this.pkg.hasFile(HARNESS_CONFIG_FILE)) {
      await import(this.pkg.resolve(HARNESS_CONFIG_FILE));
    }
    this.#configured = true;
  }
  async loadFiles(format) {
    const tests = Array();
    for (let spec of this.#spec) {
      spec = spec.replace(/\.ts$/, ".js");
      spec = (0, import_node_path.relative)(this.pkg.path, spec);
      if (!spec.startsWith(".") && !spec.startsWith("build/") && !spec.startsWith("dist/")) {
        spec = `build/${format}/${spec}`;
      }
      tests.push(...await this.pkg.glob(spec));
    }
    for (let i = 0; i < tests.length; i++) {
      if (tests[i].indexOf("/src/") === -1) {
        continue;
      }
      tests[i] = await this.#mapSourceToTest(tests[i]);
    }
    if (!tests.length) {
      fatal(`No files match ${this.#spec.join(", ")}`);
    }
    return [...(0, import_files.listSupportFiles)(format), ...tests];
  }
  async #run(progress, runner) {
    const result = await runner();
    if (progress.status !== import_js_tools.Progress.Status.Success) {
      fatal(`Test ${progress.status.toLowerCase()}, aborting`);
    }
    return result;
  }
  async #mapSourceToTest(filename) {
    try {
      const src = await (0, import_promises.readFile)(filename, "utf-8");
      const [, args] = src.match(/\/\/ matter-test (.*)/) ?? [];
      if (args) {
        return this.#parseMarkerArgs(args, filename);
      }
    } catch (e) {
    }
    return filename.replace("/src/", "/test/");
  }
  #parseMarkerArgs(args, filename) {
    const parts = args.match(/[a-z]+=(?:"(?:[^"\\]|\\.)+"|[^"]\S+)/g);
    if (!parts) {
      throw new Error("No matter-test parameters detected");
    }
    let file;
    let module2;
    for (const part of parts) {
      const equalPos = part.indexOf("=");
      const name = part.substring(0, equalPos);
      let value = part.substring(equalPos + 1);
      if (value[0] === '"') {
        value = value.substring(1, value.length - 2).replace(/\\"/g, '"').replace(/\\\\/g, '"');
      }
      switch (name) {
        case "file":
          file = value;
          break;
        case "module":
          module2 = value;
          break;
        default:
          throw new Error(`Unrecognized matter-test parameter "${name}"`);
      }
    }
    if (file === void 0) {
      throw new Error(`matter-test parameter "file" is required`);
    }
    if (file.startsWith("./") || file.startsWith("../")) {
      file = (0, import_node_path.resolve)((0, import_node_path.dirname)(filename), file);
    }
    let testPkg;
    if (module2 === void 0) {
      testPkg = this.pkg;
    } else {
      testPkg = this.pkg.findPackage(module2);
      if (testPkg === void 0) {
        throw new Error(`Unknown matter-test module "${module2}"`);
      }
    }
    return testPkg.resolve("test", file);
  }
}
function fatal(message) {
  import_js_tools.std.err.write(import_js_tools.ansi.bright.red(`
${message}

`));
  process.exit(1);
}
//# sourceMappingURL=runner.js.map
