Ctrl K
ComunidadGuías…

scripts/cov-files.ts

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
#!/usr/bin/env -S deno run --allow-all

/**
 * Scoped coverage probe: run only the given test files with the full harness
 * (same setup as `test:files`), then print the lines and branches this run
 * left uncovered. This is a diagnostic view of a slice. The full
 * `test:coverage` gate stays the authority.
 *
 *   deno task cov:files test/scripts/unread-fields/
 *   deno task cov:files test/scripts/unread-fields/ --only unread-fields
 *
 * `--only <part>` limits the report to files whose path contains `part`.
 * Repeat `--only` to allow several parts. Every other argument goes to
 * `deno test` unchanged.
 */

import { splitFlagValues } from "#scripts/flag-values.ts";
import { requireValue } from "#shared/required-value.ts";
import {
  type CoverageFailure,
  findCoverageFailures,
  printFailureSummary,
} from "./coverage-check.ts";
import { COVERAGE_OUTPUT_DIR } from "./coverage-output.ts";
import { captureOutput, denoCommand } from "./process.ts";
import { projectRoot } from "./project-root.ts";
import { runTests, withTestHarness } from "./test-harness.ts";

const usage = (): never => {
  console.error(
    "Usage: deno task cov:files <test-file>... [--only <path-part>]...",
  );
  Deno.exit(1);
};

interface ScopedArgs {
  only: string[];
  testArgs: string[];
}

/** One `--only` value: a real path part, never the flag behind it. */
const onlyPart = (value: string | undefined): string => {
  const part = requireValue(value, "--only needs a path part");
  if (part.startsWith("--")) usage();
  return part;
};

/** The `--only` parts that focus the report, plus the args for `deno test`. */
const scopedArgs = (args: string[]): ScopedArgs => {
  const { rest, values } = splitFlagValues(args, "--only");
  return { only: values.map(onlyPart), testArgs: rest };
};

/** The run's lcov, read straight from `deno coverage`. */
const lcovOfRun = async (): Promise<string> => {
  const captured = await captureOutput(
    denoCommand(["coverage", COVERAGE_OUTPUT_DIR, "--lcov"], {
      cwd: projectRoot,
    }),
  );
  if (!captured.success) {
    throw new Error(`deno coverage failed with code ${captured.code}`);
  }
  return captured.stdout;
};

/** A failure counts when its path holds a part, or when no part was given. */
const matchesOnly = (
  failure: CoverageFailure,
  only: readonly string[],
): boolean =>
  only.length === 0 || only.some((part) => failure.file.includes(part));

const printGapsFor = async (
  failures: CoverageFailure[],
  only: readonly string[],
): Promise<void> => {
  const focused = failures.filter((failure) => matchesOnly(failure, only));
  if (focused.length === 0) {
    console.log(
      only.length === 0
        ? "All files have 100% line and branch coverage."
        : "No gaps among the files matched by --only.",
    );
    return;
  }
  for (const failure of focused) await printFailureSummary(failure);
  const hidden = failures.length - focused.length;
  console.error(
    `\n${focused.length} file(s) with gaps${
      hidden > 0 ? ` (${hidden} more not shown; pass --only to focus)` : ""
    }.`,
  );
  console.error("A scoped run covers only what these tests touch.");
};

const main = async (): Promise<void> => {
  const { only, testArgs } = scopedArgs(Deno.args);
  if (testArgs.length === 0) usage();

  const testCode = await withTestHarness(() => runTests(testArgs, true));
  if (testCode !== 0) Deno.exit(testCode);

  const failures = findCoverageFailures(await lcovOfRun());
  if (failures === null) {
    console.error("No coverage data was collected for this run.");
    Deno.exit(1);
  }
  await printGapsFor(failures, only);
};

main();