Files
sam-scenarios/attendance-settings.json
light cff20a6c0e refactor: navigation 속성 추가 (targetUrl, urlPattern, menuHints)
- 54개 시나리오 파일에 URL 기반 메뉴 탐색을 위한 navigation 속성 추가
- targetUrl: 정확한 페이지 URL 경로
- urlPattern: ko 버전 포함 URL 패턴 (regex)
- menuHints: 메뉴명 힌트 배열 (fallback용)

메뉴 탐색 실패율 41.8% → URL 기반 방식으로 개선 예정

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 21:47:29 +09:00

399 lines
12 KiB
JSON

{
"id": "attendance-settings",
"name": "설정 - 근태설정",
"screenshotPolicy": {
"onErrorOnly": true,
"captureOn": ["error", "fail", "timeout", "404", "500", "blocked"]
},
"url": "/ko/settings/attendance-settings",
"navigation": {
"targetUrl": "/settings/attendance-settings",
"urlPattern": "/settings/attendance-settings|/ko/settings/attendance-settings",
"menuHints": ["근태설정", "근태 설정", "설정"]
},
"menuNavigation": {
"level1": "설정",
"level2": "근태설정",
"expectedUrl": "/ko/settings/attendance-settings"
},
"menuNavigationEnhanced": {
"strategy": "scroll-and-search",
"sidebarSelector": ".sidebar-scroll, [data-testid='sidebar'], nav[role='navigation']",
"scrollStep": 200,
"maxScrollAttempts": 10,
"waitAfterScroll": 300,
"level1": {
"text": "설정",
"selectors": [
"button:has-text('설정')",
"[data-menu='settings']",
"a:has-text('설정')"
]
},
"level2": {
"text": "근태설정",
"selectors": [
"a:has-text('근태설정')",
"[href*='attendance-settings']",
"button:has-text('근태설정')"
]
},
"fallbackUrl": "/ko/settings/attendance-settings"
},
"expectedAPIs": [
{
"method": "GET",
"path": "/api/v1/settings/attendance",
"description": "출퇴근 설정 조회"
},
{
"method": "GET",
"path": "/api/v1/departments/tree",
"description": "부서 트리 조회"
},
{
"method": "PUT",
"path": "/api/v1/settings/attendance",
"description": "출퇴근 설정 저장"
}
],
"steps": [
{
"id": 0,
"name": "사이드바 메뉴 전체 펼치기",
"description": "모두 펼치기 버튼을 클릭하여 전체 메뉴를 펼친 후 메뉴 탐색 준비",
"actions": [
{ "type": "evaluate", "script": "document.querySelector('.sidebar-scroll, [data-testid=\"sidebar\"], nav[role=\"navigation\"]')?.scrollTo({top:0,behavior:'instant'})" },
{ "type": "wait", "duration": 300 },
{ "type": "evaluate", "script": "Array.from(document.querySelectorAll('button')).find(b => b.innerText?.includes('모두 펼치기'))?.click()" },
{ "type": "wait", "duration": 2000 }
],
"expected": {
"sidebarReady": true
}
},
{
"id": 1,
"name": "2단계 메뉴 진입: 설정 > 근태설정",
"description": "설정 > 근태설정 메뉴로 이동하여 페이지 로드 확인 (scrollAndFind 패턴 사용)",
"actions": [
{ "type": "scrollAndFind", "target": "설정", "container": ".sidebar-scroll", "scrollStep": 200, "maxAttempts": 10 },
{ "type": "click", "target": "설정" },
{ "type": "wait", "duration": 500 },
{ "type": "scrollAndFind", "target": "근태설정", "container": ".sidebar-scroll", "scrollStep": 200, "maxAttempts": 10 },
{ "type": "click", "target": "근태설정" },
{ "type": "wait", "target": "페이지 로드 완료" }
],
"expected": {
"url": "/ko/settings/attendance-settings",
"title": "출퇴근관리",
"authenticated": true
}
},
{
"id": 2,
"name": "페이지 제목 확인",
"action": "verify",
"target": "heading",
"expected": "'출퇴근관리' 텍스트 표시"
},
{
"id": 3,
"name": "설명 텍스트 확인",
"action": "verify",
"target": "description",
"expected": "'출퇴근 방법을 관리합니다.' 텍스트 표시"
},
{
"id": 4,
"name": "GPS 출퇴근 카드 확인",
"action": "verify",
"target": "card",
"expected": "'GPS 출퇴근' 카드 표시"
},
{
"id": 5,
"name": "자동 출퇴근 카드 확인",
"action": "verify",
"target": "card",
"expected": "'자동 출퇴근' 카드 표시"
},
{
"id": 6,
"name": "저장 버튼 확인",
"action": "verify",
"target": "button",
"expected": "'저장' 버튼 표시 (초기 상태 비활성화 가능)"
},
{
"id": 7,
"name": "초기 설정 상태 확인",
"action": "verify",
"target": "checkboxes",
"expected": "GPS 출퇴근, 자동 출퇴근 체크박스 상태 확인"
},
{
"id": 8,
"name": "GPS 출퇴근 비활성화 상태 - 연동 부서 비활성화 확인",
"action": "verify",
"target": "combobox",
"expected": "GPS 체크박스가 OFF일 때 연동 부서 콤보박스 비활성화"
},
{
"id": 9,
"name": "GPS 출퇴근 비활성화 상태 - 허용 반경 비활성화 확인",
"action": "verify",
"target": "select",
"expected": "GPS 체크박스가 OFF일 때 허용 반경 셀렉트 비활성화"
},
{
"id": 10,
"name": "GPS 출퇴근 활성화",
"action": "click",
"target": "GPS 출퇴근 체크박스",
"expected": "체크박스 선택됨",
"critical": true
},
{
"id": 11,
"name": "GPS 활성화 후 - 연동 부서 활성화 확인",
"action": "verify",
"target": "combobox",
"expected": "연동 부서 콤보박스 활성화됨"
},
{
"id": 12,
"name": "GPS 활성화 후 - 허용 반경 활성화 확인",
"action": "verify",
"target": "select",
"expected": "허용 반경 셀렉트 활성화됨"
},
{
"id": 13,
"name": "GPS 연동 부서 콤보박스 클릭",
"action": "click",
"target": "GPS 연동 부서 콤보박스",
"expected": "부서 선택 드롭다운 열림"
},
{
"id": 14,
"name": "GPS 부서 선택 - 첫 번째 부서",
"action": "select",
"target": "부서 옵션",
"expected": "첫 번째 부서 선택됨"
},
{
"id": 15,
"name": "GPS 부서 선택 - 두 번째 부서",
"action": "select",
"target": "부서 옵션",
"expected": "두 번째 부서 추가 선택됨 (다중 선택)"
},
{
"id": 16,
"name": "GPS 연동 부서 드롭다운 닫기",
"action": "click",
"target": "외부 영역",
"expected": "드롭다운 닫힘, 선택된 부서 표시"
},
{
"id": 17,
"name": "허용 반경 드롭다운 클릭",
"action": "click",
"target": "허용 반경 셀렉트",
"expected": "반경 옵션 드롭다운 열림"
},
{
"id": 18,
"name": "허용 반경 변경",
"action": "select",
"target": "300M 옵션",
"expected": "'300M' 선택됨",
"critical": true
},
{
"id": 19,
"name": "자동 출퇴근 활성화",
"action": "click",
"target": "자동 출퇴근 체크박스",
"expected": "체크박스 선택됨",
"critical": true
},
{
"id": 20,
"name": "자동 출퇴근 활성화 후 - 연동 부서 활성화 확인",
"action": "verify",
"target": "combobox",
"expected": "자동 출퇴근 연동 부서 콤보박스 활성화됨"
},
{
"id": 21,
"name": "자동 출퇴근 연동 부서 콤보박스 클릭",
"action": "click",
"target": "자동 출퇴근 연동 부서 콤보박스",
"expected": "부서 선택 드롭다운 열림"
},
{
"id": 22,
"name": "자동 출퇴근 부서 선택",
"action": "select",
"target": "부서 옵션",
"expected": "부서 선택됨"
},
{
"id": 23,
"name": "자동 출퇴근 연동 부서 드롭다운 닫기",
"action": "click",
"target": "외부 영역",
"expected": "드롭다운 닫힘"
},
{
"id": 24,
"name": "저장 버튼 클릭",
"action": "click",
"target": "저장 버튼",
"expected": "저장 API 호출, 로딩 상태 표시",
"critical": true
},
{
"id": 25,
"name": "저장 완료 토스트 확인",
"action": "verify",
"target": "toast",
"expected": "'출퇴근 설정이 저장되었습니다.' 토스트 표시"
},
{
"id": 26,
"name": "URL 유지 확인",
"action": "verify",
"target": "url",
"expected": "URL이 /settings/attendance-settings 유지 (에러 페이지 이동 없음)"
},
{
"id": 27,
"name": "페이지 새로고침",
"action": "reload",
"target": "page",
"expected": "페이지 새로고침 후 GET API 재호출"
},
{
"id": 28,
"name": "설정 지속성 확인 - GPS 출퇴근",
"action": "verify",
"target": "checkbox",
"expected": "GPS 출퇴근 체크박스 선택 상태 유지"
},
{
"id": 29,
"name": "설정 지속성 확인 - 허용 반경",
"action": "verify",
"target": "select",
"expected": "허용 반경 300M 선택 상태 유지"
},
{
"id": 30,
"name": "GPS 출퇴근 비활성화",
"action": "click",
"target": "GPS 출퇴근 체크박스",
"expected": "체크박스 선택 해제"
},
{
"id": 31,
"name": "GPS 비활성화 후 - 연동 부서 초기화 확인",
"action": "verify",
"target": "combobox",
"expected": "연동 부서 '부서 선택' 상태로 초기화 (UI 전용)"
},
{
"id": 32,
"name": "GPS 비활성화 후 - 허용 반경 초기화 확인",
"action": "verify",
"target": "select",
"expected": "허용 반경 '100M'로 초기화 (UI 전용)"
},
{
"id": 33,
"name": "GPS 비활성화 후 - 컨트롤 비활성화 확인",
"action": "verify",
"target": "controls",
"expected": "연동 부서 및 허용 반경 비활성화됨"
},
{
"id": 34,
"name": "자동 출퇴근 비활성화",
"action": "click",
"target": "자동 출퇴근 체크박스",
"expected": "체크박스 선택 해제"
},
{
"id": 35,
"name": "자동 출퇴근 비활성화 후 - 연동 부서 초기화 확인",
"action": "verify",
"target": "combobox",
"expected": "연동 부서 '부서 선택' 상태로 초기화 (UI 전용)"
},
{
"id": 36,
"name": "자동 출퇴근 비활성화 후 - 컨트롤 비활성화 확인",
"action": "verify",
"target": "combobox",
"expected": "연동 부서 비활성화됨"
},
{
"id": 37,
"name": "비활성화 상태 저장",
"action": "click",
"target": "저장 버튼",
"expected": "저장 API 호출"
},
{
"id": 38,
"name": "비활성화 저장 완료 확인",
"action": "verify",
"target": "toast",
"expected": "'출퇴근 설정이 저장되었습니다.' 토스트 표시"
},
{
"id": 39,
"name": "모든 허용 반경 옵션 테스트 - 50M",
"action": "test-options",
"target": "허용 반경 셀렉트",
"expected": "50M, 100M, 300M, 500M 옵션 모두 선택 가능"
},
{
"id": 40,
"name": "콘솔 에러 확인",
"action": "verify",
"target": "console",
"expected": "콘솔에 에러 로그 없음"
},
{
"id": 41,
"name": "안내 문구 확인",
"action": "verify",
"target": "help-text",
"expected": "3개의 안내 문구 표시"
},
{
"id": 42,
"name": "최종 상태 확인",
"action": "verify",
"target": "page",
"expected": "페이지 정상 동작, 모든 설정 저장됨"
}
],
"testData": {
"settings": {
"gpsEnabled": true,
"allowedRadius": 300,
"autoEnabled": true
},
"radiusOptions": [
{ "value": 50, "label": "50M" },
{ "value": 100, "label": "100M" },
{ "value": 300, "label": "300M" },
{ "value": 500, "label": "500M" }
]
}
}