Files
sam-scenarios/detail-roundtrip-acc.json

190 lines
20 KiB
JSON
Raw Normal View History

{
"id": "detail-roundtrip-acc",
"name": "상세 조회 왕복 검증: 회계",
"version": "1.0.0",
"auth": {
"role": "admin"
},
"menuNavigation": {
"level1": "회계관리",
"level2": "거래처관리"
},
"screenshotPolicy": {
"captureOnFail": true,
"captureOnPass": false
},
"steps": [
{
"id": 1,
"name": "[회계관리 > 거래처관리] 페이지 로드 대기",
"action": "wait",
"timeout": 3000
},
{
"id": 2,
"name": "[회계관리 > 거래처관리] 테이블 로드 대기",
"action": "wait_for_table",
"timeout": 5000
},
{
"id": 3,
"name": "[회계관리 > 거래처관리] 테이블 상태 캡처",
"action": "evaluate",
"script": "(async()=>{const w=ms=>new Promise(r=>setTimeout(r,ms));const R={phase:'CAPTURE'};const rows=Array.from(document.querySelectorAll('table tbody tr')).filter(r=>r.offsetParent!==null);R.rowCount=rows.length;if(rows.length===0){R.warn='테이블에 데이터 없음 - 상세 조회 불가';R.ok=true;return JSON.stringify(R);}const testRow=rows.find(r=>r.innerText?.includes('E2E_TEST_'));const firstRow=testRow||rows[0];R.usedTestRow=!!testRow;const cells=Array.from(firstRow.querySelectorAll('td'));const cellTexts=cells.map(c=>c.innerText?.trim().substring(0,50)).filter(t=>t.length>0);R.firstRowTexts=cellTexts;const style=window.getComputedStyle(firstRow);R.hasCursor=style.cursor==='pointer';R.listUrl=window.location.href;window.__CAPTURED__={rowCount:rows.length,firstRowTexts:cellTexts,listUrl:window.location.href};R.ok=true;return JSON.stringify(R);})()",
"timeout": 10000,
"phase": "CAPTURE"
},
{
"id": 4,
"name": "[회계관리 > 거래처관리] 첫 행 클릭 → 상세 이동",
"action": "evaluate",
"script": "(async()=>{const w=ms=>new Promise(r=>setTimeout(r,ms));const R={phase:'CLICK_ROW'};const rows=Array.from(document.querySelectorAll('table tbody tr')).filter(r=>r.offsetParent!==null);if(rows.length===0){R.error='행 없음';R.ok=false;return JSON.stringify(R);}const testRow=rows.find(r=>r.innerText?.includes('E2E_TEST_'));const firstRow=testRow||rows[0];R.usedTestRow=!!testRow;const targetCell=firstRow.querySelector('td:nth-child(2)')||firstRow.querySelector('td');if(!targetCell){R.error='클릭할 셀 없음';R.ok=false;return JSON.stringify(R);}R.clickedText=targetCell.innerText?.trim().substring(0,30);R.urlBefore=window.location.href;targetCell.click();await w(500);if(window.location.href===R.urlBefore){ const link=firstRow.querySelector('a[href]'); if(link){link.click();await w(500);}}let waited=0;while(window.location.href===R.urlBefore&&waited<5000){await w(300);waited+=300;}R.urlAfter=window.location.href;R.urlChanged=R.urlAfter!==R.urlBefore;if(!R.urlChanged){R.warn='행 클릭 후 URL 변경 없음 - 모달 또는 인라인 상세일 수 있음';R.ok=true;return JSON.stringify(R);}R.ok=true;return JSON.stringify(R);})()",
"timeout": 10000,
"phase": "CLICK_ROW"
},
{
"id": 5,
"name": "[회계관리 > 거래처관리] 상세 페이지 데이터 검증",
"action": "evaluate",
"script": "(async()=>{const w=ms=>new Promise(r=>setTimeout(r,ms));const R={phase:'VERIFY_DETAIL'};await w(1500);R.currentUrl=window.location.href;const idPattern=new RegExp('[/][0-9a-f]{8,}|[/][0-9]+[?]|[/][0-9]+$');R.hasIdInUrl=idPattern.test(R.currentUrl);R.hasViewMode=R.currentUrl.includes('mode=view')||R.currentUrl.includes('mode=edit');const captured=window.__CAPTURED__;R.hasCapturedData=!!captured;if(captured&&captured.firstRowTexts){ const pageText=document.body.innerText; let matchCount=0; const checks=[]; for(const t of captured.firstRowTexts){ if(t.length>=2){ const found=pageText.includes(t); if(found)matchCount++; checks.push({text:t.substring(0,20),found}); } } R.dataChecks=checks.slice(0,5); R.matchCount=matchCount; R.totalChecked=checks.length; R.dataMatch=matchCount>0;}const tabs=document.querySelectorAll('[role=\"tab\"],[role=\"tablist\"] button,button[data-state]');R.tabCount=tabs.length;R.tabLabels=Array.from(tabs).slice(0,5).map(t=>t.innerText?.trim().substring(0,20));const inputs=document.querySelectorAll('input:not([type=\"hidden\"]),textarea,select');R.inputCount=inputs.length;R.ok=R.dataMatch!==false;if(!R.ok)R.error='상세 페이지에서 목록 데이터 불일치';return JSON.stringify(R);})()",
"timeout": 10000,
"phase": "VERIFY_DETAIL"
},
{
"id": 6,
"name": "[회계관리 > 거래처관리] 목록으로 복귀",
"action": "evaluate",
"script": "(async()=>{const w=ms=>new Promise(r=>setTimeout(r,ms));const R={phase:'GO_BACK'};R.detailUrl=window.location.href;const captured=window.__CAPTURED__;const listUrl=captured?.listUrl||'';const listBtn=Array.from(document.querySelectorAll('button,a')).find(b=>{ const txt=b.innerText?.trim()||''; return /목록|리스트|뒤로|Back|List/i.test(txt)&&b.offsetParent!==null;});if(listBtn){ R.method='목록 버튼 클릭'; listBtn.click(); await w(2000);}else{ R.method='history.back()'; window.history.back(); await w(2000);}R.returnedUrl=window.location.href;R.urlMatches=listUrl?R.returnedUrl===listUrl:!R.returnedUrl.includes('mode=view');if(!R.urlMatches&&listUrl){ R.info='목록 URL과 다름: expected='+listUrl.substring(listUrl.length-40)+' actual='+R.returnedUrl.substring(R.returnedUrl.length-40);}R.ok=R.urlMatches!==false;if(!R.ok)R.error='목록 URL 복귀 실패';return JSON.stringify(R);})()",
"timeout": 10000,
"phase": "GO_BACK"
},
{
"id": 7,
"name": "[회계관리 > 거래처관리] 목록 무결성 확인",
"action": "evaluate",
"script": "(async()=>{const w=ms=>new Promise(r=>setTimeout(r,ms));await w(1500);const R={phase:'LIST_INTACT'};const captured=window.__CAPTURED__;if(!captured){R.warn='캡처 데이터 없음';R.ok=true;return JSON.stringify(R);}const rows=Array.from(document.querySelectorAll('table tbody tr')).filter(r=>r.offsetParent!==null);R.currentRowCount=rows.length;R.originalRowCount=captured.rowCount;R.rowCountMatch=R.currentRowCount===R.originalRowCount;if(rows.length>0){ const cells=Array.from(rows[0].querySelectorAll('td')); const cellTexts=cells.map(c=>c.innerText?.trim().substring(0,50)).filter(t=>t.length>0); R.currentFirstRow=cellTexts.slice(0,3); R.originalFirstRow=(captured.firstRowTexts||[]).slice(0,3); let textMatch=0; for(const t of R.originalFirstRow){ if(cellTexts.some(c=>c.includes(t)||t.includes(c)))textMatch++; } R.firstRowMatch=textMatch>0;}else{ R.firstRowMatch=false; R.warn='목록 복귀 후 행 없음';}R.intact=R.rowCountMatch&&R.firstRowMatch;if(!R.intact&&!R.rowCountMatch)R.info='행 수 변경: '+R.originalRowCount+'→'+R.currentRowCount;R.ok=R.intact!==false;return JSON.stringify(R);})()",
"timeout": 10000,
"phase": "LIST_INTACT"
},
{
"id": 8,
"name": "[회계관리 > 어음관리] 메뉴 이동",
"action": "menu_navigate",
"level1": "회계관리",
"level2": "어음관리",
"timeout": 10000
},
{
"id": 9,
"name": "[회계관리 > 어음관리] 페이지 로드 대기",
"action": "wait",
"timeout": 3000
},
{
"id": 10,
"name": "[회계관리 > 어음관리] 테이블 로드 대기",
"action": "wait_for_table",
"timeout": 5000
},
{
"id": 11,
"name": "[회계관리 > 어음관리] 테이블 상태 캡처",
"action": "evaluate",
"script": "(async()=>{const w=ms=>new Promise(r=>setTimeout(r,ms));const R={phase:'CAPTURE'};const rows=Array.from(document.querySelectorAll('table tbody tr')).filter(r=>r.offsetParent!==null);R.rowCount=rows.length;if(rows.length===0){R.warn='테이블에 데이터 없음 - 상세 조회 불가';R.ok=true;return JSON.stringify(R);}const testRow=rows.find(r=>r.innerText?.includes('E2E_TEST_'));const firstRow=testRow||rows[0];R.usedTestRow=!!testRow;const cells=Array.from(firstRow.querySelectorAll('td'));const cellTexts=cells.map(c=>c.innerText?.trim().substring(0,50)).filter(t=>t.length>0);R.firstRowTexts=cellTexts;const style=window.getComputedStyle(firstRow);R.hasCursor=style.cursor==='pointer';R.listUrl=window.location.href;window.__CAPTURED__={rowCount:rows.length,firstRowTexts:cellTexts,listUrl:window.location.href};R.ok=true;return JSON.stringify(R);})()",
"timeout": 10000,
"phase": "CAPTURE"
},
{
"id": 12,
"name": "[회계관리 > 어음관리] 첫 행 클릭 → 상세 이동",
"action": "evaluate",
"script": "(async()=>{const w=ms=>new Promise(r=>setTimeout(r,ms));const R={phase:'CLICK_ROW'};const rows=Array.from(document.querySelectorAll('table tbody tr')).filter(r=>r.offsetParent!==null);if(rows.length===0){R.error='행 없음';R.ok=false;return JSON.stringify(R);}const testRow=rows.find(r=>r.innerText?.includes('E2E_TEST_'));const firstRow=testRow||rows[0];R.usedTestRow=!!testRow;const targetCell=firstRow.querySelector('td:nth-child(2)')||firstRow.querySelector('td');if(!targetCell){R.error='클릭할 셀 없음';R.ok=false;return JSON.stringify(R);}R.clickedText=targetCell.innerText?.trim().substring(0,30);R.urlBefore=window.location.href;targetCell.click();await w(500);if(window.location.href===R.urlBefore){ const link=firstRow.querySelector('a[href]'); if(link){link.click();await w(500);}}let waited=0;while(window.location.href===R.urlBefore&&waited<5000){await w(300);waited+=300;}R.urlAfter=window.location.href;R.urlChanged=R.urlAfter!==R.urlBefore;if(!R.urlChanged){R.warn='행 클릭 후 URL 변경 없음 - 모달 또는 인라인 상세일 수 있음';R.ok=true;return JSON.stringify(R);}R.ok=true;return JSON.stringify(R);})()",
"timeout": 10000,
"phase": "CLICK_ROW"
},
{
"id": 13,
"name": "[회계관리 > 어음관리] 상세 페이지 데이터 검증",
"action": "evaluate",
"script": "(async()=>{const w=ms=>new Promise(r=>setTimeout(r,ms));const R={phase:'VERIFY_DETAIL'};await w(1500);R.currentUrl=window.location.href;const idPattern=new RegExp('[/][0-9a-f]{8,}|[/][0-9]+[?]|[/][0-9]+$');R.hasIdInUrl=idPattern.test(R.currentUrl);R.hasViewMode=R.currentUrl.includes('mode=view')||R.currentUrl.includes('mode=edit');const captured=window.__CAPTURED__;R.hasCapturedData=!!captured;if(captured&&captured.firstRowTexts){ const pageText=document.body.innerText; let matchCount=0; const checks=[]; for(const t of captured.firstRowTexts){ if(t.length>=2){ const found=pageText.includes(t); if(found)matchCount++; checks.push({text:t.substring(0,20),found}); } } R.dataChecks=checks.slice(0,5); R.matchCount=matchCount; R.totalChecked=checks.length; R.dataMatch=matchCount>0;}const tabs=document.querySelectorAll('[role=\"tab\"],[role=\"tablist\"] button,button[data-state]');R.tabCount=tabs.length;R.tabLabels=Array.from(tabs).slice(0,5).map(t=>t.innerText?.trim().substring(0,20));const inputs=document.querySelectorAll('input:not([type=\"hidden\"]),textarea,select');R.inputCount=inputs.length;R.ok=R.dataMatch!==false;if(!R.ok)R.error='상세 페이지에서 목록 데이터 불일치';return JSON.stringify(R);})()",
"timeout": 10000,
"phase": "VERIFY_DETAIL"
},
{
"id": 14,
"name": "[회계관리 > 어음관리] 목록으로 복귀",
"action": "evaluate",
"script": "(async()=>{const w=ms=>new Promise(r=>setTimeout(r,ms));const R={phase:'GO_BACK'};R.detailUrl=window.location.href;const captured=window.__CAPTURED__;const listUrl=captured?.listUrl||'';const listBtn=Array.from(document.querySelectorAll('button,a')).find(b=>{ const txt=b.innerText?.trim()||''; return /목록|리스트|뒤로|Back|List/i.test(txt)&&b.offsetParent!==null;});if(listBtn){ R.method='목록 버튼 클릭'; listBtn.click(); await w(2000);}else{ R.method='history.back()'; window.history.back(); await w(2000);}R.returnedUrl=window.location.href;R.urlMatches=listUrl?R.returnedUrl===listUrl:!R.returnedUrl.includes('mode=view');if(!R.urlMatches&&listUrl){ R.info='목록 URL과 다름: expected='+listUrl.substring(listUrl.length-40)+' actual='+R.returnedUrl.substring(R.returnedUrl.length-40);}R.ok=R.urlMatches!==false;if(!R.ok)R.error='목록 URL 복귀 실패';return JSON.stringify(R);})()",
"timeout": 10000,
"phase": "GO_BACK"
},
{
"id": 15,
"name": "[회계관리 > 어음관리] 목록 무결성 확인",
"action": "evaluate",
"script": "(async()=>{const w=ms=>new Promise(r=>setTimeout(r,ms));await w(1500);const R={phase:'LIST_INTACT'};const captured=window.__CAPTURED__;if(!captured){R.warn='캡처 데이터 없음';R.ok=true;return JSON.stringify(R);}const rows=Array.from(document.querySelectorAll('table tbody tr')).filter(r=>r.offsetParent!==null);R.currentRowCount=rows.length;R.originalRowCount=captured.rowCount;R.rowCountMatch=R.currentRowCount===R.originalRowCount;if(rows.length>0){ const cells=Array.from(rows[0].querySelectorAll('td')); const cellTexts=cells.map(c=>c.innerText?.trim().substring(0,50)).filter(t=>t.length>0); R.currentFirstRow=cellTexts.slice(0,3); R.originalFirstRow=(captured.firstRowTexts||[]).slice(0,3); let textMatch=0; for(const t of R.originalFirstRow){ if(cellTexts.some(c=>c.includes(t)||t.includes(c)))textMatch++; } R.firstRowMatch=textMatch>0;}else{ R.firstRowMatch=false; R.warn='목록 복귀 후 행 없음';}R.intact=R.rowCountMatch&&R.firstRowMatch;if(!R.intact&&!R.rowCountMatch)R.info='행 수 변경: '+R.originalRowCount+'→'+R.currentRowCount;R.ok=R.intact!==false;return JSON.stringify(R);})()",
"timeout": 10000,
"phase": "LIST_INTACT"
},
{
"id": 16,
"name": "[회계관리 > 입금관리] 메뉴 이동",
"action": "menu_navigate",
"level1": "회계관리",
"level2": "입금관리",
"timeout": 10000
},
{
"id": 17,
"name": "[회계관리 > 입금관리] 페이지 로드 대기",
"action": "wait",
"timeout": 3000
},
{
"id": 18,
"name": "[회계관리 > 입금관리] 테이블 로드 대기",
"action": "wait_for_table",
"timeout": 5000
},
{
"id": 19,
"name": "[회계관리 > 입금관리] 테이블 상태 캡처",
"action": "evaluate",
"script": "(async()=>{const w=ms=>new Promise(r=>setTimeout(r,ms));const R={phase:'CAPTURE'};const rows=Array.from(document.querySelectorAll('table tbody tr')).filter(r=>r.offsetParent!==null);R.rowCount=rows.length;if(rows.length===0){R.warn='테이블에 데이터 없음 - 상세 조회 불가';R.ok=true;return JSON.stringify(R);}const testRow=rows.find(r=>r.innerText?.includes('E2E_TEST_'));const firstRow=testRow||rows[0];R.usedTestRow=!!testRow;const cells=Array.from(firstRow.querySelectorAll('td'));const cellTexts=cells.map(c=>c.innerText?.trim().substring(0,50)).filter(t=>t.length>0);R.firstRowTexts=cellTexts;const style=window.getComputedStyle(firstRow);R.hasCursor=style.cursor==='pointer';R.listUrl=window.location.href;window.__CAPTURED__={rowCount:rows.length,firstRowTexts:cellTexts,listUrl:window.location.href};R.ok=true;return JSON.stringify(R);})()",
"timeout": 10000,
"phase": "CAPTURE"
},
{
"id": 20,
"name": "[회계관리 > 입금관리] 첫 행 클릭 → 상세 이동",
"action": "evaluate",
"script": "(async()=>{const w=ms=>new Promise(r=>setTimeout(r,ms));const R={phase:'CLICK_ROW'};const rows=Array.from(document.querySelectorAll('table tbody tr')).filter(r=>r.offsetParent!==null);if(rows.length===0){R.error='행 없음';R.ok=false;return JSON.stringify(R);}const testRow=rows.find(r=>r.innerText?.includes('E2E_TEST_'));const firstRow=testRow||rows[0];R.usedTestRow=!!testRow;const targetCell=firstRow.querySelector('td:nth-child(2)')||firstRow.querySelector('td');if(!targetCell){R.error='클릭할 셀 없음';R.ok=false;return JSON.stringify(R);}R.clickedText=targetCell.innerText?.trim().substring(0,30);R.urlBefore=window.location.href;targetCell.click();await w(500);if(window.location.href===R.urlBefore){ const link=firstRow.querySelector('a[href]'); if(link){link.click();await w(500);}}let waited=0;while(window.location.href===R.urlBefore&&waited<5000){await w(300);waited+=300;}R.urlAfter=window.location.href;R.urlChanged=R.urlAfter!==R.urlBefore;if(!R.urlChanged){R.warn='행 클릭 후 URL 변경 없음 - 모달 또는 인라인 상세일 수 있음';R.ok=true;return JSON.stringify(R);}R.ok=true;return JSON.stringify(R);})()",
"timeout": 10000,
"phase": "CLICK_ROW"
},
{
"id": 21,
"name": "[회계관리 > 입금관리] 상세 페이지 데이터 검증",
"action": "evaluate",
"script": "(async()=>{const w=ms=>new Promise(r=>setTimeout(r,ms));const R={phase:'VERIFY_DETAIL'};await w(1500);R.currentUrl=window.location.href;const idPattern=new RegExp('[/][0-9a-f]{8,}|[/][0-9]+[?]|[/][0-9]+$');R.hasIdInUrl=idPattern.test(R.currentUrl);R.hasViewMode=R.currentUrl.includes('mode=view')||R.currentUrl.includes('mode=edit');const captured=window.__CAPTURED__;R.hasCapturedData=!!captured;if(captured&&captured.firstRowTexts){ const pageText=document.body.innerText; let matchCount=0; const checks=[]; for(const t of captured.firstRowTexts){ if(t.length>=2){ const found=pageText.includes(t); if(found)matchCount++; checks.push({text:t.substring(0,20),found}); } } R.dataChecks=checks.slice(0,5); R.matchCount=matchCount; R.totalChecked=checks.length; R.dataMatch=matchCount>0;}const tabs=document.querySelectorAll('[role=\"tab\"],[role=\"tablist\"] button,button[data-state]');R.tabCount=tabs.length;R.tabLabels=Array.from(tabs).slice(0,5).map(t=>t.innerText?.trim().substring(0,20));const inputs=document.querySelectorAll('input:not([type=\"hidden\"]),textarea,select');R.inputCount=inputs.length;R.ok=R.dataMatch!==false;if(!R.ok)R.error='상세 페이지에서 목록 데이터 불일치';return JSON.stringify(R);})()",
"timeout": 10000,
"phase": "VERIFY_DETAIL"
},
{
"id": 22,
"name": "[회계관리 > 입금관리] 목록으로 복귀",
"action": "evaluate",
"script": "(async()=>{const w=ms=>new Promise(r=>setTimeout(r,ms));const R={phase:'GO_BACK'};R.detailUrl=window.location.href;const captured=window.__CAPTURED__;const listUrl=captured?.listUrl||'';const listBtn=Array.from(document.querySelectorAll('button,a')).find(b=>{ const txt=b.innerText?.trim()||''; return /목록|리스트|뒤로|Back|List/i.test(txt)&&b.offsetParent!==null;});if(listBtn){ R.method='목록 버튼 클릭'; listBtn.click(); await w(2000);}else{ R.method='history.back()'; window.history.back(); await w(2000);}R.returnedUrl=window.location.href;R.urlMatches=listUrl?R.returnedUrl===listUrl:!R.returnedUrl.includes('mode=view');if(!R.urlMatches&&listUrl){ R.info='목록 URL과 다름: expected='+listUrl.substring(listUrl.length-40)+' actual='+R.returnedUrl.substring(R.returnedUrl.length-40);}R.ok=R.urlMatches!==false;if(!R.ok)R.error='목록 URL 복귀 실패';return JSON.stringify(R);})()",
"timeout": 10000,
"phase": "GO_BACK"
},
{
"id": 23,
"name": "[회계관리 > 입금관리] 목록 무결성 확인",
"action": "evaluate",
"script": "(async()=>{const w=ms=>new Promise(r=>setTimeout(r,ms));await w(1500);const R={phase:'LIST_INTACT'};const captured=window.__CAPTURED__;if(!captured){R.warn='캡처 데이터 없음';R.ok=true;return JSON.stringify(R);}const rows=Array.from(document.querySelectorAll('table tbody tr')).filter(r=>r.offsetParent!==null);R.currentRowCount=rows.length;R.originalRowCount=captured.rowCount;R.rowCountMatch=R.currentRowCount===R.originalRowCount;if(rows.length>0){ const cells=Array.from(rows[0].querySelectorAll('td')); const cellTexts=cells.map(c=>c.innerText?.trim().substring(0,50)).filter(t=>t.length>0); R.currentFirstRow=cellTexts.slice(0,3); R.originalFirstRow=(captured.firstRowTexts||[]).slice(0,3); let textMatch=0; for(const t of R.originalFirstRow){ if(cellTexts.some(c=>c.includes(t)||t.includes(c)))textMatch++; } R.firstRowMatch=textMatch>0;}else{ R.firstRowMatch=false; R.warn='목록 복귀 후 행 없음';}R.intact=R.rowCountMatch&&R.firstRowMatch;if(!R.intact&&!R.rowCountMatch)R.info='행 수 변경: '+R.originalRowCount+'→'+R.currentRowCount;R.ok=R.intact!==false;return JSON.stringify(R);})()",
"timeout": 10000,
"phase": "LIST_INTACT"
}
]
}