All files / src overview-report.ts

100% Statements 9/9
93.18% Branches 41/44
100% Functions 3/3
100% Lines 9/9

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53                              108x 108x     108x     108x 108x 108x 108x                                 105x       537x            
import { withReportLocale } from "./report-locale.js";
import type { QualityOverview } from "./quality-overview.js";
 
export interface OverviewLinks {
  readonly requirementMap?: string;
  readonly allure?: string;
  readonly coverage?: string;
  readonly source?: { readonly url: string; readonly label: string };
}
 
export function renderOverview(
  overview: QualityOverview,
  sha = "",
  links: OverviewLinks = {},
): string {
  const requirement = overview.requirementCoverage;
  const requirementValue = requirement
    ? `${requirement.covered} / ${requirement.total}`
    : "Unavailable";
  const requirementPercent = requirement
    ? `${percent(requirement.covered, requirement.total)}%`
    : "—";
  const missing = overview.missingEvidence ?? "Unavailable";
  const tests = overview.testResults;
  const lines = overview.codeCoverageLines;
  return withReportLocale(`<!doctype html>
<html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><meta name="format-detection" content="telephone=no"><title>Moura Quality Reports</title>
<style>:root{color-scheme:light}body{font:16px system-ui,sans-serif;line-height:1.5;max-width:72rem;margin:auto;padding:2rem;color:#172033;background:#fff}h1,h2{line-height:1.2}.intro{margin-bottom:2rem;color:#4b5565}.status-card,.metric,.report{border:1px solid #ccd3df;border-radius:.65rem;padding:1.25rem}.status-card{border-width:2px;margin-bottom:1rem}.status-card[data-status=PASS]{border-color:#167044}.status-card[data-status=INCOMPLETE]{border-color:#a15c00}.status-card[data-status=FAIL]{border-color:#b42318}.eyebrow{display:block;font-weight:700;color:#4b5565}.overall{display:block;font-size:2rem;font-weight:800}.overall.PASS{color:#167044}.overall.INCOMPLETE{color:#854d0e}.overall.FAIL{color:#b42318}.primary,.secondary,.reports{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:1rem;margin:1rem 0}.metric{color:inherit;text-decoration:none}.metric h2,.report h2{margin:0 0 .5rem;font-size:1.15rem}.value{display:block;font-size:1.8rem;font-weight:750}.subvalue{color:#4b5565}.results{display:grid;grid-template-columns:repeat(3,1fr);gap:.5rem}.results span{display:block}.results strong{font-size:1.35rem}.details{margin-top:2rem}.report{display:block;color:inherit;text-decoration:none}.report p{margin:.35rem 0;color:#4b5565}.open{font-weight:700;color:#167044}.meta{margin-top:2rem;font-size:.9rem}.meta p{margin:.25rem 0}.meta a,.metric:hover,.metric:focus,.report:hover,.report:focus{color:#167044}@media(max-width:40rem){body{padding:1rem}.intro{margin-bottom:1.5rem}.primary,.secondary,.reports{grid-template-columns:1fr}}</style></head>
<body><main><h1>Moura Quality Reports</h1><p class="intro">Verification completeness against project requirements.</p>
<section class="status-card" data-status="${overview.status}"><span class="eyebrow">Overall Status</span><strong class="overall ${overview.status}">${overview.status}</strong><span>Required verification and its Evidence determine this status.</span></section>
<div class="primary"><a class="metric" href="${escapeHtml(links.requirementMap ?? "./moura/index.html")}"><h2>Requirement Coverage</h2><strong class="value">${requirementValue}</strong><span class="subvalue">${requirementPercent}</span></a>
<a class="metric" href="${escapeHtml(links.requirementMap ?? "./moura/index.html")}"><h2>Missing Evidence</h2><strong class="value">${missing}</strong><span class="subvalue">View verification gaps →</span></a></div>
<div class="secondary"><${links.allure ? `a class="metric" href="${escapeHtml(links.allure)}"` : 'div class="metric"'}><h2>Test Results</h2><div class="results"><span><span>Passed</span><strong>${tests?.passed ?? "—"}</strong></span><span><span>Failed</span><strong>${tests ? tests.failed + tests.broken : "—"}</strong></span><span><span>Skipped</span><strong>${tests?.skipped ?? "—"}</strong></span></div></${links.allure ? "a" : "div"}>
<${links.coverage ? `a class="metric" href="${escapeHtml(links.coverage)}"` : 'div class="metric"'}><h2>Code Coverage</h2><span>Lines</span><strong class="value">${lines === undefined ? "—" : `${lines}%`}</strong></${links.coverage ? "a" : "div"}></div>
<section class="details"><h2>Detailed Reports</h2><div class="reports">
<a class="report" href="${escapeHtml(links.requirementMap ?? "./moura/index.html")}"><h2>Requirement Coverage</h2><p>Declared traceability and verification status</p><span class="open">Open →</span></a>
${links.allure ? `<a class="report" href="${escapeHtml(links.allure)}"><h2>Allure Report</h2><p>Test execution details</p><span class="open">Open →</span></a>` : ""}
${links.coverage ? `<a class="report" href="${escapeHtml(links.coverage)}"><h2>Code Coverage</h2><p>Source code coverage</p><span class="open">Open →</span></a>` : ""}
</div></section>${links.source || sha ? `<footer class="meta">${links.source ? `<p><span>Source:</span> <a href="${escapeHtml(links.source.url)}">${escapeHtml(links.source.label)}</a></p>` : ""}${sha ? `<p><span>Commit:</span> <code>${escapeHtml(sha)}</code></p>` : ""}</footer>` : ""}</main></body></html>\n`);
}
 
function percent(covered: number, total: number): number {
  return total === 0 ? 100 : Math.round((covered / total) * 100);
}
 
function escapeHtml(value: string): string {
  return value
    .replaceAll("&", "&amp;")
    .replaceAll("<", "&lt;")
    .replaceAll(">", "&gt;")
    .replaceAll('"', "&quot;");
}