fix: enable WASM-first auth flow for dashboard
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>
This commit is contained in:
@@ -0,0 +1,68 @@
|
||||
import { chromium } from "@playwright/test";
|
||||
|
||||
(async () => {
|
||||
console.log("════════════════════════════════════════════════════════");
|
||||
console.log(" ✅ FINAL TEST - @rendermode InteractiveWebAssembly");
|
||||
console.log("════════════════════════════════════════════════════════\n");
|
||||
|
||||
const b = await chromium.launch({ headless: false });
|
||||
const p = await b.newPage();
|
||||
|
||||
p.on("console", msg => {
|
||||
const text = msg.text();
|
||||
if (text.includes("[") && text.includes("]")) {
|
||||
console.log(" 📝 " + text);
|
||||
}
|
||||
});
|
||||
|
||||
try {
|
||||
console.log("1️⃣ 로그인 페이지 로드");
|
||||
await p.goto("http://localhost:5265/login.html");
|
||||
|
||||
console.log("2️⃣ 로그인 (admin/admin)");
|
||||
await p.fill("input[name='username']", "admin");
|
||||
await p.fill("input[name='password']", "admin");
|
||||
await p.click("button[type='submit']");
|
||||
|
||||
console.log("3️⃣ 모니터링 (10초)\n");
|
||||
let redirected = false;
|
||||
for (let i = 1; i <= 10; i++) {
|
||||
await new Promise(r => setTimeout(r, 1000));
|
||||
const url = p.url();
|
||||
if (!url.includes("login")) {
|
||||
console.log(`\n ✅ [${i}s] 리다이렉트됨!`);
|
||||
console.log(` URL: ${url}`);
|
||||
redirected = true;
|
||||
break;
|
||||
}
|
||||
process.stdout.write(` [${i}s] ${url}\r`);
|
||||
}
|
||||
|
||||
const finalUrl = p.url();
|
||||
|
||||
if (finalUrl.includes("/dashboard")) {
|
||||
console.log("\n\n✅✅✅ 성공! 대시보드에 도착했습니다!\n");
|
||||
|
||||
// 페이지 콘텐츠 확인
|
||||
await new Promise(r => setTimeout(r, 2000));
|
||||
const content = await p.content();
|
||||
|
||||
if (content.includes("관리자 대시보드")) {
|
||||
console.log("✅ 대시보드 콘텐츠 확인됨!\n");
|
||||
console.log("🎉 로그인 완성! 인증 흐름 정상 작동!\n");
|
||||
} else {
|
||||
console.log("⚠️ 대시보드 콘텐츠 미확인\n");
|
||||
}
|
||||
} else {
|
||||
console.log(`\n❌ 아직도 ${finalUrl}에 있습니다\n`);
|
||||
}
|
||||
|
||||
await p.screenshot({ path: "./ultimate-test-result.png", fullPage: true });
|
||||
console.log("📷 스크린샷: ultimate-test-result.png");
|
||||
|
||||
} catch (e) {
|
||||
console.error("❌ Error:", e.message);
|
||||
}
|
||||
|
||||
await b.close();
|
||||
})();
|
||||
Reference in New Issue
Block a user