Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions apps/pr-reviewer/fixtures/demo-pr/cart-total.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,4 +63,13 @@ describe('cartTotal', () => {
it('handles large quantities', () => {
expect(cartTotal([{ price: 3, qty: 1_000_000 }])).toBe(3_000_000);
});

it('rounds each line to whole cents', () => {
expect(
cartTotal([
{ price: 33.3, qty: 3 },
{ price: 10.4, qty: 1 },
]),
).toBe(110);
});
});
2 changes: 1 addition & 1 deletion apps/pr-reviewer/fixtures/demo-pr/cart-total.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ export function cartTotal(items: { price: number; qty: number }[]): number {
if (items[i].qty < 0) {
throw new RangeError(`Negative quantity for item ${i}`);
}
total += items[i].price * items[i].qty;
total += Math.round(items[i].price * items[i].qty);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: The code rounds each line item's subtotal individually. Subtotals less than 0.5 will be rounded to 0, leading to an incorrect final cart total and potential under-charging.
Severity: MEDIUM

Suggested Fix

To prevent precision loss, sum the exact subtotals of all line items first, and then round the final total only once at the very end. For example: return Math.round(items.reduce((acc, item) => acc + (item.price * item.qty), 0));. This ensures fractional values are not discarded prematurely.

Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent. Verify if this is a real issue. If it is, propose a fix; if not, explain why it's
not valid.

Location: apps/pr-reviewer/fixtures/demo-pr/cart-total.ts#L7

Potential issue: The function calculates the total cart value by rounding the subtotal
for each line item before summing them. The use of `Math.round(items[i].price *
items[i].qty)` can lead to accumulated rounding errors. If an item's subtotal is a
fractional value less than 0.5, it will be rounded down to 0. If a cart contains
multiple such items, their cost will be completely lost from the final total, resulting
in the customer being under-charged. This edge case is not covered by existing tests but
is a plausible scenario, especially if discounts create fractional prices.

Did we get this right? 👍 / 👎 to inform future reviews.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unsafe floating-point line rounding

Medium Severity

Math.round on the raw price * qty product can pick the wrong whole cent when binary floating point lands just below a half-cent. Checkout then undercharges those lines by one cent. The new coverage stays far enough from a .5 boundary that this miss is not caught.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 4b9abd1. Configure here.

}
return total;
}
Loading