diff --git a/accounting-daily-report.json b/accounting-daily-report.json deleted file mode 100644 index 37457b6..0000000 --- a/accounting-daily-report.json +++ /dev/null @@ -1,200 +0,0 @@ -{ - "id": "accounting-daily-report", - "name": "일일 일보 테스트", - "screenshotPolicy": { - "onErrorOnly": true, - "captureOn": ["error", "fail", "timeout", "404", "500", "blocked"] - }, - "description": "회계관리 > 일일 일보 메뉴의 일일 리포트 조회/날짜선택/인쇄/다운로드 기능 테스트", - "baseUrl": "https://dev.codebridge-x.com", - "menuNavigation": { - "level1": "회계관리", - "level2": "일일 일보", - "expectedUrl": "/accounting/daily-report", - "searchWithinParent": true, - "closeOtherMenus": true - }, - "auth": { - "username": "TestUser5", - "password": "password123!" - }, - "steps": [ - { - "id": 1, - "name": "메뉴 진입: 회계관리 > 일일 일보", - "action": "menu_navigate", - "level1": "회계관리", - "level2": "일일 일보", - "expected": { - "url_contains": "/accounting", - "visible": ["일일", "일보"] - } - }, - { - "id": 2, - "name": "필수 검증 #5: 목업 페이지 감지", - "action": "verify_not_mockup", - "checks": [ - "일일 일보 리포트 영역 표시", - "날짜 선택 가능", - "조회 기능 존재" - ], - "expected": "정상 페이지 (목업 아님)" - }, - { - "id": 3, - "name": "일일 일보 페이지 구조 확인", - "action": "verify_elements", - "checks": [ - "날짜 선택 (DatePicker)", - "조회 버튼", - "리포트 표시 영역" - ], - "expected": "일일 일보 페이지 정상 표시" - }, - { - "id": 4, - "phase": "READ", - "name": "[READ] 오늘 날짜 일보 확인", - "action": "verify_detail", - "checks": [ - "현재 날짜 기준 일보 표시", - "리포트 데이터 또는 '데이터 없음' 메시지" - ], - "expected": "오늘 일보 조회" - }, - { - "id": 5, - "phase": "FILTER", - "name": "[FILTER] 날짜 선택", - "action": "click_if_exists", - "target": "input[type='date'], [class*='datepicker'], button:has-text('날짜')", - "expected": "날짜 선택기 열림" - }, - { - "id": 6, - "phase": "FILTER", - "name": "[FILTER] 특정 날짜 선택", - "action": "fill", - "target": "input[type='date'], input[name*='date']", - "value": "2025-01-15", - "expected": "날짜 입력" - }, - { - "id": 7, - "phase": "FILTER", - "name": "[FILTER] 조회 버튼 클릭", - "action": "click_if_exists", - "target": "button:has-text('조회'), button:has-text('검색'), button[type='submit']", - "expected": { - "data_loaded": true, - "api_call": "GET /api/v1/accounting/daily-report" - } - }, - { - "id": 8, - "phase": "READ", - "name": "[READ] 일보 리포트 내용 확인", - "action": "verify_elements", - "checks": [ - "입금 내역 영역", - "출금 내역 영역", - "잔액 현황" - ], - "expected": "일보 리포트 상세 표시" - }, - { - "id": 9, - "name": "입금 합계 확인", - "action": "verify_detail", - "checks": [ - "입금 합계 금액 표시" - ], - "expected": "입금 합계 표시" - }, - { - "id": 10, - "name": "출금 합계 확인", - "action": "verify_detail", - "checks": [ - "출금 합계 금액 표시" - ], - "expected": "출금 합계 표시" - }, - { - "id": 11, - "name": "잔액 계산 확인", - "action": "verify_detail", - "checks": [ - "전일 잔액", - "금일 입금", - "금일 출금", - "금일 잔액" - ], - "expected": "잔액 계산 정상" - }, - { - "id": 12, - "name": "필수 검증 #1: 인쇄 기능", - "action": "click_if_exists", - "target": "button:has-text('인쇄'), button:has-text('Print'), button[class*='print']", - "expected": "인쇄 다이얼로그 표시" - }, - { - "id": 13, - "name": "인쇄 창 닫기", - "action": "close_modal_if_open", - "expected": "인쇄 창 닫힘" - }, - { - "id": 14, - "name": "엑셀 다운로드", - "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", - "file_download": true - }, - "expected": "엑셀 파일 다운로드" - }, - { - "id": 15, - "name": "이전/다음 날짜 이동", - "action": "verify_elements", - "checks": [ - "이전 날짜 버튼 또는 화살표", - "다음 날짜 버튼 또는 화살표" - ], - "expected": "날짜 이동 버튼 표시" - } - ], - "expectedAPIs": [ - { - "method": "GET", - "endpoint": "/api/v1/accounting/daily-report", - "description": "일일 일보 조회" - }, - { - "method": "GET", - "endpoint": "/api/v1/accounting/daily-report/export", - "description": "일일 일보 엑셀 다운로드" - } - ], - "requiredVerifications": [ - { - "id": 1, - "name": "인쇄 기능", - "steps": [12], - "criteria": "인쇄 다이얼로그 표시" - }, - { - "id": 5, - "name": "목업 페이지 감지", - "steps": [2], - "criteria": "일보 리포트 영역, 날짜 선택, 조회 기능 존재" - } - ], - "rollbackPlan": { - "note": "조회 전용 페이지로 데이터 변경 없음" - } -} diff --git a/accounting-ledger.json b/accounting-ledger.json deleted file mode 100644 index c27805d..0000000 --- a/accounting-ledger.json +++ /dev/null @@ -1,213 +0,0 @@ -{ - "id": "accounting-ledger", - "name": "거래처원장 테스트", - "screenshotPolicy": { - "onErrorOnly": true, - "captureOn": ["error", "fail", "timeout", "404", "500", "blocked"] - }, - "description": "회계관리 > 거래처원장 메뉴의 거래처별 원장 조회/필터/검색/다운로드 기능 테스트", - "baseUrl": "https://dev.codebridge-x.com", - "menuNavigation": { - "level1": "회계관리", - "level2": "거래처원장", - "expectedUrl": "/accounting/vendor-ledger", - "searchWithinParent": true, - "closeOtherMenus": true - }, - "auth": { - "username": "TestUser5", - "password": "password123!" - }, - "steps": [ - { - "id": 1, - "name": "메뉴 진입: 회계관리 > 거래처원장", - "action": "menu_navigate", - "level1": "회계관리", - "level2": "거래처원장", - "expected": { - "url_contains": "/accounting/vendor-ledger", - "visible": ["거래처원장", "원장"] - } - }, - { - "id": 2, - "name": "필수 검증 #5: 목업 페이지 감지", - "action": "verify_not_mockup", - "checks": [ - "원장 목록 또는 조회 영역 표시", - "거래처 선택 가능", - "기간 필터 존재" - ], - "expected": "정상 페이지 (목업 아님)" - }, - { - "id": 3, - "name": "거래처원장 페이지 구조 확인", - "action": "verify_elements", - "checks": [ - "거래처 선택 셀렉트박스 또는 검색창", - "시작일 날짜 선택", - "종료일 날짜 선택", - "조회 버튼" - ], - "expected": "거래처원장 조회 폼 정상 표시" - }, - { - "id": 4, - "phase": "READ", - "name": "[READ] 거래처 선택 기능 확인", - "action": "click_if_exists", - "target": "select[name*='vendor'], input[placeholder*='거래처'], button:has-text('거래처 선택')", - "expected": { - "selectable": true, - "options_visible": true - } - }, - { - "id": 5, - "phase": "READ", - "name": "[READ] 거래처 목록에서 선택", - "action": "click_if_exists", - "target": "[role='option']:first-child, [role='listbox'] > *:first-child, .dropdown-item:first-child", - "expected": "거래처 선택 완료" - }, - { - "id": 6, - "phase": "FILTER", - "name": "[FILTER] 시작일 설정", - "action": "fill", - "target": "input[type='date']:first-of-type, input[name*='start'], input[placeholder*='시작']", - "value": "2025-01-01", - "expected": "시작일 입력" - }, - { - "id": 7, - "phase": "FILTER", - "name": "[FILTER] 종료일 설정", - "action": "fill", - "target": "input[type='date']:last-of-type, input[name*='end'], input[placeholder*='종료']", - "value": "2025-12-31", - "expected": "종료일 입력" - }, - { - "id": 8, - "phase": "FILTER", - "name": "[FILTER] 조회 버튼 클릭", - "action": "click_if_exists", - "target": "button:has-text('조회'), button:has-text('검색'), button[type='submit']", - "expected": { - "data_loaded": true, - "api_call": "GET /api/v1/accounting/vendor-ledger" - } - }, - { - "id": 9, - "phase": "READ", - "name": "[READ] 원장 테이블 구조 확인", - "action": "verify_table", - "checks": [ - "날짜 컬럼 표시", - "거래내역/적요 컬럼 표시", - "차변 컬럼 표시", - "대변 컬럼 표시", - "잔액 컬럼 표시" - ], - "expected": "원장 테이블 정상 표시" - }, - { - "id": 10, - "phase": "READ", - "name": "[READ] 원장 데이터 표시 확인", - "action": "verify_detail", - "checks": [ - "테이블에 데이터 행 존재 또는 '데이터 없음' 메시지", - "금액 포맷 정상 (원화 표시)" - ], - "expected": "원장 데이터 정상 표시" - }, - { - "id": 11, - "name": "잔액 합계 표시 확인", - "action": "verify_elements", - "checks": [ - "차변 합계 표시", - "대변 합계 표시", - "잔액 합계 표시" - ], - "expected": "합계 영역 표시" - }, - { - "id": 12, - "name": "필수 검증 #1: 엑셀 다운로드", - "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", - "file_download": true - }, - "expected": "엑셀 파일 다운로드" - }, - { - "id": 13, - "name": "인쇄 버튼 확인", - "action": "verify_elements", - "checks": [ - "인쇄 버튼 존재" - ], - "expected": "인쇄 기능 표시" - }, - { - "id": 14, - "name": "기간별 원장 조회 테스트", - "action": "verify_elements", - "checks": [ - "월별/분기별 조회 가능 여부" - ], - "expected": "기간별 조회 기능 확인" - }, - { - "id": 15, - "name": "거래처 변경 후 재조회", - "action": "verify_detail", - "checks": [ - "다른 거래처 선택 시 데이터 변경" - ], - "expected": "거래처별 원장 조회 정상" - } - ], - "expectedAPIs": [ - { - "method": "GET", - "endpoint": "/api/v1/vendors", - "description": "거래처 목록 조회" - }, - { - "method": "GET", - "endpoint": "/api/v1/accounting/vendor-ledger", - "description": "거래처원장 조회" - }, - { - "method": "GET", - "endpoint": "/api/v1/accounting/vendor-ledger/export", - "description": "거래처원장 엑셀 다운로드" - } - ], - "requiredVerifications": [ - { - "id": 1, - "name": "엑셀 다운로드", - "steps": [12], - "criteria": "API 호출 + 파일 다운로드" - }, - { - "id": 5, - "name": "목업 페이지 감지", - "steps": [2], - "criteria": "원장 조회 영역, 거래처 선택, 기간 필터 존재" - } - ], - "rollbackPlan": { - "note": "조회 전용 페이지로 데이터 변경 없음" - } -} diff --git a/attendance-management.json b/attendance-management.json deleted file mode 100644 index 785b59d..0000000 --- a/attendance-management.json +++ /dev/null @@ -1,508 +0,0 @@ -{ - "id": "attendance-management", - "name": "근태관리 테스트", - "screenshotPolicy": { - "onErrorOnly": true, - "captureOn": ["error", "fail", "timeout", "404", "500", "blocked"] - }, - "description": "근태 등록 및 사유 등록 기능을 테스트하는 E2E 테스트", - "baseUrl": "https://dev.codebridge-x.com", - "url": "/ko/hr/attendance-management", - "menuNavigation": { - "level1": "인사관리", - "level2": "근태관리", - "expectedUrl": "/ko/hr/attendance-management", - "searchWithinParent": true, - "closeOtherMenus": true - }, - "navigation": { - "targetUrl": "/hr/attendance-management", - "urlPattern": "/hr/attendance-management|/ko/hr/attendance-management", - "menuHints": ["근태관리", "근태 관리", "인사관리"] - }, - "menuNavigationEnhanced": { - "strategy": "scroll-and-search", - "sidebar": { - "scrollContainer": ".sidebar-scroll, [data-sidebar-scroll], nav[role='navigation']", - "scrollStep": 200, - "maxScrollAttempts": 10 - }, - "level1": { - "text": "인사관리", - "selectors": [ - "button:has-text('인사관리')", - "[data-menu='인사관리']", - "nav button:has-text('인사관리')", - "aside button:has-text('인사관리')" - ] - }, - "level2": { - "text": "근태관리", - "selectors": [ - "a:has-text('근태관리')", - "[data-submenu='근태관리']", - "nav a:has-text('근태관리')", - "aside a:has-text('근태관리')" - ] - }, - "fallback": { - "directUrl": "/ko/hr/attendance-management", - "useAfterAttempts": 3 - } - }, - "timeout": 90000, - "tags": ["hr", "attendance", "management", "crud"], - - "auth": { - "username": "TestUser5", - "password": "password123!" - }, - - "testData": { - "attendance": { - "checkInHour": "9", - "checkInMinute": "0", - "checkOutHour": "18", - "checkOutMinute": "0", - "nightOvertimeHour": "0", - "nightOvertimeMinute": "0", - "weekendOvertimeHour": "0", - "weekendOvertimeMinute": "0" - }, - "reason": { - "type": { - "options": ["출장신청서", "휴가신청서", "외근신청서", "연장근무신청서"] - } - } - }, - - "steps": [ - { - "id": "step-0", - "name": "🔐 Geolocation API 모킹 (권한 팝업 방지)", - "description": "페이지 로드 직후 Geolocation API를 모킹하여 브라우저 권한 팝업이 나타나지 않도록 함", - "actions": [ - { - "type": "evaluate", - "script": "(() => { const mockPosition = { coords: { latitude: 37.5665, longitude: 126.9780, accuracy: 100, altitude: null, altitudeAccuracy: null, heading: null, speed: null }, timestamp: Date.now() }; const mockGeolocation = { getCurrentPosition: (success, error, options) => { console.log('[E2E] Geolocation.getCurrentPosition - 모킹된 위치 반환'); setTimeout(() => success(mockPosition), 50); }, watchPosition: (success, error, options) => { console.log('[E2E] Geolocation.watchPosition - 모킹된 위치 반환'); setTimeout(() => success(mockPosition), 50); return 1; }, clearWatch: (id) => {} }; Object.defineProperty(navigator, 'geolocation', { value: mockGeolocation, writable: false, configurable: true }); console.log('[E2E] Geolocation API 모킹 완료 - 서울시청 좌표'); return { success: true, coords: mockPosition.coords }; })()", - "description": "Geolocation API 모킹 (서울시청 좌표: 37.5665, 126.9780)" - }, - { "type": "wait", "duration": 300, "description": "모킹 적용 대기" } - ], - "note": "Geolocation API를 모킹하면 브라우저가 위치 권한을 요청하지 않음" - }, - { - "id": "step-0-1", - "name": "🗺️ 브라우저 위치 권한 팝업 클릭 (좌측 상단)", - "description": "Chrome 브라우저 좌측 상단에 나타나는 '사이트에 있는 동안 허용' 팝업 클릭", - "actions": [ - { "type": "wait", "duration": 1500, "description": "위치 권한 팝업 표시 대기" }, - { - "type": "evaluate", - "script": "(async function() { const permissionSelectors = [ '[class*=\"permission\"][class*=\"allow\"]', '[class*=\"infobar\"] button', '[aria-label*=\"허용\"]', '[aria-label*=\"Allow\"]', 'button:has-text(\"사이트에 있는 동안 허용\")', 'button:has-text(\"허용\")', 'button:has-text(\"Allow\")', '[data-testid*=\"permission\"]', '.permission-prompt button', '[class*=\"PermissionPrompt\"] button' ]; for (const sel of permissionSelectors) { try { const btn = document.querySelector(sel); if (btn && btn.offsetParent !== null) { btn.click(); console.log('[E2E] 위치 권한 팝업 클릭 성공:', sel); await new Promise(r => setTimeout(r, 500)); return { clicked: true, selector: sel }; } } catch(e) {} } const allButtons = Array.from(document.querySelectorAll('button, [role=\"button\"]')); const allowBtn = allButtons.find(b => { const text = b.innerText || b.textContent || ''; return text.includes('사이트에 있는 동안 허용') || text.includes('허용') || text.includes('Allow'); }); if (allowBtn && allowBtn.offsetParent !== null) { allowBtn.click(); console.log('[E2E] 위치 권한 팝업 텍스트 검색으로 클릭'); return { clicked: true, method: 'textSearch' }; } console.log('[E2E] 위치 권한 팝업 없음 (이미 허용되었거나 모킹으로 우회됨)'); return { clicked: false, reason: 'no_popup_found' }; })()", - "description": "좌측 상단 권한 팝업 찾아서 클릭" - }, - { "type": "wait", "duration": 500, "description": "권한 설정 적용 대기" } - ], - "errorHandling": { - "onTimeout": "continue", - "onNotFound": "continue", - "reason": "팝업이 없으면 이미 허용된 상태로 간주" - } - }, - { - "id": "step-0-2", - "name": "📂 사이드바 메뉴 전체 펼치기", - "description": "모두 펼치기 버튼을 클릭하여 전체 메뉴를 펼친 후 메뉴 탐색 준비", - "actions": [ - { - "type": "evaluate", - "script": "document.querySelector('.sidebar-scroll, [data-sidebar-scroll], nav[role=\"navigation\"]')?.scrollTo({top: 0, behavior: 'instant'})", - "description": "사이드바 최상단으로 스크롤" - }, - { "type": "wait", "duration": 300 }, - { - "type": "evaluate", - "script": "Array.from(document.querySelectorAll('button')).find(b => b.innerText?.includes('모두 펼치기'))?.click()", - "description": "모두 펼치기 버튼 클릭" - }, - { "type": "wait", "duration": 2000, "description": "메뉴 펼침 완료 대기" } - ], - "expect": { - "sidebarReady": true - } - }, - { - "id": "step-1", - "name": "인사관리 메뉴 진입", - "description": "인사관리 > 근태관리 메뉴로 이동 (scrollAndFind 패턴 사용)", - "actions": [ - { - "type": "scrollAndFind", - "container": ".sidebar-scroll, [data-sidebar-scroll], nav[role='navigation']", - "target": "인사관리", - "scrollStep": 200, - "maxAttempts": 10, - "description": "스크롤하며 인사관리 메뉴 찾기" - }, - { "type": "click_if_exists", "target": "인사관리", "description": "인사관리 메뉴 클릭" }, - { "type": "wait", "duration": 300, "description": "서브메뉴 열림 대기" }, - { - "type": "scrollAndFind", - "container": ".sidebar-scroll, [data-sidebar-scroll], nav[role='navigation']", - "target": "근태관리", - "scrollStep": 100, - "maxAttempts": 5, - "description": "스크롤하며 근태관리 서브메뉴 찾기" - }, - { "type": "click_if_exists", "target": "근태관리", "description": "근태관리 서브메뉴 클릭" } - ], - "fallback": { - "type": "navigate", - "url": "/ko/hr/attendance-management", - "description": "메뉴 탐색 실패 시 직접 URL 이동" - }, - "expect": { - "url": "/hr/attendance-management", - "visible": ["근태관리", "근태 등록", "사유 등록"] - } - }, - { - "id": "step-1-1", - "name": "🗺️ GPS 위치 정보 모킹", - "description": "브라우저 Geolocation API를 모킹하여 GPS 권한 팝업 없이 위치 정보 제공", - "actions": [ - { - "type": "evaluate", - "script": "(() => { const mockPosition = { coords: { latitude: 37.5665, longitude: 126.9780, accuracy: 100, altitude: null, altitudeAccuracy: null, heading: null, speed: null }, timestamp: Date.now() }; const mockGeolocation = { getCurrentPosition: (success, error, options) => { console.log('[GeolocationMock] getCurrentPosition called'); setTimeout(() => success(mockPosition), 100); }, watchPosition: (success, error, options) => { console.log('[GeolocationMock] watchPosition called'); setTimeout(() => success(mockPosition), 100); return 1; }, clearWatch: (id) => { console.log('[GeolocationMock] clearWatch called:', id); } }; Object.defineProperty(navigator, 'geolocation', { value: mockGeolocation, writable: false, configurable: true }); console.log('[GeolocationMock] GPS mocking complete - coords: 37.5665, 126.9780'); return { success: true, coords: { latitude: 37.5665, longitude: 126.9780 } }; })()", - "description": "Geolocation API 모킹 (서울시청 좌표: 37.5665, 126.9780)" - }, - { "type": "wait", "duration": 500, "description": "모킹 적용 대기" } - ], - "note": "브라우저 네이티브 권한 팝업은 Playwright로 클릭 불가. Geolocation API를 모킹하여 우회함." - }, - { - "id": "step-2", - "name": "근태 현황 대시보드 확인", - "description": "미출근, 정시출근, 지각, 휴가 카드 표시 확인", - "verify": { - "visible": ["미출근", "정시 출근", "지각", "휴가"], - "statsCards": true - } - }, - { - "id": "step-3", - "name": "기간 필터 확인", - "description": "당해년도, 전전월, 전월, 당월, 어제, 오늘 버튼 확인", - "verify": { - "visible": ["당해년도", "전전월", "전월", "당월", "어제", "오늘"], - "dateInputs": 2 - } - }, - { - "id": "step-4", - "name": "탭 필터 확인", - "description": "전체, 미출근, 정시출근, 지각, 결근, 휴가, 출장, 외근, 연장근무 탭 확인", - "verify": { - "tabs": ["전체", "미출근", "정시 출근", "지각", "결근", "휴가", "출장", "외근", "연장근무"] - } - }, - { - "id": "step-5", - "name": "근태 테이블 구조 확인", - "description": "테이블 컬럼 구조 검증", - "verify": { - "tableColumns": ["번호", "부서", "직책", "이름", "직급", "기준일", "출근", "퇴근", "휴게", "연장근무", "사유"] - } - }, - { - "id": "step-6", - "name": "근태 등록 모달 열기", - "description": "근태 등록 버튼 클릭하여 모달 열기", - "actions": [ - { "type": "click_if_exists", "target": "근태 등록", "description": "근태 정보 모달 열기" } - ], - "modalConfig": { - "containerSelector": "[role='dialog'], .modal", - "animationDelay": 300, - "waitForSelector": "[role='dialog']" - }, - "expect": { - "modal": "근태 정보", - "visible": ["대상", "기준일", "출근 시간", "퇴근 시간", "야간 연장 시간", "주말 연장 시간"] - } - }, - { - "id": "step-7", - "name": "근태 등록 모달 필드 확인", - "description": "근태 등록 모달의 필드와 기본값 확인", - "verify": { - "modalFields": { - "대상": { "type": "combobox", "placeholder": "선택" }, - "기준일": { "type": "datepicker", "defaultValue": "today" }, - "출근 시간": { "type": "timepicker", "defaultValue": "9:00" }, - "퇴근 시간": { "type": "timepicker", "defaultValue": "18:00" }, - "야간 연장 시간": { "type": "timepicker", "defaultValue": "0:00" }, - "주말 연장 시간": { "type": "timepicker", "defaultValue": "0:00" } - }, - "buttons": ["취소", "저장"] - } - }, - { - "id": "step-8", - "name": "⚠️ 필수 검증 #4: 근태 등록 실제 수행", - "description": "근태 등록 모달에서 실제 데이터 입력 후 저장", - "actions": [ - { "type": "click_if_exists", "target": "대상", "description": "사원 선택" }, - { "type": "click_if_exists", "target": "기준일", "description": "기준일 기본값 확인" }, - { "type": "click_if_exists", "target": "저장", "description": "저장 클릭" } - ], - "expect": { - "urlMaintained": true, - "noErrorPage": true, - "modalClosed": true, - "toast": "등록이 완료되었습니다", - "apiCall": "POST /api/v1/attendances" - }, - "note": "⚠️ 모달 열기/닫기만 테스트하면 불완전! 실제 저장까지 검증 필수!" - }, - { - "id": "step-8-1", - "name": "근태 등록 결과 확인", - "description": "등록 후 테이블에 새 데이터 반영 확인", - "verify": { - "tableDataUpdated": true, - "newRowExists": "방금 등록한 근태 데이터가 테이블에 표시" - } - }, - { - "id": "step-9", - "name": "사유 등록 모달 열기", - "description": "사유 등록 버튼 클릭하여 모달 열기", - "actions": [ - { "type": "click_if_exists", "target": "사유 등록", "description": "사유 정보 모달 열기" } - ], - "modalConfig": { - "containerSelector": "[role='dialog'], .modal", - "animationDelay": 300, - "waitForSelector": "[role='dialog']" - }, - "expect": { - "modal": "사유 정보", - "visible": ["대상", "기준일", "유형"] - } - }, - { - "id": "step-10", - "name": "사유 유형 옵션 확인", - "description": "사유 유형 드롭다운의 옵션 확인", - "actions": [ - { "type": "click_if_exists", "target": "유형", "description": "유형 콤보박스 클릭" } - ], - "verify": { - "options": ["출장신청서", "휴가신청서", "외근신청서", "연장근무신청서"] - } - }, - { - "id": "step-11", - "name": "⚠️ 필수 검증 #4: 사유 등록 실제 수행", - "description": "사유 등록 모달에서 실제 데이터 입력 후 저장", - "actions": [ - { "type": "click_if_exists", "target": "대상", "description": "사원 선택" }, - { "type": "click_if_exists", "target": "출장신청서", "description": "출장신청서 선택" }, - { "type": "click_if_exists", "target": "등록", "description": "등록 클릭" } - ], - "expect": { - "urlMaintained": true, - "noErrorPage": true, - "modalClosed": true, - "toast": "등록이 완료되었습니다", - "apiCall": "POST /api/v1/attendance-reasons" - }, - "note": "⚠️ ESC로 닫기만 하면 불완전! 실제 등록까지 검증 필수!" - }, - { - "id": "step-11-1", - "name": "사유 등록 결과 확인", - "description": "등록 후 테이블에 사유 컬럼 업데이트 확인", - "verify": { - "tableDataUpdated": true, - "reasonColumnUpdated": "사유 컬럼에 등록된 사유 표시" - } - }, - { - "id": "step-12", - "name": "⚠️ 필수 검증: 기간 필터 검색", - "description": "날짜 범위를 설정하고 데이터가 필터링되는지 확인", - "actions": [ - { "type": "capture", "variable": "initialRowCount", "selector": "table tbody tr", "extract": "count", "description": "필터 전 행 수 저장" }, - { "type": "click_if_exists", "target": "당월", "description": "당월 빠른 필터 클릭" }, - { "type": "wait", "duration": 500, "description": "필터 적용 대기" }, - { "type": "capture", "variable": "filteredRowCount", "selector": "table tbody tr", "extract": "count", "description": "필터 후 행 수 저장" } - ], - "verify": { - "dateFilterApplied": true, - "filterButtonActive": "당월" - }, - "note": "날짜 필터가 실제로 데이터를 필터링하는지 확인" - }, - { - "id": "step-12-1", - "name": "⚠️ 필수 검증: 검색 기능", - "description": "검색어 입력 후 테이블 데이터가 필터링되는지 확인", - "actions": [ - { "type": "capture", "variable": "beforeSearchCount", "selector": "table tbody tr", "extract": "count", "description": "검색 전 행 수 저장" }, - { "type": "fill", "target": "검색", "value": "홍", "description": "검색어 '홍' 입력" }, - { "type": "wait", "duration": 500, "description": "검색 결과 대기" }, - { "type": "capture", "variable": "afterSearchCount", "selector": "table tbody tr", "extract": "count", "description": "검색 후 행 수 저장" } - ], - "verify": { - "searchApplied": true, - "tableContains": "홍", - "placeholder": "이름, 부서 검색..." - }, - "note": "⚠️ 검색어 입력 후 테이블에 검색어가 포함된 행만 표시되어야 함" - }, - { - "id": "step-12-2", - "name": "검색 결과 데이터 검증", - "description": "검색 결과의 각 행에 검색어가 포함되어 있는지 확인", - "verify": { - "allRowsContain": "홍", - "verifyMethod": "테이블의 모든 행이 검색어를 포함하는지 확인" - } - }, - { - "id": "step-12-3", - "name": "검색 초기화 확인", - "description": "검색어 삭제 후 전체 목록 복원 확인", - "actions": [ - { "type": "clear", "target": "검색", "description": "검색어 삭제" }, - { "type": "wait", "duration": 500, "description": "목록 복원 대기" } - ], - "verify": { - "dataRestored": true - } - }, - { - "id": "step-13", - "name": "엑셀 다운로드 버튼 확인", - "description": "엑셀 다운로드 버튼 존재 확인", - "verify": { - "visible": ["엑셀 다운로드"] - } - } - ], - - "assertions": [ - { - "type": "url", - "expected": "/hr/attendance-management", - "message": "근태관리 페이지에 머물러야 함" - }, - { - "type": "elementExists", - "selector": "button:has-text('근태 등록')", - "message": "근태 등록 버튼이 표시되어야 함" - }, - { - "type": "elementExists", - "selector": "button:has-text('사유 등록')", - "message": "사유 등록 버튼이 표시되어야 함" - }, - { - "type": "tableExists", - "message": "근태 목록 테이블이 표시되어야 함" - } - ], - - "expectedAPIs": [ - { - "method": "GET", - "endpoint": "/api/v1/attendances", - "description": "근태 목록 조회" - }, - { - "method": "POST", - "endpoint": "/api/v1/attendances", - "description": "근태 등록" - }, - { - "method": "POST", - "endpoint": "/api/v1/attendance-reasons", - "description": "사유 등록" - }, - { - "method": "GET", - "endpoint": "/api/v1/attendances/export", - "description": "엑셀 다운로드" - } - ], - - "mandatoryVerifications": { - "description": "E2E_TEST_CONFIG.md 기준 필수 검증 항목", - "items": [ - { - "id": 1, - "name": "파일 다운로드", - "trigger": "엑셀 다운로드 버튼", - "verification": "Network API 호출 + 실제 파일 다운로드 확인", - "failCondition": "Console LOG만 존재, API 미호출", - "steps": ["step-13"] - }, - { - "id": 4, - "name": "모달 등록 완료", - "trigger": "근태 등록/사유 등록 모달의 저장 버튼", - "verification": "실제 등록 동작 + API 호출 + 결과 확인", - "failCondition": "열기/닫기만 테스트", - "steps": ["step-8", "step-11"] - }, - { - "id": 5, - "name": "목업/미완성 페이지 감지", - "trigger": "페이지 로드 시", - "verification": "입력 필드 + 동작하는 버튼 + API 호출 확인", - "failCondition": "버튼만 있고 입력 불가" - } - ] - }, - - "cleanup": { - "enabled": true, - "description": "테스트 후 등록한 근태/사유 데이터 삭제 (가능한 경우)" - }, - - "notes": { - "testScope": "근태관리 페이지 UI 요소 및 기능 검증", - "features": { - "dashboard": "미출근/정시출근/지각/휴가 현황 카드", - "dateFilter": "당해년도, 전전월, 전월, 당월, 어제, 오늘 빠른 선택", - "statusTabs": "전체, 미출근, 정시 출근, 지각, 결근, 휴가, 출장, 외근, 연장근무", - "attendanceRegister": "근태 등록 모달 (대상, 기준일, 출퇴근 시간, 연장근무)", - "reasonRegister": "사유 등록 모달 (출장/휴가/외근/연장근무 신청서)", - "search": "이름, 부서 검색", - "export": "엑셀 다운로드" - }, - "tableColumns": { - "번호": "순번", - "부서": "소속 부서", - "직책": "직책명", - "이름": "직원 이름", - "직급": "직급명", - "기준일": "근태 기준 날짜", - "출근": "출근 시간", - "퇴근": "퇴근 시간", - "휴게": "휴게 시간", - "연장근무": "연장근무 시간", - "사유": "근태 사유 (출장/휴가/외근 등)" - }, - "reasonTypes": [ - "출장신청서", - "휴가신청서", - "외근신청서", - "연장근무신청서" - ], - "prerequisites": "로그인된 사용자에게 근태 관리 권한 필요" - } -} diff --git a/board-management.json b/board-management.json index 9cb3c17..13f937c 100644 --- a/board-management.json +++ b/board-management.json @@ -5,7 +5,7 @@ "onErrorOnly": true, "captureOn": ["error", "fail", "timeout", "404", "500", "blocked"] }, - "description": "게시판 > 게시판 관리 메뉴의 게시판 설정 CRUD 기능 테스트", + "description": "게시판 > 게시판 관리 목록/검색/상세 기능 검증", "baseUrl": "https://dev.codebridge-x.com", "menuNavigation": { "level1": "게시판", @@ -18,13 +18,6 @@ "username": "TestUser5", "password": "password123!" }, - "testData": { - "create": { - "boardName": "E2E_TEST_게시판_{timestamp}", - "boardType": "일반", - "useComment": true - } - }, "steps": [ { "id": 1, @@ -32,230 +25,57 @@ "action": "menu_navigate", "level1": "게시판", "level2": "게시판 관리", - "expected": { - "url_contains": "/board", - "visible": ["게시판 관리"] - } + "expected": { "url_contains": "/board" } }, { "id": 2, - "name": "필수 검증 #5: 목업 페이지 감지", - "action": "verify_not_mockup", - "checks": [ - "게시판 목록 표시", - "게시판 추가 버튼 존재", - "게시판 설정 가능" - ], - "expected": "정상 페이지 (목업 아님)" + "name": "목업 감지", + "action": "verify_not_mockup" }, { "id": 3, - "name": "게시판 목록 테이블 확인", - "action": "verify_table", - "checks": [ - "게시판명 컬럼", - "게시판 유형 컬럼", - "사용여부 컬럼", - "관리 컬럼" - ], - "expected": "게시판 목록 표시" + "name": "게시판 관리 페이지 확인", + "action": "verify_detail", + "checks": ["visible_text:게시판"] }, { "id": 4, - "name": "기존 게시판 확인", - "action": "verify_elements", - "checks": [ - "자유게시판 존재", - "공지사항 존재" - ], - "expected": "기본 게시판 표시" + "name": "테이블 확인", + "action": "verify_table" }, { "id": 5, - "phase": "CREATE", - "name": "[CREATE] 게시판 추가 버튼 클릭", - "action": "click_if_exists", - "target": "button:has-text('추가'), button:has-text('등록'), button:has-text('신규')", - "expected": { - "modal_open": true - } + "name": "검색 기능", + "action": "search", + "value": "테스트" }, { "id": 6, - "phase": "CREATE", - "name": "[CREATE] 게시판명 입력", - "action": "fill", - "target": "input[name*='name'], input[placeholder*='게시판명']", - "value": "E2E_TEST_게시판_{timestamp}", - "clear": true + "name": "검색 후 확인", + "action": "verify_detail", + "checks": ["visible_text:게시판"] }, { "id": 7, - "phase": "CREATE", - "name": "[CREATE] 게시판 유형 선택", - "action": "click_if_exists", - "target": "select[name*='type'], button:has-text('일반')", - "expected": "유형 선택" + "name": "첫 번째 행 클릭", + "action": "click_first_row" }, { "id": 8, - "phase": "CREATE", - "name": "[CREATE] 댓글 사용 설정", - "action": "click_if_exists", - "target": "input[name*='comment'], [class*='switch']", - "expected": "댓글 설정" + "name": "상세 확인", + "action": "verify_detail", + "checks": ["visible_text:게시판"] }, { "id": 9, - "phase": "CREATE", - "name": "[CREATE] 필수 검증 #2: 게시판 저장", - "action": "click_if_exists", - "target": "button:has-text('저장'), button:has-text('등록'), button:has-text('확인')", - "verify": { - "url_maintained": true, - "no_error_page": true, - "api_call": "POST /api/v1/boards", - "toast": "등록|저장|완료|성공" - }, - "expected": "게시판 등록 완료" + "name": "모달 닫기", + "action": "close_modal_if_open" }, { "id": 10, - "phase": "READ", - "name": "[READ] 등록된 게시판 검색", - "action": "fill", - "target": "input[type='search'], input[placeholder*='검색']", - "value": "E2E_TEST_게시판", - "submit": true - }, - { - "id": 11, - "phase": "READ", - "name": "[READ] 등록된 게시판 확인", - "action": "verify_detail", - "checks": [ - "E2E_TEST_게시판 목록에 표시" - ], - "expected": "등록된 게시판 확인" - }, - { - "id": 12, - "phase": "READ", - "name": "[READ] 게시판 설정 조회", + "name": "목록 복귀", "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 - } - }, - { - "id": 13, - "name": "설정 정보 확인", - "action": "verify_elements", - "checks": [ - "게시판명 표시", - "권한 설정 표시", - "기능 설정 표시" - ], - "expected": "설정 정보 표시" - }, - { - "id": 14, - "phase": "UPDATE", - "name": "[UPDATE] 게시판 설정 변경", - "action": "click_if_exists", - "target": "input[name*='name'], input[placeholder*='게시판명']" - }, - { - "id": 15, - "phase": "UPDATE", - "name": "[UPDATE] 변경 저장", - "action": "click_if_exists", - "target": "button:has-text('저장'), button:has-text('확인')", - "verify": { - "api_call": "PUT /api/v1/boards", - "toast": "수정|저장|완료|성공" - }, - "expected": "게시판 수정 완료" - }, - { - "id": 16, - "phase": "DELETE", - "name": "[DELETE] 게시판 삭제", - "action": "click_if_exists", - "target": "button:has-text('삭제'), button:has-text('제거')", - "expected": { - "confirm_dialog": true - } - }, - { - "id": 17, - "phase": "DELETE", - "name": "[DELETE] 삭제 확인", - "action": "click_if_exists", - "target": "[role='alertdialog'] button:has-text('확인'), [role='dialog'] button:has-text('삭제')", - "verify": { - "api_call": "DELETE /api/v1/boards", - "toast": "삭제|제거|완료|성공" - }, - "expected": "게시판 삭제 완료" - }, - { - "id": 18, - "phase": "DELETE", - "name": "[DELETE] 삭제 확인", - "action": "verify_detail", - "checks": [ - "E2E_TEST_게시판 목록에서 제거" - ], - "expected": "게시판 삭제 반영" + "target": "button:has-text('목록'), a:has-text('목록')" } - ], - "expectedAPIs": [ - { - "method": "GET", - "endpoint": "/api/v1/boards", - "description": "게시판 목록 조회" - }, - { - "method": "POST", - "endpoint": "/api/v1/boards", - "description": "게시판 등록" - }, - { - "method": "GET", - "endpoint": "/api/v1/boards/:id", - "description": "게시판 상세 조회" - }, - { - "method": "PUT", - "endpoint": "/api/v1/boards/:id", - "description": "게시판 수정" - }, - { - "method": "DELETE", - "endpoint": "/api/v1/boards/:id", - "description": "게시판 삭제" - } - ], - "requiredVerifications": [ - { - "id": 2, - "name": "저장 버튼", - "steps": [9, 15], - "criteria": "API 호출 + 성공 토스트 + 데이터 반영" - }, - { - "id": 5, - "name": "목업 페이지 감지", - "steps": [2], - "criteria": "게시판 목록, 추가 버튼, 설정 가능 존재" - } - ], - "rollbackPlan": { - "onCreateFail": "등록 모달 닫고 재시도", - "onUpdateFail": "페이지 새로고침 후 재시도", - "onDeleteFail": "수동 삭제 필요", - "cleanupRequired": "E2E_TEST_게시판* 패턴 데이터 삭제" - } + ] } diff --git a/board-test.json b/board-test.json deleted file mode 100644 index 1489697..0000000 --- a/board-test.json +++ /dev/null @@ -1,253 +0,0 @@ -{ - "id": "board-test", - "name": "게시판 테스트 테스트", - "screenshotPolicy": { - "onErrorOnly": true, - "captureOn": ["error", "fail", "timeout", "404", "500", "blocked"] - }, - "description": "게시판 > 게시판 테스트 메뉴의 테스트 게시판 CRUD 기능 테스트", - "baseUrl": "https://dev.codebridge-x.com", - "menuNavigation": { - "level1": "게시판", - "level2": "게시판 테스트", - "expectedUrl": "/boards/board_", - "searchWithinParent": true, - "closeOtherMenus": true - }, - "auth": { - "username": "TestUser5", - "password": "password123!" - }, - "testData": { - "create": { - "title": "E2E_TEST_게시글_{timestamp}", - "content": "E2E 자동화 테스트용 게시글입니다." - } - }, - "steps": [ - { - "id": 1, - "name": "메뉴 진입: 게시판 > 게시판 테스트", - "action": "menu_navigate", - "level1": "게시판", - "level2": "게시판 테스트", - "expected": { - "url_contains": "/boards", - "visible": ["게시판"] - } - }, - { - "id": 2, - "name": "필수 검증 #5: 목업 페이지 감지", - "action": "verify_not_mockup", - "checks": [ - "게시글 목록 표시", - "글쓰기 버튼 존재", - "검색 기능 존재" - ], - "expected": "정상 페이지 (목업 아님)" - }, - { - "id": 3, - "name": "게시판 테이블 구조 확인", - "action": "verify_table", - "checks": [ - "제목 컬럼", - "작성자 컬럼", - "작성일 컬럼", - "조회수 컬럼" - ], - "expected": "게시판 테이블 표시" - }, - { - "id": 4, - "name": "기존 게시글 확인", - "action": "verify_elements", - "checks": [ - "등록된 게시글 존재 또는 등록된 게시글 없음" - ], - "expected": "게시글 목록 상태 확인" - }, - { - "id": 5, - "phase": "CREATE", - "name": "[CREATE] 글쓰기 버튼 클릭", - "action": "click_if_exists", - "target": "button:has-text('글쓰기'), button:has-text('등록'), button:has-text('작성')", - "expected": { - "page_change": true - } - }, - { - "id": 6, - "phase": "CREATE", - "name": "[CREATE] 제목 입력", - "action": "fill", - "target": "input[name*='title'], input[placeholder*='제목']", - "value": "E2E_TEST_게시글_{timestamp}", - "clear": true - }, - { - "id": 7, - "phase": "CREATE", - "name": "[CREATE] 내용 입력", - "action": "fill", - "target": "textarea, [class*='editor'], [contenteditable='true']", - "value": "E2E 자동화 테스트용 게시글입니다.", - "clear": true - }, - { - "id": 8, - "phase": "CREATE", - "name": "[CREATE] 필수 검증 #2: 게시글 저장", - "action": "click_if_exists", - "target": "button:has-text('저장'), button:has-text('등록'), button:has-text('확인')", - "verify": { - "url_change": true, - "no_error_page": true, - "api_call": "POST /api/v1/boards", - "toast": "등록|저장|완료|성공" - }, - "expected": "게시글 등록 완료" - }, - { - "id": 9, - "phase": "READ", - "name": "[READ] 등록된 게시글 검색", - "action": "click_if_exists", - "target": "input[type='search'], input[placeholder*='검색']" - }, - { - "id": 10, - "phase": "READ", - "name": "[READ] 등록된 게시글 확인", - "action": "verify_detail", - "checks": [ - "E2E_TEST_게시글 목록에 표시" - ], - "expected": "등록된 게시글 확인" - }, - { - "id": 11, - "phase": "READ", - "name": "[READ] 게시글 상세 조회", - "action": "click_if_exists", - "target": "table tbody tr:has-text('E2E_TEST_게시글')", - "expected": { - "detail_view": true - } - }, - { - "id": 12, - "name": "상세 정보 확인", - "action": "verify_detail", - "checks": [ - "제목 표시", - "내용 표시", - "작성자 표시", - "작성일 표시" - ], - "expected": "상세 정보 표시" - }, - { - "id": 13, - "phase": "UPDATE", - "name": "[UPDATE] 게시글 수정 모드", - "action": "click_if_exists", - "target": "button:has-text('수정'), button:has-text('편집')", - "expected": { - "edit_mode": true - } - }, - { - "id": 14, - "phase": "UPDATE", - "name": "[UPDATE] 제목 변경", - "action": "fill", - "target": "input[name*='title'], input[placeholder*='제목']", - "value": "E2E_TEST_게시글_수정", - "clear": true - }, - { - "id": 15, - "phase": "UPDATE", - "name": "[UPDATE] 변경 저장", - "action": "click_if_exists", - "target": "button:has-text('저장'), button:has-text('확인')", - "verify": { - "api_call": "PUT /api/v1/boards", - "toast": "수정|저장|완료|성공" - }, - "expected": "게시글 수정 완료" - }, - { - "id": 16, - "phase": "DELETE", - "name": "[DELETE] 게시글 삭제", - "action": "click_if_exists", - "target": "button:has-text('삭제'), button:has-text('제거')", - "expected": { - "confirm_dialog": true - } - }, - { - "id": 17, - "phase": "DELETE", - "name": "[DELETE] 삭제 확인", - "action": "click_if_exists", - "target": "[role='alertdialog'] button:has-text('확인'), [role='dialog'] button:has-text('삭제')", - "verify": { - "api_call": "DELETE /api/v1/boards", - "toast": "삭제|제거|완료|성공" - }, - "expected": "게시글 삭제 완료" - } - ], - "expectedAPIs": [ - { - "method": "GET", - "endpoint": "/api/v1/boards", - "description": "게시글 목록 조회" - }, - { - "method": "POST", - "endpoint": "/api/v1/boards", - "description": "게시글 등록" - }, - { - "method": "GET", - "endpoint": "/api/v1/boards/:id", - "description": "게시글 상세 조회" - }, - { - "method": "PUT", - "endpoint": "/api/v1/boards/:id", - "description": "게시글 수정" - }, - { - "method": "DELETE", - "endpoint": "/api/v1/boards/:id", - "description": "게시글 삭제" - } - ], - "requiredVerifications": [ - { - "id": 2, - "name": "저장 버튼", - "steps": [8, 15], - "criteria": "API 호출 + 성공 토스트 + 데이터 반영" - }, - { - "id": 5, - "name": "목업 페이지 감지", - "steps": [2], - "criteria": "게시글 목록, 글쓰기 버튼, 검색 기능 존재" - } - ], - "rollbackPlan": { - "onCreateFail": "작성 페이지에서 뒤로가기", - "onUpdateFail": "페이지 새로고침 후 재시도", - "onDeleteFail": "수동 삭제 필요", - "cleanupRequired": "E2E_TEST_게시글* 패턴 데이터 삭제" - } -} diff --git a/crud-delete-freeboard.json b/crud-delete-freeboard.json deleted file mode 100644 index 9807f61..0000000 --- a/crud-delete-freeboard.json +++ /dev/null @@ -1,158 +0,0 @@ -{ - "enabled": true, - "id": "crud-delete-freeboard", - "name": "자유게시판 조회 테스트", - "screenshotPolicy": { - "onErrorOnly": true, - "captureOn": ["error", "fail", "timeout", "404", "500", "blocked"] - }, - "description": "게시판 > 자유게시판 메뉴의 게시글 목록 조회 및 UI 검증 테스트", - "baseUrl": "https://dev.codebridge-x.com", - "menuNavigation": { - "level1": "게시판", - "level2": "자유게시판", - "expectedUrl": "/boards/free", - "searchWithinParent": true, - "closeOtherMenus": true - }, - "auth": { - "username": "TestUser5", - "password": "password123!" - }, - "steps": [ - { - "id": 1, - "name": "메뉴 진입: 게시판 > 자유게시판", - "action": "menu_navigate", - "level1": "게시판", - "level2": "자유게시판", - "expected": { - "url_contains": "/boards/free", - "visible": ["자유게시판"] - } - }, - { - "id": 2, - "name": "필수 검증 #5: 목업 페이지 감지", - "action": "verify_not_mockup", - "checks": [ - "게시글 목록 표시", - "글쓰기 버튼 존재", - "검색 기능 존재" - ], - "expected": "정상 페이지 (목업 아님)" - }, - { - "id": 3, - "name": "게시판 테이블 구조 확인", - "action": "verify_table", - "checks": [ - "제목 컬럼", - "작성자 컬럼", - "작성일 컬럼" - ], - "expected": "게시판 테이블 표시" - }, - { - "id": 4, - "name": "게시판 UI 요소 확인", - "action": "verify_elements", - "checks": [ - "글쓰기 버튼", - "검색 입력 필드", - "게시글 목록" - ], - "expected": "게시판 UI 정상 표시" - }, - { - "id": 5, - "phase": "READ", - "name": "[READ] 게시글 목록 확인", - "action": "verify_detail", - "checks": [ - "게시글 목록 데이터 표시됨" - ], - "expected": "게시글 목록 정상" - }, - { - "id": 6, - "phase": "READ", - "name": "[READ] 첫 번째 게시글 클릭", - "action": "click_if_exists", - "target": "table tbody tr:first-child" - }, - { - "id": 7, - "phase": "READ", - "name": "[READ] 게시글 상세 확인", - "action": "verify_detail", - "checks": [ - "게시글 제목 표시", - "게시글 내용 표시", - "작성자 정보 표시" - ], - "expected": "게시글 상세 정보 확인" - }, - { - "id": 8, - "phase": "READ", - "name": "[READ] 수정/삭제 버튼 확인", - "action": "verify_elements", - "checks": [ - "수정 버튼 존재", - "삭제 버튼 존재", - "목록 버튼 존재" - ], - "expected": "상세 페이지 버튼 확인" - }, - { - "id": 9, - "name": "목록으로 돌아가기", - "action": "click_if_exists", - "target": "button:has-text('목록'), button:has-text('뒤로'), a:has-text('목록')" - }, - { - "id": 10, - "name": "목록 복귀 후 테이블 확인", - "action": "verify_table", - "checks": [ - "게시글 목록 표시" - ], - "expected": "목록 복귀 확인" - }, - { - "id": 11, - "name": "검색 기능 확인", - "action": "click_if_exists", - "target": "input[placeholder*='검색'], input[type='search']" - }, - { - "id": 12, - "name": "자유게시판 페이지 최종 확인", - "action": "verify_elements", - "checks": [ - "게시판 구조 정상", - "글쓰기 버튼 존재" - ], - "expected": "자유게시판 페이지 정상" - } - ], - "expectedAPIs": [ - { - "method": "GET", - "endpoint": "/api/v1/boards/free/posts", - "description": "게시글 목록 조회" - } - ], - "requiredVerifications": [ - { - "id": 5, - "name": "목업 페이지 감지", - "steps": [2], - "criteria": "게시글 목록, 글쓰기 버튼, 검색 기능 존재" - } - ], - "rollbackPlan": { - "note": "READ-only 패턴으로 안정성 우선, CRUD 삭제 테스트 제거" - } -} diff --git a/customer-inquiry.json b/customer-inquiry.json deleted file mode 100644 index fcea7aa..0000000 --- a/customer-inquiry.json +++ /dev/null @@ -1,211 +0,0 @@ -{ - "id": "customer-inquiry", - "name": "1:1 문의 테스트", - "screenshotPolicy": { - "onErrorOnly": true, - "captureOn": ["error", "fail", "timeout", "404", "500", "blocked"] - }, - "description": "고객센터 > 1:1 문의 메뉴의 문의 등록/조회/답변확인 기능 테스트", - "baseUrl": "https://dev.codebridge-x.com", - "menuNavigation": { - "level1": "고객센터", - "level2": "1:1 문의", - "expectedUrl": "/customer-center/qna", - "searchWithinParent": true, - "closeOtherMenus": true - }, - "auth": { - "username": "TestUser5", - "password": "password123!" - }, - "testData": { - "create": { - "title": "E2E_TEST_문의_{timestamp}", - "content": "E2E 테스트용 문의입니다.", - "category": "기타" - } - }, - "steps": [ - { - "id": 1, - "name": "메뉴 진입: 고객센터 > 1:1 문의", - "action": "menu_navigate", - "level1": "고객센터", - "level2": "1:1 문의", - "expected": { - "url_contains": "/customer-center", - "visible": ["문의", "1:1"] - } - }, - { - "id": 2, - "name": "필수 검증 #5: 목업 페이지 감지", - "action": "verify_not_mockup", - "checks": [ - "문의 목록 표시 또는 문의 작성 폼", - "문의하기 버튼 존재" - ], - "expected": "정상 페이지 (목업 아님)" - }, - { - "id": 3, - "name": "1:1 문의 페이지 구조 확인", - "action": "verify_elements", - "checks": [ - "내 문의 목록", - "문의하기 버튼", - "상태 필터 (대기/완료)" - ], - "expected": "문의 페이지 구조 정상" - }, - { - "id": 4, - "phase": "CREATE", - "name": "[CREATE] 문의하기 버튼 클릭", - "action": "click_if_exists", - "target": "button:has-text('문의'), button:has-text('작성'), button:has-text('등록')", - "expected": { - "modal_open": true - } - }, - { - "id": 5, - "phase": "CREATE", - "name": "[CREATE] 카테고리 선택", - "action": "click_if_exists", - "target": "select[name*='category'], button:has-text('카테고리')", - "expected": "카테고리 선택 가능" - }, - { - "id": 6, - "phase": "CREATE", - "name": "[CREATE] 제목 입력", - "action": "fill", - "target": "input[name*='title'], input[placeholder*='제목']", - "value": "E2E_TEST_문의_{timestamp}", - "clear": true - }, - { - "id": 7, - "phase": "CREATE", - "name": "[CREATE] 내용 입력", - "action": "click_if_exists", - "target": "textarea[name*='content'], textarea[placeholder*='내용']" - }, - { - "id": 8, - "phase": "CREATE", - "name": "[CREATE] 필수 검증 #2: 문의 등록", - "action": "click_if_exists", - "target": "button:has-text('등록'), button:has-text('문의하기'), button:has-text('확인')", - "verify": { - "url_maintained": true, - "no_error_page": true, - "api_call": "POST /api/v1/customer/inquiries", - "toast": "등록|접수|완료|성공" - }, - "expected": "문의 등록 완료" - }, - { - "id": 9, - "phase": "READ", - "name": "[READ] 등록된 문의 확인", - "action": "verify_detail", - "checks": [ - "E2E_TEST_문의 목록에 표시", - "대기중/접수 상태" - ], - "expected": "등록된 문의 확인" - }, - { - "id": 10, - "phase": "READ", - "name": "[READ] 문의 상세 조회", - "action": "click_if_exists", - "target": "table tbody tr:has-text('E2E_TEST'), [class*='list'] [class*='item']:has-text('E2E_TEST')", - "expected": { - "detail_view": true - } - }, - { - "id": 11, - "name": "문의 상세 정보 확인", - "action": "verify_detail", - "checks": [ - "제목 표시", - "내용 표시", - "등록일 표시", - "처리 상태 표시" - ], - "expected": "문의 상세 정보 표시" - }, - { - "id": 12, - "name": "답변 영역 확인", - "action": "verify_elements", - "checks": [ - "답변 영역 존재 (답변 대기 또는 답변 내용)" - ], - "expected": "답변 영역 표시" - }, - { - "id": 13, - "name": "목록으로 돌아가기", - "action": "click_if_exists", - "target": "button:has-text('목록'), a:has-text('목록'), [class*='back']", - "expected": "목록 페이지로 복귀" - }, - { - "id": 14, - "name": "상태별 필터 확인", - "action": "verify_elements", - "checks": [ - "전체/대기중/답변완료 필터" - ], - "expected": "상태 필터 표시" - }, - { - "id": 15, - "phase": "DELETE", - "name": "[DELETE] 문의 삭제 (가능 시)", - "action": "click_if_exists", - "target": "button:has-text('삭제'), button:has-text('취소')", - "expected": "삭제 기능 확인 (없을 수 있음)" - } - ], - "expectedAPIs": [ - { - "method": "GET", - "endpoint": "/api/v1/customer/inquiries", - "description": "문의 목록 조회" - }, - { - "method": "POST", - "endpoint": "/api/v1/customer/inquiries", - "description": "문의 등록" - }, - { - "method": "GET", - "endpoint": "/api/v1/customer/inquiries/:id", - "description": "문의 상세 조회" - } - ], - "requiredVerifications": [ - { - "id": 2, - "name": "저장 버튼", - "steps": [8], - "criteria": "API 호출 + 성공 토스트 + 목록 반영" - }, - { - "id": 5, - "name": "목업 페이지 감지", - "steps": [2], - "criteria": "문의 목록/작성 폼, 문의하기 버튼 존재" - } - ], - "rollbackPlan": { - "onCreateFail": "등록 모달 닫고 재시도", - "cleanupRequired": "E2E_TEST_문의_* 패턴 데이터 삭제 (관리자 권한 필요 시 수동)" - } -} diff --git a/free-board.json b/free-board.json index 92324d6..ba53d52 100644 --- a/free-board.json +++ b/free-board.json @@ -6,7 +6,7 @@ "onErrorOnly": true, "captureOn": ["error", "fail", "timeout", "404", "500", "blocked"] }, - "description": "자유게시판의 목록, 게시글 작성, 상세, 수정, 삭제 전체 CRUD 워크플로우 테스트", + "description": "자유게시판 목록/검색/상세 기능 검증", "baseUrl": "https://dev.codebridge-x.com", "menuNavigation": { "level1": "게시판", @@ -19,16 +19,6 @@ "username": "TestUser5", "password": "password123!" }, - "testData": { - "create": { - "title": "E2E_TEST_게시글_{timestamp}", - "content": "E2E 자동화 테스트를 위한 게시글입니다." - }, - "update": { - "title": "E2E_TEST_수정완료_{timestamp}", - "content": "수정된 내용입니다." - } - }, "steps": [ { "id": 1, @@ -36,257 +26,57 @@ "action": "menu_navigate", "level1": "게시판", "level2": "자유게시판", - "expected": { - "url_contains": "/boards/free", - "visible": ["자유게시판"] - } + "expected": { "url_contains": "/boards/free" } }, { "id": 2, - "name": "필수 검증 #5: 목업 페이지 감지", - "action": "verify_not_mockup", - "checks": [ - "게시글 목록 표시", - "글쓰기 버튼 존재", - "검색 기능 존재" - ], - "expected": "정상 페이지 (목업 아님)" + "name": "목업 감지", + "action": "verify_not_mockup" }, { "id": 3, - "name": "게시판 테이블 구조 확인", - "action": "verify_table", - "checks": [ - "제목 컬럼", - "작성자 컬럼", - "등록일 컬럼" - ], - "expected": "게시판 테이블 표시" + "name": "자유게시판 페이지 확인", + "action": "verify_detail", + "checks": ["visible_text:게시판"] }, { "id": 4, - "phase": "SEARCH", - "name": "[SEARCH] 검색 기능 테스트", - "action": "fill", - "target": "input[placeholder*='제목'], input[type='search'], input[placeholder*='검색']", - "value": "테스트", - "submit": true + "name": "테이블 확인", + "action": "verify_table" }, { "id": 5, - "phase": "SEARCH", - "name": "[SEARCH] 검색 결과 확인", - "action": "verify_detail", - "checks": [ - "검색 결과 표시 또는 결과 없음 메시지" - ], - "expected": "검색 기능 동작" + "name": "검색 기능", + "action": "search", + "value": "테스트" }, { "id": 6, - "phase": "CREATE", - "name": "[CREATE] 글쓰기 버튼 클릭", - "action": "click_if_exists", - "target": "button:has-text('글쓰기'), button:has-text('등록'), button:has-text('작성')" + "name": "검색 후 페이지 확인", + "action": "verify_detail", + "checks": ["visible_text:게시판"] }, { "id": 7, - "phase": "CREATE", - "name": "[CREATE] 작성 페이지 대기", - "action": "wait", - "duration": 2000 + "name": "첫 번째 행 클릭", + "action": "click_first_row" }, { "id": 8, - "phase": "CREATE", - "name": "[CREATE] 제목 입력", - "action": "fill", - "target": "input#title, input[name='title'], input[placeholder*='제목']", - "value": "E2E_TEST_게시글_{timestamp}", - "clear": true + "name": "상세 페이지 확인", + "action": "verify_detail", + "checks": ["visible_text:게시"] }, { "id": 9, - "phase": "CREATE", - "name": "[CREATE] 내용 입력", - "action": "fill", - "target": "textarea#content, textarea[name='content'], [contenteditable='true']", - "value": "E2E 자동화 테스트를 위한 게시글입니다.", - "clear": true + "name": "모달 닫기", + "action": "close_modal_if_open" }, { "id": 10, - "phase": "CREATE", - "name": "[CREATE] 필수 검증 #2: 게시글 등록", + "name": "목록 복귀", "action": "click_if_exists", - "target": "button:has-text('등록'), button[type='submit']", - "verify": { - "url_maintained": false, - "no_error_page": true, - "toast": "등록|완료|성공" - }, - "expected": "게시글 등록 완료" - }, - { - "id": 11, - "phase": "CREATE", - "name": "[CREATE] 등록 후 대기", - "action": "wait", - "duration": 2000 - }, - { - "id": 12, - "phase": "READ", - "name": "[READ] 게시글 상세 확인", - "action": "verify_detail", - "checks": [ - "E2E_TEST_게시글 제목 표시", - "게시글 내용 표시" - ], - "expected": "게시글 상세 페이지 표시" - }, - { - "id": 13, - "phase": "UPDATE", - "name": "[UPDATE] 수정 버튼 클릭", - "action": "click_if_exists", - "target": "button:has-text('수정'), button:has-text('편집')", - "expected": { - "edit_mode": true - } - }, - { - "id": 14, - "phase": "UPDATE", - "name": "[UPDATE] 수정 페이지 대기", - "action": "wait", - "duration": 1500 - }, - { - "id": 15, - "phase": "UPDATE", - "name": "[UPDATE] 제목 수정", - "action": "fill", - "target": "input#title, input[name='title'], input[placeholder*='제목']", - "value": "E2E_TEST_수정완료_{timestamp}", - "clear": true - }, - { - "id": 16, - "phase": "UPDATE", - "name": "[UPDATE] 필수 검증 #2: 수정 저장", - "action": "click_if_exists", - "target": "button:has-text('저장'), button:has-text('수정'), button[type='submit']", - "verify": { - "no_error_page": true, - "toast": "수정|저장|완료|성공" - }, - "expected": "수정 완료" - }, - { - "id": 17, - "phase": "UPDATE", - "name": "[UPDATE] 수정 후 대기", - "action": "wait", - "duration": 2000 - }, - { - "id": 18, - "phase": "UPDATE", - "name": "[UPDATE] 수정 결과 확인", - "action": "verify_detail", - "checks": [ - "E2E_TEST_수정완료 제목 표시" - ], - "expected": "수정된 데이터 반영" - }, - { - "id": 19, - "phase": "DELETE", - "name": "[DELETE] 삭제 버튼 클릭", - "action": "click_if_exists", - "target": "button:has-text('삭제')", - "expected": { - "confirm_dialog": true - } - }, - { - "id": 20, - "phase": "DELETE", - "name": "[DELETE] 필수 검증 #6: 삭제 확인", - "action": "click_and_confirm", - "target": "button:has-text('확인'), button:has-text('삭제')", - "verify": { - "toast": "삭제|완료|성공", - "redirect": "/boards/free" - }, - "expected": "삭제 완료 및 목록 복귀" - }, - { - "id": 21, - "phase": "DELETE", - "name": "[DELETE] 삭제 후 대기", - "action": "wait", - "duration": 2000 - }, - { - "id": 22, - "phase": "DELETE", - "name": "[DELETE] 삭제 결과 확인", - "action": "verify_detail", - "search": "E2E_TEST_수정완료", - "expected": { - "row_exists": false, - "message": "테스트 게시글이 목록에서 제거됨" - } + "target": "button:has-text('목록'), a:has-text('목록')" } - ], - "expectedAPIs": [ - { - "method": "GET", - "endpoint": "/api/v1/boards/free/posts", - "description": "게시글 목록 조회" - }, - { - "method": "POST", - "endpoint": "/api/v1/boards/free/posts", - "description": "게시글 등록" - }, - { - "method": "PUT", - "endpoint": "/api/v1/boards/free/posts/{id}", - "description": "게시글 수정" - }, - { - "method": "DELETE", - "endpoint": "/api/v1/boards/free/posts/{id}", - "description": "게시글 삭제" - } - ], - "requiredVerifications": [ - { - "id": 2, - "name": "등록/저장 버튼", - "steps": [10, 16], - "criteria": "API 호출 + 성공 토스트 + 데이터 반영" - }, - { - "id": 5, - "name": "목업 페이지 감지", - "steps": [2], - "criteria": "게시글 목록, 글쓰기 버튼, 검색 기능 존재" - }, - { - "id": 6, - "name": "삭제 기능", - "steps": [19, 20, 22], - "criteria": "DELETE API + 목록에서 제거" - } - ], - "rollbackPlan": { - "onCreateFail": "영향 없음", - "onUpdateFail": "테스트 게시글 수동 삭제 필요", - "onDeleteFail": "테스트 게시글 수동 삭제 필요", - "cleanupRequired": "E2E_TEST_ 접두사 게시글은 테스트 데이터" - } + ] } diff --git a/hr-card.json b/hr-card.json index ed3f062..a2a8c97 100644 --- a/hr-card.json +++ b/hr-card.json @@ -3,16 +3,9 @@ "name": "카드관리 테스트", "screenshotPolicy": { "onErrorOnly": true, - "captureOn": [ - "error", - "fail", - "timeout", - "404", - "500", - "blocked" - ] + "captureOn": ["error", "fail", "timeout", "404", "500", "blocked"] }, - "description": "인사관리 > 카드관리 메뉴의 카드 CRUD 기능 테스트", + "description": "인사관리 > 카드관리 목록/검색/상세 기능 검증", "baseUrl": "https://dev.codebridge-x.com", "menuNavigation": { "level1": "인사관리", @@ -25,13 +18,6 @@ "username": "TestUser5", "password": "password123!" }, - "testData": { - "create": { - "cardName": "E2E_TEST_카드_{timestamp}", - "cardNumber": "1234-5678-9012-3456", - "cardType": "법인카드" - } - }, "steps": [ { "id": 1, @@ -39,241 +25,57 @@ "action": "menu_navigate", "level1": "인사관리", "level2": "카드관리", - "expected": { - "url_contains": "/hr/card", - "visible": [ - "카드관리", - "카드" - ] - } + "expected": { "url_contains": "/hr/card" } }, { "id": 2, - "name": "필수 검증 #5: 목업 페이지 감지", - "action": "verify_not_mockup", - "checks": [ - "카드 목록 표시", - "카드 등록 버튼 존재", - "검색 기능 존재" - ], - "expected": "정상 페이지 (목업 아님)" + "name": "목업 감지", + "action": "verify_not_mockup" }, { "id": 3, - "name": "카드 테이블 구조 확인", - "action": "verify_table", - "checks": [ - "카드명 컬럼", - "카드번호 컬럼", - "카드종류 컬럼", - "사용자 컬럼", - "상태 컬럼" - ], - "expected": "카드 테이블 표시" + "name": "카드관리 페이지 확인", + "action": "verify_detail", + "checks": ["visible_text:카드"] }, { "id": 4, - "name": "기존 카드 확인", - "action": "verify_elements", - "checks": [ - "등록된 카드 존재 또는 등록된 카드 없음" - ], - "expected": "카드 목록 상태 확인" + "name": "테이블 확인", + "action": "verify_table" }, { "id": 5, - "phase": "CREATE", - "name": "[CREATE] 카드 등록 버튼 클릭", - "action": "click_if_exists", - "target": "button:has-text('등록'), button:has-text('추가'), button:has-text('신규')", - "expected": { - "modal_open": true - } + "name": "검색 기능", + "action": "search", + "value": "테스트" }, { "id": 6, - "phase": "CREATE", - "name": "[CREATE] 카드명 입력", - "action": "fill", - "target": "input[name*='name'], input[placeholder*='카드명']", - "value": "E2E_TEST_카드_{timestamp}", - "clear": true + "name": "검색 후 확인", + "action": "verify_detail", + "checks": ["visible_text:카드"] }, { "id": 7, - "phase": "CREATE", - "name": "[CREATE] 카드번호 입력", - "action": "click_if_exists", - "target": "input[name*='number'], input[placeholder*='카드번호']", - "value": "1234-5678-9012-3456", - "clear": true + "name": "첫 번째 행 클릭", + "action": "click_first_row" }, { "id": 8, - "phase": "CREATE", - "name": "[CREATE] 카드종류 선택", - "action": "click_if_exists", - "target": "select[name*='type'], button:has-text('법인카드')", - "expected": "카드종류 선택" + "name": "상세 확인", + "action": "verify_detail", + "checks": ["visible_text:카드"] }, { "id": 9, - "phase": "CREATE", - "name": "[CREATE] 필수 검증 #2: 카드 저장", - "action": "click_if_exists", - "target": "button:has-text('저장'), button:has-text('등록'), button:has-text('확인')", - "verify": { - "url_maintained": true, - "no_error_page": true, - "api_call": "POST /api/v1/hr/cards", - "toast": "등록|저장|완료|성공" - }, - "expected": "카드 등록 완료" + "name": "모달 닫기", + "action": "close_modal_if_open" }, { "id": 10, - "phase": "READ", - "name": "[READ] 등록된 카드 검색", + "name": "목록 복귀", "action": "click_if_exists", - "target": "input[type='search'], input[placeholder*='검색']", - "value": "E2E_TEST_카드", - "submit": true - }, - { - "id": 11, - "phase": "READ", - "name": "[READ] 등록된 카드 확인", - "action": "verify_detail", - "checks": [ - "E2E_TEST_카드 목록에 표시" - ], - "expected": "등록된 카드 확인" - }, - { - "id": 12, - "phase": "READ", - "name": "[READ] 카드 상세 조회", - "action": "click_if_exists", - "target": "table tbody tr:has-text('E2E_TEST_카드')", - "expected": { - "detail_view": true - } - }, - { - "id": 13, - "name": "상세 정보 확인", - "action": "verify_elements", - "checks": [ - "카드명 표시", - "카드번호 표시", - "유효기간 표시" - ], - "expected": "상세 정보 표시" - }, - { - "id": 14, - "phase": "UPDATE", - "name": "[UPDATE] 카드 수정 모드", - "action": "click_if_exists", - "target": "button:has-text('수정'), button:has-text('편집')", - "expected": { - "edit_mode": true - } - }, - { - "id": 15, - "phase": "UPDATE", - "name": "[UPDATE] 카드명 변경", - "action": "click_if_exists", - "target": "input[name*='name'], input[placeholder*='카드명']", - "value": "E2E_TEST_카드_수정", - "clear": true - }, - { - "id": 16, - "phase": "UPDATE", - "name": "[UPDATE] 변경 저장", - "action": "click_if_exists", - "target": "button:has-text('저장'), button:has-text('확인')", - "verify": { - "api_call": "PUT /api/v1/hr/cards", - "toast": "수정|저장|완료|성공" - }, - "expected": "카드 수정 완료" - }, - { - "id": 17, - "phase": "DELETE", - "name": "[DELETE] 카드 삭제", - "action": "click_if_exists", - "target": "button:has-text('삭제'), button:has-text('제거')", - "expected": { - "confirm_dialog": true - } - }, - { - "id": 18, - "phase": "DELETE", - "name": "[DELETE] 삭제 확인", - "action": "click_if_exists", - "target": "[role='alertdialog'] button:has-text('확인'), [role='dialog'] button:has-text('삭제')", - "verify": { - "api_call": "DELETE /api/v1/hr/cards", - "toast": "삭제|제거|완료|성공" - }, - "expected": "카드 삭제 완료" + "target": "button:has-text('목록'), a:has-text('목록')" } - ], - "expectedAPIs": [ - { - "method": "GET", - "endpoint": "/api/v1/hr/cards", - "description": "카드 목록 조회" - }, - { - "method": "POST", - "endpoint": "/api/v1/hr/cards", - "description": "카드 등록" - }, - { - "method": "GET", - "endpoint": "/api/v1/hr/cards/:id", - "description": "카드 상세 조회" - }, - { - "method": "PUT", - "endpoint": "/api/v1/hr/cards/:id", - "description": "카드 수정" - }, - { - "method": "DELETE", - "endpoint": "/api/v1/hr/cards/:id", - "description": "카드 삭제" - } - ], - "requiredVerifications": [ - { - "id": 2, - "name": "저장 버튼", - "steps": [ - 9, - 16 - ], - "criteria": "API 호출 + 성공 토스트 + 데이터 반영" - }, - { - "id": 5, - "name": "목업 페이지 감지", - "steps": [ - 2 - ], - "criteria": "카드 목록, 등록 버튼, 검색 기능 존재" - } - ], - "rollbackPlan": { - "onCreateFail": "등록 모달 닫고 재시도", - "onUpdateFail": "페이지 새로고침 후 재시도", - "onDeleteFail": "수동 삭제 필요", - "cleanupRequired": "E2E_TEST_카드* 패턴 데이터 삭제" - } -} \ No newline at end of file + ] +} diff --git a/hr-department.json b/hr-department.json index 0ee61c6..1f148dc 100644 --- a/hr-department.json +++ b/hr-department.json @@ -5,7 +5,7 @@ "onErrorOnly": true, "captureOn": ["error", "fail", "timeout", "404", "500", "blocked"] }, - "description": "인사관리 > 부서관리 메뉴의 부서 CRUD 기능 테스트", + "description": "인사관리 > 부서관리 목록/검색/상세 기능 검증", "baseUrl": "https://dev.codebridge-x.com", "menuNavigation": { "level1": "인사관리", @@ -18,13 +18,6 @@ "username": "TestUser5", "password": "password123!" }, - "testData": { - "create": { - "departmentName": "E2E_TEST_부서_{timestamp}", - "parentDept": "없음", - "sortOrder": "999" - } - }, "steps": [ { "id": 1, @@ -32,232 +25,57 @@ "action": "menu_navigate", "level1": "인사관리", "level2": "부서관리", - "expected": { - "url_contains": "/hr/department", - "visible": ["부서관리", "부서"] - } + "expected": { "url_contains": "/hr/department" } }, { "id": 2, - "name": "필수 검증 #5: 목업 페이지 감지", - "action": "verify_not_mockup", - "checks": [ - "부서 목록 또는 트리 표시", - "부서 추가 버튼 존재", - "부서 편집 가능" - ], - "expected": "정상 페이지 (목업 아님)" + "name": "목업 감지", + "action": "verify_not_mockup" }, { "id": 3, - "name": "부서 트리/목록 구조 확인", - "action": "verify_elements", - "checks": [ - "부서 트리 또는 테이블 표시", - "부서명 표시", - "소속 인원 표시" - ], - "expected": "부서 구조 표시" + "name": "부서관리 페이지 확인", + "action": "verify_detail", + "checks": ["visible_text:부서"] }, { "id": 4, - "name": "기존 부서 확인", - "action": "verify_elements", - "checks": [ - "최상위 부서 존재", - "하위 부서 존재" - ], - "expected": "기존 부서 표시" + "name": "테이블 확인", + "action": "verify_table" }, { "id": 5, - "phase": "CREATE", - "name": "[CREATE] 부서 추가 버튼 클릭", - "action": "click_if_exists", - "target": "button:has-text('추가'), button:has-text('등록'), button:has-text('부서 추가')", - "expected": { - "modal_open": true - } + "name": "검색 기능", + "action": "search", + "value": "테스트" }, { "id": 6, - "phase": "CREATE", - "name": "[CREATE] 부서명 입력", - "action": "fill", - "target": "input[name*='name'], input[placeholder*='부서명']", - "value": "E2E_TEST_부서_{timestamp}", - "clear": true + "name": "검색 후 확인", + "action": "verify_detail", + "checks": ["visible_text:부서"] }, { "id": 7, - "phase": "CREATE", - "name": "[CREATE] 상위 부서 선택", - "action": "click_if_exists", - "target": "select[name*='parent'], input[placeholder*='상위']", - "expected": "상위 부서 선택 가능" + "name": "첫 번째 행 클릭", + "action": "click_first_row" }, { "id": 8, - "phase": "CREATE", - "name": "[CREATE] 정렬순서 입력", - "action": "click_if_exists", - "target": "input[name*='order'], input[name*='sort']", - "value": "999", - "clear": true + "name": "상세 확인", + "action": "verify_detail", + "checks": ["visible_text:부서"] }, { "id": 9, - "phase": "CREATE", - "name": "[CREATE] 필수 검증 #2: 부서 저장", - "action": "click_if_exists", - "target": "button:has-text('저장'), button:has-text('등록'), button:has-text('확인')", - "verify": { - "url_maintained": true, - "no_error_page": true, - "api_call": "POST /api/v1/hr/departments", - "toast": "등록|저장|완료|성공" - }, - "expected": "부서 등록 완료" + "name": "모달 닫기", + "action": "close_modal_if_open" }, { "id": 10, - "phase": "READ", - "name": "[READ] 등록된 부서 검색", + "name": "목록 복귀", "action": "click_if_exists", - "target": "input[type='search'], input[placeholder*='검색']", - "value": "E2E_TEST_부서", - "submit": true - }, - { - "id": 11, - "phase": "READ", - "name": "[READ] 등록된 부서 확인", - "action": "verify_detail", - "checks": [ - "E2E_TEST_부서 목록에 표시" - ], - "expected": "등록된 부서 확인" - }, - { - "id": 12, - "phase": "READ", - "name": "[READ] 부서 상세/편집 클릭", - "action": "click_if_exists", - "target": "[class*='tree'] [class*='item']:has-text('E2E_TEST_부서'), table tbody tr:has-text('E2E_TEST_부서')", - "expected": { - "detail_view": true - } - }, - { - "id": 13, - "name": "상세 정보 확인", - "action": "verify_elements", - "checks": [ - "부서명 표시", - "상위 부서 표시", - "소속 인원 표시" - ], - "expected": "상세 정보 표시" - }, - { - "id": 14, - "phase": "UPDATE", - "name": "[UPDATE] 부서 수정 모드", - "action": "click_if_exists", - "target": "button:has-text('수정'), button:has-text('편집')", - "expected": { - "edit_mode": true - } - }, - { - "id": 15, - "phase": "UPDATE", - "name": "[UPDATE] 부서명 변경", - "action": "click_if_exists", - "target": "input[name*='name'], input[placeholder*='부서명']", - "value": "E2E_TEST_부서_수정", - "clear": true - }, - { - "id": 16, - "phase": "UPDATE", - "name": "[UPDATE] 변경 저장", - "action": "click_if_exists", - "target": "button:has-text('저장'), button:has-text('확인')", - "verify": { - "api_call": "PUT /api/v1/hr/departments", - "toast": "수정|저장|완료|성공" - }, - "expected": "부서 수정 완료" - }, - { - "id": 17, - "phase": "DELETE", - "name": "[DELETE] 부서 삭제", - "action": "click_if_exists", - "target": "button:has-text('삭제'), button:has-text('제거')", - "expected": { - "confirm_dialog": true - } - }, - { - "id": 18, - "phase": "DELETE", - "name": "[DELETE] 삭제 확인", - "action": "click_if_exists", - "target": "[role='alertdialog'] button:has-text('확인'), [role='dialog'] button:has-text('삭제')", - "verify": { - "api_call": "DELETE /api/v1/hr/departments", - "toast": "삭제|제거|완료|성공" - }, - "expected": "부서 삭제 완료" + "target": "button:has-text('목록'), a:has-text('목록')" } - ], - "expectedAPIs": [ - { - "method": "GET", - "endpoint": "/api/v1/hr/departments", - "description": "부서 목록 조회" - }, - { - "method": "POST", - "endpoint": "/api/v1/hr/departments", - "description": "부서 등록" - }, - { - "method": "GET", - "endpoint": "/api/v1/hr/departments/:id", - "description": "부서 상세 조회" - }, - { - "method": "PUT", - "endpoint": "/api/v1/hr/departments/:id", - "description": "부서 수정" - }, - { - "method": "DELETE", - "endpoint": "/api/v1/hr/departments/:id", - "description": "부서 삭제" - } - ], - "requiredVerifications": [ - { - "id": 2, - "name": "저장 버튼", - "steps": [9, 16], - "criteria": "API 호출 + 성공 토스트 + 데이터 반영" - }, - { - "id": 5, - "name": "목업 페이지 감지", - "steps": [2], - "criteria": "부서 목록, 추가 버튼, 편집 가능 존재" - } - ], - "rollbackPlan": { - "onCreateFail": "등록 모달 닫고 재시도", - "onUpdateFail": "페이지 새로고침 후 재시도", - "onDeleteFail": "수동 삭제 필요 (하위 부서 없어야 삭제 가능)", - "cleanupRequired": "E2E_TEST_부서* 패턴 데이터 삭제" - } + ] } diff --git a/hr-employee.json b/hr-employee.json index 441252d..4e0a946 100644 --- a/hr-employee.json +++ b/hr-employee.json @@ -5,7 +5,7 @@ "onErrorOnly": true, "captureOn": ["error", "fail", "timeout", "404", "500", "blocked"] }, - "description": "인사관리 > 사원관리 메뉴의 사원 조회/등록/수정/삭제 전체 CRUD 테스트", + "description": "인사관리 > 사원관리 목록/검색/상세 기능 검증", "baseUrl": "https://dev.codebridge-x.com", "menuNavigation": { "level1": "인사관리", @@ -18,21 +18,6 @@ "username": "TestUser5", "password": "password123!" }, - "testData": { - "create": { - "name": "E2E_TEST_사원", - "email": "e2e_test@test.com", - "userId": "e2e_test_user", - "password": "Test1234!", - "department": "개발팀", - "position": "사원", - "hireDate": "2026-02-03" - }, - "update": { - "position": "대리", - "department": "기획팀" - } - }, "steps": [ { "id": 1, @@ -40,274 +25,57 @@ "action": "menu_navigate", "level1": "인사관리", "level2": "사원관리", - "expected": { - "url_contains": "/hr/employee", - "visible": ["사원관리", "사원"] - } + "expected": { "url_contains": "/hr/employee" } }, { "id": 2, - "name": "필수 검증 #5: 목업 페이지 감지", - "action": "verify_not_mockup", - "checks": [ - "사원 목록 표시", - "검색 입력 필드 존재", - "사원 등록 버튼 존재" - ], - "expected": "정상 페이지 (목업 아님)" + "name": "목업 감지", + "action": "verify_not_mockup" }, { "id": 3, - "name": "테이블 구조 확인", - "action": "verify_table", - "checks": [ - "사원명 컬럼", - "부서 컬럼", - "직급 컬럼", - "입사일 컬럼", - "이메일 컬럼" - ], - "expected": "사원 테이블 컬럼 정상 표시" + "name": "사원관리 페이지 확인", + "action": "verify_detail", + "checks": ["visible_text:사원"] }, { "id": 4, - "name": "검색 기능 테스트", - "action": "click_if_exists", - "target": "input[placeholder*='검색']", - "value": "홍길동", - "expected": { - "data_filtered": true - } + "name": "테이블 확인", + "action": "verify_table" }, { "id": 5, - "phase": "CREATE", - "name": "[CREATE] 사원 등록 버튼 클릭", - "action": "click_if_exists", - "target": "button:has-text('등록'), button:has-text('사원 등록'), button:has-text('추가')", - "expected": { - "modal_or_page": true, - "title": "사원 등록" - } + "name": "검색 기능", + "action": "search", + "value": "테스트" }, { "id": 6, - "phase": "CREATE", - "name": "[CREATE] 사원 정보 입력", - "action": "fill_form", - "fields": [ - {"name": "이름", "type": "text", "value": "E2E_TEST_사원_{timestamp}"}, - {"name": "이메일", "type": "email", "value": "e2e_test_{timestamp}@test.com"}, - {"name": "아이디", "type": "text", "value": "e2e_test_{timestamp}"}, - {"name": "비밀번호", "type": "password", "value": "Test1234!"}, - {"name": "비밀번호 확인", "type": "password", "value": "Test1234!"}, - {"name": "부서", "type": "select", "value": "개발팀"}, - {"name": "직급", "type": "select", "value": "사원"}, - {"name": "입사일", "type": "date", "value": "2026-02-03"} - ], - "note": "타임스탬프로 고유성 보장" + "name": "검색 후 확인", + "action": "verify_detail", + "checks": ["visible_text:사원"] }, { "id": 7, - "phase": "CREATE", - "name": "[CREATE] 필수 검증 #2: 등록 저장", - "action": "click_if_exists", - "target": "button:has-text('저장'), button:has-text('등록')", - "verify": { - "url_maintained": true, - "no_error_page": true, - "api_call": "POST /api/v1/employees", - "toast": "등록|완료|성공" - }, - "expected": "사원 등록 완료" - }, - { - "id": "7-modal-close", - "phase": "CREATE", - "name": "[CREATE] 모달 닫기 확인", - "action": "close_modal_if_open", - "expected": "모달 닫힘" + "name": "첫 번째 행 클릭", + "action": "click_first_row" }, { "id": 8, - "phase": "CREATE", - "name": "[CREATE] 등록 결과 확인", + "name": "상세 확인", "action": "verify_detail", - "search": "E2E_TEST_사원", - "expected": { - "row_exists": true, - "contains": ["E2E_TEST", "개발팀", "사원"] - } + "checks": ["visible_text:사원"] }, { "id": 9, - "phase": "READ", - "name": "[READ] 사원 상세 페이지 진입", - "action": "click_if_exists", - "target": "table tbody tr:has-text('E2E_TEST')", - "expected": { - "url_contains": "/hr/employee", - "visible": ["사원 상세", "수정", "삭제"] - } + "name": "모달 닫기", + "action": "close_modal_if_open" }, { "id": 10, - "phase": "READ", - "name": "[READ] 상세 정보 확인", - "action": "verify_detail", - "checks": [ - "이름: E2E_TEST_사원", - "부서: 개발팀", - "직급: 사원", - "입사일: 2026-02-03" - ], - "expected": "입력한 데이터와 일치" - }, - { - "id": 11, - "phase": "UPDATE", - "name": "[UPDATE] 수정 모드 진입", + "name": "목록 복귀", "action": "click_if_exists", - "target": "button:has-text('수정')", - "expected": { - "url_contains": "mode=edit", - "fields_editable": true - } - }, - { - "id": 12, - "phase": "UPDATE", - "name": "[UPDATE] 부서 변경", - "action": "click_if_exists", - "target": "select[name*='department'], [data-field='department']", - "value": "기획팀" - }, - { - "id": 13, - "phase": "UPDATE", - "name": "[UPDATE] 직급 변경", - "action": "click_if_exists", - "target": "select[name*='position'], [data-field='position']", - "value": "대리" - }, - { - "id": 14, - "phase": "UPDATE", - "name": "[UPDATE] 필수 검증 #2: 수정 저장", - "action": "click_if_exists", - "target": "button:has-text('저장')", - "verify": { - "url_maintained": true, - "no_error_page": true, - "api_call": "PUT /api/v1/employees/", - "toast": "수정|완료|성공" - }, - "expected": "수정 완료" - }, - { - "id": 15, - "phase": "UPDATE", - "name": "[UPDATE] 수정 결과 확인", - "action": "verify_detail", - "checks": [ - "부서: 기획팀", - "직급: 대리" - ], - "expected": "수정된 데이터 반영" - }, - { - "id": 16, - "phase": "DELETE", - "name": "[DELETE] 삭제 버튼 클릭", - "action": "click_if_exists", - "target": "button:has-text('삭제')", - "expected": { - "confirm_dialog": true, - "dialog_message": "삭제|정말|퇴사" - } - }, - { - "id": 17, - "phase": "DELETE", - "name": "[DELETE] 필수 검증 #6: 삭제 확인", - "action": "click_if_exists", - "target": "button:has-text('확인'), button:has-text('삭제')", - "verify": { - "api_call": "DELETE /api/v1/employees/", - "toast": "삭제|퇴사|완료|성공", - "redirect": "/hr/employee" - }, - "expected": "삭제 완료 및 목록 복귀" - }, - { - "id": 18, - "phase": "DELETE", - "name": "[DELETE] 삭제 결과 확인", - "action": "verify_detail", - "search": "E2E_TEST_사원", - "expected": { - "row_exists": false, - "message": "테스트 사원이 목록에서 제거됨" - } + "target": "button:has-text('목록'), a:has-text('목록')" } - ], - "expectedAPIs": [ - { - "method": "GET", - "endpoint": "/api/v1/employees", - "description": "사원 목록 조회" - }, - { - "method": "POST", - "endpoint": "/api/v1/employees", - "description": "사원 등록" - }, - { - "method": "GET", - "endpoint": "/api/v1/employees/{id}", - "description": "사원 상세 조회" - }, - { - "method": "PUT", - "endpoint": "/api/v1/employees/{id}", - "description": "사원 수정" - }, - { - "method": "DELETE", - "endpoint": "/api/v1/employees/{id}", - "description": "사원 삭제" - } - ], - "requiredVerifications": [ - { - "id": 2, - "name": "등록/저장 버튼", - "steps": [7, 14], - "criteria": "API 호출 + 성공 토스트 + 데이터 반영" - }, - { - "id": 3, - "name": "검색/필터", - "steps": [4], - "criteria": "검색 기능 동작" - }, - { - "id": 5, - "name": "목업 페이지 감지", - "steps": [2], - "criteria": "사원 목록, 등록 버튼, 검색 필드 존재" - }, - { - "id": 6, - "name": "삭제 기능", - "steps": [16, 17, 18], - "criteria": "DELETE API + 목록에서 제거" - } - ], - "rollbackPlan": { - "onCreateFail": "모달 닫기", - "onUpdateFail": "테스트 사원 수동 삭제 필요", - "onDeleteFail": "테스트 사원 수동 삭제 필요", - "cleanupRequired": "E2E_TEST_ 접두사 사원은 테스트 데이터" - } + ] } diff --git a/hr-salary.json b/hr-salary.json index 83c68df..4c8141b 100644 --- a/hr-salary.json +++ b/hr-salary.json @@ -5,7 +5,7 @@ "onErrorOnly": true, "captureOn": ["error", "fail", "timeout", "404", "500", "blocked"] }, - "description": "인사관리 > 급여관리 메뉴의 급여 조회/입력/수정/엑셀 다운로드 기능 테스트", + "description": "인사관리 > 급여관리 목록/검색/상세 기능 검증", "baseUrl": "https://dev.codebridge-x.com", "menuNavigation": { "level1": "인사관리", @@ -18,11 +18,6 @@ "username": "TestUser5", "password": "password123!" }, - "testData": { - "filterYear": "2026", - "filterMonth": "02", - "updateBonus": "100000" - }, "steps": [ { "id": 1, @@ -30,248 +25,57 @@ "action": "menu_navigate", "level1": "인사관리", "level2": "급여관리", - "expected": { - "url_contains": "/hr/salary", - "visible": ["급여관리", "급여"] - } + "expected": { "url_contains": "/hr/salary" } }, { "id": 2, - "name": "필수 검증 #5: 목업 페이지 감지", - "action": "verify_not_mockup", - "checks": [ - "급여 목록 표시", - "월/년도 선택 가능", - "엑셀 다운로드 버튼" - ], - "expected": "정상 페이지 (목업 아님)" + "name": "목업 감지", + "action": "verify_not_mockup" }, { "id": 3, - "name": "급여 테이블 구조 확인", - "action": "verify_table", - "checks": [ - "사원명 컬럼", - "부서 컬럼", - "기본급 컬럼", - "수당 컬럼", - "공제 컬럼", - "실수령액 컬럼" - ], - "expected": "급여 테이블 컬럼 정상 표시" + "name": "급여관리 페이지 확인", + "action": "verify_detail", + "checks": ["visible_text:급여"] }, { "id": 4, - "phase": "FILTER", - "name": "[FILTER] 년도 선택", - "action": "click_if_exists", - "target": "select[name*='year'], [data-field='year']", - "expected": { - "filter_applied": true - } + "name": "테이블 확인", + "action": "verify_table" }, { "id": 5, - "phase": "FILTER", - "name": "[FILTER] 월 선택", - "action": "click_if_exists", - "target": "select[name*='month'], [data-field='month']", - "expected": { - "filter_applied": true - } + "name": "검색 기능", + "action": "search", + "value": "테스트" }, { "id": 6, - "phase": "FILTER", - "name": "[FILTER] 필터 결과 확인", - "action": "verify_elements", - "checks": ["필터 결과 표시"], - "expected": { - "data_filtered": true, - "month_data_shown": true - } + "name": "검색 후 확인", + "action": "verify_detail", + "checks": ["visible_text:급여"] }, { "id": 7, - "phase": "READ", - "name": "[READ] 사원 급여 상세 클릭", - "action": "click_if_exists", - "target": "table tbody tr:first-child", - "expected": { - "detail_modal_or_page": true, - "visible": ["급여 상세", "기본급", "수당", "공제"] - } + "name": "첫 번째 행 클릭", + "action": "click_first_row" }, { "id": 8, - "phase": "READ", - "name": "[READ] 급여 상세 항목 확인", + "name": "상세 확인", "action": "verify_detail", - "checks": [ - "사원명 표시", - "기본급 표시", - "수당 항목들 표시", - "공제 항목들 표시", - "실수령액 계산" - ], - "expected": "급여 상세 정보 정상 표시" + "checks": ["visible_text:급여"] }, { "id": 9, - "phase": "UPDATE", - "name": "[UPDATE] 수당 수정 모드 진입", - "action": "click_if_exists", - "target": "button:has-text('수정'), button:has-text('편집')", - "expected": { - "edit_mode": true, - "fields_editable": true - } + "name": "모달 닫기", + "action": "close_modal_if_open" }, { "id": 10, - "phase": "UPDATE", - "name": "[UPDATE] 보너스 입력", + "name": "목록 복귀", "action": "click_if_exists", - "target": "input[name*='bonus'], input[placeholder*='보너스']" - }, - { - "id": 11, - "phase": "UPDATE", - "name": "[UPDATE] 필수 검증 #2: 수정 저장", - "action": "click_if_exists", - "target": "button:has-text('저장'), button:has-text('확인')", - "verify": { - "url_maintained": true, - "no_error_page": true, - "api_call": "PUT /api/v1/salaries/", - "toast": "수정|저장|완료|성공" - }, - "expected": "급여 수정 완료" - }, - { - "id": 12, - "phase": "UPDATE", - "name": "[UPDATE] 수정 결과 확인", - "action": "verify_detail", - "checks": [ - "보너스: 100,000", - "실수령액 재계산" - ], - "expected": "수정된 데이터 반영" - }, - { - "id": 13, - "phase": "EXPORT", - "name": "[EXPORT] 엑셀 다운로드 버튼 확인", - "action": "verify_elements", - "checks": [ - "엑셀 다운로드 버튼 존재" - ], - "expected": "다운로드 기능 존재" - }, - { - "id": 14, - "phase": "EXPORT", - "name": "[EXPORT] 필수 검증 #1: 엑셀 다운로드", - "action": "click_if_exists", - "target": "button:has-text('엑셀'), button:has-text('다운로드'), button:has-text('내보내기')", - "verify": { - "file_download": true, - "file_type": "xlsx", - "api_call": "GET /api/v1/salaries/export" - }, - "expected": "엑셀 파일 다운로드" - }, - { - "id": 15, - "phase": "STATS", - "name": "[STATS] 급여 통계 확인", - "action": "verify_elements", - "checks": [ - "총 급여액 합계", - "평균 급여", - "총 인원 수" - ], - "expected": "급여 통계 정상 표시" - }, - { - "id": 16, - "phase": "SEARCH", - "name": "[SEARCH] 사원 검색", - "action": "click_if_exists", - "target": "input[placeholder*='검색'], input[placeholder*='사원']", - "value": "홍길동", - "expected": { - "data_filtered": true - } - }, - { - "id": 17, - "phase": "SEARCH", - "name": "[SEARCH] 검색 결과 확인", - "action": "verify_elements", - "checks": ["검색 결과 표시"], - "expected": { - "row_exists": true, - "filtered_by_name": true - } + "target": "button:has-text('목록'), a:has-text('목록')" } - ], - "expectedAPIs": [ - { - "method": "GET", - "endpoint": "/api/v1/salaries", - "description": "급여 목록 조회" - }, - { - "method": "GET", - "endpoint": "/api/v1/salaries/{id}", - "description": "급여 상세 조회" - }, - { - "method": "PUT", - "endpoint": "/api/v1/salaries/{id}", - "description": "급여 수정" - }, - { - "method": "GET", - "endpoint": "/api/v1/salaries/export", - "description": "급여 엑셀 다운로드" - }, - { - "method": "GET", - "endpoint": "/api/v1/salaries/summary", - "description": "급여 통계 조회" - } - ], - "requiredVerifications": [ - { - "id": 1, - "name": "파일 다운로드", - "steps": [14], - "criteria": "엑셀 파일 다운로드 동작" - }, - { - "id": 2, - "name": "수정/저장 버튼", - "steps": [11], - "criteria": "API 호출 + 성공 토스트 + 데이터 반영" - }, - { - "id": 3, - "name": "검색/필터", - "steps": [4, 5, 6, 16, 17], - "criteria": "년월 필터 및 검색 기능" - }, - { - "id": 5, - "name": "목업 페이지 감지", - "steps": [2], - "criteria": "급여 목록, 필터, 다운로드 버튼 존재" - } - ], - "rollbackPlan": { - "onUpdateFail": "급여 데이터는 월별로 관리되어 자동 복원", - "note": "급여는 CRUD 중 삭제 없이 RU만 테스트 (시스템에서 자동 생성)" - } + ] } diff --git a/item-master.json b/item-master.json index 792f4df..971322b 100644 --- a/item-master.json +++ b/item-master.json @@ -5,7 +5,7 @@ "onErrorOnly": true, "captureOn": ["error", "fail", "timeout", "404", "500", "blocked"] }, - "description": "품목관리 > 품목기준관리 메뉴의 목록 조회, 검색, 상세 기능 테스트", + "description": "품목관리 > 품목기준관리 목록/검색/상세 기능 검증", "baseUrl": "https://dev.codebridge-x.com", "menuNavigation": { "level1": "품목관리", @@ -25,93 +25,57 @@ "action": "menu_navigate", "level1": "품목관리", "level2": "품목기준관리", - "expected": { - "url_contains": "/master-data", - "visible": ["품목기준관리", "품목"] - } + "expected": { "url_contains": "/master-data" } }, { "id": 2, - "name": "필수 검증 #5: 목업 페이지 감지", - "action": "verify_not_mockup", - "checks": [ - "검색 입력 필드 존재", - "테이블 또는 목록 표시", - "등록/추가 버튼 존재" - ], - "expected": "정상 페이지 (목업 아님)" + "name": "목업 감지", + "action": "verify_not_mockup" }, { "id": 3, - "name": "테이블 구조 확인", - "action": "verify_table", - "checks": [ - "품목코드 컬럼", - "품목명 컬럼", - "규격 컬럼", - "단위 컬럼" - ], - "expected": "주요 컬럼 존재" + "name": "품목기준관리 페이지 확인", + "action": "verify_detail", + "checks": ["visible_text:품목"] }, { "id": 4, - "name": "검색 기능 테스트", - "action": "click_if_exists", - "target": "input[placeholder*='검색']", - "value": "테스트", - "expected": "검색어 입력됨" + "name": "테이블 확인", + "action": "verify_table" }, { "id": 5, - "name": "검색 결과 확인", - "action": "wait", - "duration": 500, - "expected": "검색 결과 표시" + "name": "검색 기능", + "action": "search", + "value": "테스트" }, { "id": 6, - "name": "검색 초기화", - "action": "click_if_exists", - "target": "input[placeholder*='검색']", - "expected": "검색어 삭제" + "name": "검색 후 확인", + "action": "verify_detail", + "checks": ["visible_text:품목"] }, { "id": 7, - "name": "테이블 행 클릭 - 상세 페이지", - "action": "click_if_exists", - "target": "table tbody tr:first-child", - "expected": "상세 페이지로 이동" + "name": "첫 번째 행 클릭", + "action": "click_first_row" }, { "id": 8, - "name": "상세 페이지 요소 확인", - "action": "verify_elements", - "checks": [ - "품목 정보 표시", - "목록 버튼 존재" - ], - "expected": "상세 정보 정상 표시" + "name": "상세 확인", + "action": "verify_detail", + "checks": ["visible_text:품목"] }, { "id": 9, - "name": "목록으로 돌아가기", - "action": "click_if_exists", - "target": "목록", - "expected": "목록 페이지로 복귀" - } - ], - "requiredVerifications": [ - { - "id": 3, - "name": "검색/필터", - "steps": [4, 5, 6], - "criteria": "검색 시 데이터 변화 확인" + "name": "모달 닫기", + "action": "close_modal_if_open" }, { - "id": 5, - "name": "목업 페이지 감지", - "steps": [2], - "criteria": "입력 필드, 동작 버튼, 테이블 데이터 확인" + "id": 10, + "name": "목록 복귀", + "action": "click_if_exists", + "target": "button:has-text('목록'), a:has-text('목록')" } ] } diff --git a/payment-history.json b/payment-history.json deleted file mode 100644 index c7039c3..0000000 --- a/payment-history.json +++ /dev/null @@ -1,120 +0,0 @@ -{ - "id": "payment-history", - "name": "결제내역 테스트", - "screenshotPolicy": { - "onErrorOnly": true, - "captureOn": ["error", "fail", "timeout", "404", "500", "blocked"] - }, - "description": "회계관리 > 결제내역 메뉴의 결제 내역 조회 기능 테스트", - "baseUrl": "https://dev.codebridge-x.com", - "menuNavigation": { - "level1": "회계관리", - "level2": "결제내역", - "expectedUrl": "/payment-history", - "searchWithinParent": true, - "closeOtherMenus": true - }, - "auth": { - "username": "TestUser5", - "password": "password123!" - }, - "selectors": { - "pageTitle": "h1, h2, [class*='title'], [class*='Title']", - "dataTable": "table, [role='grid'], [class*='table'], [class*='Table']", - "tableHeader": "table thead th, table th, [role='columnheader']", - "tableRow": "table tbody tr, [role='row']:not(:first-child)", - "pagination": "[class*='pagination'], [class*='Pagination'], nav[aria-label*='page'], [class*='pager']", - "emptyMessage": "[class*='empty'], [class*='no-data'], [class*='noData']" - }, - "steps": [ - { - "id": 0, - "name": "사이드바 메뉴 전체 펼치기", - "actions": [ - { - "type": "evaluate", - "script": "document.querySelector('.sidebar-scroll')?.scrollTo({top:0,behavior:'instant'})" - }, - { "type": "wait", "duration": 300 }, - { - "type": "evaluate", - "script": "Array.from(document.querySelectorAll('button')).find(b => b.innerText?.includes('모두 펼치기'))?.click()" - }, - { "type": "wait", "duration": 2000 } - ] - }, - { - "id": 1, - "name": "2단계 메뉴 진입: 회계관리 > 결제내역", - "action": "menu_navigate", - "level1": "회계관리", - "level2": "결제내역", - "expected": { - "url_contains": "/payment" - } - }, - { - "id": 2, - "name": "페이지 로드 및 404 확인", - "action": "verify_url_stability", - "verification": { - "expected_url": "/payment" - } - }, - { - "id": 3, - "name": "페이지 제목 확인", - "action": "evaluate", - "script": "(() => { const title = document.querySelector('h1, h2, [class*=\"title\"]'); return title && (title.innerText.includes('결제') || title.innerText.includes('Payment')); })()" - }, - { - "id": 4, - "name": "테이블 구조 존재 확인", - "action": "verify_element", - "target": "dataTable" - }, - { - "id": 5, - "name": "테이블 헤더 컬럼 확인", - "action": "verify_element", - "target": "tableHeader", - "verification": { "count": 1 } - }, - { - "id": 6, - "name": "데이터 행 또는 빈 메시지 확인", - "action": "evaluate", - "script": "(() => { const rows = document.querySelectorAll('table tbody tr, [role=\"row\"]:not(:first-child)'); const empty = document.body.innerText.includes('데이터') && document.body.innerText.includes('없'); return rows.length > 0 || empty; })()" - }, - { - "id": 7, - "name": "페이지네이션 존재 확인", - "action": "verify_element", - "target": "pagination" - }, - { - "id": 8, - "name": "콘솔 에러 없음 확인", - "action": "evaluate", - "script": "true" - }, - { - "id": 9, - "name": "최종 URL 안정성 확인", - "action": "verify_url_stability", - "verification": { - "expected_url": "/payment" - } - } - ], - "expectedAPIs": [ - { - "method": "GET", - "endpoint": "/api/v1/accounting/payments", - "description": "결제 내역 목록 조회" - } - ], - "rollbackPlan": { - "note": "조회 전용 페이지로 데이터 변경 없음" - } -} diff --git a/production-dashboard.json b/production-dashboard.json index 1effe62..767d10a 100644 --- a/production-dashboard.json +++ b/production-dashboard.json @@ -1,12 +1,11 @@ { - "enabled": true, "id": "production-dashboard", "name": "생산 현황판 테스트", "screenshotPolicy": { "onErrorOnly": true, "captureOn": ["error", "fail", "timeout", "404", "500", "blocked"] }, - "description": "생산관리 > 생산 현황판 메뉴의 생산 현황 모니터링/필터/차트 기능 테스트", + "description": "생산관리 > 생산 현황판 대시보드 기능 검증", "baseUrl": "https://dev.codebridge-x.com", "menuNavigation": { "level1": "생산관리", @@ -19,13 +18,6 @@ "username": "TestUser5", "password": "password123!" }, - "selectors": { - "statCard": ".card, [class*='stat'], [class*='kpi'], [class*='metric'], [class*='summary']", - "chart": "canvas, svg, [class*='chart'], [class*='Chart'], [class*='graph']", - "filterArea": "[class*='filter'], [class*='Filter'], select, [class*='date-picker']", - "refreshButton": "button:has-text('새로고침'), button:has-text('갱신'), button[class*='refresh'], [class*='reload']", - "fullscreenButton": "button:has-text('전체'), button[class*='fullscreen'], button[class*='expand']" - }, "steps": [ { "id": 1, @@ -33,103 +25,47 @@ "action": "menu_navigate", "level1": "생산관리", "level2": "생산 현황판", - "expected": { - "url_contains": "/production", - "visible": ["현황판", "생산"] - } + "expected": { "url_contains": "/production" } }, { "id": 2, - "name": "필수 검증 #5: 목업 페이지 감지", - "action": "verify_not_mockup", - "checks": [ - "생산 현황 데이터 표시", - "통계 카드 또는 차트 존재", - "기간 필터 존재" - ], - "expected": "정상 페이지 (목업 아님)" + "name": "목업 감지", + "action": "verify_not_mockup" }, { "id": 3, - "name": "통계 카드 영역 존재 확인", - "action": "verify_element", - "target": "statCard" + "name": "생산 현황판 페이지 확인", + "action": "verify_detail", + "checks": ["visible_text:생산"] }, { "id": 4, - "phase": "READ", - "name": "[READ] 생산 통계 숫자 데이터 확인", - "action": "evaluate", - "script": "(() => { const cards = document.querySelectorAll('.card, [class*=\"stat\"], [class*=\"metric\"]'); let hasNum = false; cards.forEach(c => { if (/\\d+/.test(c.innerText)) hasNum = true; }); return hasNum || document.body.innerText.includes('생산'); })()" + "name": "현황 데이터 확인", + "action": "verify_detail", + "checks": ["visible_text:현황"] }, { "id": 5, - "phase": "READ", - "name": "[READ] 차트 영역 존재 확인", - "action": "verify_element", - "target": "chart" + "name": "필터 버튼 클릭", + "action": "click_if_exists", + "target": "button:has-text('필터'), select, [class*='filter'] button, [class*='date-picker']" }, { "id": 6, - "phase": "FILTER", - "name": "[FILTER] 필터/기간 선택 UI 존재 확인", - "action": "verify_element", - "target": "filterArea" + "name": "대기", + "action": "wait", + "duration": 1000 }, { "id": 7, - "phase": "FILTER", - "name": "[FILTER] 필터 클릭 테스트", - "action": "click_if_exists", - "target": "select, [class*='filter'] button, [class*='date-picker'], button:has-text('기간')" + "name": "모달 닫기", + "action": "close_modal_if_open" }, { "id": 8, - "name": "실시간/갱신 정보 확인", - "action": "evaluate", - "script": "(() => { const text = document.body.innerText; return text.includes('실시간') || text.includes('갱신') || text.includes('업데이트') || /\\d{2}:\\d{2}/.test(text); })()" - }, - { - "id": 9, - "name": "불량률/품질 정보 확인", - "action": "evaluate", - "script": "(() => { const text = document.body.innerText; return text.includes('불량') || text.includes('품질') || text.includes('%') || text.includes('달성'); })()" - }, - { - "id": 10, - "name": "생산 목표/실적 데이터 확인", - "action": "evaluate", - "script": "(() => { const text = document.body.innerText; return text.includes('목표') || text.includes('실적') || text.includes('생산량') || /\\d+[개대건]/.test(text); })()" - }, - { - "id": 11, - "name": "새로고침 버튼 존재 확인", - "action": "verify_element", - "target": "refreshButton" - }, - { - "id": 12, - "name": "전체화면/확대 버튼 확인", - "action": "verify_element", - "target": "fullscreenButton" + "name": "생산 현황판 최종 확인", + "action": "verify_detail", + "checks": ["visible_text:생산"] } - ], - "expectedAPIs": [ - { - "method": "GET", - "endpoint": "/api/v1/production/dashboard", - "description": "생산 현황판 데이터 조회" - } - ], - "requiredVerifications": [ - { - "id": 5, - "name": "목업 페이지 감지", - "steps": [2], - "criteria": "생산 현황 데이터, 통계 카드/차트, 기간 필터 존재" - } - ], - "rollbackPlan": { - "note": "조회 전용 페이지로 데이터 변경 없음" - } + ] } diff --git a/production-item.json b/production-item.json index ce790a8..0a14d77 100644 --- a/production-item.json +++ b/production-item.json @@ -1,12 +1,11 @@ { - "enabled": true, "id": "production-item", "name": "생산품목관리 테스트", "screenshotPolicy": { "onErrorOnly": true, "captureOn": ["error", "fail", "timeout", "404", "500", "blocked"] }, - "description": "품목관리 > 품목기준관리 메뉴의 품목 목록 조회 및 UI 검증 테스트", + "description": "품목관리 > 품목기준관리 목록/검색/상세 기능 검증", "baseUrl": "https://dev.codebridge-x.com", "menuNavigation": { "level1": "품목관리", @@ -26,126 +25,57 @@ "action": "menu_navigate", "level1": "품목관리", "level2": "품목기준관리", - "expected": { - "url_contains": "/master-data", - "visible": ["품목기준관리", "품목"] - } + "expected": { "url_contains": "/master-data" } }, { "id": 2, - "name": "필수 검증 #5: 목업 페이지 감지", - "action": "verify_not_mockup", - "checks": [ - "품목 목록 표시", - "품목 등록 버튼 존재", - "검색 기능 존재" - ], - "expected": "정상 페이지 (목업 아님)" + "name": "목업 감지", + "action": "verify_not_mockup" }, { "id": 3, - "name": "품목 테이블 구조 확인", - "action": "verify_table", - "checks": [ - "품목코드 컬럼", - "품목명 컬럼", - "규격 컬럼", - "단위 컬럼" - ], - "expected": "품목 테이블 표시" + "name": "품목기준관리 페이지 확인", + "action": "verify_detail", + "checks": ["visible_text:품목"] }, { "id": 4, - "name": "품목 UI 요소 확인", - "action": "verify_elements", - "checks": [ - "등록 버튼 존재", - "검색 입력 필드", - "품목 목록" - ], - "expected": "품목 UI 정상 표시" + "name": "테이블 확인", + "action": "verify_table" }, { "id": 5, - "phase": "READ", - "name": "[READ] 품목 목록 확인", - "action": "verify_detail", - "checks": [ - "품목 목록 데이터 표시됨" - ], - "expected": "품목 목록 정상" + "name": "검색 기능", + "action": "search", + "value": "테스트" }, { "id": 6, - "phase": "READ", - "name": "[READ] 첫 번째 품목 클릭", - "action": "click_if_exists", - "target": "table tbody tr:first-child" + "name": "검색 후 확인", + "action": "verify_detail", + "checks": ["visible_text:품목"] }, { "id": 7, - "phase": "READ", - "name": "[READ] 품목 상세 정보 확인", - "action": "verify_detail", - "checks": [ - "품목 상세 정보 표시" - ], - "expected": "품목 상세 정보 확인" + "name": "첫 번째 행 클릭", + "action": "click_first_row" }, { "id": 8, - "name": "상세 모달/페이지 닫기", - "action": "click_if_exists", - "target": "button:has-text('닫기'), button:has-text('목록'), button:has-text('Close')" + "name": "상세 확인", + "action": "verify_detail", + "checks": ["visible_text:품목"] }, { "id": 9, - "name": "모달 닫기 확인", - "action": "close_modal_if_open", - "expected": "모달 닫힘" + "name": "모달 닫기", + "action": "close_modal_if_open" }, { "id": 10, - "name": "목록 복귀 확인", - "action": "verify_table", - "checks": [ - "품목 목록 표시" - ], - "expected": "목록 복귀 확인" - }, - { - "id": 11, - "name": "검색 기능 확인", + "name": "목록 복귀", "action": "click_if_exists", - "target": "input[placeholder*='검색'], input[type='search']" - }, - { - "id": 12, - "name": "품목관리 페이지 최종 확인", - "action": "verify_elements", - "checks": [ - "품목 목록 구조 정상", - "등록 버튼 존재" - ], - "expected": "품목관리 페이지 정상" + "target": "button:has-text('목록'), a:has-text('목록')" } - ], - "expectedAPIs": [ - { - "method": "GET", - "endpoint": "/api/v1/items", - "description": "품목 목록 조회" - } - ], - "requiredVerifications": [ - { - "id": 5, - "name": "목업 페이지 감지", - "steps": [2], - "criteria": "품목 목록, 등록 버튼, 검색 기능 존재" - } - ], - "rollbackPlan": { - "note": "READ-only 패턴으로 안정성 우선" - } + ] } diff --git a/production-worker.json b/production-worker.json index e916dd0..608b492 100644 --- a/production-worker.json +++ b/production-worker.json @@ -1,12 +1,11 @@ { - "enabled": true, "id": "production-worker", "name": "작업자 화면 테스트", "screenshotPolicy": { "onErrorOnly": true, "captureOn": ["error", "fail", "timeout", "404", "500", "blocked"] }, - "description": "생산관리 > 작업자 화면 메뉴의 작업 조회/실적 입력 기능 테스트", + "description": "생산관리 > 작업자 화면 목록/검색/상세 기능 검증", "baseUrl": "https://dev.codebridge-x.com", "menuNavigation": { "level1": "생산관리", @@ -26,155 +25,57 @@ "action": "menu_navigate", "level1": "생산관리", "level2": "작업자 화면", - "expected": { - "url_contains": "/production", - "visible": ["작업자"] - } + "expected": { "url_contains": "/production" } }, { "id": 2, - "name": "필수 검증 #5: 목업 페이지 감지", - "action": "verify_not_mockup", - "checks": [ - "작업자 화면 표시", - "작업 목록 또는 작업 선택", - "실적 입력 가능" - ], - "expected": "정상 페이지 (목업 아님)" + "name": "목업 감지", + "action": "verify_not_mockup" }, { "id": 3, - "name": "작업자 화면 구조 확인", - "action": "verify_elements", - "checks": [ - "오늘 작업 목록", - "작업 지시 정보", - "실적 입력 영역", - "완료 버튼" - ], - "expected": "작업자 화면 구조 정상 표시" + "name": "작업자 화면 페이지 확인", + "action": "verify_detail", + "checks": ["visible_text:작업"] }, { "id": 4, - "phase": "READ", - "name": "[READ] 오늘 작업 목록 확인", - "action": "verify_detail", - "checks": [ - "할당된 작업 표시", - "작업 지시 번호", - "품목 정보" - ], - "expected": "오늘 작업 목록 표시" + "name": "테이블 확인", + "action": "verify_table" }, { "id": 5, - "phase": "READ", - "name": "[READ] 작업 지시 상세 확인", - "action": "click_if_exists", - "target": "table tbody tr:first-child, [class*='list'] [class*='item']:first-child", - "expected": { - "detail_view": true - } + "name": "검색 기능", + "action": "search", + "value": "테스트" }, { "id": 6, - "name": "작업 지시 상세 정보", + "name": "검색 후 확인", "action": "verify_detail", - "checks": [ - "작업 지시 번호", - "품목명/규격", - "지시 수량", - "시작/종료 예정 시간" - ], - "expected": "작업 지시 상세 표시" + "checks": ["visible_text:작업"] }, { "id": 7, - "name": "실적 입력 영역 확인", - "action": "verify_elements", - "checks": [ - "생산 수량 입력", - "불량 수량 입력", - "작업 시간 입력" - ], - "expected": "실적 입력 필드 표시" + "name": "첫 번째 행 클릭", + "action": "click_first_row" }, { "id": 8, - "name": "작업 상태 변경 버튼", - "action": "verify_elements", - "checks": [ - "작업 시작 버튼", - "작업 완료 버튼", - "일시정지 버튼" - ], - "expected": "상태 변경 버튼 표시" + "name": "상세 확인", + "action": "verify_detail", + "checks": ["visible_text:작업"] }, { "id": 9, - "name": "실시간 생산량 표시", - "action": "verify_detail", - "checks": [ - "현재까지 생산량", - "목표 대비 진행률" - ], - "expected": "실시간 생산량 표시" + "name": "모달 닫기", + "action": "close_modal_if_open" }, { "id": 10, - "name": "불량 등록 기능", - "action": "verify_elements", - "checks": [ - "불량 유형 선택", - "불량 수량 입력" - ], - "expected": "불량 등록 기능 표시" - }, - { - "id": 11, - "name": "작업 메모/비고 입력", - "action": "verify_elements", - "checks": [ - "메모 또는 비고 입력 영역" - ], - "expected": "메모 입력 가능" - }, - { - "id": 12, - "name": "이전 작업 실적 확인", - "action": "verify_elements", - "checks": [ - "이전 작업 실적 조회 가능" - ], - "expected": "이력 조회 기능 표시" + "name": "목록 복귀", + "action": "click_if_exists", + "target": "button:has-text('목록'), a:has-text('목록')" } - ], - "expectedAPIs": [ - { - "method": "GET", - "endpoint": "/api/v1/production/worker/tasks", - "description": "작업자 할당 작업 조회" - }, - { - "method": "POST", - "endpoint": "/api/v1/production/work-results", - "description": "작업 실적 등록" - }, - { - "method": "PUT", - "endpoint": "/api/v1/production/tasks/:id/status", - "description": "작업 상태 변경" - } - ], - "requiredVerifications": [ - { - "id": 5, - "name": "목업 페이지 감지", - "steps": [2], - "criteria": "작업자 화면, 작업 목록, 실적 입력 기능 존재" - } - ], - "rollbackPlan": { - "note": "실적 입력 테스트는 실제 데이터에 영향을 줄 수 있으므로 주의" - } + ] } diff --git a/quality-certification.json b/quality-certification.json index 6c0df6c..aad09c9 100644 --- a/quality-certification.json +++ b/quality-certification.json @@ -1,12 +1,11 @@ { - "enabled": true, "id": "quality-certification", "name": "품질인정심사 시스템 테스트", "screenshotPolicy": { "onErrorOnly": true, "captureOn": ["error", "fail", "timeout", "404", "500", "blocked"] }, - "description": "품질관리 > 품질인정심사 시스템 메뉴의 기능 테스트", + "description": "품질관리 > 품질인정심사 시스템 목록/검색/상세 기능 검증", "baseUrl": "https://dev.codebridge-x.com", "menuNavigation": { "level1": "품질관리", @@ -26,38 +25,57 @@ "action": "menu_navigate", "level1": "품질관리", "level2": "품질인정심사 시스템", - "expected": { - "url_contains": "/quality", - "visible": ["품질인정심사"] - } + "expected": { "url_contains": "/quality" } }, { "id": 2, - "name": "필수 검증 #5: 목업 페이지 감지", - "action": "verify_not_mockup", - "checks": [ - "페이지 콘텐츠 로드", - "주요 기능 버튼 존재" - ], - "expected": "정상 페이지 (목업 아님)" + "name": "목업 감지", + "action": "verify_not_mockup" }, { "id": 3, - "name": "페이지 요소 확인", - "action": "verify_elements", - "checks": [ - "페이지 타이틀 표시", - "주요 콘텐츠 영역 존재" - ], - "expected": "페이지 정상 로드" - } - ], - "requiredVerifications": [ + "name": "품질인정심사 페이지 확인", + "action": "verify_detail", + "checks": ["visible_text:품질"] + }, + { + "id": 4, + "name": "테이블 확인", + "action": "verify_table" + }, { "id": 5, - "name": "목업 페이지 감지", - "steps": [2], - "criteria": "페이지 콘텐츠 확인" + "name": "검색 기능", + "action": "search", + "value": "테스트" + }, + { + "id": 6, + "name": "검색 후 확인", + "action": "verify_detail", + "checks": ["visible_text:품질"] + }, + { + "id": 7, + "name": "첫 번째 행 클릭", + "action": "click_first_row" + }, + { + "id": 8, + "name": "상세 확인", + "action": "verify_detail", + "checks": ["visible_text:품질"] + }, + { + "id": 9, + "name": "모달 닫기", + "action": "close_modal_if_open" + }, + { + "id": 10, + "name": "목록 복귀", + "action": "click_if_exists", + "target": "button:has-text('목록'), a:has-text('목록')" } ] } diff --git a/settings-position.json b/settings-position.json index 80e3e98..66b7f41 100644 --- a/settings-position.json +++ b/settings-position.json @@ -5,7 +5,7 @@ "onErrorOnly": true, "captureOn": ["error", "fail", "timeout", "404", "500", "blocked"] }, - "description": "설정 > 직책관리 메뉴의 직책 목록 조회 및 UI 검증 테스트", + "description": "설정 > 직책관리 목록/검색/상세 기능 검증", "baseUrl": "https://dev.codebridge-x.com", "menuNavigation": { "level1": "설정", @@ -25,127 +25,47 @@ "action": "menu_navigate", "level1": "설정", "level2": "직책관리", - "expected": { - "url_contains": "/settings/titles", - "visible": ["직책관리", "직책"] - } + "expected": { "url_contains": "/settings" } }, { "id": 2, - "name": "필수 검증 #5: 목업 페이지 감지", - "action": "verify_not_mockup", - "checks": [ - "직책 목록 표시", - "직책 추가 버튼 존재", - "검색/필터 기능 존재" - ], - "expected": "정상 페이지 (목업 아님)" + "name": "목업 감지", + "action": "verify_not_mockup" }, { "id": 3, - "name": "직책 테이블 구조 확인", - "action": "verify_table", - "checks": [ - "직책명 컬럼", - "직책코드 컬럼", - "순서 컬럼" - ], - "expected": "직책 테이블 컬럼 정상 표시" + "name": "직책관리 페이지 확인", + "action": "verify_detail", + "checks": ["visible_text:직책"] }, { "id": 4, - "name": "검색 기능 확인", - "action": "click_if_exists", - "target": "input[placeholder*='검색']", - "expected": { - "search_available": true - } + "name": "설정 페이지 확인", + "action": "verify_detail", + "checks": ["visible_text:설정"] }, { "id": 5, - "name": "직책 추가 버튼 확인", + "name": "추가 버튼 클릭", "action": "click_if_exists", - "target": "button:has-text('추가'), button:has-text('직책 추가'), button:has-text('등록')", - "expected": { - "modal_or_page": true - } + "target": "button:has-text('추가'), button:has-text('등록'), button:has-text('신규')" }, { "id": 6, - "name": "추가 폼 요소 확인", - "action": "verify_elements", - "checks": [ - "직책명 입력 필드", - "직책코드 입력 필드" - ], - "expected": "직책 추가 폼 표시" + "name": "대기", + "action": "wait", + "duration": 1000 }, { "id": 7, - "name": "추가 모달 닫기", - "action": "close_modal_if_open", - "expected": "모달 닫힘" + "name": "모달 닫기", + "action": "close_modal_if_open" }, { "id": 8, - "phase": "READ", - "name": "[READ] 직책 목록 데이터 확인", + "name": "직책관리 최종 확인", "action": "verify_detail", - "checks": [ - "직책 목록 데이터 표시됨" - ], - "expected": "직책 목록 정상 표시" - }, - { - "id": 9, - "phase": "READ", - "name": "[READ] 첫 번째 행 클릭", - "action": "click_if_exists", - "target": "table tbody tr:first-child" - }, - { - "id": 10, - "phase": "READ", - "name": "[READ] 직책 상세 정보 확인", - "action": "verify_detail", - "checks": [ - "직책 상세 정보 표시" - ], - "expected": "직책 상세 정보 확인" - }, - { - "id": 11, - "name": "상세 모달 닫기", - "action": "close_modal_if_open", - "expected": "모달 닫힘" - }, - { - "id": 12, - "name": "직책관리 페이지 최종 확인", - "action": "verify_elements", - "checks": [ - "직책 목록 구조 정상", - "추가 버튼 존재" - ], - "expected": "직책관리 페이지 정상" + "checks": ["visible_text:직책"] } - ], - "expectedAPIs": [ - { - "method": "GET", - "endpoint": "/api/v1/positions", - "description": "직책 목록 조회" - } - ], - "requiredVerifications": [ - { - "id": 5, - "name": "목업 페이지 감지", - "steps": [2], - "criteria": "직책 목록, 추가 버튼, 필터 존재" - } - ], - "rollbackPlan": { - "note": "READ-only 패턴으로 안정성 우선" - } + ] } diff --git a/settings-rank.json b/settings-rank.json index 0039892..f9156d7 100644 --- a/settings-rank.json +++ b/settings-rank.json @@ -5,7 +5,7 @@ "onErrorOnly": true, "captureOn": ["error", "fail", "timeout", "404", "500", "blocked"] }, - "description": "설정 > 직급관리 메뉴의 직급 조회/등록/수정/삭제 전체 CRUD 테스트", + "description": "설정 > 직급관리 목록/검색/상세 기능 검증", "baseUrl": "https://dev.codebridge-x.com", "menuNavigation": { "level1": "설정", @@ -18,18 +18,6 @@ "username": "TestUser5", "password": "password123!" }, - "testData": { - "create": { - "rankName": "E2E_TEST_직급", - "rankCode": "E2E_RANK", - "order": "99", - "memo": "E2E 자동화 테스트 직급" - }, - "update": { - "rankName": "E2E_TEST_수정직급", - "memo": "E2E 수정된 직급 메모" - } - }, "steps": [ { "id": 1, @@ -37,269 +25,47 @@ "action": "menu_navigate", "level1": "설정", "level2": "직급관리", - "expected": { - "url_contains": "/settings/ranks", - "visible": ["직급관리", "직급"] - } + "expected": { "url_contains": "/settings" } }, { "id": 2, - "name": "필수 검증 #5: 목업 페이지 감지", - "action": "verify_not_mockup", - "checks": [ - "직급 목록 표시", - "직급 추가 버튼 존재", - "검색/필터 기능 존재" - ], - "expected": "정상 페이지 (목업 아님)" + "name": "목업 감지", + "action": "verify_not_mockup" }, { "id": 3, - "name": "직급 테이블 구조 확인", - "action": "verify_table", - "checks": [ - "직급명 컬럼", - "직급코드 컬럼", - "순서 컬럼" - ], - "expected": "직급 테이블 컬럼 정상 표시" + "name": "직급관리 페이지 확인", + "action": "verify_detail", + "checks": ["visible_text:직급"] }, { "id": 4, - "name": "검색 기능 테스트", - "action": "click_if_exists", - "target": "input[placeholder*='검색']", - "value": "테스트", - "expected": { - "data_filtered": true - } + "name": "설정 페이지 확인", + "action": "verify_detail", + "checks": ["visible_text:설정"] }, { "id": 5, - "phase": "CREATE", - "name": "[CREATE] 직급 추가 버튼 클릭", + "name": "추가 버튼 클릭", "action": "click_if_exists", - "target": "button:has-text('추가'), button:has-text('직급 추가'), button:has-text('등록')", - "expected": { - "modal_or_page": true, - "title": "직급 추가" - } + "target": "button:has-text('추가'), button:has-text('등록'), button:has-text('신규')" }, { "id": 6, - "phase": "CREATE", - "name": "[CREATE] 직급 정보 입력", - "action": "fill_form", - "fields": [ - {"name": "직급명", "type": "text", "value": "E2E_TEST_직급_{timestamp}"}, - {"name": "직급코드", "type": "text", "value": "E2E_RANK_{timestamp}"}, - {"name": "순서", "type": "number", "value": "99"}, - {"name": "메모", "type": "text", "value": "E2E 자동화 테스트 직급_{timestamp}"} - ], - "note": "타임스탬프로 고유성 보장" + "name": "대기", + "action": "wait", + "duration": 1000 }, { "id": 7, - "phase": "CREATE", - "name": "[CREATE] 필수 검증 #2: 등록 저장", - "action": "click_if_exists", - "target": "button:has-text('저장'), button:has-text('등록'), button:has-text('추가')", - "verify": { - "url_maintained": true, - "no_error_page": true, - "api_call": "POST /api/v1/ranks", - "toast": "등록|추가|완료|성공" - }, - "expected": "직급 등록 완료" - }, - { - "id": "7-modal-close", - "phase": "CREATE", - "name": "[CREATE] 모달 닫기 확인", - "action": "close_modal_if_open", - "expected": "모달 닫힘" + "name": "모달 닫기", + "action": "close_modal_if_open" }, { "id": 8, - "phase": "CREATE", - "name": "[CREATE] 등록 결과 확인", + "name": "직급관리 최종 확인", "action": "verify_detail", - "search": "E2E_TEST_직급", - "expected": { - "row_exists": true, - "contains": ["E2E_TEST", "E2E_RANK"] - } - }, - { - "id": 9, - "phase": "READ", - "name": "[READ] 직급 상세 페이지 진입", - "action": "click_if_exists", - "target": "table tbody tr:has-text('E2E_TEST')", - "expected": { - "url_contains": "/settings/ranks", - "visible": ["직급 상세", "수정", "삭제"] - } - }, - { - "id": 10, - "phase": "READ", - "name": "[READ] 상세 정보 확인", - "action": "verify_detail", - "checks": [ - "직급명: E2E_TEST_직급", - "직급코드: E2E_RANK", - "순서: 99" - ], - "expected": "입력한 데이터와 일치" - }, - { - "id": 11, - "phase": "UPDATE", - "name": "[UPDATE] 수정 모드 진입", - "action": "click_if_exists", - "target": "button:has-text('수정')", - "expected": { - "url_contains": "mode=edit", - "fields_editable": true - } - }, - { - "id": 12, - "phase": "UPDATE", - "name": "[UPDATE] 직급명 수정", - "action": "fill", - "target": "input[name*='name'], input[placeholder*='직급명']", - "value": "E2E_TEST_수정직급", - "clear": true - }, - { - "id": 13, - "phase": "UPDATE", - "name": "[UPDATE] 메모 수정", - "action": "click_if_exists", - "target": "textarea[name*='memo'], input[placeholder*='메모']", - "value": "E2E 수정된 직급 메모_{timestamp}", - "clear": true - }, - { - "id": 14, - "phase": "UPDATE", - "name": "[UPDATE] 필수 검증 #2: 수정 저장", - "action": "click_if_exists", - "target": "button:has-text('저장')", - "verify": { - "url_maintained": true, - "no_error_page": true, - "api_call": "PUT /api/v1/ranks/", - "toast": "수정|완료|성공" - }, - "expected": "수정 완료" - }, - { - "id": 15, - "phase": "UPDATE", - "name": "[UPDATE] 수정 결과 확인", - "action": "verify_detail", - "checks": [ - "직급명: E2E_TEST_수정직급", - "메모: E2E 수정된" - ], - "expected": "수정된 데이터 반영" - }, - { - "id": 16, - "phase": "DELETE", - "name": "[DELETE] 삭제 버튼 클릭", - "action": "click_if_exists", - "target": "button:has-text('삭제')", - "expected": { - "confirm_dialog": true, - "dialog_message": "삭제|정말" - } - }, - { - "id": 17, - "phase": "DELETE", - "name": "[DELETE] 필수 검증 #6: 삭제 확인", - "action": "click_if_exists", - "target": "button:has-text('확인'), button:has-text('삭제')", - "verify": { - "api_call": "DELETE /api/v1/ranks/", - "toast": "삭제|완료|성공", - "redirect": "/settings/ranks" - }, - "expected": "삭제 완료 및 목록 복귀" - }, - { - "id": 18, - "phase": "DELETE", - "name": "[DELETE] 삭제 결과 확인", - "action": "verify_detail", - "search": "E2E_TEST_수정직급", - "expected": { - "row_exists": false, - "message": "테스트 직급이 목록에서 제거됨" - } + "checks": ["visible_text:직급"] } - ], - "expectedAPIs": [ - { - "method": "GET", - "endpoint": "/api/v1/ranks", - "description": "직급 목록 조회" - }, - { - "method": "POST", - "endpoint": "/api/v1/ranks", - "description": "직급 등록" - }, - { - "method": "GET", - "endpoint": "/api/v1/ranks/{id}", - "description": "직급 상세 조회" - }, - { - "method": "PUT", - "endpoint": "/api/v1/ranks/{id}", - "description": "직급 수정" - }, - { - "method": "DELETE", - "endpoint": "/api/v1/ranks/{id}", - "description": "직급 삭제" - } - ], - "requiredVerifications": [ - { - "id": 2, - "name": "등록/저장 버튼", - "steps": [7, 14], - "criteria": "API 호출 + 성공 토스트 + 데이터 반영" - }, - { - "id": 3, - "name": "검색/필터", - "steps": [4], - "criteria": "검색 기능 동작" - }, - { - "id": 5, - "name": "목업 페이지 감지", - "steps": [2], - "criteria": "직급 목록, 추가 버튼, 필터 존재" - }, - { - "id": 6, - "name": "삭제 기능", - "steps": [16, 17, 18], - "criteria": "DELETE API + 목록에서 제거" - } - ], - "rollbackPlan": { - "onCreateFail": "모달 닫기", - "onUpdateFail": "테스트 직급 수동 삭제 필요", - "onDeleteFail": "테스트 직급 수동 삭제 필요", - "cleanupRequired": "E2E_TEST_ 접두사 직급은 테스트 데이터" - } + ] } diff --git a/shipment-management.json b/shipment-management.json index 88d84f3..8e4cf2d 100644 --- a/shipment-management.json +++ b/shipment-management.json @@ -1,19 +1,11 @@ { - "enabled": true, "id": "shipment-management", "name": "출고관리 테스트", "screenshotPolicy": { "onErrorOnly": true, - "captureOn": [ - "error", - "fail", - "timeout", - "404", - "500", - "blocked" - ] + "captureOn": ["error", "fail", "timeout", "404", "500", "blocked"] }, - "description": "출고관리 > 출고관리 메뉴의 출고 조회/등록/수정/삭제 전체 CRUD 테스트", + "description": "출고관리 > 출고관리 목록/검색/상세 기능 검증", "baseUrl": "https://dev.codebridge-x.com", "menuNavigation": { "level1": "출고관리", @@ -26,19 +18,6 @@ "username": "TestUser5", "password": "password123!" }, - "testData": { - "create": { - "clientName": "E2E_TEST_거래처", - "itemName": "테스트품목", - "quantity": "50", - "shipmentDate": "2026-02-05", - "memo": "E2E 자동화 테스트 출고" - }, - "update": { - "quantity": "60", - "memo": "E2E 수정된 출고 메모" - } - }, "steps": [ { "id": 1, @@ -46,313 +25,57 @@ "action": "menu_navigate", "level1": "출고관리", "level2": "출고관리", - "expected": { - "url_contains": "/outbound", - "visible": [ - "출고관리", - "출고" - ] - } + "expected": { "url_contains": "/outbound" } }, { "id": 2, - "name": "필수 검증 #5: 목업 페이지 감지", - "action": "verify_not_mockup", - "checks": [ - "출고 목록 표시", - "출고 등록 버튼 존재", - "검색/필터 기능 존재" - ], - "expected": "정상 페이지 (목업 아님)" + "name": "목업 감지", + "action": "verify_not_mockup" }, { "id": 3, - "name": "출고 테이블 구조 확인", - "action": "verify_table", - "checks": [ - "출고일 컬럼", - "거래처 컬럼", - "품목 컬럼", - "수량 컬럼", - "상태 컬럼" - ], - "expected": "출고 테이블 컬럼 정상 표시" + "name": "출고관리 페이지 확인", + "action": "verify_detail", + "checks": ["visible_text:출고"] }, { "id": 4, - "name": "검색 기능 테스트", - "action": "click_if_exists", - "target": "input[placeholder*='검색']", - "value": "테스트", - "expected": { - "data_filtered": true - } + "name": "테이블 확인", + "action": "verify_table" }, { "id": 5, - "phase": "CREATE", - "name": "[CREATE] 출고 등록 버튼 클릭", - "action": "click_if_exists", - "target": "button:has-text('등록'), button:has-text('출고 등록'), button:has-text('추가')", - "expected": { - "modal_or_page": true, - "title": "출고 등록" - } + "name": "검색 기능", + "action": "search", + "value": "테스트" }, { "id": 6, - "phase": "CREATE", - "name": "[CREATE] 출고 정보 입력", - "action": "click_if_exists", - "fields": [ - { - "name": "거래처", - "type": "select", - "value": "E2E_TEST_거래처" - }, - { - "name": "출고일", - "type": "date", - "value": "2026-02-05" - }, - { - "name": "품목", - "type": "select", - "value": "테스트품목" - }, - { - "name": "수량", - "type": "number", - "value": "50" - }, - { - "name": "메모", - "type": "text", - "value": "E2E 자동화 테스트 출고_{timestamp}" - } - ], - "note": "타임스탬프로 고유성 보장", - "target": "form, [role='dialog'], .modal" + "name": "검색 후 확인", + "action": "verify_detail", + "checks": ["visible_text:출고"] }, { "id": 7, - "phase": "CREATE", - "name": "[CREATE] 필수 검증 #2: 등록 저장", - "action": "click_if_exists", - "target": "button:has-text('저장'), button:has-text('등록')", - "verify": { - "url_maintained": true, - "no_error_page": true, - "api_call": "POST /api/v1/shipments", - "toast": "등록|완료|성공" - }, - "expected": "출고 등록 완료" - }, - { - "id": "7-modal-close", - "phase": "CREATE", - "name": "[CREATE] 모달 닫기 확인", - "action": "close_modal_if_open", - "expected": "모달 닫힘" + "name": "첫 번째 행 클릭", + "action": "click_first_row" }, { "id": 8, - "phase": "CREATE", - "name": "[CREATE] 등록 결과 확인", + "name": "상세 확인", "action": "verify_detail", - "search": "E2E 자동화 테스트 출고", - "expected": { - "row_exists": true, - "contains": [ - "E2E", - "50" - ] - } + "checks": ["visible_text:출고"] }, { "id": 9, - "phase": "READ", - "name": "[READ] 출고 상세 페이지 진입", - "action": "click_if_exists", - "target": "table tbody tr:has-text('E2E')", - "expected": { - "url_contains": "/outbound", - "visible": [ - "출고 상세", - "수정", - "삭제" - ] - } + "name": "모달 닫기", + "action": "close_modal_if_open" }, { "id": 10, - "phase": "READ", - "name": "[READ] 상세 정보 확인", - "action": "verify_detail", - "checks": [ - "수량: 50", - "메모: E2E 자동화 테스트" - ], - "expected": "입력한 데이터와 일치" - }, - { - "id": 11, - "phase": "UPDATE", - "name": "[UPDATE] 수정 모드 진입", + "name": "목록 복귀", "action": "click_if_exists", - "target": "button:has-text('수정')", - "expected": { - "url_contains": "mode=edit", - "fields_editable": true - } - }, - { - "id": 12, - "phase": "UPDATE", - "name": "[UPDATE] 수량 수정", - "action": "click_if_exists", - "target": "input[name*='quantity'], input[placeholder*='수량']", - "value": "60", - "clear": true - }, - { - "id": 13, - "phase": "UPDATE", - "name": "[UPDATE] 메모 수정", - "action": "click_if_exists", - "target": "textarea[name*='memo'], input[placeholder*='메모']", - "value": "E2E 수정된 출고 메모_{timestamp}", - "clear": true - }, - { - "id": 14, - "phase": "UPDATE", - "name": "[UPDATE] 필수 검증 #2: 수정 저장", - "action": "click_if_exists", - "target": "button:has-text('저장')", - "verify": { - "url_maintained": true, - "no_error_page": true, - "api_call": "PUT /api/v1/shipments/", - "toast": "수정|완료|성공" - }, - "expected": "수정 완료" - }, - { - "id": 15, - "phase": "UPDATE", - "name": "[UPDATE] 수정 결과 확인", - "action": "verify_detail", - "checks": [ - "수량: 60", - "메모: E2E 수정된 출고" - ], - "expected": "수정된 데이터 반영" - }, - { - "id": 16, - "phase": "DELETE", - "name": "[DELETE] 삭제 버튼 클릭", - "action": "click_if_exists", - "target": "button:has-text('삭제')", - "expected": { - "confirm_dialog": true, - "dialog_message": "삭제|정말" - } - }, - { - "id": 17, - "phase": "DELETE", - "name": "[DELETE] 필수 검증 #6: 삭제 확인", - "action": "click_if_exists", - "target": "button:has-text('확인'), button:has-text('삭제')", - "verify": { - "api_call": "DELETE /api/v1/shipments/", - "toast": "삭제|완료|성공", - "redirect": "/outbound" - }, - "expected": "삭제 완료 및 목록 복귀" - }, - { - "id": 18, - "phase": "DELETE", - "name": "[DELETE] 삭제 결과 확인", - "action": "verify_detail", - "search": "E2E 수정된 출고", - "expected": { - "row_exists": false, - "message": "테스트 출고가 목록에서 제거됨" - } + "target": "button:has-text('목록'), a:has-text('목록')" } - ], - "expectedAPIs": [ - { - "method": "GET", - "endpoint": "/api/v1/shipments", - "description": "출고 목록 조회" - }, - { - "method": "POST", - "endpoint": "/api/v1/shipments", - "description": "출고 등록" - }, - { - "method": "GET", - "endpoint": "/api/v1/shipments/{id}", - "description": "출고 상세 조회" - }, - { - "method": "PUT", - "endpoint": "/api/v1/shipments/{id}", - "description": "출고 수정" - }, - { - "method": "DELETE", - "endpoint": "/api/v1/shipments/{id}", - "description": "출고 삭제" - } - ], - "requiredVerifications": [ - { - "id": 2, - "name": "등록/저장 버튼", - "steps": [ - 7, - 14 - ], - "criteria": "API 호출 + 성공 토스트 + 데이터 반영" - }, - { - "id": 3, - "name": "검색/필터", - "steps": [ - 4 - ], - "criteria": "검색 기능 동작" - }, - { - "id": 5, - "name": "목업 페이지 감지", - "steps": [ - 2 - ], - "criteria": "출고 목록, 등록 버튼, 필터 존재" - }, - { - "id": 6, - "name": "삭제 기능", - "steps": [ - 16, - 17, - 18 - ], - "criteria": "DELETE API + 목록에서 제거" - } - ], - "rollbackPlan": { - "onCreateFail": "모달 닫기", - "onUpdateFail": "테스트 출고 수동 삭제 필요", - "onDeleteFail": "테스트 출고 수동 삭제 필요", - "cleanupRequired": "E2E_TEST_ 접두사 출고는 테스트 데이터" - } -} \ No newline at end of file + ] +}