import "./chunk-2ESYSVXG.js";

// src/reporter.ts
import chalk from "chalk";
import { readConfig, upload } from "@argos-ci/core";
import { copyFile, readdir, writeFile } from "fs/promises";
import { dirname as dirname2, join } from "path";

// src/util.ts
import { createRequire as createRequire2 } from "module";

// src/metadata.ts
import {
  getGitRepositoryPath,
  readVersionFromPackage
} from "@argos-ci/util";
import { relative } from "path";
import { createRequire } from "module";
import { AsyncLocalStorage } from "async_hooks";
var require2 = createRequire(import.meta.url);
function tryResolve(pkg) {
  try {
    return require2.resolve(pkg);
  } catch {
    return null;
  }
}
var metadataConfigStorage = new AsyncLocalStorage();
var DEFAULT_PLAYWRIGHT_LIBRARIES = [
  "@playwright/test",
  "playwright",
  "playwright-core"
];
async function getAutomationLibraryMetadata() {
  const metadataConfig = metadataConfigStorage.getStore();
  const libraries = metadataConfig?.playwrightLibraries ?? DEFAULT_PLAYWRIGHT_LIBRARIES;
  for (const name of libraries) {
    const pkgPath = tryResolve(`${name}/package.json`);
    if (pkgPath) {
      const version = await readVersionFromPackage(pkgPath);
      return { version, name };
    }
  }
  throw new Error(
    `Unable to find any of the following packages: ${libraries.join(", ")}`
  );
}
async function getArgosPlaywrightVersion() {
  const pkgPath = require2.resolve("@argos-ci/playwright/package.json");
  return readVersionFromPackage(pkgPath);
}
async function getSdkMetadata() {
  const metadataConfig = metadataConfigStorage.getStore();
  if (metadataConfig) {
    return metadataConfig.sdk;
  }
  const argosPlaywrightVersion = await getArgosPlaywrightVersion();
  return {
    name: "@argos-ci/playwright",
    version: argosPlaywrightVersion
  };
}
async function getLibraryMetadata() {
  const [automationLibrary, sdk] = await Promise.all([
    getAutomationLibraryMetadata(),
    getSdkMetadata()
  ]);
  return {
    automationLibrary,
    sdk
  };
}
async function getTestMetadataFromTestCase(testCase, testResult) {
  const repositoryPath = await getGitRepositoryPath();
  const testMetadata = {
    title: testCase.title,
    titlePath: testCase.titlePath(),
    retry: testResult.retry,
    retries: testCase.retries,
    repeat: testCase.repeatEachIndex,
    location: {
      file: repositoryPath ? relative(repositoryPath, testCase.location.file) : testCase.location.file,
      line: testCase.location.line,
      column: testCase.location.column
    },
    annotations: testCase.annotations
  };
  return testMetadata;
}
async function getMetadataFromTestCase(testCase, testResult) {
  const [libMetadata, testMetadata] = await Promise.all([
    getLibraryMetadata(),
    getTestMetadataFromTestCase(testCase, testResult)
  ]);
  const metadata = {
    test: testMetadata,
    ...libMetadata
  };
  return metadata;
}

// src/util.ts
import {
  getGlobalScript
} from "@argos-ci/browser";
import { dirname, resolve } from "path";
import { mkdir } from "fs/promises";
var require3 = createRequire2(import.meta.url);
var PNG_EXTENSION = `.png`;
var ARIA_EXTENSION = `.aria.yml`;
var METADATA_EXTENSION = `.argos.json`;
var MAX_NAME_LENGTH = 255 - PNG_EXTENSION.length - METADATA_EXTENSION.length;
function truncate(text, length) {
  if (text.length <= length) {
    return text;
  }
  return text.slice(0, length - 1) + "\u2026";
}
function getAutomaticScreenshotName(test, result) {
  const name = test.titlePath().join(" ");
  let suffix = "";
  suffix += result.retry > 0 ? ` #${result.retry + 1}` : "";
  suffix += result.status === "failed" || result.status === "timedOut" ? " (failed)" : "";
  const maxNameLength = MAX_NAME_LENGTH - suffix.length;
  if (name.length > maxNameLength) {
    return `${truncate(`${test.id} - ${test.title}`, maxNameLength)}${suffix}`;
  }
  return `${name}${suffix}`;
}

