From a1d0f93f47df01b25f1309d6f089d89d9928a730 Mon Sep 17 00:00:00 2001 From: Alex Walker Date: Sat, 3 Aug 2024 16:21:56 +0100 Subject: [PATCH 1/3] Add unit tests for each goal type --- .../server/budget/goals/goalsAverage.test.ts | 89 +++++++++ .../src/server/budget/goals/goalsBy.test.ts | 134 +++++++++++++ .../budget/goals/goalsPercentage.test.ts | 180 ++++++++++++++++++ .../budget/goals/goalsRemainder.test.ts | 79 ++++++++ .../server/budget/goals/goalsSimple.test.ts | 147 ++++++++++++++ .../server/budget/goals/goalsSpend.test.ts | 105 ++++++++++ .../src/server/budget/goals/goalsWeek.test.ts | 124 ++++++++++++ upcoming-release-notes/3183.md | 6 + 8 files changed, 864 insertions(+) create mode 100644 packages/loot-core/src/server/budget/goals/goalsAverage.test.ts create mode 100644 packages/loot-core/src/server/budget/goals/goalsBy.test.ts create mode 100644 packages/loot-core/src/server/budget/goals/goalsPercentage.test.ts create mode 100644 packages/loot-core/src/server/budget/goals/goalsRemainder.test.ts create mode 100644 packages/loot-core/src/server/budget/goals/goalsSimple.test.ts create mode 100644 packages/loot-core/src/server/budget/goals/goalsSpend.test.ts create mode 100644 packages/loot-core/src/server/budget/goals/goalsWeek.test.ts create mode 100644 upcoming-release-notes/3183.md diff --git a/packages/loot-core/src/server/budget/goals/goalsAverage.test.ts b/packages/loot-core/src/server/budget/goals/goalsAverage.test.ts new file mode 100644 index 00000000000..07285d34c16 --- /dev/null +++ b/packages/loot-core/src/server/budget/goals/goalsAverage.test.ts @@ -0,0 +1,89 @@ +import * as actions from '../actions'; + +import { goalsAverage } from './goalsAverage'; + +jest.mock('../actions'); + +describe('goalsAverage', () => { + const mockGetSheetValue = actions.getSheetValue as jest.Mock; + + beforeEach(() => { + jest.clearAllMocks(); + }); + + it('should calculate the amount to budget based on the average of only one previous month of spending', async () => { + // Given + const template = { amount: 1 }; + const month = '2024-07'; + const category = { id: 1 }; + const errors: string[] = []; + const to_budget = 0; + + mockGetSheetValue.mockResolvedValueOnce(200); + + // When + const result = await goalsAverage( + template, + month, + category, + errors, + to_budget, + ); + + // Then + expect(result.to_budget).toBe(-200); + expect(result.errors).toHaveLength(0); + }); + + it('should calculate the amount to budget based on the average of multiple previous months of spending', async () => { + // Given + const template = { amount: 4 }; + const month = '2024-08'; + const category = { id: 1 }; + const errors: string[] = []; + const to_budget = 0; + + mockGetSheetValue + .mockResolvedValueOnce(200) + .mockResolvedValueOnce(300) + .mockResolvedValueOnce(100) + .mockResolvedValueOnce(400); + + // When + const result = await goalsAverage( + template, + month, + category, + errors, + to_budget, + ); + + // Then + expect(result.to_budget).toBe(-250); + expect(result.errors).toHaveLength(0); + }); + + it('should return error when template amount passed in is <= 0', async () => { + // Given + const template = { amount: 0 }; + const month = '2024-08'; + const category = { id: 1 }; + const errors: string[] = []; + const to_budget = 1000; + + // When + const result = await goalsAverage( + template, + month, + category, + errors, + to_budget, + ); + + // Then + expect(result.to_budget).toBe(1000); + expect(result.errors).toStrictEqual([ + 'Number of months to average is not valid', + ]); + }); +}); diff --git a/packages/loot-core/src/server/budget/goals/goalsBy.test.ts b/packages/loot-core/src/server/budget/goals/goalsBy.test.ts new file mode 100644 index 00000000000..cafec5ae716 --- /dev/null +++ b/packages/loot-core/src/server/budget/goals/goalsBy.test.ts @@ -0,0 +1,134 @@ +import * as actions from '../actions'; + +import { goalsBy } from './goalsBy'; + +jest.mock('../actions'); + +describe('goalsBy', () => { + const mockIsReflectBudget = actions.isReflectBudget as jest.Mock; + + beforeEach(() => { + jest.clearAllMocks(); + }); + + it('should return correct budget amount with target in the future and no current balance', async () => { + // Given + const template = { amount: 100, month: '2024-12' }; + const current_month = '2024-08'; + const last_month_balance = 0; + const to_budget = 0; + const errors: string[] = []; + const template_lines = [template]; + const l = 0; + const remainder = 0; + mockIsReflectBudget.mockReturnValue(false); + + // When + const result = await goalsBy( + template_lines, + current_month, + template, + l, + remainder, + last_month_balance, + to_budget, + errors, + ); + + // Then + expect(result.to_budget).toBe(2000); + expect(result.errors).toHaveLength(0); + expect(result.remainder).toBe(0); + }); + + it('should return correct budget amount with target in the future and existing balance towards goal', async () => { + // Given + const template = { amount: 100, month: '2024-12' }; + const current_month = '2024-08'; + const last_month_balance = 5000; + const to_budget = 0; + const errors: string[] = []; + const template_lines = [template]; + const l = 0; + const remainder = 0; + mockIsReflectBudget.mockReturnValue(false); + + // When + const result = await goalsBy( + template_lines, + current_month, + template, + l, + remainder, + last_month_balance, + to_budget, + errors, + ); + + // Then + expect(result.to_budget).toBe(1000); + expect(result.errors).toHaveLength(0); + expect(result.remainder).toBe(0); + }); + + it('should return correct budget amount when target balance met early', async () => { + // Given + const template = { amount: 100, month: '2024-12' }; + const current_month = '2024-08'; + const last_month_balance = 10000; + const to_budget = 0; + const errors: string[] = []; + const template_lines = [template]; + const l = 0; + const remainder = 0; + mockIsReflectBudget.mockReturnValue(false); + + // When + const result = await goalsBy( + template_lines, + current_month, + template, + l, + remainder, + last_month_balance, + to_budget, + errors, + ); + + // Then + expect(result.to_budget).toBe(0); + expect(result.errors).toHaveLength(0); + expect(result.remainder).toBe(0); + }); + + it('should return error when budget is a reflect budget', async () => { + // Given + const template = { amount: -100, month: '2024-08', repeat: 1 }; + const current_month = '2024-08'; + const last_month_balance = 0; + const to_budget = 0; + const errors: string[] = []; + const template_lines = [template]; + const l = 0; + const remainder = 0; + mockIsReflectBudget.mockReturnValue(true); + + // When + const result = await goalsBy( + template_lines, + current_month, + template, + l, + remainder, + last_month_balance, + to_budget, + errors, + ); + + // Then + expect(result.to_budget).toBe(0); + expect(result.errors).toStrictEqual([ + 'by templates are not supported in Report budgets', + ]); + }); +}); diff --git a/packages/loot-core/src/server/budget/goals/goalsPercentage.test.ts b/packages/loot-core/src/server/budget/goals/goalsPercentage.test.ts new file mode 100644 index 00000000000..4dca6ac3706 --- /dev/null +++ b/packages/loot-core/src/server/budget/goals/goalsPercentage.test.ts @@ -0,0 +1,180 @@ +import * as db from '../../db'; +import * as actions from '../actions'; + +import { goalsPercentage } from './goalsPercentage'; + +jest.mock('../actions'); +jest.mock('../../db'); + +describe('goalsPercentage', () => { + const mockGetSheetValue = actions.getSheetValue as jest.Mock; + const mockGetCategories = db.getCategories as jest.Mock; + + beforeEach(() => { + jest.clearAllMocks(); + }); + + it('should calculate the budget based on a percentage of all income for the current month', async () => { + // Given + const template = { percent: 10, category: 'all income' }; + const month = '2024-08'; + const available_start = 0; + const sheetName = '2024-08'; + const to_budget = 0; + const errors: string[] = []; + + mockGetSheetValue.mockResolvedValueOnce(1000); + + // When + const result = await goalsPercentage( + template, + month, + available_start, + sheetName, + to_budget, + errors, + ); + + // Then + expect(result.to_budget).toBe(100); + expect(result.errors).toHaveLength(0); + }); + + it('should calculate the budget based on a percentage of all income for the previous month', async () => { + // Given + const template = { percent: 10, category: 'all income', previous: true }; + const month = '2024-08'; + const available_start = 0; + const sheetName = '2024-08'; + const to_budget = 0; + const errors: string[] = []; + + mockGetSheetValue.mockResolvedValueOnce(1000); + + // When + const result = await goalsPercentage( + template, + month, + available_start, + sheetName, + to_budget, + errors, + ); + + // Then + expect(result.to_budget).toBe(100); + expect(result.errors).toHaveLength(0); + }); + + it('should calculate the budget based on a percentage of available funds', async () => { + // Given + const template = { percent: 10, category: 'available funds' }; + const month = '2024-08'; + const available_start = 1000; + const sheetName = '2024-08'; + const to_budget = 0; + const errors: string[] = []; + + // When + const result = await goalsPercentage( + template, + month, + available_start, + sheetName, + to_budget, + errors, + ); + + // Then + expect(result.to_budget).toBe(100); + expect(result.errors).toHaveLength(0); + }); + + it('should calculate the budget based on a percentage of a specific income category for the current month', async () => { + // Given + const template = { percent: 10, category: 'Salary' }; + const month = '2024-08'; + const available_start = 0; + const sheetName = '2024-08'; + const to_budget = 0; + const errors: string[] = []; + + mockGetCategories.mockResolvedValueOnce([ + { id: 1, name: 'Salary', is_income: true }, + ]); + mockGetSheetValue.mockResolvedValueOnce(1000); + + // When + const result = await goalsPercentage( + template, + month, + available_start, + sheetName, + to_budget, + errors, + ); + + // Then + expect(result.to_budget).toBe(100); + expect(result.errors).toHaveLength(0); + }); + + it('should calculate the budget based on a percentage of a specific income category for the previous month', async () => { + // Given + const template = { percent: 10, category: 'Salary', previous: true }; + const month = '2024-08'; + const available_start = 0; + const sheetName = '2024-08'; + const to_budget = 0; + const errors: string[] = []; + + mockGetCategories.mockResolvedValueOnce([ + { id: 1, name: 'Salary', is_income: true }, + ]); + mockGetSheetValue.mockResolvedValueOnce(1000); + + // When + const result = await goalsPercentage( + template, + month, + available_start, + sheetName, + to_budget, + errors, + ); + + // Then + expect(result.to_budget).toBe(100); + expect(result.errors).toHaveLength(0); + }); + + it('should return an error if the specified income category does not exist', async () => { + // Given + const template = { percent: 10, category: 'NonExistentCategory' }; + const month = '2024-08'; + const available_start = 0; + const sheetName = '2024-08'; + const to_budget = 0; + const errors: string[] = []; + + mockGetCategories.mockResolvedValueOnce([ + { id: 1, name: 'Salary', is_income: true }, + ]); + + // When + const result = await goalsPercentage( + template, + month, + available_start, + sheetName, + to_budget, + errors, + ); + + // Then + expect(result.to_budget).toBe(0); + expect(result.errors).toStrictEqual([ + 'Could not find category “NonExistentCategory”', + ]); + }); +}); diff --git a/packages/loot-core/src/server/budget/goals/goalsRemainder.test.ts b/packages/loot-core/src/server/budget/goals/goalsRemainder.test.ts new file mode 100644 index 00000000000..b68b9897d96 --- /dev/null +++ b/packages/loot-core/src/server/budget/goals/goalsRemainder.test.ts @@ -0,0 +1,79 @@ +import { goalsRemainder } from './goalsRemainder'; + +describe('goalsRemainder', () => { + it('should calculate the budget correctly when remainder_scale is greater than 0', async () => { + // Given + const template = { weight: 100 }; + const budgetAvailable = 1000; + const remainder_scale = 0.5; + const to_budget = 0; + + // When + const result = await goalsRemainder( + template, + budgetAvailable, + remainder_scale, + to_budget, + ); + + // Then + expect(result.to_budget).toBe(50); + }); + + it('should calculate the budget correctly when remainder_scale is 0', async () => { + // Given + const template = { weight: 100 }; + const budgetAvailable = 1000; + const remainder_scale = 0; + const to_budget = 0; + + // When + const result = await goalsRemainder( + template, + budgetAvailable, + remainder_scale, + to_budget, + ); + + // Then + expect(result.to_budget).toBe(100); + }); + + it('should calculate the budget correctly when when the calculated budget exceeds the budget available', async () => { + // Given + const template = { weight: 1000 }; + const budgetAvailable = 500; + const remainder_scale = 1; + const to_budget = 0; + + // When + const result = await goalsRemainder( + template, + budgetAvailable, + remainder_scale, + to_budget, + ); + + // Then + expect(result.to_budget).toBe(500); + }); + + it('should calculate the budget correctly when there is 1 minor unit leftover from rounding', async () => { + // Given + const template = { weight: 499 }; + const budgetAvailable = 500; + const remainder_scale = 1; + const to_budget = 0; + + // When + const result = await goalsRemainder( + template, + budgetAvailable, + remainder_scale, + to_budget, + ); + + // Then + expect(result.to_budget).toBe(500); + }); +}); diff --git a/packages/loot-core/src/server/budget/goals/goalsSimple.test.ts b/packages/loot-core/src/server/budget/goals/goalsSimple.test.ts new file mode 100644 index 00000000000..fd7f2ac2ed1 --- /dev/null +++ b/packages/loot-core/src/server/budget/goals/goalsSimple.test.ts @@ -0,0 +1,147 @@ +import { goalsSimple } from './goalsSimple'; + +describe('goalsSimple', () => { + it('should return correct budget amount when limit set and no balance left from previous months', async () => { + // Given + const template = { limit: { amount: 100, hold: false } }; + const limitCheck = false; + const errors: string[] = []; + const limit = 0; + const hold = false; + const to_budget = 0; + const last_month_balance = 0; + + // When + const result = await goalsSimple( + template, + limitCheck, + errors, + limit, + hold, + to_budget, + last_month_balance, + ); + + // Then + expect(result.to_budget).toBe(10000); + expect(result.errors).toHaveLength(0); + expect(result.limitCheck).toBe(true); + expect(result.limit).toBe(10000); + expect(result.hold).toBe(false); + }); + + it('should return correct budget amount when limit set and balance from previous month left over', async () => { + // Given + const template = { limit: { amount: 100, hold: false } }; + const limitCheck = false; + const errors: string[] = []; + const limit = 0; + const hold = false; + const to_budget = 0; + const last_month_balance = 2000; + + // When + const result = await goalsSimple( + template, + limitCheck, + errors, + limit, + hold, + to_budget, + last_month_balance, + ); + + // Then + expect(result.to_budget).toBe(8000); + expect(result.errors).toHaveLength(0); + expect(result.limitCheck).toBe(true); + expect(result.limit).toBe(10000); + }); + + it('should return correct budget amount when assigned from previous month is greater than the limit set', async () => { + // Given + const template = { limit: { amount: 100, hold: false } }; + const limitCheck = false; + const errors: string[] = []; + const limit = 0; + const hold = false; + const to_budget = 0; + const last_month_balance = 20000; + + // When + const result = await goalsSimple( + template, + limitCheck, + errors, + limit, + hold, + to_budget, + last_month_balance, + ); + + // Then + expect(result.to_budget).toBe(-10000); + expect(result.errors).toHaveLength(0); + expect(result.limitCheck).toBe(true); + expect(result.limit).toBe(10000); + expect(result.hold).toBe(false); + }); + + it('should return correct budget amount when both limit and monthly limit set', async () => { + // Given + const template = { monthly: 50, limit: { amount: 100, hold: false } }; + const limitCheck = false; + const errors: string[] = []; + const limit = 0; + const hold = false; + const to_budget = 0; + const last_month_balance = 0; + + // When + const result = await goalsSimple( + template, + limitCheck, + errors, + limit, + hold, + to_budget, + last_month_balance, + ); + + // Then + expect(result.to_budget).toBe(5000); + expect(result.errors).toHaveLength(0); + expect(result.limitCheck).toBe(true); + expect(result.limit).toBe(10000); + expect(result.hold).toBe(false); + }); + + it('should fail when multiple limit checks exist', async () => { + // Given + const template = { limit: { amount: 100, hold: true } }; + const limitCheck = true; + const errors: string[] = []; + const limit = 0; + const hold = true; + const to_budget = 0; + const last_month_balance = 200; + + // When + const result = await goalsSimple( + template, + limitCheck, + errors, + limit, + hold, + to_budget, + last_month_balance, + ); + + // Then + expect(result.to_budget).toBe(0); + expect(result.errors).toStrictEqual(['More than one “up to” limit found.']); + expect(result.limitCheck).toBe(true); + expect(result.limit).toBe(0); + expect(result.hold).toBe(true); + }); +}); diff --git a/packages/loot-core/src/server/budget/goals/goalsSpend.test.ts b/packages/loot-core/src/server/budget/goals/goalsSpend.test.ts new file mode 100644 index 00000000000..0b69e800e94 --- /dev/null +++ b/packages/loot-core/src/server/budget/goals/goalsSpend.test.ts @@ -0,0 +1,105 @@ +import { getSheetValue } from '../actions'; + +import { goalsSpend } from './goalsSpend'; + +jest.mock('../actions'); + +describe('goalsSpend', () => { + const mockGetSheetValue = getSheetValue as jest.Mock; + + beforeEach(() => { + jest.clearAllMocks(); + }); + + it('should return correct budget amount for range when no spending has happened', async () => { + // Given + const template = { amount: 60, from: '2024-01', month: '2024-12' }; + const last_month_balance = 0; + const current_month = '2024-08-01'; + const to_budget = 0; + const errors: string[] = []; + const category = { id: 'uuid' }; + + mockGetSheetValue + .mockResolvedValueOnce(0) + .mockResolvedValueOnce(500) + .mockResolvedValueOnce(500) + .mockResolvedValueOnce(500) + .mockResolvedValueOnce(500) + .mockResolvedValueOnce(500) + .mockResolvedValueOnce(500) + .mockResolvedValueOnce(500); + + // When + const result = await goalsSpend( + template, + last_month_balance, + current_month, + to_budget, + errors, + category, + ); + + // Then + expect(result.to_budget).toBe(500); + expect(result.errors).toHaveLength(0); + }); + + it('should return correct budget amount for range when spending has happened', async () => { + // Given + const template = { amount: 60, from: '2024-01', month: '2024-12' }; + const last_month_balance = 0; + const current_month = '2024-08-01'; + const to_budget = 0; + const errors: string[] = []; + const category = { id: 'uuid' }; + + mockGetSheetValue + .mockResolvedValueOnce(500) + .mockResolvedValueOnce(500) + .mockResolvedValueOnce(500) + .mockResolvedValueOnce(500) + .mockResolvedValueOnce(500) + .mockResolvedValueOnce(500) + .mockResolvedValueOnce(500) + .mockResolvedValueOnce(500); + + // When + const result = await goalsSpend( + template, + last_month_balance, + current_month, + to_budget, + errors, + category, + ); + + // Then + expect(result.to_budget).toBe(600); + expect(result.errors).toHaveLength(0); + }); + + it('should return error when range is in the past', async () => { + // Given + const template = { amount: 60, from: '2024-01', month: '2024-05' }; + const last_month_balance = 0; + const current_month = '2024-08-01'; + const to_budget = 0; + const errors: string[] = []; + const category = { id: 'uuid' }; + + // When + const result = await goalsSpend( + template, + last_month_balance, + current_month, + to_budget, + errors, + category, + ); + + // Then + expect(result.to_budget).toBe(0); + expect(result.errors).toStrictEqual(['2024-05 is in the past.']); + }); +}); diff --git a/packages/loot-core/src/server/budget/goals/goalsWeek.test.ts b/packages/loot-core/src/server/budget/goals/goalsWeek.test.ts new file mode 100644 index 00000000000..c1351ca8cb7 --- /dev/null +++ b/packages/loot-core/src/server/budget/goals/goalsWeek.test.ts @@ -0,0 +1,124 @@ +import { goalsWeek } from './goalsWeek'; + +describe('goalsWeek', () => { + it('should return the correct budget amount for a weekly repeat', async () => { + // Given + const template = { amount: 100, starting: '2024-08-01', weeks: 1 }; + const limit = 0; + const limitCheck = false; + const hold = false; + const current_month = '2024-08-01'; + const to_budget = 0; + const errors: string[] = []; + + // When + const result = await goalsWeek( + template, + limit, + limitCheck, + hold, + current_month, + to_budget, + errors, + ); + + // Then + expect(result.to_budget).toBe(50000); + expect(result.errors).toHaveLength(0); + expect(result.limit).toBe(0); + expect(result.limitCheck).toBe(false); + expect(result.hold).toBe(false); + }); + + it('should return the correct budget amount for a bi-weekly repeat', async () => { + // Given + const template = { amount: '100', starting: '2024-08-01', weeks: 2 }; + const limit = 0; + const limitCheck = false; + const hold = false; + const current_month = '2024-08-01'; + const to_budget = 0; + const errors: string[] = []; + + // When + const result = await goalsWeek( + template, + limit, + limitCheck, + hold, + current_month, + to_budget, + errors, + ); + + // Then + expect(result.to_budget).toBe(30000); + expect(result.errors).toHaveLength(0); + expect(result.limit).toBe(0); + expect(result.limitCheck).toBe(false); + expect(result.hold).toBe(false); + }); + + it('should return the correct budget when limit set', async () => { + // Given + const template = { amount: 100, starting: '2024-08-01', weeks: 1 }; + const limit = 20000; + const limitCheck = false; + const hold = false; + const current_month = '2024-08-01'; + const to_budget = 0; + const errors: string[] = []; + + // When + const result = await goalsWeek( + template, + limit, + limitCheck, + hold, + current_month, + to_budget, + errors, + ); + + // Then + expect(result.to_budget).toBe(50000); + expect(result.errors).toHaveLength(0); + expect(result.limit).toBe(20000); + expect(result.limitCheck).toBe(false); + expect(result.hold).toBe(false); + }); + + it('should return error when multiple limit checks exist', async () => { + // Given + const template = { + amount: '100', + starting: '2024-08-01', + weeks: 1, + limit: { amount: 100, hold: true }, + }; + const limit = 1000; + const limitCheck = true; + const hold = false; + const current_month = '2024-08-01'; + const to_budget = 0; + const errors: string[] = []; + + // When + const result = await goalsWeek( + template, + limit, + limitCheck, + hold, + current_month, + to_budget, + errors, + ); + + // Then + expect(result.to_budget).toBe(0); + expect(result.errors).toStrictEqual(['More than one “up to” limit found.']); + expect(result.limit).toBe(1000); + expect(result.limitCheck).toBe(true); + expect(result.hold).toBe(false); + }); +}); diff --git a/upcoming-release-notes/3183.md b/upcoming-release-notes/3183.md new file mode 100644 index 00000000000..37bff0702e9 --- /dev/null +++ b/upcoming-release-notes/3183.md @@ -0,0 +1,6 @@ +--- +category: Maintenance +authors: [ ACWalker ] +--- + +Add unit tests for all the goal template types except for schedule. From 052b77c3d888778900537c171afa0fa55ce18d6b Mon Sep 17 00:00:00 2001 From: alex Date: Sun, 4 Aug 2024 21:50:05 +0100 Subject: [PATCH 2/3] Add test for goals schedule template --- .../server/budget/goals/goalsSchedule.test.ts | 85 +++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 packages/loot-core/src/server/budget/goals/goalsSchedule.test.ts diff --git a/packages/loot-core/src/server/budget/goals/goalsSchedule.test.ts b/packages/loot-core/src/server/budget/goals/goalsSchedule.test.ts new file mode 100644 index 00000000000..abfa9c035d8 --- /dev/null +++ b/packages/loot-core/src/server/budget/goals/goalsSchedule.test.ts @@ -0,0 +1,85 @@ +import * as db from '../../db'; +import { getRuleForSchedule } from '../../schedules/app'; +import { isReflectBudget } from '../actions'; + +import { goalsSchedule } from './goalsSchedule'; + +jest.mock('../../db'); +jest.mock('../actions'); +jest.mock('../../schedules/app', () => { + const actualModule = jest.requireActual('../../schedules/app'); + return { + ...actualModule, + getRuleForSchedule: jest.fn(), + }; +}); + +describe('goalsSchedule', () => { + beforeEach(() => { + jest.clearAllMocks(); + }); + + it('should return correct budget when recurring schedule set', async () => { + // Given + const scheduleFlag = false; + const template_lines = [{ type: 'schedule', name: 'Test Schedule' }]; + const current_month = '2024-08-01'; + const balance = 0; + const remainder = 0; + const last_month_balance = 0; + const to_budget = 0; + const errors: string[] = []; + const category = { id: 1, name: 'Test Category' }; + + (db.first as jest.Mock).mockResolvedValue({ id: 1, completed: 0 }); + (getRuleForSchedule as jest.Mock).mockResolvedValue({ + serialize: () => ({ + conditions: [ + { + op: 'is', + field: 'date', + value: { + start: '2024-08-01', + interval: 1, + frequency: 'monthly', + patterns: [], + skipWeekend: false, + weekendSolveMode: 'before', + endMode: 'never', + endOccurrences: 1, + endDate: '2024-08-04', + }, + type: 'date', + }, + { + op: 'is', + field: 'amount', + value: -10000, + type: 'number', + }, + ], + }), + execActions: () => ({ amount: -10000, subtransactions: [] }), + }); + (isReflectBudget as jest.Mock).mockReturnValue(false); + + // When + const result = await goalsSchedule( + scheduleFlag, + template_lines, + current_month, + balance, + remainder, + last_month_balance, + to_budget, + errors, + category, + ); + + // Then + expect(result.to_budget).toBe(10000); + expect(result.errors).toHaveLength(0); + expect(result.remainder).toBe(0); + expect(result.scheduleFlag).toBe(true); + }); +}); From c761cd4533e695c2d300ca9779e6d78977df7c50 Mon Sep 17 00:00:00 2001 From: alex Date: Sun, 4 Aug 2024 21:58:36 +0100 Subject: [PATCH 3/3] Update release notes --- upcoming-release-notes/3183.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/upcoming-release-notes/3183.md b/upcoming-release-notes/3183.md index 37bff0702e9..852936ebd44 100644 --- a/upcoming-release-notes/3183.md +++ b/upcoming-release-notes/3183.md @@ -3,4 +3,4 @@ category: Maintenance authors: [ ACWalker ] --- -Add unit tests for all the goal template types except for schedule. +Add unit tests for the existing goal template types.