const { Cart } = require('./solution'); describe('Cart', () => { test('empty cart totals', () => { const c = new Cart(); expect(c.subtotal()).toBe(0); expect(c.discount()).toBe(0); expect(c.shipping()).toBe(0); expect(c.total()).toBe(0); }); test('add merges quantities and is chainable', () => { const c = new Cart().add('a', 'Kalem', 1000).add('a', 'Kalem', 1000, 2); expect(c.items.get('a').qty).toBe(3); expect(c.subtotal()).toBe(3000); }); test.each([[-1, 1], [1.5, 1], ['10', 1]])('rejects bad price %p', (p, q) => { expect(() => new Cart().add('x', 'X', p, q)).toThrow(TypeError); }); test.each([0, 1.5])('rejects bad qty %p', (q) => { expect(() => new Cart().add('x', 'X', 100, q)).toThrow(RangeError); }); test('remove partially, fully and unknown', () => { const c = new Cart().add('a', 'A', 100, 3); expect(c.remove('a', 1)).toBe(true); expect(c.items.get('a').qty).toBe(2); expect(c.remove('a')).toBe(true); expect(c.items.size).toBe(0); expect(c.remove('zz')).toBe(false); }); test('percent coupon is case-insensitive and rounds', () => { const c = new Cart().add('a', 'A', 1005); c.applyCoupon('yuzde10'); expect(c.discount()).toBe(101); }); test('fixed coupon is capped at subtotal', () => { const c = new Cart().add('a', 'A', 3000); c.applyCoupon('INDIRIM50'); expect(c.discount()).toBe(3000); expect(c.total()).toBe(2999); }); test('invalid coupon throws', () => { expect(() => new Cart().applyCoupon('YOK')).toThrow('Geçersiz kupon'); }); test('free shipping threshold uses discounted amount', () => { const c = new Cart().add('a', 'A', 50000); expect(c.shipping()).toBe(0); c.applyCoupon('YUZDE10'); expect(c.shipping()).toBe(2999); expect(c.total()).toBe(50000 - 5000 + 2999); }); test('below threshold pays shipping', () => { expect(new Cart().add('a', 'A', 49999).shipping()).toBe(2999); }); });