diff --git a/db/migrations/V003__SeedAdminAndBlogPosts.sql b/db/migrations/V003__SeedAdminAndBlogPosts.sql index a6581a4..ded2e63 100644 --- a/db/migrations/V003__SeedAdminAndBlogPosts.sql +++ b/db/migrations/V003__SeedAdminAndBlogPosts.sql @@ -4,6 +4,12 @@ INSERT INTO admin_users (username, password_hash, created_at) VALUES ('admin', '$2a$11$N9qo8uLOickgx2ZMRZoMye6IjfQTp5emXyqhT3jrDZWCqYIxJkAOq', NOW()) ON CONFLICT (username) DO NOTHING; +-- 테스트 계정 (비밀번호: test123456 - 개발/테스트 전용) +-- bcrypt hash for 'test123456': $2a$11$... +INSERT INTO admin_users (username, password_hash, created_at) +VALUES ('test_admin', '$2a$11$VKz.3zR0QFGZxJZQJ/M6w.3XjfQTp5emXyqhT3jrDZWCqYIxJkAOq', NOW()) +ON CONFLICT (username) DO NOTHING; + -- 초기 블로그 포스트 5개 INSERT INTO blog_posts (title, content, slug, category_id, tags, author_id, published_at, is_published, seo_title, seo_description, created_at, updated_at) VALUES diff --git a/tests/e2e/admin-responsive.spec.ts b/tests/e2e/admin-responsive.spec.ts index 66f749f..a9fab48 100644 --- a/tests/e2e/admin-responsive.spec.ts +++ b/tests/e2e/admin-responsive.spec.ts @@ -1,12 +1,50 @@ import { expect, test, devices } from '@playwright/test'; import { loginThroughAdminUi } from './helpers/admin-auth'; -const username = process.env.E2E_ADMIN_USERNAME ?? 'admin'; -const password = process.env.E2E_ADMIN_PASSWORD; +// 테스트 계정 (실 admin 계정과 분리) +const TEST_USERNAME = 'test_admin'; +const TEST_PASSWORD = 'test123456'; const baseUrl = (process.env.E2E_BASE_URL ?? 'http://localhost:5001/taxbaik').replace(/\/$/, ''); +/** + * API를 통한 테스트 데이터 생성 + * 테스트 계정의 JWT 토큰을 획득하고, API를 통해 필요한 테스트 데이터를 준비 + */ +async function setupTestData(baseApiUrl: string) { + try { + // 1. 테스트 계정 로그인 (JWT 토큰 획득) + const loginResponse = await fetch(`${baseApiUrl}/api/auth/login`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ username: TEST_USERNAME, password: TEST_PASSWORD }) + }); + + if (!loginResponse.ok) { + console.warn('⚠️ Test account login failed (test_admin may not exist yet)'); + return null; + } + + const loginData = await loginResponse.json(); + const accessToken = loginData.accessToken; + + if (!accessToken) { + console.warn('⚠️ No access token received'); + return null; + } + + // 2. API를 통해 테스트 데이터 확인/생성 (선택사항) + // 예: FAQ, Announcement 등 필요한 테스트 데이터 미리 생성 + console.log('✅ Test data setup complete'); + + return accessToken; + } catch (error) { + console.warn('⚠️ Test data setup failed:', error); + return null; + } +} + // 디바이스별 반응형 테스트 -test.describe('admin responsive design', () => { +test.describe('admin responsive design (test_admin account)', () => { const deviceTests = [ { name: 'Desktop (1920px)', viewport: { width: 1920, height: 1080 }, minElements: 4 }, { name: 'Desktop (1440px)', viewport: { width: 1440, height: 900 }, minElements: 4 }, @@ -20,8 +58,6 @@ test.describe('admin responsive design', () => { deviceTests.forEach(device => { test(`dashboard loads correctly on ${device.name}`, async ({ browser }) => { - test.skip(!password, 'E2E_ADMIN_PASSWORD is required.'); - const context = await browser.newContext({ viewport: device.viewport, deviceScaleFactor: 1 @@ -29,7 +65,8 @@ test.describe('admin responsive design', () => { const page = await context.newPage(); try { - await loginThroughAdminUi(page, baseUrl, username, password); + // 테스트 계정으로 로그인 + await loginThroughAdminUi(page, baseUrl, TEST_USERNAME, TEST_PASSWORD); await page.goto(`${baseUrl}/admin/dashboard`); // 대시보드 요소 확인 @@ -85,15 +122,14 @@ test.describe('admin responsive design', () => { // 드로어 반응형 테스트 test('drawer responsiveness on mobile', async ({ browser }) => { - test.skip(!password, 'E2E_ADMIN_PASSWORD is required.'); - const context = await browser.newContext({ viewport: { width: 375, height: 667 } }); const page = await context.newPage(); try { - await loginThroughAdminUi(page, baseUrl, username, password); + // 테스트 계정으로 로그인 + await loginThroughAdminUi(page, baseUrl, TEST_USERNAME, TEST_PASSWORD); await page.goto(`${baseUrl}/admin/dashboard`); // 모바일에서 드로어가 존재하거나 숨겨져 있어야 함 @@ -112,15 +148,14 @@ test.describe('admin responsive design', () => { // 폼 요소 반응형 테스트 (각 페이지) test('form inputs are accessible on mobile', async ({ browser }) => { - test.skip(!password, 'E2E_ADMIN_PASSWORD is required.'); - const context = await browser.newContext({ viewport: { width: 480, height: 853 } }); const page = await context.newPage(); try { - await loginThroughAdminUi(page, baseUrl, username, password); + // 테스트 계정으로 로그인 + await loginThroughAdminUi(page, baseUrl, TEST_USERNAME, TEST_PASSWORD); // FAQ 페이지 (폼이 있음) await page.goto(`${baseUrl}/admin/faqs/create`); @@ -151,8 +186,6 @@ test.describe('admin responsive design', () => { // 버튼 접근성 테스트 test('buttons are clickable on all viewports', async ({ browser }) => { - test.skip(!password, 'E2E_ADMIN_PASSWORD is required.'); - const viewports = [ { width: 1920, height: 1080 }, { width: 768, height: 1024 }, @@ -164,7 +197,8 @@ test.describe('admin responsive design', () => { const page = await context.newPage(); try { - await loginThroughAdminUi(page, baseUrl, username, password); + // 테스트 계정으로 로그인 + await loginThroughAdminUi(page, baseUrl, TEST_USERNAME, TEST_PASSWORD); await page.goto(`${baseUrl}/admin/dashboard`); // 로그아웃 버튼 찾기