diff --git a/docs/test-plan.md b/docs/test-plan.md index f9546356..6b1599a9 100644 --- a/docs/test-plan.md +++ b/docs/test-plan.md @@ -5,128 +5,38 @@ - 멀티 서비스(Backend/Ory Stack/Front) 연동 품질 확보 - 릴리즈 기준과 장애 분석 기준의 표준화 -## 2) 범위 -### 포함 -- Backend (Go Fiber) -- UserFront (Flutter Web/App) -- AdminFront / DevFront (React) -- Ory Stack (Kratos/Hydra/Keto/Oathkeeper) -- Gateway/네트워크 구성 (baron_net, ory-net, public_net) -- DB (PostgreSQL, ClickHouse, Redis) +## 2) 현재 기준 스냅샷 +- 기준 시각: 2026-02-19 16:32:09 KST +- 기준 커밋: `85998bd` +- Backend 전체 statement coverage: **24.7%** +- 테스트 인벤토리 수량: + - Backend(Go): **104개** + - UserFront(Flutter): **47개** + - AdminFront/DevFront(Playwright): **4개** -### 제외(별도 계획) -- 외부 IDP 벤더의 장애 대응 (Descope 등) -- 프로덕션 데이터 복구 시나리오(백업/DR) +### Backend 패키지별 커버리지 +- `cmd/server`: 2.6% +- `internal/handler`: 25.0% +- `internal/idp`: 16.6% +- `internal/middleware`: 59.6% +- `internal/response`: 91.7% +- `internal/service`: 32.7% +- `internal/utils`: 24.5% +- `internal/validator`: 89.3% -## 3) 원칙 -- **Shift-left**: 개발 단계에서 최대한 조기 검증 -- **단계적 신뢰**: Unit → Integration → E2E 순으로 신뢰도 상승 -- **환경 분리**: 로컬/스테이징/프로덕션 구성 차이를 문서로 명시 -- **결정적 테스트**: 시간/랜덤/외부 의존성 최소화 -- **Idempotent**: 반복 실행 시 동일 결과 보장 -- **보안 우선**: 민감정보(PII/Token)는 테스트 로그에 노출 금지 -- **실패 우선 기록**: 실패 로그/재현 절차를 우선 확보 +## 3) 하위 문서 (전수 목록) +- Backend 테스트 전수 목록: `docs/test-plan/backend-test-inventory.md` +- UserFront 테스트 전수 목록: `docs/test-plan/userfront-test-inventory.md` +- AdminFront/DevFront E2E 전수 목록: `docs/test-plan/web-e2e-test-inventory.md` -## 4) 테스트 레이어 및 목표 -### 4.1 Unit Test -- Backend: 비즈니스 로직, 유효성 검증, Mapper/Adapter -- Frontend: 유틸/상태관리/컴포넌트 로직 -- 목표: 빠른 피드백(수초~수분) +## 4) 실행 커맨드 +- Backend 전체 테스트: `cd backend && go test ./...` +- Backend 커버리지: `cd backend && go test ./... -coverprofile=coverage.out && go tool cover -func=coverage.out` +- UserFront 테스트: `cd userfront && flutter test` +- AdminFront E2E: `cd adminfront && npm test` +- DevFront E2E: `cd devfront && npm test` -### 4.2 Integration Test -- Backend + DB(Postgres/ClickHouse/Redis) -- Backend + Ory Admin API (Kratos/Hydra/Keto) -- 목표: 네트워크/스토리지 연동 검증 - -### 4.3 Contract Test -- Backend ↔ Frontend API 스키마/응답 계약 검증 -- OIDC/OpenID Connect 표준 응답 형식 검증 - -### 4.4 E2E Test (Happy/Edge Path) -- 로그인 플로우(Password / Magic Link / SMS / QR) -- Consent 플로우 (Hydra login/consent) -- 토큰 발급/재발급/로그아웃/세션 만료 -- 목표: 핵심 사용자 여정의 회귀 방지 - -### 4.5 Smoke Test -- 배포 직후 필수 엔드포인트 헬스체크 -- `GET /health`, Ory readiness, UserFront 정적 리소스 - -### 4.6 Regression / Non-functional -- 성능: 로그인/토큰 발급 지연, 대량 감사 로그 적재 -- 보안: 인증 우회, 권한 상승, 세션 고정 공격 -- 관측성: 핵심 로그/메트릭 누락 여부 - -## 5) 환경 전략 -- 로컬: `make up-all` 또는 `docker compose -f compose.infra.yaml -f compose.ory.yaml -f docker-compose.yaml up -d` -- 스테이징: 프로덕션과 동일한 네트워크/도메인 구성 -- 프로덕션: 최소한의 smoke/관측성 점검 - -## 6) 테스트 데이터 정책 -- 표준 시드 사용자/테넌트/클라이언트 세트 정의 -- PII 마스킹 규칙(이메일/전화번호/토큰) -- 재현용 고정 데이터와 랜덤 데이터 분리 -- 테스트 종료 후 클린업 규칙 정의 - -## 7) 자동화 및 CI/CD 기준 (현행) -- **현재 상태**: 레포에 CI/CD 워크플로우 정의가 없음. 테스트는 로컬/수동 실행 기준으로 운영. -- **CI 변수 활용**: AdminFront/DevFront Playwright 설정은 `CI` 환경 변수에 따라 재시도/워커 수를 조정함. -- **수동 실행 기준**: - - Backend: `go test ./...` (위치: `backend/`) - - UserFront: `flutter test` (위치: `userfront/`) - - AdminFront: `npm test` (Playwright, 위치: `adminfront/`, baseURL `http://localhost:5173`) - - DevFront: `npm test` (Playwright, 위치: `devfront/`, baseURL `http://localhost:5174`) - -### 7.1 수동 게이트 제안(현행 기준) -- PR/머지 전 최소 기준: Backend Unit + 해당 Front 테스트(변경 범위) -- 배포 전 최소 기준: Smoke + 핵심 E2E(로그인/Consent) - -## 8) 핵심 플로우 테스트 시나리오 -### 인증/세션 -- Password 로그인 성공/실패/락/재시도 -- Magic Link 발송/검증/만료 -- SMS 코드 발송/검증/재시도 제한 -- QR 승인/거절/타임아웃 -- 로그아웃 시 세션/쿠키/토큰 무효화 - -### 원격 링크 로그인(verify-only) -- Desktop에서 링크 요청 → Mobile에서 링크 클릭(verifyOnly) → Desktop Poll로 세션 발급 -- Mobile 단말에 세션 생성/로그인이 발생하지 않는지 확인 -- Audit/로그인 이력에 Desktop 세션 ID만 기록되는지 확인 -- 인증수단 표기(SMS/Email)가 요청 수단과 일치하는지 확인 -- 코드/링크 만료 시 승인 실패 및 재요청 안내 - -### OIDC/Hydra -- Login Challenge 처리 -- Consent 승인/거절 -- Token/Refresh Token 발급 -- Redirect URI 검증 - -### 권한/정책(Keto) -- 권한 부여/회수 시 접근 제어 확인 -- 관리자/일반 사용자 분리 - -### 네트워크/프록시 -- `baron_net`와 `ory-net` 경계 준수 -- Frontend에서 Ory 내부 Admin 포트 접근 불가 - -## 9) 관측성/장애 대응 테스트 -- 에러 로그 구조(필수 필드 포함) 확인 -- Audit Log 누락/중복 체크 -- 실패 시 재시도 정책 검증 - -## 10) 책임 및 운영 프로세스 -- 각 영역별 오너 지정(Backend/Front/Ory) -- 실패 시 triage 기준: 재현 가능 여부 → 영향도 → 우선순위 -- 테스트 케이스/기대 결과는 이슈/PR에 링크 - -## 11) 유지보수 원칙 -- 신규 기능은 반드시 관련 테스트 추가 -- 회귀 버그 발생 시 재현 테스트를 우선 추가 -- 불안정 테스트는 원인 분석 후 격리 또는 개선 - -## 12) 체크리스트 (릴리즈 전) -- Smoke 통과 -- 핵심 E2E 통과 -- 보안 관련 회귀 없음 -- 장애/모니터링 대시보드 정상 +## 5) 유지 원칙 +- 신규 기능은 관련 테스트를 반드시 추가합니다. +- 회귀 이슈는 재현 테스트를 먼저 추가하고 수정합니다. +- 본 문서의 수치/목록은 `origin/dev` 기준으로 주기적으로 갱신합니다. diff --git a/docs/test-plan/backend-test-inventory.md b/docs/test-plan/backend-test-inventory.md new file mode 100644 index 00000000..6daa3b97 --- /dev/null +++ b/docs/test-plan/backend-test-inventory.md @@ -0,0 +1,111 @@ +# Backend 테스트 전수 목록 + +- 범위: `backend/cmd/server`, `backend/internal/**` +- 기준: `func Test...` 패턴으로 수집한 단위/통합 테스트 + +| 파일 | 테스트 | 역할 | +|---|---|---| +| `backend/cmd/server/error_handler_test.go:23` | `TestNewErrorHandler_ProductionMasksServerError` | 오류/예외/거부 경로 검증 | +| `backend/cmd/server/error_handler_test.go:48` | `TestNewErrorHandler_ProductionPassesClientError` | 오류/예외/거부 경로 검증 | +| `backend/cmd/server/error_handler_test.go:73` | `TestNewErrorHandler_DevelopmentReturnsOriginalServerError` | 오류/예외/거부 경로 검증 | +| `backend/cmd/server/error_handler_test.go:98` | `TestNewErrorHandler_MapsUnauthorizedCode` | 오류/예외/거부 경로 검증 | +| `backend/internal/handler/api_key_handler_test.go:19` | `TestApiKeyHandler_CreateApiKey` | 핵심 CRUD/서비스 동작 검증 | +| `backend/internal/handler/api_key_handler_test.go:41` | `TestApiKeyHandler_Validation` | 유효성/정책/유틸 검증 | +| `backend/internal/handler/auth_handler_async_test.go:198` | `TestSignup_AsyncDB_Isolation` | 복구/격리/회복 탄력성 검증 | +| `backend/internal/handler/auth_handler_client_test.go:16` | `TestRevokeLinkedRp_Success` | 인증/OIDC 플로우 검증 | +| `backend/internal/handler/auth_handler_client_test.go:56` | `TestListRpHistory_Aggregation` | Hydra/RP 연동 검증 | +| `backend/internal/handler/auth_handler_consent_test.go:134` | `TestAcceptConsentRequest_Normal` | 인증/OIDC 플로우 검증 | +| `backend/internal/handler/auth_handler_consent_test.go:26` | `TestGetConsentRequest_Normal` | 인증/OIDC 플로우 검증 | +| `backend/internal/handler/auth_handler_consent_test.go:71` | `TestGetConsentRequest_Skip_AutoAccept` | 인증/OIDC 플로우 검증 | +| `backend/internal/handler/auth_handler_link_test.go:24` | `TestEnchantedLinkFlow_Email_Success` | 인증/OIDC 플로우 검증 | +| `backend/internal/handler/auth_handler_link_test.go:94` | `TestEnchantedLinkFlow_Sms_Success` | 인증/OIDC 플로우 검증 | +| `backend/internal/handler/auth_handler_linked_test.go:26` | `TestListLinkedRps_PriorityAndAggregation` | 인증/OIDC 플로우 검증 | +| `backend/internal/handler/auth_handler_login_test.go:114` | `TestPasswordLogin_OIDC_Success` | 인증/OIDC 플로우 검증 | +| `backend/internal/handler/auth_handler_login_test.go:201` | `TestPasswordLogin_OIDC_InactiveClient` | 오류/예외/거부 경로 검증 | +| `backend/internal/handler/auth_handler_login_test.go:255` | `TestPasswordLogin_NoOIDC_Success` | 인증/OIDC 플로우 검증 | +| `backend/internal/handler/auth_handler_oidc_test.go:106` | `TestAcceptOidcLoginRequest_TokenFallbackToCookie` | 복구/격리/회복 탄력성 검증 | +| `backend/internal/handler/auth_handler_oidc_test.go:21` | `TestAcceptOidcLoginRequest_CookieOnly` | 인증/OIDC 플로우 검증 | +| `backend/internal/handler/auth_handler_otp_test.go:14` | `TestHandleKratosCourierRelay_Email` | 인증/OIDC 플로우 검증 | +| `backend/internal/handler/auth_handler_otp_test.go:43` | `TestVerifySignupCode_Success` | 인증/OIDC 플로우 검증 | +| `backend/internal/handler/auth_handler_otp_test.go:85` | `TestVerifySignupCode_Invalid` | 오류/예외/거부 경로 검증 | +| `backend/internal/handler/auth_handler_qr_test.go:107` | `TestScanQRLogin_Success` | 인증/OIDC 플로우 검증 | +| `backend/internal/handler/auth_handler_qr_test.go:150` | `TestResolveConsentSubjects_TokenAndCookie` | 인증/OIDC 플로우 검증 | +| `backend/internal/handler/auth_handler_qr_test.go:57` | `TestQRLoginFlow_Success` | 인증/OIDC 플로우 검증 | +| `backend/internal/handler/auth_handler_test.go:20` | `TestCompletePasswordReset_MissingLoginID` | 오류/예외/거부 경로 검증 | +| `backend/internal/handler/auth_handler_test.go:50` | `TestCompletePasswordReset_InvalidPasswordPolicy` | 오류/예외/거부 경로 검증 | +| `backend/internal/handler/auth_handler_test.go:80` | `TestCompletePasswordReset_NilIDPProvider` | 인증/OIDC 플로우 검증 | +| `backend/internal/handler/dev_handler_test.go:103` | `TestCreateClient_Success` | Hydra/RP 연동 검증 | +| `backend/internal/handler/dev_handler_test.go:15` | `TestListClients_Success` | Hydra/RP 연동 검증 | +| `backend/internal/handler/dev_handler_test.go:49` | `TestGetClient_Success` | Hydra/RP 연동 검증 | +| `backend/internal/handler/dev_handler_test.go:83` | `TestGetClient_NotFound` | 오류/예외/거부 경로 검증 | +| `backend/internal/handler/password_policy_test.go:57` | `TestGeneratePasswordUsesNonAlphanumericRequirement` | 유효성/정책/유틸 검증 | +| `backend/internal/handler/tenant_handler_test.go:101` | `TestTenantHandler_ApproveTenant` | 핵심 CRUD/서비스 동작 검증 | +| `backend/internal/handler/tenant_handler_test.go:73` | `TestTenantHandler_CreateTenant` | 핵심 CRUD/서비스 동작 검증 | +| `backend/internal/handler/user_group_handler_test.go:109` | `TestUserGroupHandler_AddMember` | 권한/관계 모델 검증 | +| `backend/internal/handler/user_group_handler_test.go:128` | `TestUserGroupHandler_AssignRole` | 권한/관계 모델 검증 | +| `backend/internal/handler/user_group_handler_test.go:71` | `TestUserGroupHandler_List` | 권한/관계 모델 검증 | +| `backend/internal/handler/user_group_handler_test.go:91` | `TestUserGroupHandler_Create` | 권한/관계 모델 검증 | +| `backend/internal/idp/factory_test.go:123` | `TestChainedProviderMetadataUnion` | 회귀 방지 기본 동작 검증 | +| `backend/internal/idp/factory_test.go:139` | `TestChainedProviderUpdateUserPasswordFallback` | 복구/격리/회복 탄력성 검증 | +| `backend/internal/idp/factory_test.go:152` | `TestChainedProviderUpdateUserPasswordAllFail` | 인증/OIDC 플로우 검증 | +| `backend/internal/middleware/audit_middleware_test.go:42` | `TestAuditMiddleware` | 회귀 방지 기본 동작 검증 | +| `backend/internal/middleware/error_code_enricher_test.go:22` | `TestErrorCodeEnricher_AddsCodeToLegacyErrorResponse` | 오류/예외/거부 경로 검증 | +| `backend/internal/middleware/error_code_enricher_test.go:50` | `TestErrorCodeEnricher_DoesNotOverrideExistingCode` | 오류/예외/거부 경로 검증 | +| `backend/internal/middleware/error_code_enricher_test.go:72` | `TestErrorCodeEnricher_IgnoreSuccessPayload` | 오류/예외/거부 경로 검증 | +| `backend/internal/middleware/rbac_test.go:115` | `TestRequireKetoPermission_Success` | 권한/관계 모델 검증 | +| `backend/internal/middleware/rbac_test.go:138` | `TestRequireTenantMatch_SuperAdmin` | 권한/관계 모델 검증 | +| `backend/internal/middleware/rbac_test.go:160` | `TestRequireTenantMatch_Forbidden` | 오류/예외/거부 경로 검증 | +| `backend/internal/middleware/rbac_test.go:184` | `TestRequireRole_Unauthorized` | 오류/예외/거부 경로 검증 | +| `backend/internal/middleware/rbac_test.go:69` | `TestRequireRole_Success` | 권한/관계 모델 검증 | +| `backend/internal/middleware/rbac_test.go:92` | `TestRequireRole_Forbidden` | 오류/예외/거부 경로 검증 | +| `backend/internal/response/error_response_test.go:22` | `TestErrorWithDetailsResponseShape` | 오류/예외/거부 경로 검증 | +| `backend/internal/response/error_response_test.go:61` | `TestStatusCodeMapping` | 회귀 방지 기본 동작 검증 | +| `backend/internal/service/hydra_admin_service_test.go:102` | `TestHydraAdminService_GetConsentRequest` | 인증/OIDC 플로우 검증 | +| `backend/internal/service/hydra_admin_service_test.go:124` | `TestHydraAdminService_PatchClientStatus` | Hydra/RP 연동 검증 | +| `backend/internal/service/hydra_admin_service_test.go:13` | `TestHydraAdminService_ListClients` | Hydra/RP 연동 검증 | +| `backend/internal/service/hydra_admin_service_test.go:148` | `TestHydraAdminService_UpdateClient` | Hydra/RP 연동 검증 | +| `backend/internal/service/hydra_admin_service_test.go:165` | `TestHydraAdminService_ListConsentSessions` | 인증/OIDC 플로우 검증 | +| `backend/internal/service/hydra_admin_service_test.go:183` | `TestHydraAdminService_RevokeConsentSessions` | 인증/OIDC 플로우 검증 | +| `backend/internal/service/hydra_admin_service_test.go:198` | `TestHydraAdminService_RejectConsentRequest` | 오류/예외/거부 경로 검증 | +| `backend/internal/service/hydra_admin_service_test.go:215` | `TestHydraAdminService_RejectLoginRequest` | 오류/예외/거부 경로 검증 | +| `backend/internal/service/hydra_admin_service_test.go:232` | `TestHydraAdminService_GetLoginRequest` | 인증/OIDC 플로우 검증 | +| `backend/internal/service/hydra_admin_service_test.go:249` | `TestHydraAdminService_AcceptConsentRequest` | 인증/OIDC 플로우 검증 | +| `backend/internal/service/hydra_admin_service_test.go:267` | `TestHydraAdminService_AcceptLoginRequest` | 인증/OIDC 플로우 검증 | +| `backend/internal/service/hydra_admin_service_test.go:294` | `TestHydraAdminService_ErrorHandling` | 오류/예외/거부 경로 검증 | +| `backend/internal/service/hydra_admin_service_test.go:319` | `TestHydraAdminService_NotFound` | 오류/예외/거부 경로 검증 | +| `backend/internal/service/hydra_admin_service_test.go:39` | `TestHydraAdminService_GetClient` | Hydra/RP 연동 검증 | +| `backend/internal/service/hydra_admin_service_test.go:60` | `TestHydraAdminService_CreateClient` | Hydra/RP 연동 검증 | +| `backend/internal/service/hydra_admin_service_test.go:86` | `TestHydraAdminService_DeleteClient` | Hydra/RP 연동 검증 | +| `backend/internal/service/keto_service_test.go:101` | `TestKetoService_ErrorHandling` | 오류/예외/거부 경로 검증 | +| `backend/internal/service/keto_service_test.go:123` | `TestKetoService_CheckPermission_Forbidden` | 오류/예외/거부 경로 검증 | +| `backend/internal/service/keto_service_test.go:12` | `TestKetoService_CheckPermission` | 권한/관계 모델 검증 | +| `backend/internal/service/keto_service_test.go:137` | `TestKetoService_CreateRelation_Retry` | 복구/격리/회복 탄력성 검증 | +| `backend/internal/service/keto_service_test.go:34` | `TestKetoService_CreateRelation` | 권한/관계 모델 검증 | +| `backend/internal/service/keto_service_test.go:58` | `TestKetoService_DeleteRelation` | 권한/관계 모델 검증 | +| `backend/internal/service/keto_service_test.go:79` | `TestKetoService_ListRelations` | 권한/관계 모델 검증 | +| `backend/internal/service/ory_service_test.go:125` | `TestFindIdentityID_QueryEncoding` | 회귀 방지 기본 동작 검증 | +| `backend/internal/service/ory_service_test.go:38` | `TestUpdateUserPassword_Success` | 인증/OIDC 플로우 검증 | +| `backend/internal/service/ory_service_test.go:78` | `TestUpdateUserPassword_NotFound` | 오류/예외/거부 경로 검증 | +| `backend/internal/service/ory_service_test.go:98` | `TestUpdateUserPassword_ServerError` | 오류/예외/거부 경로 검증 | +| `backend/internal/service/relying_party_service_test.go:133` | `TestRelyingPartyService_Create_HydraFail` | Hydra/RP 연동 검증 | +| `backend/internal/service/relying_party_service_test.go:152` | `TestRelyingPartyService_Create_KetoFail_Rollback` | 복구/격리/회복 탄력성 검증 | +| `backend/internal/service/relying_party_service_test.go:190` | `TestRelyingPartyService_Get_Success` | Hydra/RP 연동 검증 | +| `backend/internal/service/relying_party_service_test.go:221` | `TestRelyingPartyService_Update_Success` | Hydra/RP 연동 검증 | +| `backend/internal/service/relying_party_service_test.go:250` | `TestRelyingPartyService_Delete_Success` | Hydra/RP 연동 검증 | +| `backend/internal/service/relying_party_service_test.go:85` | `TestRelyingPartyService_Create_Success` | Hydra/RP 연동 검증 | +| `backend/internal/service/tenant_service_test.go:126` | `TestTenantService_RegisterTenant_AddsDomainsAsVerified` | 핵심 CRUD/서비스 동작 검증 | +| `backend/internal/service/tenant_service_test.go:156` | `TestTenantService_RequestRegistration_AddsDomainAsUnverified` | 핵심 CRUD/서비스 동작 검증 | +| `backend/internal/service/tenant_service_test.go:187` | `TestTenantService_RequestRegistration_RejectsDomainMismatch` | 오류/예외/거부 경로 검증 | +| `backend/internal/service/tenant_service_test.go:208` | `TestTenantService_ApproveTenant_AssignsAdminRelationWhenUserExists` | 권한/관계 모델 검증 | +| `backend/internal/service/tenant_service_test.go:240` | `TestTenantService_ApproveTenant_DoesNotAssignWhenUserMissing` | 오류/예외/거부 경로 검증 | +| `backend/internal/service/user_group_service_test.go:103` | `TestUserGroupService_Create` | 권한/관계 모델 검증 | +| `backend/internal/service/user_group_service_test.go:124` | `TestUserGroupService_AddMember` | 권한/관계 모델 검증 | +| `backend/internal/service/user_group_service_test.go:138` | `TestUserGroupService_AssignRoleToTenant` | 권한/관계 모델 검증 | +| `backend/internal/service/user_group_service_test.go:154` | `TestUserGroupService_ListRoles` | 권한/관계 모델 검증 | +| `backend/internal/service/user_group_service_test.go:188` | `TestUserGroupService_Get_WithKratosFallback` | 복구/격리/회복 탄력성 검증 | +| `backend/internal/utils/masking_test.go:9` | `TestMaskSensitiveJSON` | 유효성/정책/유틸 검증 | +| `backend/internal/utils/slug_test.go:15` | `TestValidateSlug_ReservedKeywords` | 유효성/정책/유틸 검증 | +| `backend/internal/utils/slug_test.go:38` | `TestValidateSlug_LengthRules` | 유효성/정책/유틸 검증 | +| `backend/internal/utils/slug_test.go:60` | `TestValidateSlug_FormatRules` | 유효성/정책/유틸 검증 | +| `backend/internal/utils/slug_test.go:8` | `TestValidateSlug_Valid` | 유효성/정책/유틸 검증 | +| `backend/internal/validator/schema_validator_test.go:65` | `TestValidateIDPCompatibility` | 유효성/정책/유틸 검증 | diff --git a/docs/test-plan/userfront-test-inventory.md b/docs/test-plan/userfront-test-inventory.md new file mode 100644 index 00000000..76d27e9a --- /dev/null +++ b/docs/test-plan/userfront-test-inventory.md @@ -0,0 +1,54 @@ +# UserFront 테스트 전수 목록 + +- 범위: `userfront/test/*.dart` +- 기준: `test(...)`, `testWidgets(...)` 케이스 전수 + +| 파일 | 테스트 | 역할 | +|---|---|---| +| `userfront/test/dashboard_providers_test.dart` | `AuthTimelineNotifier는 다음 커서를 사용해 추가 로드한다` | 대시보드 타임라인 상태관리 검증 | +| `userfront/test/dashboard_providers_test.dart` | `AuthTimelineNotifier는 실패 시 오류 메시지를 보관한다` | 대시보드 타임라인 상태관리 검증 | +| `userfront/test/dashboard_providers_test.dart` | `AuthTimelineNotifier는 초기 페이지를 로드한다` | 대시보드 타임라인 상태관리 검증 | +| `userfront/test/dashboard_providers_test.dart` | `AuthTimelineNotifier는 커서가 없으면 추가 로드를 하지 않는다` | 대시보드 타임라인 상태관리 검증 | +| `userfront/test/error_screen_test.dart` | `개발환경은 원문 메시지를 노출한다` | 에러 노출 정책 검증 | +| `userfront/test/error_screen_test.dart` | `프로덕션은 ORY 코드를 bypass 처리한다` | 핵심 동작 회귀 방지 검증 | +| `userfront/test/error_screen_test.dart` | `프로덕션은 whitelist 메시지를 노출한다` | 에러 노출 정책 검증 | +| `userfront/test/error_screen_test.dart` | `프로덕션은 비허용 에러를 unknown_error로 처리한다` | 에러 노출 정책 검증 | +| `userfront/test/locale_registry_test.dart` | `extractSupportedLocaleCodesFromAssets excludes template and invalid` | i18n 로케일 해석/정규화 규칙 검증 | +| `userfront/test/locale_registry_test.dart` | `fallback locale prefers en when available` | fallback/복구 경로 검증 | +| `userfront/test/locale_registry_test.dart` | `fallback locale uses first sorted code when en is absent` | fallback/복구 경로 검증 | +| `userfront/test/locale_storage_platform_test.dart` | `legacy key에서 locale로 마이그레이션 (웹)` | i18n 로케일 해석/정규화 규칙 검증 | +| `userfront/test/locale_storage_platform_test.dart` | `localStorage write/read (웹)` | 브라우저 스토리지 저장/복원 정책 검증 | +| `userfront/test/locale_storage_platform_test.dart` | `localStorage 접근이 차단되면 sessionStorage로 fallback (웹)` | fallback/복구 경로 검증 | +| `userfront/test/locale_storage_platform_test.dart` | `localStorage 접근이 차단되면 메모리 fallback (웹)` | fallback/복구 경로 검증 | +| `userfront/test/locale_utils_test.dart` | `buildLocalizedPath applies locale` | i18n 로케일 해석/정규화 규칙 검증 | +| `userfront/test/locale_utils_test.dart` | `buildLocalizedPath keeps unknown 2-letter prefix as path` | 리다이렉트/쿼리 보존 규칙 검증 | +| `userfront/test/locale_utils_test.dart` | `buildLocalizedPath preserves fragment` | 리다이렉트/쿼리 보존 규칙 검증 | +| `userfront/test/locale_utils_test.dart` | `buildLocalizedPath preserves query parameters` | 리다이렉트/쿼리 보존 규칙 검증 | +| `userfront/test/locale_utils_test.dart` | `buildLocalizedPath preserves raw query order and duplicates` | 리다이렉트/쿼리 보존 규칙 검증 | +| `userfront/test/locale_utils_test.dart` | `buildLocalizedPath preserves redirect_url parameter` | 리다이렉트/쿼리 보존 규칙 검증 | +| `userfront/test/locale_utils_test.dart` | `buildLocalizedPath replaces existing locale` | i18n 로케일 해석/정규화 규칙 검증 | +| `userfront/test/locale_utils_test.dart` | `buildSigninRedirectPath keeps path without query` | 리다이렉트/쿼리 보존 규칙 검증 | +| `userfront/test/locale_utils_test.dart` | `buildSigninRedirectPath preserves full raw query` | 리다이렉트/쿼리 보존 규칙 검증 | +| `userfront/test/locale_utils_test.dart` | `buildSigninRedirectPath preserves redirect_url and redirect_uri` | 리다이렉트/쿼리 보존 규칙 검증 | +| `userfront/test/locale_utils_test.dart` | `extractLocaleFromPath picks locale when present` | i18n 로케일 해석/정규화 규칙 검증 | +| `userfront/test/locale_utils_test.dart` | `extractLocaleFromPath returns null when missing` | fallback/복구 경로 검증 | +| `userfront/test/locale_utils_test.dart` | `normalizeLocaleCode falls back to default` | i18n 로케일 해석/정규화 규칙 검증 | +| `userfront/test/locale_utils_test.dart` | `normalizeLocaleCode handles supported locales` | i18n 로케일 해석/정규화 규칙 검증 | +| `userfront/test/locale_utils_test.dart` | `stripLocalePath keeps path without locale` | 리다이렉트/쿼리 보존 규칙 검증 | +| `userfront/test/locale_utils_test.dart` | `stripLocalePath removes locale segment` | i18n 로케일 해석/정규화 규칙 검증 | +| `userfront/test/login_challenge_resolver_test.dart` | `URI query가 비어 있으면 raw search에서 복구` | fallback/복구 경로 검증 | +| `userfront/test/login_challenge_resolver_test.dart` | `raw search도 비어 있으면 raw href에서 복구` | fallback/복구 경로 검증 | +| `userfront/test/login_challenge_resolver_test.dart` | `widget 값이 없으면 URI query에서 복구` | fallback/복구 경로 검증 | +| `userfront/test/login_challenge_resolver_test.dart` | `widget 값이 있으면 최우선으로 사용` | 핵심 동작 회귀 방지 검증 | +| `userfront/test/login_challenge_resolver_test.dart` | `값이 전부 없으면 missing` | fallback/복구 경로 검증 | +| `userfront/test/oidc_redirect_guard_test.dart` | `http/https 절대 URL만 허용` | 핵심 동작 회귀 방지 검증 | +| `userfront/test/oidc_redirect_guard_test.dart` | `빈 문자열과 파싱 실패를 차단` | 핵심 동작 회귀 방지 검증 | +| `userfront/test/password_login_flow_policy_test.dart` | `OIDC challenge가 없고 jwt가 있으면 로컬 로그인 완료로 진행한다` | 로그인 분기/라우팅 규칙 검증 | +| `userfront/test/password_login_flow_policy_test.dart` | `OIDC challenge가 있고 redirectTo가 없으면 accept를 시도한다` | 로그인 분기/라우팅 규칙 검증 | +| `userfront/test/password_login_flow_policy_test.dart` | `redirectTo/jwt 모두 없으면 invalid로 처리한다` | 로그인 분기/라우팅 규칙 검증 | +| `userfront/test/password_login_flow_policy_test.dart` | `redirectTo가 있으면 OIDC redirect를 우선한다` | 로그인 분기/라우팅 규칙 검증 | +| `userfront/test/router_redirect_widget_test.dart` | `/login: login_challenge와 redirect_uri를 전달` | 리다이렉트/쿼리 보존 규칙 검증 | +| `userfront/test/router_redirect_widget_test.dart` | `로그인 상태: profile 접근 시 signin으로 리다이렉트하지 않음` | 로그인 분기/라우팅 규칙 검증 | +| `userfront/test/router_redirect_widget_test.dart` | `비로그인: redirect_uri/login_challenge가 signin으로 전달` | 리다이렉트/쿼리 보존 규칙 검증 | +| `userfront/test/router_redirect_widget_test.dart` | `비로그인: redirect_uri가 없으면 redirect_url을 전달` | 리다이렉트/쿼리 보존 규칙 검증 | +| `userfront/test/widget_test.dart` | `BaronSSOApp builds` | 기본 앱 렌더링 스모크 검증 | diff --git a/docs/test-plan/web-e2e-test-inventory.md b/docs/test-plan/web-e2e-test-inventory.md new file mode 100644 index 00000000..7e771a51 --- /dev/null +++ b/docs/test-plan/web-e2e-test-inventory.md @@ -0,0 +1,11 @@ +# AdminFront/DevFront E2E 테스트 전수 목록 + +- 범위: `adminfront/tests/*.spec.ts`, `devfront/tests/*.spec.ts` +- 기준: Playwright `test(...)` 케이스 전수 + +| 파일 | 테스트 | 역할 | +|---|---|---| +| `adminfront/tests/example.spec.ts:3` | `has title` | 초기 페이지 렌더링 스모크 검증 | +| `adminfront/tests/user-management.spec.ts:26` | `user create and delete flow` | 관리자 사용자 생성/삭제 E2E 검증 | +| `devfront/tests/clients.spec.ts:3` | `clients page loads correctly` | DevFront 클라이언트 페이지 접근 스모크 검증 | +| `devfront/tests/example.spec.ts:3` | `has title` | 초기 페이지 렌더링 스모크 검증 |