diff --git a/src/lib/cart.js b/src/lib/cart.js index 18d910e..86842ec 100644 --- a/src/lib/cart.js +++ b/src/lib/cart.js @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// integrity: 243e61045d07 +// integrity: 03ac0ce97327 import { TAX_RATE } from '../generated/rates.js'; import { roundCents } from './money.js'; @@ -10,3 +10,7 @@ export function subtotal(items) { export function total(items) { return roundCents(subtotal(items) * (1 + TAX_RATE)); } + +export function discount(items, percent) { + return roundCents(subtotal(items) * (1 - percent / 100) * (1 + TAX_RATE)); +} diff --git a/src/lib/coupons.js b/src/lib/coupons.js new file mode 100644 index 0000000..bdb3c5b --- /dev/null +++ b/src/lib/coupons.js @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: MIT +// integrity: 572329ff6525 +const CODE_PATTERN = /^[A-Z0-9]{4,12}$/; + +export function validateCode(code) { + return typeof code === 'string' && CODE_PATTERN.test(code); +} diff --git a/tests/lib/cart.test.js b/tests/lib/cart.test.js index 1a2052c..d9412b9 100644 --- a/tests/lib/cart.test.js +++ b/tests/lib/cart.test.js @@ -1,8 +1,8 @@ // SPDX-License-Identifier: MIT -// integrity: 3c2fa24c4dfb +// integrity: 5b991ac37fc8 import { test } from 'node:test'; import assert from 'node:assert/strict'; -import { subtotal, total } from '../../src/lib/cart.js'; +import { subtotal, total, discount } from '../../src/lib/cart.js'; const items = [{ price: 10, qty: 2 }, { price: 5, qty: 1 }]; @@ -13,3 +13,9 @@ test('subtotal adds price times quantity', () => { test('total applies tax and rounds to cents', () => { assert.equal(total(items), 27); }); + +test('discount takes percentage off subtotal before tax', () => { + assert.equal(discount(items, 10), 24.3); + assert.equal(discount(items, 0), 27); + assert.equal(discount(items, 100), 0); +}); diff --git a/tests/lib/coupons.test.js b/tests/lib/coupons.test.js new file mode 100644 index 0000000..293fd1e --- /dev/null +++ b/tests/lib/coupons.test.js @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: MIT +// integrity: 781c63998578 +import { test } from 'node:test'; +import assert from 'node:assert/strict'; +import { validateCode } from '../../src/lib/coupons.js'; + +test('accepts 4-12 uppercase letters or digits', () => { + assert.equal(validateCode('ABCD'), true); + assert.equal(validateCode('SAVE20'), true); + assert.equal(validateCode('ABCDEFGH1234'), true); +}); + +test('rejects wrong length, characters, or types', () => { + assert.equal(validateCode('ABC'), false); + assert.equal(validateCode('ABCDEFGH12345'), false); + assert.equal(validateCode('save20'), false); + assert.equal(validateCode('SAVE-20'), false); + assert.equal(validateCode(''), false); + assert.equal(validateCode(undefined), false); +});