import { chromium } from 'playwright'; const BASE = 'http://127.0.0.1:3000'; const opts = { waitUntil: 'domcontentloaded', timeout: 15000 }; (async () => { const browser = await chromium.launch({ headless: true, args: ['--no-sandbox'] }); // Obtenir un token via API const apiCtx = await browser.newContext(); const apiPage = await apiCtx.newPage(); await apiPage.goto(BASE + '/api/auth/login', opts); const token = await apiPage.evaluate(async () => { const res = await fetch('/api/auth/login', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ username: 'roman', password: 'roman123' }) }); const data = await res.json(); return data.access_token || null; }); await apiCtx.close(); console.log(`Token obtained: ${token ? token.substring(0, 20) + '...' : 'FAILED'}`); if (!token) { console.error('Cannot get token, aborting'); process.exit(1); } // ========== NON AUTHENTIFIE ========== console.log('\n=== NON AUTHENTIFIE ==='); const anonCtx = await browser.newContext({ viewport: { width: 1440, height: 900 } }); const anon = await anonCtx.newPage(); const snap = async (p, name, url, wait = 3000) => { try { await p.goto(url, opts); await p.waitForTimeout(wait); await p.screenshot({ path: `/tmp/screenshots/${name}.png`, fullPage: false }); console.log(`OK: ${name}`); } catch(e) { console.log(`FAIL: ${name} - ${e.message}`); } }; await snap(anon, 'anon_01_home', `${BASE}/`); await snap(anon, 'anon_02_watchlist', `${BASE}/watchlist`); await snap(anon, 'anon_03_favorites', `${BASE}/favorites`); await snap(anon, 'anon_04_downloads', `${BASE}/downloads`); await snap(anon, 'anon_05_settings', `${BASE}/settings`); await snap(anon, 'anon_06_recommendations', `${BASE}/recommendations`); // ========== AUTHENTIFIE (cookie + localStorage) ========== console.log('\n=== AUTHENTIFIE ==='); const authCtx = await browser.newContext({ viewport: { width: 1440, height: 900 }, }); // Injecter le token comme cookie AVANT toute navigation await authCtx.addCookies([{ name: 'auth_token', value: token, domain: '127.0.0.1', path: '/', sameSite: 'Strict', httpOnly: false, }]); const auth = await authCtx.newPage(); // Injecter dans localStorage au premier chargement await auth.goto(BASE + '/', opts); await auth.evaluate((t) => { localStorage.setItem('auth_token', t); }, token); await auth.waitForTimeout(3000); await auth.screenshot({ path: '/tmp/screenshots/auth_01_home.png', fullPage: false }); console.log('OK: auth_01_home'); await snap(auth, 'auth_02_watchlist', `${BASE}/watchlist`); await snap(auth, 'auth_03_favorites', `${BASE}/favorites`); await snap(auth, 'auth_04_downloads', `${BASE}/downloads`); await snap(auth, 'auth_05_settings', `${BASE}/settings`); await snap(auth, 'auth_06_recommendations', `${BASE}/recommendations`); // ========== TESTS FONCTIONNELS ========== console.log('\n=== TESTS FONCTIONNELS ==='); // Test API: toggle favori const favResult = await auth.evaluate(async (t) => { try { const res = await fetch('/api/favorites/toggle', { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${t}` }, body: JSON.stringify({ content_type: 'anime', anime_id: 'test-screenshot-1', title: 'Test Screenshot Anime' }) }); const data = await res.json(); return { status: res.status, is_favorite: data.is_favorite }; } catch(e) { return { error: e.message }; } }, token); console.log(`Favorite toggle: ${JSON.stringify(favResult)}`); // Voir les favoris await snap(auth, 'auth_07_favorites_after_add', `${BASE}/favorites`); // Test API: ajouter watchlist item const wlResult = await auth.evaluate(async (t) => { try { const res = await fetch('/api/watchlist', { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${t}` }, body: JSON.stringify({ anime_title: 'Test Screenshot Anime', anime_url: 'https://example.com/anime/1', episode_count: 12, current_episode: 0, status: 'watching' }) }); const data = await res.json(); return { status: res.status, id: data.id, title: data.anime_title }; } catch(e) { return { error: e.message }; } }, token); console.log(`Watchlist add: ${JSON.stringify(wlResult)}`); // Voir la watchlist await snap(auth, 'auth_08_watchlist_with_item', `${BASE}/watchlist`); // Scroller sur la home await auth.goto(`${BASE}/`, opts); await auth.waitForTimeout(2000); await auth.evaluate(() => window.scrollTo(0, 600)); await auth.waitForTimeout(1000); await auth.screenshot({ path: '/tmp/screenshots/auth_09_home_scrolled.png', fullPage: false }); console.log('OK: auth_09_home_scrolled'); // ========== NETTOYAGE ========== console.log('\n=== Nettoyage ==='); // Retirer le favori de test await auth.evaluate(async (t) => { await fetch('/api/favorites/toggle', { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${t}` }, body: JSON.stringify({ content_type: 'anime', anime_id: 'test-screenshot-1', title: 'Test Screenshot Anime' }) }); }); // Retirer le watchlist item de test if (wlResult.id) { await auth.evaluate(async ({t, id}) => { await fetch(`/api/watchlist/${id}`, { method: 'DELETE', headers: { 'Authorization': `Bearer ${t}` } }); }, { t: token, id: wlResult.id }); console.log('Test watchlist item deleted'); } console.log('Test favorite removed'); await browser.close(); console.log('\n=== ALL DONE ==='); })();