fixing categories 3rd normal form
All checks were successful
Deploy to Test Environment / deploy-to-test (push) Successful in 18m34s
All checks were successful
Deploy to Test Environment / deploy-to-test (push) Successful in 18m34s
This commit is contained in:
174
src/tests/integration/category.routes.test.ts
Normal file
174
src/tests/integration/category.routes.test.ts
Normal file
@@ -0,0 +1,174 @@
|
||||
// src/tests/integration/category.routes.test.ts
|
||||
import { describe, it, expect, beforeAll } from 'vitest';
|
||||
import supertest from 'supertest';
|
||||
|
||||
/**
|
||||
* @vitest-environment node
|
||||
*/
|
||||
|
||||
describe('Category API Routes (Integration)', () => {
|
||||
let request: ReturnType<typeof supertest>;
|
||||
|
||||
beforeAll(async () => {
|
||||
const app = (await import('../../../server')).default;
|
||||
request = supertest(app);
|
||||
});
|
||||
|
||||
describe('GET /api/categories', () => {
|
||||
it('should return list of all categories', async () => {
|
||||
const response = await request.get('/api/categories');
|
||||
|
||||
expect(response.status).toBe(200);
|
||||
expect(response.body.success).toBe(true);
|
||||
expect(Array.isArray(response.body.data)).toBe(true);
|
||||
expect(response.body.data.length).toBeGreaterThan(0);
|
||||
|
||||
// Verify category structure
|
||||
const firstCategory = response.body.data[0];
|
||||
expect(firstCategory).toHaveProperty('category_id');
|
||||
expect(firstCategory).toHaveProperty('name');
|
||||
expect(firstCategory).toHaveProperty('created_at');
|
||||
expect(firstCategory).toHaveProperty('updated_at');
|
||||
expect(typeof firstCategory.category_id).toBe('number');
|
||||
expect(typeof firstCategory.name).toBe('string');
|
||||
});
|
||||
|
||||
it('should return categories in alphabetical order', async () => {
|
||||
const response = await request.get('/api/categories');
|
||||
const categories = response.body.data;
|
||||
|
||||
// Verify alphabetical ordering
|
||||
for (let i = 1; i < categories.length; i++) {
|
||||
const prevName = categories[i - 1].name.toLowerCase();
|
||||
const currName = categories[i].name.toLowerCase();
|
||||
expect(currName >= prevName).toBe(true);
|
||||
}
|
||||
});
|
||||
|
||||
it('should include expected categories', async () => {
|
||||
const response = await request.get('/api/categories');
|
||||
const categories = response.body.data;
|
||||
const categoryNames = categories.map((c: { name: string }) => c.name);
|
||||
|
||||
// Verify some expected categories exist
|
||||
expect(categoryNames).toContain('Dairy & Eggs');
|
||||
expect(categoryNames).toContain('Fruits & Vegetables');
|
||||
expect(categoryNames).toContain('Meat & Seafood');
|
||||
expect(categoryNames).toContain('Bakery & Bread');
|
||||
});
|
||||
});
|
||||
|
||||
describe('GET /api/categories/:id', () => {
|
||||
it('should return specific category by valid ID', async () => {
|
||||
// First get all categories to find a valid ID
|
||||
const listResponse = await request.get('/api/categories');
|
||||
const firstCategory = listResponse.body.data[0];
|
||||
|
||||
const response = await request.get(`/api/categories/${firstCategory.category_id}`);
|
||||
|
||||
expect(response.status).toBe(200);
|
||||
expect(response.body.success).toBe(true);
|
||||
expect(response.body.data.category_id).toBe(firstCategory.category_id);
|
||||
expect(response.body.data.name).toBe(firstCategory.name);
|
||||
});
|
||||
|
||||
it('should return 404 for non-existent category ID', async () => {
|
||||
const response = await request.get('/api/categories/999999');
|
||||
|
||||
expect(response.status).toBe(404);
|
||||
expect(response.body.success).toBe(false);
|
||||
expect(response.body.error).toContain('not found');
|
||||
});
|
||||
|
||||
it('should return 400 for invalid category ID (not a number)', async () => {
|
||||
const response = await request.get('/api/categories/invalid');
|
||||
|
||||
expect(response.status).toBe(400);
|
||||
expect(response.body.success).toBe(false);
|
||||
expect(response.body.error).toContain('Invalid category ID');
|
||||
});
|
||||
|
||||
it('should return 400 for negative category ID', async () => {
|
||||
const response = await request.get('/api/categories/-1');
|
||||
|
||||
expect(response.status).toBe(400);
|
||||
expect(response.body.success).toBe(false);
|
||||
expect(response.body.error).toContain('Invalid category ID');
|
||||
});
|
||||
|
||||
it('should return 400 for zero category ID', async () => {
|
||||
const response = await request.get('/api/categories/0');
|
||||
|
||||
expect(response.status).toBe(400);
|
||||
expect(response.body.success).toBe(false);
|
||||
expect(response.body.error).toContain('Invalid category ID');
|
||||
});
|
||||
});
|
||||
|
||||
describe('GET /api/categories/lookup', () => {
|
||||
it('should find category by exact name', async () => {
|
||||
const response = await request.get('/api/categories/lookup?name=Dairy%20%26%20Eggs');
|
||||
|
||||
expect(response.status).toBe(200);
|
||||
expect(response.body.success).toBe(true);
|
||||
expect(response.body.data.name).toBe('Dairy & Eggs');
|
||||
expect(response.body.data.category_id).toBeGreaterThan(0);
|
||||
});
|
||||
|
||||
it('should find category by case-insensitive name', async () => {
|
||||
const response = await request.get('/api/categories/lookup?name=dairy%20%26%20eggs');
|
||||
|
||||
expect(response.status).toBe(200);
|
||||
expect(response.body.success).toBe(true);
|
||||
expect(response.body.data.name).toBe('Dairy & Eggs');
|
||||
});
|
||||
|
||||
it('should find category with mixed case', async () => {
|
||||
const response = await request.get('/api/categories/lookup?name=DaIrY%20%26%20eGgS');
|
||||
|
||||
expect(response.status).toBe(200);
|
||||
expect(response.body.success).toBe(true);
|
||||
expect(response.body.data.name).toBe('Dairy & Eggs');
|
||||
});
|
||||
|
||||
it('should return 404 for non-existent category name', async () => {
|
||||
const response = await request.get('/api/categories/lookup?name=NonExistentCategory');
|
||||
|
||||
expect(response.status).toBe(404);
|
||||
expect(response.body.success).toBe(false);
|
||||
expect(response.body.error).toContain('not found');
|
||||
});
|
||||
|
||||
it('should return 400 if name parameter is missing', async () => {
|
||||
const response = await request.get('/api/categories/lookup');
|
||||
|
||||
expect(response.status).toBe(400);
|
||||
expect(response.body.success).toBe(false);
|
||||
expect(response.body.error).toContain('required');
|
||||
});
|
||||
|
||||
it('should return 400 for empty name parameter', async () => {
|
||||
const response = await request.get('/api/categories/lookup?name=');
|
||||
|
||||
expect(response.status).toBe(400);
|
||||
expect(response.body.success).toBe(false);
|
||||
expect(response.body.error).toContain('required');
|
||||
});
|
||||
|
||||
it('should return 400 for whitespace-only name parameter', async () => {
|
||||
const response = await request.get('/api/categories/lookup?name= ');
|
||||
|
||||
expect(response.status).toBe(400);
|
||||
expect(response.body.success).toBe(false);
|
||||
expect(response.body.error).toContain('required');
|
||||
});
|
||||
|
||||
it('should handle URL-encoded category names', async () => {
|
||||
const response = await request.get('/api/categories/lookup?name=Dairy%20%26%20Eggs');
|
||||
|
||||
expect(response.status).toBe(200);
|
||||
expect(response.body.success).toBe(true);
|
||||
expect(response.body.data.name).toBe('Dairy & Eggs');
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user