fix: remove stale single-item demo-checkout tests, add cart integration tests
This commit is contained in:
@@ -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);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user