- 전수 순회: IA 전 라우트 412개 기능 인벤토리를 체크리스트 백로그로 관리 (docs/ops/e2e-full-sweep-2026-07-27.md), 신규 full-sweep 스펙 10파일 추가. RED→GREEN으로 결함 12건 수정: 관리자 무한 렌더 프리즈(TanStack autoReset 루프), 복수 코호트 저장 유실, 페르소나 보관 503(SQL 컬럼 모호성), PII 과잉 마스킹, /admin/ai watchdog 오탐 오버레이, 모바일 겹침 2건, 설정 스크롤 스파이, 온보딩 전화번호 무검증, 리뷰 조사·난도 라벨, pending 피드백 등. - 소유자 결정 구현: 설정 아바타 변경, 동의 철회·재동의 전체 흐름, 신규 학습자 기초 우선 추천, 학생 분석 테이블 가상화(@tanstack/react-virtual), 저작 모드 죽은 레일 정리, 감정 밸런스 타임라인 차트(deep turn_valence + 결정론 파생 폴백). - 디자인 감사(142차): 라이트 팔레트 AA 대비, 다크 토큰 별칭 통일, 미정의 CSS 변수 정리, 한글 keep-all 전역화, 탭 타깃 24px, LCP preconnect. - 검증: npm run e2e 병렬 432 수집 GREEN + 직렬 49/49 exit 0, 백엔드 pytest 421, gateway 29, typecheck/build/design-ssot/dead-code/중복 게이트 통과, layout-visual-gate 15/15, session-layout 8/8. 상세는 SSOT 대시보드 142~144차 노트.
68 lines
2.4 KiB
Python
68 lines
2.4 KiB
Python
"""온보딩/프로필 연락처(phone) 형식 검증 회귀 테스트.
|
|
|
|
2026-07-27 전수 순회에서 발견: 온보딩 연락처에 "전화번호아님텍스트" 같은
|
|
임의 문자열을 넣어도 클라이언트·서버 모두 통과되어 DB에 저장됐다.
|
|
OnboardingRequest / UserProfilePatch 는 숫자 9~15자리(하이픈·공백·괄호·점·
|
|
선행 + 허용)만 받아야 한다.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import unittest
|
|
|
|
from pydantic import ValidationError
|
|
|
|
from .routes.users import OnboardingRequest, UserProfilePatch
|
|
|
|
|
|
def _onboarding_kwargs(**overrides: object) -> dict:
|
|
base: dict = {
|
|
"legal_name": "검증 사용자",
|
|
"affiliation": "한신대학교",
|
|
"department": "상담심리학과",
|
|
"grade_level": "3학년",
|
|
"phone": "010-1234-5678",
|
|
"contact_address": "경기도 오산시 한신대길 137",
|
|
"nickname": "검증",
|
|
"self_introduction": "연락처 검증 테스트 사용자입니다.",
|
|
"avatar_url": "",
|
|
"terms_accepted": True,
|
|
"privacy_accepted": True,
|
|
}
|
|
base.update(overrides)
|
|
return base
|
|
|
|
|
|
class OnboardingPhoneValidationTest(unittest.TestCase):
|
|
def test_onboarding_rejects_non_numeric_phone_text(self) -> None:
|
|
with self.assertRaises(ValidationError):
|
|
OnboardingRequest(**_onboarding_kwargs(phone="전화번호아님텍스트"))
|
|
|
|
def test_onboarding_rejects_phone_with_too_few_digits(self) -> None:
|
|
with self.assertRaises(ValidationError):
|
|
OnboardingRequest(**_onboarding_kwargs(phone="010-12"))
|
|
|
|
def test_onboarding_accepts_common_korean_phone_formats(self) -> None:
|
|
for phone in (
|
|
"010-1234-5678",
|
|
"01012345678",
|
|
"010 1234 5678",
|
|
"02-123-4567",
|
|
"031-8000-9000",
|
|
"+82-10-1234-5678",
|
|
):
|
|
with self.subTest(phone=phone):
|
|
req = OnboardingRequest(**_onboarding_kwargs(phone=phone))
|
|
self.assertEqual(req.phone, phone.strip())
|
|
|
|
def test_profile_patch_rejects_non_numeric_phone_text(self) -> None:
|
|
with self.assertRaises(ValidationError):
|
|
UserProfilePatch(phone="전화번호아님텍스트")
|
|
|
|
def test_profile_patch_allows_omitted_phone(self) -> None:
|
|
patch = UserProfilePatch()
|
|
self.assertIsNone(patch.phone)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|