import { test, expect } from '@playwright/test'; test.describe('관리자 페이지 플로우 테스트', () => { test.beforeEach(async ({ page }) => { // 로그인 페이지로 이동 await page.goto('/Account/Login'); await page.waitForLoadState('domcontentloaded'); // 로그인 수행 (admin/quant123! 자격증명 — CLAUDE.md "Mandatory Pre-Deployment Checklist" 참조. // "admin/admin"은 실제 시드 비밀번호(V4 마이그레이션)와 불일치해 로그인 실패를 유발하던 버그였음. const usernameInput = page.locator('#username'); const passwordInput = page.locator('#password'); const loginButton = page.locator('#loginBtn'); await usernameInput.fill('admin'); await passwordInput.fill('quant123!'); await loginButton.click(); // 로그인 후 페이지 로드 대기 await page.waitForLoadState('domcontentloaded'); }); test('대시보드 페이지 접근 및 렌더링', async ({ page }) => { console.log('\n=== 대시보드 페이지 테스트 ==='); // 대시보드 접근 await page.goto('/Admin/Dashboard'); await page.waitForLoadState('domcontentloaded'); // 페이지 타이틀 확인 const title = await page.title(); expect(title).toContain('대시보드'); console.log('✓ 대시보드 페이지 렌더링 완료'); }); test('사용자 목록 페이지 접근', async ({ page }) => { console.log('\n=== 사용자 목록 페이지 테스트 ==='); // 사용자 목록 페이지 접근 await page.goto('/Admin/Users'); await page.waitForLoadState('domcontentloaded'); // 페이지 타이틀 확인 const title = await page.title(); expect(title).toContain('사용자'); // 테이블 확인 const table = page.locator('table'); await expect(table).toBeVisible(); console.log('✓ 사용자 목록 페이지 렌더링 완료'); }); test('사용자 생성 폼 접근', async ({ page }) => { console.log('\n=== 사용자 생성 폼 테스트 ==='); // 사용자 생성 페이지 접근 await page.goto('/Admin/Users/Create'); await page.waitForLoadState('domcontentloaded'); // 페이지 타이틀 확인 (실제 렌더링 타이틀: "새 사용자 추가 - QuantEngine") const title = await page.title(); expect(title).toContain('사용자 추가'); // 폼 필드 확인 const usernameField = page.locator('input[name="username"]'); const passwordField = page.locator('input[name="password"]'); const submitButton = page.locator('button[type="submit"]'); await expect(usernameField).toBeVisible(); await expect(passwordField).toBeVisible(); await expect(submitButton).toBeVisible(); console.log('✓ 사용자 생성 폼 렌더링 완료'); }); test('수집 모니터링 페이지 접근', async ({ page }) => { console.log('\n=== 수집 모니터링 페이지 테스트 ==='); // 수집 페이지 접근 await page.goto('/Admin/Collection'); await page.waitForLoadState('domcontentloaded'); // 페이지 타이틀 확인 const title = await page.title(); expect(title).toContain('수집'); // 테이블이나 콘텐츠 확인 const card = page.locator('.card'); await expect(card).toBeVisible(); console.log('✓ 수집 모니터링 페이지 렌더링 완료'); }); test('로그아웃 기능', async ({ page }) => { console.log('\n=== 로그아웃 테스트 ==='); // 대시보드 접근 (로그인 상태) await page.goto('/Admin/Dashboard'); await page.waitForLoadState('domcontentloaded'); // 로그아웃 버튼 찾기 및 클릭 const logoutButton = page.locator('a:has-text("로그아웃")', { exact: true }); if (await logoutButton.isVisible()) { await logoutButton.click(); await page.waitForLoadState('domcontentloaded'); } else { // 대체로 form submit 기반 로그아웃 const logoutLink = page.locator('a[href*="/Account/Logout"]'); if (await logoutLink.isVisible()) { await logoutLink.click(); await page.waitForLoadState('domcontentloaded'); } } // 로그아웃 후 현재 URL 확인 const currentUrl = page.url(); expect( currentUrl.includes('/Account/Login') || currentUrl.includes('/Account/AccessDenied') || !currentUrl.includes('/Admin') ).toBeTruthy(); console.log('✓ 로그아웃 기능 작동 확인'); }); test('인증 없이 관리자 페이지 접근 불가', async ({ page }) => { console.log('\n=== 인증 없이 관리자 페이지 접근 테스트 ==='); // 새 context에서 쿠키 없이 접근 const context = await page.context().browser()?.newContext(); if (!context) { console.log('⚠️ 새 context 생성 실패, 테스트 스킵'); return; } const unauthorizedPage = await context.newPage(); // 인증 없이 관리자 페이지 접근 시도 await unauthorizedPage.goto('/Admin/Dashboard'); await unauthorizedPage.waitForLoadState('domcontentloaded'); // 로그인 페이지로 리다이렉트되어야 함 const finalUrl = unauthorizedPage.url(); expect(finalUrl).toContain('/Account/Login'); await unauthorizedPage.close(); await context.close(); console.log('✓ 인증 없이 관리자 페이지 접근 제어 확인'); }); });