diff --git a/tests/bad-code.test.js b/tests/bad-code.test.js deleted file mode 100644 index 9de800d..0000000 --- a/tests/bad-code.test.js +++ /dev/null @@ -1,11 +0,0 @@ -import { test } from 'node:test'; -import assert from 'node:assert/strict'; -import { applyCoupon } from '../src/lib/pricing.js'; - -test('bad code fails', () => { - assert.throws(() => applyCoupon(20, 'BOGUS'), { message: 'Unknown coupon: BOGUS' }); -}); - -test('bad code with spaces fails the same way', () => { - assert.throws(() => applyCoupon(20, ' nope '), { message: 'Unknown coupon: nope' }); -}); diff --git a/tests/blank-code.test.js b/tests/blank-code.test.js deleted file mode 100644 index 2670186..0000000 --- a/tests/blank-code.test.js +++ /dev/null @@ -1,13 +0,0 @@ -import { test } from 'node:test'; -import assert from 'node:assert/strict'; -import { applyCoupon, total } from '../src/lib/pricing.js'; - -// Duplicate of empty-coupon.test.js -test('blank coupon does nothing', () => { - assert.equal(applyCoupon(50, ''), 0); - assert.equal(total([{ price: 10, qty: 1 }], { coupon: '' }), total([{ price: 10, qty: 1 }])); -}); - -test('spaces only is also no discount', () => { - assert.equal(applyCoupon(50, ' '), 0); -}); diff --git a/tests/coupons-save10.test.js b/tests/coupons-save10.test.js deleted file mode 100644 index 77a32b1..0000000 --- a/tests/coupons-save10.test.js +++ /dev/null @@ -1,13 +0,0 @@ -import { test } from 'node:test'; -import assert from 'node:assert/strict'; -import { total } from '../src/lib/pricing.js'; - -test('SAVE10 makes the order cheaper', () => { - const items = [{ price: 40, qty: 1 }]; - assert.ok(total(items, { coupon: 'SAVE10' }) < total(items)); -}); - -test('save10 lowercase also makes it cheaper', () => { - const items = [{ price: 40, qty: 1 }]; - assert.ok(total(items, { coupon: 'save10' }) < total(items)); -}); diff --git a/tests/coupons.test.js b/tests/coupons.test.js new file mode 100644 index 0000000..fa0cddf --- /dev/null +++ b/tests/coupons.test.js @@ -0,0 +1,57 @@ +import { test } from 'node:test'; +import assert from 'node:assert/strict'; +import { applyCoupon, subtotal, total } from '../src/lib/pricing.js'; +import { roundCents } from '../src/lib/money.js'; +import { TAX_RATE } from '../src/generated/rates.js'; +import { CART_10, CART_40, LARGE_CART, SMALL_CART } from './helpers/fixtures.js'; + +test('SAVE10 makes the order cheaper', () => { + assert.ok(total(CART_40, { coupon: 'SAVE10' }) < total(CART_40)); +}); + +test('SAVE10 is case-insensitive', () => { + assert.ok(total(CART_40, { coupon: 'save10' }) < total(CART_40)); +}); + +test('SAVE10 rounds the discount and totals correctly on a 10.05 cart', () => { + const items = [{ price: 10.05, qty: 1 }]; + const sub = subtotal(items); + assert.equal(sub, 10.05); + assert.equal(applyCoupon(sub, 'SAVE10'), 1.01); + const after = 10.05 - 1.01; + assert.equal(total(items, { coupon: 'SAVE10' }), roundCents(after + roundCents(after * TAX_RATE))); +}); + +test('FLAT5 takes five dollars off a large cart', () => { + const sub = subtotal(LARGE_CART); + assert.equal(applyCoupon(sub, 'FLAT5'), 5); + assert.equal(total(LARGE_CART, { coupon: 'FLAT5' }), roundCents((sub - 5) * (1 + TAX_RATE))); +}); + +test('FLAT5 ignores case and surrounding whitespace', () => { + const sub = subtotal(LARGE_CART); + assert.equal(applyCoupon(sub, ' flat5 '), 5); + assert.equal(total(LARGE_CART, { coupon: 'Flat5' }), roundCents((sub - 5) * (1 + TAX_RATE))); +}); + +test('FLAT5 on an order under $5 discounts only the subtotal, making total 0', () => { + assert.equal(applyCoupon(3, 'FLAT5'), 3); + assert.equal(total(SMALL_CART, { coupon: 'FLAT5' }), 0); +}); + +test('empty coupon string means no discount', () => { + assert.equal(applyCoupon(50, ''), 0); + assert.equal(total(CART_10, { coupon: '' }), total(CART_10)); +}); + +test('whitespace-only coupon means no discount', () => { + assert.equal(applyCoupon(50, ' '), 0); +}); + +test('unknown coupon throws', () => { + assert.throws(() => applyCoupon(20, 'BOGUS'), { message: 'Unknown coupon: BOGUS' }); +}); + +test('unknown coupon error reports the trimmed code', () => { + assert.throws(() => applyCoupon(20, ' nope '), { message: 'Unknown coupon: nope' }); +}); diff --git a/tests/dead-helper.test.js b/tests/dead-helper.test.js deleted file mode 100644 index 0831a9e..0000000 --- a/tests/dead-helper.test.js +++ /dev/null @@ -1,8 +0,0 @@ -import { test } from 'node:test'; -import assert from 'node:assert/strict'; -// legacyComputeDiscount was removed when applyCoupon landed; this file never got deleted. -import { legacyComputeDiscount } from '../src/lib/pricing.js'; - -test('legacy helper still works', () => { - assert.equal(legacyComputeDiscount(100, 'SAVE10'), 10); -}); diff --git a/tests/discount-percent.test.js b/tests/discount-percent.test.js deleted file mode 100644 index 2f2c111..0000000 --- a/tests/discount-percent.test.js +++ /dev/null @@ -1,13 +0,0 @@ -import { test } from 'node:test'; -import assert from 'node:assert/strict'; -import { total } from '../src/lib/pricing.js'; - -test('percent off coupon reduces the bill', () => { - const items = [{ price: 40, qty: 1 }]; - assert.ok(total(items, { coupon: 'SAVE10' }) < total(items)); -}); - -test('coupon works when written in lowercase', () => { - const items = [{ price: 40, qty: 1 }]; - assert.ok(total(items, { coupon: 'save10' }) < total(items)); -}); diff --git a/tests/empty-coupon.test.js b/tests/empty-coupon.test.js deleted file mode 100644 index dd04706..0000000 --- a/tests/empty-coupon.test.js +++ /dev/null @@ -1,12 +0,0 @@ -import { test } from 'node:test'; -import assert from 'node:assert/strict'; -import { total, applyCoupon } from '../src/lib/pricing.js'; - -test('empty coupon string means no discount', () => { - assert.equal(applyCoupon(50, ''), 0); - assert.equal(total([{ price: 10, qty: 1 }], { coupon: '' }), total([{ price: 10, qty: 1 }])); -}); - -test('whitespace-only coupon means no discount', () => { - assert.equal(applyCoupon(50, ' '), 0); -}); diff --git a/tests/flat5-again.test.js b/tests/flat5-again.test.js deleted file mode 100644 index 846494e..0000000 --- a/tests/flat5-again.test.js +++ /dev/null @@ -1,25 +0,0 @@ -import { test } from 'node:test'; -import assert from 'node:assert/strict'; -import { total, applyCoupon, subtotal } from '../src/lib/pricing.js'; -import { roundCents } from '../src/lib/money.js'; -import { TAX_RATE } from '../src/generated/rates.js'; - -test('flat five dollar coupon on the big order', () => { - const items = [ - { price: 12.5, qty: 2 }, - { price: 7, qty: 1 }, - ]; - const sub = subtotal(items); - assert.equal(applyCoupon(sub, 'FLAT5'), 5); - assert.equal(total(items, { coupon: 'FLAT5' }), roundCents((sub - 5) * (1 + TAX_RATE))); -}); - -test('FLAT5 also works in mixed case', () => { - const items = [ - { price: 12.5, qty: 2 }, - { price: 7, qty: 1 }, - ]; - const sub = subtotal(items); - assert.equal(applyCoupon(sub, ' flat5 '), 5); - assert.equal(total(items, { coupon: 'Flat5' }), roundCents((sub - 5) * (1 + TAX_RATE))); -}); diff --git a/tests/flat5.test.js b/tests/flat5.test.js deleted file mode 100644 index 4c4cffa..0000000 --- a/tests/flat5.test.js +++ /dev/null @@ -1,16 +0,0 @@ -import { test } from 'node:test'; -import assert from 'node:assert/strict'; -import { total, applyCoupon, subtotal } from '../src/lib/pricing.js'; -import { roundCents } from '../src/lib/money.js'; -import { TAX_RATE } from '../src/generated/rates.js'; - -test('FLAT5 takes five dollars off a large cart', () => { - const items = [ - { price: 12.5, qty: 2 }, - { price: 7, qty: 1 }, - ]; - const sub = subtotal(items); // 32 - const disc = applyCoupon(sub, 'FLAT5'); - assert.equal(disc, 5); - assert.equal(total(items, { coupon: 'FLAT5' }), roundCents((sub - 5) * (1 + TAX_RATE))); -}); diff --git a/tests/helpers/fixtures.js b/tests/helpers/fixtures.js new file mode 100644 index 0000000..f540009 --- /dev/null +++ b/tests/helpers/fixtures.js @@ -0,0 +1,8 @@ +export const LARGE_CART = [ + { price: 12.5, qty: 2 }, + { price: 7, qty: 1 }, +]; // subtotal 32 + +export const SMALL_CART = [{ price: 3, qty: 1 }]; +export const CART_40 = [{ price: 40, qty: 1 }]; +export const CART_10 = [{ price: 10, qty: 1 }]; diff --git a/tests/legacy-skipped.test.js b/tests/legacy-skipped.test.js deleted file mode 100644 index 0686b69..0000000 --- a/tests/legacy-skipped.test.js +++ /dev/null @@ -1,21 +0,0 @@ -import { test } from 'node:test'; -import assert from 'node:assert/strict'; -import { total } from '../src/lib/pricing.js'; - -test.skip('old seasonal coupon WINTER20 (removed from product)', () => { - const items = [{ price: 100, qty: 1 }]; - assert.equal(total(items, { coupon: 'WINTER20' }), 86.4); -}); - -test.skip('TODO: gift-card stacking', () => { - assert.ok(true); -}); - -// Was useful once; left commented out -// test('BLACKFRIDAY50', () => { -// assert.equal(total([{ price: 20, qty: 1 }], { coupon: 'BLACKFRIDAY50' }), 10.8); -// }); - -test('sanity: a plain cart still totals', () => { - assert.ok(total([{ price: 1, qty: 1 }]) > 0); -}); diff --git a/tests/noop-assert.test.js b/tests/noop-assert.test.js deleted file mode 100644 index f9e845a..0000000 --- a/tests/noop-assert.test.js +++ /dev/null @@ -1,13 +0,0 @@ -import { test } from 'node:test'; -import assert from 'node:assert/strict'; -import { total } from '../src/lib/pricing.js'; - -test('total returns something', () => { - const r = total([{ price: 9.99, qty: 3 }], { coupon: 'SAVE10' }); - assert.ok(typeof r === 'number'); -}); - -test('coupon option is accepted', () => { - total([{ price: 50, qty: 1 }], { coupon: 'SAVE10' }); - assert.ok(true); -}); diff --git a/tests/pricing-basic.test.js b/tests/pricing.test.js similarity index 70% rename from tests/pricing-basic.test.js rename to tests/pricing.test.js index 2364cb0..886f893 100644 --- a/tests/pricing-basic.test.js +++ b/tests/pricing.test.js @@ -3,6 +3,7 @@ import assert from 'node:assert/strict'; import { subtotal, total } from '../src/lib/pricing.js'; import { roundCents } from '../src/lib/money.js'; import { TAX_RATE } from '../src/generated/rates.js'; +import { CART_10 } from './helpers/fixtures.js'; test('subtotal adds price times qty', () => { const items = [ @@ -12,7 +13,6 @@ test('subtotal adds price times qty', () => { assert.equal(subtotal(items), 25); }); -test('total applies tax with no coupon', () => { - const items = [{ price: 10, qty: 1 }]; - assert.equal(total(items), roundCents(10 * (1 + TAX_RATE))); +test('total applies tax when there is no coupon', () => { + assert.equal(total(CART_10), roundCents(10 * (1 + TAX_RATE))); }); diff --git a/tests/save10-another-cart.test.js b/tests/save10-another-cart.test.js deleted file mode 100644 index 43190bf..0000000 --- a/tests/save10-another-cart.test.js +++ /dev/null @@ -1,14 +0,0 @@ -import { test } from 'node:test'; -import assert from 'node:assert/strict'; -import { applyCoupon, total, subtotal } from '../src/lib/pricing.js'; -import { roundCents } from '../src/lib/money.js'; -import { TAX_RATE } from '../src/generated/rates.js'; - -test('SAVE10 works on another cart', () => { - const items = [{ price: 10.05, qty: 1 }]; - const sub = subtotal(items); - assert.equal(sub, 10.05); - assert.equal(applyCoupon(sub, 'SAVE10'), 1.01); - const after = 10.05 - 1.01; - assert.equal(total(items, { coupon: 'SAVE10' }), roundCents(after + roundCents(after * TAX_RATE))); -}); diff --git a/tests/small-order-coupon.test.js b/tests/small-order-coupon.test.js deleted file mode 100644 index 3ca0fa4..0000000 --- a/tests/small-order-coupon.test.js +++ /dev/null @@ -1,9 +0,0 @@ -import { test } from 'node:test'; -import assert from 'node:assert/strict'; -import { applyCoupon, total } from '../src/lib/pricing.js'; - -test('coupon on a small order still makes it cheaper', () => { - const items = [{ price: 3, qty: 1 }]; - assert.equal(applyCoupon(3, 'FLAT5'), 3); - assert.equal(total(items, { coupon: 'FLAT5' }), 0); -});