Files
flyer-crawler.projectium.com/src/tests/integration/flyer.integration.test.ts
Torben Sorensen 459f5f7976
All checks were successful
Deploy to Test Environment / deploy-to-test (push) Successful in 21m36s
sql fixes
2026-01-02 18:59:16 -08:00

124 lines
4.8 KiB
TypeScript

// src/tests/integration/flyer.integration.test.ts
import { describe, it, expect, beforeAll } from 'vitest';
import supertest from 'supertest';
import { getPool } from '../../services/db/connection.db';
import app from '../../../server';
import type { Flyer, FlyerItem } from '../../types';
/**
* @vitest-environment node
*/
describe('Public Flyer API Routes Integration Tests', () => {
let flyers: Flyer[] = [];
// Use a supertest instance for all requests in this file
const request = supertest(app);
let createdFlyerId: number;
// Fetch flyers once before all tests in this suite to use in subsequent tests.
beforeAll(async () => {
// Ensure at least one flyer exists
const storeRes = await getPool().query(
`INSERT INTO public.stores (name) VALUES ('Integration Test Store') RETURNING store_id`,
);
const storeId = storeRes.rows[0].store_id;
const flyerRes = await getPool().query(
`INSERT INTO public.flyers (store_id, file_name, image_url, icon_url, item_count, checksum)
VALUES ($1, 'integration-test.jpg', 'https://example.com/flyer-images/integration-test.jpg', 'https://example.com/flyer-images/icons/integration-test.jpg', 1, $2) RETURNING flyer_id`,
[storeId, `${Date.now().toString(16)}`.padEnd(64, '0')],
);
createdFlyerId = flyerRes.rows[0].flyer_id;
// Add an item to it
await getPool().query(
`INSERT INTO public.flyer_items (flyer_id, item, price_display, price_in_cents, quantity)
VALUES ($1, 'Integration Test Item', '$1.99', 199, 'each')`,
[createdFlyerId],
);
const response = await request.get('/api/flyers');
flyers = response.body;
});
describe('GET /api/flyers', () => {
it('should return a list of flyers', async () => {
// Act: Call the API endpoint using the client function.
const response = await request.get('/api/flyers');
const flyers: Flyer[] = response.body;
expect(response.status).toBe(200);
expect(flyers).toBeInstanceOf(Array);
// We created a flyer in beforeAll, so we expect the array not to be empty.
expect(flyers.length).toBeGreaterThan(0);
// Check the shape of the first flyer object to ensure it matches the expected type.
const firstFlyer = flyers[0];
expect(firstFlyer).toHaveProperty('flyer_id');
expect(firstFlyer).toHaveProperty('file_name');
expect(firstFlyer).toHaveProperty('image_url');
expect(firstFlyer).toHaveProperty('store');
expect(firstFlyer.store).toHaveProperty('store_id');
expect(firstFlyer.store).toHaveProperty('name');
});
});
describe('GET /api/flyers/:id/items', () => {
it('should return items for a specific flyer', async () => {
// Arrange: Ensure we have at least one flyer to test with.
expect(flyers.length).toBeGreaterThan(0);
const testFlyer = flyers[0];
// Act: Fetch items for the first flyer.
const response = await request.get(`/api/flyers/${testFlyer.flyer_id}/items`);
const items: FlyerItem[] = response.body;
expect(response.status).toBe(200);
expect(items).toBeInstanceOf(Array);
// If there are items, check the shape of the first one.
if (items.length > 0) {
const firstItem = items[0];
expect(firstItem).toHaveProperty('flyer_item_id');
expect(firstItem).toHaveProperty('item');
expect(firstItem).toHaveProperty('price_display');
expect(firstItem.flyer_id).toBe(testFlyer.flyer_id);
}
});
});
describe('POST /api/flyers/items/batch-fetch', () => {
it('should return items for multiple flyer IDs', async () => {
// Arrange: Get IDs from the flyers fetched in beforeAll.
const flyerIds = flyers.map((f) => f.flyer_id);
expect(flyerIds.length).toBeGreaterThan(0);
// Act: Fetch items for all available flyers.
const response = await request.post('/api/flyers/items/batch-fetch').send({ flyerIds });
const items: FlyerItem[] = response.body;
expect(response.status).toBe(200);
expect(items).toBeInstanceOf(Array);
// The total number of items should be greater than or equal to the number of flyers (assuming at least one item per flyer).
if (items.length > 0) {
expect(items[0]).toHaveProperty('flyer_item_id');
}
});
});
describe('POST /api/flyers/items/batch-count', () => {
it('should return the total count of items for multiple flyer IDs', async () => {
// Arrange
const flyerIds = flyers.map((f) => f.flyer_id);
expect(flyerIds.length).toBeGreaterThan(0);
// Act
const response = await request.post('/api/flyers/items/batch-count').send({ flyerIds });
const result = response.body;
// Assert
expect(result.count).toBeTypeOf('number');
expect(result.count).toBeGreaterThan(0);
});
});
});