import assert from 'node:assert/strict' import test from 'node:test' import { adjustBudget, budgetReserve, canDecrease, canIncrease, budgetSubmission, cloneBudget, emptyBudget, missingEssentials, } from '../src/modules/gold-land/budgeting/budgetMath' import { ApiNetworkError, StaleSessionError } from '../src/api/errors' import { invalidateSession } from '../src/api/authSession' import { bindMeMutationApply, resetMeMutationQueueForTests, runMeMutation } from '../src/api/meMutationQueue' const categories = [ { id: 'transport' as const, label: 'رفت‌وآمد', requiredInitial: 20, requiredFinal: 30 }, { id: 'food' as const, label: 'آب و غذا', requiredInitial: 25, requiredFinal: 25 }, { id: 'savings' as const, label: 'پس‌انداز', requiredInitial: null, requiredFinal: null }, { id: 'fun' as const, label: 'تفریح', requiredInitial: null, requiredFinal: null }, ] test('reserve and button limits stay inside 100 coins', () => { let amounts = emptyBudget() assert.equal(budgetReserve(100, amounts), 100) assert.equal(canDecrease(amounts, 'fun', 5), false) for (let i = 0; i < 20; i += 1) { amounts = adjustBudget(amounts, 'fun', 5, 5, 100) } assert.equal(budgetReserve(100, amounts), 0) assert.equal(canIncrease(amounts, 5, 100), false) const unchanged = adjustBudget(amounts, 'food', 5, 5, 100) assert.equal(unchanged.food, 0) assert.equal(unchanged.fun, 100) }) test('editing the final budget does not change the submitted initial allocations', () => { const initial = { transport: 20, food: 25, savings: 20, fun: 0 } const finalPlan = cloneBudget(initial) const payload = budgetSubmission(initial, finalPlan) finalPlan.transport += 10 finalPlan.fun = 15 assert.deepEqual(payload[0]?.allocations, { transport: 20, food: 25, savings: 20, fun: 0 }) assert.equal(payload[1]?.allocations.transport, 20) assert.equal(missingEssentials(initial, categories, 'initial').length, 0) assert.equal(missingEssentials(finalPlan, categories, 'final').some((item) => item.id === 'food'), false) }) test('network and late session responses do not apply a new account', async () => { resetMeMutationQueueForTests() let applied = 0 bindMeMutationApply(() => { applied += 1 return true }) await assert.rejects( () => runMeMutation(async () => { throw new ApiNetworkError() }), ApiNetworkError, ) assert.equal(applied, 0) await assert.rejects( () => runMeMutation(async () => { invalidateSession() return { me: { user: { coins: 999 } } } }), StaleSessionError, ) assert.equal(applied, 0) })