diff --git a/src/lib/cart.js b/src/lib/cart.js index 18d910e..e9d947e 100644 --- a/src/lib/cart.js +++ b/src/lib/cart.js @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// integrity: 243e61045d07 +// integrity: 3959ee635ee9 import { TAX_RATE } from '../generated/rates.js'; import { roundCents } from './money.js'; @@ -10,3 +10,8 @@ export function subtotal(items) { export function total(items) { return roundCents(subtotal(items) * (1 + TAX_RATE)); } + +export function discount(items, percent) { + const discounted = subtotal(items) * (1 - percent / 100); + return roundCents(discounted * (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..da4b65b 100644 --- a/tests/lib/cart.test.js +++ b/tests/lib/cart.test.js @@ -1,8 +1,8 @@ // SPDX-License-Identifier: MIT -// integrity: 3c2fa24c4dfb +// integrity: 441c014a22bf 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 the subtotal, then applies 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..3dbc1ab --- /dev/null +++ b/tests/lib/coupons.test.js @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: MIT +// integrity: c451b10b8918 +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('SAVE10'), true); + assert.equal(validateCode('ABCD'), true); + assert.equal(validateCode('A1B2C3D4E5F6'), true); +}); + +test('rejects wrong length', () => { + assert.equal(validateCode('ABC'), false); + assert.equal(validateCode('A1B2C3D4E5F67'), false); + assert.equal(validateCode(''), false); +}); + +test('rejects lowercase, symbols, whitespace and non-strings', () => { + assert.equal(validateCode('save10'), false); + assert.equal(validateCode('SAVE-10'), false); + assert.equal(validateCode('SAVE10\n'), false); + assert.equal(validateCode(undefined), false); +});