fix: remove stale single-item demo-checkout tests, add cart integration tests #13

Merged
bermudalamb merged 1 commits from fix/stale-demo-checkout-tests into main 2026-08-14 16:12:33 -05:00
2 changed files with 118 additions and 66 deletions
Showing only changes of commit 1c46632e8f - Show all commits
@@ -0,0 +1,118 @@
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) VALUES ('Test Item', 1000) 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) VALUES ('Test Item', 1000) 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) VALUES ('Test Item', 1000) 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) VALUES ('Item A', 1000), ('Item B', 2000) 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) VALUES ('Item A', 1000) 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);
});
});
@@ -1,66 +0,0 @@
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();
});
describe('GET /api/items', () => {
it('returns an empty array when there are no items', async () => {
const res = await request(app).get('/api/items');
expect(res.status).toBe(200);
expect(res.body).toEqual([]);
});
it('returns items with an empty images array when none are attached', async () => {
await pool.query(
`INSERT INTO items (name, description, price_cents) VALUES ('Vintage Lamp', 'A one-of-a-kind lamp.', 4500)`
);
const res = await request(app).get('/api/items');
expect(res.status).toBe(200);
expect(res.body).toHaveLength(1);
expect(res.body[0]).toMatchObject({
name: 'Vintage Lamp',
price_cents: 4500,
status: 'available',
images: []
});
});
it('returns 404 for a nonexistent item', async () => {
const res = await request(app).get('/api/items/99999');
expect(res.status).toBe(404);
});
});
describe('demo checkout', () => {
it('marks an available item as sold', async () => {
const { rows } = await pool.query(
`INSERT INTO items (name, price_cents) VALUES ('Test Item', 1000) RETURNING id`
);
const itemId = rows[0].id;
const res = await request(app).post(`/api/checkout/demo/${itemId}/purchase`);
expect(res.status).toBe(200);
expect(res.body.status).toBe('sold');
const check = await request(app).get(`/api/items/${itemId}`);
expect(check.body.status).toBe('sold');
});
it('refuses to sell an item that is already sold', async () => {
const { rows } = await pool.query(
`INSERT INTO items (name, price_cents, status) VALUES ('Already Sold', 1000, 'sold') RETURNING id`
);
const itemId = rows[0].id;
const res = await request(app).post(`/api/checkout/demo/${itemId}/purchase`);
expect(res.status).toBe(409);
});
});