feat: add month breakdown and session backups
Allow recurring costs and confirmations to remain unassigned when created from a purchase without a post. Add browser backup retention and restore controls, with coverage and documentation updates.
This commit is contained in:
+20
-2
@@ -54,6 +54,24 @@ describe("round trip", () => {
|
||||
});
|
||||
|
||||
describe("validation", () => {
|
||||
test("accepts an unassigned recurring cost and its unassigned charge", () => {
|
||||
const data = populated();
|
||||
const cost = addRecurringCost(data, {
|
||||
name: "Phone", folderId: null, archived: false,
|
||||
amount: { amount: 30, currency: "DKK" }, startDate: "2026-01",
|
||||
recurrence: { kind: "everyNMonths", n: 1 }, anchoring: "calendar",
|
||||
splitMode: "percent", splits: [],
|
||||
});
|
||||
data.purchases.push({
|
||||
id: "phone-charge", date: "2026-01", description: "Phone",
|
||||
total: { amount: 30, currency: "DKK" }, splitMode: "percent", splits: [],
|
||||
schedule: null, source: { recurringId: cost.id, occurrenceDate: "2026-01" },
|
||||
});
|
||||
const restored = parseDatasetJson(exportDatasetJson(data));
|
||||
expect(restored.recurring[0]!.splits).toEqual([]);
|
||||
expect(restored.purchases.at(-1)!.splits).toEqual([]);
|
||||
expect(() => monthView(restored, "2026-01")).not.toThrow();
|
||||
});
|
||||
test("accepts a purchase with no post and preserves it through export", () => {
|
||||
const data = populated();
|
||||
data.purchases[0]!.splits = [];
|
||||
@@ -553,8 +571,8 @@ describe("recurring cost validation", () => {
|
||||
).toThrow(/unknown post/);
|
||||
});
|
||||
|
||||
test("no splits at all is refused", () => {
|
||||
expect(() => parseDatasetJson(withRecurring([{ ...valid, splits: [] }])))
|
||||
test("a missing splits array is refused", () => {
|
||||
expect(() => parseDatasetJson(withRecurring([{ ...valid, splits: null }])))
|
||||
.toThrow(/no splits/);
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user