/**
 * @license
 * Copyright 2022-2026 Matter.js Authors
 * SPDX-License-Identifier: Apache-2.0
 */
import "./util/node-shims.js";
import "./global-definitions.js";
import { ansi, Graph, JsonNotFoundError, Package, Progress, Project, ProjectBuilder } from "@nacho-iot/js-tools";
import { clear } from "node:console";
import yargs from "yargs";
import { hideBin } from "yargs/helpers";
import { chip } from "./chip/chip.js";
import { defaultDescriptor, printReport } from "./print-report.js";
import { TestRunner } from "./runner.js";
const SHUTDOWN_TIMEOUT_MS = 5e3;
var TestType = /* @__PURE__ */ ((TestType2) => {
  TestType2["esm"] = "esm";
  TestType2["cjs"] = "cjs";
  TestType2["web"] = "web";
  return TestType2;
})(TestType || {});
Error.stackTraceLimit = 50;
async function main(argv = process.argv) {
  process.on("SIGINT", interrupt);
  process.on("SIGTERM", interrupt);
  const testTypes = /* @__PURE__ */ new Set();
  let ls = false;
  let manual = false;
  const args = await yargs(hideBin(argv)).usage("Runs tests in packages adhering to matter.js standards.").option("prefix", {
    alias: "p",
    default: ".",
    type: "string",
    describe: "specify directory of package to test"
  }).option("web", {
    alias: "w",
    default: false,
    type: "boolean",
    describe: "enable web tests in default test mode"
  }).option("spec", {
    type: "array",
    string: true,
    describe: "One or more paths of tests to run",
    default: "./test/**/*{.test,Test}.ts"
  }).option("all-logs", { type: "boolean", describe: "Emit log messages in real time" }).option("debug", { type: "boolean", describe: "Enable Mocha debugging" }).option("environment", { alias: "e", type: "string", describe: "Select named test environment" }).option("fgrep", { alias: "f", type: "string", describe: "Only run tests matching this string" }).option("force-exit", { type: "boolean", describe: "Force Node to exit after tests complete" }).option("grep", { alias: "g", type: "string", describe: "Only run tests matching this regexp" }).option("invert", { alias: "i", type: "boolean", describe: "Inverts --grep and --fgrep matches" }).option("profile", { type: "boolean", describe: "Write profiling data to build/profiles (node only)" }).option("wtf", { type: "boolean", describe: "Enlist wtfnode to detect test leaks" }).option("trace-unhandled", { type: "boolean", describe: "Detail unhandled rejections with trace-unhandled" }).option("machine", { type: "boolean", describe: "Tailor output for LLM ingestion" }).option("clear", { type: "boolean", describe: "Clear terminal before testing" }).option("repeat", { type: "number", describe: "Run tests multiple times (avoids VM warmup on reruns)" }).option("report", { type: "boolean", describe: "Display test summary after testing" }).option("pull", { type: "boolean", describe: "Update containers before testing", default: true }).command("*", "run all supported test types").command("esm", "run tests on node (ES6 modules)", () => testTypes.add("esm" /* esm */)).command("cjs", "run tests on node (CommonJS modules)", () => testTypes.add("cjs" /* cjs */)).command("web", "run tests in web browser", () => testTypes.add("web" /* web */)).command("inspect", "display details about tests", () => ls = true).command("manual", "start web test server and print URL for manual testing", () => {
    testTypes.add("web" /* web */);
    manual = true;
  }).strict().argv;
  let packageLocation = args.prefix;
  if (packageLocation === "." && args.spec) {
    const firstSpec = Array.isArray(args.spec) ? args.spec[0] : args.spec;
    packageLocation = firstSpec;
  }
  const builder = new ProjectBuilder();
  const pkg = new Package({ path: packageLocation });
  try {
    const found = pkg.findJson(".matter-test.json");
    const config = found.json;
    if ("allLogs" in config && !process.argv.includes("--no-all-logs")) {
      args.allLogs = !!config.allLogs;
    }
    if ("pull" in config && !process.argv.includes("--no-pull")) {
      args.pull = !!config.pull;
    }
    if ("env" in config) {
      for (const key in config.env) {
        process.env[key] = `${config.env[key]}`;
      }
    }
  } catch (e) {
    if (!(e instanceof JsonNotFoundError)) {
      throw e;
    }
  }
  chip.pullBeforeTesting = args.pull;
  if (pkg.isWorkspace) {
    const graph = await Graph.load(pkg);
    await graph.build(builder);
    if (args.clear) {
      clear();
    }
    for (const node of graph.nodes) {
      if (!node.pkg.hasTests || node.pkg.json.nacho?.test === false) {
        continue;
      }
      await test(node.pkg, true);
    }
  } else {
    const graph = await Graph.forProject(pkg.path);
    if (graph) {
      await graph.build(builder);
    } else {
      await builder.build(new Project(pkg));
    }
    if (args.clear) {
      clear();
    }
    await test(pkg, false);
  }
  await chip.close();
  if (args.forceExit) {
    process.exit(0);
  }
  async function test(pkg2, detectWeb) {
    process.chdir(pkg2.path);
    if (ls) {
      const progress2 = pkg2.start("Inspecting");
      const runner2 = new TestRunner(pkg2, progress2, args);
      const report2 = await defaultDescriptor(runner2);
      progress2.close();
      printReport(report2, true);
      console.log();
      return;
    }
    const thisTestTypes = new Set(testTypes);
    if (!thisTestTypes.size) {
      if (pkg2.supportsEsm) {
        thisTestTypes.add("esm" /* esm */);
      }
      if (pkg2.supportsCjs) {
        thisTestTypes.add("cjs" /* cjs */);
      }
      if (args.web && (!detectWeb || supportsWebTests(pkg2))) {
        thisTestTypes.add("web" /* web */);
      }
    }
    const repeat = args.repeat;
    if (repeat !== void 0 && repeat > 1) {
      if (thisTestTypes.has("web" /* web */) && thisTestTypes.size === 1) {
        throw new Error("--repeat is not supported with web tests");
      }
      thisTestTypes.delete("web" /* web */);
    }
    const progress = args.machine ? new Progress() : pkg2.start("Testing");
    const runner = new TestRunner(pkg2, progress, args);
    let report;
    if (thisTestTypes.has("esm" /* esm */)) {
      report = await runner.runNode("esm", repeat);
    }
    if (thisTestTypes.has("cjs" /* cjs */)) {
      await runner.runNode("cjs", repeat);
    }
    if (thisTestTypes.has("web" /* web */)) {
      await runner.runWeb(manual);
    }
    if (!args.machine) {
      progress.close();
    }
    if (args.report && report) {
      printReport(report);
      console.log();
    }
  }
  const timeout = setTimeout(() => {
    console.error(`Error: Tests passed but process did not exit cleanly after ${SHUTDOWN_TIMEOUT_MS / 1e3}s.`);
    const diagnostics = MatterHooks?.generateDiagnostics?.();
    if (diagnostics) {
      console.log("\nPROCESS STATE:\n", diagnostics, "\n");
    }
    process.exit(101);
  }, SHUTDOWN_TIMEOUT_MS);
  timeout.unref();
}
function supportsWebTests(pkg) {
  const testScript = pkg.json?.scripts?.test;
  if (typeof testScript !== "string") {
    return false;
  }
  return testScript.split(" ").includes("-w");
}
function interrupt() {
  process.stderr.write(`\u{1F4A5} ${ansi.red("Aborted")}
`);
  process.exit(1);
}
if (typeof MatterHooks !== "undefined") {
  MatterHooks.interrupt = interrupt;
}
export {
  main
};
//# sourceMappingURL=cli.js.map
