All files / cwv/_collections cwv-comparison.util.ts

100% Statements 90/90
84% Branches 21/25
100% Functions 4/4
100% Lines 90/90

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 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 911x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 9x 9x 9x 9x 9x 9x 9x 9x 9x 9x 9x 9x 9x 45x 45x 45x 34x 34x 11x 45x 45x 45x 7x 45x 45x 45x 9x 9x 1x 1x 1x 1x 1x 1x 1x 1x 2x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x  
import { DyE2E_CWVMetric_Type } from '../../contracts/_enums/cwv-metric-type.enum';
 
/**
 * MP-05/Wave-3 — CWV report comparison util.
 *
 * Két JSON-report-ot összevet (régi vs új) és visszaadja a regressziókat.
 * Tipikus use-case: nightly CICD vs előző-stable, vagy PR-build vs main.
 */
 
export interface DyE2E_CWVComparison_Summary {
  metric: DyE2E_CWVMetric_Type;
  oldP75: number;
  newP75: number;
  /** Delta = newP75 − oldP75. Pozitív = romlás (LCP/CLS/INP/TTFB/FCP-nél). */
  delta: number;
  /** Százalékos változás. */
  deltaPercent: number;
  /** "improved" | "regressed" | "stable". */
  status: 'improved' | 'regressed' | 'stable';
}
 
export interface DyE2E_CWVReport_Shape {
  route?: string;
  summary?: Record<string, { p75?: number; n?: number }>;
  raw?: Array<{ metric?: string; value?: number; iter?: number }>;
  [extra: string]: unknown;
}
 
export class DyE2E_CWVComparison_Util {
 
  /** Delta-tűrés (% alatti változás "stable"-nek számít). Default 5%. */
  static defaultStableTolerancePercent: number = 5;
 
  /**
   * Összevet két CWV-JSON-report-ot.
   *
   * @param oldReport — előző (baseline) report
   * @param newReport — új (current) report
   * @param tolerance — % alatti változás "stable". Default `defaultStableTolerancePercent`.
   */
  static compareReports(
    oldReport: DyE2E_CWVReport_Shape,
    newReport: DyE2E_CWVReport_Shape,
    tolerance: number = DyE2E_CWVComparison_Util.defaultStableTolerancePercent,
  ): DyE2E_CWVComparison_Summary[] {
    const metrics: DyE2E_CWVMetric_Type[] = [
      DyE2E_CWVMetric_Type.lcp,
      DyE2E_CWVMetric_Type.cls,
      DyE2E_CWVMetric_Type.inp,
      DyE2E_CWVMetric_Type.ttfb,
      DyE2E_CWVMetric_Type.fcp,
    ];
    const result: DyE2E_CWVComparison_Summary[] = [];
    for (const metric of metrics) {
      const oldP75: number = oldReport.summary?.[metric]?.p75 ?? NaN;
      const newP75: number = newReport.summary?.[metric]?.p75 ?? NaN;
      if (!isFinite(oldP75) || !isFinite(newP75)) {
        continue;
      }
      const delta: number = newP75 - oldP75;
      const deltaPercent: number = oldP75 > 0 ? (delta / oldP75) * 100 : 0;
      const status: 'improved' | 'regressed' | 'stable' =
        Math.abs(deltaPercent) <= tolerance ? 'stable' :
        delta < 0 ? 'improved' :
        'regressed';
      result.push({ metric, oldP75, newP75, delta, deltaPercent, status });
    }
    return result;
  }
 
  /** Csak a regresszióknak a leírása (kiemelve). */
  static regressionsOnly(comparisons: DyE2E_CWVComparison_Summary[]): DyE2E_CWVComparison_Summary[] {
    return comparisons.filter((c: DyE2E_CWVComparison_Summary): boolean => c.status === 'regressed');
  }
 
  /** Ember-olvasható összegzés markdown-tablázatra. */
  static formatMarkdownTable(comparisons: DyE2E_CWVComparison_Summary[]): string {
    if (comparisons.length === 0) {
      return '_No comparable metrics._';
    }
    const header: string = '| Metric | Old p75 | New p75 | Delta | Δ% | Status |\n|---|---|---|---|---|---|';
    const rows: string[] = comparisons.map((c: DyE2E_CWVComparison_Summary): string => {
      const unit: string = c.metric === DyE2E_CWVMetric_Type.cls ? '' : 'ms';
      const icon: string = c.status === 'improved' ? '🟢' :
        c.status === 'regressed' ? '🔴' : '⚪';
      return `| ${c.metric.toUpperCase()} | ${c.oldP75.toFixed(2)}${unit} | ${c.newP75.toFixed(2)}${unit} | ${c.delta.toFixed(2)}${unit} | ${c.deltaPercent.toFixed(1)}% | ${icon} ${c.status} |`;
    });
    return `${header}\n${rows.join('\n')}`;
  }
}