import request from 'supertest'; import app from '../../src/app'; import { pool } from '../../src/db'; import { resetDb, closeDb } from './setup/testDb'; beforeEach(async () => { await resetDb(); }); afterAll(async () => { await pool.end(); await closeDb(); }); async function registerAndGetAgent(email: string) { const agent = request.agent(app); await agent.post('/api/customers/register').send({ email, password: 'supersecret123' }); return agent; } describe('cart', () => { it('adding an item to cart marks it reserved', async () => { const { rows } = await pool.query(`INSERT INTO items (name, price_cents, status) VALUES ('Test Item', 1000, 'available') RETURNING id`); const itemId = rows[0].id; const agent = await registerAndGetAgent('cart1@example.com'); const addRes = await agent.post(`/api/cart/items/${itemId}`); expect(addRes.status).toBe(201); const itemCheck = await request(app).get(`/api/items/${itemId}`); expect(itemCheck.body.status).toBe('reserved'); const cartRes = await agent.get('/api/cart'); expect(cartRes.body.items).toHaveLength(1); expect(cartRes.body.items[0].item_id).toBe(itemId); }); it('refuses to add an item that is already reserved', async () => { const { rows } = await pool.query(`INSERT INTO items (name, price_cents, status) VALUES ('Test Item', 1000, 'available') RETURNING id`); const itemId = rows[0].id; const agentA = await registerAndGetAgent('cartA@example.com'); const agentB = await registerAndGetAgent('cartB@example.com'); await agentA.post(`/api/cart/items/${itemId}`); const res = await agentB.post(`/api/cart/items/${itemId}`); expect(res.status).toBe(409); }); it('removing an item from cart releases it back to available', async () => { const { rows } = await pool.query(`INSERT INTO items (name, price_cents, status) VALUES ('Test Item', 1000, 'available') RETURNING id`); const itemId = rows[0].id; const agent = await registerAndGetAgent('cart2@example.com'); await agent.post(`/api/cart/items/${itemId}`); const removeRes = await agent.delete(`/api/cart/items/${itemId}`); expect(removeRes.status).toBe(204); const itemCheck = await request(app).get(`/api/items/${itemId}`); expect(itemCheck.body.status).toBe('available'); }); }); describe('cart demo checkout', () => { async function addShippingAddress(agent: any) { const res = await agent.post('/api/customers/me/addresses').send({ fullName: 'Jane Doe', addressLine1: '123 Main St', city: 'Springfield', state: 'IL', postalCode: '62701' }); return res.body.address.id; } it('completes a multi-item cart purchase and marks all items sold', async () => { const { rows } = await pool.query( `INSERT INTO items (name, price_cents, status) VALUES ('Item A', 1000, 'available'), ('Item B', 2000, 'available') RETURNING id` ); const [itemA, itemB] = rows; const agent = await registerAndGetAgent('checkout1@example.com'); await agent.post(`/api/cart/items/${itemA.id}`); await agent.post(`/api/cart/items/${itemB.id}`); const addressId = await addShippingAddress(agent); const res = await agent.post('/api/checkout/cart/demo/purchase').send({ shippingAddressId: addressId }); expect(res.status).toBe(200); expect(res.body.status).toBe('completed'); const checkA = await request(app).get(`/api/items/${itemA.id}`); const checkB = await request(app).get(`/api/items/${itemB.id}`); expect(checkA.body.status).toBe('sold'); expect(checkB.body.status).toBe('sold'); const cartRes = await agent.get('/api/cart'); expect(cartRes.body.items).toHaveLength(0); const ordersRes = await agent.get('/api/customers/me/orders'); expect(ordersRes.body).toHaveLength(2); }); it('refuses checkout without a shipping address', async () => { const { rows } = await pool.query(`INSERT INTO items (name, price_cents, status) VALUES ('Item A', 1000, 'available') RETURNING id`); const agent = await registerAndGetAgent('checkout2@example.com'); await agent.post(`/api/cart/items/${rows[0].id}`); const res = await agent.post('/api/checkout/cart/demo/purchase').send({}); expect(res.status).toBe(400); }); it('refuses checkout with an empty cart', async () => { const agent = await registerAndGetAgent('checkout3@example.com'); const addressId = await addShippingAddress(agent); const res = await agent.post('/api/checkout/cart/demo/purchase').send({ shippingAddressId: addressId }); expect(res.status).toBe(400); }); });