Skip to content

test: 솔로 토너먼트 E2E 테스트 시나리오 도입 #388

Description

@kanghaeun

구현할 기능

솔로 토너먼트 핵심 여정(생성 → 아이템 추가 → 매치 진행 → 영수증 결과)에 대한 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. 목 데이터

  • 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, remainingItems 4개)
    • MOCK_TOURNAMENT_COMPLETED: id 3, GetTournamentCompletedResponseT (result 4개, hasGroupResult: false)
  • e2e/mocks/wish.ts 신규 — by-wish 페이지용 위시 4개 (getWishlist 원 응답 형태 { wish, item }[])
  • e2e/mocks/me.tsMOCK_MEMBER_ME 추가 — by-wish 진입은 MEMBER에게만 노출되므로 담기 spec에서 GET /users/me를 멤버로 목킹
  • 필요 시 images.tsMOCK_IMAGE_URLS / MOCK_IMAGE_MAP에 product 항목 추가
  • 타입은 전부 실제 응답 타입을 import해 선언 (README 규칙 준수)

2. fixture 확장

  • e2e/fixtures/mockApiFixture.tsapi.getPage(path, data, pageResponse?) 메서드 추가
    • 기본값: { nextCursor: null, hasNext: false }
    • getWishlist가 응답 최상위 pageResponse를 읽는데 기존 api.getcreateApiSuccess(data)만 래핑하므로 필요

3. SSR 목 추가

  • e2e/setup/mockApiServer.tsSSR_MOCK_ROUTES에 추가
  [`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)

  • 생성: 홈 → 새 토너먼트 만들기 → 이름 입력(빈 값이면 버튼 비활성 확인) → POST /tournaments 목 → /tournament/1/create 도착
  • by-wish 담기: create 페이지(멤버 목) → 아이템 추가 → 위시에서 가져오기/tournament/1/create/by-wish → 위시 4개 선택(선택 전 다음 버튼 비활성) → 담기 POST /items/wish → create 복귀, 4/32 라벨 + 아이템 4개 렌더 확인
    • 담기 직전 GET TOURNAMENT(1)MOCK_TOURNAMENT_PENDING_WITH_ITEMS로 재등록
  • 가드 — 시작 불가: 아이템 0개(MOCK_TOURNAMENT_PENDING) → 시작 버튼 toBeDisabled + 최소 2개 이상 담아주세요 라벨
  • 가드 — 부전승: 아이템 3개 → 시작 클릭 → ByeWarningDialog 문구 노출
  • 시작 성공: 아이템 4개 → 시작 → POST /start 목 → toHaveURL(/tournament/1/loading)
    • loading → match 자동 전환은 검증하지 않음 (id 1 SSR이 PENDING이라 match 진입 불가)

B. tournamentMatch.spec.ts — 매치 진행 (id 2)

  • /tournament/2/match 직접 진입 (SSR IN_PROGRESS 목 응답)
  • 4강 배지 + 좌/우 상품 카드 2개 노출 → 카드 선택 ×2 (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 목)
  • 영수증에 1위 상품명·순위 목록 렌더 확인 (영수증 뽑기 애니메이션 ~2초는 auto-waiting으로 흡수)
  • 영수증 저장 버튼 노출 확인 (클릭 X)
  • 공유(플레이 링크) 버튼 노출 확인 (isRoot && isOwner → 노출; 클릭 X)
  • 홈으로 링크 클릭 → /home 도착

Metadata

Metadata

Assignees

Labels

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions