|
| 1 | +# Phase 1.5 QA 체크리스트 & E2E 시나리오 |
| 2 | + |
| 3 | +> 이 문서는 Phase 1.5 완료 기준 검증을 위한 QA 체크리스트, E2E 시나리오, 접근성 기준을 정의합니다. |
| 4 | +> 실제 API 연결 전까지는 mock 계정(`admin@fieldstack.dev` / `user@fieldstack.dev`)으로 검증합니다. |
| 5 | +
|
| 6 | +--- |
| 7 | + |
| 8 | +## 1. 핵심 플로우 QA 체크리스트 |
| 9 | + |
| 10 | +### 1.1 설치 → 로그인 → 홈 → 설정 |
| 11 | + |
| 12 | +| # | 항목 | 예상 결과 | 상태 | |
| 13 | +|---|------|-----------|------| |
| 14 | +| 1 | `pnpm dev:bypass`로 실행 — 상단에 "DEV BYPASS" pill 표시 | 노란 pill + notice 표시 | — | |
| 15 | +| 2 | `admin@fieldstack.dev` / `Admin1234!` 로그인 | "로그인 성공." notice, `#home` 이동 | — | |
| 16 | +| 3 | 홈 화면 — 모듈 0개 상태 Empty UX 표시 | 온보딩 3단계 가이드 + EmptyState 표시 | — | |
| 17 | +| 4 | 최초 로그인 시 환영 배너 표시 | 파란 gradient 배너 + ✕ 닫기 | — | |
| 18 | +| 5 | 환영 배너 닫기 → 재로그인 시 미표시 | localStorage 기반 1회 표시 | — | |
| 19 | +| 6 | Settings 열기 → 테마 변경 → 즉시 반영 | data-theme 토글, FOUC 없음 | — | |
| 20 | +| 7 | Settings — 변경 없이 저장 버튼 비활성화 | 저장 버튼 disabled | — | |
| 21 | +| 8 | Settings — 변경 후 저장 → notice 표시 후 모달 닫힘 | "설정이 저장되었습니다." notice | — | |
| 22 | +| 9 | Settings — 미저장 상태에서 닫기 → confirm 경고 | 브라우저 confirm 창 | — | |
| 23 | +| 10 | 사이드바 — Home / Marketplace / Settings / Sign Out 동작 | 각 항목 정상 탐색 | — | |
| 24 | + |
| 25 | +### 1.2 관리자 흐름 |
| 26 | + |
| 27 | +| # | 항목 | 예상 결과 | 상태 | |
| 28 | +|---|------|-----------|------| |
| 29 | +| 11 | 관리자 로그인 → 홈에 Admin Overview 배너 표시 | 활성 사용자·설치 모듈·시스템 상태 카드 | — | |
| 30 | +| 12 | 사이드바 Admin 진입 → PIN 인증 모달 | 🔐 모달, 4자리 입력 | — | |
| 31 | +| 13 | PIN `1234` 입력 → Admin 패널 진입 | "관리자 인증 완료. 30분간 유효합니다." notice | — | |
| 32 | +| 14 | 잘못된 PIN 5회 입력 → 5분 잠금 | 카운트다운 표시 | — | |
| 33 | +| 15 | Admin — 보안 설정 클릭 → PIN 변경 폼 표시 | 현재/새 PIN 입력 3단계 | — | |
| 34 | +| 16 | PIN 변경 — 현재 PIN 불일치 → 에러 | "현재 PIN이 올바르지 않습니다." | — | |
| 35 | +| 17 | PIN 변경 — 성공 → 성공 화면 | 녹색 확인 화면 | — | |
| 36 | +| 18 | Admin — 감사 로그 클릭 → 전체 로그 표시 | 10건 + 필터 탭 동작 | — | |
| 37 | +| 19 | 30분 대기(타이머 mock) → 관리자 세션 만료 notice | "관리자 세션이 만료되었습니다." notice | — | |
| 38 | +| 20 | 일반 사용자 로그인 → 사이드바에 Admin 진입점 미표시 | Admin 버튼 없음 | — | |
| 39 | + |
| 40 | +### 1.3 인증 예외 흐름 |
| 41 | + |
| 42 | +| # | 항목 | 예상 결과 | 상태 | |
| 43 | +|---|------|-----------|------| |
| 44 | +| 21 | 비밀번호 5회 실패 → 30분 잠금 | 잠금 Alert, 폼 disabled | — | |
| 45 | +| 22 | `otp1234` 비밀번호 → OTP step 전환 | 로그인 내 OTP 입력 단계 | — | |
| 46 | +| 23 | OTP 인증 완료 → 홈 이동 | "2단계 인증 완료." notice | — | |
| 47 | +| 24 | `temp1234` 비밀번호 → 강제 비밀번호 변경 화면 | ChangePasswordView 전체 화면 | — | |
| 48 | +| 25 | ForgotPassword — 이메일 경로 3단계 흐름 | 경로 선택 → 이메일 입력 → 새 비밀번호 설정 → 완료 | — | |
| 49 | +| 26 | ForgotPassword — 관리자 토큰 경로 흐름 | 이메일+토큰 입력 → 새 비밀번호 설정 → 완료 | — | |
| 50 | + |
| 51 | +### 1.4 딥 링크 & 개인화 |
| 52 | + |
| 53 | +| # | 항목 | 예상 결과 | 상태 | |
| 54 | +|---|------|-----------|------| |
| 55 | +| 27 | 비인증 상태에서 `#admin` 직접 진입 → 로그인 후 `#admin` 복귀 | redirectAfterLogin 동작 | — | |
| 56 | +| 28 | 비인증 상태에서 `#marketplace` 직접 진입 → 로그인 후 `#marketplace` 복귀 | redirectAfterLogin 동작 | — | |
| 57 | +| 29 | Settings — 로그인 후 첫 화면 "마켓플레이스" 설정 저장 → 다음 로그인 시 `#marketplace` 이동 | fs_startup_route 반영 | — | |
| 58 | +| 30 | 로그아웃 → "로그아웃 되었습니다." notice | 한국어 notice | — | |
| 59 | + |
| 60 | +--- |
| 61 | + |
| 62 | +## 2. 반응형 기준 |
| 63 | + |
| 64 | +| 브레이크포인트 | 적용 내용 | |
| 65 | +|----------------|-----------| |
| 66 | +| > 768px (데스크톱) | 사이드바 고정 220px, 본문 margin-left: 220px | |
| 67 | +| ≤ 768px (모바일) | 사이드바 숨김, 상단 바 + 햄버거 버튼, 슬라이드인 Drawer | |
| 68 | +| ≤ 860px | 본문 padding 20px | |
| 69 | +| ≤ 540px | Settings 모달 → 하단 bottom sheet | |
| 70 | +| ≤ 980px | Admin columns → 단일 컬럼 | |
| 71 | +| ≤ 900px | 로그인 화면 → showcase 영역 숨김, 단일 컬럼 | |
| 72 | + |
| 73 | +### 반응형 체크 항목 |
| 74 | + |
| 75 | +| # | 항목 | 기준 | 상태 | |
| 76 | +|---|------|------|------| |
| 77 | +| R1 | 768px 이하: 햄버거 버튼 표시 + 사이드바 숨김 | shell-mobile-topbar 노출 | — | |
| 78 | +| R2 | 768px 이하: 햄버거 클릭 → 사이드바 슬라이드인 + 오버레이 | transition 정상 동작 | — | |
| 79 | +| R3 | 768px 이하: 오버레이 클릭 → 사이드바 닫힘 | closeMobileMenu 동작 | — | |
| 80 | +| R4 | 540px 이하: Settings → bottom sheet 애니메이션 | slideUp 전환 | — | |
| 81 | +| R5 | 980px 이하: Admin 2컬럼 → 1컬럼 | 레이아웃 깨짐 없음 | — | |
| 82 | +| R6 | 900px 이하: 로그인 showcase 숨김 | 로그인 카드만 표시 | — | |
| 83 | + |
| 84 | +--- |
| 85 | + |
| 86 | +## 3. 에러 / 빈 상태 / 권한 거부 일관성 |
| 87 | + |
| 88 | +| 화면 | 에러 상태 | 빈 상태 | 권한 거부 | |
| 89 | +|------|-----------|---------|-----------| |
| 90 | +| 로그인 | 인라인 에러 텍스트 (버튼 아래) | — | 잠금 Alert (5회 실패) | |
| 91 | +| 홈 | — | EmptyState (모듈 0개) + 온보딩 3단계 | — | |
| 92 | +| 마켓플레이스 | — | EmptyState (Phase 3 안내) | — | |
| 93 | +| Admin | — | — | 🔒 lock screen + PIN 인증 버튼 | |
| 94 | +| Admin > 섹션 | — | "준비 중" 플레이스홀더 | — | |
| 95 | +| Settings | 저장 실패 시 notice (미구현 — Phase 1.95+) | — | — | |
| 96 | +| 비밀번호 복구 | 단계별 인라인 에러 | — | — | |
| 97 | + |
| 98 | +--- |
| 99 | + |
| 100 | +## 4. E2E 시나리오 정의 |
| 101 | + |
| 102 | +### 4.1 핵심 시나리오 |
| 103 | + |
| 104 | +#### S-01: 최초 로그인 온보딩 |
| 105 | +``` |
| 106 | +전제: localStorage 비어 있음 (첫 방문) |
| 107 | +1. 앱 열기 → 로그인 화면 |
| 108 | +2. admin@fieldstack.dev / Admin1234! 입력 → 로그인 |
| 109 | +3. 환영 배너 표시 확인 |
| 110 | +4. 배너 ✕ 클릭 → 배너 사라짐 |
| 111 | +5. 로그아웃 → 재로그인 → 배너 미표시 확인 |
| 112 | +기대: fs_first_visit_shown = "true" 저장 |
| 113 | +``` |
| 114 | + |
| 115 | +#### S-02: 설치 → 로그인 → 홈 → 설정 핵심 플로우 |
| 116 | +``` |
| 117 | +1. pnpm dev:bypass 실행 |
| 118 | +2. 로그인 (admin@fieldstack.dev) |
| 119 | +3. 홈 화면 — Empty UX 확인 |
| 120 | +4. Settings 열기 → 테마 다크/라이트 전환 확인 |
| 121 | +5. 언어 변경 → 저장 → notice 확인 |
| 122 | +6. Sign Out → 로그인 화면 복귀 |
| 123 | +``` |
| 124 | + |
| 125 | +#### S-03: 관리자 PIN 플로우 |
| 126 | +``` |
| 127 | +1. admin@fieldstack.dev 로그인 |
| 128 | +2. 사이드바 Admin → PIN 모달 표시 |
| 129 | +3. 1111 입력 → 오류 (1/5) |
| 130 | +4. 1234 입력 → Admin 패널 진입 |
| 131 | +5. 보안 설정 클릭 → PIN 변경 폼 |
| 132 | +6. 현재: 1234 / 새: 5678 / 확인: 5678 → PIN 변경 성공 |
| 133 | +7. 로그아웃 → 재로그인 → Admin 진입 → PIN 재인증 게이트 확인 |
| 134 | +``` |
| 135 | + |
| 136 | +#### S-04: 딥 링크 복귀 |
| 137 | +``` |
| 138 | +1. 로그아웃 상태에서 URL에 #admin 입력 |
| 139 | +2. 로그인 화면으로 리다이렉트 |
| 140 | +3. 로그인 완료 → #admin으로 자동 복귀 (PIN 게이트 표시) |
| 141 | +``` |
| 142 | + |
| 143 | +#### S-05: 비밀번호 복구 |
| 144 | +``` |
| 145 | +[이메일 경로] |
| 146 | +1. 로그인 화면 → "비밀번호를 잊으셨나요?" 클릭 |
| 147 | +2. 이메일 경로 선택 → 이메일 입력 → 전송 완료 화면 |
| 148 | +3. 새 비밀번호 입력 → 완료 → 로그인 화면 복귀 |
| 149 | +
|
| 150 | +[관리자 토큰 경로] |
| 151 | +1. 관리자 토큰 경로 선택 → 이메일 + 토큰 입력 |
| 152 | +2. 새 비밀번호 입력 → 완료 → 로그인 화면 복귀 |
| 153 | +``` |
| 154 | + |
| 155 | +### 4.2 확장 시나리오 |
| 156 | + |
| 157 | +#### S-06: 로그인 잠금 및 복구 |
| 158 | +``` |
| 159 | +1. 잘못된 비밀번호 5회 입력 → 30분 잠금 Alert |
| 160 | +2. 30분 대기 (또는 타이머 조작) → 잠금 해제 |
| 161 | +3. 정상 로그인 |
| 162 | +``` |
| 163 | + |
| 164 | +#### S-07: 관리자 PIN 만료 재인증 |
| 165 | +``` |
| 166 | +1. 관리자 PIN 인증 완료 |
| 167 | +2. 30분 경과 (타이머 mock: setTimeout 조작) |
| 168 | +3. "관리자 세션이 만료되었습니다." notice 표시 |
| 169 | +4. Admin 화면 → PIN 게이트 복원 확인 |
| 170 | +5. PIN 재인증 → Admin 패널 재진입 |
| 171 | +``` |
| 172 | + |
| 173 | +#### S-08: 임시 비밀번호 강제 변경 |
| 174 | +``` |
| 175 | +1. 이메일 임의값 / 비밀번호 temp1234 로그인 |
| 176 | +2. ChangePasswordView 전체 화면 표시 (shell 없음) |
| 177 | +3. 정책 체크리스트 확인 |
| 178 | +4. 새 비밀번호 입력 → 변경 완료 → 홈 이동 |
| 179 | +``` |
| 180 | + |
| 181 | +#### S-09: 개인화 첫 화면 설정 |
| 182 | +``` |
| 183 | +1. 로그인 → Settings → 로그인 후 첫 화면: "마켓플레이스" 선택 → 저장 |
| 184 | +2. 로그아웃 → 재로그인 → #marketplace로 이동 확인 |
| 185 | +3. Settings → 다시 "홈 화면"으로 변경 → 저장 |
| 186 | +4. 로그아웃 → 재로그인 → #home으로 이동 확인 |
| 187 | +``` |
| 188 | + |
| 189 | +--- |
| 190 | + |
| 191 | +## 5. 접근성 QA 체크리스트 |
| 192 | + |
| 193 | +### 5.1 키보드 전용 조작 |
| 194 | + |
| 195 | +| # | 항목 | 기준 | |
| 196 | +|---|------|------| |
| 197 | +| A1 | Tab으로 로그인 폼 전체 탐색 가능 | 이메일 → 비밀번호 → 로그인 버튼 순서 | |
| 198 | +| A2 | Tab으로 사이드바 nav 전체 탐색 가능 | Home → Marketplace → Modules → Settings → Admin → Sign Out | |
| 199 | +| A3 | 사이드바 nav list 내 ArrowUp/ArrowDown 이동 | Workspace, Modules 섹션 내 순환 | |
| 200 | +| A4 | Modal(Settings, AdminPin) — Tab 순환, Esc 닫기 | 포커스 트랩 (Phase 1.5.6 범위 외) | |
| 201 | +| A5 | 버튼 Enter/Space 동작 | 모든 `<button>` 요소 | |
| 202 | + |
| 203 | +### 5.2 ARIA 레이블 |
| 204 | + |
| 205 | +| # | 항목 | 기준 | |
| 206 | +|---|------|------| |
| 207 | +| A6 | 사이드바 `aria-label="사이드바 네비게이션"` | AppShell `<aside>` | |
| 208 | +| A7 | 주 메뉴 `aria-label="주 메뉴"` | AppShell `<nav>` | |
| 209 | +| A8 | 현재 페이지 `aria-current="page"` | 활성 nav 항목 | |
| 210 | +| A9 | 모바일 햄버거 `aria-label="메뉴 열기"`, `aria-expanded` | 상태 반영 | |
| 211 | +| A10 | 드로어 닫기 버튼 `aria-label="메뉴 닫기"` | ✕ 버튼 | |
| 212 | +| A11 | 감사 로그 필터 그룹 `role="group"` | 필터 탭 영역 | |
| 213 | +| A12 | 에러 메시지 `role="alert"` | PIN 오류, 로그인 에러 | |
| 214 | +| A13 | notice 바 `role="status"`, `aria-live="polite"` | shell-notice | |
| 215 | +| A14 | 홈 환영 배너 `role="region"` | home-welcome-banner | |
| 216 | + |
| 217 | +### 5.3 명도 대비 |
| 218 | + |
| 219 | +| 요소 | 전경색 | 배경색 | 비고 | |
| 220 | +|------|--------|--------|------| |
| 221 | +| 본문 텍스트 (`--text`) | `#E2E8F0` | `#0F172A` | WCAG AA 이상 | |
| 222 | +| 보조 텍스트 (`--text-muted`) | `#94A3B8` | `#0F172A` | 대형 텍스트 기준 통과 | |
| 223 | +| Accent 버튼 | `#fff` | `#3B82F6` | AA 통과 | |
| 224 | +| 에러 텍스트 (`--err`) | `#F87171` | `#0F172A` | AA 통과 | |
| 225 | + |
| 226 | +> 라이트 모드 대비는 Phase 1.5.6 범위에서 별도 검증 필요. |
| 227 | +
|
| 228 | +### 5.4 포커스 가시성 |
| 229 | + |
| 230 | +| # | 항목 | 기준 | |
| 231 | +|---|------|------| |
| 232 | +| A15 | 모든 interactive 요소 focus ring 표시 | `global.css` `:focus-visible` 2px outline | |
| 233 | +| A16 | 모달 열릴 때 첫 interactive 요소로 포커스 이동 | 자동 포커스 (현재 미구현 — Phase 1.5.6 개선 여지) | |
| 234 | +| A17 | 모달 닫힐 때 트리거 버튼으로 포커스 복귀 | 자동 복귀 (현재 미구현 — Phase 1.5.6 개선 여지) | |
| 235 | + |
| 236 | +--- |
| 237 | + |
| 238 | +## 6. 텍스트 / 피드백 톤 가이드 |
| 239 | + |
| 240 | +### 6.1 notice (상단 바 일시 메시지) |
| 241 | + |
| 242 | +| 상황 | 문구 | |
| 243 | +|------|------| |
| 244 | +| 로그인 성공 | "로그인 성공." | |
| 245 | +| OTP 인증 완료 | "2단계 인증 완료." | |
| 246 | +| 로그아웃 | "로그아웃 되었습니다." | |
| 247 | +| 비밀번호 변경 완료 | "비밀번호가 변경되었습니다." | |
| 248 | +| 비밀번호 복구 완료 | "비밀번호가 복구되었습니다. 새 비밀번호로 로그인하세요." | |
| 249 | +| 관리자 PIN 인증 완료 | "관리자 인증 완료. 30분간 유효합니다." | |
| 250 | +| 관리자 세션 만료 | "관리자 세션이 만료되었습니다. 다시 인증해 주세요." | |
| 251 | +| 설정 저장 완료 | "설정이 저장되었습니다." | |
| 252 | +| 관리자 권한 부여 (dev) | "관리자 권한이 부여되었습니다." | |
| 253 | +| 관리자 권한 해제 (dev) | "관리자 권한이 해제되었습니다." | |
| 254 | + |
| 255 | +### 6.2 에러 메시지 규칙 |
| 256 | + |
| 257 | +- 계정 존재 여부 비노출: 이메일/비밀번호 오류를 구분하지 않음 |
| 258 | + - ✓ "이메일 또는 비밀번호가 올바르지 않습니다." |
| 259 | + - ✗ "존재하지 않는 이메일입니다." |
| 260 | +- 잠금 상태: 남은 시간 표시 |
| 261 | + - ✓ "계정이 잠겼습니다. 30분 후 다시 시도하세요." |
| 262 | +- PIN 오류: 남은 시도 횟수 표시 |
| 263 | + - ✓ "PIN이 올바르지 않습니다. (1/5)" |
| 264 | + |
| 265 | +### 6.3 확인 / 경고 대화상자 |
| 266 | + |
| 267 | +| 상황 | 문구 | |
| 268 | +|------|------| |
| 269 | +| 미저장 변경 닫기 | "저장하지 않은 변경사항이 있습니다. 닫으시겠습니까?" | |
0 commit comments