Collapse the three Compare tabs (MoM / YoY / Budget) into two modes. The
new "Actual vs actual" mode exposes an explicit reference-month dropdown
in the header (defaults to the previous month, wraps around January) and
a MoM/YoY sub-toggle. The chart is rewritten to a grouped side-by-side
BarChart with two bars per category (reference period vs comparison
period) so both values are visible at a glance instead of just the
delta. The URL PeriodSelector stays in sync with the reference month.
- useCompare: state splits into { mode: "actual"|"budget", subMode:
"mom"|"yoy", year, month }. Pure helpers previousMonth(),
defaultReferencePeriod(), comparisonMeta() extracted for tests
- CompareModeTabs: 2 modes instead of 3
- New CompareSubModeToggle and CompareReferenceMonthPicker components
- ComparePeriodChart: grouped bars via two <Bar dataKey="..."/> on a
vertical BarChart
- i18n: modeActual / subModeMoM / subModeYoY / referenceMonth (FR+EN),
retire modeMoM / modeYoY
- 9 new vitest cases covering the pure helpers (January wrap-around for
both MoM and YoY, default reference period, month/year arithmetic)
Closes #96
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
47 lines
1.8 KiB
TypeScript
47 lines
1.8 KiB
TypeScript
import { describe, it, expect } from "vitest";
|
|
import { previousMonth, defaultReferencePeriod, comparisonMeta } from "./useCompare";
|
|
|
|
describe("useCompare helpers", () => {
|
|
describe("previousMonth", () => {
|
|
it("goes back one month within the same year", () => {
|
|
expect(previousMonth(2026, 3)).toEqual({ year: 2026, month: 2 });
|
|
expect(previousMonth(2026, 12)).toEqual({ year: 2026, month: 11 });
|
|
});
|
|
|
|
it("wraps around January to December of previous year", () => {
|
|
expect(previousMonth(2026, 1)).toEqual({ year: 2025, month: 12 });
|
|
});
|
|
});
|
|
|
|
describe("defaultReferencePeriod", () => {
|
|
it("returns the month before the given date", () => {
|
|
expect(defaultReferencePeriod(new Date(2026, 3, 15))).toEqual({ year: 2026, month: 3 });
|
|
});
|
|
|
|
it("wraps around when today is in January", () => {
|
|
expect(defaultReferencePeriod(new Date(2026, 0, 10))).toEqual({ year: 2025, month: 12 });
|
|
});
|
|
|
|
it("handles the last day of a month", () => {
|
|
expect(defaultReferencePeriod(new Date(2026, 6, 31))).toEqual({ year: 2026, month: 6 });
|
|
});
|
|
});
|
|
|
|
describe("comparisonMeta", () => {
|
|
it("MoM returns the previous month", () => {
|
|
expect(comparisonMeta("mom", 2026, 3)).toEqual({ previousYear: 2026, previousMonth: 2 });
|
|
});
|
|
|
|
it("MoM wraps around January", () => {
|
|
expect(comparisonMeta("mom", 2026, 1)).toEqual({ previousYear: 2025, previousMonth: 12 });
|
|
});
|
|
|
|
it("YoY returns the same month in the previous year", () => {
|
|
expect(comparisonMeta("yoy", 2026, 3)).toEqual({ previousYear: 2025, previousMonth: 3 });
|
|
});
|
|
|
|
it("YoY for January stays on January of previous year", () => {
|
|
expect(comparisonMeta("yoy", 2026, 1)).toEqual({ previousYear: 2025, previousMonth: 1 });
|
|
});
|
|
});
|
|
});
|