Skip to content

Commit 7367982

Browse files
authored
Merge pull request #158 from mgifford/copilot/add-tooltip-for-numerical-calculations
Add calculation tooltips to Performance Impact estimated totals
2 parents 100f662 + 55df629 commit 7367982

File tree

2 files changed

+73
-9
lines changed

2 files changed

+73
-9
lines changed

src/publish/render-pages.js

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1431,20 +1431,30 @@ function renderPerformanceImpactSection(report) {
14311431
const urlCount = impact.url_count_with_timing;
14321432
const scanDate = escapeHtml(formatScanDate(report.run_date));
14331433

1434+
const timeDuration = formatDuration(extraHours);
1435+
const totalSeconds = Number(impact.total_extra_load_time_seconds).toLocaleString('en-US');
1436+
const timeTipId = `perf-impact-tip-${_perfTimeTooltipSeq++}`;
1437+
const timeTooltipText = `Extra time is calculated as: for each scanned URL, max(0, actual LCP \u2212 ${escapeHtml(benchmarkLcpSec)}s) \u00d7 page loads. Total: ${escapeHtml(totalSeconds)} seconds.`;
1438+
const timeValueHtml = `<span class="perf-time-trigger" role="button" tabindex="0" aria-label="${escapeHtml(timeDuration)}" aria-describedby="${timeTipId}">${escapeHtml(timeDuration)}<span id="${timeTipId}" role="tooltip" class="perf-time-tooltip">${timeTooltipText}</span></span>`;
1439+
14341440
const timeRow = `<tr>
14351441
<td data-label="Metric">Extra time waiting (vs ${benchmarkLcpSec}s LCP benchmark)</td>
1436-
<td data-label="Estimated total">${formatDuration(extraHours)}</td>
1437-
<td data-label="Notes">${Number(impact.total_extra_load_time_seconds).toLocaleString('en-US')} seconds</td>
1442+
<td data-label="Estimated total">${timeValueHtml}</td>
1443+
<td data-label="Notes">${totalSeconds} seconds</td>
14381444
</tr>`;
14391445

1440-
const weightRow =
1441-
impact.url_count_with_weight > 0
1442-
? `<tr>
1446+
let weightRow = '';
1447+
if (impact.url_count_with_weight > 0) {
1448+
const dataSizeStr = formatDataSize(extraGb);
1449+
const weightTipId = `perf-impact-tip-${_perfTimeTooltipSeq++}`;
1450+
const weightTooltipText = `Extra data is calculated as: for each scanned URL, max(0, actual page weight \u2212 ${escapeHtml(benchmarkWeightMb)} MB) \u00d7 page loads.`;
1451+
const weightValueHtml = `<span class="perf-time-trigger" role="button" tabindex="0" aria-label="${escapeHtml(dataSizeStr)}" aria-describedby="${weightTipId}">${escapeHtml(dataSizeStr)}<span id="${weightTipId}" role="tooltip" class="perf-time-tooltip">${weightTooltipText}</span></span>`;
1452+
weightRow = `<tr>
14431453
<td data-label="Metric">Extra data transferred (vs ${benchmarkWeightMb} MB page weight benchmark)</td>
1444-
<td data-label="Estimated total">${formatDataSize(extraGb)}</td>
1454+
<td data-label="Estimated total">${weightValueHtml}</td>
14451455
<td data-label="Notes">Across ${Number(impact.url_count_with_weight).toLocaleString('en-US')} URLs with weight data</td>
1446-
</tr>`
1447-
: '';
1456+
</tr>`;
1457+
}
14481458

