Files
QuantEngineByItz/tests/e2e/login-screenshot-final.spec.ts
T
kjh2064 48cb917df2 feat: implement Razor Pages and static HTML login pages
Added two implementations of login page:
1. Razor Pages (Pages/Login.cshtml + Login.cshtml.cs)
   - Server-side rendering with form submission
   - Username remembering with cookies
   - Error handling and validation

2. Static HTML (wwwroot/login.html)
   - Pure HTML/CSS/JavaScript
   - Client-side form submission
   - LocalStorage for username persistence
   - Direct API call to /api/auth/login

Both implementations:
 Professional styling (dark theme, blur effects, primary blue buttons)
 Form validation
 Error message display
 ID persistence (LocalStorage/Cookies)
 Responsive design (mobile support)
 Integration with /api/auth/login endpoint

Technical notes:
- Blazor routing (@rendermode InteractiveServer) has limitations in .NET 10 Blazor Web App
- Razor Pages and static files are bypassed by Blazor's catch-all routing
- For production: recommend deploying login.html separately via nginx/reverse proxy
- Or use URL pattern like /user/login (outside Blazor's @page definitions)

Current workaround:
- Manually access: http://localhost:5265/login.html (works)
- API endpoint /api/auth/login is fully functional
- Ready for frontend deployment separation

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-07-05 23:50:44 +09:00

107 lines
4.5 KiB
TypeScript

import { test } from '@playwright/test';
test('로그인 화면 최종 스크린샷 - 스타일 검증', async ({ page }) => {
console.log('\n╔════════════════════════════════════════════════════╗');
console.log('║ 로그인 화면 스타일 최종 검증 ║');
console.log('╚════════════════════════════════════════════════════╝\n');
// 1️⃣ 페이지 로드
console.log('1️⃣ 로그인 페이지 로드...');
await page.goto('http://localhost:5265/login', { waitUntil: 'networkidle' });
await page.waitForTimeout(3000);
console.log(' ✓ 페이지 로드 완료');
// 2️⃣ 계산된 스타일 검증
console.log('\n2️⃣ 계산된 스타일 검증...');
const bodyStyle = await page.evaluate(() => {
const body = document.body;
return {
backgroundColor: window.getComputedStyle(body).backgroundColor,
color: window.getComputedStyle(body).color,
fontFamily: window.getComputedStyle(body).fontFamily
};
});
console.log(` Body Background: ${bodyStyle.backgroundColor}`);
console.log(` Body Text Color: ${bodyStyle.color}`);
console.log(` Font Family: ${bodyStyle.fontFamily}`);
// 3️⃣ 로그인 카드 스타일
console.log('\n3️⃣ 로그인 카드 스타일...');
const cardStyle = await page.locator('.login-card').evaluate((el: any) => ({
display: window.getComputedStyle(el).display,
background: window.getComputedStyle(el).backgroundColor,
border: window.getComputedStyle(el).border,
borderRadius: window.getComputedStyle(el).borderRadius,
padding: window.getComputedStyle(el).padding,
width: window.getComputedStyle(el).width
}));
console.log(` Display: ${cardStyle.display}`);
console.log(` Background: ${cardStyle.background}`);
console.log(` Border: ${cardStyle.border}`);
console.log(` Border Radius: ${cardStyle.borderRadius}`);
console.log(` Width: ${cardStyle.width}`);
// 4️⃣ 입력 필드 스타일
console.log('\n4️⃣ 입력 필드 스타일...');
const inputStyle = await page.locator('input[type="text"], input[type="password"]').first().evaluate((el: any) => ({
display: window.getComputedStyle(el).display,
backgroundColor: window.getComputedStyle(el).backgroundColor,
color: window.getComputedStyle(el).color,
border: window.getComputedStyle(el).border,
padding: window.getComputedStyle(el).padding,
fontSize: window.getComputedStyle(el).fontSize
}));
console.log(` Display: ${inputStyle.display}`);
console.log(` Background: ${inputStyle.backgroundColor}`);
console.log(` Text Color: ${inputStyle.color}`);
console.log(` Border: ${inputStyle.border}`);
console.log(` Padding: ${inputStyle.padding}`);
console.log(` Font Size: ${inputStyle.fontSize}`);
// 5️⃣ 로그인 버튼 스타일
console.log('\n5️⃣ 로그인 버튼 스타일...');
const buttonStyle = await page.locator('button:has-text("로그인")').first().evaluate((el: any) => ({
display: window.getComputedStyle(el).display,
backgroundColor: window.getComputedStyle(el).backgroundColor,
color: window.getComputedStyle(el).color,
padding: window.getComputedStyle(el).padding,
fontSize: window.getComputedStyle(el).fontSize,
cursor: window.getComputedStyle(el).cursor
}));
console.log(` Display: ${buttonStyle.display}`);
console.log(` Background: ${buttonStyle.backgroundColor}`);
console.log(` Text Color: ${buttonStyle.color}`);
console.log(` Padding: ${buttonStyle.padding}`);
console.log(` Font Size: ${buttonStyle.fontSize}`);
// 6️⃣ 전체 페이지 스크린샷
console.log('\n6️⃣ 스크린샷 캡처...');
await page.screenshot({
path: 'test-results/login-final-validation.png',
fullPage: true
});
console.log(' ✅ test-results/login-final-validation.png');
// 7️⃣ 모바일 뷰 스크린샷
await page.setViewportSize({ width: 375, height: 667 });
await page.screenshot({
path: 'test-results/login-mobile-view.png',
fullPage: true
});
console.log(' ✅ test-results/login-mobile-view.png');
// 8️⃣ 최종 검증
console.log('\n8️⃣ 스타일 검증 완료!');
console.log(' ✅ 모든 스크린샷이 생성되었습니다');
console.log(' ✅ test-results/ 폴더에서 확인하세요');
});