eae0a68f06
Key changes: - Add @rendermode InteractiveWebAssembly to Dashboard.razor (CLAUDE.md mandates Interactive WebAssembly as default) - Reorder MapRazorComponents: WebAssembly first, then Server - Simplify login.html: just redirect after 2s (no fetch verification) Root cause of 302 redirect loop: - Dashboard was rendering server-side (no @rendermode specified) - Server-side rendering can't access localStorage - CustomAuthenticationStateProvider read empty token - Dashboard redirected to /login - Result: 302 loop Solution: Force client-side WASM rendering so: 1. Blazor WASM loads in browser 2. CustomAuthenticationStateProvider accesses localStorage 3. Token is read from localStorage 4. /api/auth/me validates token 5. User is authenticated 6. Dashboard displays Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
58 lines
1.6 KiB
JavaScript
58 lines
1.6 KiB
JavaScript
import { chromium } from "@playwright/test";
|
|
|
|
(async () => {
|
|
console.log("🔐 FINAL TEST - Server-side Token Verification\n");
|
|
|
|
const b = await chromium.launch({ headless: false });
|
|
const p = await b.newPage();
|
|
|
|
const consoleLogs = [];
|
|
p.on("console", msg => {
|
|
const text = msg.text();
|
|
consoleLogs.push(text);
|
|
if (text.includes("[Login]")) {
|
|
console.log(" 📝 " + text);
|
|
}
|
|
});
|
|
|
|
try {
|
|
console.log("1. Loading login page...");
|
|
await p.goto("http://localhost:5265/login.html", { waitUntil: "networkidle" });
|
|
|
|
console.log("2. Submitting login...");
|
|
await p.fill("input[name='username']", "admin");
|
|
await p.fill("input[name='password']", "admin");
|
|
await p.click("button[type='submit']");
|
|
|
|
console.log("3. Monitoring (15 seconds)...\n");
|
|
for (let i = 1; i <= 15; i++) {
|
|
await new Promise(r => setTimeout(r, 1000));
|
|
const url = p.url();
|
|
if (!url.includes("login")) {
|
|
console.log(`\n ✅ [${i}s] Redirected to: ${url}`);
|
|
break;
|
|
}
|
|
}
|
|
|
|
const finalUrl = p.url();
|
|
console.log(`\n📍 Final URL: ${finalUrl}`);
|
|
|
|
if (finalUrl.includes("/dashboard")) {
|
|
console.log("✅✅✅ SUCCESS! User is on dashboard!\n");
|
|
const content = await p.content();
|
|
if (content.includes("관리자 대시보드")) {
|
|
console.log("✅ Dashboard content confirmed!");
|
|
}
|
|
} else {
|
|
console.log("❌ Still at: " + finalUrl);
|
|
}
|
|
|
|
await p.screenshot({ path: "./final-success-test.png" });
|
|
|
|
} catch (e) {
|
|
console.error("Error:", e.message);
|
|
}
|
|
|
|
await b.close();
|
|
})();
|