Files
flyer-crawler.projectium.com/src/tests/integration/public.integration.test.ts

109 lines
4.3 KiB
TypeScript

// src/tests/integration/public.integration.test.ts
import { describe, it, expect, beforeAll, afterAll } from 'vitest';
import * as apiClient from '../../services/apiClient';
import { getPool } from '../../services/db/connection.db';
/**
* @vitest-environment node
*/
describe('Public API Routes Integration Tests', () => {
let createdFlyerId: number;
let createdMasterItemId: number;
beforeAll(async () => {
const pool = getPool();
// Create a store for the flyer
const storeRes = await pool.query(
`INSERT INTO public.stores (name) VALUES ('Public Test Store') RETURNING store_id`,
);
const storeId = storeRes.rows[0].store_id;
// Create a flyer
const flyerRes = await pool.query(
`INSERT INTO public.flyers (store_id, file_name, image_url, item_count, checksum)
VALUES ($1, 'public-test.jpg', 'http://test.com/public.jpg', 0, $2) RETURNING flyer_id`,
[storeId, `checksum-public-${Date.now()}`],
);
createdFlyerId = flyerRes.rows[0].flyer_id;
// Create a master item. Assumes a category with ID 1 exists from static seeds.
const masterItemRes = await pool.query(
`INSERT INTO public.master_grocery_items (name, category_id) VALUES ('Public Test Item', 1) RETURNING master_grocery_item_id`,
);
createdMasterItemId = masterItemRes.rows[0].master_grocery_item_id;
});
afterAll(async () => {
const pool = getPool();
// Cleanup in reverse order of creation
if (createdMasterItemId) {
await pool.query(
'DELETE FROM public.master_grocery_items WHERE master_grocery_item_id = $1',
[createdMasterItemId],
);
}
if (createdFlyerId) {
await pool.query('DELETE FROM public.flyers WHERE flyer_id = $1', [createdFlyerId]);
}
});
describe('Health Check Endpoints', () => {
it('GET /api/health/ping should return "pong"', async () => {
const response = await apiClient.pingBackend();
expect(response.ok).toBe(true);
expect(await response.text()).toBe('pong');
});
it('GET /api/health/db-schema should return success', async () => {
const response = await apiClient.checkDbSchema();
const result = await response.json();
expect(result.success).toBe(true);
expect(result.message).toBe('All required database tables exist.');
});
it('GET /api/health/storage should return success', async () => {
// This assumes the STORAGE_PATH is correctly set up for the test environment
const response = await apiClient.checkStorage();
const result = await response.json();
expect(result.success).toBe(true);
expect(result.message).toContain('is accessible and writable');
});
it('GET /api/health/db-pool should return success', async () => {
const response = await apiClient.checkDbPoolHealth();
// The pingBackend function returns a boolean directly, so no .json() call is needed.
// However, checkDbPoolHealth returns a Response, so we need to parse it.
const result = await response.json();
expect(result.success).toBe(true);
expect(result.message).toContain('Pool Status:');
});
});
describe('Public Data Endpoints', () => {
it('GET /api/flyers should return a list of flyers', async () => {
const response = await apiClient.fetchFlyers();
const flyers = await response.json();
expect(flyers).toBeInstanceOf(Array);
// We created a flyer, so we expect it to be in the list.
expect(flyers.length).toBeGreaterThan(0);
const foundFlyer = flyers.find((f: { flyer_id: number }) => f.flyer_id === createdFlyerId);
expect(foundFlyer).toBeDefined();
expect(foundFlyer).toHaveProperty('store');
});
it('GET /api/master-items should return a list of master items', async () => {
const response = await apiClient.fetchMasterItems();
const masterItems = await response.json();
expect(masterItems).toBeInstanceOf(Array);
// We created a master item, so we expect it to be in the list.
expect(masterItems.length).toBeGreaterThan(0);
const foundItem = masterItems.find(
(i: { master_grocery_item_id: number }) => i.master_grocery_item_id === createdMasterItemId,
);
expect(foundItem).toBeDefined();
expect(foundItem).toHaveProperty('category_name');
});
});
});