// src/attachment.ts
function parseAttachmentName(name) {
  const match = name.match(/^argos\/(screenshot|aria)(\/metadata)?___(.*)$/);
  if (!match) {
    return null;
  }
  const [, mainType, metadataPart, originalName] = match;
  if (!originalName) {
    throw new Error(`Invalid attachment name: ${name}`);
  }
  const type = metadataPart ? `${mainType}/metadata` : mainType;
  return { type, originalName };
}
function getAttachmentFilename(attachment) {
  const parsed = parseAttachmentName(attachment.name);
  if (!parsed) {
    throw new Error(`Invalid attachment name: ${attachment.name}`);
  }
  const { type, originalName } = parsed;
  const extension = {
    screenshot: PNG_EXTENSION,
    aria: ARIA_EXTENSION,
    "screenshot/metadata": `${PNG_EXTENSION}${METADATA_EXTENSION}`,
    "aria/metadata": `${ARIA_EXTENSION}${METADATA_EXTENSION}`
  }[type];
  return `${originalName}${extension}`;
}
function checkIsTrace(attachment) {
  return attachment.name === "trace" && attachment.contentType === "application/zip" && Boolean(attachment.path);
}
function checkIsArgosSnapshot(attachment) {
  const parsed = parseAttachmentName(attachment.name);
  if (!parsed) {
    return false;
  }
  return parsed.type === "aria" || parsed.type === "screenshot";
}
function checkIsArgosMetadata(attachment) {
  const parsed = parseAttachmentName(attachment.name);
  if (!parsed) {
    return false;
  }
  return parsed.type === "aria/metadata" || parsed.type === "screenshot/metadata";
}
function checkIsAutomaticScreenshot(attachment) {
  return attachment.name === "screenshot" && attachment.contentType === "image/png" && Boolean(attachment.path);
}

// src/debug.ts
import createDebug from "debug";
var KEY = "@argos-ci/playwright";
var debug = createDebug(KEY);

// src/reporter.ts
import { createDirectory, createTemporaryDirectory } from "@argos-ci/util";
function checkIsDynamicBuildName(buildName) {
  return Boolean(typeof buildName === "object" && buildName);
}
function createArgosReporterOptions(options) {
  return options;
}
async function getParallelFromConfig(config) {
  if (!config.shard) {
    return null;
  }
  if (config.shard.total === 1) {
    return null;
  }
  const argosConfig = await readConfig();
  if (!argosConfig.parallelNonce) {
    throw new Error(
      "Playwright shard mode detected. Please specify ARGOS_PARALLEL_NONCE env variable. Read /parallel-testing"
    );
  }
  return {
    total: argosConfig.parallelTotal ?? config.shard.total,
    nonce: argosConfig.parallelNonce,
    index: argosConfig.parallelIndex ?? config.shard.current
  };
}
var ArgosReporter = class {
  rootUploadDirectoryPromise;
  uploadDirectoryPromises;
  config;
  playwrightConfig;
  uploadToArgos;
  constructor(config) {
    this.config = config;
    this.uploadToArgos = config.uploadToArgos ?? true;
    this.rootUploadDirectoryPromise = null;
    this.uploadDirectoryPromises = /* @__PURE__ */ new Map();
  }
  /**
   * Write a file to the temporary directory.
   */
  async writeFile(path, body) {
    await createDirectory(dirname2(path));
    debug(`Writing file to ${path}`);
    await writeFile(path, body);
    debug(`File written to ${path}`);
  }
  /**
   * Copy a file to the temporary directory.
   */
  async copyFile(from, to) {
    await createDirectory(dirname2(to));
    debug(`Copying file from ${from} to ${to}`);
    await copyFile(from, to);
    debug(`File copied from ${from} to ${to}`);
  }
  /**
   * Copy the trace file if found in the result.
   */
  async copyTraceIfFound(result, path) {
    const trace = result.attachments.find(checkIsTrace) ?? null;
    if (trace) {
      await this.copyFile(trace.path, path + ".pw-trace.zip");
    }
  }
  /**
   * Get the root upload directory (cached).
   */
  getRootUploadDirectory() {
    if (!this.rootUploadDirectoryPromise) {
      this.rootUploadDirectoryPromise = createTemporaryDirectory();
    }
    return this.rootUploadDirectoryPromise;
  }
  onBegin(config) {
    debug("ArgosReporter:onBegin");
    this.playwrightConfig = config;
  }
  async onTestEnd(test, result) {
    const buildName = checkIsDynamicBuildName(this.config.buildName) ? this.config.buildName.get(test) : this.config.buildName;
    if (buildName === "") {
      throw new Error('Argos "buildName" cannot be an empty string.');
    }
    const rootUploadDir = await this.getRootUploadDirectory();
    const uploadDir = buildName ? join(rootUploadDir, buildName) : rootUploadDir;
    debug("ArgosReporter:onTestEnd");
    await Promise.all(
      result.attachments.map(async (attachment) => {
        if (checkIsArgosSnapshot(attachment) || checkIsArgosMetadata(attachment)) {
          const path = join(uploadDir, getAttachmentFilename(attachment));
          await Promise.all([
            this.copyFile(attachment.path, path),
            this.copyTraceIfFound(result, path)
          ]);
          return;
        }
        if (checkIsAutomaticScreenshot(attachment)) {
          const metadata = await getMetadataFromTestCase(test, result);
          const name = getAutomaticScreenshotName(test, result);
          const path = join(uploadDir, `${name}${PNG_EXTENSION}`);
          await Promise.all([
            this.writeFile(path + METADATA_EXTENSION, JSON.stringify(metadata)),
            this.copyFile(attachment.path, path),
            this.copyTraceIfFound(result, path)
          ]);
          return;
        }
      })
    );
  }
  async onEnd(result) {
    debug("ArgosReporter:onEnd");
    const rootUploadDir = await this.getRootUploadDirectory();
    if (!this.uploadToArgos) {
      debug("Not uploading to Argos because uploadToArgos is false.");
      debug(`Upload directory: ${rootUploadDir}`);
      return;
    }
    debug("Getting parallel from config");
    const parallel = await getParallelFromConfig(this.playwrightConfig);
    if (parallel) {
      debug(
        `Using parallel config \u2014 total: ${parallel.total}, nonce: "${parallel.nonce}"`
      );
    } else {
      debug("Non-parallel mode");
    }
    const buildNameConfig = this.config.buildName;
    const uploadOptions = {
      files: ["**/*.png", "**/*.aria.yml"],
      parallel: parallel ?? void 0,
      ...this.config,
      buildName: void 0,
      // We will set it later
      metadata: {
        testReport: {
          status: result.status,
          stats: {
            startTime: result.startTime.toISOString(),
            duration: result.duration
          }
        }
      }
    };
    try {
      if (checkIsDynamicBuildName(buildNameConfig)) {
        debug(
          `Dynamic build names, uploading to Argos for each build name: ${buildNameConfig.values.join()}`
        );
        const directories = await readdir(rootUploadDir);
        if (directories.some((dir) => !buildNameConfig.values.includes(dir))) {
          throw new Error(
            `The \`buildName.values\` (${buildNameConfig.values.join(", ")}) are inconsistent with the \`buildName.get\` returns values (${directories.join(", ")}). Please fix the configuration.`
          );
        }
        const iteratesOnBuildNames = parallel ? buildNameConfig.values : directories;
        for (const buildName of iteratesOnBuildNames) {
          const uploadDir = join(rootUploadDir, buildName);
          await createDirectory(uploadDir);
          debug(`Uploading to Argos for build: ${buildName}`);
          const res = await upload({
            ...uploadOptions,
            root: uploadDir,
            buildName
          });
          console.log(
            chalk.green(
              `\u2705 Argos "${buildName}" build created: ${res.build.url}`
            )
          );
        }
      } else {
        debug("Uploading to Argos");
        const uploadDir = buildNameConfig ? join(rootUploadDir, buildNameConfig) : rootUploadDir;
        const res = await upload({
          ...uploadOptions,
          root: uploadDir,
          buildName: buildNameConfig ?? void 0
        });
        console.log(chalk.green(`\u2705 Argos build created: ${res.build.url}`));
      }
    } catch (error) {
      console.error(error);
      return { status: "failed" };
    }
    return;
  }
  printsToStdio() {
    return false;
  }
};
var reporter_default = ArgosReporter;
export {
  createArgosReporterOptions,
  reporter_default as default
};
