diff --git a/board-test.json b/board-test.json index 433a1ed..1fc8b8f 100644 --- a/board-test.json +++ b/board-test.json @@ -5,17 +5,25 @@ "onErrorOnly": true, "captureOn": ["error", "fail", "timeout", "404", "500", "blocked"] }, - "description": "게시판 > 게시판 테스트 메뉴의 테스트 게시판 기능 테스트", + "description": "게시판 > 게시판 테스트 메뉴의 테스트 게시판 CRUD 기능 테스트", "baseUrl": "https://dev.codebridge-x.com", "menuNavigation": { "level1": "게시판", "level2": "게시판 테스트", - "expectedUrl": "/boards/board_" + "expectedUrl": "/boards/board_", + "searchWithinParent": true, + "closeOtherMenus": true }, "auth": { "username": "TestUser5", "password": "password123!" }, + "testData": { + "create": { + "title": "E2E_TEST_게시글_{timestamp}", + "content": "E2E 자동화 테스트용 게시글입니다." + } + }, "steps": [ { "id": 1, @@ -34,27 +42,215 @@ "action": "verify_not_mockup", "checks": [ "게시글 목록 표시", - "글쓰기 버튼 존재" + "글쓰기 버튼 존재", + "검색 기능 존재" ], "expected": "정상 페이지 (목업 아님)" }, { "id": 3, - "name": "게시판 기능 확인", + "name": "게시판 테이블 구조 확인", + "action": "verify_table", + "checks": [ + "제목 컬럼", + "작성자 컬럼", + "작성일 컬럼", + "조회수 컬럼" + ], + "expected": "게시판 테이블 표시" + }, + { + "id": 4, + "name": "기존 게시글 확인", "action": "verify_elements", "checks": [ - "게시글 테이블", - "검색 기능" + "등록된 게시글 존재 또는 등록된 게시글 없음" ], - "expected": "게시판 기능 표시" + "expected": "게시글 목록 상태 확인" + }, + { + "id": 5, + "phase": "CREATE", + "name": "[CREATE] 글쓰기 버튼 클릭", + "action": "click", + "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", + "target": "button:has-text('저장'), button:has-text('등록'), button:has-text('확인')", + "critical": true, + "verify": { + "url_change": true, + "no_error_page": true, + "api_call": "POST /api/v1/boards", + "toast": "등록|저장|완료|성공" + }, + "expected": "게시글 등록 완료" + }, + { + "id": 9, + "phase": "READ", + "name": "[READ] 등록된 게시글 검색", + "action": "fill", + "target": "input[type='search'], input[placeholder*='검색']", + "value": "E2E_TEST_게시글", + "submit": true + }, + { + "id": 10, + "phase": "READ", + "name": "[READ] 등록된 게시글 확인", + "action": "verify_detail", + "checks": [ + "E2E_TEST_게시글 목록에 표시" + ], + "expected": "등록된 게시글 확인" + }, + { + "id": 11, + "phase": "READ", + "name": "[READ] 게시글 상세 조회", + "action": "click", + "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", + "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", + "target": "button:has-text('저장'), button:has-text('확인')", + "verify": { + "api_call": "PUT /api/v1/boards", + "toast": "수정|저장|완료|성공" + }, + "expected": "게시글 수정 완료" + }, + { + "id": 16, + "phase": "DELETE", + "name": "[DELETE] 게시글 삭제", + "action": "click", + "target": "button:has-text('삭제'), button:has-text('제거')", + "expected": { + "confirm_dialog": true + } + }, + { + "id": 17, + "phase": "DELETE", + "name": "[DELETE] 삭제 확인", + "action": "click", + "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": "게시판 기능 확인" + "criteria": "게시글 목록, 글쓰기 버튼, 검색 기능 존재" } - ] + ], + "rollbackPlan": { + "onCreateFail": "작성 페이지에서 뒤로가기", + "onUpdateFail": "페이지 새로고침 후 재시도", + "onDeleteFail": "수동 삭제 필요", + "cleanupRequired": "E2E_TEST_게시글* 패턴 데이터 삭제" + } } diff --git a/comprehensive-analysis.json b/comprehensive-analysis.json index ecd55b9..c5ece78 100644 --- a/comprehensive-analysis.json +++ b/comprehensive-analysis.json @@ -5,269 +5,255 @@ "onErrorOnly": true, "captureOn": ["error", "fail", "timeout", "404", "500", "blocked"] }, - "description": "리포트 > 종합분석 페이지의 CEO 대시보드 조회 및 필터링 기능을 테스트하는 E2E 테스트", + "description": "리포트 > 종합분석 메뉴의 CEO 대시보드 조회 및 필터링 기능 테스트", "baseUrl": "https://dev.codebridge-x.com", - "url": "/report/comprehensive", "menuNavigation": { "level1": "리포트", "level2": "종합분석", - "expectedUrl": "/report/comprehensive" + "expectedUrl": "/report/comprehensive", + "searchWithinParent": true, + "closeOtherMenus": true }, - "navigation": { - "targetUrl": "/reports/comprehensive-analysis", - "urlPattern": "/reports/comprehensive-analysis|/report/comprehensive", - "menuHints": ["종합분석", "리포트", "경영분석"] + "auth": { + "username": "TestUser5", + "password": "password123!" }, - "menuNavigationEnhanced": { - "strategy": "scroll-and-search", - "sidebar": { - "scrollContainer": ".sidebar-scroll", - "scrollStep": 200, - "maxScrollAttempts": 5, - "waitAfterScroll": 300 - }, - "level1": { - "text": "리포트", - "expandable": true, - "waitAfterClick": 500 - }, - "level2": { - "text": "종합분석", - "waitAfterClick": 300 - }, - "fallbackUrl": "/report/comprehensive", - "expectedUrl": "/report/comprehensive" - }, - "timeout": 90000, - "tags": ["report", "dashboard", "read-only"], - - "login": { - "url": "https://dev.codebridge-x.com/login", - "credentials": { - "id": "TestUser5", - "password": "password123!" - }, - "successIndicator": "대시보드" - }, - "steps": [ { - "id": "step-0", - "name": "사이드바 메뉴 전체 펼치기", - "description": "모두 펼치기 버튼을 클릭하여 전체 메뉴를 펼친 후 메뉴 탐색 준비", - "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": "step-1", - "name": "리포트 메뉴 진입", - "description": "리포트 > 종합분석 메뉴로 이동", - "actions": [ - { - "type": "scrollAndFind", - "container": ".sidebar-scroll", - "target": "리포트", - "scrollStep": 200, - "maxAttempts": 5 - }, - { "type": "click", "target": "리포트" }, - { "type": "wait", "duration": 500 }, - { "type": "click", "target": "종합분석" } - ], - "expect": { - "url": "/report/comprehensive", + "id": 1, + "name": "메뉴 진입: 리포트 > 종합분석", + "action": "menu_navigate", + "level1": "리포트", + "level2": "종합분석", + "expected": { + "url_contains": "/report/comprehensive", "visible": ["CEO 대시보드", "전사 경영 현황"] - }, - "fallback": { - "type": "navigate", - "url": "/report/comprehensive" } }, { - "id": "step-2", - "name": "페이지 구조 확인", - "description": "대시보드 위젯 및 버튼 확인", - "verify": { - "visible": ["CEO 대시보드", "일일보고서", "경영분석"], - "widgets": ["견적", "수주", "생산", "검사", "출고예정", "출고완료"] - } + "id": 2, + "name": "필수 검증 #5: 목업 페이지 감지", + "action": "verify_not_mockup", + "checks": [ + "대시보드 위젯 표시", + "실시간 데이터 표시", + "필터 옵션 존재" + ], + "expected": "정상 페이지 (목업 아님)" }, { - "id": "step-3", + "id": 3, "name": "프로세스 현황 위젯 확인", - "description": "전체 업무 프로세스 현황 위젯 확인", - "verify": { - "visible": ["모든 프로세스 현황", "견적", "수주", "생산", "검사", "출고예정", "출고완료"] - } + "action": "verify_elements", + "checks": [ + "견적 위젯", + "수주 위젯", + "생산 위젯", + "검사 위젯", + "출고예정 위젯", + "출고완료 위젯" + ], + "expected": "프로세스 현황 위젯 표시" }, { - "id": "step-4", + "id": 4, "name": "매출 지표 확인", - "description": "매출 관련 지표 위젯 확인", - "verify": { - "visible": ["당일 출하매출", "매출총이익률", "일일 순손익", "일별 매출", "월별 매출", "연간 매출"] - } + "action": "verify_elements", + "checks": [ + "당일 출하매출", + "매출총이익률", + "일일 순손익" + ], + "expected": "매출 지표 표시" }, { - "id": "step-5", + "id": 5, + "name": "매출 차트 확인", + "action": "verify_elements", + "checks": [ + "일별 매출 차트", + "월별 매출 차트", + "연간 매출 차트" + ], + "expected": "매출 차트 표시" + }, + { + "id": 6, "name": "미수금 현황 확인", - "description": "미수금 관련 위젯 확인", - "verify": { - "visible": ["총 미수금", "연체", "거래처별 미수금"] - } + "action": "verify_elements", + "checks": [ + "총 미수금", + "연체 금액", + "거래처별 미수금" + ], + "expected": "미수금 현황 표시" }, { - "id": "step-6", + "id": 7, "name": "재고 현황 확인", - "description": "재고 관련 위젯 확인", - "verify": { - "visible": ["재고 총액", "재고 회전율", "재고 부족 품목"] - } - }, - { - "id": "step-7", - "name": "캘린더 필터 테스트", - "description": "캘린더 필터 옵션 동작 확인", - "actions": [ - { "type": "click", "target": "필터 옵션" }, - { "type": "wait", "duration": 300 } + "action": "verify_elements", + "checks": [ + "재고 총액", + "재고 회전율", + "재고 부족 품목" ], - "expect": { - "visible": ["입고", "출고", "자재", "일정", "휴가", "출장"] - } + "expected": "재고 현황 표시" }, { - "id": "step-8", - "name": "필수 검증 #3: 필터 선택 테스트", - "description": "캘린더 필터 선택 동작 확인", - "actions": [ - { "type": "click", "target": "입고" }, - { "type": "wait", "duration": 300 } + "id": 8, + "phase": "FILTER", + "name": "[FILTER] 캘린더 필터 옵션 클릭", + "action": "click", + "target": "button:has-text('필터'), [class*='filter-option'], [class*='calendar-filter']", + "expected": "필터 옵션 열림" + }, + { + "id": 9, + "phase": "FILTER", + "name": "[FILTER] 필터 항목 확인", + "action": "verify_elements", + "checks": [ + "입고 필터", + "출고 필터", + "자재 필터", + "일정 필터", + "휴가 필터", + "출장 필터" ], - "expect": { - "filterApplied": true - } + "expected": "필터 항목 표시" }, { - "id": "step-9", + "id": 10, + "phase": "FILTER", + "name": "[FILTER] 필터 선택 테스트", + "action": "click", + "target": "label:has-text('입고'), input[value='입고']", + "expected": "필터 선택됨" + }, + { + "id": 11, + "phase": "FILTER", + "name": "[FILTER] 필터 적용 확인", + "action": "verify_detail", + "checks": [ + "선택한 필터에 따른 데이터 표시" + ], + "expected": "필터 동작 확인" + }, + { + "id": 12, "name": "인력 현황 확인", - "description": "출근율 및 결근 현황 위젯 확인", - "verify": { - "visible": ["일일 출근율", "결근", "지각"] - } + "action": "verify_elements", + "checks": [ + "일일 출근율", + "결근 현황", + "지각 현황" + ], + "expected": "인력 현황 표시" }, { - "id": "step-10", + "id": 13, "name": "품질검사 결과 확인", - "description": "품질검사 결과 위젯 확인", - "verify": { - "visible": ["품질검사 결과", "적합률", "부적합률"] - } + "action": "verify_elements", + "checks": [ + "품질검사 결과", + "적합률", + "부적합률" + ], + "expected": "품질검사 결과 표시" }, { - "id": "step-11", + "id": 14, "name": "승인 대기 품의서 확인", - "description": "승인 대기 중인 품의서 위젯 확인", - "verify": { - "visible": ["승인 대기 중인 품의서", "구매품의", "투자품의", "인사품의"] - } + "action": "verify_elements", + "checks": [ + "승인 대기 품의서", + "구매품의", + "투자품의" + ], + "expected": "승인 대기 품의서 표시" }, { - "id": "step-12", + "id": 15, "name": "휴가/출장 현황 확인", - "description": "휴가 및 출장 현황 위젯 확인", - "verify": { - "visible": ["휴가/출장 현황", "휴가 현황", "출장 현황", "부서별 현황"] - } + "action": "verify_elements", + "checks": [ + "휴가 현황", + "출장 현황", + "부서별 현황" + ], + "expected": "휴가/출장 현황 표시" }, { - "id": "step-13", + "id": 16, "name": "TOP 5 고객 매출 확인", - "description": "TOP 5 고객별 매출 현황 위젯 확인", - "verify": { - "visible": ["TOP 5 고객별 매출 현황"] - } + "action": "verify_elements", + "checks": [ + "TOP 5 고객별 매출 현황" + ], + "expected": "TOP 5 고객 매출 표시" }, { - "id": "step-14", + "id": 17, "name": "일일보고서 버튼 확인", - "description": "일일보고서 버튼 존재 확인", - "verify": { - "buttonExists": "일일보고서" - } + "action": "verify_elements", + "checks": [ + "일일보고서 버튼 존재" + ], + "expected": "일일보고서 버튼 표시" }, { - "id": "step-15", + "id": 18, "name": "경영분석 버튼 확인", - "description": "경영분석 버튼 존재 확인", - "verify": { - "buttonExists": "경영분석" - } + "action": "verify_elements", + "checks": [ + "경영분석 버튼 존재" + ], + "expected": "경영분석 버튼 표시" } ], - - "assertions": [ + "expectedAPIs": [ { - "type": "url", - "expected": "/report/comprehensive", - "message": "종합분석 페이지에 머물러야 함" + "method": "GET", + "endpoint": "/api/v1/reports/comprehensive", + "description": "종합분석 데이터 조회" }, { - "type": "elementExists", - "selector": "text=CEO 대시보드", - "message": "CEO 대시보드 제목이 표시되어야 함" + "method": "GET", + "endpoint": "/api/v1/reports/process-status", + "description": "프로세스 현황 조회" + }, + { + "method": "GET", + "endpoint": "/api/v1/reports/sales-summary", + "description": "매출 요약 조회" + }, + { + "method": "GET", + "endpoint": "/api/v1/reports/receivables", + "description": "미수금 현황 조회" + }, + { + "method": "GET", + "endpoint": "/api/v1/reports/inventory", + "description": "재고 현황 조회" } ], - - "mandatoryVerifications": { - "description": "E2E_TEST_CONFIG.md 기준 필수 검증 항목", - "items": [ - { - "id": 3, - "name": "검색/필터", - "trigger": "캘린더 필터", - "verification": "필터 적용 확인", - "failCondition": "필터 미동작" - }, - { - "id": 5, - "name": "목업/미완성 페이지 감지", - "trigger": "페이지 로드 시", - "verification": "실제 데이터 표시 + 동작하는 위젯 확인", - "failCondition": "더미 데이터만 표시, 버튼 미동작" - } - ] - }, - - "notes": { - "testScope": "CEO 대시보드 조회 및 필터링 테스트", - "pageType": "조회 전용 대시보드 (실시간 데이터 표시)", - "dashboardWidgets": [ - "모든 프로세스 현황 (견적, 수주, 생산, 검사, 출고예정, 출고완료)", - "스마트 워크플로우 캘린더", - "매출 지표 (당일, 월별, 연간)", - "미수금 현황", - "현금 흐름", - "재고 현황", - "차량별 가동률", - "출근율/결근 현황", - "품질검사 결과", - "승인 대기 품의서", - "휴가/출장 현황", - "TOP 5 고객별 매출" - ], - "filterOptions": ["입고", "출고", "자재", "일정", "휴가", "출장"], - "buttons": ["일일보고서", "경영분석"], - "prerequisites": "로그인된 사용자" + "requiredVerifications": [ + { + "id": 3, + "name": "검색/필터", + "steps": [8, 9, 10, 11], + "criteria": "캘린더 필터 동작" + }, + { + "id": 5, + "name": "목업 페이지 감지", + "steps": [2], + "criteria": "대시보드 위젯, 실시간 데이터, 필터 옵션 존재" + } + ], + "rollbackPlan": { + "note": "조회 전용 대시보드로 데이터 변경 없음" } }