Skip to content

feat: add playwright e2e tests with ci - #7

Merged
pangil5634 merged 26 commits into
mainfrom
feat/e2e-playwright
Oct 27, 2026
Merged

pangil5634 merged 26 commits into
mainfrom
feat/e2e-playwright

Conversation

@pangil5634

Copy link
Copy Markdown
Member

무엇을 했나

Playwright 로 화면별·기능별 E2E 테스트를 만들고, PR 과 main 푸시마다 도는 CI 를 붙였습니다.

  • Firebase 에뮬레이터(auth, firestore) 위에서 돌아 실제 프로젝트에 닿지 않습니다. 비밀값이 필요 없습니다.
  • 테스트마다 새 사용자를 써서 병렬로 돌려도 데이터가 섞이지 않습니다.
  • 케이스 목록(e2e/cases/*.md)이 기준이고, spec 은 같은 ID(TC-HOME-002 등)로 이어집니다.
  • P1 22건과 스모크·회귀 케이스를 구현했습니다. 데스크톱과 모바일(Pixel 7) 크기로 74개가 돕니다.

실행: npm run e2e (전체), npm run e2e:ui (Playwright UI). JDK 21 이상이 필요합니다. 자세한 내용은 e2e/README.md.

테스트로 찾아 고친 버그

  • 저장이 실패하면 집계 복구도 실패해 완료 체크 실패 알림이 뜨지 않던 문제
  • 카테고리 색을 바꿔도 홈 주간 루틴 표에 옛 색이 남던 문제 (캐시 무효화 누락)
  • 한 주 보기가 할 일에 복사된 옛 카테고리 색을 영구히 그리던 문제
  • 그 달의 월간 통계를 처음 만드는 사이의 할 일 추가·체크가 집계에서 영구히 빠지던 문제

회귀 케이스는 고친 코드를 되돌리면 실패하는 것을 확인했습니다.

함께 바꾼 것

  • 할 일 삭제, 루틴 삭제, 카테고리 종료에 확인 창을 넣었습니다.
  • 확인 버튼이 처리 중으로 바뀔 때 생기던 잔상, 모달 안을 길게 누르면 뒤의 목록 끌기가 시작되던 문제를 고쳤습니다.
  • 할 일 체크·추가·상세, 루틴 표, 캘린더 칸, 날짜 선택기, 모달 등에 접근 가능한 이름을 붙였습니다. 클릭만 되던 div 는 버튼이 됐습니다.
  • firebase-tools 를 개발 의존성으로 고정했습니다.

남은 일

e2e/TODO.md 에 정리했습니다. 이름 없는 요소 5곳, seed 확장, 그리고 부하가 클 때 한 번 관찰한 "다시 받아 온 집계가 진행 중인 체크 표시를 덮는" 동작입니다.

주간 표에서 할 일을 끌 때 손을 따라 그리는 카드가 항상 미완료로 보이던 문제를 고쳤습니다.
드래그 데이터에 완료 여부를 함께 실어 끌리는 카드도 원래 체크 상태를 유지합니다.
루틴 순서 저장이 끝나면 기록 화면이 읽는 루틴 목록 캐시의 orderIndex 도 새 차례로 고칩니다.
캐시가 낡았다고 표시되지 않아 기록 화면에 옛 순서가 남던 문제를 서버를 다시 읽지 않고 해결했습니다.
vite --mode e2e 로 띄울 때만 Auth·Firestore 에뮬레이터에 붙도록 했습니다.
실제 Google 팝업은 자동화할 수 없어, 에뮬레이터가 받아 주는 가짜 Google 토큰으로 로그인하는 통로를 같은 조건에서만 엽니다.
.env.e2e 가 프로젝트를 demo-checky 로 덮어써 테스트가 운영 데이터에 닿지 않게 하고, firebase.json 에 Auth 에뮬레이터 포트를 추가했습니다.
배포 빌드는 mode 가 production 이라 이 코드가 번들에 들어가지 않습니다.
Playwright 를 들여와 npm run e2e 와 npm run e2e:ui 로 에뮬레이터 위에서 E2E 테스트를 돌립니다.
테스트마다 새 사용자로 로그인해 병렬로 돌려도 데이터가 섞이지 않고, 콘솔 에러가 나면 테스트를 실패시킵니다.
로그인 전후 화면이 열리는지 보는 스모크 케이스를 데스크톱과 모바일 크기로 추가했습니다.
케이스 목록(e2e/cases)과 작성 규칙(e2e/README.md)을 함께 두었습니다.
테스트 시작 데이터를 에뮬레이터 REST API 로 바로 넣는 seed 도우미를 추가했습니다.
Firebase SDK 는 Playwright 프로세스 안에서 gRPC 모듈 로딩 에러를 내 쓰지 않습니다.
가짜 Google 토큰의 sub 와 Firebase uid 가 달라, 테스트용 로그인 통로가 실제 uid 를 돌려주도록 고쳤습니다.
150ms 이상 눌러야 시작하는 dnd-kit 끌기를 재현하는 drag 도우미와, 화면의 오늘 날짜를 고정하는 today 옵션을 추가했습니다.
루틴 순서 변경이 기록 화면에 반영되는지, 완료한 할 일을 끄는 동안 체크 표시가 유지되는지 확인하는 회귀 케이스를 추가했습니다.
고친 코드를 되돌리면 두 케이스 모두 실패하는 것을 확인했습니다.
역할도 이름도 없는 끌기 미리보기를 찾을 수 있도록 data-testid 를 달았습니다.
할 일 삭제, 루틴 삭제, 카테고리 종료가 누르는 즉시 실행되던 것을 확인 창을 거치도록 바꿨습니다.
할 일과 루틴은 완료·수행 기록까지 함께 지워져 되돌릴 수 없다고 알리고, 카테고리 종료는 복구할 수 있다고 안내합니다.
취소하면 상세 모달로 돌아가 아무것도 바뀌지 않습니다.
확인 버튼 문구가 처리 중으로 바뀌며 폭이 넓어지면 옆 버튼이 밀리고, 비활성 전환과 겹쳐 밀리기 전 버튼 조각이 잔상으로 남았습니다.
두 문구를 같은 칸에 겹쳐 두고 하나만 보이게 해 폭을 긴 쪽에 고정했습니다.
카테고리 상세 모달은 끌어서 정렬하는 항목 안에서 열려, 모달 안을 길게 누르면 그 항목의 끌기가 시작됐습니다.
항목에 걸린 transform 이 모달의 기준이 되어 모달이 항목 크기로 쪼그라들고, 누른 채 움직이면 순서도 바뀔 수 있었습니다.
모달 바깥으로 누름 이벤트가 올라가지 않게 막았습니다.
홈·카테고리·루틴·기록·마이·공통 화면의 E2E 케이스 후보를 우선순위와 근거 코드와 함께 제안 상태로 정리했습니다.
케이스 구현을 막는 지점(이름 없는 요소, seed 로 만들 수 없는 데이터)을 e2e/TODO.md 에 모았습니다.
…rols

할 일 완료 체크, 할 일 추가, 색상 선택처럼 클릭만 되던 div 를 버튼으로 바꿔 키보드와 스크린 리더로도 쓸 수 있게 했습니다.
할 일·루틴 상세 버튼, 루틴 표 체크, 캘린더 칸, 카테고리 이름과 색 견본에 이름과 선택 상태를 달았습니다.
루틴명 레이블을 입력란과 연결하고, 모든 모달이 제목을 대화상자의 이름으로 갖게 했습니다.
E2E 테스트가 이 요소들을 역할과 이름으로 찾을 수 있습니다.
완료 체크 저장이 실패하면 월간 집계를 다시 써서 복구한 뒤 알림을 띄웠습니다.
네트워크가 끊긴 것처럼 쓰기가 막힌 상황에서는 복구도 함께 실패해, 체크가 설명 없이 풀리기만 했습니다.
알림을 먼저 띄우고 집계 복구는 실패해도 넘어가도록 바꿨습니다. 할 일과 루틴 체크에 모두 적용됩니다.
홈의 할 일 추가, 완료 체크, 수정·삭제, 저장 실패, 루틴과 할 일이 겹친 날의 월간 통계 케이스를 추가했습니다.
저장이 끝나기를 기다리는 waitForSaved, 쓰기 실패를 흉내 내는 failWrites, 일부러 낸 에러를 허용하는 expectedError 를 더했습니다.
홈이 시드보다 먼저 월간 통계를 만들지 않도록 로그인은 데이터를 읽지 않는 화면에서 합니다.
동시 수정으로 거절된 뒤 SDK 가 다시 시도한 커밋의 콘솔 기록은 거절된 횟수만큼만 걸러 냅니다.
할 일 상세 모달의 입력란에 이름을 달았습니다.
반복 요일을 바꿔도 이전 기록이 유지되는지, 요일 변경이 홈 주간 표에 반영되는지, 새 루틴이 목록과 홈에 바로 나오는지 확인하는 케이스를 추가했습니다.
기록 화면은 오늘까지만 세어 오늘부터 적용한 변경으로는 회귀를 잡지 못하므로, 해당 확인은 케이스 문서에 메모로 남겼습니다.
홈 주간 루틴 표는 줄마다 분류 이름과 색을 담아 캐시하는데, 분류를 바꿔도 이 캐시는 무효화되지 않았습니다.
홈을 열어 둔 채 분류 색을 바꾸면 캐시가 살아 있는 10분 동안 체크 아이콘이 옛 색으로 보였습니다.
분류 변경 뒤 무효화하는 캐시에 주간 루틴 표를 더했습니다.
할 일 문서에는 만들 때의 분류 색이 복사돼 있어, 한 주 보기는 분류 색을 바꿔도 옛 색을 계속 그렸습니다.
기록 화면과 같이 분류의 지금 색을 쓰고, 분류를 찾지 못할 때만 복사해 둔 색으로 그립니다.
카테고리 생성, 확인 창을 거친 종료, 순서 변경과 이름·색 변경이 홈·루틴·기록 화면에 반영되는지 확인하는 케이스를 추가했습니다.
이름·색 변경 케이스는 홈 주간 루틴 표와 한 주 보기에 옛 색이 남던 두 문제를 지킵니다.
달력에는 앞뒤 달의 날짜도 같은 숫자로 보여, 버튼 이름이 숫자뿐이면 어느 날인지 알 수 없었습니다.
날짜 버튼에 "2026년 9월 30일" 같은 이름과 선택 상태를 달았습니다.
홈에서 할 일·루틴을 체크하거나 할 일을 다른 달로 옮기면 기록 화면이 새로고침 없이 맞게 세는지 확인하는 케이스를 추가했습니다.
오늘 뒤의 날을 세지 않는 규칙과, 일요일에 시작해 두 달에 걸친 주를 합쳐 세는 규칙도 확인합니다.
기록 화면 캐시를 고치는 세 곳을 각각 빼면 해당 케이스가 실패하는 것을 확인했습니다.
그 달의 월간 통계 문서를 처음 만드는 사이에 할 일을 추가하면, 그 할 일이 집계에서 영구히 빠지는 것을 재현했습니다.
수정 방식을 정해야 해 TC-HOME-016 으로 케이스 목록에 올렸습니다.
이 경쟁과 섞여 가끔 실패하던 TC-HOME-004 는 문서가 저장된 뒤에 조작하도록 분리했습니다.
탈퇴, 본인 확인 창을 닫았을 때, 로그아웃, 같은 탭에서 계정을 바꿀 때, 첫 로그인 시 프로필 생성 케이스를 추가했습니다.
탈퇴의 본인 확인은 Auth 에뮬레이터의 계정 선택 창에서 같은 계정을 고르는 것으로 대신합니다.
탈퇴 뒤 데이터가 지워졌는지는 관리자 권한으로 에뮬레이터를 조회하는 inspect 로 확인합니다.
사용자 아래 여섯 컬렉션을 모두 채우도록 루틴 기록 시드를 더했고, 새로고침 없이 로그인하는 signIn({ inPlace }) 를 추가했습니다.
그 달의 월간 통계 문서를 처음 만드는 사이에 할 일을 추가하거나 체크하면, 그 반영은 문서가 없어 건너뛰고
곧이어 저장되는 문서는 조작 전에 센 값이라 조작이 캘린더 집계에서 영구히 빠졌습니다.
문서가 없어 건너뛴 조작을 달마다 세어 두고, 첫 문서를 만든 쪽이 그 수가 바뀌었을 때만 원본에서 다시 셉니다.
문서 없는 달에 하루치 문서를 만들지 않는다는 기존 원칙은 그대로이고, 추가 읽기는 경쟁이 생겼을 때만 일어납니다.
첫 월간 통계 문서 저장을 붙잡아 그 사이에 할 일 추가와 루틴 체크를 끼워 넣고, 새로고침 뒤 집계가 맞는지 확인합니다.
수정 전에는 두 경우 모두 실패하는 것을 확인했습니다.
로컬과 CI 가 같은 에뮬레이터를 쓰도록 firebase-tools 를 개발 의존성으로 고정했습니다.
에뮬레이터를 거치는 저장·조회가 PC 부하에 따라 늦어져 화면 확인 대기 시간을 10초로 늘렸습니다.
탈퇴 본인 확인 창은 누른 뒤 닫히기까지 충분히 기다리고, 닫히지 않을 때만 다시 누릅니다.
TC-HOME-004 는 네트워크가 조용해지기를 기다리는 대신 월간 통계 문서가 실제로 생기기를 기다립니다.
부하가 클 때 한 번 관찰한, 다시 받아 온 집계가 진행 중인 체크 표시를 덮는 동작은 TODO 에 기록했습니다.
PR 과 main 푸시마다 타입·린트·단위 테스트와 Playwright E2E 를 돌리는 워크플로를 추가했습니다.
E2E 는 Firebase 에뮬레이터 위에서 돌아 실제 프로젝트에 닿지 않고 비밀값도 쓰지 않습니다.
에뮬레이터 실행 파일은 firebase-tools 버전으로 캐시하고, 실패하면 리포트와 trace 를 Artifacts 로 남깁니다.
단위 테스트가 Firebase 초기화를 거치는데 설정을 로컬 .env 에서 읽어, .env 가 없는 CI 에서 auth/invalid-api-key 로 실패했습니다.
vitest 가 읽는 .env.test 에 demo 프로젝트 값을 두어, CI 에서도 돌고 로컬에서도 운영 설정을 쓰지 않게 했습니다.
@pangil5634
pangil5634 merged commit 7ab2a1a into main Oct 27, 2026
2 checks passed
@pangil5634
pangil5634 deleted the feat/e2e-playwright branch October 27, 2026 13:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant