import { describe, expect, it } from "vitest";
import {
  choosePlaywrightFinalResult,
  extractPlaywrightFailure,
  parsePlaywrightJsonResults,
} from "./playwright.mjs";

describe("playwright-report", () => {
  it("handles empty and invalid output", () => {
    expect(parsePlaywrightJsonResults("", "/tmp")).toEqual({
      fileResults: new Map(),
      errors: [],
    });

    const invalid = parsePlaywrightJsonResults("{", "/tmp");
    expect(invalid.errors[0]).toContain("Could not parse Playwright JSON output");
  });

  it("collects nested suite results", () => {
    const stdout = JSON.stringify({
      errors: [{ message: "reporter failure" }],
      suites: [
        {
          file: "/tmp/tests/auth.spec.js",
          specs: [
            {
              title: "auth works",
              tests: [
                {
                  outcome: "unexpected",
                  results: [
                    {
                      status: "failed",
                      duration: 15,
                      error: {
                        message: "boom\nstack",
                      },
                    },
                  ],
                },
              ],
            },
          ],
        },
      ],
    });

    const parsed = parsePlaywrightJsonResults(stdout, "/tmp");
    expect(parsed.errors).toEqual(["reporter failure"]);
    expect(parsed.fileResults.get("tests/auth.spec.js")).toEqual({
      failed: true,
      status: "failed",
      error: "boom",
      durationMs: 15,
      failureDetails: [
        {
          kind: "playwright-spec",
          key: "auth works",
          title: "auth works",
          count: 1,
          message: "boom",
        },
      ],
    });
  });

  it("marks files as skipped when every Playwright test is skipped", () => {
    const stdout = JSON.stringify({
      suites: [
        {
          file: "/tmp/tests/billing.spec.js",
          specs: [
            {
              title: "billing is stubbed",
              tests: [
                {
                  outcome: "skipped",
                  results: [
                    {
                      status: "skipped",
                      duration: 7,
                    },
                  ],
                },
              ],
            },
          ],
        },
      ],
    });

    const parsed = parsePlaywrightJsonResults(stdout, "/tmp");
    expect(parsed.fileResults.get("tests/billing.spec.js")).toEqual({
      failed: false,
      status: "skipped",
      error: null,
      durationMs: 7,
      failureDetails: [],
    });
  });

  it("keeps file status passed when one spec passes and another is skipped", () => {
    const stdout = JSON.stringify({
      suites: [
        {
          file: "/tmp/tests/mixed.spec.js",
          specs: [
            {
              title: "passes",
              tests: [
                {
                  outcome: "expected",
                  results: [
                    {
                      status: "passed",
                      duration: 5,
                    },
                  ],
                },
              ],
            },
            {
              title: "skips",
              tests: [
                {
                  outcome: "skipped",
                  results: [
                    {
                      status: "skipped",
                      duration: 3,
                    },
                  ],
                },
              ],
            },
          ],
        },
      ],
    });

    const parsed = parsePlaywrightJsonResults(stdout, "/tmp");
    expect(parsed.fileResults.get("tests/mixed.spec.js")).toEqual({
      failed: false,
      status: "passed",
      error: null,
      durationMs: 8,
      failureDetails: [],
    });
  });

  it("chooses the final result and extracts failures", () => {
    expect(
      choosePlaywrightFinalResult([
        { status: "failed" },
        { status: "passed" },
      ])
    ).toEqual({ status: "passed" });

    expect(
      extractPlaywrightFailure(
        { error: { message: "first line\nsecond line" } },
        { title: "spec title" },
        { errors: [] }
      )
    ).toBe("first line");
  });
});
