구현할 기능
솔로 토너먼트 핵심 여정(생성 → 아이템 추가 → 매치 진행 → 영수증 결과)에 대한 Playwright E2E 테스트를 도입한다.
범위
- 해피패스 + 핵심 가드
- 아이템 추가는 위시에서 가져오기(by-wish) 방식으로 검증
구조 제약과 결정
match / result 페이지는 RSC가 서버사이드에서 getTournament을 직접 호출하는데, SSR 목 스텁(mockApiServer.ts)은 경로당 응답이 실행 내내 고정이다.
같은 GET /tournaments/{id}가 단계별로 PENDING → IN_PROGRESS → COMPLETED로 변해야 하므로,
단계별로 토너먼트 id를 분리해 3개 spec으로 작성한다 (목 서버 무변경).
| id |
상태 |
단계 |
| 1 |
PENDING |
생성·아이템 담기 단계 (기존 목 재사용) |
| 2 |
IN_PROGRESS |
매치 단계 |
| 3 |
COMPLETED |
결과 단계 |
작업 상세 내용
1. 목 데이터
2. fixture 확장
3. SSR 목 추가
[`GET ${ENDPOINTS.TOURNAMENT(2)}`]: createApiSuccess(MOCK_TOURNAMENT_IN_PROGRESS),
[`GET ${ENDPOINTS.TOURNAMENT(3)}`]: createApiSuccess(MOCK_TOURNAMENT_COMPLETED),
- id 2를 IN_PROGRESS로 주면 match RSC의 PENDING 분기(SSR
POST /start)를 타지 않아 목이 단순해짐
4. 테스트 spec 3개 (e2e/specs/tournament/)
A. tournamentItemAdd.spec.ts — 생성 + 담기 + 시작 가드 (id 1)
B. tournamentMatch.spec.ts — 매치 진행 (id 2)
C. tournamentResult.spec.ts — 영수증 결과 (id 3)
구현할 기능
솔로 토너먼트 핵심 여정(생성 → 아이템 추가 → 매치 진행 → 영수증 결과)에 대한 Playwright E2E 테스트를 도입한다.
범위
구조 제약과 결정
match/result페이지는 RSC가 서버사이드에서getTournament을 직접 호출하는데, SSR 목 스텁(mockApiServer.ts)은 경로당 응답이 실행 내내 고정이다.같은
GET /tournaments/{id}가 단계별로PENDING → IN_PROGRESS → COMPLETED로 변해야 하므로,단계별로 토너먼트 id를 분리해 3개 spec으로 작성한다 (목 서버 무변경).
PENDINGIN_PROGRESSCOMPLETED작업 상세 내용
1. 목 데이터
e2e/mocks/tournament.ts확장MOCK_TOURNAMENT_ITEMS:TournamentItemT[]4개 (READY 상태, 가격 상이,MOCK_IMAGE_URLS사용)MOCK_TOURNAMENT_PENDING_WITH_ITEMS: id 1,pending.items에 4개 (by-wish 담기 후 재조회 응답용)MOCK_TOURNAMENT_PENDING_3ITEMS: 부전승 모달 가드용 (3개 = 2의 거듭제곱 아님)MOCK_TOURNAMENT_IN_PROGRESS: id 2,GetTournamentInProgressResponseT(currentRound: 4,lastHistory: null,remainingItems4개)MOCK_TOURNAMENT_COMPLETED: id 3,GetTournamentCompletedResponseT(result4개,hasGroupResult: false)e2e/mocks/wish.ts신규 — by-wish 페이지용 위시 4개 (getWishlist원 응답 형태{ wish, item }[])e2e/mocks/me.ts에MOCK_MEMBER_ME추가 — by-wish 진입은 MEMBER에게만 노출되므로 담기 spec에서GET /users/me를 멤버로 목킹images.ts의MOCK_IMAGE_URLS/MOCK_IMAGE_MAP에 product 항목 추가2. fixture 확장
e2e/fixtures/mockApiFixture.ts에api.getPage(path, data, pageResponse?)메서드 추가{ nextCursor: null, hasNext: false }getWishlist가 응답 최상위pageResponse를 읽는데 기존api.get은createApiSuccess(data)만 래핑하므로 필요3. SSR 목 추가
e2e/setup/mockApiServer.ts의SSR_MOCK_ROUTES에 추가POST /start)를 타지 않아 목이 단순해짐4. 테스트 spec 3개 (
e2e/specs/tournament/)A.
tournamentItemAdd.spec.ts— 생성 + 담기 + 시작 가드 (id 1)새 토너먼트 만들기→ 이름 입력(빈 값이면 버튼 비활성 확인) →POST /tournaments목 →/tournament/1/create도착위시에서 가져오기→/tournament/1/create/by-wish→ 위시 4개 선택(선택 전 다음 버튼 비활성) → 담기POST /items/wish→ create 복귀,4/32라벨 + 아이템 4개 렌더 확인GET TOURNAMENT(1)을MOCK_TOURNAMENT_PENDING_WITH_ITEMS로 재등록MOCK_TOURNAMENT_PENDING) → 시작 버튼toBeDisabled+최소 2개 이상 담아주세요라벨ByeWarningDialog문구 노출POST /start목 →toHaveURL(/tournament/1/loading)B.
tournamentMatch.spec.ts— 매치 진행 (id 2)/tournament/2/match직접 진입 (SSR IN_PROGRESS 목 응답)POST /matches목: null 응답)POST /matches목:{ result: [...] }응답)page.waitForRequest로 결승 기록 요청(payload의selectedTournamentItemId)이 나갔는지 단언/result로 push되지만 id 2 SSR이 IN_PROGRESS라 서버가 match로 되돌림 — URL 전환은 이 spec에서 검증하지 않음 (spec 주석으로 명시)pairItems.ts) → "특정 상품이 왼쪽" 같은 순서 의존 단언 금지, "카드 2개 중 첫 번째 클릭" + 이름 존재 여부로 검증C.
tournamentResult.spec.ts— 영수증 결과 (id 3)/tournament/3/result직접 진입 (SSR COMPLETED 목)영수증 저장버튼 노출 확인 (클릭 X)isRoot && isOwner→ 노출; 클릭 X)홈으로링크 클릭 →/home도착