/** * Dev Puppeteer script — intercepts /api/game/load and injects a fresh * game state built from the actual compiled data files, so we can browse * the game UI without auth or a real DB record. */ import puppeteer from "puppeteer"; import { createRequire } from "module"; const require = createRequire(import.meta.url); // Load actual game data from compiled API output const { defaultAchievements } = require("./apps/api/prod/src/data/achievements.js"); const { defaultEquipment } = require("./apps/api/prod/src/data/equipment.js"); const { defaultBosses } = require("./apps/api/prod/src/data/bosses.js"); const { defaultQuests } = require("./apps/api/prod/src/data/quests.js"); const { defaultAdventurers } = require("./apps/api/prod/src/data/adventurers.js"); const { defaultUpgrades } = require("./apps/api/prod/src/data/upgrades.js"); const { defaultZones } = require("./apps/api/prod/src/data/zones.js"); console.log("šŸ“¦ Data loaded:"); console.log(` achievements : ${defaultAchievements.length}`); console.log(` equipment : ${defaultEquipment.length}`); console.log(` bosses : ${defaultBosses.length}`); console.log(` quests : ${defaultQuests.length}`); // Spot-check for our new items const newEquipIds = [ "chaos_mantle", "titan_core", "expanse_blade", "void_armour_mk2", "cosmos_blade", "reality_plate", "maelstrom_edge", "cosmic_plate", "primeval_blade", "ancient_aegis", "absolute_blade", "eternity_plate", "omniversal_core", ]; const foundNew = newEquipIds.filter(id => defaultEquipment.some(e => e.id === id)); const missingNew = newEquipIds.filter(id => !defaultEquipment.some(e => e.id === id)); console.log(`\nšŸ—”ļø New equipment found (${foundNew.length}/13): ${foundNew.join(", ")}`); if (missingNew.length > 0) console.log(` āŒ Missing: ${missingNew.join(", ")}`); const questEternal = defaultAchievements.find(a => a.id === "quest_eternal"); const fullyEquipped = defaultAchievements.find(a => a.id === "fully_equipped"); console.log(`\nšŸ† quest_eternal condition amount : ${questEternal?.condition?.amount}`); console.log(`šŸ† fully_equipped condition amount: ${fullyEquipped?.condition?.amount}`); // Build a minimal but valid mock game state const mockState = { achievements : defaultAchievements, adventurers : defaultAdventurers, baseClickPower: 1, bosses : defaultBosses, equipment : defaultEquipment, lastTickAt : Date.now(), player : { avatar : null, characterName : "Hikari Test", createdAt : Date.now(), discordId : "000000000000000001", discriminator : "0", lastSavedAt : Date.now(), lifetimeAchievementsUnlocked: 0, lifetimeAdventurersRecruited: 0, lifetimeBossesDefeated : 0, lifetimeClicks : 0, lifetimeGoldEarned : 0, lifetimeQuestsCompleted : 0, totalClicks : 0, totalGoldEarned : 0, username : "HikariTest", }, prestige : { count : 0, runestones : 0, }, quests : defaultQuests, resources : { crystals : 0, essence : 0, gold : 0, }, upgrades : defaultUpgrades, zones : defaultZones, }; const mockLoadResponse = { currentSchemaVersion: 1, inGuild : true, loginBonus : null, loginStreak : 0, offlineEssence : 0, offlineGold : 0, offlineSeconds : 0, schemaOutdated : false, signature : undefined, state : mockState, }; console.log("\n🌐 Launching browser..."); const browser = await puppeteer.launch({ args : ["--no-sandbox", "--disable-setuid-sandbox"], headless: false, }); const page = await browser.newPage(); await page.setViewport({ height: 900, width: 1400 }); // Intercept the game load call and inject our mock state await page.setRequestInterception(true); page.on("request", (req) => { if (req.url().includes("/api/game/load") && req.method() === "GET") { console.log(" ā†©ļø Intercepted /api/game/load — injecting mock state"); req.respond({ body : JSON.stringify(mockLoadResponse), contentType : "application/json", headers : { "Content-Type": "application/json" }, status : 200, }); } else { req.continue(); } }); // Set a fake token so the frontend thinks we're logged in await page.evaluateOnNewDocument(() => { localStorage.setItem("elysium_token", "dev.fake.token"); }); console.log(" šŸ”— Navigating to http://localhost:5173 ..."); await page.goto("http://localhost:5173", { waitUntil: "networkidle2" }); // Give the game a moment to tick and render await new Promise(r => setTimeout(r, 3000)); await page.screenshot({ path: "/tmp/elysium-01-game.png" }); console.log(" šŸ“ø Screenshot: /tmp/elysium-01-game.png"); // Try to find the equipment panel const equipmentTab = await page.$("button, a, [role='tab']"); console.log(`\nšŸ” Checking page title: ${await page.title()}`); // Log any visible text that mentions our new items const pageText = await page.evaluate(() => document.body.innerText); const newItemsVisible = newEquipIds.filter(id => pageText.toLowerCase().includes(id.replace(/_/g, " ").toLowerCase().slice(0, 8))); console.log(`\nšŸ—”ļø New item names visible in UI: ${newItemsVisible.length > 0 ? newItemsVisible.join(", ") : "none yet (may need to navigate to equipment panel)"}`); // Check achievement counts visible in page const hasQuestEternal = pageText.includes("112"); const hasFullyEquipped = pageText.includes("78"); console.log(` quest_eternal (112) visible: ${hasQuestEternal}`); console.log(` fully_equipped (78) visible: ${hasFullyEquipped}`); console.log("\nāœ… Browser open — take a look around! Close it when done."); console.log(" (or Ctrl+C to exit)\n");