diff --git a/something.txt b/something.txt new file mode 100644 index 0000000..f76e7f9 --- /dev/null +++ b/something.txt @@ -0,0 +1,336 @@ +/** + * PokeRogue Extension E2E Test - v2 + */ +const { chromium } = require('playwright'); +const path = require('path'); +const fs = require('fs'); +const EXTENSION_PATH = '/home/ceo/Desktop/poke-extension'; +const USER_DATA_DIR = '/tmp/poke-ext-test-profile-' + Date.now(); +const SCREENSHOT_DIR = '/home/ceo/Desktop/poke-extension'; +const USERNAME = 'ClaudeCode'; +const PASSWORD = '5454%colagenio%5656'; +const consoleMessages = []; +const extMessages = []; +const sleep = ms => new Promise(r => setTimeout(r, ms)); +async function shot(page, name) { + const fp = path.join(SCREENSHOT_DIR, `test-${name}.png`); + await page.screenshot({ path: fp }); + console.log(`[SHOT] ${fp}`); +} +async function main() { + console.log('[TEST] === PokeRogue Extension E2E Test v2 ==='); + // Step 1: Launch + console.log('\n[STEP 1] Launching Chromium with extension...'); + const context = await chromium.launchPersistentContext(USER_DATA_DIR, { + headless: false, + args: [ + '--ignore-gpu-blacklist', + '--disable-gpu-sandbox', + `--disable-extensions-except=${EXTENSION_PATH}`, + `--load-extension=${EXTENSION_PATH}`, + '--no-first-run', + '--disable-blink-features=AutomationControlled', + '--window-size=1280,900', + ], + viewport: { width: 1280, height: 900 }, + ignoreDefaultArgs: ['--disable-extensions'], + }); + let page = context.pages()[0] || await context.newPage(); + page.on('console', msg => { + const t = msg.text(); + consoleMessages.push({ type: msg.type(), text: t }); + if (t.includes('[PokeRogue Ext]')) { + extMessages.push(t); + console.log(` [EXT] ${t}`); + } + }); + page.on('pageerror', err => console.log(` [PERR] ${err.message.substring(0, 150)}`)); + // Step 2: Navigate + console.log('\n[STEP 2] Navigating to pokerogue.net...'); + await page.goto('https://pokerogue.net/', { waitUntil: 'domcontentloaded', timeout: 60000 }); + console.log(' Waiting 20s for Phaser...'); + await sleep(20000); + await shot(page, '01-initial-load'); + // Step 3: Check messages + console.log('\n[STEP 3] Extension messages check:'); + for (const c of ['Game bridge loaded', 'SceneManager prototype patch installed', 'Game instance captured']) { + console.log(` ${extMessages.some(m => m.includes(c)) ? '✓' : '✗'} ${c}`); + } + const gameCheck = await page.evaluate(() => ({ + exists: !!window.__POKEXT_GAME__, + hasScene: !!(window.__POKEXT_GAME__?.scene), + hasCanvas: !!(window.__POKEXT_GAME__?.canvas), + })); + console.log(` __POKEXT_GAME__: ${JSON.stringify(gameCheck)}`); + // Step 4: Login + console.log('\n[STEP 4] Logging in...'); + + // Focus canvas and press Enter to get to login screen + await page.mouse.click(640, 450); + await sleep(1000); + await page.keyboard.press('Enter'); + await sleep(2000); + await shot(page, '02-login-screen'); + // Find visible inputs by coordinates + const inputInfo = await page.evaluate(() => { + const all = Array.from(document.querySelectorAll('input')); + return all.map((inp, i) => { + const r = inp.getBoundingClientRect(); + const s = window.getComputedStyle(inp); + return { + i, type: inp.type, + vis: r.width > 0 && r.height > 0 && s.display !== 'none' && s.visibility !== 'hidden', + x: r.x, y: r.y, w: r.width, h: r.height, + }; + }).filter(x => x.vis); + }); + console.log(` Visible inputs: ${JSON.stringify(inputInfo)}`); + const textInputs = inputInfo.filter(i => i.type === 'text'); + const pwdInputs = inputInfo.filter(i => i.type === 'password'); + if (textInputs.length > 0 && pwdInputs.length > 0) { + const ui = textInputs[0]; + const pi = pwdInputs[0]; + // Click username field and type + await page.mouse.click(ui.x + ui.w / 2, ui.y + ui.h / 2); + await sleep(300); + await page.keyboard.press('Control+a'); + await sleep(100); + await page.keyboard.type(USERNAME, { delay: 30 }); + await sleep(300); + // Click password field and type + await page.mouse.click(pi.x + pi.w / 2, pi.y + pi.h / 2); + await sleep(300); + await page.keyboard.press('Control+a'); + await sleep(100); + await page.keyboard.type(PASSWORD, { delay: 30 }); + await sleep(300); + await shot(page, '03-login-filled'); + // Verify + const vals = await page.evaluate(({ uIdx, pIdx }) => { + const inputs = document.querySelectorAll('input'); + return { u: inputs[uIdx]?.value, pLen: inputs[pIdx]?.value?.length }; + }, { uIdx: ui.i, pIdx: pi.i }); + console.log(` Filled: user="${vals.u}", pwdLen=${vals.pLen}`); + // Submit - press Enter + await page.keyboard.press('Enter'); + console.log(' Submitted login form'); + await sleep(5000); + await shot(page, '04-after-login'); + // Check if we need to retry + const loginResult = await page.evaluate(() => { + const text = document.body.innerText || ''; + return { + hasError: text.includes('incorrect') || text.includes('must not be empty') || text.includes('Invalid'), + snippet: text.substring(0, 200), + }; + }); + + if (loginResult.hasError) { + console.log(` Login may have failed: ${loginResult.snippet.substring(0, 100)}`); + // Try again - click username, clear, retype + await page.mouse.click(ui.x + ui.w / 2, ui.y + ui.h / 2); + await sleep(200); + await page.keyboard.press('Control+a'); + await page.keyboard.press('Backspace'); + await sleep(100); + await page.keyboard.type(USERNAME, { delay: 50 }); + await sleep(200); + + await page.mouse.click(pi.x + pi.w / 2, pi.y + pi.h / 2); + await sleep(200); + await page.keyboard.press('Control+a'); + await page.keyboard.press('Backspace'); + await sleep(100); + await page.keyboard.type(PASSWORD, { delay: 50 }); + await sleep(200); + + // Now find and click the Login button in the canvas area + // The button is below the password field typically + // Try pressing Enter from password field + await page.keyboard.press('Enter'); + await sleep(5000); + await shot(page, '05-login-retry'); + } + } else { + console.log(' No visible login inputs found!'); + } + // Wait for login to complete and main menu to appear + await sleep(3000); + await shot(page, '06-post-login'); + // Step 5: Start battle + console.log('\n[STEP 5] Starting a battle...'); + + // Focus canvas + await page.mouse.click(640, 450); + await sleep(500); + // Check current game phase/state + const preMenuState = await page.evaluate(() => { + const g = window.__POKEXT_GAME__; + if (!g?.scene) return { noGame: true }; + const scenes = g.scene.scenes || []; + const battleScene = scenes.find(s => s.currentBattle !== undefined); + return { + sceneKeys: scenes.map(s => s.sys?.settings?.key).slice(0, 10), + hasBattleScene: !!battleScene, + currentPhase: battleScene?.currentPhase?.constructor?.name || 'none', + currentBattle: battleScene?.currentBattle ? { + waveIndex: battleScene.currentBattle.waveIndex, + turn: battleScene.currentBattle.turn, + } : null, + }; + }); + console.log(` Pre-menu state: ${JSON.stringify(preMenuState)}`); + // Navigate through menus + // After login: main menu appears. Press Enter to select first option. + // If "Continue" is available, it starts from last save. + // If "New Game", it starts character selection. + + let battleFound = false; + + for (let attempt = 0; attempt < 25; attempt++) { + const bc = await page.evaluate(() => { + const g = window.__POKEXT_GAME__; + if (!g?.scene) return { battle: false }; + const scenes = g.scene.scenes || []; + for (const s of scenes) { + if (s.currentBattle) { + const pf = typeof s.getPlayerField === 'function' ? s.getPlayerField() : []; + const ef = typeof s.getEnemyField === 'function' ? s.getEnemyField() : []; + if (pf.length > 0 && ef.length > 0) { + return { battle: true, wave: s.currentBattle.waveIndex, players: pf.length, enemies: ef.length }; + } + return { battle: false, partial: true, wave: s.currentBattle.waveIndex }; + } + } + return { battle: false }; + }); + if (bc.battle) { + console.log(` Battle found at attempt ${attempt + 1}! Wave: ${bc.wave}, Players: ${bc.players}, Enemies: ${bc.enemies}`); + battleFound = true; + break; + } + if (attempt % 5 === 0 && attempt > 0) { + console.log(` Attempt ${attempt}: no battle yet (${JSON.stringify(bc)})`); + await shot(page, `07-nav-attempt-${attempt}`); + } + // Press Enter to advance through menus/dialogs + await page.keyboard.press('Enter'); + await sleep(1500); + } + if (!battleFound) { + console.log(' Battle not found after Enter presses, trying arrow navigation...'); + // Try selecting different menu options + for (let i = 0; i < 3; i++) { + await page.keyboard.press('ArrowDown'); + await sleep(500); + } + await page.keyboard.press('Enter'); + await sleep(3000); + + for (let attempt = 0; attempt < 10; attempt++) { + const bc = await page.evaluate(() => { + const g = window.__POKEXT_GAME__; + if (!g?.scene) return { battle: false }; + return { battle: (g.scene.scenes || []).some(s => s.currentBattle) }; + }); + if (bc.battle) { + battleFound = true; + console.log(` Battle found after arrow nav!`); + break; + } + await page.keyboard.press('Enter'); + await sleep(2000); + } + } + // Wait for battle to fully load + await sleep(5000); + await shot(page, '08-battle-state'); + // Step 6: Verify overlay + console.log('\n[STEP 6] Verifying overlay...'); + await sleep(3000); // Let polling catch up + const finalState = await page.evaluate(() => { + const g = window.__POKEXT_GAME__; + const overlay = document.getElementById('poke-ext-overlay'); + + let battleInfo = null; + if (g?.scene) { + for (const s of (g.scene.scenes || [])) { + if (s.currentBattle) { + try { + const pf = typeof s.getPlayerField === 'function' ? s.getPlayerField() : []; + const ef = typeof s.getEnemyField === 'function' ? s.getEnemyField() : []; + battleInfo = { + wave: s.currentBattle.waveIndex, + double: !!s.currentBattle.double, + player: pf.filter(Boolean).map(p => ({ + name: typeof p.getNameToRender === 'function' ? p.getNameToRender() : (p.name || '?'), + types: typeof p.getTypes === 'function' ? p.getTypes() : [], + moves: (p.moveset || []).filter(Boolean).map(m => { + const mv = typeof m.getMove === 'function' ? m.getMove() : m; + return { name: typeof m.getName === 'function' ? m.getName() : (mv?.name || '?'), type: mv?.type ?? -1, power: mv?.power ?? 0, cat: mv?.category ?? -1 }; + }), + })), + enemy: ef.filter(Boolean).map(p => ({ + name: typeof p.getNameToRender === 'function' ? p.getNameToRender() : (p.name || '?'), + types: typeof p.getTypes === 'function' ? p.getTypes() : [], + })), + }; + } catch (e) { battleInfo = { error: e.message }; } + } + } + } + + return { + gameExists: !!g, + battleInfo, + overlay: { + exists: !!overlay, + visible: overlay ? overlay.style.display !== 'none' : false, + html: overlay ? overlay.innerHTML : '', + text: overlay ? overlay.innerText : '', + }, + }; + }); + console.log(` Game exists: ${finalState.gameExists}`); + console.log(` Battle: ${JSON.stringify(finalState.battleInfo, null, 2)}`); + console.log(` Overlay exists: ${finalState.overlay.exists}, visible: ${finalState.overlay.visible}`); + console.log(` Overlay text:\n${finalState.overlay.text}`); + console.log(` Overlay HTML (1500 chars):\n${finalState.overlay.html.substring(0, 1500)}`); + await shot(page, '09-final-with-overlay'); + // Try to get overlay closeup + if (finalState.overlay.exists) { + try { + const el = await page.$('#poke-ext-overlay'); + if (el) { + await el.screenshot({ path: path.join(SCREENSHOT_DIR, 'test-10-overlay-closeup.png') }); + console.log('[SHOT] test-10-overlay-closeup.png'); + } + } catch (_) {} + } + // Step 7: All ext messages + console.log('\n[STEP 7] All [PokeRogue Ext] messages:'); + console.log('─'.repeat(60)); + extMessages.forEach((m, i) => console.log(` ${i + 1}. ${m}`)); + if (!extMessages.length) console.log(' (none)'); + console.log('─'.repeat(60)); + const errs = consoleMessages.filter(m => m.type === 'error'); + if (errs.length) { + console.log(`\n Errors (${errs.length}):`); + errs.slice(0, 10).forEach(e => console.log(` ${e.text.substring(0, 200)}`)); + } + console.log('\n[SUMMARY]'); + console.log(` ${gameCheck.exists ? '✓' : '✗'} Game captured via SceneManager patch`); + console.log(` ${finalState.overlay.exists ? '✓' : '✗'} Overlay created`); + console.log(` ${finalState.battleInfo ? '✓' : '✗'} Battle detected`); + if (finalState.battleInfo && !finalState.battleInfo.error) { + console.log(` ${finalState.overlay.text.includes('Effectiveness') ? '✓' : '✗'} Overlay shows type effectiveness`); + } + console.log(` Extension messages: ${extMessages.length}`); + await context.close(); + try { fs.rmSync(USER_DATA_DIR, { recursive: true, force: true }); } catch (_) {} + console.log('\n[TEST] Done!'); +} +main().catch(err => { + console.error('[FATAL]', err.message); + process.exit(1); +});