Files
sam-scenarios/quality-inspection.json

139 lines
6.4 KiB
JSON
Raw Normal View History

{
"enabled": true,
"id": "quality-inspection",
"name": "제품검사관리 테스트",
"version": "2.0.0",
"screenshotPolicy": {
"captureOnFail": true,
"captureOnPass": false
},
"description": "품질관리 > 제품검사관리 메뉴의 목록/상세/검색 조회 테스트 (v2: CRUD→조회전용, validation 에러 방지)",
"baseUrl": "https://dev.codebridge-x.com",
"menuNavigation": {
"level1": "품질관리",
"level2": "제품검사관리",
"expectedUrl": "/quality/inspections",
"searchWithinParent": true,
"closeOtherMenus": true
},
"auth": { "username": "TestUser5", "password": "password123!" },
"steps": [
{
"id": 1,
"name": "메뉴 진입: 품질관리 > 제품검사관리",
"action": "menu_navigate",
"level1": "품질관리",
"level2": "제품검사관리",
"expected": { "url_contains": "/quality/inspections" }
},
{
"id": 2,
"name": "페이지 로드 대기",
"action": "wait",
"timeout": 3000
},
{
"id": 3,
"name": "URL 검증",
"action": "verify_url",
"expected": { "url_contains": "/quality/inspections" }
},
{
"id": 4,
"name": "목업 감지",
"action": "verify_not_mockup",
"checks": ["제품검사 목록 표시", "등록 버튼 존재"]
},
{
"id": 5,
"name": "테이블 로드 대기",
"action": "wait_for_table",
"timeout": 5000
},
{
"id": 6,
"name": "통계 카드 확인",
"action": "evaluate",
"script": "(() => { const cards = document.querySelectorAll('[class*=\"card\"], [class*=\"Card\"], [class*=\"stat\"]'); return JSON.stringify({ ok: true, info: 'Stats: ' + cards.length + ' cards' }); })()"
},
{
"id": 7,
"name": "테이블 구조 확인",
"action": "verify_table",
"checks": ["테이블 컬럼 확인"]
},
{
"id": 8,
"name": "필터/검색 존재 확인",
"action": "evaluate",
"script": "(() => { const selects = document.querySelectorAll('select, [role=\"combobox\"], button[class*=\"select\"]'); const inputs = document.querySelectorAll('input[type=\"search\"], input[placeholder*=\"검색\"]'); return JSON.stringify({ ok: true, info: 'filters=' + selects.length + ' search=' + inputs.length }); })()"
},
{
"id": 9,
"name": "[READ] 첫 번째 행 클릭 (상세)",
"phase": "READ",
"action": "click_first_row"
},
{
"id": 10,
"name": "[READ] 상세 대기",
"phase": "READ",
"action": "wait",
"timeout": 2000
},
{
"id": 11,
"name": "[READ] 상세 다이얼로그/페이지 확인",
"phase": "READ",
"action": "evaluate",
"script": "(()=>{const R={phase:'DETAIL_CHECK'};const dlg=document.querySelector('[role=\"dialog\"]');const isVis=el=>!!el&&el.getBoundingClientRect().width>0;if(isVis(dlg)){R.hasDialog=true;R.text=dlg.innerText?.substring(0,100);}else{R.hasDialog=false;R.url=window.location.href;R.bodyText=document.body.innerText?.substring(0,100);}R.ok=true;R.info=R.hasDialog?'pass: 상세 다이얼로그 열림':'pass: 상세 페이지 또는 모달 미사용';return JSON.stringify(R);})()"
},
{
"id": 12,
"name": "[READ] 모달 닫기",
"phase": "READ",
"action": "close_modal_if_open"
},
{
"id": 13,
"name": "[CREATE] 등록 다이얼로그 열기 (저장 안함)",
"phase": "CREATE",
"action": "evaluate",
"script": "(async()=>{const w=ms=>new Promise(r=>setTimeout(r,ms));const R={phase:'CREATE_CHECK'};const btn=Array.from(document.querySelectorAll('button')).find(b=>/등록|추가|신규/.test(b.innerText?.trim())&&b.offsetParent!==null&&!b.disabled);if(btn){btn.click();await w(1500);const dlg=document.querySelector('[role=\"dialog\"]');const isVis=el=>!!el&&el.getBoundingClientRect().width>0;R.dialogOpen=isVis(dlg);if(R.dialogOpen){const labels=Array.from(dlg.querySelectorAll('label')).map(l=>l.innerText?.trim()).filter(Boolean);R.formLabels=labels.slice(0,10);R.info='pass: 등록 폼 확인 (labels='+labels.length+')';}else{R.info='warn: 등록 다이얼로그 미표시';}}else{R.info='warn: 등록 버튼 미발견';}R.ok=true;return JSON.stringify(R);})()",
"timeout": 5000
},
{
"id": 14,
"name": "[CREATE] 등록 다이얼로그 닫기 (저장하지 않음)",
"phase": "CREATE",
"action": "evaluate",
"script": "(async()=>{const w=ms=>new Promise(r=>setTimeout(r,ms));const dlg=document.querySelector('[role=\"dialog\"]');const isVis=el=>!!el&&el.getBoundingClientRect().width>0;if(isVis(dlg)){const cancelBtn=Array.from(dlg.querySelectorAll('button')).find(b=>/취소|닫기|Close/.test(b.innerText?.trim()));if(cancelBtn){cancelBtn.click();await w(500);}else{document.dispatchEvent(new KeyboardEvent('keydown',{key:'Escape',bubbles:true}));await w(500);}}return JSON.stringify({ok:true,info:'pass: 등록 다이얼로그 닫힘 (데이터 저장 안함)'});})()"
},
{
"id": 15,
"name": "페이지네이션 확인",
"action": "evaluate",
"script": "(() => { const p = document.querySelector('[class*=\"pagination\"], [class*=\"Pagination\"], nav[aria-label*=\"page\"]'); const btns = Array.from(document.querySelectorAll('button')).filter(b => /^\\d+$/.test(b.innerText?.trim())); return JSON.stringify({ ok: true, info: p ? 'pagination found' : btns.length > 0 ? 'page buttons: ' + btns.length : 'no pagination (ok)' }); })()"
},
{
"id": 16,
"name": "[SUMMARY] API 호출 통계",
"action": "evaluate",
"script": "(()=>{const logs=window.__E2E__?.getApiLogs?.()?.logs||[];const quality=logs.filter(l=>l.url?.includes('quality')||l.url?.includes('inspection'));return JSON.stringify({ok:true,info:'API total='+logs.length+' quality='+quality.length+' success='+logs.filter(l=>l.status>=200&&l.status<300).length});})()"
}
],
"expectedAPIs": [
{ "method": "GET", "endpoint": "/api/v1/quality/inspections", "description": "제품검사 목록 조회" }
],
"rollbackPlan": {
"note": "조회 전용 테스트. 등록 다이얼로그는 열기만 하고 저장하지 않음. 데이터 변경 없음."
},
"knownIssues": [
{
"issue": "api/v1/inspections/calendar route not found",
"type": "frontend_bug",
"description": "프론트엔드가 페이지 로드 시 미구현 API 호출. E2E에서 방지 불가."
}
]
}