Files
2026-06-28 21:34:58 -04:00

240 lines
8.4 KiB
TypeScript

import { PrismaClient } from '@prisma/client';
const API_BASE = 'http://localhost:3051/api';
const MENU_NAME = 'test-challenger-menu-unique';
const prisma = new PrismaClient();
async function runTests() {
console.log('--- STARTING MENU IMAGE VERIFICATION TESTS ---');
// 0. Clean up any existing test menu from previous runs
console.log('Cleaning up existing test menu (if any)...');
await prisma.menu.deleteMany({ where: { name: MENU_NAME } });
// 1. Test POST /api/menus/ (Creation with valid images)
console.log('\n1. Testing POST /api/menus/ with valid images...');
const createPayload = {
name: MENU_NAME,
rootImage: 'https://example.com/root-image.jpg',
items: [
{
label: 'Challenger Item 1',
url: '/challenger-1',
order: 1,
columnImage: 'https://example.com/column-image-1.jpg',
hoverImage: 'https://example.com/hover-image-1.jpg'
},
{
label: 'Challenger Item 2',
url: '/challenger-2',
order: 2,
columnImage: null, // Null is allowed
hoverImage: null // Null is allowed
}
]
};
const createRes = await fetch(`${API_BASE}/menus/`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(createPayload)
});
console.log(`POST response status: ${createRes.status}`);
const createData = await createRes.json();
console.log('POST response data:', JSON.stringify(createData, null, 2));
if (createRes.status !== 200 && createRes.status !== 201) {
throw new Error(`Failed to create menu. Status: ${createRes.status}`);
}
// 2. Verify via Database directly
console.log('\n2. Verifying database record directly via Prisma...');
const dbMenu = await prisma.menu.findUnique({
where: { name: MENU_NAME },
include: { items: { orderBy: { order: 'asc' } } }
});
if (!dbMenu) {
throw new Error('Menu was not found in the database!');
}
console.log(`DB Menu rootImage: "${dbMenu.rootImage}"`);
if (dbMenu.rootImage !== 'https://example.com/root-image.jpg') {
throw new Error(`DB rootImage mismatch: expected "https://example.com/root-image.jpg", got "${dbMenu.rootImage}"`);
}
console.log(`DB MenuItem 1 columnImage: "${dbMenu.items[0].columnImage}", hoverImage: "${dbMenu.items[0].hoverImage}"`);
if (dbMenu.items[0].columnImage !== 'https://example.com/column-image-1.jpg' ||
dbMenu.items[0].hoverImage !== 'https://example.com/hover-image-1.jpg') {
throw new Error('DB MenuItem 1 images mismatch!');
}
console.log(`DB MenuItem 2 columnImage: ${dbMenu.items[1].columnImage}, hoverImage: ${dbMenu.items[1].hoverImage}`);
if (dbMenu.items[1].columnImage !== null || dbMenu.items[1].hoverImage !== null) {
throw new Error('DB MenuItem 2 images should be null!');
}
console.log('Database validation passed!');
// 3. Test GET /api/menus/{name}
console.log(`\n3. Querying GET /api/menus/${MENU_NAME}...`);
const getRes = await fetch(`${API_BASE}/menus/${MENU_NAME}`);
console.log(`GET response status: ${getRes.status}`);
const getData = await getRes.json();
console.log('GET response data:', JSON.stringify(getData, null, 2));
// The GET /api/menus/{name} might return tree or flat structure depending on design.
// Let's verify rootImage is present in response.
if (getData.rootImage !== 'https://example.com/root-image.jpg') {
throw new Error(`GET API rootImage mismatch: expected "https://example.com/root-image.jpg", got "${getData.rootImage}"`);
}
// 4. Test PUT /api/menus/{name} (Update images)
console.log(`\n4. Testing PUT /api/menus/${MENU_NAME} to update images...`);
const updatePayload = {
isActive: true,
rootImage: 'https://example.com/new-root-image.jpg',
items: [
{
id: dbMenu.items[0].id,
label: 'Challenger Item 1 Updated',
url: '/challenger-1-updated',
order: 1,
columnImage: 'https://example.com/new-column-image-1.jpg',
hoverImage: 'https://example.com/new-hover-image-1.jpg'
}
]
};
const putRes = await fetch(`${API_BASE}/menus/${MENU_NAME}`, {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(updatePayload)
});
console.log(`PUT response status: ${putRes.status}`);
const putData = await putRes.json();
console.log('PUT response data:', JSON.stringify(putData, null, 2));
if (putRes.status !== 200) {
throw new Error(`Failed to update menu. Status: ${putRes.status}`);
}
// Verify the update in DB
const dbMenuUpdated = await prisma.menu.findUnique({
where: { name: MENU_NAME },
include: { items: true }
});
if (!dbMenuUpdated) {
throw new Error('Updated menu not found in DB!');
}
console.log(`Updated DB Menu rootImage: "${dbMenuUpdated.rootImage}"`);
if (dbMenuUpdated.rootImage !== 'https://example.com/new-root-image.jpg') {
throw new Error('Updated DB rootImage mismatch!');
}
console.log(`Updated DB MenuItem columnImage: "${dbMenuUpdated.items[0].columnImage}", hoverImage: "${dbMenuUpdated.items[0].hoverImage}"`);
if (dbMenuUpdated.items[0].columnImage !== 'https://example.com/new-column-image-1.jpg' ||
dbMenuUpdated.items[0].hoverImage !== 'https://example.com/new-hover-image-1.jpg') {
throw new Error('Updated DB MenuItem images mismatch!');
}
console.log('Update validation passed!');
// 5. Test validation errors for incorrect types
console.log('\n5. Testing validation errors for incorrect types...');
// 5a. Invalid rootImage (number)
console.log('Testing invalid rootImage (number) in POST...');
const invalidPayload1 = {
name: `${MENU_NAME}-invalid`,
rootImage: 12345, // Invalid, should be string or null
items: []
};
const invalidRes1 = await fetch(`${API_BASE}/menus/`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(invalidPayload1)
});
console.log(`POST response status (invalid rootImage): ${invalidRes1.status}`);
const invalidData1 = await invalidRes1.json();
console.log('Response body:', JSON.stringify(invalidData1));
if (invalidRes1.status === 200 || invalidRes1.status === 201) {
throw new Error('Validation failed: Accepted invalid rootImage (number)!');
}
// 5b. Invalid columnImage (boolean) in POST
console.log('Testing invalid columnImage (boolean) in POST...');
const invalidPayload2 = {
name: `${MENU_NAME}-invalid`,
rootImage: null,
items: [
{
label: 'Invalid Item',
url: '/invalid',
order: 1,
columnImage: true, // Invalid, should be string or null
hoverImage: null
}
]
};
const invalidRes2 = await fetch(`${API_BASE}/menus/`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(invalidPayload2)
});
console.log(`POST response status (invalid columnImage): ${invalidRes2.status}`);
const invalidData2 = await invalidRes2.json();
console.log('Response body:', JSON.stringify(invalidData2));
if (invalidRes2.status === 200 || invalidRes2.status === 201) {
throw new Error('Validation failed: Accepted invalid columnImage (boolean)!');
}
// 5c. Invalid hoverImage (object) in POST
console.log('Testing invalid hoverImage (object) in POST...');
const invalidPayload3 = {
name: `${MENU_NAME}-invalid`,
rootImage: null,
items: [
{
label: 'Invalid Item',
url: '/invalid',
order: 1,
columnImage: null,
hoverImage: { url: 'https://example.com' } // Invalid, should be string or null
}
]
};
const invalidRes3 = await fetch(`${API_BASE}/menus/`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(invalidPayload3)
});
console.log(`POST response status (invalid hoverImage): ${invalidRes3.status}`);
const invalidData3 = await invalidRes3.json();
console.log('Response body:', JSON.stringify(invalidData3));
if (invalidRes3.status === 200 || invalidRes3.status === 201) {
throw new Error('Validation failed: Accepted invalid hoverImage (object)!');
}
console.log('\nAll validation error tests passed successfully!');
// Cleanup
console.log('\nCleaning up database...');
await prisma.menu.deleteMany({ where: { name: MENU_NAME } });
console.log('Cleanup completed.');
console.log('\n--- ALL VERIFICATION TESTS PASSED SUCCESSFULLY! ---');
}
runTests()
.catch(err => {
console.error('TEST RUN FAILED:', err);
process.exit(1);
})
.finally(() => prisma.$disconnect());