Summary
Three visual bugs in the Purchases page Savings History chart, identified in QA session 596.
QA 2.2 -- x-axis starts at purchase date, not period start
Symptom: The leftmost tick on the Savings History chart is the date of the first data point returned by the API, not the start of the selected period. Selecting "Last 30 days" with a recent first purchase shows a chart that starts mid-period, making the empty left portion invisible.
Root cause: The chart used a default category x-axis with a labels array derived from data point timestamps. Chart.js category axes position the first tick at the first label, ignoring the period start entirely.
Fix: Converted datasets to {x: timestamp_ms, y: value} objects and switched the x-axis to type:'linear' with min = period start (ms) and max = now (ms), mirroring the Home dashboard chart fix from PR #746. A tick.callback formats timestamps using the shared formatTrendAxisTick helper (extracted to frontend/src/modules/chart-utils.ts).
QA 2.3 -- Period Savings tooltip shows 4 decimal places vs Cumulative 2
Symptom: Hovering over the chart shows "Period Savings: $25.5678/mo" (4 decimals) while "Cumulative Savings: $25.57" shows 2 decimals. The KPI box above uses 2 decimals. Inconsistent presentation.
Root cause: The tooltip label callback used value.toFixed(4) for dataset index 0 (Period Savings) but value.toFixed(2) for dataset index 1 (Cumulative).
Fix: Changed toFixed(4) to toFixed(2) for Period Savings so both series and the KPI use the same 2-decimal precision.
QA 2.4/2.5 -- y-axis tick behavior changes oddly when toggling series
Symptom: Clicking the legend to toggle a dataset causes the y-axis tick step to change (e.g. 0.2 -> 0.1) and the cumulative y1-axis to show duplicate integer labels (e.g. "$0", "$0", "$1", "$1") when the domain is narrow.
Root cause: Neither y-axis had a maxTicksLimit, so Chart.js re-autoscaled freely on every toggle. The y1 tick formatter used toFixed(0) which collapses nearby float ticks to the same integer string.
Fix: Added maxTicksLimit: 6 to both y and y1 tick configs. Updated the y1 formatter to distinguish integer ticks (no decimals) from float ticks (2 decimals), preventing label collision when the autoscaled domain is narrow.
Testing
- New regression tests added in
frontend/src/__tests__/savings-history.test.ts:
- QA 2.2: asserts
x-axis type === 'linear' with numeric min equal to period start
- QA 2.3: asserts Period Savings tooltip has exactly 2 decimal places matching Cumulative
- QA 2.4: asserts both y-axes have
maxTicksLimit
- QA 2.5: asserts y1 formatter does not collapse distinct float ticks to the same integer label
All 83 tests in savings-history.test.ts pass. npx tsc --noEmit reports no errors.
Summary
Three visual bugs in the Purchases page Savings History chart, identified in QA session 596.
QA 2.2 -- x-axis starts at purchase date, not period start
Symptom: The leftmost tick on the Savings History chart is the date of the first data point returned by the API, not the start of the selected period. Selecting "Last 30 days" with a recent first purchase shows a chart that starts mid-period, making the empty left portion invisible.
Root cause: The chart used a default
categoryx-axis with alabelsarray derived from data point timestamps. Chart.js category axes position the first tick at the first label, ignoring the period start entirely.Fix: Converted datasets to
{x: timestamp_ms, y: value}objects and switched the x-axis totype:'linear'withmin= period start (ms) andmax= now (ms), mirroring the Home dashboard chart fix from PR #746. Atick.callbackformats timestamps using the sharedformatTrendAxisTickhelper (extracted tofrontend/src/modules/chart-utils.ts).QA 2.3 -- Period Savings tooltip shows 4 decimal places vs Cumulative 2
Symptom: Hovering over the chart shows "Period Savings: $25.5678/mo" (4 decimals) while "Cumulative Savings: $25.57" shows 2 decimals. The KPI box above uses 2 decimals. Inconsistent presentation.
Root cause: The tooltip
labelcallback usedvalue.toFixed(4)for dataset index 0 (Period Savings) butvalue.toFixed(2)for dataset index 1 (Cumulative).Fix: Changed
toFixed(4)totoFixed(2)for Period Savings so both series and the KPI use the same 2-decimal precision.QA 2.4/2.5 -- y-axis tick behavior changes oddly when toggling series
Symptom: Clicking the legend to toggle a dataset causes the y-axis tick step to change (e.g. 0.2 -> 0.1) and the cumulative y1-axis to show duplicate integer labels (e.g. "$0", "$0", "$1", "$1") when the domain is narrow.
Root cause: Neither y-axis had a
maxTicksLimit, so Chart.js re-autoscaled freely on every toggle. They1tick formatter usedtoFixed(0)which collapses nearby float ticks to the same integer string.Fix: Added
maxTicksLimit: 6to bothyandy1tick configs. Updated they1formatter to distinguish integer ticks (no decimals) from float ticks (2 decimals), preventing label collision when the autoscaled domain is narrow.Testing
frontend/src/__tests__/savings-history.test.ts:x-axis type === 'linear'with numericminequal to period startmaxTicksLimitAll 83 tests in
savings-history.test.tspass.npx tsc --noEmitreports no errors.