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