/**
 * @license
 * Copyright 2022-2026 Matter.js Authors
 * SPDX-License-Identifier: Apache-2.0
 */
import { Package } from "@nacho-iot/js-tools";
import { build } from "esbuild";
import express from "express";
import { writeFile } from "node:fs/promises";
import { relative } from "node:path";
import { chromium } from "playwright";
import { WebReporter } from "./web-reporter.js";
async function testWeb(runner, manual) {
  const files = await runner.loadFiles("esm");
  const bundlePath = await bundle(files, runner);
  const server = await new Promise((resolve, reject) => {
    try {
      const server2 = express().use(express.static(Package.workspace.resolve("node_modules"))).use(express.static(Package.workspace.path)).get("/", (_, res) => {
        res.send(buildIndex(bundlePath));
      }).listen(0, "localhost", () => resolve(server2));
    } catch (e) {
      reject(e);
    }
  });
  const addr = server.address();
  let ip = addr.address;
  if (ip.indexOf(":") !== -1) {
    ip = `[${ip}]`;
  }
  const url = `http://${ip}:${addr.port}/`;
  await new Promise((resolve, reject) => {
    server.on("error", reject);
    server.on("close", resolve);
    if (manual) {
      console.log(`Run tests manually at ${url}`);
    } else {
      testInBrowser(url, runner.reporter, runner.options).then(() => {
        server.close(() => {
          resolve();
        });
      }).catch((error) => {
        reject(error);
      });
    }
  });
}
testWeb.entrypointPreprocessor = void 0;
async function testInBrowser(url, reporter, options) {
  async function setup() {
    const browser = await chromium.launch();
    const page = await browser.newPage();
    return { browser, page };
  }
  async function run({ browser, page }) {
    await page.goto(url);
    await page.evaluate((options2) => globalThis.MatterTest.auto(options2), options);
    await browser.close();
  }
  await new Promise((resolve, reject) => {
    setup().then((cx) => {
      cx.page.on("console", consoleHandler(reporter));
      cx.page.on("pageerror", (error) => reject(error));
      return cx;
    }).then(run).then(resolve).catch(reject);
  });
}
function consoleHandler(reporter) {
  return (message) => {
    const type = message.type();
    switch (type) {
      case "log":
      case "debug":
      case "info":
      case "error":
      case "warning":
      case "trace":
        break;
      default:
        return;
    }
    const text = message.text();
    if (type !== "log" || !text.startsWith(WebReporter.FLAG)) {
      console[type === "warning" ? "warn" : type](text);
      return;
    }
    const args = JSON.parse(text.slice(WebReporter.FLAG.length));
    const method = reporter[args[0]];
    if (typeof method !== "function") {
      throw new Error(`Invalid encoded reporter update method ${args[0]}`);
    }
    method.call(reporter, ...args.slice(1));
  };
}
function buildIndex(bundlePath) {
  return `<!DOCTYPE html>
<html>
<head>
    <title>Matter.js Web Testing</title>
    <link rel="stylesheet" href="mocha/mocha.css">
</head>
<body>
    <div id="mocha"><h1><a href="javascript:MatterTest.start()">run tests</a></h1></div>
    <script src="mocha/mocha.js"><\/script>
    <script src="${bundlePath}" type="module"><\/script>
</body>
</html>`;
}
async function bundle(files, { pkg, entrypointPreprocessor }) {
  const entrypointPath = pkg.resolve("build/esm/test-entrypoint.js");
  const bundlePath = pkg.resolve("build/cjs/test-bundle.js");
  const entrypoint = files.map((path) => {
    path = relative(pkg.resolve("build/esm"), path).replace(/\\/g, "/");
    if (!path.startsWith(".")) {
      path = `./${path}`;
    }
    return `import ${JSON.stringify(path)}`;
  });
  entrypointPreprocessor?.(entrypoint);
  await writeFile(pkg.resolve("build/esm/test-entrypoint.js"), entrypoint.join("\n"));
  await build({
    entryPoints: [entrypointPath],
    bundle: true,
    format: "cjs",
    outfile: bundlePath,
    external: ["wtfnode"],
    keepNames: true,
    conditions: ["static-load"],
    // This doesn't work...
    // logOverride: {
    //     "direct-eval": "silent",
    // },
    // ...so we do this:
    logLevel: "error"
  });
  return pkg.workspace.relative(bundlePath);
}
export {
  testWeb
};
//# sourceMappingURL=web.js.map
