summaryrefslogtreecommitdiff
path: root/gui/src/types/BalanceToBudgetRatio.spec.ts
diff options
context:
space:
mode:
authorJoe Carstairs <me@joeac.net>2024-09-17 13:20:04 +0100
committerJoe Carstairs <me@joeac.net>2024-09-17 13:20:04 +0100
commitcd269b3540fb5e3a988c1b59d3763db360b1fb34 (patch)
treea728403d8d5708ad29eeed2b391706b09a93fe4c /gui/src/types/BalanceToBudgetRatio.spec.ts
parentf0e3e0cfb183253e03b1a61ddecb7b9330d47fdb (diff)
many, many changes
Diffstat (limited to 'gui/src/types/BalanceToBudgetRatio.spec.ts')
-rw-r--r--gui/src/types/BalanceToBudgetRatio.spec.ts307
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);
+ });
+});