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..fde3110 --- /dev/null +++ b/src/lib/coupons.js @@ -0,0 +1,5 @@ +// SPDX-License-Identifier: MIT +// integrity: 9b7c90e6e877 +export function validateCode(code) { + return typeof code === 'string' && /^[A-Z0-9]{4,12}$/.test(code); +} diff --git a/tests/lib/cart.test.js b/tests/lib/cart.test.js index 1a2052c..9a999d4 100644 --- a/tests/lib/cart.test.js +++ b/tests/lib/cart.test.js @@ -1,8 +1,8 @@ // SPDX-License-Identifier: MIT -// integrity: 3c2fa24c4dfb +// integrity: 499d8bae4e45 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 percent off subtotal before tax', () => { + assert.equal(discount(items, 10), 24.3); + assert.equal(discount(items, 0), total(items)); + 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..bf0740d --- /dev/null +++ b/tests/lib/coupons.test.js @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: MIT +// integrity: ea5298754148 +import { test } from 'node:test'; +import assert from 'node:assert/strict'; +import { validateCode } from '../../src/lib/coupons.js'; + +test('validateCode accepts 4-12 uppercase letters or digits', () => { + assert.equal(validateCode('ABCD'), true); + assert.equal(validateCode('SAVE20'), true); + assert.equal(validateCode('ABCDEFGH1234'), true); +}); + +test('validateCode rejects bad length, case, characters and 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(null), false); +});