From 25e7b87c2bf2a147e1d8051f824d2c0243d37d33 Mon Sep 17 00:00:00 2001 From: "Aaron K. Clark" Date: Tue, 19 May 2026 14:09:00 -0500 Subject: [PATCH] test(customerpayment): cover non-finite cpayAmount rejection MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The `cpayAmountField` zod schema applies `.coerce.number().finite()` — JSON has no literal for Infinity, but `coerce` happily turns the string "Infinity" into the float, and a DOUBLE column would store it and poison every downstream sum / aging-bucket calculation. The existing "accepts negative cpayAmount" test had a comment claiming the schema "blocks 0 and the infinities" but only the zero case had an explicit test; the .finite() branch was unpinned. Add POST + PATCH cases covering Infinity and -Infinity. Mirrors the existing invoicejob.test.js coverage for the same scenario on `injbAmount`. Test count: 790 → 792. Co-Authored-By: Claude Opus 4.7 (1M context) --- tests/api/customerpayment.test.js | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/tests/api/customerpayment.test.js b/tests/api/customerpayment.test.js index c1ff633..91a973e 100644 --- a/tests/api/customerpayment.test.js +++ b/tests/api/customerpayment.test.js @@ -76,6 +76,25 @@ describe('CustomerPayment body validation', () => { .send({ cpayAmount: 0 }); expect(res.status).toBe(400); }); + + test('POST rejects non-finite cpayAmount (Infinity via z.coerce.number)', async () => { + // The schema applies `z.coerce.number().finite()` — JSON has no + // literal for Infinity, but `coerce` happily turns the STRING + // "Infinity" into the float, and a DOUBLE column would store it + // and poison every downstream sum / aging-bucket calculation. + // Pin the .finite() guard so a future schema rewrite that drops + // it surfaces here. Mirrors the invoicejob.test.js coverage for + // the same scenario on injbAmount. + const res = await request(app).post('/v1/customerpayment').set('authKey', 'any') + .send({ cpayCustId: 1, cpayDate: '2026-01-01', cpayAmount: 'Infinity' }); + expect(res.status).toBe(400); + }); + + test('PATCH rejects non-finite cpayAmount', async () => { + const res = await request(app).patch('/v1/customerpayment/1').set('authKey', 'any') + .send({ cpayAmount: '-Infinity' }); + expect(res.status).toBe(400); + }); }); describe('CustomerPayment tenant-enumeration defense (secure 404)', () => {