Skip to content

Commit 07c94ee

Browse files
committed
test: 공지사항 e2e 테스트 보완 및 홈 공지 팝업 e2e 테스트 추가(#283)
- 공지 목록의 제목, 날짜 포맷 검증 - 홈 진입시 활성 공지 팝업 표시 확인 - 확인 클릭 후 dismiss 쿠키 설정으로 재진입시 팝업 미표시 확인
1 parent 491aa4d commit 07c94ee

2 files changed

Lines changed: 107 additions & 0 deletions

File tree

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
import { test, expect } from '@playwright/test';
2+
import path from 'path';
3+
4+
// 백엔드 .env.local의 ADMIN_KEY (개발 환경 기본값)
5+
const ADMIN_KEY = process.env.E2E_ADMIN_KEY ?? 'ittda_admin';
6+
const ANNOUNCEMENT_TITLE = 'E2E 테스트 공지사항';
7+
8+
// /api/admin/announcements → Next.js 프록시 → 백엔드 /v1/admin/announcements
9+
async function createAnnouncement(
10+
request: import('@playwright/test').APIRequestContext,
11+
): Promise<string> {
12+
const res = await request.post('/api/admin/announcements', {
13+
headers: { 'x-admin-key': ADMIN_KEY, 'Content-Type': 'application/json' },
14+
data: {
15+
title: ANNOUNCEMENT_TITLE,
16+
content: 'E2E 테스트 중 생성된 공지입니다.',
17+
isActive: true,
18+
},
19+
});
20+
const body = await res.json();
21+
if (!body.data?.id) throw new Error(`공지 생성 실패: ${JSON.stringify(body)}`);
22+
return body.data.id;
23+
}
24+
25+
async function deleteAnnouncement(
26+
request: import('@playwright/test').APIRequestContext,
27+
id: string,
28+
): Promise<void> {
29+
await request.delete(`/api/admin/announcements/${id}`, {
30+
headers: { 'x-admin-key': ADMIN_KEY },
31+
});
32+
}
33+
34+
test.describe('홈 공지사항 팝업', () => {
35+
let announcementId: string;
36+
37+
test.use({ storageState: path.join(__dirname, '.auth/guest.json') });
38+
39+
test.beforeAll(async ({ request }) => {
40+
// isActive: true 생성 시 기존 활성 공지가 자동 비활성화됨
41+
announcementId = await createAnnouncement(request);
42+
});
43+
44+
test.afterAll(async ({ request }) => {
45+
await deleteAnnouncement(request, announcementId);
46+
});
47+
48+
test('활성 공지사항이 있으면 홈 진입 시 팝업 모달이 표시된다', async ({ page }) => {
49+
await page.goto('/');
50+
await expect(
51+
page.getByText(ANNOUNCEMENT_TITLE),
52+
).toBeVisible({ timeout: 8000 });
53+
// 확인 버튼도 함께 표시된다
54+
await expect(page.getByRole('button', { name: '확인' })).toBeVisible();
55+
});
56+
57+
test('"확인" 버튼을 누르면 모달이 닫히고 다시 홈에 와도 팝업이 뜨지 않는다', async ({ page }) => {
58+
// 각 테스트는 test.use({ storageState })로 독립된 컨텍스트를 가지므로
59+
// dismiss 쿠키가 없는 초기 상태로 시작됨
60+
await page.goto('/');
61+
await expect(page.getByText(ANNOUNCEMENT_TITLE)).toBeVisible({ timeout: 8000 });
62+
63+
// 2) 확인 버튼 클릭 → dismiss 쿠키 설정 + router.refresh()
64+
await page.getByRole('button', { name: '확인' }).click();
65+
await expect(page.getByText(ANNOUNCEMENT_TITLE)).not.toBeVisible({ timeout: 5000 });
66+
67+
// 3) 홈 재진입 → 쿠키 기반으로 SSR에서 모달 렌더링 제외
68+
await page.goto('/');
69+
await expect(page.getByText(ANNOUNCEMENT_TITLE)).not.toBeVisible({ timeout: 5000 });
70+
});
71+
});

frontend/e2e/announcements.spec.ts

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,4 +35,40 @@ test.describe('공지사항', () => {
3535
// /profile로 이동하거나 브라우저 히스토리의 이전 페이지로 이동
3636
await expect(page).toHaveURL(/\/(profile|announcements)/, { timeout: 3000 });
3737
});
38+
39+
test('공지사항이 있을 때 각 항목에 제목과 날짜가 표시된다', async ({ page }) => {
40+
await page.goto('/announcements');
41+
42+
// 빈 상태면 건너뜀
43+
const isEmpty = await page
44+
.getByText('공지사항이 없습니다.')
45+
.isVisible({ timeout: 3000 })
46+
.catch(() => false);
47+
if (isEmpty) {
48+
test.skip();
49+
return;
50+
}
51+
52+
const firstCard = page.locator('main > div').first();
53+
// 제목 — h3 태그
54+
await expect(firstCard.locator('h3')).toBeVisible({ timeout: 8000 });
55+
await expect(firstCard.locator('h3')).not.toBeEmpty();
56+
// 날짜 — formatKoreanDate가 '년' 포함
57+
await expect(firstCard.getByText(/\d{4}/)).toBeVisible();
58+
});
59+
60+
test('진행 중인 공지에는 "진행 중" 배지가 표시된다', async ({ page }) => {
61+
await page.goto('/announcements');
62+
63+
const badge = page.getByText('진행 중');
64+
const hasBadge = await badge.isVisible({ timeout: 3000 }).catch(() => false);
65+
66+
if (!hasBadge) {
67+
// 현재 활성 공지가 없는 환경이면 건너뜀
68+
test.skip();
69+
return;
70+
}
71+
72+
await expect(badge.first()).toBeVisible();
73+
});
3874
});

0 commit comments

Comments
 (0)