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 | 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 5x 5x 5x 5x 5x 5x 5x 5x 5x 5x 5x 5x 5x 5x 5x 5x 25x 25x 22x 22x 3x 25x 25x 25x 25x 25x 25x 25x 25x 5x 5x 1x 1x 1x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 20x 20x 16x 16x 16x 4x 4x 4x 20x 20x 20x 20x 4x 4x 1x | import { DyE2E_CWVMetric_Type } from '../../contracts/_enums/cwv-metric-type.enum';
import { DyE2E_CWVThresholds_Interface } from '../../contracts/_models/interfaces/cwv-thresholds.interface';
import { CWV_GOOD_THRESHOLDS } from '../../contracts/_collections/constants/cwv-default-thresholds.const';
/**
* Wave-3 — CWV JSON-report summarizer util.
*
* Bemenet: a `DyE2E_CWVEmission_Util.emitRouteBlock()` által írt JSON-shape
* ({ route, summary, raw }). Kimenet: ember-olvasható markdown vagy JSON.
*/
export interface DyE2E_CWVReportShape_Min {
route?: string;
summary?: Record<string, { n?: number; p50?: number; p75?: number; p95?: number; mean?: number; min?: number; max?: number }>;
}
export class DyE2E_CWVSummarize_Util {
/** Markdown-tablázat egy report-ról. */
static toMarkdown(
report: DyE2E_CWVReportShape_Min,
thresholds: DyE2E_CWVThresholds_Interface = CWV_GOOD_THRESHOLDS,
): string {
const lines: string[] = [];
lines.push(`## CWV summary — ${report.route ?? 'unknown route'}`);
lines.push('');
lines.push('| Metric | n | p50 | p75 | p95 | Target | Status |');
lines.push('|---|---|---|---|---|---|---|');
const metrics: { key: DyE2E_CWVMetric_Type; thresholdKey: keyof DyE2E_CWVThresholds_Interface; unit: string }[] = [
{ key: DyE2E_CWVMetric_Type.lcp, thresholdKey: 'lcp_p75_ms', unit: 'ms' },
{ key: DyE2E_CWVMetric_Type.cls, thresholdKey: 'cls_p75', unit: '' },
{ key: DyE2E_CWVMetric_Type.inp, thresholdKey: 'inp_p75_ms', unit: 'ms' },
{ key: DyE2E_CWVMetric_Type.ttfb, thresholdKey: 'ttfb_p75_ms', unit: 'ms' },
{ key: DyE2E_CWVMetric_Type.fcp, thresholdKey: 'fcp_p75_ms', unit: 'ms' },
];
for (const m of metrics) {
const stat = report.summary?.[m.key];
if (!stat || !stat.n || stat.n === 0) {
continue;
}
const threshold: number | undefined = thresholds[m.thresholdKey];
const passing: boolean = typeof threshold === 'number' && typeof stat.p75 === 'number' && stat.p75 <= threshold;
const icon: string = passing ? '🟢' : (typeof threshold === 'number' ? '🔴' : '⚪');
const targetText: string = typeof threshold === 'number' ? `≤ ${threshold}${m.unit}` : 'n/a';
const p50: string = typeof stat.p50 === 'number' ? `${stat.p50.toFixed(2)}${m.unit}` : '—';
const p75: string = typeof stat.p75 === 'number' ? `${stat.p75.toFixed(2)}${m.unit}` : '—';
const p95: string = typeof stat.p95 === 'number' ? `${stat.p95.toFixed(2)}${m.unit}` : '—';
lines.push(`| ${m.key.toUpperCase()} | ${stat.n} | ${p50} | ${p75} | ${p95} | ${targetText} | ${icon} |`);
}
return lines.join('\n');
}
/** Egyszerű JSON-summary (csak p75 + status). */
static toJsonSummary(
report: DyE2E_CWVReportShape_Min,
thresholds: DyE2E_CWVThresholds_Interface = CWV_GOOD_THRESHOLDS,
): Record<string, { p75: number | null; status: 'pass' | 'fail' | 'no-data' }> {
const out: Record<string, { p75: number | null; status: 'pass' | 'fail' | 'no-data' }> = {};
const mapping: { key: DyE2E_CWVMetric_Type; thresholdKey: keyof DyE2E_CWVThresholds_Interface }[] = [
{ key: DyE2E_CWVMetric_Type.lcp, thresholdKey: 'lcp_p75_ms' },
{ key: DyE2E_CWVMetric_Type.cls, thresholdKey: 'cls_p75' },
{ key: DyE2E_CWVMetric_Type.inp, thresholdKey: 'inp_p75_ms' },
{ key: DyE2E_CWVMetric_Type.ttfb, thresholdKey: 'ttfb_p75_ms' },
{ key: DyE2E_CWVMetric_Type.fcp, thresholdKey: 'fcp_p75_ms' },
];
for (const m of mapping) {
const stat = report.summary?.[m.key];
if (!stat || !stat.n || stat.n === 0) {
out[m.key] = { p75: null, status: 'no-data' };
continue;
}
const threshold: number | undefined = thresholds[m.thresholdKey];
const status: 'pass' | 'fail' | 'no-data' =
typeof threshold === 'number' && typeof stat.p75 === 'number'
? (stat.p75 <= threshold ? 'pass' : 'fail')
: 'no-data';
out[m.key] = { p75: stat.p75 ?? null, status: status };
}
return out;
}
}
|