303 lines
11 KiB
JSON
303 lines
11 KiB
JSON
{
|
|
"id": "item-management",
|
|
"name": "품목관리 (Item Management)",
|
|
"screenshotPolicy": {
|
|
"onErrorOnly": true,
|
|
"captureOn": ["error", "fail", "timeout", "404", "500", "blocked"]
|
|
},
|
|
"description": "생산관리 - 품목관리 메뉴의 전체 기능 테스트: 품목 조회, 검색, 필터, 등록, 상세보기, 수정, 삭제",
|
|
"priority": "High",
|
|
"baseUrl": "https://dev.codebridge-x.com",
|
|
"menuNavigation": {
|
|
"level1": "생산관리",
|
|
"level2": "품목관리",
|
|
"expectedUrl": "/ko/production/screen-production",
|
|
"searchWithinParent": true,
|
|
"closeOtherMenus": true
|
|
},
|
|
"auth": {
|
|
"username": "TestUser5",
|
|
"password": "password123!"
|
|
},
|
|
"selectors": {
|
|
"statCard": ".card, [class*='stat'], [class*='summary'], [class*='kpi']",
|
|
"searchInput": "input[type='search'], input[type='text'][placeholder*='검색'], input[placeholder*='Search'], input[placeholder*='품목']",
|
|
"tabButtons": "button[role='tab'], [class*='tab'] button, [class*='filter'] button",
|
|
"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']",
|
|
"actionButtons": "button:has-text('상세'), button:has-text('수정'), button:has-text('삭제')",
|
|
"registerButton": "button:has-text('품목 등록'), button:has-text('등록'), button[class*='add']",
|
|
"saveButton": "button:has-text('저장'), button[type='submit']",
|
|
"cancelButton": "button:has-text('취소'), button:has-text('닫기')",
|
|
"toast": "[class*='toast'], [class*='Toast'], [role='alert'], [class*='notification']",
|
|
"modal": "[role='dialog'], [class*='modal'], [class*='Modal']",
|
|
"formField": "input:not([type='hidden']), textarea, select",
|
|
"combobox": "select, [role='combobox'], [class*='select'], [class*='dropdown']",
|
|
"pageTitle": "h1, h2, [class*='title'], [class*='Title']"
|
|
},
|
|
"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": "/production" }
|
|
},
|
|
{
|
|
"id": 2,
|
|
"name": "페이지 로드 및 404 확인",
|
|
"action": "evaluate",
|
|
"script": "(() => { const url = window.location.href; const text = document.body.innerText; return !text.includes('404') && !text.includes('Not Found') && (url.includes('production') || text.includes('품목')); })()"
|
|
},
|
|
{
|
|
"id": 3,
|
|
"name": "통계 카드 영역 존재 확인",
|
|
"action": "verify_element",
|
|
"target": "statCard"
|
|
},
|
|
{
|
|
"id": 4,
|
|
"name": "통계 카드 숫자 데이터 확인",
|
|
"action": "evaluate",
|
|
"script": "(() => { const cards = document.querySelectorAll('.card, [class*=\"stat\"]'); let hasNum = false; cards.forEach(c => { if (/\\d+/.test(c.innerText)) hasNum = true; }); return hasNum || document.body.innerText.includes('전체'); })()"
|
|
},
|
|
{
|
|
"id": 5,
|
|
"name": "품목 등록 버튼 존재 확인",
|
|
"action": "verify_element",
|
|
"target": "registerButton"
|
|
},
|
|
{
|
|
"id": 6,
|
|
"name": "검색 입력 필드 존재 확인",
|
|
"action": "evaluate",
|
|
"script": "(() => { const hasInput = document.querySelector('input[type=\"search\"], input[placeholder*=\"검색\"], input[placeholder*=\"품목\"]'); return hasInput || document.body.innerText.includes('검색'); })()"
|
|
},
|
|
{
|
|
"id": 7,
|
|
"name": "탭/필터 버튼 존재 확인",
|
|
"action": "evaluate",
|
|
"script": "(() => { const text = document.body.innerText; return text.includes('전체') && (text.includes('제품') || text.includes('부품') || text.includes('소모품')); })()"
|
|
},
|
|
{
|
|
"id": 8,
|
|
"name": "데이터 테이블 헤더 확인",
|
|
"action": "evaluate",
|
|
"script": "(() => { const th = document.querySelectorAll('table th, thead th, [role=\"columnheader\"]'); return th.length > 0 || document.body.innerText.includes('품목코드'); })()"
|
|
},
|
|
{
|
|
"id": 9,
|
|
"name": "데이터 행 존재 확인",
|
|
"action": "evaluate",
|
|
"script": "(() => { const rows = document.querySelectorAll('table tbody tr, [role=\"row\"]:not(:first-child)'); return rows.length > 0 || document.body.innerText.includes('데이터가 없습니다'); })()"
|
|
},
|
|
{
|
|
"id": 10,
|
|
"name": "페이지네이션 존재 확인",
|
|
"action": "evaluate",
|
|
"script": "(() => { const pag = document.querySelector('[class*=\"pagination\"], [class*=\"Pagination\"], nav[aria-label*=\"page\"]'); const hasPageNum = document.body.innerText.match(/\\d+\\s*-\\s*\\d+|페이지|Page/); return pag || hasPageNum; })()"
|
|
},
|
|
{
|
|
"id": 11,
|
|
"phase": "FILTER",
|
|
"name": "[FILTER] 검색 기능 테스트 - 검색어 입력",
|
|
"action": "evaluate",
|
|
"script": "(() => { const input = document.querySelector('input[type=\"search\"], input[placeholder*=\"검색\"], input[placeholder*=\"품목\"]'); if (input) { input.value = 'CS-001'; input.dispatchEvent(new Event('input', {bubbles:true})); return true; } return document.body.innerText.includes('품목'); })()"
|
|
},
|
|
{
|
|
"id": 12,
|
|
"phase": "FILTER",
|
|
"name": "[FILTER] 검색 결과 대기",
|
|
"action": "wait",
|
|
"duration": 1500
|
|
},
|
|
{
|
|
"id": 13,
|
|
"phase": "FILTER",
|
|
"name": "[FILTER] 검색 결과 테이블 확인",
|
|
"action": "evaluate",
|
|
"script": "(() => { const rows = document.querySelectorAll('table tbody tr'); return rows.length >= 0; })()"
|
|
},
|
|
{
|
|
"id": 14,
|
|
"phase": "FILTER",
|
|
"name": "[FILTER] 검색 초기화 - 검색창 클리어",
|
|
"action": "evaluate",
|
|
"script": "(() => { const input = document.querySelector('input[type=\"search\"], input[placeholder*=\"검색\"], input[placeholder*=\"품목\"]'); if (input) { input.value = ''; input.dispatchEvent(new Event('input', {bubbles:true})); return true; } return true; })()"
|
|
},
|
|
{
|
|
"id": 15,
|
|
"phase": "FILTER",
|
|
"name": "[FILTER] 제품 탭 클릭",
|
|
"action": "click_if_exists",
|
|
"target": "button:has-text('제품'), [class*='tab']:has-text('제품')"
|
|
},
|
|
{
|
|
"id": 16,
|
|
"phase": "FILTER",
|
|
"name": "[FILTER] 필터 결과 대기",
|
|
"action": "wait",
|
|
"duration": 1000
|
|
},
|
|
{
|
|
"id": 17,
|
|
"phase": "FILTER",
|
|
"name": "[FILTER] 전체 탭 클릭 (초기화)",
|
|
"action": "click_if_exists",
|
|
"target": "button:has-text('전체'), [class*='tab']:has-text('전체')"
|
|
},
|
|
{
|
|
"id": 18,
|
|
"name": "페이지네이션 - 2페이지 이동",
|
|
"action": "click_if_exists",
|
|
"target": "button:has-text('2'), [class*='pagination'] button:has-text('2'), a:has-text('2')"
|
|
},
|
|
{
|
|
"id": 19,
|
|
"name": "2페이지 로드 대기",
|
|
"action": "wait",
|
|
"duration": 1000
|
|
},
|
|
{
|
|
"id": 20,
|
|
"name": "1페이지로 복귀",
|
|
"action": "click_if_exists",
|
|
"target": "button:has-text('1'), [class*='pagination'] button:has-text('1'), a:has-text('1')"
|
|
},
|
|
{
|
|
"id": 21,
|
|
"phase": "CREATE",
|
|
"name": "[CREATE] 품목 등록 버튼 클릭",
|
|
"action": "click",
|
|
"target": "registerButton"
|
|
},
|
|
{
|
|
"id": 22,
|
|
"phase": "CREATE",
|
|
"name": "[CREATE] 등록 페이지/모달 로드 대기",
|
|
"action": "wait",
|
|
"duration": 1500
|
|
},
|
|
{
|
|
"id": 23,
|
|
"phase": "CREATE",
|
|
"name": "[CREATE] 등록 폼 존재 확인",
|
|
"action": "evaluate",
|
|
"script": "(() => { const hasForm = document.querySelectorAll('input, select, textarea').length > 0; const hasText = document.body.innerText.includes('등록') || document.body.innerText.includes('품목'); return hasForm || hasText; })()"
|
|
},
|
|
{
|
|
"id": 24,
|
|
"phase": "CREATE",
|
|
"name": "[CREATE] 품목 유형 선택 영역 확인",
|
|
"action": "verify_element",
|
|
"target": "combobox"
|
|
},
|
|
{
|
|
"id": 25,
|
|
"phase": "CREATE",
|
|
"name": "[CREATE] 품목 유형 드롭다운 클릭",
|
|
"action": "click_if_exists",
|
|
"target": "select, [class*='select'], [role='combobox']"
|
|
},
|
|
{
|
|
"id": 26,
|
|
"phase": "CREATE",
|
|
"name": "[CREATE] 제품 옵션 선택",
|
|
"action": "click_if_exists",
|
|
"target": "option:has-text('제품'), [role='option']:has-text('제품'), li:has-text('제품')"
|
|
},
|
|
{
|
|
"id": 27,
|
|
"phase": "CREATE",
|
|
"name": "[CREATE] 필수 입력 필드 존재 확인",
|
|
"action": "verify_element",
|
|
"target": "formField"
|
|
},
|
|
{
|
|
"id": 28,
|
|
"phase": "CREATE",
|
|
"name": "[CREATE] 취소 버튼 클릭 (등록 취소)",
|
|
"action": "click_if_exists",
|
|
"target": "cancelButton"
|
|
},
|
|
{
|
|
"id": 29,
|
|
"phase": "CREATE",
|
|
"name": "[CREATE] 목록 페이지 복귀 대기",
|
|
"action": "wait",
|
|
"duration": 1000
|
|
},
|
|
{
|
|
"id": 30,
|
|
"phase": "READ",
|
|
"name": "[READ] 첫 번째 행 상세보기 버튼 클릭",
|
|
"action": "click_if_exists",
|
|
"target": "button:has-text('상세'), button:has-text('보기'), table tbody tr:first-child button"
|
|
},
|
|
{
|
|
"id": 31,
|
|
"phase": "READ",
|
|
"name": "[READ] 상세 정보 로드 대기",
|
|
"action": "wait",
|
|
"duration": 1000
|
|
},
|
|
{
|
|
"id": 32,
|
|
"phase": "READ",
|
|
"name": "[READ] 상세 정보 표시 확인",
|
|
"action": "evaluate",
|
|
"script": "(() => { const text = document.body.innerText; return text.includes('품목') || text.includes('코드') || text.includes('상세') || document.querySelector('[role=\"dialog\"]'); })()"
|
|
},
|
|
{
|
|
"id": 33,
|
|
"phase": "READ",
|
|
"name": "[READ] 상세 모달/페이지 닫기",
|
|
"action": "click_if_exists",
|
|
"target": "button:has-text('닫기'), button:has-text('Close'), [class*='close'], button[aria-label='Close']"
|
|
},
|
|
{
|
|
"id": 34,
|
|
"phase": "READ",
|
|
"name": "[READ] 목록 페이지 복귀 대기",
|
|
"action": "wait",
|
|
"duration": 500
|
|
},
|
|
{
|
|
"id": 35,
|
|
"name": "테이블 구조 최종 확인",
|
|
"action": "verify_element",
|
|
"target": "table, [role='grid'], [class*='table']"
|
|
},
|
|
{
|
|
"id": 36,
|
|
"name": "액션 버튼 존재 확인",
|
|
"action": "evaluate",
|
|
"script": "(() => { const text = document.body.innerText; return text.includes('상세') || text.includes('수정') || text.includes('삭제'); })()"
|
|
},
|
|
{
|
|
"id": 37,
|
|
"name": "페이지 정상 동작 최종 확인",
|
|
"action": "evaluate",
|
|
"script": "(() => { const text = document.body.innerText; return text.includes('품목') || text.includes('전체') || text.includes('제품') || text.includes('부품'); })()"
|
|
}
|
|
],
|
|
"expectedAPIs": [
|
|
{ "method": "GET", "endpoint": "/api/items", "description": "품목 목록 조회" }
|
|
],
|
|
"rollbackPlan": {
|
|
"note": "테스트 데이터 생성하지 않음 - 조회 및 UI 검증만 수행"
|
|
}
|
|
}
|