{ "id": "quality-performance-report", "name": "실적신고관리 테스트", "version": "2.0.0", "enabled": true, "screenshotPolicy": { "captureOnFail": true, "captureOnPass": false }, "description": "품질관리 > 실적신고관리 메뉴의 페이지 로드, 테이블, 필터 검증 (READ-only. 백엔드 API 전체 미구현 - Mock 동작)", "baseUrl": "https://dev.codebridge-x.com", "menuNavigation": { "level1": "품질관리", "level2": "실적신고관리", "expectedUrl": "/quality/performance-report", "searchWithinParent": true, "closeOtherMenus": true }, "auth": { "username": "TestUser5", "password": "password123!" }, "steps": [ { "id": 1, "name": "메뉴 진입: 품질관리 > 실적신고관리", "action": "menu_navigate", "level1": "품질관리", "level2": "실적신고관리", "expected": { "url_contains": "/quality" } }, { "id": 2, "name": "페이지 로드 대기", "action": "wait", "timeout": 3000 }, { "id": 3, "name": "URL 검증", "action": "verify_url", "expected": { "url_contains": "/quality/performance-report" } }, { "id": 4, "name": "목업 감지", "action": "verify_not_mockup", "checks": ["실적 또는 신고 텍스트 표시", "버튼 동작 가능"] }, { "id": 5, "name": "테이블 로드 대기", "action": "wait_for_table", "timeout": 10000 }, { "id": 6, "name": "통계 카드 확인", "action": "evaluate", "script": "(() => { const cards = document.querySelectorAll('[class*=\"card\"], [class*=\"Card\"], [class*=\"stat\"], [class*=\"summary\"]'); return cards.length > 0 ? 'pass: Stats cards=' + cards.length : 'warn: No stat cards'; })()" }, { "id": 7, "name": "테이블 컬럼 구조 확인", "action": "evaluate", "script": "(() => { const ths = Array.from(document.querySelectorAll('table thead th, table th, [role=\"columnheader\"]')); const cols = ths.map(t => t.innerText?.trim()).filter(Boolean); return cols.length > 0 ? 'pass: columns=' + cols.length + ' [' + cols.join(', ') + ']' : 'warn: No table headers'; })()" }, { "id": 8, "name": "테이블 데이터 행 확인", "action": "evaluate", "script": "(() => { const rows = document.querySelectorAll('table tbody tr'); const vis = Array.from(rows).filter(r => r.offsetParent !== null); return vis.length > 0 ? 'pass: ' + vis.length + ' rows' : 'warn: No data rows'; })()" }, { "id": 9, "name": "필터/탭 UI 확인", "action": "evaluate", "script": "(() => { const selects = document.querySelectorAll('select, [role=\"combobox\"], button[class*=\"Select\"]'); const tabs = document.querySelectorAll('button[role=\"tab\"]'); const searchInputs = document.querySelectorAll('input[type=\"search\"], input[placeholder*=\"검색\"]'); return 'pass: filters=' + selects.length + ' tabs=' + tabs.length + ' search=' + searchInputs.length; })()" }, { "id": 10, "name": "액션 버튼 확인 (클릭하지 않음)", "action": "evaluate", "script": "(() => { const btns = Array.from(document.querySelectorAll('button')).filter(b => b.offsetParent !== null); const actionBtns = btns.filter(b => /등록|확정|배포|신규|추가/.test(b.innerText?.trim())); return 'pass: action buttons=' + actionBtns.length + (actionBtns.length > 0 ? ' [' + actionBtns.map(b => b.innerText.trim()).join(', ') + ']' : ''); })()" }, { "id": 11, "name": "페이지네이션 확인", "action": "evaluate", "script": "(() => { const p = document.querySelector('[class*=\"pagination\"], [class*=\"Pagination\"], nav[aria-label*=\"page\"]'); return p ? 'pass: Pagination found' : 'No pagination (ok)'; })()" }, { "id": 12, "name": "[SUMMARY] API 호출 통계", "action": "evaluate", "script": "(() => { const logs = window.__E2E__ ? window.__E2E__.getApiLogs().logs : (window.__API_LOGS__ || []); const perfApi = logs.filter(l => l.url?.includes('performance')); const failedApis = logs.filter(l => l.status >= 400); return 'pass: API total=' + logs.length + ' performance=' + perfApi.length + ' failed=' + failedApis.length; })()" } ], "knownIssues": [ { "issue": "GET /api/v1/performance-reports → 404", "reason": "백엔드 API 전체 미구현. 프론트엔드가 USE_MOCK_FALLBACK으로 Mock 데이터 표시", "severity": "medium", "action": "백엔드에 performance-reports 라우트 그룹 구현 필요 (7개 엔드포인트)" }, { "issue": "GET /api/v1/performance-reports/stats → 404", "reason": "동일 - 통계 엔드포인트 미구현", "severity": "medium" } ], "rollbackPlan": { "note": "READ-only 테스트. 데이터 변경 없음." } }