diff options
| author | Joe Carstairs <me@joeac.net> | 2024-09-17 13:20:04 +0100 |
|---|---|---|
| committer | Joe Carstairs <me@joeac.net> | 2024-09-17 13:20:04 +0100 |
| commit | cd269b3540fb5e3a988c1b59d3763db360b1fb34 (patch) | |
| tree | a728403d8d5708ad29eeed2b391706b09a93fe4c /gui/src/types/BalanceToBudgetRatio.spec.ts | |
| parent | f0e3e0cfb183253e03b1a61ddecb7b9330d47fdb (diff) | |
many, many changes
Diffstat (limited to 'gui/src/types/BalanceToBudgetRatio.spec.ts')
| -rw-r--r-- | gui/src/types/BalanceToBudgetRatio.spec.ts | 307 |
1 files changed, 307 insertions, 0 deletions
diff --git a/gui/src/types/BalanceToBudgetRatio.spec.ts b/gui/src/types/BalanceToBudgetRatio.spec.ts new file mode 100644 index 0000000..3a956ea --- /dev/null +++ b/gui/src/types/BalanceToBudgetRatio.spec.ts @@ -0,0 +1,307 @@ +import { describe, expect, it } from "vitest"; +import { BalanceToBudgetRatio } from "./balanceToBudgetRatio"; +import { Gbp } from "./currency/gbp"; + +describe("balanceToBudgetRatio", () => { + it("new() returns null when budget is null", () => { + const result = BalanceToBudgetRatio.new(new Gbp(1, 0, 1), null); + expect(result).toBeNull(); + }); + + it("toString() rounds to 2 decimal places", () => { + const mockCurrencyPi = { valueOf: () => Math.PI }; + const mockCurrencyUnit = { valueOf: () => 1 }; + const sut = BalanceToBudgetRatio.new(mockCurrencyPi, { + quantity: mockCurrencyUnit, + period: 42, + }); + + const result = sut?.toString(); + + expect(result).toBe("3.14"); + }); + + it("new() sets normalisedRatio to 1 when balance and budget are equal and positive", () => { + const twoFifty = new Gbp(2, 50, 1); + const result = BalanceToBudgetRatio.new(twoFifty, { + quantity: twoFifty, + period: 42, + }); + expect(result?.normalisedRatio).toBeCloseTo(1.0); + }); + + it("new() sets normalisedRatio to 2 when balance is twice budget", () => { + const twoFifty = new Gbp(2, 50, 1); + const oneTwentyFive = new Gbp(1, 25, 1); + const result = BalanceToBudgetRatio.new(twoFifty, { + quantity: oneTwentyFive, + period: 42, + }); + expect(result?.normalisedRatio).toBeCloseTo(2.0); + }); + + it("new() sets normalisedRatio to -2 when a negative balance is -1 * twice budget", () => { + const minusTwoFifty = new Gbp(2, 50, -1); + const oneTwentyFive = new Gbp(1, 25, 1); + const result = BalanceToBudgetRatio.new(minusTwoFifty, { + quantity: oneTwentyFive, + period: 42, + }); + expect(result?.normalisedRatio).toBeCloseTo(-2.0); + }); + + it("new() sets normalisedRatio to -0.5 when balance is -1 * half a negative budget", () => { + const oneTwentyFive = new Gbp(1, 25, 1); + const minusTwoFifty = new Gbp(2, 50, -1); + const result = BalanceToBudgetRatio.new(oneTwentyFive, { + quantity: minusTwoFifty, + period: 42, + }); + expect(result?.normalisedRatio).toBeCloseTo(-0.5); + }); + + it("new() sets normalisedRatio to 1 when balance and budget are equal and negative", () => { + const minusTwoFifty = new Gbp(2, 50, -1); + const result = BalanceToBudgetRatio.new(minusTwoFifty, { + quantity: minusTwoFifty, + period: 42, + }); + expect(result?.normalisedRatio).toBeCloseTo(1.0); + }); + + it('new() sets recommended action to "arrears" when ratio is less than 0', () => { + const oneTwentyFive = new Gbp(1, 25, 1); + const minusTwoFifty = new Gbp(2, 50, -1); + + const result = BalanceToBudgetRatio.new(oneTwentyFive, { + quantity: minusTwoFifty, + period: 42, + }); + + expect(result?.recommendedAction).toBe("arrears"); + }); + + it('new() sets recommended action to "save" when ratio is between 0 and 1', () => { + const oneTwentyFive = new Gbp(1, 25, 1); + const twoFifty = new Gbp(2, 50, 1); + + const result = BalanceToBudgetRatio.new(oneTwentyFive, { + quantity: twoFifty, + period: 42, + }); + + expect(result?.recommendedAction).toBe("save"); + }); + + it('new() sets recommended action to "spend" when ratio is larger than 1', () => { + const oneTwentyFive = new Gbp(1, 25, 1); + const twoFifty = new Gbp(2, 50, 1); + + const result = BalanceToBudgetRatio.new(twoFifty, { + quantity: oneTwentyFive, + period: 42, + }); + + expect(result?.recommendedAction).toBe("spend"); + }); + + it("normalises to a factor of 2 when all ratios are positive", () => { + const oneTwentyFive = new Gbp(1, 25, 1); + const twoFifty = new Gbp(2, 50, 1); + const twoOverOne = BalanceToBudgetRatio.new(twoFifty, { + quantity: oneTwentyFive, + period: 42, + }); + const twoOverTwo = BalanceToBudgetRatio.new(twoFifty, { + quantity: twoFifty, + period: 42, + }); + const oneOverOne = BalanceToBudgetRatio.new(oneTwentyFive, { + quantity: oneTwentyFive, + period: 42, + }); + const oneOverTwo = BalanceToBudgetRatio.new(oneTwentyFive, { + quantity: twoFifty, + period: 42, + }); + + const normaliser = BalanceToBudgetRatio.makeNormaliser( + twoOverOne, + twoOverTwo, + oneOverOne, + oneOverTwo, + ); + + expect(normaliser(twoOverOne).normalisedRatio).toBeCloseTo(1.0); + expect(normaliser(twoOverTwo).normalisedRatio).toBeCloseTo(0.5); + expect(normaliser(oneOverOne).normalisedRatio).toBeCloseTo(0.5); + expect(normaliser(oneOverTwo).normalisedRatio).toBeCloseTo(0.25); + }); + + it("normalises to a factor of 2 when all ratios are negative", () => { + const oneTwentyFive = new Gbp(1, 25, 1); + const twoFifty = new Gbp(2, 50, 1); + const minusOneTwentyFive = new Gbp(1, 25, -1); + const minusTwoFifty = new Gbp(2, 50, -1); + const minusTwoOverOne = BalanceToBudgetRatio.new(minusTwoFifty, { + quantity: oneTwentyFive, + period: 42, + }); + const minusTwoOverTwo = BalanceToBudgetRatio.new(minusTwoFifty, { + quantity: twoFifty, + period: 42, + }); + const minusOneOverOne = BalanceToBudgetRatio.new(minusOneTwentyFive, { + quantity: oneTwentyFive, + period: 42, + }); + const minusOneOverTwo = BalanceToBudgetRatio.new(minusOneTwentyFive, { + quantity: twoFifty, + period: 42, + }); + + const normaliser = BalanceToBudgetRatio.makeNormaliser( + minusTwoOverOne, + minusTwoOverTwo, + minusOneOverOne, + minusOneOverTwo, + ); + + expect(normaliser(minusTwoOverOne).normalisedRatio).toBeCloseTo(-1.0); + expect(normaliser(minusTwoOverTwo).normalisedRatio).toBeCloseTo(-0.5); + expect(normaliser(minusOneOverOne).normalisedRatio).toBeCloseTo(-0.5); + expect(normaliser(minusOneOverTwo).normalisedRatio).toBeCloseTo(-0.25); + }); + + it("normalises to a factor of 2 when ratios are a mix of positive and negative", () => { + const oneTwentyFive = new Gbp(1, 25, 1); + const twoFifty = new Gbp(2, 50, 1); + const minusOneTwentyFive = new Gbp(1, 25, -1); + const minusTwoFifty = new Gbp(2, 50, -1); + const twoOverOne = BalanceToBudgetRatio.new(twoFifty, { + quantity: oneTwentyFive, + period: 42, + }); + const twoOverTwo = BalanceToBudgetRatio.new(twoFifty, { + quantity: twoFifty, + period: 42, + }); + const oneOverOne = BalanceToBudgetRatio.new(oneTwentyFive, { + quantity: oneTwentyFive, + period: 42, + }); + const oneOverTwo = BalanceToBudgetRatio.new(oneTwentyFive, { + quantity: twoFifty, + period: 42, + }); + const minusTwoOverOne = BalanceToBudgetRatio.new(minusTwoFifty, { + quantity: oneTwentyFive, + period: 42, + }); + const minusTwoOverTwo = BalanceToBudgetRatio.new(minusTwoFifty, { + quantity: twoFifty, + period: 42, + }); + const minusOneOverOne = BalanceToBudgetRatio.new(minusOneTwentyFive, { + quantity: oneTwentyFive, + period: 42, + }); + const minusOneOverTwo = BalanceToBudgetRatio.new(minusOneTwentyFive, { + quantity: twoFifty, + period: 42, + }); + + const normaliser = BalanceToBudgetRatio.makeNormaliser( + twoOverOne, + twoOverTwo, + oneOverOne, + oneOverTwo, + minusTwoOverOne, + minusTwoOverTwo, + minusOneOverOne, + minusOneOverTwo, + ); + + expect(normaliser(twoOverOne).normalisedRatio).toBeCloseTo(1.0); + expect(normaliser(twoOverTwo).normalisedRatio).toBeCloseTo(0.5); + expect(normaliser(oneOverOne).normalisedRatio).toBeCloseTo(0.5); + expect(normaliser(oneOverTwo).normalisedRatio).toBeCloseTo(0.25); + expect(normaliser(minusTwoOverOne).normalisedRatio).toBeCloseTo(-1.0); + expect(normaliser(minusTwoOverTwo).normalisedRatio).toBeCloseTo(-0.5); + expect(normaliser(minusOneOverOne).normalisedRatio).toBeCloseTo(-0.5); + expect(normaliser(minusOneOverTwo).normalisedRatio).toBeCloseTo(-0.25); + }); + + it("sorts large positive ratios before small positive ratios", () => { + const oneTwentyFive = new Gbp(1, 25, 1); + const twoFifty = new Gbp(2, 50, 1); + const twoOverTwo = BalanceToBudgetRatio.new(twoFifty, { + quantity: twoFifty, + period: 42, + }); + const oneOverTwo = BalanceToBudgetRatio.new(oneTwentyFive, { + quantity: twoFifty, + period: 42, + }); + + const resultLeftways = BalanceToBudgetRatio.compare(twoOverTwo, oneOverTwo); + const resultRightways = BalanceToBudgetRatio.compare( + oneOverTwo, + twoOverTwo, + ); + + expect(resultLeftways).toBeCloseTo(-resultRightways); + expect(resultLeftways).toBeLessThan(0); + }); + + it("sorts small negative ratios before large negative ratios", () => { + const twoFifty = new Gbp(2, 50, 1); + const minusOneTwentyFive = new Gbp(1, 25, -1); + const minusTwoFifty = new Gbp(2, 50, -1); + const minusTwoOverTwo = BalanceToBudgetRatio.new(minusTwoFifty, { + quantity: twoFifty, + period: 42, + }); + const minusOneOverTwo = BalanceToBudgetRatio.new(minusOneTwentyFive, { + quantity: twoFifty, + period: 42, + }); + + const resultLeftways = BalanceToBudgetRatio.compare( + minusOneOverTwo, + minusTwoOverTwo, + ); + const resultRightways = BalanceToBudgetRatio.compare( + minusTwoOverTwo, + minusOneOverTwo, + ); + + expect(resultLeftways).toBeCloseTo(-resultRightways); + expect(resultLeftways).toBeLessThan(0); + }); + + it("sorts positive ratios before negative ratios", () => { + const twoFifty = new Gbp(2, 50, 1); + const minusTwoFifty = new Gbp(2, 50, -1); + const twoOverTwo = BalanceToBudgetRatio.new(twoFifty, { + quantity: twoFifty, + period: 42, + }); + const minusTwoOverTwo = BalanceToBudgetRatio.new(minusTwoFifty, { + quantity: twoFifty, + period: 42, + }); + + const resultLeftways = BalanceToBudgetRatio.compare( + twoOverTwo, + minusTwoOverTwo, + ); + const resultRightways = BalanceToBudgetRatio.compare( + minusTwoOverTwo, + twoOverTwo, + ); + + expect(resultLeftways).toBeCloseTo(-resultRightways); + expect(resultLeftways).toBeLessThan(0); + }); +}); |
