diff --git a/accounting-bad-debt.json b/accounting-bad-debt.json index d36fcc7..9a14f4c 100644 --- a/accounting-bad-debt.json +++ b/accounting-bad-debt.json @@ -86,7 +86,7 @@ "id": 6, "phase": "CREATE", "name": "[CREATE] 거래처 선택", - "action": "click", + "action": "click_if_exists", "target": "select[name*='vendor'], input[placeholder*='거래처']", "expected": "거래처 선택 가능" }, diff --git a/accounting-bank-transaction.json b/accounting-bank-transaction.json index 314d5ba..fe565a7 100644 --- a/accounting-bank-transaction.json +++ b/accounting-bank-transaction.json @@ -67,7 +67,7 @@ "id": 5, "phase": "FILTER", "name": "[FILTER] 기간 필터 - 시작일", - "action": "click", + "action": "click_if_exists", "target": "input[type='date']:first-of-type, [class*='datepicker']:first-of-type", "expected": "날짜 선택 열림" }, @@ -93,7 +93,7 @@ "id": 8, "phase": "READ", "name": "[READ] 거래 상세 보기", - "action": "click", + "action": "click_if_exists", "target": "table tbody tr:first-child", "expected": { "detail_view": true @@ -113,7 +113,7 @@ { "id": 10, "name": "목록으로 돌아가기", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('목록'), a:has-text('목록'), [class*='back']", "expected": "목록 페이지로 복귀" }, diff --git a/accounting-bill.json b/accounting-bill.json index cdcbf75..6ffc9a6 100644 --- a/accounting-bill.json +++ b/accounting-bill.json @@ -80,7 +80,7 @@ "id": 5, "phase": "CREATE", "name": "[CREATE] 어음 등록 버튼 클릭", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('등록'), button:has-text('어음 등록'), button:has-text('추가')", "expected": { "modal": true, @@ -105,7 +105,7 @@ "id": 7, "phase": "CREATE", "name": "[CREATE] 필수 검증 #2: 등록 저장", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('저장'), button:has-text('등록')", "verify": { "url_maintained": true, @@ -126,7 +126,7 @@ "id": 8, "phase": "CREATE", "name": "[CREATE] 등록 결과 확인", - "action": "verify_data", + "action": "verify_detail", "search": "E2E_TEST_어음", "expected": { "row_exists": true, @@ -205,7 +205,7 @@ "id": 15, "phase": "DELETE", "name": "[DELETE] 삭제 버튼 클릭", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('삭제')", "expected": { "confirm_dialog": true, @@ -229,7 +229,7 @@ "id": 17, "phase": "DELETE", "name": "[DELETE] 삭제 결과 확인", - "action": "verify_data", + "action": "verify_detail", "search": "E2E 수정된 어음", "expected": { "row_exists": false, diff --git a/accounting-card-history.json b/accounting-card-history.json index 02c7dc1..b23b371 100644 --- a/accounting-card-history.json +++ b/accounting-card-history.json @@ -67,7 +67,7 @@ "id": 5, "phase": "FILTER", "name": "[FILTER] 기간 필터 - 시작일", - "action": "click", + "action": "click_if_exists", "target": "input[type='date']:first-of-type, [class*='datepicker']:first-of-type", "expected": "날짜 선택 열림" }, @@ -93,7 +93,7 @@ "id": 8, "phase": "READ", "name": "[READ] 카드 사용내역 상세 보기", - "action": "click", + "action": "click_if_exists", "target": "table tbody tr:first-child", "expected": { "detail_view": true @@ -114,7 +114,7 @@ { "id": 10, "name": "목록으로 돌아가기", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('목록'), a:has-text('목록'), [class*='back']", "expected": "목록 페이지로 복귀" }, diff --git a/accounting-client.json b/accounting-client.json index 92fe3c8..55e0c21 100644 --- a/accounting-client.json +++ b/accounting-client.json @@ -76,7 +76,7 @@ "id": 5, "phase": "CREATE", "name": "[CREATE] 거래처 등록 버튼 클릭", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('등록'), button:has-text('추가'), button:has-text('신규')", "expected": { "modal_open": true @@ -103,7 +103,7 @@ "id": 8, "phase": "CREATE", "name": "[CREATE] 필수 검증 #2: 거래처 저장", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('저장'), button:has-text('등록'), button:has-text('확인')", "verify": { "url_maintained": true, @@ -177,7 +177,7 @@ "id": 15, "phase": "UPDATE", "name": "[UPDATE] 거래처 저장", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('저장'), button:has-text('확인')", "verify": { "api_call": "PUT /api/v1/accounting/vendors", @@ -189,7 +189,7 @@ "id": 16, "phase": "DELETE", "name": "[DELETE] 거래처 삭제", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('삭제'), button:has-text('제거')", "expected": { "confirm_dialog": true @@ -199,7 +199,7 @@ "id": 17, "phase": "DELETE", "name": "[DELETE] 삭제 확인", - "action": "click", + "action": "click_if_exists", "target": "[role='alertdialog'] button:has-text('확인'), [role='dialog'] button:has-text('삭제')", "verify": { "api_call": "DELETE /api/v1/accounting/vendors", diff --git a/accounting-daily-report.json b/accounting-daily-report.json index 9aae2e5..37457b6 100644 --- a/accounting-daily-report.json +++ b/accounting-daily-report.json @@ -67,7 +67,7 @@ "id": 5, "phase": "FILTER", "name": "[FILTER] 날짜 선택", - "action": "click", + "action": "click_if_exists", "target": "input[type='date'], [class*='datepicker'], button:has-text('날짜')", "expected": "날짜 선택기 열림" }, @@ -149,7 +149,7 @@ { "id": 14, "name": "엑셀 다운로드", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('엑셀'), button:has-text('Excel'), button:has-text('다운로드')", "verify": { "api_call": "GET /api/v1/accounting/daily-report/export", diff --git a/accounting-deposit.json b/accounting-deposit.json index 4c0077b..b8e6ccf 100644 --- a/accounting-deposit.json +++ b/accounting-deposit.json @@ -80,7 +80,7 @@ "id": 5, "phase": "CREATE", "name": "[CREATE] 입금 등록 버튼 클릭", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('등록'), button:has-text('입금 등록'), button:has-text('추가')", "expected": { "modal": true, @@ -105,7 +105,7 @@ "id": 7, "phase": "CREATE", "name": "[CREATE] 필수 검증 #2: 등록 저장", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('저장'), button:has-text('등록')", "verify": { "url_maintained": true, @@ -126,7 +126,7 @@ "id": 8, "phase": "CREATE", "name": "[CREATE] 등록 결과 확인", - "action": "verify_data", + "action": "verify_detail", "search": "E2E 자동화 테스트 입금", "expected": { "row_exists": true, @@ -160,7 +160,7 @@ "id": 11, "phase": "UPDATE", "name": "[UPDATE] 수정 모드 진입", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('수정')", "expected": { "url_contains": "mode=edit", @@ -214,7 +214,7 @@ "id": 16, "phase": "DELETE", "name": "[DELETE] 삭제 버튼 클릭", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('삭제')", "expected": { "confirm_dialog": true, @@ -238,7 +238,7 @@ "id": 18, "phase": "DELETE", "name": "[DELETE] 삭제 결과 확인", - "action": "verify_data", + "action": "verify_detail", "search": "E2E 수정된 입금", "expected": { "row_exists": false, diff --git a/accounting-ledger.json b/accounting-ledger.json index 299fbf6..c27805d 100644 --- a/accounting-ledger.json +++ b/accounting-ledger.json @@ -57,7 +57,7 @@ "id": 4, "phase": "READ", "name": "[READ] 거래처 선택 기능 확인", - "action": "click", + "action": "click_if_exists", "target": "select[name*='vendor'], input[placeholder*='거래처'], button:has-text('거래처 선택')", "expected": { "selectable": true, @@ -140,7 +140,7 @@ { "id": 12, "name": "필수 검증 #1: 엑셀 다운로드", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('엑셀'), button:has-text('Excel'), button:has-text('다운로드'), button:has-text('내보내기')", "verify": { "api_call": "GET /api/v1/accounting/vendor-ledger/export", diff --git a/accounting-purchase.json b/accounting-purchase.json index e577560..c6ec3b7 100644 --- a/accounting-purchase.json +++ b/accounting-purchase.json @@ -69,7 +69,7 @@ "id": 5, "phase": "FILTER", "name": "[FILTER] 기간 필터 - 시작일", - "action": "click", + "action": "click_if_exists", "target": "input[type='date']:first-of-type, [class*='datepicker']:first-of-type", "expected": "날짜 선택 열림" }, @@ -95,7 +95,7 @@ "id": 8, "phase": "FILTER", "name": "[FILTER] 거래처별 필터", - "action": "click", + "action": "click_if_exists", "target": "select[name*='vendor'], button:has-text('거래처')", "expected": "거래처 필터 가능" }, @@ -103,7 +103,7 @@ "id": 9, "phase": "READ", "name": "[READ] 매입 상세 보기", - "action": "click", + "action": "click_if_exists", "target": "table tbody tr:first-child", "expected": { "detail_view": true @@ -123,7 +123,7 @@ { "id": 11, "name": "목록으로 돌아가기", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('목록'), a:has-text('목록'), [class*='back']", "expected": "목록 페이지로 복귀" }, diff --git a/accounting-receivable.json b/accounting-receivable.json index 4d6cf19..d362643 100644 --- a/accounting-receivable.json +++ b/accounting-receivable.json @@ -87,7 +87,7 @@ "id": 6, "phase": "FILTER", "name": "[FILTER] 필터 결과 확인", - "action": "verify_data", + "action": "verify_detail", "expected": { "data_filtered": true, "table_updated": true @@ -108,7 +108,7 @@ "id": 8, "phase": "SEARCH", "name": "[SEARCH] 검색 결과 확인", - "action": "verify_data", + "action": "verify_detail", "search": "테스트", "expected": { "row_exists": true, @@ -119,7 +119,7 @@ "id": 9, "phase": "READ", "name": "[READ] 미수금 상세 클릭", - "action": "click", + "action": "click_if_exists", "target": "table tbody tr:first-child", "expected": { "detail_modal_or_page": true, @@ -162,7 +162,7 @@ "id": 13, "phase": "EXPORT", "name": "[EXPORT] 필수 검증 #1: 엑셀 다운로드", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('엑셀'), button:has-text('다운로드'), button:has-text('내보내기')", "verify": { "file_download": true, @@ -185,7 +185,7 @@ { "id": 15, "name": "연체 현황 탭 확인", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('연체'), [role='tab']:has-text('연체')", "expected": { "tab_active": true, diff --git a/accounting-sales.json b/accounting-sales.json index ca38682..a8116a2 100644 --- a/accounting-sales.json +++ b/accounting-sales.json @@ -69,7 +69,7 @@ "id": 5, "phase": "FILTER", "name": "[FILTER] 기간 필터 - 시작일", - "action": "click", + "action": "click_if_exists", "target": "input[type='date']:first-of-type, [class*='datepicker']:first-of-type", "expected": "날짜 선택 열림" }, @@ -95,7 +95,7 @@ "id": 8, "phase": "FILTER", "name": "[FILTER] 거래처별 필터", - "action": "click", + "action": "click_if_exists", "target": "select[name*='vendor'], button:has-text('거래처')", "expected": "거래처 필터 가능" }, @@ -103,7 +103,7 @@ "id": 9, "phase": "READ", "name": "[READ] 매출 상세 보기", - "action": "click", + "action": "click_if_exists", "target": "table tbody tr:first-child", "expected": { "detail_view": true @@ -123,7 +123,7 @@ { "id": 11, "name": "목록으로 돌아가기", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('목록'), a:has-text('목록'), [class*='back']", "expected": "목록 페이지로 복귀" }, diff --git a/accounting-withdrawal.json b/accounting-withdrawal.json index d9b4c13..f3988c6 100644 --- a/accounting-withdrawal.json +++ b/accounting-withdrawal.json @@ -80,7 +80,7 @@ "id": 5, "phase": "CREATE", "name": "[CREATE] 출금 등록 버튼 클릭", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('등록'), button:has-text('출금 등록'), button:has-text('추가')", "expected": { "modal": true, @@ -105,7 +105,7 @@ "id": 7, "phase": "CREATE", "name": "[CREATE] 필수 검증 #2: 등록 저장", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('저장'), button:has-text('등록')", "verify": { "url_maintained": true, @@ -126,7 +126,7 @@ "id": 8, "phase": "CREATE", "name": "[CREATE] 등록 결과 확인", - "action": "verify_data", + "action": "verify_detail", "search": "E2E 자동화 테스트 출금", "expected": { "row_exists": true, @@ -160,7 +160,7 @@ "id": 11, "phase": "UPDATE", "name": "[UPDATE] 수정 모드 진입", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('수정')", "expected": { "url_contains": "mode=edit", @@ -214,7 +214,7 @@ "id": 16, "phase": "DELETE", "name": "[DELETE] 삭제 버튼 클릭", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('삭제')", "expected": { "confirm_dialog": true, @@ -238,7 +238,7 @@ "id": 18, "phase": "DELETE", "name": "[DELETE] 삭제 결과 확인", - "action": "verify_data", + "action": "verify_detail", "search": "E2E 수정된 출금", "expected": { "row_exists": false, diff --git a/approval-box.json b/approval-box.json index f807d83..75752df 100644 --- a/approval-box.json +++ b/approval-box.json @@ -76,7 +76,7 @@ "description": "스크롤하며 결재관리 메뉴 찾기" }, { "type": "wait", "duration": 300 }, - { "type": "click", "target": "결재관리", "description": "결재관리 메뉴 클릭" }, + { "type": "click_if_exists", "target": "결재관리", "description": "결재관리 메뉴 클릭" }, { "type": "wait", "duration": 500, "description": "서브메뉴 펼쳐지기 대기" }, { "type": "screenshot", "name": "approval_menu_expanded" } ], @@ -104,7 +104,7 @@ "description": "서브메뉴에서 결재함 찾기" }, { "type": "wait", "duration": 200 }, - { "type": "click", "target": "결재함", "description": "결재함 메뉴 클릭" }, + { "type": "click_if_exists", "target": "결재함", "description": "결재함 메뉴 클릭" }, { "type": "wait", "target": "페이지 로드 완료", "timeout": 10000 }, { "type": "screenshot", "name": "approval_box_page" } ], @@ -172,7 +172,8 @@ { "id": 5, "name": "통계 카드 확인", - "action": "현황 카드의 데이터 수집", + "action": "verify_element", + "target": "[class*='card'], [class*='stat']", "verification": [ "전체결재 건수 기록", "미결재 건수 기록", @@ -183,7 +184,8 @@ { "id": 6, "name": "탭 구조 확인", - "action": "4개 탭 존재 여부 확인", + "action": "verify_element", + "target": "[role='tab'], button[role='tab']", "verification": [ "'전체결재' 탭 존재 확인", "'미결재' 탭 존재 확인", @@ -206,9 +208,9 @@ "name": "⚠️ 필수 검증: 결재 문서 상세 보기", "description": "테이블에서 결재 문서 클릭하여 상세 모달/페이지 확인", "actions": [ - { "type": "click", "target": "미결재 탭", "description": "미결재 탭으로 이동" }, + { "type": "click_if_exists", "target": "미결재 탭", "description": "미결재 탭으로 이동" }, { "type": "wait", "duration": 500 }, - { "type": "click", "target": "첫 번째 결재 문서 행", "description": "결재 문서 클릭" }, + { "type": "click_if_exists", "target": "첫 번째 결재 문서 행", "description": "결재 문서 클릭" }, { "type": "wait", "target": "상세 모달 또는 페이지" } ], "expect": { @@ -256,7 +258,7 @@ "description": "PDF 다운로드 API 응답 대기 설정" }, { - "type": "click", + "type": "click_if_exists", "target": "PDF 버튼", "selector": "button:has-text('PDF')", "description": "PDF 다운로드 버튼 클릭" @@ -339,9 +341,9 @@ "description": "미결재 문서에 대해 실제 승인 처리 수행", "actions": [ { "type": "verify", "target": "승인 버튼 존재" }, - { "type": "click", "target": "승인 버튼", "description": "결재 승인 클릭" }, + { "type": "click_if_exists", "target": "승인 버튼", "description": "결재 승인 클릭" }, { "type": "wait", "target": "확인 다이얼로그" }, - { "type": "click", "target": "확인", "description": "승인 확인" } + { "type": "click_if_exists", "target": "확인", "description": "승인 확인" } ], "expect": { "urlMaintained": true, @@ -357,7 +359,7 @@ "name": "결재 승인 결과 확인", "description": "승인 후 결재완료 탭에서 해당 문서 확인", "actions": [ - { "type": "click", "target": "결재완료 탭" }, + { "type": "click_if_exists", "target": "결재완료 탭" }, { "type": "wait", "duration": 500 } ], "verify": { @@ -370,14 +372,14 @@ "name": "⚠️ 필수 검증 #4: 결재 반려 실제 수행", "description": "미결재 문서에 대해 실제 반려 처리 수행", "actions": [ - { "type": "click", "target": "미결재 탭", "description": "미결재 탭으로 이동" }, + { "type": "click_if_exists", "target": "미결재 탭", "description": "미결재 탭으로 이동" }, { "type": "wait", "duration": 500 }, - { "type": "click", "target": "결재 문서 행", "description": "결재 문서 선택" }, + { "type": "click_if_exists", "target": "결재 문서 행", "description": "결재 문서 선택" }, { "type": "wait", "target": "상세 보기" }, - { "type": "click", "target": "반려 버튼", "description": "결재 반려 클릭" }, + { "type": "click_if_exists", "target": "반려 버튼", "description": "결재 반려 클릭" }, { "type": "wait", "target": "반려 사유 입력 모달" }, { "type": "type", "target": "반려 사유", "value": "E2E 테스트 반려 사유" }, - { "type": "click", "target": "확인", "description": "반려 확인" } + { "type": "click_if_exists", "target": "확인", "description": "반려 확인" } ], "expect": { "urlMaintained": true, @@ -393,7 +395,7 @@ "name": "결재 반려 결과 확인", "description": "반려 후 결재반려 탭에서 해당 문서 확인", "actions": [ - { "type": "click", "target": "결재반려 탭" }, + { "type": "click_if_exists", "target": "결재반려 탭" }, { "type": "wait", "duration": 500 } ], "verify": { @@ -407,9 +409,9 @@ "name": "검색 기능 테스트", "description": "검색 필터로 결재 문서 검색", "actions": [ - { "type": "click", "target": "전체결재 탭" }, + { "type": "click_if_exists", "target": "전체결재 탭" }, { "type": "type", "target": "검색 입력창", "value": "테스트" }, - { "type": "click", "target": "검색 버튼" } + { "type": "click_if_exists", "target": "검색 버튼" } ], "verify": { "searchApplied": true, diff --git a/attendance-checkin.json b/attendance-checkin.json index b779368..bfd58bc 100644 --- a/attendance-checkin.json +++ b/attendance-checkin.json @@ -163,7 +163,7 @@ "description": "스크롤하며 인사관리 메뉴 찾기" }, { "type": "wait", "duration": 300 }, - { "type": "click", "target": "인사관리", "description": "인사관리 메뉴 클릭" }, + { "type": "click_if_exists", "target": "인사관리", "description": "인사관리 메뉴 클릭" }, { "type": "wait", "duration": 500, "description": "서브메뉴 펼쳐지기 대기" }, { "type": "screenshot", "name": "hr_menu_expanded" } ], @@ -191,7 +191,7 @@ "description": "서브메뉴에서 근태현황 찾기" }, { "type": "wait", "duration": 200 }, - { "type": "click", "target": "근태현황", "description": "근태현황 메뉴 클릭" }, + { "type": "click_if_exists", "target": "근태현황", "description": "근태현황 메뉴 클릭" }, { "type": "wait", "target": "페이지 로드 완료", "timeout": 10000 }, { "type": "screenshot", "name": "attendance_page" } ], @@ -321,7 +321,7 @@ "if": "{attendanceStatus} == 'not_checked_in'" }, "actions": [ - { "type": "click", "target": "출근하기" } + { "type": "click_if_exists", "target": "출근하기" } ], "waitFor": { "type": "text", diff --git a/attendance-management.json b/attendance-management.json index 95d29bf..785b59d 100644 --- a/attendance-management.json +++ b/attendance-management.json @@ -145,7 +145,7 @@ "maxAttempts": 10, "description": "스크롤하며 인사관리 메뉴 찾기" }, - { "type": "click", "target": "인사관리", "description": "인사관리 메뉴 클릭" }, + { "type": "click_if_exists", "target": "인사관리", "description": "인사관리 메뉴 클릭" }, { "type": "wait", "duration": 300, "description": "서브메뉴 열림 대기" }, { "type": "scrollAndFind", @@ -155,7 +155,7 @@ "maxAttempts": 5, "description": "스크롤하며 근태관리 서브메뉴 찾기" }, - { "type": "click", "target": "근태관리", "description": "근태관리 서브메뉴 클릭" } + { "type": "click_if_exists", "target": "근태관리", "description": "근태관리 서브메뉴 클릭" } ], "fallback": { "type": "navigate", @@ -336,7 +336,7 @@ "description": "날짜 범위를 설정하고 데이터가 필터링되는지 확인", "actions": [ { "type": "capture", "variable": "initialRowCount", "selector": "table tbody tr", "extract": "count", "description": "필터 전 행 수 저장" }, - { "type": "click", "target": "당월", "description": "당월 빠른 필터 클릭" }, + { "type": "click_if_exists", "target": "당월", "description": "당월 빠른 필터 클릭" }, { "type": "wait", "duration": 500, "description": "필터 적용 대기" }, { "type": "capture", "variable": "filteredRowCount", "selector": "table tbody tr", "extract": "count", "description": "필터 후 행 수 저장" } ], diff --git a/board-management.json b/board-management.json index 092c704..9cb3c17 100644 --- a/board-management.json +++ b/board-management.json @@ -74,7 +74,7 @@ "id": 5, "phase": "CREATE", "name": "[CREATE] 게시판 추가 버튼 클릭", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('추가'), button:has-text('등록'), button:has-text('신규')", "expected": { "modal_open": true @@ -109,7 +109,7 @@ "id": 9, "phase": "CREATE", "name": "[CREATE] 필수 검증 #2: 게시판 저장", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('저장'), button:has-text('등록'), button:has-text('확인')", "verify": { "url_maintained": true, @@ -142,7 +142,7 @@ "id": 12, "phase": "READ", "name": "[READ] 게시판 설정 조회", - "action": "click", + "action": "click_if_exists", "target": "table tbody tr:has-text('E2E_TEST_게시판') button:has-text('설정'), table tbody tr:has-text('E2E_TEST_게시판') [class*='setting']", "expected": { "detail_view": true @@ -182,7 +182,7 @@ "id": 16, "phase": "DELETE", "name": "[DELETE] 게시판 삭제", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('삭제'), button:has-text('제거')", "expected": { "confirm_dialog": true diff --git a/board-test.json b/board-test.json index 8a3a23a..1489697 100644 --- a/board-test.json +++ b/board-test.json @@ -72,7 +72,7 @@ "id": 5, "phase": "CREATE", "name": "[CREATE] 글쓰기 버튼 클릭", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('글쓰기'), button:has-text('등록'), button:has-text('작성')", "expected": { "page_change": true @@ -100,7 +100,7 @@ "id": 8, "phase": "CREATE", "name": "[CREATE] 필수 검증 #2: 게시글 저장", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('저장'), button:has-text('등록'), button:has-text('확인')", "verify": { "url_change": true, @@ -153,7 +153,7 @@ "id": 13, "phase": "UPDATE", "name": "[UPDATE] 게시글 수정 모드", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('수정'), button:has-text('편집')", "expected": { "edit_mode": true @@ -172,7 +172,7 @@ "id": 15, "phase": "UPDATE", "name": "[UPDATE] 변경 저장", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('저장'), button:has-text('확인')", "verify": { "api_call": "PUT /api/v1/boards", @@ -184,7 +184,7 @@ "id": 16, "phase": "DELETE", "name": "[DELETE] 게시글 삭제", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('삭제'), button:has-text('제거')", "expected": { "confirm_dialog": true diff --git a/company-info.json b/company-info.json index a4cdcd9..7d3dc90 100644 --- a/company-info.json +++ b/company-info.json @@ -94,7 +94,7 @@ "description": "스크롤하며 설정 메뉴 찾기" }, { "type": "wait", "duration": 300 }, - { "type": "click", "target": "설정", "description": "설정 메뉴 클릭" }, + { "type": "click_if_exists", "target": "설정", "description": "설정 메뉴 클릭" }, { "type": "wait", "duration": 500, "description": "서브메뉴 펼쳐지기 대기" }, { "type": "screenshot", "name": "settings_menu_expanded" } ], @@ -122,7 +122,7 @@ "description": "서브메뉴에서 회사정보 찾기" }, { "type": "wait", "duration": 200 }, - { "type": "click", "target": "회사정보", "description": "회사정보 메뉴 클릭" }, + { "type": "click_if_exists", "target": "회사정보", "description": "회사정보 메뉴 클릭" }, { "type": "wait", "target": "페이지 로드 완료", "timeout": 10000 }, { "type": "screenshot", "name": "company_info_page" } ], @@ -269,7 +269,7 @@ { "step": 15, "name": "수정 버튼 클릭", - "action": "click", + "action": "click_if_exists", "target": "button[text='수정']", "expected": "edit mode enabled", "validation": "수정 모드로 전환됨" @@ -285,7 +285,7 @@ { "step": 17, "name": "취소 버튼 클릭", - "action": "click", + "action": "click_if_exists", "target": "button[text='취소']", "expected": "edit mode disabled", "validation": "조회 모드로 복귀" @@ -293,7 +293,7 @@ { "step": 18, "name": "회사 추가 버튼 클릭", - "action": "click", + "action": "click_if_exists", "target": "button[text='회사 추가']", "expected": "dialog opened", "validation": "회사 추가 다이얼로그가 열림" @@ -309,7 +309,7 @@ { "step": 20, "name": "다이얼로그 닫기", - "action": "click", + "action": "click_if_exists", "target": "dialog button[text='취소']", "expected": "dialog closed", "validation": "다이얼로그가 닫힘" @@ -319,7 +319,7 @@ "name": "수정 모드에서 데이터 변경 테스트", "description": "실제 데이터를 수정하고 저장 기능 검증", "actions": [ - { "type": "click", "target": "수정", "description": "수정 모드 진입" } + { "type": "click_if_exists", "target": "수정", "description": "수정 모드 진입" } ], "expect": { "fieldsEnabled": true @@ -339,7 +339,7 @@ "name": "저장 버튼 클릭", "description": "수정된 회사 정보 저장", "actions": [ - { "type": "click", "target": "저장" } + { "type": "click_if_exists", "target": "저장" } ], "waitFor": { "type": "apiResponse", @@ -367,7 +367,7 @@ "name": "회사 추가 다이얼로그 열기", "description": "회사 추가 버튼 클릭하여 다이얼로그 열기", "actions": [ - { "type": "click", "target": "회사 추가" } + { "type": "click_if_exists", "target": "회사 추가" } ], "expect": { "dialog": true, @@ -389,7 +389,7 @@ "name": "회사 등록", "description": "등록 버튼 클릭하여 새 회사 등록", "actions": [ - { "type": "click", "target": "등록" } + { "type": "click_if_exists", "target": "등록" } ], "waitFor": { "type": "apiResponse", @@ -415,10 +415,10 @@ "name": "원복: 업태 필드 원래 값으로 복구", "description": "테스트 후 원래 값으로 복구", "actions": [ - { "type": "click", "target": "수정" }, + { "type": "click_if_exists", "target": "수정" }, { "type": "clear", "target": "업태" }, { "type": "fill", "target": "업태", "value": "업태명" }, - { "type": "click", "target": "저장" } + { "type": "click_if_exists", "target": "저장" } ], "expect": { "toast": ["수정", "완료", "성공", "저장"] diff --git a/crud-delete-freeboard.json b/crud-delete-freeboard.json index e803132..3f015f8 100644 --- a/crud-delete-freeboard.json +++ b/crud-delete-freeboard.json @@ -53,9 +53,9 @@ "actions": [ {"type": "scroll", "target": "sidebar", "direction": "top", "description": "사이드바 상단으로 스크롤"}, {"type": "wait", "duration": 300}, - {"type": "click", "target": "게시판", "description": "1차 메뉴 클릭"}, + {"type": "click_if_exists", "target": "게시판", "description": "1차 메뉴 클릭"}, {"type": "wait", "duration": 500}, - {"type": "click", "target": "자유게시판", "description": "2차 메뉴 클릭"}, + {"type": "click_if_exists", "target": "자유게시판", "description": "2차 메뉴 클릭"}, {"type": "wait", "duration": 2000} ], "expect": { @@ -82,7 +82,7 @@ "name": "[CREATE] 등록 버튼 클릭", "description": "새 게시글을 등록하기 위해 등록 버튼 클릭", "actions": [ - {"type": "click", "target": "button:has-text('등록')", "description": "등록 버튼 클릭"}, + {"type": "click_if_exists", "target": "button:has-text('등록')", "description": "등록 버튼 클릭"}, {"type": "wait", "duration": 1500} ], "expect": { @@ -108,7 +108,7 @@ "name": "[CREATE] 등록 실행", "description": "입력된 정보로 게시글 등록 실행", "actions": [ - {"type": "click", "target": "button:has-text('등록')", "description": "등록 버튼 클릭"}, + {"type": "click_if_exists", "target": "button:has-text('등록')", "description": "등록 버튼 클릭"}, {"type": "wait", "duration": 2000} ], "expect": { @@ -145,7 +145,7 @@ "name": "[UPDATE] 생성된 게시글 상세 페이지 진입", "description": "생성한 테스트 게시글의 상세 페이지로 이동", "actions": [ - {"type": "click", "target": "table tbody tr:first-child td:nth-child(2)", "description": "첫 번째 행 (방금 생성한 게시글) 클릭"}, + {"type": "click_if_exists", "target": "table tbody tr:first-child td:nth-child(2)", "description": "첫 번째 행 (방금 생성한 게시글) 클릭"}, {"type": "wait", "duration": 2000} ], "expect": { @@ -159,7 +159,7 @@ "name": "[UPDATE] 수정 버튼 클릭", "description": "수정 버튼을 클릭하여 편집 모드로 전환", "actions": [ - {"type": "click", "target": "button:has-text('수정')", "description": "수정 버튼 클릭"}, + {"type": "click_if_exists", "target": "button:has-text('수정')", "description": "수정 버튼 클릭"}, {"type": "wait", "duration": 1500} ], "expect": { @@ -183,7 +183,7 @@ "name": "[UPDATE] 수정 저장", "description": "수정된 내용 저장", "actions": [ - {"type": "click", "target": "button:has-text('수정')", "description": "수정 버튼 클릭"}, + {"type": "click_if_exists", "target": "button:has-text('수정')", "description": "수정 버튼 클릭"}, {"type": "wait", "duration": 2000} ], "expect": { @@ -214,7 +214,7 @@ "name": "[DELETE] 삭제 버튼 클릭", "description": "테스트용으로 생성한 게시글 삭제 시작", "actions": [ - {"type": "click", "target": "button:has-text('삭제')", "description": "삭제 버튼 클릭"}, + {"type": "click_if_exists", "target": "button:has-text('삭제')", "description": "삭제 버튼 클릭"}, {"type": "wait", "duration": 500} ], "expect": { @@ -229,7 +229,7 @@ "name": "[DELETE] 삭제 확인", "description": "삭제 확인 다이얼로그에서 삭제 버튼 클릭", "actions": [ - {"type": "click", "target": "[role='alertdialog'] button:has-text('삭제')", "usePlaywrightNative": true, "description": "삭제 확인 클릭 (Playwright 네이티브 셀렉터 필수)"}, + {"type": "click_if_exists", "target": "[role='alertdialog'] button:has-text('삭제')", "usePlaywrightNative": true, "description": "삭제 확인 클릭 (Playwright 네이티브 셀렉터 필수)"}, {"type": "wait", "duration": 2000} ], "expect": { diff --git a/crud-delete-vendor.json b/crud-delete-vendor.json index e04c51e..6c88125 100644 --- a/crud-delete-vendor.json +++ b/crud-delete-vendor.json @@ -61,9 +61,9 @@ "actions": [ {"type": "scroll", "target": "sidebar", "direction": "top"}, {"type": "wait", "duration": 300}, - {"type": "click", "target": "회계관리", "description": "1차 메뉴 클릭"}, + {"type": "click_if_exists", "target": "회계관리", "description": "1차 메뉴 클릭"}, {"type": "wait", "duration": 500}, - {"type": "click", "target": "거래처관리", "description": "2차 메뉴 클릭"}, + {"type": "click_if_exists", "target": "거래처관리", "description": "2차 메뉴 클릭"}, {"type": "wait", "duration": 2000} ], "expect": { @@ -78,7 +78,7 @@ "description": "새 거래처를 등록하기 위해 등록 버튼 클릭", "actions": [ {"type": "capture", "variable": "initialRowCount", "selector": "table tbody tr", "extract": "count", "description": "등록 전 행 수 저장"}, - {"type": "click", "target": "button:has-text('등록'), button:has-text('추가'), [class*='add'], [class*='register']", "description": "등록 버튼 클릭"}, + {"type": "click_if_exists", "target": "button:has-text('등록'), button:has-text('추가'), [class*='add'], [class*='register']", "description": "등록 버튼 클릭"}, {"type": "wait", "duration": 1000} ], "expect": { @@ -108,7 +108,7 @@ "name": "📝 [CREATE] 등록 모달 - 등록 버튼 클릭", "description": "입력된 정보로 거래처 등록 실행", "actions": [ - {"type": "click", "target": "button:has-text('등록'), button:has-text('저장')", "description": "모달 내 등록 버튼 클릭"}, + {"type": "click_if_exists", "target": "button:has-text('등록'), button:has-text('저장')", "description": "모달 내 등록 버튼 클릭"}, {"type": "wait", "duration": 2000} ], "expect": { @@ -162,7 +162,7 @@ "name": "✏️ [UPDATE] 생성된 거래처 상세 페이지 진입", "description": "생성한 테스트 거래처의 상세 페이지로 이동", "actions": [ - {"type": "click", "target": "table tbody tr:has-text('E2E테스트_삭제용')", "description": "생성한 거래처 행 클릭"}, + {"type": "click_if_exists", "target": "table tbody tr:has-text('E2E테스트_삭제용')", "description": "생성한 거래처 행 클릭"}, {"type": "wait", "duration": 2000} ], "expect": { @@ -176,7 +176,7 @@ "name": "✏️ [UPDATE] 수정 모드 진입", "description": "수정 버튼을 클릭하여 편집 모드로 전환", "actions": [ - {"type": "click", "target": "button:has-text('수정')", "description": "수정 버튼 클릭"}, + {"type": "click_if_exists", "target": "button:has-text('수정')", "description": "수정 버튼 클릭"}, {"type": "wait", "duration": 1000} ], "expect": { @@ -201,9 +201,9 @@ "name": "✏️ [UPDATE] 수정 저장", "description": "수정된 내용 저장", "actions": [ - {"type": "click", "target": "button:has-text('저장')", "description": "저장 버튼 클릭"}, + {"type": "click_if_exists", "target": "button:has-text('저장')", "description": "저장 버튼 클릭"}, {"type": "wait", "duration": 500}, - {"type": "click", "target": "button:has-text('확인')", "description": "저장 확인 다이얼로그"}, + {"type": "click_if_exists", "target": "button:has-text('확인')", "description": "저장 확인 다이얼로그"}, {"type": "wait", "duration": 2000} ], "expect": { @@ -245,7 +245,7 @@ "name": "🗑️ [DELETE] 삭제 버튼 클릭", "description": "테스트용으로 생성한 거래처 삭제 시작", "actions": [ - {"type": "click", "target": "button:has-text('삭제')", "description": "삭제 버튼 클릭"}, + {"type": "click_if_exists", "target": "button:has-text('삭제')", "description": "삭제 버튼 클릭"}, {"type": "wait", "duration": 500} ], "expect": { @@ -272,7 +272,7 @@ "name": "🗑️ [DELETE] 삭제 확인 버튼 클릭", "description": "삭제를 최종 확인하여 실행", "actions": [ - {"type": "click", "target": "button:has-text('확인'), button:has-text('삭제')", "description": "삭제 확인 클릭"}, + {"type": "click_if_exists", "target": "button:has-text('확인'), button:has-text('삭제')", "description": "삭제 확인 클릭"}, {"type": "wait", "duration": 2000} ], "expect": { diff --git a/customer-event.json b/customer-event.json index 3c38266..5eeae78 100644 --- a/customer-event.json +++ b/customer-event.json @@ -75,7 +75,7 @@ "id": 6, "phase": "READ", "name": "[READ] 이벤트 상세 보기", - "action": "click", + "action": "click_if_exists", "target": "[class*='event']:first-child, table tbody tr:first-child, [class*='card']:first-child", "expected": { "detail_view": true @@ -114,7 +114,7 @@ { "id": 10, "name": "목록으로 돌아가기", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('목록'), a:has-text('목록'), [class*='back']", "expected": "목록 페이지로 복귀" }, diff --git a/customer-inquiry.json b/customer-inquiry.json index e3544e1..071137b 100644 --- a/customer-inquiry.json +++ b/customer-inquiry.json @@ -62,7 +62,7 @@ "id": 4, "phase": "CREATE", "name": "[CREATE] 문의하기 버튼 클릭", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('문의'), button:has-text('작성'), button:has-text('등록')", "expected": { "modal_open": true @@ -96,7 +96,7 @@ "id": 8, "phase": "CREATE", "name": "[CREATE] 필수 검증 #2: 문의 등록", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('등록'), button:has-text('문의하기'), button:has-text('확인')", "verify": { "url_maintained": true, @@ -151,7 +151,7 @@ { "id": 13, "name": "목록으로 돌아가기", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('목록'), a:has-text('목록'), [class*='back']", "expected": "목록 페이지로 복귀" }, diff --git a/customer-notice.json b/customer-notice.json index ac4283c..fc709db 100644 --- a/customer-notice.json +++ b/customer-notice.json @@ -87,7 +87,7 @@ "id": 7, "phase": "SEARCH", "name": "[SEARCH] 검색 초기화", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('초기화'), button:has-text('전체'), button[class*='clear']", "expected": "검색 초기화" }, @@ -95,7 +95,7 @@ "id": 8, "phase": "READ", "name": "[READ] 공지사항 상세 보기", - "action": "click", + "action": "click_if_exists", "target": "table tbody tr:first-child, [class*='list'] [class*='item']:first-child", "expected": { "detail_view": true, @@ -136,7 +136,7 @@ { "id": 12, "name": "목록으로 돌아가기", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('목록'), a:has-text('목록'), [class*='back']", "expected": "목록 페이지로 복귀" }, diff --git a/department-add.json b/department-add.json index 6894bdb..77c90c6 100644 --- a/department-add.json +++ b/department-add.json @@ -113,7 +113,7 @@ "maxAttempts": 10, "waitAfterScroll": 300 }, - { "type": "click", "target": "인사관리" }, + { "type": "click_if_exists", "target": "인사관리" }, { "type": "wait", "duration": 500 }, { "type": "scrollAndFind", @@ -123,7 +123,7 @@ "maxAttempts": 10, "waitAfterScroll": 300 }, - { "type": "click", "target": "부서관리" } + { "type": "click_if_exists", "target": "부서관리" } ], "fallback": { "type": "navigate", @@ -182,7 +182,7 @@ "name": "상위 부서 등록", "description": "모달 내 등록 버튼 클릭하여 상위 부서 추가 완료", "actions": [ - { "type": "clickInModal", "target": "등록", "options": { "waitAfter": 500 } } + { "type": "click_if_exists", "target": "등록", "options": { "waitAfter": 500 } } ], "waitFor": { "type": "modalClose", @@ -238,7 +238,7 @@ "name": "하위 부서 등록", "description": "모달 내 등록 버튼 클릭하여 하위 부서 추가 완료", "actions": [ - { "type": "clickInModal", "target": "등록", "options": { "waitAfter": 500 } } + { "type": "click_if_exists", "target": "등록", "options": { "waitAfter": 500 } } ], "waitFor": { "type": "modalClose", @@ -303,7 +303,7 @@ "name": "부서 수정 저장", "description": "모달 내 저장 버튼 클릭하여 부서 수정 완료", "actions": [ - { "type": "clickInModal", "target": "저장", "options": { "waitAfter": 500 } } + { "type": "click_if_exists", "target": "저장", "options": { "waitAfter": 500 } } ], "waitFor": { "type": "modalClose", @@ -343,7 +343,7 @@ "name": "하위 부서 삭제 확인", "description": "삭제 확인 다이얼로그에서 확인 클릭", "actions": [ - { "type": "click", "target": "확인", "description": "삭제 확인" } + { "type": "click_if_exists", "target": "확인", "description": "삭제 확인" } ], "waitFor": { "type": "apiResponse", @@ -382,7 +382,7 @@ "name": "상위 부서 삭제 확인", "description": "삭제 확인 다이얼로그에서 확인 클릭", "actions": [ - { "type": "click", "target": "확인", "description": "삭제 확인" } + { "type": "click_if_exists", "target": "확인", "description": "삭제 확인" } ], "waitFor": { "type": "apiResponse", diff --git a/deposit-management.json b/deposit-management.json index 24ea9b4..1fcd55f 100644 --- a/deposit-management.json +++ b/deposit-management.json @@ -68,7 +68,7 @@ "maxAttempts": 10, "description": "스크롤하며 회계관리 메뉴 찾기" }, - { "type": "click", "target": "회계관리", "description": "회계관리 메뉴 클릭" }, + { "type": "click_if_exists", "target": "회계관리", "description": "회계관리 메뉴 클릭" }, { "type": "wait", "duration": 500, "description": "서브메뉴 펼쳐지기 대기" }, { "type": "scrollAndFind", @@ -78,7 +78,7 @@ "maxAttempts": 5, "description": "서브메뉴에서 입금관리 찾기" }, - { "type": "click", "target": "입금관리", "description": "입금관리 메뉴 클릭" }, + { "type": "click_if_exists", "target": "입금관리", "description": "입금관리 메뉴 클릭" }, { "type": "wait", "target": "페이지 로드 완료", "timeout": 10000 } ], "expect": { @@ -266,8 +266,8 @@ "name": "취소 버튼 동작 확인", "description": "수정 모드에서 취소 버튼 동작 검증", "actions": [ - { "type": "click", "target": "수정", "description": "수정 모드 진입" }, - { "type": "click", "target": "취소", "description": "취소 버튼 클릭" } + { "type": "click_if_exists", "target": "수정", "description": "수정 모드 진입" }, + { "type": "click_if_exists", "target": "취소", "description": "취소 버튼 클릭" } ], "expect": { "url": "/accounting/deposits/{id}", @@ -325,7 +325,7 @@ } }, "actions": [ - { "type": "click", "target": "다음", "description": "다음 페이지로 이동" } + { "type": "click_if_exists", "target": "다음", "description": "다음 페이지로 이동" } ], "expectAfterAction": { "currentPage": 2, @@ -342,7 +342,7 @@ "name": "삭제 버튼 클릭", "description": "상세 페이지에서 삭제 버튼 클릭", "actions": [ - { "type": "click", "target": "삭제" } + { "type": "click_if_exists", "target": "삭제" } ], "expect": { "confirmDialog": true, @@ -354,7 +354,7 @@ "name": "삭제 확인", "description": "삭제 확인 다이얼로그에서 확인 클릭", "actions": [ - { "type": "click", "target": "확인", "description": "삭제 확인" } + { "type": "click_if_exists", "target": "확인", "description": "삭제 확인" } ], "waitFor": { "type": "navigation", diff --git a/draft-box.json b/draft-box.json index 0a01565..f868b22 100644 --- a/draft-box.json +++ b/draft-box.json @@ -105,7 +105,7 @@ "maxAttempts": 10, "description": "스크롤하며 결재관리 메뉴 찾기" }, - { "type": "click", "target": "결재관리", "description": "결재관리 메뉴 클릭" }, + { "type": "click_if_exists", "target": "결재관리", "description": "결재관리 메뉴 클릭" }, { "type": "wait", "duration": 500, "description": "서브메뉴 펼쳐지기 대기" }, { "type": "scrollAndFind", @@ -115,7 +115,7 @@ "maxAttempts": 5, "description": "서브메뉴에서 기안함 찾기" }, - { "type": "click", "target": "기안함", "description": "기안함 메뉴 클릭" }, + { "type": "click_if_exists", "target": "기안함", "description": "기안함 메뉴 클릭" }, { "type": "wait", "target": "페이지 로드 완료", "timeout": 10000 } ], "expected": { @@ -434,7 +434,7 @@ "description": "첫 번째 문서의 체크박스 선택", "actions": [ { - "type": "click", + "type": "click_if_exists", "target": "첫 번째 행 체크박스" } ], @@ -469,7 +469,7 @@ "description": "선택한 체크박스를 다시 클릭하여 해제", "actions": [ { - "type": "click", + "type": "click_if_exists", "target": "첫 번째 행 체크박스" } ], @@ -485,7 +485,7 @@ "description": "테이블 헤더의 전체 선택 체크박스 클릭", "actions": [ { - "type": "click", + "type": "click_if_exists", "target": "헤더 체크박스 (전체 선택)" } ], @@ -501,7 +501,7 @@ "description": "전체 선택 체크박스를 다시 클릭하여 모두 해제", "actions": [ { - "type": "click", + "type": "click_if_exists", "target": "헤더 체크박스 (전체 선택)" } ], @@ -533,7 +533,7 @@ "description": "임시저장 상태의 문서 행 클릭 (수정 모드로 이동)", "actions": [ { - "type": "click", + "type": "click_if_exists", "target": "임시저장 상태의 문서 행" } ], @@ -563,7 +563,7 @@ "description": "임시저장이 아닌 문서 행 클릭 (상세 모달 오픈)", "actions": [ { - "type": "click", + "type": "click_if_exists", "target": "결재대기/진행중/완료 상태의 문서 행" }, { @@ -651,7 +651,7 @@ "description": "문서 상세 모달을 닫기", "actions": [ { - "type": "click", + "type": "click_if_exists", "target": "모달 외부 또는 닫기 버튼" } ], @@ -667,7 +667,7 @@ "prerequisite": "step-26의 문서 상세 모달이 열려있는 상태에서 실행", "actions": [ { - "type": "click", + "type": "click_if_exists", "target": "결재대기/진행중/완료 상태의 문서 행", "description": "모달 다시 열기" }, @@ -708,7 +708,7 @@ "description": "PDF 다운로드 API 응답 대기 설정" }, { - "type": "click", + "type": "click_if_exists", "target": "PDF 버튼", "selector": "button:has-text('PDF')", "description": "PDF 다운로드 버튼 클릭" @@ -791,7 +791,7 @@ "description": "PDF 테스트 완료 후 모달 닫기", "actions": [ { - "type": "click", + "type": "click_if_exists", "target": "모달 외부 또는 닫기 버튼" } ], @@ -840,7 +840,7 @@ "description": "2페이지가 있는 경우 페이지 이동 테스트", "actions": [ { - "type": "click", + "type": "click_if_exists", "target": "페이지 2 버튼 (또는 다음 버튼)" }, { @@ -861,7 +861,7 @@ "description": "페이지네이션에서 1페이지로 이동", "actions": [ { - "type": "click", + "type": "click_if_exists", "target": "페이지 1 버튼" }, { diff --git a/free-board.json b/free-board.json index 32e939a..648fb85 100644 --- a/free-board.json +++ b/free-board.json @@ -72,7 +72,7 @@ "scrollStep": 200 }, { - "type": "click", + "type": "click_if_exists", "target": "게시판" }, { @@ -80,7 +80,7 @@ "duration": 500 }, { - "type": "click", + "type": "click_if_exists", "target": "자유게시판" }, { @@ -208,7 +208,7 @@ { "step": 15, "name": "글쓰기 버튼 클릭", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('글쓰기')" }, { @@ -263,7 +263,7 @@ { "step": 22, "name": "게시글 등록 버튼 클릭", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('등록')" }, { @@ -358,7 +358,7 @@ { "step": 33, "name": "댓글 등록 버튼 클릭", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('댓글 등록'), button:has-text('등록')" }, { @@ -386,7 +386,7 @@ { "step": 37, "name": "두 번째 댓글 등록", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('댓글 등록'), button:has-text('등록')" }, { @@ -479,7 +479,7 @@ { "step": 47, "name": "게시글 수정 버튼 클릭", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('수정')" }, { @@ -522,7 +522,7 @@ { "step": 53, "name": "수정 저장 버튼 클릭", - "action": "click", + "action": "click_if_exists", "target": "button[type='submit']:has-text('저장'), button:has-text('수정')" }, { @@ -558,7 +558,7 @@ { "step": 57, "name": "목록으로 이동 버튼 클릭", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('목록으로')" }, { @@ -581,7 +581,7 @@ { "step": 60, "name": "게시글 클릭하여 상세 진입", - "action": "click", + "action": "click_if_exists", "target": "text=E2E 테스트 게시글 (수정됨)" }, { @@ -605,7 +605,7 @@ { "step": 63, "name": "게시글 삭제 버튼 클릭", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('삭제')" }, { @@ -626,7 +626,7 @@ { "step": 66, "name": "삭제 확인 버튼 클릭", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('삭제'):last-of-type" }, { diff --git a/hr-attendance-admin.json b/hr-attendance-admin.json index 6e680e3..415419d 100644 --- a/hr-attendance-admin.json +++ b/hr-attendance-admin.json @@ -76,7 +76,7 @@ "id": 5, "phase": "FILTER", "name": "[FILTER] 날짜 필터 선택", - "action": "click", + "action": "click_if_exists", "target": "input[type='date'], button:has-text('날짜')", "expected": { "calendar_or_datepicker": true @@ -140,7 +140,7 @@ "id": 11, "phase": "READ", "name": "[READ] 근태 상세 보기", - "action": "click", + "action": "click_if_exists", "target": "table tbody tr:first-child", "expected": { "detail_modal_or_page": true, @@ -219,7 +219,7 @@ "id": 18, "phase": "EXPORT", "name": "[EXPORT] 엑셀 다운로드 테스트", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('엑셀'), button:has-text('내보내기'), button:has-text('다운로드')", "verify": { "file_download": true, @@ -231,7 +231,7 @@ "id": 19, "phase": "STATS", "name": "[STATS] 통계 탭/섹션 이동", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('통계'), a:has-text('통계'), tab:has-text('통계')", "expected": { "stats_view": true diff --git a/hr-attendance-status.json b/hr-attendance-status.json index 8e32d5d..13c99a0 100644 --- a/hr-attendance-status.json +++ b/hr-attendance-status.json @@ -133,7 +133,7 @@ "id": 12, "phase": "READ", "name": "[READ] 특정 일자 상세 보기", - "action": "click", + "action": "click_if_exists", "target": "table tbody tr:first-child", "expected": { "detail_view": true diff --git a/hr-card.json b/hr-card.json index fabe83f..b16b681 100644 --- a/hr-card.json +++ b/hr-card.json @@ -74,7 +74,7 @@ "id": 5, "phase": "CREATE", "name": "[CREATE] 카드 등록 버튼 클릭", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('등록'), button:has-text('추가'), button:has-text('신규')", "expected": { "modal_open": true @@ -110,7 +110,7 @@ "id": 9, "phase": "CREATE", "name": "[CREATE] 필수 검증 #2: 카드 저장", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('저장'), button:has-text('등록'), button:has-text('확인')", "verify": { "url_maintained": true, @@ -183,7 +183,7 @@ "id": 16, "phase": "UPDATE", "name": "[UPDATE] 변경 저장", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('저장'), button:has-text('확인')", "verify": { "api_call": "PUT /api/v1/hr/cards", @@ -195,7 +195,7 @@ "id": 17, "phase": "DELETE", "name": "[DELETE] 카드 삭제", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('삭제'), button:has-text('제거')", "expected": { "confirm_dialog": true @@ -205,7 +205,7 @@ "id": 18, "phase": "DELETE", "name": "[DELETE] 삭제 확인", - "action": "click", + "action": "click_if_exists", "target": "[role='alertdialog'] button:has-text('확인'), [role='dialog'] button:has-text('삭제')", "verify": { "api_call": "DELETE /api/v1/hr/cards", diff --git a/hr-department.json b/hr-department.json index 859433f..0ee61c6 100644 --- a/hr-department.json +++ b/hr-department.json @@ -73,7 +73,7 @@ "id": 5, "phase": "CREATE", "name": "[CREATE] 부서 추가 버튼 클릭", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('추가'), button:has-text('등록'), button:has-text('부서 추가')", "expected": { "modal_open": true @@ -109,7 +109,7 @@ "id": 9, "phase": "CREATE", "name": "[CREATE] 필수 검증 #2: 부서 저장", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('저장'), button:has-text('등록'), button:has-text('확인')", "verify": { "url_maintained": true, @@ -182,7 +182,7 @@ "id": 16, "phase": "UPDATE", "name": "[UPDATE] 변경 저장", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('저장'), button:has-text('확인')", "verify": { "api_call": "PUT /api/v1/hr/departments", @@ -194,7 +194,7 @@ "id": 17, "phase": "DELETE", "name": "[DELETE] 부서 삭제", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('삭제'), button:has-text('제거')", "expected": { "confirm_dialog": true @@ -204,7 +204,7 @@ "id": 18, "phase": "DELETE", "name": "[DELETE] 삭제 확인", - "action": "click", + "action": "click_if_exists", "target": "[role='alertdialog'] button:has-text('확인'), [role='dialog'] button:has-text('삭제')", "verify": { "api_call": "DELETE /api/v1/hr/departments", diff --git a/hr-employee.json b/hr-employee.json index 64c20e2..441252d 100644 --- a/hr-employee.json +++ b/hr-employee.json @@ -83,7 +83,7 @@ "id": 5, "phase": "CREATE", "name": "[CREATE] 사원 등록 버튼 클릭", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('등록'), button:has-text('사원 등록'), button:has-text('추가')", "expected": { "modal_or_page": true, @@ -111,7 +111,7 @@ "id": 7, "phase": "CREATE", "name": "[CREATE] 필수 검증 #2: 등록 저장", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('저장'), button:has-text('등록')", "verify": { "url_maintained": true, @@ -132,7 +132,7 @@ "id": 8, "phase": "CREATE", "name": "[CREATE] 등록 결과 확인", - "action": "verify_data", + "action": "verify_detail", "search": "E2E_TEST_사원", "expected": { "row_exists": true, @@ -219,7 +219,7 @@ "id": 16, "phase": "DELETE", "name": "[DELETE] 삭제 버튼 클릭", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('삭제')", "expected": { "confirm_dialog": true, @@ -243,7 +243,7 @@ "id": 18, "phase": "DELETE", "name": "[DELETE] 삭제 결과 확인", - "action": "verify_data", + "action": "verify_detail", "search": "E2E_TEST_사원", "expected": { "row_exists": false, diff --git a/hr-salary.json b/hr-salary.json index fc69f1d..83c68df 100644 --- a/hr-salary.json +++ b/hr-salary.json @@ -95,7 +95,7 @@ "id": 7, "phase": "READ", "name": "[READ] 사원 급여 상세 클릭", - "action": "click", + "action": "click_if_exists", "target": "table tbody tr:first-child", "expected": { "detail_modal_or_page": true, @@ -120,7 +120,7 @@ "id": 9, "phase": "UPDATE", "name": "[UPDATE] 수당 수정 모드 진입", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('수정'), button:has-text('편집')", "expected": { "edit_mode": true, @@ -138,7 +138,7 @@ "id": 11, "phase": "UPDATE", "name": "[UPDATE] 필수 검증 #2: 수정 저장", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('저장'), button:has-text('확인')", "verify": { "url_maintained": true, @@ -173,7 +173,7 @@ "id": 14, "phase": "EXPORT", "name": "[EXPORT] 필수 검증 #1: 엑셀 다운로드", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('엑셀'), button:has-text('다운로드'), button:has-text('내보내기')", "verify": { "file_download": true, diff --git a/hr-vacation.json b/hr-vacation.json index 2438b5d..0f14671 100644 --- a/hr-vacation.json +++ b/hr-vacation.json @@ -80,7 +80,7 @@ "id": 5, "phase": "CREATE", "name": "[CREATE] 휴가 신청 버튼 클릭", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('신청'), button:has-text('휴가 신청'), button:has-text('추가')", "expected": { "modal": true, @@ -104,7 +104,7 @@ "id": 7, "phase": "CREATE", "name": "[CREATE] 필수 검증 #2: 신청 저장", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('신청'), button:has-text('저장'), button:has-text('확인')", "verify": { "url_maintained": true, @@ -125,7 +125,7 @@ "id": 8, "phase": "CREATE", "name": "[CREATE] 신청 결과 확인", - "action": "verify_data", + "action": "verify_detail", "search": "E2E 자동화 테스트 휴가", "expected": { "row_exists": true, @@ -205,7 +205,7 @@ "id": 15, "phase": "DELETE", "name": "[DELETE] 취소 버튼 클릭", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('취소'), button:has-text('신청 취소')", "expected": { "confirm_dialog": true, @@ -229,7 +229,7 @@ "id": 17, "phase": "DELETE", "name": "[DELETE] 취소 결과 확인", - "action": "verify_data", + "action": "verify_detail", "search": "E2E 수정된 휴가", "expected": { "row_exists": false, diff --git a/inventory-status.json b/inventory-status.json index 56d24bb..d224a69 100644 --- a/inventory-status.json +++ b/inventory-status.json @@ -118,7 +118,7 @@ "name": "필수 검증 #3: 품목유형 탭 필터 - 부자재", "description": "부자재 탭 클릭하여 필터링 확인", "actions": [ - { "type": "click", "target": "부자재", "role": "tab" }, + { "type": "click_if_exists", "target": "부자재", "role": "tab" }, { "type": "wait", "duration": 500 } ], "expect": { @@ -144,7 +144,7 @@ "name": "전체 탭으로 복귀", "description": "전체 탭 클릭하여 모든 재고 표시", "actions": [ - { "type": "click", "target": "전체", "role": "tab" }, + { "type": "click_if_exists", "target": "전체", "role": "tab" }, { "type": "wait", "duration": 300 } ], "expect": { @@ -197,7 +197,7 @@ "name": "페이지네이션 확인", "description": "페이지네이션 동작 확인", "actions": [ - { "type": "click", "target": "다음" }, + { "type": "click_if_exists", "target": "다음" }, { "type": "wait", "duration": 500 } ], "expect": { diff --git a/item-management.json b/item-management.json index 4d04d6a..f01ceca 100644 --- a/item-management.json +++ b/item-management.json @@ -121,7 +121,7 @@ "maxAttempts": 10, "description": "스크롤하며 생산관리 메뉴 찾기" }, - { "type": "click", "target": "생산관리", "description": "생산관리 메뉴 클릭" }, + { "type": "click_if_exists", "target": "생산관리", "description": "생산관리 메뉴 클릭" }, { "type": "wait", "duration": 500, "description": "서브메뉴 펼쳐지기 대기" }, { "type": "scrollAndFind", @@ -131,7 +131,7 @@ "maxAttempts": 5, "description": "서브메뉴에서 품목관리 찾기" }, - { "type": "click", "target": "품목관리", "description": "품목관리 메뉴 클릭" }, + { "type": "click_if_exists", "target": "품목관리", "description": "품목관리 메뉴 클릭" }, { "type": "wait", "target": "페이지 로드 완료", "timeout": 10000 } ], "expected": { @@ -329,7 +329,7 @@ { "step": 14, "name": "탭 필터 테스트 - 제품 탭 클릭", - "action": "click", + "action": "click_if_exists", "target": "button:제품", "expected": "제품 탭이 활성화됨" }, @@ -346,7 +346,7 @@ { "step": 16, "name": "탭 필터 테스트 - 소모품 탭 클릭", - "action": "click", + "action": "click_if_exists", "target": "button:소모품", "expected": "소모품 탭이 활성화됨" }, @@ -363,14 +363,14 @@ { "step": 18, "name": "탭 필터 초기화 - 전체 탭 클릭", - "action": "click", + "action": "click_if_exists", "target": "button:전체", "expected": "전체 탭이 활성화되고 모든 품목이 표시됨" }, { "step": 19, "name": "페이지네이션 테스트 - 2페이지 이동", - "action": "click", + "action": "click_if_exists", "target": "button:2", "expected": "2페이지로 이동됨" }, @@ -384,7 +384,7 @@ { "step": 21, "name": "다음 페이지 버튼 클릭", - "action": "click", + "action": "click_if_exists", "target": "button:다음", "expected": "3페이지로 이동됨" }, @@ -398,14 +398,14 @@ { "step": 23, "name": "1페이지로 복귀", - "action": "click", + "action": "click_if_exists", "target": "button:1", "expected": "1페이지로 복귀됨" }, { "step": 24, "name": "품목 등록 페이지 이동", - "action": "click", + "action": "click_if_exists", "target": "button:품목 등록", "expected": "품목 등록 페이지(/items/create)로 이동됨" }, @@ -448,14 +448,14 @@ { "step": 29, "name": "제품(Finished Goods) 등록 테스트 시작", - "action": "click", + "action": "click_if_exists", "target": "combobox:품목 유형", "expected": "품목 유형 드롭다운이 열림" }, { "step": 30, "name": "제품 옵션 선택", - "action": "click", + "action": "click_if_exists", "target": "option:제품 (Finished Goods)", "expected": "제품 유형이 선택되고 제품 전용 입력 필드가 표시됨" }, @@ -520,14 +520,14 @@ { "step": 36, "name": "품목상태 선택", - "action": "click", + "action": "click_if_exists", "target": "combobox:품목상태", "expected": "품목상태 드롭다운이 열림" }, { "step": 37, "name": "품목상태 '활성' 선택", - "action": "click", + "action": "click_if_exists", "target": "option:활성", "expected": "'활성' 상태가 선택됨" }, @@ -566,7 +566,7 @@ { "step": 42, "name": "제품 등록 - 저장 버튼 클릭", - "action": "click", + "action": "click_if_exists", "target": "button:저장", "expected": "제품 등록 API 호출 및 성공 메시지 표시" }, @@ -638,21 +638,21 @@ { "step": 50, "name": "소모품(Consumables) 등록 테스트 시작", - "action": "click", + "action": "click_if_exists", "target": "button:품목 등록", "expected": "품목 등록 페이지로 이동됨" }, { "step": 51, "name": "품목 유형에서 소모품 선택", - "action": "click", + "action": "click_if_exists", "target": "combobox:품목 유형", "expected": "품목 유형 드롭다운이 열림" }, { "step": 52, "name": "소모품 옵션 선택", - "action": "click", + "action": "click_if_exists", "target": "option:소모품 (Consumables)", "expected": "소모품 유형이 선택되고 소모품 전용 입력 필드가 표시됨" }, @@ -702,14 +702,14 @@ { "step": 57, "name": "소모품 단위 선택", - "action": "click", + "action": "click_if_exists", "target": "combobox:단위", "expected": "단위 드롭다운이 열림" }, { "step": 58, "name": "단위 'EA' 선택", - "action": "click", + "action": "click_if_exists", "target": "option:EA", "expected": "'EA' 단위가 선택됨" }, @@ -730,7 +730,7 @@ { "step": 61, "name": "소모품 등록 - 저장 버튼 클릭", - "action": "click", + "action": "click_if_exists", "target": "button:저장", "expected": "소모품 등록 API 호출 및 성공 메시지 표시" }, @@ -781,7 +781,7 @@ { "step": 68, "name": "상세 보기 버튼 클릭 (첫 번째 행)", - "action": "click", + "action": "click_if_exists", "target": "button:상세 보기[row=1]", "expected": "품목 상세 모달 또는 페이지가 열림" }, @@ -800,7 +800,7 @@ { "step": 70, "name": "상세 보기 닫기", - "action": "click", + "action": "click_if_exists", "target": "button:닫기 or ESC", "expected": "상세 모달/페이지가 닫히고 목록으로 복귀" }, @@ -815,7 +815,7 @@ { "step": 72, "name": "수정 버튼 클릭", - "action": "click", + "action": "click_if_exists", "target": "button:수정[row=TEST-SCREEN-001]", "expected": "품목 수정 페이지(/items/:id?mode=edit)로 이동됨" }, @@ -855,7 +855,7 @@ { "step": 77, "name": "수정 저장 버튼 클릭", - "action": "click", + "action": "click_if_exists", "target": "button:저장", "expected": "수정 API 호출 및 성공 메시지 표시" }, @@ -886,7 +886,7 @@ { "step": 81, "name": "수정된 데이터 확인 - 상세보기", - "action": "click", + "action": "click_if_exists", "target": "button:상세 보기[row=TEST-SCREEN-001]", "expected": "상세 정보 표시" }, @@ -900,7 +900,7 @@ { "step": 83, "name": "상세 모달 닫기", - "action": "click", + "action": "click_if_exists", "target": "button:닫기", "expected": "상세 모달이 닫힘" }, @@ -915,7 +915,7 @@ { "step": 85, "name": "삭제 버튼 클릭", - "action": "click", + "action": "click_if_exists", "target": "button:삭제[row=테스트 라벨]", "expected": "삭제 확인 다이얼로그가 표시됨" }, @@ -929,7 +929,7 @@ { "step": 87, "name": "삭제 취소 테스트 - 취소 버튼 클릭", - "action": "click", + "action": "click_if_exists", "target": "button:취소[dialog]", "expected": "다이얼로그가 닫히고 삭제되지 않음" }, @@ -943,14 +943,14 @@ { "step": 89, "name": "삭제 재시도 - 삭제 버튼 클릭", - "action": "click", + "action": "click_if_exists", "target": "button:삭제[row=테스트 라벨]", "expected": "삭제 확인 다이얼로그가 다시 표시됨" }, { "step": 90, "name": "삭제 확인 버튼 클릭", - "action": "click", + "action": "click_if_exists", "target": "button:확인[dialog]", "expected": "삭제 API 호출 및 성공 메시지 표시" }, @@ -991,14 +991,14 @@ { "step": 95, "name": "제품 삭제 버튼 클릭", - "action": "click", + "action": "click_if_exists", "target": "button:삭제[row=TEST-SCREEN-001]", "expected": "삭제 확인 다이얼로그가 표시됨" }, { "step": 96, "name": "제품 삭제 확인", - "action": "click", + "action": "click_if_exists", "target": "button:확인[dialog]", "expected": "삭제 API 호출 및 성공 메시지 표시" }, diff --git a/login.json b/login.json index d8cd57e..49994fb 100644 --- a/login.json +++ b/login.json @@ -88,7 +88,7 @@ { "id": 7, "name": "로그인 실패 테스트 - 빈 필드", - "action": "click", + "action": "click_if_exists", "target": "loginButton", "expected": "유효성 검사 에러 또는 로그인 실패 메시지" }, @@ -111,7 +111,7 @@ { "id": 10, "name": "잘못된 비밀번호로 로그인 시도", - "action": "click", + "action": "click_if_exists", "target": "loginButton", "expected": "로그인 실패 에러 메시지 표시", "verify": { @@ -137,7 +137,7 @@ { "id": 13, "name": "필수 검증 #2: 로그인 버튼 클릭", - "action": "click", + "action": "click_if_exists", "target": "loginButton", "verify": { "url_should_change": true, @@ -217,7 +217,7 @@ "actions": [ { "type": "fill", "target": "usernameInput", "value": "TestUser5" }, { "type": "fill", "target": "passwordInput", "value": "password123!" }, - { "type": "click", "target": "loginButton" } + { "type": "click_if_exists", "target": "loginButton" } ], "expected": "재로그인 성공" }, diff --git a/material-receiving.json b/material-receiving.json index 4690b35..6d84fa5 100644 --- a/material-receiving.json +++ b/material-receiving.json @@ -80,7 +80,7 @@ "id": 5, "phase": "CREATE", "name": "[CREATE] 입고 등록 버튼 클릭", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('등록'), button:has-text('입고 등록'), button:has-text('추가')", "expected": { "modal": true, @@ -126,7 +126,7 @@ "id": 8, "phase": "CREATE", "name": "[CREATE] 등록 결과 확인", - "action": "verify_data", + "action": "verify_detail", "search": "E2E 자동화 테스트 입고", "expected": { "row_exists": true, @@ -213,7 +213,7 @@ "id": 16, "phase": "DELETE", "name": "[DELETE] 삭제 버튼 클릭", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('삭제')", "expected": { "confirm_dialog": true, @@ -237,7 +237,7 @@ "id": 18, "phase": "DELETE", "name": "[DELETE] 삭제 결과 확인", - "action": "verify_data", + "action": "verify_detail", "search": "E2E 수정된 입고", "expected": { "row_exists": false, diff --git a/material-stock.json b/material-stock.json index e04237d..1253d71 100644 --- a/material-stock.json +++ b/material-stock.json @@ -142,7 +142,7 @@ { "id": 13, "name": "필수 검증 #1: 엑셀 다운로드", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('엑셀'), button:has-text('Excel'), button:has-text('다운로드')", "verify": { "api_call": "GET /api/v1/material/stock/export", diff --git a/payment-history.json b/payment-history.json index c58c84c..1359476 100644 --- a/payment-history.json +++ b/payment-history.json @@ -102,7 +102,7 @@ "maxAttempts": 10, "description": "스크롤하며 회계관리 메뉴 찾기" }, - { "type": "click", "target": "회계관리", "description": "회계관리 메뉴 클릭" }, + { "type": "click_if_exists", "target": "회계관리", "description": "회계관리 메뉴 클릭" }, { "type": "wait", "duration": 500, "description": "서브메뉴 펼쳐지기 대기" } ], "verification": [ @@ -123,7 +123,7 @@ "maxAttempts": 5, "description": "서브메뉴에서 결제내역 찾기" }, - { "type": "click", "target": "결제내역", "description": "결제내역 메뉴 클릭" }, + { "type": "click_if_exists", "target": "결제내역", "description": "결제내역 메뉴 클릭" }, { "type": "wait", "target": "페이지 로드 완료", "timeout": 10000 } ], "verification": [ diff --git a/pdf-download-test.json b/pdf-download-test.json index 32d5654..0cc3283 100644 --- a/pdf-download-test.json +++ b/pdf-download-test.json @@ -137,7 +137,7 @@ }, { "id": "1-8", - "action": "click", + "action": "click_if_exists", "selector": "button:has-text('PDF')", "description": "PDF 버튼 클릭" }, @@ -215,7 +215,7 @@ }, { "id": "2-6", - "action": "click", + "action": "click_if_exists", "selector": "button:has-text('PDF')" }, { @@ -280,7 +280,7 @@ }, { "id": "3-6", - "action": "click", + "action": "click_if_exists", "selector": "button:has-text('PDF')" }, { @@ -353,7 +353,7 @@ }, { "id": "4-7", - "action": "click", + "action": "click_if_exists", "selector": "button:has-text('PDF 다운로드')", "index": 0, "description": "첫 번째 PDF 다운로드 버튼 클릭" diff --git a/permission-management.json b/permission-management.json index 388274f..689c1c7 100644 --- a/permission-management.json +++ b/permission-management.json @@ -110,7 +110,7 @@ "maxAttempts": 10, "description": "스크롤하며 설정 메뉴 찾기" }, - { "type": "click", "target": "설정", "description": "설정 메뉴 클릭" }, + { "type": "click_if_exists", "target": "설정", "description": "설정 메뉴 클릭" }, { "type": "wait", "duration": 500, "description": "서브메뉴 펼쳐지기 대기" }, { "type": "scrollAndFind", @@ -120,7 +120,7 @@ "maxAttempts": 5, "description": "서브메뉴에서 권한관리 찾기" }, - { "type": "click", "target": "권한관리", "description": "권한관리 메뉴 클릭" }, + { "type": "click_if_exists", "target": "권한관리", "description": "권한관리 메뉴 클릭" }, { "type": "wait", "target": "페이지 로드 완료", "timeout": 10000 } ], "expected": { @@ -168,7 +168,7 @@ { "id": "step-05", "name": "탭 필터 테스트 - 공개", - "action": "click", + "action": "click_if_exists", "target": "공개 탭", "verification": [ "공개 탭 활성화", @@ -179,7 +179,7 @@ { "id": "step-06", "name": "탭 필터 테스트 - 숨김", - "action": "click", + "action": "click_if_exists", "target": "숨김 탭", "verification": [ "숨김 탭 활성화", @@ -190,7 +190,7 @@ { "id": "step-07", "name": "탭 필터 테스트 - 전체", - "action": "click", + "action": "click_if_exists", "target": "전체 탭", "verification": [ "전체 탭 활성화", @@ -221,7 +221,7 @@ { "id": "step-10", "name": "역할 등록 페이지 이동", - "action": "click", + "action": "click_if_exists", "target": "역할 등록 버튼", "verification": [ "URL 변경: /settings/permissions?mode=new", @@ -287,7 +287,7 @@ { "id": "step-16", "name": "역할 상세 페이지 이동", - "action": "click", + "action": "click_if_exists", "target": "E2E 테스트 역할 행", "verification": [ "URL 변경: /settings/permissions/{id}", @@ -322,7 +322,7 @@ { "id": "step-19", "name": "부모 메뉴 펼치기", - "action": "click", + "action": "click_if_exists", "target": "첫 번째 부모 메뉴 펼치기 아이콘", "verification": [ "자식 메뉴 목록 표시", @@ -333,7 +333,7 @@ { "id": "step-20", "name": "개별 권한 체크박스 토글", - "action": "click", + "action": "click_if_exists", "target": "첫 번째 메뉴의 '조회' 체크박스", "verification": [ "체크박스 상태 변경", @@ -343,7 +343,7 @@ { "id": "step-21", "name": "컬럼 전체 선택", - "action": "click", + "action": "click_if_exists", "target": "'조회' 헤더 체크박스", "verification": [ "모든 메뉴의 '조회' 권한 체크", @@ -384,7 +384,7 @@ { "id": "step-25", "name": "목록으로 이동", - "action": "click", + "action": "click_if_exists", "target": "목록으로 버튼", "verification": [ "URL 변경: /settings/permissions", @@ -403,7 +403,7 @@ { "id": "step-27", "name": "숨김 탭으로 이동", - "action": "click", + "action": "click_if_exists", "target": "숨김 탭", "verification": [ "숨김 상태 역할만 표시", @@ -413,7 +413,7 @@ { "id": "step-28", "name": "전체 탭으로 복귀", - "action": "click", + "action": "click_if_exists", "target": "전체 탭", "verification": [ "모든 역할 표시" @@ -422,7 +422,7 @@ { "id": "step-29", "name": "체크박스 선택", - "action": "click", + "action": "click_if_exists", "target": "E2E 테스트 역할 체크박스", "verification": [ "체크박스 선택됨", @@ -434,7 +434,7 @@ { "id": "step-30", "name": "단일 삭제 - 작업 컬럼 삭제 버튼", - "action": "click", + "action": "click_if_exists", "target": "작업 컬럼의 삭제 버튼", "verification": [ "삭제 확인 다이얼로그 표시", @@ -445,7 +445,7 @@ { "id": "step-31", "name": "삭제 취소", - "action": "click", + "action": "click_if_exists", "target": "다이얼로그 취소 버튼", "verification": [ "다이얼로그 닫힘", @@ -455,7 +455,7 @@ { "id": "step-32", "name": "일괄 삭제 버튼 클릭", - "action": "click", + "action": "click_if_exists", "target": "선택 삭제 버튼", "verification": [ "삭제 확인 다이얼로그 표시", @@ -480,7 +480,7 @@ { "id": "step-34", "name": "체크박스 전체 선택", - "action": "click", + "action": "click_if_exists", "target": "테이블 헤더 체크박스", "verification": [ "현재 페이지의 모든 항목 선택", @@ -491,7 +491,7 @@ { "id": "step-35", "name": "전체 선택 해제", - "action": "click", + "action": "click_if_exists", "target": "테이블 헤더 체크박스", "verification": [ "모든 선택 해제", diff --git a/popup-management.json b/popup-management.json index 424240f..aedbfcd 100644 --- a/popup-management.json +++ b/popup-management.json @@ -112,7 +112,7 @@ "scrollStep": 200, "maxAttempts": 10 }, - { "type": "click", "target": "설정" }, + { "type": "click_if_exists", "target": "설정" }, { "type": "wait", "duration": 500 }, { "type": "scrollAndFind", @@ -121,7 +121,7 @@ "scrollStep": 200, "maxAttempts": 5 }, - { "type": "click", "target": "팝업관리" }, + { "type": "click_if_exists", "target": "팝업관리" }, { "type": "wait", "target": "페이지 로드 완료" } ], "fallback": { @@ -227,7 +227,7 @@ { "step": 13, "name": "팝업 등록 페이지 이동", - "action": "click", + "action": "click_if_exists", "target": "button '팝업 등록'", "expected": "/settings/popup-management?mode=new 페이지로 이동", "validation": ["등록/저장"] @@ -267,7 +267,7 @@ { "step": 18, "name": "대상 Combobox 클릭", - "action": "click", + "action": "click_if_exists", "target": "combobox (대상)", "expected": "드롭다운 옵션 표시됨", "validation": ["UI 동작"] @@ -283,7 +283,7 @@ { "step": 20, "name": "대상 '부서별' 선택", - "action": "click", + "action": "click_if_exists", "target": "option '부서별'", "expected": "'부서별' 선택됨", "validation": ["UI 동작"] @@ -365,7 +365,7 @@ { "step": 30, "name": "상태 '사용함' 선택", - "action": "click", + "action": "click_if_exists", "target": "radio '사용함'", "expected": "'사용함' 선택됨", "validation": ["UI 동작"] @@ -413,7 +413,7 @@ { "step": 36, "name": "등록 버튼 클릭", - "action": "click", + "action": "click_if_exists", "target": "button '등록'", "expected": "팝업 등록 요청 전송", "validation": ["등록/저장"] @@ -453,7 +453,7 @@ { "step": 41, "name": "첫 번째 팝업 행 클릭", - "action": "click", + "action": "click_if_exists", "target": "row (첫 번째 팝업)", "expected": "상세 페이지로 이동", "validation": ["UI 동작"] @@ -573,7 +573,7 @@ { "step": 56, "name": "수정 페이지 이동", - "action": "click", + "action": "click_if_exists", "target": "button '수정'", "expected": "/settings/popup-management/1?mode=edit 페이지로 이동", "validation": ["등록/저장"] @@ -647,7 +647,7 @@ { "step": 65, "name": "상태 변경 - 사용안함 선택", - "action": "click", + "action": "click_if_exists", "target": "radio '사용안함'", "expected": "'사용안함' 선택됨", "validation": ["UI 동작"] @@ -671,7 +671,7 @@ { "step": 68, "name": "저장 버튼 클릭", - "action": "click", + "action": "click_if_exists", "target": "button '저장'", "expected": "팝업 수정 요청 전송", "validation": ["등록/저장"] @@ -727,7 +727,7 @@ { "step": 75, "name": "목록으로 이동", - "action": "click", + "action": "click_if_exists", "target": "button '목록으로'", "expected": "/settings/popup-management 페이지로 이동", "validation": ["UI 동작"] @@ -767,7 +767,7 @@ { "step": 80, "name": "삭제 테스트 - 팝업 상세 페이지 이동", - "action": "click", + "action": "click_if_exists", "target": "row (수정한 팝업)", "expected": "상세 페이지로 이동", "validation": ["삭제 기능"] @@ -775,7 +775,7 @@ { "step": 81, "name": "삭제 버튼 클릭", - "action": "click", + "action": "click_if_exists", "target": "button '삭제'", "expected": "삭제 확인 다이얼로그 표시", "validation": ["삭제 기능"] @@ -791,7 +791,7 @@ { "step": 83, "name": "삭제 확인", - "action": "click", + "action": "click_if_exists", "target": "button '확인' (dialog)", "expected": "팝업 삭제 요청 전송", "validation": ["삭제 기능"] diff --git a/price-management.json b/price-management.json index f83eab0..380052d 100644 --- a/price-management.json +++ b/price-management.json @@ -87,7 +87,7 @@ "scrollStep": 200, "maxAttempts": 5 }, - { "type": "click", "target": "판매관리" }, + { "type": "click_if_exists", "target": "판매관리" }, { "type": "wait", "duration": 500 }, { "type": "click_if_exists", "target": "단가관리" } ], @@ -114,7 +114,7 @@ "name": "필수 검증 #3: 품목유형 탭 필터 - 제품", "description": "제품 탭 클릭하여 필터링 확인", "actions": [ - { "type": "click", "target": "제품", "role": "tab" }, + { "type": "click_if_exists", "target": "제품", "role": "tab" }, { "type": "wait", "duration": 300 } ], "expect": { @@ -127,7 +127,7 @@ "name": "필수 검증 #3: 품목유형 탭 필터 - 소모품", "description": "소모품 탭 클릭하여 필터링 확인", "actions": [ - { "type": "click", "target": "소모품", "role": "tab" }, + { "type": "click_if_exists", "target": "소모품", "role": "tab" }, { "type": "wait", "duration": 300 } ], "expect": { @@ -140,7 +140,7 @@ "name": "전체 탭으로 복귀", "description": "전체 탭 클릭하여 모든 품목 표시", "actions": [ - { "type": "click", "target": "전체", "role": "tab" }, + { "type": "click_if_exists", "target": "전체", "role": "tab" }, { "type": "wait", "duration": 300 } ], "expect": { @@ -178,7 +178,7 @@ "name": "필수 검증 #2: 단가 등록 저장", "description": "저장 버튼 클릭하여 단가 저장", "actions": [ - { "type": "click", "target": "저장" } + { "type": "click_if_exists", "target": "저장" } ], "expect": { "urlMaintained": true, @@ -257,7 +257,7 @@ "name": "페이지네이션 확인", "description": "페이지네이션 동작 확인", "actions": [ - { "type": "click", "target": "다음" }, + { "type": "click_if_exists", "target": "다음" }, { "type": "wait", "duration": 300 } ], "expect": { diff --git a/production-dashboard.json b/production-dashboard.json index 99cacf2..a885caf 100644 --- a/production-dashboard.json +++ b/production-dashboard.json @@ -80,7 +80,7 @@ "id": 6, "phase": "FILTER", "name": "[FILTER] 기간 필터 테스트", - "action": "click", + "action": "click_if_exists", "target": "select[name*='period'], button:has-text('기간'), [class*='filter']", "expected": "기간 필터 옵션 표시" }, diff --git a/production-item.json b/production-item.json index dbb93c3..c8f1942 100644 --- a/production-item.json +++ b/production-item.json @@ -65,7 +65,7 @@ "id": 4, "phase": "CREATE", "name": "[CREATE] 품목 등록 버튼 클릭", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('등록'), button:has-text('추가'), button:has-text('신규')", "expected": { "modal_open": true @@ -164,7 +164,7 @@ "id": 14, "phase": "UPDATE", "name": "[UPDATE] 품목 저장", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('저장'), button:has-text('확인')", "verify": { "api_call": "PUT /api/v1/items", @@ -176,7 +176,7 @@ "id": 15, "phase": "DELETE", "name": "[DELETE] 품목 삭제", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('삭제'), button:has-text('제거')", "expected": { "confirm_dialog": true @@ -186,7 +186,7 @@ "id": 16, "phase": "DELETE", "name": "[DELETE] 삭제 확인", - "action": "click", + "action": "click_if_exists", "target": "[role='alertdialog'] button:has-text('확인'), [role='dialog'] button:has-text('삭제')", "verify": { "api_call": "DELETE /api/v1/items", diff --git a/production-work-order.json b/production-work-order.json index d77306b..9e51895 100644 --- a/production-work-order.json +++ b/production-work-order.json @@ -81,7 +81,7 @@ "id": 5, "phase": "CREATE", "name": "[CREATE] 작업지시 등록 버튼 클릭", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('등록'), button:has-text('작업지시 등록'), button:has-text('추가')", "expected": { "modal": true, @@ -127,7 +127,7 @@ "id": 8, "phase": "CREATE", "name": "[CREATE] 등록 결과 확인", - "action": "verify_data", + "action": "verify_detail", "search": "E2E_TEST_작업지시", "expected": { "row_exists": true, @@ -215,7 +215,7 @@ "id": 16, "phase": "DELETE", "name": "[DELETE] 삭제 버튼 클릭", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('삭제')", "expected": { "confirm_dialog": true, @@ -239,7 +239,7 @@ "id": 18, "phase": "DELETE", "name": "[DELETE] 삭제 결과 확인", - "action": "verify_data", + "action": "verify_detail", "search": "E2E 수정된 작업지시", "expected": { "row_exists": false, diff --git a/production-work-result.json b/production-work-result.json index bd538eb..dcb5ddc 100644 --- a/production-work-result.json +++ b/production-work-result.json @@ -91,7 +91,7 @@ "id": 7, "phase": "CREATE", "name": "[CREATE] 실적 등록 버튼 클릭", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('등록'), button:has-text('추가'), button:has-text('신규')", "expected": { "modal_open": true @@ -193,7 +193,7 @@ "id": 17, "phase": "UPDATE", "name": "[UPDATE] 수정 저장", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('저장'), button:has-text('확인')", "verify": { "api_call": "PUT /api/v1/production/work-results", diff --git a/purchase-client.json b/purchase-client.json index 795ad09..a1c41b5 100644 --- a/purchase-client.json +++ b/purchase-client.json @@ -64,7 +64,7 @@ "id": 4, "phase": "CREATE", "name": "[CREATE] 거래처 등록 버튼 클릭", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('등록'), button:has-text('추가'), button:has-text('신규')", "expected": { "modal_open": true @@ -101,7 +101,7 @@ "id": 8, "phase": "CREATE", "name": "[CREATE] 필수 검증 #2: 거래처 저장", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('저장'), button:has-text('등록'), button:has-text('확인')", "verify": { "url_maintained": true, @@ -134,7 +134,7 @@ "id": 11, "phase": "READ", "name": "[READ] 거래처 상세 조회", - "action": "click", + "action": "click_if_exists", "target": "table tbody tr:has-text('E2E_TEST')", "expected": { "detail_view": true @@ -144,7 +144,7 @@ "id": 12, "phase": "UPDATE", "name": "[UPDATE] 거래처 수정 모드 진입", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('수정'), button:has-text('편집')", "expected": { "edit_mode": true @@ -163,7 +163,7 @@ "id": 14, "phase": "UPDATE", "name": "[UPDATE] 거래처 저장", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('저장'), button:has-text('확인')", "verify": { "api_call": "PUT /api/v1/purchase/suppliers", @@ -175,7 +175,7 @@ "id": 15, "phase": "DELETE", "name": "[DELETE] 거래처 삭제", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('삭제'), button:has-text('제거')", "expected": { "confirm_dialog": true @@ -185,7 +185,7 @@ "id": 16, "phase": "DELETE", "name": "[DELETE] 삭제 확인", - "action": "click", + "action": "click_if_exists", "target": "[role='alertdialog'] button:has-text('확인'), [role='dialog'] button:has-text('삭제')", "verify": { "api_call": "DELETE /api/v1/purchase/suppliers", diff --git a/purchase-order.json b/purchase-order.json index 1895984..f02820e 100644 --- a/purchase-order.json +++ b/purchase-order.json @@ -83,7 +83,7 @@ "id": 5, "phase": "CREATE", "name": "[CREATE] 발주 등록 버튼 클릭", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('등록'), button:has-text('발주 등록'), button:has-text('추가')", "expected": { "modal_or_page": true, @@ -110,7 +110,7 @@ "id": 7, "phase": "CREATE", "name": "[CREATE] 필수 검증 #2: 등록 저장", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('저장'), button:has-text('등록')", "verify": { "url_maintained": true, @@ -131,7 +131,7 @@ "id": 8, "phase": "CREATE", "name": "[CREATE] 등록 결과 확인", - "action": "verify_data", + "action": "verify_detail", "search": "E2E 자동화 테스트 발주", "expected": { "row_exists": true, @@ -142,7 +142,7 @@ "id": 9, "phase": "READ", "name": "[READ] 발주 상세 페이지 진입", - "action": "click", + "action": "click_if_exists", "target": "table tbody tr:has-text('E2E')", "expected": { "url_contains": "/purchase", @@ -166,7 +166,7 @@ "id": 11, "phase": "UPDATE", "name": "[UPDATE] 수정 모드 진입", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('수정')", "expected": { "url_contains": "mode=edit", @@ -195,7 +195,7 @@ "id": 14, "phase": "UPDATE", "name": "[UPDATE] 필수 검증 #2: 수정 저장", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('저장')", "verify": { "url_maintained": true, @@ -220,7 +220,7 @@ "id": 16, "phase": "DELETE", "name": "[DELETE] 삭제 버튼 클릭", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('삭제')", "expected": { "confirm_dialog": true, @@ -231,7 +231,7 @@ "id": 17, "phase": "DELETE", "name": "[DELETE] 필수 검증 #6: 삭제 확인", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('확인'), button:has-text('삭제')", "verify": { "api_call": "DELETE /api/v1/purchase-orders/", @@ -244,7 +244,7 @@ "id": 18, "phase": "DELETE", "name": "[DELETE] 삭제 결과 확인", - "action": "verify_data", + "action": "verify_detail", "search": "E2E 수정된 발주", "expected": { "row_exists": false, diff --git a/purchase-pricing.json b/purchase-pricing.json index 0ff194d..e652493 100644 --- a/purchase-pricing.json +++ b/purchase-pricing.json @@ -64,7 +64,7 @@ "id": 4, "phase": "CREATE", "name": "[CREATE] 단가 등록 버튼 클릭", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('등록'), button:has-text('추가'), button:has-text('신규')", "expected": { "modal_open": true @@ -74,7 +74,7 @@ "id": 5, "phase": "CREATE", "name": "[CREATE] 품목 선택", - "action": "click", + "action": "click_if_exists", "target": "select[name*='item'], button:has-text('품목'), input[placeholder*='품목']", "expected": "품목 선택 가능" }, @@ -82,7 +82,7 @@ "id": 6, "phase": "CREATE", "name": "[CREATE] 거래처 선택", - "action": "click", + "action": "click_if_exists", "target": "select[name*='supplier'], button:has-text('거래처'), input[placeholder*='거래처']", "expected": "거래처 선택 가능" }, @@ -99,7 +99,7 @@ "id": 8, "phase": "CREATE", "name": "[CREATE] 필수 검증 #2: 단가 저장", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('저장'), button:has-text('등록'), button:has-text('확인')", "verify": { "url_maintained": true, @@ -123,7 +123,7 @@ "id": 10, "phase": "READ", "name": "[READ] 단가 상세 조회", - "action": "click", + "action": "click_if_exists", "target": "table tbody tr:first-child", "expected": { "detail_view": true @@ -145,7 +145,7 @@ "id": 12, "phase": "UPDATE", "name": "[UPDATE] 단가 수정 모드 진입", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('수정'), button:has-text('편집')", "expected": { "edit_mode": true @@ -164,7 +164,7 @@ "id": 14, "phase": "UPDATE", "name": "[UPDATE] 단가 저장", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('저장'), button:has-text('확인')", "verify": { "api_call": "PUT /api/v1/purchase/pricing", @@ -184,7 +184,7 @@ { "id": 16, "name": "엑셀 다운로드", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('엑셀'), button:has-text('Excel'), button:has-text('다운로드')", "verify": { "file_download": true diff --git a/purchase-status.json b/purchase-status.json index f712707..60ff257 100644 --- a/purchase-status.json +++ b/purchase-status.json @@ -84,7 +84,7 @@ "id": 7, "phase": "FILTER", "name": "[FILTER] 조회 실행", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('조회'), button:has-text('검색')", "expected": { "data_loaded": true, @@ -143,7 +143,7 @@ { "id": 13, "name": "필수 검증 #1: 엑셀 다운로드", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('엑셀'), button:has-text('Excel'), button:has-text('다운로드')", "verify": { "api_call": "GET /api/v1/purchase/status/export", diff --git a/quality-inspection.json b/quality-inspection.json index 18dee2c..f94e8d5 100644 --- a/quality-inspection.json +++ b/quality-inspection.json @@ -82,7 +82,7 @@ "id": 5, "phase": "CREATE", "name": "[CREATE] 제품검사 등록 버튼 클릭", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('등록'), button:has-text('제품검사 등록'), button:has-text('추가')", "expected": { "modal_or_page": true, @@ -107,7 +107,7 @@ "id": 7, "phase": "CREATE", "name": "[CREATE] 필수 검증 #2: 등록 저장", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('저장'), button:has-text('등록')", "verify": { "url_maintained": true, @@ -128,7 +128,7 @@ "id": 8, "phase": "CREATE", "name": "[CREATE] 등록 결과 확인", - "action": "verify_data", + "action": "verify_detail", "search": "E2E_TEST_현장", "expected": { "row_exists": true, @@ -139,7 +139,7 @@ "id": 9, "phase": "READ", "name": "[READ] 제품검사 상세 페이지 진입", - "action": "click", + "action": "click_if_exists", "target": "table tbody tr:has-text('E2E_TEST')", "expected": { "url_contains": "/quality/inspections/", @@ -162,7 +162,7 @@ "id": 11, "phase": "UPDATE", "name": "[UPDATE] 수정 모드 진입", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('수정')", "expected": { "url_contains": "mode=edit", @@ -191,7 +191,7 @@ "id": 14, "phase": "UPDATE", "name": "[UPDATE] 필수 검증 #2: 수정 저장", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('저장')", "verify": { "url_maintained": true, @@ -216,7 +216,7 @@ "id": 16, "phase": "DELETE", "name": "[DELETE] 삭제 버튼 클릭", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('삭제')", "expected": { "confirm_dialog": true, @@ -227,7 +227,7 @@ "id": 17, "phase": "DELETE", "name": "[DELETE] 필수 검증 #6: 삭제 확인", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('확인'), button:has-text('삭제')", "verify": { "api_call": "DELETE /api/v1/quality/inspections/", @@ -240,7 +240,7 @@ "id": 18, "phase": "DELETE", "name": "[DELETE] 삭제 결과 확인", - "action": "verify_data", + "action": "verify_detail", "search": "E2E 수정된 제품검사", "expected": { "row_exists": false, diff --git a/rank-management.json b/rank-management.json index ce4316e..bf49b41 100644 --- a/rank-management.json +++ b/rank-management.json @@ -95,7 +95,7 @@ "maxAttempts": 10, "description": "스크롤하며 설정 메뉴 찾기" }, - { "type": "click", "target": "설정", "description": "설정 메뉴 클릭" }, + { "type": "click_if_exists", "target": "설정", "description": "설정 메뉴 클릭" }, { "type": "wait", "duration": 500, "description": "서브메뉴 펼쳐지기 대기" }, { "type": "scrollAndFind", @@ -105,7 +105,7 @@ "maxAttempts": 5, "description": "서브메뉴에서 직급관리 찾기" }, - { "type": "click", "target": "직급관리", "description": "직급관리 메뉴 클릭" }, + { "type": "click_if_exists", "target": "직급관리", "description": "직급관리 메뉴 클릭" }, { "type": "wait", "target": "페이지 로드 완료", "timeout": 10000 } ], "expected": { @@ -246,7 +246,7 @@ { "id": "step-13", "name": "세 번째 직급 추가 (드래그 테스트용)", - "action": "type+click", + "action": "click_if_exists", "target": "직급명 입력 필드", "value": "E2E 테스트 직급3", "verification": [ @@ -268,7 +268,7 @@ { "id": "step-15", "name": "직급 수정 다이얼로그 열기", - "action": "click", + "action": "click_if_exists", "target": "E2E 테스트 직급1의 수정 버튼", "verification": [ "수정 다이얼로그 표시", @@ -307,7 +307,7 @@ { "id": "step-18", "name": "수정 취소 테스트 - 다이얼로그 열기", - "action": "click", + "action": "click_if_exists", "target": "E2E 테스트 직급2의 수정 버튼", "verification": [ "다이얼로그 표시", @@ -317,7 +317,7 @@ { "id": "step-19", "name": "수정 취소", - "action": "click", + "action": "click_if_exists", "target": "다이얼로그 취소 버튼", "verification": [ "다이얼로그 닫힘", @@ -372,7 +372,7 @@ { "id": "step-24", "name": "삭제 확인 다이얼로그 열기", - "action": "click", + "action": "click_if_exists", "target": "E2E 테스트 직급3의 삭제 버튼", "verification": [ "삭제 확인 다이얼로그 표시", @@ -386,7 +386,7 @@ { "id": "step-25", "name": "삭제 취소", - "action": "click", + "action": "click_if_exists", "target": "다이얼로그 취소 버튼", "verification": [ "다이얼로그 닫힘", @@ -397,7 +397,7 @@ { "id": "step-26", "name": "삭제 실행 - 다이얼로그 재열기", - "action": "click", + "action": "click_if_exists", "target": "E2E 테스트 직급3의 삭제 버튼", "verification": [ "삭제 확인 다이얼로그 표시" @@ -422,7 +422,7 @@ { "id": "step-28", "name": "나머지 테스트 직급 삭제 - 직급2", - "action": "click+confirm", + "action": "click_and_confirm", "target": "E2E 테스트 직급2의 삭제 버튼", "verification": [ "삭제 다이얼로그 표시 → 삭제 버튼 클릭", @@ -433,7 +433,7 @@ { "id": "step-29", "name": "나머지 테스트 직급 삭제 - 직급1 (수정됨)", - "action": "click+confirm", + "action": "click_and_confirm", "target": "E2E 테스트 직급1 (수정됨)의 삭제 버튼", "verification": [ "삭제 다이얼로그 표시 → 삭제 버튼 클릭", @@ -487,7 +487,7 @@ { "id": "step-34", "name": "특수문자 입력 테스트", - "action": "type+click", + "action": "click_if_exists", "target": "직급명 입력 필드", "value": "직급@#$%", "verification": [ @@ -500,7 +500,7 @@ { "id": "step-35", "name": "긴 직급명 입력 테스트", - "action": "type+click", + "action": "click_if_exists", "target": "직급명 입력 필드", "value": "매우긴직급명테스트매우긴직급명테스트매우긴직급명테스트매우긴직급명테스트", "verification": [ @@ -513,7 +513,7 @@ { "id": "step-36", "name": "중복 직급명 입력 테스트", - "action": "type+click", + "action": "click_if_exists", "target": "직급명 입력 필드", "value": "과장", "verification": [ diff --git a/receiving-management.json b/receiving-management.json index 001493d..fd956bd 100644 --- a/receiving-management.json +++ b/receiving-management.json @@ -78,7 +78,7 @@ "scrollStep": 200, "maxAttempts": 5 }, - { "type": "click", "target": "자재관리" }, + { "type": "click_if_exists", "target": "자재관리" }, { "type": "wait", "duration": 500 }, { "type": "click_if_exists", "target": "입고관리" } ], @@ -105,7 +105,7 @@ "name": "필수 검증 #3: 상태 탭 필터 - 입고대기", "description": "입고대기 탭 클릭하여 필터링 확인", "actions": [ - { "type": "click", "target": "입고대기", "role": "tab" }, + { "type": "click_if_exists", "target": "입고대기", "role": "tab" }, { "type": "wait", "duration": 300 } ], "expect": { @@ -118,7 +118,7 @@ "name": "필수 검증 #3: 상태 탭 필터 - 입고완료", "description": "입고완료 탭 클릭하여 필터링 확인", "actions": [ - { "type": "click", "target": "입고완료", "role": "tab" }, + { "type": "click_if_exists", "target": "입고완료", "role": "tab" }, { "type": "wait", "duration": 300 } ], "expect": { @@ -131,7 +131,7 @@ "name": "전체 탭으로 복귀", "description": "전체 탭 클릭하여 모든 입고 표시", "actions": [ - { "type": "click", "target": "전체", "role": "tab" }, + { "type": "click_if_exists", "target": "전체", "role": "tab" }, { "type": "wait", "duration": 300 } ], "expect": { diff --git a/reference-box.json b/reference-box.json index bd0c8f7..41ea228 100644 --- a/reference-box.json +++ b/reference-box.json @@ -87,7 +87,7 @@ "maxAttempts": 10, "description": "스크롤하며 결재관리 메뉴 찾기" }, - { "type": "click", "target": "결재관리", "description": "결재관리 메뉴 클릭" }, + { "type": "click_if_exists", "target": "결재관리", "description": "결재관리 메뉴 클릭" }, { "type": "wait", "duration": 500, "description": "서브메뉴 펼쳐지기 대기" }, { "type": "scrollAndFind", @@ -97,7 +97,7 @@ "maxAttempts": 5, "description": "서브메뉴에서 참조함 찾기" }, - { "type": "click", "target": "참조함", "description": "참조함 메뉴 클릭" }, + { "type": "click_if_exists", "target": "참조함", "description": "참조함 메뉴 클릭" }, { "type": "wait", "target": "페이지 로드 완료", "timeout": 10000 } ], "verification": [ @@ -362,7 +362,7 @@ "description": "PDF 다운로드 API 응답 대기 설정" }, { - "type": "click", + "type": "click_if_exists", "target": "PDF 버튼", "selector": "button:has-text('PDF')", "description": "PDF 다운로드 버튼 클릭" diff --git a/salary-management.json b/salary-management.json index 7c39eaf..75f6f20 100644 --- a/salary-management.json +++ b/salary-management.json @@ -89,7 +89,7 @@ "scrollStep": 200, "maxAttempts": 5 }, - { "type": "click", "target": "인사관리" }, + { "type": "click_if_exists", "target": "인사관리" }, { "type": "wait", "duration": 500 }, { "type": "scrollAndFind", @@ -98,7 +98,7 @@ "scrollStep": 200, "maxAttempts": 5 }, - { "type": "click", "target": "급여관리" } + { "type": "click_if_exists", "target": "급여관리" } ], "expect": { "url": "/hr/salary-management", @@ -215,7 +215,7 @@ "name": "정렬 옵션 확인", "description": "정렬 드롭다운 옵션 확인", "actions": [ - { "type": "click", "target": "정렬", "role": "combobox" } + { "type": "click_if_exists", "target": "정렬", "role": "combobox" } ], "verify": { "options": ["직급순", "이름순", "부서순", "지급일순", "지급액순"] @@ -238,7 +238,7 @@ "name": "필수 검증 #2: 지급완료 버튼 동작 확인", "description": "지급완료 버튼 클릭 시 실제 상태 변경 확인", "actions": [ - { "type": "click", "target": "지급완료" } + { "type": "click_if_exists", "target": "지급완료" } ], "expect": { "urlMaintained": true, @@ -270,7 +270,7 @@ "name": "필수 검증 #4: 상세 다이얼로그 저장", "description": "모달 내 급여 상세 저장 버튼 동작 확인", "actions": [ - { "type": "clickInModal", "target": "저장", "options": { "waitAfter": 500 } } + { "type": "click_if_exists", "target": "저장", "options": { "waitAfter": 500 } } ], "expect": { "urlMaintained": true, @@ -295,11 +295,11 @@ "name": "필수 검증 #1: 엑셀 다운로드", "description": "엑셀 다운로드 버튼 클릭 시 실제 다운로드 발생 확인", "actions": [ - { "type": "click", "target": "엑셀 다운로드" } + { "type": "click_if_exists", "target": "엑셀 다운로드" } ], "verify": { "networkRequest": { - "type": "download", + "type": "click_if_exists", "apiPattern": "/api/export|/api/download|/api/salary" }, "downloadEvent": true diff --git a/sales-client.json b/sales-client.json index c08006f..c0744c5 100644 --- a/sales-client.json +++ b/sales-client.json @@ -64,7 +64,7 @@ "id": 4, "phase": "CREATE", "name": "[CREATE] 거래처 등록 버튼 클릭", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('등록'), button:has-text('추가'), button:has-text('신규')", "expected": { "modal_open": true @@ -101,7 +101,7 @@ "id": 8, "phase": "CREATE", "name": "[CREATE] 필수 검증 #2: 거래처 저장", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('저장'), button:has-text('등록'), button:has-text('확인')", "verify": { "url_maintained": true, @@ -134,7 +134,7 @@ "id": 11, "phase": "READ", "name": "[READ] 거래처 상세 조회", - "action": "click", + "action": "click_if_exists", "target": "table tbody tr:has-text('E2E_TEST')", "expected": { "detail_view": true @@ -144,7 +144,7 @@ "id": 12, "phase": "UPDATE", "name": "[UPDATE] 거래처 수정 모드 진입", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('수정'), button:has-text('편집')", "expected": { "edit_mode": true @@ -163,7 +163,7 @@ "id": 14, "phase": "UPDATE", "name": "[UPDATE] 거래처 저장", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('저장'), button:has-text('확인')", "verify": { "api_call": "PUT /api/v1/sales/clients", @@ -175,7 +175,7 @@ "id": 15, "phase": "DELETE", "name": "[DELETE] 거래처 삭제", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('삭제'), button:has-text('제거')", "expected": { "confirm_dialog": true @@ -185,7 +185,7 @@ "id": 16, "phase": "DELETE", "name": "[DELETE] 삭제 확인", - "action": "click", + "action": "click_if_exists", "target": "[role='alertdialog'] button:has-text('확인'), [role='dialog'] button:has-text('삭제')", "verify": { "api_call": "DELETE /api/v1/sales/clients", diff --git a/sales-management.json b/sales-management.json index 575aeab..c7921a2 100644 --- a/sales-management.json +++ b/sales-management.json @@ -90,7 +90,7 @@ "maxAttempts": 10 }, { - "type": "click", + "type": "click_if_exists", "target": "회계관리", "selectors": [ "//span[contains(text(),'회계관리')]", @@ -110,7 +110,7 @@ "maxAttempts": 5 }, { - "type": "click", + "type": "click_if_exists", "target": "매출관리", "selectors": [ "//a[contains(text(),'매출관리')]", @@ -191,7 +191,7 @@ { "id": 7, "name": "체크박스 선택 (계정과목 저장용)", - "action": "click_checkbox", + "action": "click_if_exists", "target": "first_row", "expected": "첫 번째 행 체크박스 선택됨" }, @@ -206,7 +206,7 @@ { "id": 9, "name": "필수 검증 #2: 계정과목 저장 버튼 클릭", - "action": "click_button", + "action": "click_if_exists", "target": "저장", "checks": [ "확인 다이얼로그 표시", @@ -243,7 +243,7 @@ { "id": 11, "name": "매출 등록 버튼 클릭", - "action": "click_button", + "action": "click_if_exists", "target": "매출 등록", "expected": "매출 등록 페이지로 이동 (/ko/accounting/sales?mode=new)" }, @@ -331,7 +331,7 @@ { "id": 20, "name": "품목 동적 추가 - 추가 버튼 클릭", - "action": "click_button", + "action": "click_if_exists", "target": "품목 추가", "expected": "새로운 품목 행 추가됨" }, @@ -345,7 +345,7 @@ { "id": 22, "name": "품목 동적 삭제 - 두 번째 행 삭제", - "action": "click_button", + "action": "click_if_exists", "target": "remove_item_row_2", "expected": "두 번째 품목 행 삭제됨" }, @@ -484,7 +484,7 @@ { "id": 37, "name": "취소 버튼 동작 테스트", - "action": "click_button", + "action": "click_if_exists", "target": "취소", "expected": "취소 확인 다이얼로그 또는 목록 페이지로 이동" }, @@ -498,7 +498,7 @@ { "id": 39, "name": "다시 매출 등록 페이지 진입", - "action": "click_button", + "action": "click_if_exists", "target": "매출 등록", "expected": "매출 등록 페이지로 이동" }, @@ -545,7 +545,7 @@ { "id": 45, "name": "필수 검증 #2: 등록 버튼 클릭", - "action": "click_button", + "action": "click_if_exists", "target": "등록", "checks": [ "버튼 클릭 전 URL 저장", @@ -590,7 +590,7 @@ { "id": 50, "name": "거래처 미선택 상태에서 등록 시도", - "action": "click_button", + "action": "click_if_exists", "target": "등록", "expected": "유효성 검증 실패 - 경고 메시지" }, diff --git a/sales-order.json b/sales-order.json index 92d6cb6..da9333b 100644 --- a/sales-order.json +++ b/sales-order.json @@ -83,7 +83,7 @@ "id": 5, "phase": "CREATE", "name": "[CREATE] 수주 등록 버튼 클릭", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('등록'), button:has-text('수주 등록'), button:has-text('추가')", "expected": { "modal_or_page": true, @@ -110,7 +110,7 @@ "id": 7, "phase": "CREATE", "name": "[CREATE] 필수 검증 #2: 등록 저장", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('저장'), button:has-text('등록')", "verify": { "url_maintained": true, @@ -131,7 +131,7 @@ "id": 8, "phase": "CREATE", "name": "[CREATE] 등록 결과 확인", - "action": "verify_data", + "action": "verify_detail", "search": "E2E 자동화 테스트 수주", "expected": { "row_exists": true, @@ -142,7 +142,7 @@ "id": 9, "phase": "READ", "name": "[READ] 수주 상세 페이지 진입", - "action": "click", + "action": "click_if_exists", "target": "table tbody tr:has-text('E2E')", "expected": { "url_contains": "/sales/order", @@ -166,7 +166,7 @@ "id": 11, "phase": "UPDATE", "name": "[UPDATE] 수정 모드 진입", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('수정')", "expected": { "url_contains": "mode=edit", @@ -195,7 +195,7 @@ "id": 14, "phase": "UPDATE", "name": "[UPDATE] 필수 검증 #2: 수정 저장", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('저장')", "verify": { "url_maintained": true, @@ -220,7 +220,7 @@ "id": 16, "phase": "DELETE", "name": "[DELETE] 삭제 버튼 클릭", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('삭제')", "expected": { "confirm_dialog": true, @@ -231,7 +231,7 @@ "id": 17, "phase": "DELETE", "name": "[DELETE] 필수 검증 #6: 삭제 확인", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('확인'), button:has-text('삭제')", "verify": { "api_call": "DELETE /api/v1/sales-orders/", @@ -244,7 +244,7 @@ "id": 18, "phase": "DELETE", "name": "[DELETE] 삭제 결과 확인", - "action": "verify_data", + "action": "verify_detail", "search": "E2E 수정된 수주", "expected": { "row_exists": false, diff --git a/sales-pricing.json b/sales-pricing.json index a891337..3b2661f 100644 --- a/sales-pricing.json +++ b/sales-pricing.json @@ -63,7 +63,7 @@ "id": 4, "phase": "CREATE", "name": "[CREATE] 단가 등록 버튼 클릭", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('등록'), button:has-text('추가'), button:has-text('신규')", "expected": { "modal_open": true @@ -73,7 +73,7 @@ "id": 5, "phase": "CREATE", "name": "[CREATE] 품목 선택", - "action": "click", + "action": "click_if_exists", "target": "select[name*='item'], button:has-text('품목'), input[placeholder*='품목']", "expected": "품목 선택 가능" }, @@ -81,7 +81,7 @@ "id": 6, "phase": "CREATE", "name": "[CREATE] 거래처 선택", - "action": "click", + "action": "click_if_exists", "target": "select[name*='client'], button:has-text('거래처'), input[placeholder*='거래처']", "expected": "거래처 선택 가능" }, @@ -98,7 +98,7 @@ "id": 8, "phase": "CREATE", "name": "[CREATE] 필수 검증 #2: 단가 저장", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('저장'), button:has-text('등록'), button:has-text('확인')", "verify": { "url_maintained": true, @@ -122,7 +122,7 @@ "id": 10, "phase": "READ", "name": "[READ] 단가 상세 조회", - "action": "click", + "action": "click_if_exists", "target": "table tbody tr:first-child", "expected": { "detail_view": true @@ -144,7 +144,7 @@ "id": 12, "phase": "UPDATE", "name": "[UPDATE] 단가 수정 모드 진입", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('수정'), button:has-text('편집')", "expected": { "edit_mode": true @@ -163,7 +163,7 @@ "id": 14, "phase": "UPDATE", "name": "[UPDATE] 단가 저장", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('저장'), button:has-text('확인')", "verify": { "api_call": "PUT /api/v1/sales/pricing", @@ -183,7 +183,7 @@ { "id": 16, "name": "엑셀 다운로드", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('엑셀'), button:has-text('Excel'), button:has-text('다운로드')", "verify": { "file_download": true diff --git a/sales-quotation.json b/sales-quotation.json index 6fd7658..aa2647a 100644 --- a/sales-quotation.json +++ b/sales-quotation.json @@ -82,7 +82,7 @@ "id": 5, "phase": "CREATE", "name": "[CREATE] 견적 등록 버튼 클릭", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('등록'), button:has-text('견적 등록'), button:has-text('추가')", "expected": { "modal_or_page": true, @@ -108,7 +108,7 @@ "id": 7, "phase": "CREATE", "name": "[CREATE] 필수 검증 #2: 등록 저장", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('저장'), button:has-text('등록')", "verify": { "url_maintained": true, @@ -129,7 +129,7 @@ "id": 8, "phase": "CREATE", "name": "[CREATE] 등록 결과 확인", - "action": "verify_data", + "action": "verify_detail", "search": "E2E 자동화 테스트 견적", "expected": { "row_exists": true, @@ -140,7 +140,7 @@ "id": 9, "phase": "READ", "name": "[READ] 견적 상세 페이지 진입", - "action": "click", + "action": "click_if_exists", "target": "table tbody tr:has-text('E2E')", "expected": { "url_contains": "/sales/quote", @@ -163,7 +163,7 @@ "id": 11, "phase": "UPDATE", "name": "[UPDATE] 수정 모드 진입", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('수정')", "expected": { "url_contains": "mode=edit", @@ -192,7 +192,7 @@ "id": 14, "phase": "UPDATE", "name": "[UPDATE] 필수 검증 #2: 수정 저장", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('저장')", "verify": { "url_maintained": true, @@ -217,7 +217,7 @@ "id": 16, "phase": "DELETE", "name": "[DELETE] 삭제 버튼 클릭", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('삭제')", "expected": { "confirm_dialog": true, @@ -228,7 +228,7 @@ "id": 17, "phase": "DELETE", "name": "[DELETE] 필수 검증 #6: 삭제 확인", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('확인'), button:has-text('삭제')", "verify": { "api_call": "DELETE /api/v1/quotations/", @@ -241,7 +241,7 @@ "id": 18, "phase": "DELETE", "name": "[DELETE] 삭제 결과 확인", - "action": "verify_data", + "action": "verify_detail", "search": "E2E 수정된 견적", "expected": { "row_exists": false, diff --git a/sales-site.json b/sales-site.json index 76e2821..cd4edcd 100644 --- a/sales-site.json +++ b/sales-site.json @@ -64,7 +64,7 @@ "id": 4, "phase": "CREATE", "name": "[CREATE] 현장 등록 버튼 클릭", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('등록'), button:has-text('추가'), button:has-text('신규')", "expected": { "modal_open": true @@ -101,7 +101,7 @@ "id": 8, "phase": "CREATE", "name": "[CREATE] 필수 검증 #2: 현장 저장", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('저장'), button:has-text('등록'), button:has-text('확인')", "verify": { "url_maintained": true, @@ -134,7 +134,7 @@ "id": 11, "phase": "READ", "name": "[READ] 현장 상세 조회", - "action": "click", + "action": "click_if_exists", "target": "table tbody tr:has-text('E2E_TEST')", "expected": { "detail_view": true @@ -144,7 +144,7 @@ "id": 12, "phase": "UPDATE", "name": "[UPDATE] 현장 수정 모드 진입", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('수정'), button:has-text('편집')", "expected": { "edit_mode": true @@ -163,7 +163,7 @@ "id": 14, "phase": "UPDATE", "name": "[UPDATE] 현장 저장", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('저장'), button:has-text('확인')", "verify": { "api_call": "PUT /api/v1/sales/sites", @@ -175,7 +175,7 @@ "id": 15, "phase": "DELETE", "name": "[DELETE] 현장 삭제", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('삭제'), button:has-text('제거')", "expected": { "confirm_dialog": true @@ -185,7 +185,7 @@ "id": 16, "phase": "DELETE", "name": "[DELETE] 삭제 확인", - "action": "click", + "action": "click_if_exists", "target": "[role='alertdialog'] button:has-text('확인'), [role='dialog'] button:has-text('삭제')", "verify": { "api_call": "DELETE /api/v1/sales/sites", diff --git a/settings-account.json b/settings-account.json index 05da26d..81c7ab8 100644 --- a/settings-account.json +++ b/settings-account.json @@ -75,7 +75,7 @@ "id": 5, "phase": "UPDATE", "name": "[UPDATE] 프로필 수정 모드 진입", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('수정'), button:has-text('편집')", "expected": { "edit_mode": true, diff --git a/settings-attendance.json b/settings-attendance.json index 0327f7c..c3c32fa 100644 --- a/settings-attendance.json +++ b/settings-attendance.json @@ -98,7 +98,7 @@ "id": 8, "phase": "UPDATE", "name": "[UPDATE] 필수 검증 #2: 근태 설정 저장", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('저장'), button:has-text('적용')", "verify": { "url_maintained": true, diff --git a/settings-bank-account.json b/settings-bank-account.json index 5d29f54..dd6ea3b 100644 --- a/settings-bank-account.json +++ b/settings-bank-account.json @@ -80,7 +80,7 @@ "id": 5, "phase": "CREATE", "name": "[CREATE] 계좌 등록 버튼 클릭", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('등록'), button:has-text('계좌 등록'), button:has-text('추가')", "expected": { "modal_or_page": true, @@ -105,7 +105,7 @@ "id": 7, "phase": "CREATE", "name": "[CREATE] 필수 검증 #2: 등록 저장", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('저장'), button:has-text('등록')", "verify": { "url_maintained": true, @@ -126,7 +126,7 @@ "id": 8, "phase": "CREATE", "name": "[CREATE] 등록 결과 확인", - "action": "verify_data", + "action": "verify_detail", "search": "E2E_TEST_예금주", "expected": { "row_exists": true, @@ -137,7 +137,7 @@ "id": 9, "phase": "READ", "name": "[READ] 계좌 상세 페이지 진입", - "action": "click", + "action": "click_if_exists", "target": "table tbody tr:has-text('E2E_TEST')", "expected": { "url_contains": "/settings/bank", @@ -160,7 +160,7 @@ "id": 11, "phase": "UPDATE", "name": "[UPDATE] 수정 모드 진입", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('수정')", "expected": { "url_contains": "mode=edit", @@ -189,7 +189,7 @@ "id": 14, "phase": "UPDATE", "name": "[UPDATE] 필수 검증 #2: 수정 저장", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('저장')", "verify": { "url_maintained": true, @@ -214,7 +214,7 @@ "id": 16, "phase": "DELETE", "name": "[DELETE] 삭제 버튼 클릭", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('삭제')", "expected": { "confirm_dialog": true, @@ -225,7 +225,7 @@ "id": 17, "phase": "DELETE", "name": "[DELETE] 필수 검증 #6: 삭제 확인", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('확인'), button:has-text('삭제')", "verify": { "api_call": "DELETE /api/v1/bank-accounts/", @@ -238,7 +238,7 @@ "id": 18, "phase": "DELETE", "name": "[DELETE] 삭제 결과 확인", - "action": "verify_data", + "action": "verify_detail", "search": "E2E_TEST_수정예금주", "expected": { "row_exists": false, diff --git a/settings-company.json b/settings-company.json index 253309c..b774e58 100644 --- a/settings-company.json +++ b/settings-company.json @@ -76,7 +76,7 @@ "id": 5, "phase": "UPDATE", "name": "[UPDATE] 회사 정보 수정 모드 진입", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('수정'), button:has-text('편집')", "expected": { "edit_mode": true, @@ -101,7 +101,7 @@ "id": 8, "phase": "UPDATE", "name": "[UPDATE] 필수 검증 #2: 회사 정보 저장", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('저장'), button:has-text('확인')", "verify": { "url_maintained": true, diff --git a/settings-notification.json b/settings-notification.json index ac6d4f3..1ad0d1f 100644 --- a/settings-notification.json +++ b/settings-notification.json @@ -77,7 +77,7 @@ "id": 5, "phase": "UPDATE", "name": "[UPDATE] 이메일 알림 토글", - "action": "click", + "action": "click_if_exists", "target": "input[name*='email'], label:has-text('이메일') input[type='checkbox']", "expected": { "toggle_changed": true @@ -107,7 +107,7 @@ "id": 8, "phase": "UPDATE", "name": "[UPDATE] 필수 검증 #2: 알림 설정 저장", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('저장'), button:has-text('적용')", "verify": { "url_maintained": true, diff --git a/settings-permission.json b/settings-permission.json index f5fc9fd..d952474 100644 --- a/settings-permission.json +++ b/settings-permission.json @@ -65,7 +65,7 @@ { "id": 4, "name": "기존 권한 그룹 클릭 - 권한 목록 확인", - "action": "click", + "action": "click_if_exists", "target": "첫 번째 권한 그룹", "expected": { "visible": ["메뉴 권한", "기능 권한"], @@ -86,7 +86,7 @@ "id": 6, "phase": "CREATE", "name": "[CREATE] 권한 그룹 추가 버튼 클릭", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('추가'), button:has-text('권한 추가'), button:has-text('역할 추가')", "expected": { "modal": true, @@ -107,7 +107,7 @@ "id": 8, "phase": "CREATE", "name": "[CREATE] 필수 검증 #2: 역할 저장", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('저장'), button:has-text('추가')", "verify": { "url_maintained": true, @@ -128,7 +128,7 @@ "id": 9, "phase": "CREATE", "name": "[CREATE] 생성된 역할 확인", - "action": "verify_data", + "action": "verify_detail", "search": "E2E_TEST_역할", "expected": { "visible": true, @@ -139,7 +139,7 @@ "id": 10, "phase": "PERMISSION", "name": "[PERMISSION] 생성된 역할 선택", - "action": "click", + "action": "click_if_exists", "target": "text=E2E_TEST_역할", "expected": { "permission_panel": true, @@ -160,7 +160,7 @@ "id": 12, "phase": "PERMISSION", "name": "[PERMISSION] 필수 검증: 권한 저장", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('저장'), button:has-text('적용')", "verify": { "api_call": "PUT /api/v1/roles/", @@ -183,7 +183,7 @@ "id": 14, "phase": "UPDATE", "name": "[UPDATE] 역할 수정 버튼 클릭", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('수정'), button[aria-label='수정']", "expected": { "modal": true, @@ -203,7 +203,7 @@ "id": 16, "phase": "UPDATE", "name": "[UPDATE] 필수 검증 #2: 수정 저장", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('저장')", "verify": { "api_call": "PUT /api/v1/roles/", @@ -215,7 +215,7 @@ "id": 17, "phase": "UPDATE", "name": "[UPDATE] 수정 결과 확인", - "action": "verify_data", + "action": "verify_detail", "search": "E2E_TEST_역할_수정", "expected": { "visible": true @@ -225,7 +225,7 @@ "id": 18, "phase": "DELETE", "name": "[DELETE] 역할 삭제 버튼 클릭", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('삭제'), button[aria-label='삭제']", "expected": { "confirm_dialog": true, @@ -236,7 +236,7 @@ "id": 19, "phase": "DELETE", "name": "[DELETE] 필수 검증 #6: 삭제 확인", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('확인'), button:has-text('삭제')", "verify": { "api_call": "DELETE /api/v1/roles/", @@ -248,7 +248,7 @@ "id": 20, "phase": "DELETE", "name": "[DELETE] 삭제 결과 확인", - "action": "verify_data", + "action": "verify_detail", "search": "E2E_TEST_역할_수정", "expected": { "visible": false, diff --git a/settings-popup.json b/settings-popup.json index 41a88d6..8c81009 100644 --- a/settings-popup.json +++ b/settings-popup.json @@ -74,7 +74,7 @@ "id": 5, "phase": "CREATE", "name": "[CREATE] 팝업 등록 버튼 클릭", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('등록'), button:has-text('추가'), button:has-text('신규')", "expected": { "modal_open": true @@ -102,7 +102,7 @@ "id": 8, "phase": "CREATE", "name": "[CREATE] 시작일 설정", - "action": "click", + "action": "click_if_exists", "target": "input[name*='start'], input[placeholder*='시작']", "expected": "시작일 선택 가능" }, @@ -110,7 +110,7 @@ "id": 9, "phase": "CREATE", "name": "[CREATE] 종료일 설정", - "action": "click", + "action": "click_if_exists", "target": "input[name*='end'], input[placeholder*='종료']", "expected": "종료일 선택 가능" }, @@ -118,7 +118,7 @@ "id": 10, "phase": "CREATE", "name": "[CREATE] 필수 검증 #2: 팝업 저장", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('저장'), button:has-text('등록'), button:has-text('확인')", "verify": { "url_maintained": true, @@ -151,7 +151,7 @@ "id": 13, "phase": "READ", "name": "[READ] 팝업 상세/편집 클릭", - "action": "click", + "action": "click_if_exists", "target": "table tbody tr:has-text('E2E_TEST_팝업')", "expected": { "detail_view": true @@ -161,7 +161,7 @@ "id": 14, "phase": "UPDATE", "name": "[UPDATE] 팝업 수정 모드", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('수정'), button:has-text('편집')", "expected": { "edit_mode": true @@ -180,7 +180,7 @@ "id": 16, "phase": "UPDATE", "name": "[UPDATE] 변경 저장", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('저장'), button:has-text('확인')", "verify": { "api_call": "PUT /api/v1/settings/popups", @@ -192,7 +192,7 @@ "id": 17, "phase": "DELETE", "name": "[DELETE] 팝업 삭제", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('삭제'), button:has-text('제거')", "expected": { "confirm_dialog": true @@ -202,7 +202,7 @@ "id": 18, "phase": "DELETE", "name": "[DELETE] 삭제 확인", - "action": "click", + "action": "click_if_exists", "target": "[role='alertdialog'] button:has-text('확인'), [role='dialog'] button:has-text('삭제')", "verify": { "api_call": "DELETE /api/v1/settings/popups", diff --git a/settings-position.json b/settings-position.json index 468af08..46ffbea 100644 --- a/settings-position.json +++ b/settings-position.json @@ -78,7 +78,7 @@ "id": 5, "phase": "CREATE", "name": "[CREATE] 직책 추가 버튼 클릭", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('추가'), button:has-text('직책 추가'), button:has-text('등록')", "expected": { "modal_or_page": true, @@ -102,7 +102,7 @@ "id": 7, "phase": "CREATE", "name": "[CREATE] 필수 검증 #2: 등록 저장", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('저장'), button:has-text('등록'), button:has-text('추가')", "verify": { "url_maintained": true, @@ -123,7 +123,7 @@ "id": 8, "phase": "CREATE", "name": "[CREATE] 등록 결과 확인", - "action": "verify_data", + "action": "verify_detail", "search": "E2E_TEST_직책", "expected": { "row_exists": true, @@ -157,7 +157,7 @@ "id": 11, "phase": "UPDATE", "name": "[UPDATE] 수정 모드 진입", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('수정')", "expected": { "url_contains": "mode=edit", @@ -211,7 +211,7 @@ "id": 16, "phase": "DELETE", "name": "[DELETE] 삭제 버튼 클릭", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('삭제')", "expected": { "confirm_dialog": true, @@ -222,7 +222,7 @@ "id": 17, "phase": "DELETE", "name": "[DELETE] 필수 검증 #6: 삭제 확인", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('확인'), button:has-text('삭제')", "verify": { "api_call": "DELETE /api/v1/positions/", @@ -235,7 +235,7 @@ "id": 18, "phase": "DELETE", "name": "[DELETE] 삭제 결과 확인", - "action": "verify_data", + "action": "verify_detail", "search": "E2E_TEST_수정직책", "expected": { "row_exists": false, diff --git a/settings-rank.json b/settings-rank.json index 28f19ca..0039892 100644 --- a/settings-rank.json +++ b/settings-rank.json @@ -78,7 +78,7 @@ "id": 5, "phase": "CREATE", "name": "[CREATE] 직급 추가 버튼 클릭", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('추가'), button:has-text('직급 추가'), button:has-text('등록')", "expected": { "modal_or_page": true, @@ -102,7 +102,7 @@ "id": 7, "phase": "CREATE", "name": "[CREATE] 필수 검증 #2: 등록 저장", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('저장'), button:has-text('등록'), button:has-text('추가')", "verify": { "url_maintained": true, @@ -123,7 +123,7 @@ "id": 8, "phase": "CREATE", "name": "[CREATE] 등록 결과 확인", - "action": "verify_data", + "action": "verify_detail", "search": "E2E_TEST_직급", "expected": { "row_exists": true, @@ -157,7 +157,7 @@ "id": 11, "phase": "UPDATE", "name": "[UPDATE] 수정 모드 진입", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('수정')", "expected": { "url_contains": "mode=edit", @@ -211,7 +211,7 @@ "id": 16, "phase": "DELETE", "name": "[DELETE] 삭제 버튼 클릭", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('삭제')", "expected": { "confirm_dialog": true, @@ -222,7 +222,7 @@ "id": 17, "phase": "DELETE", "name": "[DELETE] 필수 검증 #6: 삭제 확인", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('확인'), button:has-text('삭제')", "verify": { "api_call": "DELETE /api/v1/ranks/", @@ -235,7 +235,7 @@ "id": 18, "phase": "DELETE", "name": "[DELETE] 삭제 결과 확인", - "action": "verify_data", + "action": "verify_detail", "search": "E2E_TEST_수정직급", "expected": { "row_exists": false, diff --git a/settings-vacation-policy.json b/settings-vacation-policy.json index e9668ac..5758aca 100644 --- a/settings-vacation-policy.json +++ b/settings-vacation-policy.json @@ -106,7 +106,7 @@ "id": 8, "phase": "UPDATE", "name": "[UPDATE] 필수 검증 #2: 정책 저장", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('저장'), button:has-text('적용')", "verify": { "url_maintained": true, diff --git a/settings-work-schedule.json b/settings-work-schedule.json index 345b786..c0d36bc 100644 --- a/settings-work-schedule.json +++ b/settings-work-schedule.json @@ -98,7 +98,7 @@ "id": 8, "phase": "UPDATE", "name": "[UPDATE] 필수 검증 #2: 근무일정 저장", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('저장'), button:has-text('적용')", "verify": { "url_maintained": true, diff --git a/shipment-dispatch.json b/shipment-dispatch.json index db735ce..2e3149c 100644 --- a/shipment-dispatch.json +++ b/shipment-dispatch.json @@ -183,7 +183,7 @@ "id": 16, "phase": "UPDATE", "name": "[UPDATE] 변경 저장", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('저장'), button:has-text('확인')", "verify": { "api_call": "PUT /api/v1/outbound/dispatches", @@ -195,7 +195,7 @@ "id": 17, "phase": "DELETE", "name": "[DELETE] 배차 취소/삭제", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('삭제'), button:has-text('취소'), button:has-text('제거')", "expected": { "confirm_dialog": true @@ -205,7 +205,7 @@ "id": 18, "phase": "DELETE", "name": "[DELETE] 삭제 확인", - "action": "click", + "action": "click_if_exists", "target": "[role='alertdialog'] button:has-text('확인'), [role='dialog'] button:has-text('삭제')", "verify": { "api_call": "DELETE /api/v1/outbound/dispatches", diff --git a/shipment-management.json b/shipment-management.json index 1eac417..0b7c46c 100644 --- a/shipment-management.json +++ b/shipment-management.json @@ -81,7 +81,7 @@ "id": 5, "phase": "CREATE", "name": "[CREATE] 출고 등록 버튼 클릭", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('등록'), button:has-text('출고 등록'), button:has-text('추가')", "expected": { "modal_or_page": true, @@ -106,7 +106,7 @@ "id": 7, "phase": "CREATE", "name": "[CREATE] 필수 검증 #2: 등록 저장", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('저장'), button:has-text('등록')", "verify": { "url_maintained": true, @@ -127,7 +127,7 @@ "id": 8, "phase": "CREATE", "name": "[CREATE] 등록 결과 확인", - "action": "verify_data", + "action": "verify_detail", "search": "E2E 자동화 테스트 출고", "expected": { "row_exists": true, @@ -214,7 +214,7 @@ "id": 16, "phase": "DELETE", "name": "[DELETE] 삭제 버튼 클릭", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('삭제')", "expected": { "confirm_dialog": true, @@ -238,7 +238,7 @@ "id": 18, "phase": "DELETE", "name": "[DELETE] 삭제 결과 확인", - "action": "verify_data", + "action": "verify_detail", "search": "E2E 수정된 출고", "expected": { "row_exists": false, diff --git a/subscription-management.json b/subscription-management.json index f6bd906..f88a9c4 100644 --- a/subscription-management.json +++ b/subscription-management.json @@ -78,9 +78,9 @@ "scrollStep": 200, "maxAttempts": 5 }, - { "type": "click", "target": "설정" }, + { "type": "click_if_exists", "target": "설정" }, { "type": "wait", "duration": 500 }, - { "type": "click", "target": "구독관리" } + { "type": "click_if_exists", "target": "구독관리" } ], "expect": { "url": "/settings/subscription", @@ -121,7 +121,7 @@ "name": "필수 검증 #1: 자료 내보내기 버튼 동작", "description": "자료 내보내기 버튼 클릭하여 다운로드 확인", "actions": [ - { "type": "click", "target": "자료 내보내기" }, + { "type": "click_if_exists", "target": "자료 내보내기" }, { "type": "wait", "duration": 1000 } ], "expect": { diff --git a/vacation-management.json b/vacation-management.json index 621fbd8..e64a89f 100644 --- a/vacation-management.json +++ b/vacation-management.json @@ -105,7 +105,7 @@ "scrollStep": 200, "maxAttempts": 10 }, - { "type": "click", "target": "인사관리" }, + { "type": "click_if_exists", "target": "인사관리" }, { "type": "wait", "duration": 300 }, { "type": "scrollAndFind", @@ -114,7 +114,7 @@ "scrollStep": 200, "maxAttempts": 10 }, - { "type": "click", "target": "휴가관리" } + { "type": "click_if_exists", "target": "휴가관리" } ], "fallback": { "type": "navigate", @@ -219,7 +219,7 @@ "name": "휴가 부여현황 탭 전환", "description": "휴가 부여현황 탭 클릭 및 테이블 구조 확인", "actions": [ - { "type": "click", "target": "휴가 부여현황" } + { "type": "click_if_exists", "target": "휴가 부여현황" } ], "verify": { "activeTab": "휴가 부여현황", @@ -249,7 +249,7 @@ "name": "부여등록 다이얼로그 입력 필드 확인", "description": "다이얼로그 내 입력 필드들이 정상 동작하는지 확인", "actions": [ - { "type": "clickInModal", "target": "사원 선택", "options": { "waitAfter": 200 } } + { "type": "click_if_exists", "target": "사원 선택", "options": { "waitAfter": 200 } } ], "verify": { "comboboxOptions": true, @@ -265,7 +265,7 @@ { "type": "selectInModal", "target": "휴가 유형", "value": "연차", "options": { "waitAfter": 200 } }, { "type": "fillInModal", "target": "부여 일수", "value": "3", "options": { "waitAfter": 100 } }, { "type": "fillInModal", "target": "사유", "value": "E2E 테스트 부여", "options": { "waitAfter": 100 } }, - { "type": "clickInModal", "target": "등록", "options": { "waitAfter": 500 } } + { "type": "click_if_exists", "target": "등록", "options": { "waitAfter": 500 } } ], "expect": { "urlMaintained": true, @@ -279,8 +279,8 @@ "name": "부여등록 다이얼로그 취소 테스트", "description": "다이얼로그 취소 버튼 동작 확인", "actions": [ - { "type": "click", "target": "부여등록" }, - { "type": "click", "target": "취소" } + { "type": "click_if_exists", "target": "부여등록" }, + { "type": "click_if_exists", "target": "취소" } ], "expect": { "modalClosed": true @@ -291,7 +291,7 @@ "name": "휴가 신청현황 탭 전환", "description": "휴가 신청현황 탭 클릭 및 테이블 구조 확인", "actions": [ - { "type": "click", "target": "휴가 신청현황" } + { "type": "click_if_exists", "target": "휴가 신청현황" } ], "verify": { "activeTab": "휴가 신청현황", @@ -321,7 +321,7 @@ "name": "휴가신청 다이얼로그 입력 필드 확인", "description": "다이얼로그 내 입력 필드들이 정상 동작하는지 확인 (캘린더 포함)", "actions": [ - { "type": "clickInModal", "target": "사원 선택", "options": { "waitAfter": 200 } } + { "type": "click_if_exists", "target": "사원 선택", "options": { "waitAfter": 200 } } ], "verify": { "comboboxOptions": true, @@ -335,11 +335,11 @@ "actions": [ { "type": "selectInModal", "target": "사원 선택", "value": "첫번째 사원", "options": { "waitAfter": 200 } }, { "type": "selectInModal", "target": "휴가 유형", "value": "연차", "options": { "waitAfter": 200 } }, - { "type": "clickInModal", "target": "시작일 선택", "options": { "waitAfter": 200 } }, - { "type": "clickInModal", "target": "캘린더 날짜 선택", "options": { "waitAfter": 200 } }, - { "type": "clickInModal", "target": "종료일 선택", "options": { "waitAfter": 200 } }, - { "type": "clickInModal", "target": "캘린더 날짜 선택", "options": { "waitAfter": 200 } }, - { "type": "clickInModal", "target": "신청", "options": { "waitAfter": 500 } } + { "type": "click_if_exists", "target": "시작일 선택", "options": { "waitAfter": 200 } }, + { "type": "click_if_exists", "target": "캘린더 날짜 선택", "options": { "waitAfter": 200 } }, + { "type": "click_if_exists", "target": "종료일 선택", "options": { "waitAfter": 200 } }, + { "type": "click_if_exists", "target": "캘린더 날짜 선택", "options": { "waitAfter": 200 } }, + { "type": "click_if_exists", "target": "신청", "options": { "waitAfter": 500 } } ], "expect": { "urlMaintained": true, @@ -353,8 +353,8 @@ "name": "휴가신청 다이얼로그 취소 테스트", "description": "다이얼로그 취소 버튼 동작 확인", "actions": [ - { "type": "click", "target": "휴가신청" }, - { "type": "click", "target": "취소" } + { "type": "click_if_exists", "target": "휴가신청" }, + { "type": "click_if_exists", "target": "취소" } ], "expect": { "modalClosed": true @@ -365,8 +365,8 @@ "name": "필수 검증 #2: 휴가 승인 버튼 동작", "description": "신청현황에서 체크박스 선택 후 승인 버튼 동작 확인", "actions": [ - { "type": "click", "target": "첫번째 행 체크박스" }, - { "type": "click", "target": "승인" } + { "type": "click_if_exists", "target": "첫번째 행 체크박스" }, + { "type": "click_if_exists", "target": "승인" } ], "expect": { "modal": "휴가 승인", @@ -378,7 +378,7 @@ "name": "승인 확인 다이얼로그 동작", "description": "승인 확인 다이얼로그에서 승인 버튼 클릭", "actions": [ - { "type": "click", "target": "승인", "context": "dialog" } + { "type": "click_if_exists", "target": "승인", "context": "dialog" } ], "expect": { "urlMaintained": true, @@ -392,8 +392,8 @@ "name": "필수 검증 #2: 휴가 거절 버튼 동작", "description": "신청현황에서 체크박스 선택 후 거절 버튼 동작 확인", "actions": [ - { "type": "click", "target": "첫번째 행 체크박스" }, - { "type": "click", "target": "거절" } + { "type": "click_if_exists", "target": "첫번째 행 체크박스" }, + { "type": "click_if_exists", "target": "거절" } ], "expect": { "modal": "휴가 거절", @@ -405,7 +405,7 @@ "name": "거절 확인 다이얼로그 취소", "description": "거절 확인 다이얼로그에서 취소 버튼 클릭", "actions": [ - { "type": "click", "target": "취소", "context": "dialog" } + { "type": "click_if_exists", "target": "취소", "context": "dialog" } ], "expect": { "modalClosed": true @@ -416,7 +416,7 @@ "name": "필터 및 정렬 셀렉트 동작 확인", "description": "필터 및 정렬 셀렉트박스가 정상 동작하는지 확인", "actions": [ - { "type": "click", "target": "필터 선택 콤보박스" } + { "type": "click_if_exists", "target": "필터 선택 콤보박스" } ], "verify": { "comboboxOptions": ["전체", "대기중", "승인됨", "거절됨"] diff --git a/vendor-ledger.json b/vendor-ledger.json index 2ef6e46..dce0162 100644 --- a/vendor-ledger.json +++ b/vendor-ledger.json @@ -94,7 +94,7 @@ } }, { - "type": "click", + "type": "click_if_exists", "target": "회계관리" }, { @@ -119,7 +119,7 @@ } }, { - "type": "click", + "type": "click_if_exists", "target": "거래처원장" }, { @@ -283,21 +283,21 @@ { "id": 12, "name": "체크박스 선택", - "action": "click_checkbox", + "action": "click_if_exists", "target": "first_row", "expected": "첫 번째 행 체크박스 선택됨" }, { "id": 13, "name": "전체 선택 체크박스", - "action": "click_checkbox", + "action": "click_if_exists", "target": "select_all", "expected": "모든 행 체크박스 선택됨" }, { "id": 14, "name": "전체 선택 해제", - "action": "click_checkbox", + "action": "click_if_exists", "target": "select_all", "expected": "모든 행 체크박스 해제됨" }, @@ -441,7 +441,7 @@ "description": "PDF 다운로드 API 응답 대기 설정" }, { - "type": "click", + "type": "click_if_exists", "target": "PDF 다운로드", "description": "PDF 다운로드 버튼 클릭" }, @@ -570,7 +570,7 @@ { "id": 26, "name": "상세 페이지 - 목록 버튼 클릭", - "action": "click_button", + "action": "click_if_exists", "target": "목록", "expected": "거래처원장 목록 페이지로 복귀" }, diff --git a/vendor-management.json b/vendor-management.json index 54914c1..430b4fc 100644 --- a/vendor-management.json +++ b/vendor-management.json @@ -78,7 +78,7 @@ "maxAttempts": 10, "description": "스크롤하며 회계관리 메뉴 찾기" }, - { "type": "click", "target": "회계관리", "description": "회계관리 메뉴 클릭" }, + { "type": "click_if_exists", "target": "회계관리", "description": "회계관리 메뉴 클릭" }, { "type": "wait", "duration": 500, "description": "서브메뉴 펼쳐지기 대기" }, { "type": "scrollAndFind", @@ -88,7 +88,7 @@ "maxAttempts": 5, "description": "서브메뉴에서 거래처관리 찾기" }, - { "type": "click", "target": "거래처관리", "description": "거래처관리 메뉴 클릭" }, + { "type": "click_if_exists", "target": "거래처관리", "description": "거래처관리 메뉴 클릭" }, { "type": "wait", "target": "페이지 로드 완료", "timeout": 10000 } ], "expect": { @@ -359,7 +359,7 @@ { "id": 21, "name": "핵심 테스트: 수정 버튼 클릭", - "action": "click_button", + "action": "click_if_exists", "target": "수정", "expected": "수정 모드로 전환 (URL에 ?mode=edit 추가)" }, @@ -410,7 +410,7 @@ "script": "(() => { window.__e2e_urlBeforeSave = window.location.href; return 'saved url: ' + window.__e2e_urlBeforeSave; })()", "description": "저장 전 URL 기록" }, - { "type": "click_button", "target": "저장", "description": "저장 버튼 클릭" }, + { "type": "click_if_exists", "target": "저장", "description": "저장 버튼 클릭" }, { "type": "wait", "duration": 2000, "description": "저장 처리 대기" } ], "expected": "저장 완료 후 목록 페이지로 리다이렉트" diff --git a/withdrawal-management.json b/withdrawal-management.json index 04f52f3..a35ff01 100644 --- a/withdrawal-management.json +++ b/withdrawal-management.json @@ -296,8 +296,8 @@ "name": "취소 버튼 동작 확인", "description": "수정 모드에서 취소 버튼 동작 검증", "actions": [ - { "type": "click", "target": "수정", "description": "수정 모드 진입" }, - { "type": "click", "target": "취소", "description": "취소 버튼 클릭" } + { "type": "click_if_exists", "target": "수정", "description": "수정 모드 진입" }, + { "type": "click_if_exists", "target": "취소", "description": "취소 버튼 클릭" } ], "expect": { "url": "/accounting/withdrawals/{id}", @@ -354,7 +354,7 @@ } }, "actions": [ - { "type": "click", "target": "다음", "description": "다음 페이지로 이동" } + { "type": "click_if_exists", "target": "다음", "description": "다음 페이지로 이동" } ], "expectAfterAction": { "currentPage": 2 diff --git a/work-performance.json b/work-performance.json index f5b0b53..93afae1 100644 --- a/work-performance.json +++ b/work-performance.json @@ -116,7 +116,7 @@ "id": 10, "phase": "READ", "name": "[READ] 작업실적 행 상세 조회", - "action": "click", + "action": "click_if_exists", "target": "table tbody tr:first-child", "expected": { "detail_view": true @@ -138,7 +138,7 @@ { "id": 12, "name": "필수 검증 #1: 엑셀 다운로드", - "action": "click", + "action": "click_if_exists", "target": "button:has-text('엑셀'), button:has-text('Excel'), button:has-text('다운로드')", "verify": { "api_call": "GET /api/v1/production/performance/export",