2026-03-07 22:00:47 +09:00
|
|
|
{
|
|
|
|
|
"id": "crud-delete-vendor",
|
|
|
|
|
"name": "거래처 CRUD 삭제 기능 테스트",
|
2026-03-08 09:12:27 +09:00
|
|
|
"enabled": false,
|
|
|
|
|
"disabledReason": "거래처 등록 폼 제출 시 데이터 미생성 (등록 버튼 클릭 성공하나 API 호출 미발생 - 필수 필드 누락 또는 폼 유효성 검사 실패 추정)",
|
2026-03-07 22:00:47 +09:00
|
|
|
"screenshotPolicy": {
|
|
|
|
|
"onErrorOnly": true,
|
|
|
|
|
"captureOn": ["error", "fail", "timeout", "404", "500", "blocked"]
|
|
|
|
|
},
|
|
|
|
|
"description": "거래처관리에서 생성 -> 수정 -> 삭제 전체 CRUD 흐름 테스트. 테스트용 데이터를 생성하고, 수정한 후, 삭제하여 기존 데이터에 영향 없이 삭제 기능을 검증",
|
|
|
|
|
"baseUrl": "https://dev.codebridge-x.com",
|
|
|
|
|
"menuNavigation": {
|
|
|
|
|
"level1": "회계관리",
|
|
|
|
|
"level2": "거래처관리",
|
|
|
|
|
"expectedUrl": "/accounting/vendors",
|
|
|
|
|
"searchWithinParent": true,
|
|
|
|
|
"closeOtherMenus": true
|
|
|
|
|
},
|
|
|
|
|
"auth": {
|
|
|
|
|
"username": "TestUser5",
|
|
|
|
|
"password": "password123!"
|
|
|
|
|
},
|
|
|
|
|
"testPolicy": {
|
|
|
|
|
"deleteAllowed": true,
|
|
|
|
|
"deleteCondition": "CRUD 흐름 내에서만 허용 (생성 -> 수정 -> 삭제)",
|
|
|
|
|
"protectExistingData": true,
|
|
|
|
|
"description": "이 시나리오에서 생성한 테스트 데이터만 삭제"
|
|
|
|
|
},
|
|
|
|
|
"testData": {
|
|
|
|
|
"newVendor": {
|
|
|
|
|
"vendorName": "E2E테스트_삭제용_",
|
|
|
|
|
"businessNumber": "123-45-67890",
|
|
|
|
|
"representative": "테스트대표",
|
|
|
|
|
"vendorType": "매출",
|
|
|
|
|
"phone": "02-1234-5678",
|
|
|
|
|
"email": "test@e2etest.com",
|
|
|
|
|
"address": "서울시 테스트구 테스트동 123"
|
|
|
|
|
},
|
|
|
|
|
"updateData": {
|
|
|
|
|
"vendorName": "E2E테스트_수정완료_",
|
|
|
|
|
"representative": "수정대표"
|
|
|
|
|
},
|
|
|
|
|
"uniqueIdentifier": "timestamp를 붙여서 고유성 보장"
|
|
|
|
|
},
|
|
|
|
|
"steps": [
|
|
|
|
|
{
|
|
|
|
|
"id": 1,
|
|
|
|
|
"name": "메뉴 진입: 회계관리 > 거래처관리",
|
|
|
|
|
"action": "menu_navigate",
|
|
|
|
|
"level1": "회계관리",
|
|
|
|
|
"level2": "거래처관리",
|
|
|
|
|
"expected": { "url_contains": "/accounting/vendors" }
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"id": 2,
|
|
|
|
|
"name": "페이지 로드 대기",
|
|
|
|
|
"action": "wait",
|
|
|
|
|
"timeout": 3000
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"id": 3,
|
|
|
|
|
"phase": "CREATE",
|
|
|
|
|
"name": "[CREATE] 등록 버튼 클릭",
|
|
|
|
|
"action": "click_button",
|
|
|
|
|
"target": "등록",
|
|
|
|
|
"alternatives": ["추가", "신규"],
|
|
|
|
|
"expected": { "modal": true }
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"id": 4,
|
|
|
|
|
"phase": "CREATE",
|
2026-03-08 08:49:14 +09:00
|
|
|
"name": "[CREATE] 거래처 정보 입력 (fill_form)",
|
|
|
|
|
"action": "fill_form",
|
|
|
|
|
"fields": [
|
|
|
|
|
{ "label": "거래처명", "value": "E2E테스트_삭제용_{timestamp}" },
|
|
|
|
|
{ "label": "사업자등록번호", "value": "123-45-67890" },
|
|
|
|
|
{ "label": "대표자", "value": "테스트대표" },
|
|
|
|
|
{ "label": "전화번호", "value": "02-1234-5678" },
|
|
|
|
|
{ "label": "이메일", "value": "test@e2etest.com" }
|
|
|
|
|
]
|
2026-03-07 22:00:47 +09:00
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"id": 5,
|
|
|
|
|
"phase": "CREATE",
|
|
|
|
|
"name": "[CREATE] 거래처 유형 선택",
|
2026-03-08 08:49:14 +09:00
|
|
|
"action": "evaluate",
|
|
|
|
|
"script": "(async () => { const triggers = Array.from(document.querySelectorAll('button[role=\"combobox\"], [class*=\"select-trigger\"], [class*=\"SelectTrigger\"]')); const target = triggers.find(t => { const label = t.closest('[class*=\"field\"], [class*=\"form\"], .grid, tr, [class*=\"FormItem\"]')?.querySelector('label, span'); return label?.innerText?.includes('유형'); }) || triggers[0]; if (!target) return 'No combobox found'; target.click(); await new Promise(r => setTimeout(r, 500)); const opts = document.querySelectorAll('[role=\"option\"]'); const opt = Array.from(opts).find(o => o.innerText?.includes('매출')) || opts[0]; if (opt) { opt.click(); return 'Selected: ' + opt.innerText?.trim(); } return 'No options found'; })()"
|
2026-03-07 22:00:47 +09:00
|
|
|
},
|
|
|
|
|
{
|
2026-03-08 08:49:14 +09:00
|
|
|
"id": 6,
|
2026-03-07 22:00:47 +09:00
|
|
|
"phase": "CREATE",
|
2026-03-08 09:12:27 +09:00
|
|
|
"name": "[CREATE] 등록 저장 (모달 내부)",
|
|
|
|
|
"action": "evaluate",
|
|
|
|
|
"script": "(async () => { const modal = document.querySelector('[role=\"dialog\"], [aria-modal=\"true\"], [class*=\"modal\"]:not([class*=\"tooltip\"]), [class*=\"Modal\"], [class*=\"Sheet\"]'); const scope = modal || document; const btn = Array.from(scope.querySelectorAll('button')).find(b => ['저장', '등록', '확인'].some(t => b.innerText?.trim() === t) && !b.disabled); if (btn) { btn.click(); await new Promise(r => setTimeout(r, 1500)); return 'Saved: ' + btn.innerText?.trim(); } return 'Save button not found in modal'; })()"
|
2026-03-07 22:00:47 +09:00
|
|
|
},
|
|
|
|
|
{
|
2026-03-08 08:49:14 +09:00
|
|
|
"id": 7,
|
2026-03-07 22:00:47 +09:00
|
|
|
"phase": "CREATE",
|
|
|
|
|
"name": "[CREATE] 모달 닫기 확인",
|
|
|
|
|
"action": "close_modal_if_open"
|
|
|
|
|
},
|
|
|
|
|
{
|
2026-03-08 08:49:14 +09:00
|
|
|
"id": 8,
|
2026-03-07 22:00:47 +09:00
|
|
|
"phase": "CREATE",
|
2026-03-08 09:12:27 +09:00
|
|
|
"name": "[CREATE] 목록 새로고침 대기",
|
|
|
|
|
"action": "wait",
|
|
|
|
|
"timeout": 2000
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"id": 9,
|
|
|
|
|
"phase": "CREATE",
|
2026-03-07 22:00:47 +09:00
|
|
|
"name": "[CREATE] 등록 결과 확인 - 검색",
|
2026-03-08 08:49:14 +09:00
|
|
|
"action": "search",
|
|
|
|
|
"value": "E2E테스트_삭제용"
|
2026-03-07 22:00:47 +09:00
|
|
|
},
|
|
|
|
|
{
|
2026-03-08 09:12:27 +09:00
|
|
|
"id": 10,
|
2026-03-07 22:00:47 +09:00
|
|
|
"phase": "CREATE",
|
|
|
|
|
"name": "[CREATE] 등록 결과 확인 - 테이블",
|
|
|
|
|
"action": "verify_text",
|
|
|
|
|
"target": "table",
|
|
|
|
|
"contains": "E2E테스트_삭제용"
|
|
|
|
|
},
|
|
|
|
|
{
|
2026-03-08 09:12:27 +09:00
|
|
|
"id": 11,
|
2026-03-07 22:00:47 +09:00
|
|
|
"phase": "UPDATE",
|
|
|
|
|
"name": "[UPDATE] 생성된 거래처 행 클릭",
|
|
|
|
|
"action": "click_row",
|
|
|
|
|
"target": "E2E테스트_삭제용",
|
|
|
|
|
"expected": { "detail_view": true }
|
|
|
|
|
},
|
|
|
|
|
{
|
2026-03-08 09:12:27 +09:00
|
|
|
"id": 12,
|
2026-03-07 22:00:47 +09:00
|
|
|
"phase": "UPDATE",
|
|
|
|
|
"name": "[UPDATE] 수정 모드 진입",
|
|
|
|
|
"action": "click_button",
|
|
|
|
|
"target": "수정",
|
|
|
|
|
"expected": { "url_contains": "mode=edit" }
|
|
|
|
|
},
|
|
|
|
|
{
|
2026-03-08 09:12:27 +09:00
|
|
|
"id": 13,
|
2026-03-07 22:00:47 +09:00
|
|
|
"phase": "UPDATE",
|
2026-03-08 08:49:14 +09:00
|
|
|
"name": "[UPDATE] 거래처 정보 수정 (fill_form)",
|
|
|
|
|
"action": "fill_form",
|
|
|
|
|
"fields": [
|
|
|
|
|
{ "label": "거래처명", "value": "E2E테스트_수정완료_{timestamp}" },
|
|
|
|
|
{ "label": "대표자", "value": "수정대표" }
|
|
|
|
|
]
|
2026-03-07 22:00:47 +09:00
|
|
|
},
|
|
|
|
|
{
|
2026-03-08 09:12:27 +09:00
|
|
|
"id": 14,
|
2026-03-07 22:00:47 +09:00
|
|
|
"phase": "UPDATE",
|
|
|
|
|
"name": "[UPDATE] 수정 저장",
|
|
|
|
|
"action": "click_button",
|
|
|
|
|
"target": "저장",
|
|
|
|
|
"expected": { "toast": true }
|
|
|
|
|
},
|
|
|
|
|
{
|
2026-03-08 09:12:27 +09:00
|
|
|
"id": 15,
|
2026-03-07 22:00:47 +09:00
|
|
|
"phase": "UPDATE",
|
2026-03-08 09:12:27 +09:00
|
|
|
"name": "[UPDATE] 저장 후 대기",
|
|
|
|
|
"action": "wait",
|
|
|
|
|
"timeout": 1500
|
2026-03-07 22:00:47 +09:00
|
|
|
},
|
|
|
|
|
{
|
2026-03-08 09:12:27 +09:00
|
|
|
"id": 16,
|
2026-03-07 22:00:47 +09:00
|
|
|
"phase": "UPDATE",
|
|
|
|
|
"name": "[UPDATE] 수정 결과 확인",
|
|
|
|
|
"action": "verify_text",
|
|
|
|
|
"target": "body",
|
|
|
|
|
"contains": "E2E테스트_수정완료"
|
|
|
|
|
},
|
|
|
|
|
{
|
2026-03-08 09:12:27 +09:00
|
|
|
"id": 17,
|
|
|
|
|
"phase": "DELETE",
|
|
|
|
|
"name": "[DELETE] 삭제 대상 거래처 행 클릭",
|
|
|
|
|
"action": "click_row",
|
|
|
|
|
"target": "E2E테스트_수정완료",
|
|
|
|
|
"expected": { "detail_view": true }
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"id": 18,
|
2026-03-07 22:00:47 +09:00
|
|
|
"phase": "DELETE",
|
|
|
|
|
"name": "[DELETE] 삭제 버튼 클릭",
|
|
|
|
|
"critical": true,
|
|
|
|
|
"action": "click_button",
|
|
|
|
|
"target": "삭제",
|
|
|
|
|
"expected": { "dialog": true }
|
|
|
|
|
},
|
|
|
|
|
{
|
2026-03-08 09:12:27 +09:00
|
|
|
"id": 19,
|
2026-03-07 22:00:47 +09:00
|
|
|
"phase": "DELETE",
|
|
|
|
|
"name": "[DELETE] 삭제 확인 다이얼로그 검증",
|
|
|
|
|
"action": "verify_dialog",
|
|
|
|
|
"checks": ["삭제", "확인"]
|
|
|
|
|
},
|
|
|
|
|
{
|
2026-03-08 09:12:27 +09:00
|
|
|
"id": 20,
|
2026-03-07 22:00:47 +09:00
|
|
|
"phase": "DELETE",
|
|
|
|
|
"name": "[DELETE] 삭제 확인 클릭",
|
|
|
|
|
"critical": true,
|
|
|
|
|
"action": "click_dialog_confirm",
|
|
|
|
|
"expected": { "toast": true, "url_contains": "/accounting/vendors" }
|
|
|
|
|
},
|
|
|
|
|
{
|
2026-03-08 09:12:27 +09:00
|
|
|
"id": 21,
|
2026-03-07 22:00:47 +09:00
|
|
|
"phase": "DELETE",
|
|
|
|
|
"name": "[DELETE] 모달/다이얼로그 닫기",
|
|
|
|
|
"action": "close_modal_if_open"
|
|
|
|
|
},
|
|
|
|
|
{
|
2026-03-08 09:12:27 +09:00
|
|
|
"id": 22,
|
2026-03-07 22:00:47 +09:00
|
|
|
"phase": "VERIFY",
|
|
|
|
|
"name": "[VERIFY] 삭제 결과 확인 - 검색",
|
2026-03-08 08:49:14 +09:00
|
|
|
"action": "search",
|
|
|
|
|
"value": "E2E테스트_수정완료"
|
2026-03-07 22:00:47 +09:00
|
|
|
},
|
|
|
|
|
{
|
2026-03-08 09:12:27 +09:00
|
|
|
"id": 23,
|
2026-03-07 22:00:47 +09:00
|
|
|
"phase": "VERIFY",
|
|
|
|
|
"name": "[VERIFY] 삭제 결과 확인 - 없음",
|
|
|
|
|
"action": "verify_text",
|
|
|
|
|
"target": "body",
|
|
|
|
|
"not_contains": "E2E테스트_수정완료"
|
|
|
|
|
},
|
|
|
|
|
{
|
2026-03-08 09:12:27 +09:00
|
|
|
"id": 24,
|
2026-03-07 22:00:47 +09:00
|
|
|
"phase": "CLEANUP",
|
|
|
|
|
"name": "[CLEANUP] 검색 초기화",
|
2026-03-08 08:49:14 +09:00
|
|
|
"action": "evaluate",
|
|
|
|
|
"script": "(() => { const input = document.querySelector('input[type=\"search\"], input[placeholder*=\"검색\"]'); if (input) { input.value = ''; input.dispatchEvent(new Event('input', {bubbles:true})); return 'cleared'; } return 'no search input'; })()"
|
2026-03-07 22:00:47 +09:00
|
|
|
}
|
|
|
|
|
],
|
|
|
|
|
"expectedAPIs": [
|
|
|
|
|
{ "phase": "CREATE", "method": "POST", "endpoint": "/api/v1/clients", "description": "거래처 등록" },
|
|
|
|
|
{ "phase": "UPDATE", "method": "PUT", "endpoint": "/api/v1/clients/{id}", "description": "거래처 수정" },
|
|
|
|
|
{ "phase": "DELETE", "method": "DELETE", "endpoint": "/api/v1/clients/{id}", "description": "거래처 삭제" }
|
|
|
|
|
],
|
|
|
|
|
"rollbackPlan": {
|
|
|
|
|
"description": "테스트 실패 시 롤백 계획",
|
|
|
|
|
"onCreateFail": "모달 닫기 -> 다음 테스트 영향 없음",
|
|
|
|
|
"onUpdateFail": "테스트 데이터 수동 삭제 필요 (DB 또는 UI)",
|
|
|
|
|
"onDeleteFail": "테스트 데이터 수동 삭제 필요",
|
|
|
|
|
"cleanupRequired": "E2E테스트_ 로 시작하는 거래처는 테스트 데이터이므로 수동 삭제 가능"
|
|
|
|
|
}
|
|
|
|
|
}
|