14491459
return `
14501460
<section aria-labelledby="performance-impact-heading">
@@ -1464,7 +1474,7 @@ function renderPerformanceImpactSection(report) {
14641474
${weightRow}
14651475
</tbody>
14661476
</table>`)}
1467-
<p><small>Extra time is calculated as: for each scanned URL, <em>max(0, actual LCP &minus; ${benchmarkLcpSec}s) &times; page loads</em>. Extra data is calculated as: <em>max(0, actual page weight &minus; ${benchmarkWeightMb} MB) &times; page loads</em>. LCP and page weight are measured by Lighthouse. Wikipedia copy count uses a size of 24.05 GB per <a href="https://en.wikipedia.org/wiki/Wikipedia:Size_of_Wikipedia" target="_blank" rel="noreferrer">Wikipedia:Size of Wikipedia</a>. These are rough estimates based on a sample of the top government URLs by traffic.</small></p>
1477+
<p><small>LCP and page weight are measured by Lighthouse. Wikipedia copy count uses a size of 24.05 GB per <a href="https://en.wikipedia.org/wiki/Wikipedia:Size_of_Wikipedia" target="_blank" rel="noreferrer">Wikipedia:Size of Wikipedia</a>. These are rough estimates based on a sample of the top government URLs by traffic. Hover or focus the estimated totals for calculation details.</small></p>
14681478
</section>`;
14691479
}
14701480

tests/unit/render-pages.test.js

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2381,6 +2381,60 @@ test('renderDailyReportPage: performance impact shows GB and Wikipedia copies fo
23812381
assert.ok(html.includes('copies of Wikipedia'), 'Should show Wikipedia copy count for moderate data');
23822382
});
23832383

2384+
test('renderDailyReportPage: performance impact time value has tooltip with formula and seconds', () => {
2385+
const report = {
2386+
...minimalReport,
2387+
run_date: '2026-03-20',
2388+
performance_impact: {
2389+
benchmark_lcp_ms: 2500,
2390+
benchmark_page_weight_bytes: 1_600_000,
2391+
url_count_with_timing: 5,
2392+
url_count_with_weight: 0,
2393+
total_extra_load_time_seconds: 310_216_405,
2394+
total_extra_load_time_hours: 86171,
2395+
total_extra_bytes: 0,
2396+
total_extra_gigabytes: 0
2397+
}
2398+
};
2399+
2400+
const html = renderDailyReportPage(report);
2401+
2402+
// Duration value should be wrapped in a perf-time-trigger tooltip span
2403+
assert.ok(html.includes('class="perf-time-trigger"'), 'Duration value should use perf-time-trigger');
2404+
assert.ok(html.includes('class="perf-time-tooltip"'), 'Duration value should have a perf-time-tooltip');
2405+
assert.ok(html.includes('role="tooltip"'), 'Tooltip should have role=tooltip');
2406+
// Tooltip should contain the formula and total seconds
2407+
assert.ok(html.includes('310,216,405 seconds'), 'Tooltip should show total seconds');
2408+
assert.ok(html.includes('Extra time is calculated as'), 'Tooltip should contain the LCP formula');
2409+
assert.ok(html.includes('max(0, actual LCP'), 'Tooltip should include max(0, actual LCP formula text');
2410+
});
2411+
2412+
test('renderDailyReportPage: performance impact data value has tooltip with formula', () => {
2413+
const report = {
2414+
...minimalReport,
2415+
run_date: '2026-03-20',
2416+
performance_impact: {
2417+
benchmark_lcp_ms: 2500,
2418+
benchmark_page_weight_bytes: 1_600_000,
2419+
url_count_with_timing: 5,
2420+
url_count_with_weight: 97,
2421+
total_extra_load_time_seconds: 1000,
2422+
total_extra_load_time_hours: 0.28,
2423+
total_extra_bytes: 72_748_199_470_000,
2424+
total_extra_gigabytes: 67728.43
2425+
}
2426+
};
2427+
2428+
const html = renderDailyReportPage(report);
2429+
2430+
// Data size value should also have a tooltip
2431+
// Both time and data rows have perf-time-trigger tooltips
2432+
const triggerMatches = (html.match(/class="perf-time-trigger"/g) || []).length;
2433+
assert.ok(triggerMatches >= 2, 'Both time and data rows should have perf-time-trigger tooltips');
2434+
assert.ok(html.includes('Extra data is calculated as'), 'Data tooltip should contain the page weight formula');
2435+
assert.ok(html.includes('max(0, actual page weight'), 'Data tooltip should include max(0, actual page weight formula text');
2436+
});
2437+
23842438
test('renderDailyReportPage URL count cell has tooltip with affected hostnames', () => {
23852439
const report = {
23862440
...minimalReport,

0 commit comments

Comments
 (0)