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());