Files
sam-scenarios/workflow-sales-lifecycle.json

177 lines
13 KiB
JSON
Raw Normal View History

{
"id": "workflow-sales-lifecycle",
"name": "비즈니스 워크플로우: 거래처→단가→수주→매출 흐름",
"version": "2.0.0",
"category": "workflow",
"auth": {
"role": "admin"
},
"menuNavigation": {
"level1": "판매관리",
"level2": "거래처관리"
},
"screenshotPolicy": {
"captureOnFail": true,
"captureOnPass": false
},
"steps": [
{
"id": 1,
"name": "[INIT] 콘솔 에러 모니터링 + 워크플로우 컨텍스트 초기화",
"action": "evaluate",
"script": "(()=>{window.__CONSOLE_ERRORS__=[];const origError=console.error;console.error=function(...args){window.__CONSOLE_ERRORS__.push(args.join(' ').substring(0,200));origError.apply(console,args);};window.__WORKFLOW_CTX__={pages:[],totalRows:0,crossPageMatches:0,perfMetrics:[],errors:[]};return JSON.stringify({ok:true,info:'Console error monitor + workflow context initialized'});})()",
"timeout": 5000,
"phase": "INIT"
},
{
"id": 2,
"name": "[판매 > 거래처관리] wait",
"action": "wait",
"timeout": 3000
},
{
"id": 3,
"name": "[판매 > 거래처관리] wait_for_table",
"action": "wait_for_table",
"timeout": 5000
},
{
"id": 4,
"name": "[판매 > 거래처관리] CAPTURE_CLIENT + 데이터 존재 검증",
"action": "evaluate",
"script": "(async()=>{const w=ms=>new Promise(r=>setTimeout(r,ms));const R={phase:'CAPTURE_CLIENT'};await w(1500);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=false;R.info='fail: 거래처관리 테이블에 데이터 0건 - 워크플로우 검증 불가';return JSON.stringify(R);}const testRow=rows.find(r=>r.innerText?.includes('E2E_TEST_'));const targetRow=testRow||rows[0];R.usedTestRow=!!testRow;const cells=targetRow.querySelectorAll('td');let val='';const indices=[1,2,3];for(const i of indices){const t=cells[i]?.innerText?.trim();if(t&&t.length>=2&&t.length<=40&&!/^[\\d,.]+$/.test(t)&&!/^\\d{4}[-/]/.test(t)){val=t;break;}}R.clientName=val;if(!val){R.warn='clientName 추출 실패';R.ok=true;return JSON.stringify(R);}if(!window.__WORKFLOW_CTX__)window.__WORKFLOW_CTX__={pages:[],totalRows:0,crossPageMatches:0,perfMetrics:[],errors:[]};window.__WORKFLOW_CTX__.clientName=val;window.__E2E_VENDOR__=val;window.__WORKFLOW_CTX__.pages.push({name:'거래처관리',rows:rows.length});window.__WORKFLOW_CTX__.totalRows+=rows.length;R.ok=true;R.info='pass: 거래처 \"'+val+'\" 캡처 완료, '+rows.length+'건 존재';return JSON.stringify(R);})()",
"phase": "CAPTURE_CLIENT"
},
{
"id": 5,
"name": "[판매 > 거래처관리] 페이지 로드 성능 + JS 에러 확인",
"action": "evaluate",
"script": "(()=>{const R={phase:'PERF_거래처관리'};const nav=performance.getEntriesByType('navigation')[0];R.loadTime=nav?Math.round(nav.loadEventEnd-nav.startTime):'N/A';const errors=window.__CONSOLE_ERRORS__||[];R.jsErrors=errors.length;if(window.__WORKFLOW_CTX__){window.__WORKFLOW_CTX__.perfMetrics.push({page:'거래처관리',loadTime:R.loadTime});window.__WORKFLOW_CTX__.errors.push({page:'거래처관리',count:errors.length});}R.ok=true;R.info='pass: page load '+R.loadTime+'ms, '+errors.length+' JS errors';return JSON.stringify(R);})()",
"timeout": 5000,
"phase": "VERIFY"
},
{
"id": 6,
"name": "[판매 > 단가관리] 메뉴 이동",
"action": "menu_navigate",
"level1": "판매관리",
"level2": "단가관리",
"timeout": 10000
},
{
"id": 7,
"name": "[판매 > 단가관리] wait",
"action": "wait",
"timeout": 3000
},
{
"id": 8,
"name": "[판매 > 단가관리] wait_for_table",
"action": "wait_for_table",
"timeout": 5000
},
{
"id": 9,
"name": "[판매 > 단가관리] CAPTURE_PRICE_ITEM + 데이터 존재 검증",
"action": "evaluate",
"script": "(async()=>{const w=ms=>new Promise(r=>setTimeout(r,ms));const R={phase:'CAPTURE_PRICE_ITEM'};await w(1500);const rows=Array.from(document.querySelectorAll('table tbody tr')).filter(r=>r.offsetParent!==null);R.rowCount=rows.length;if(rows.length===0){R.ok=true;R.info='warn: 단가관리 테이블에 데이터 0건';if(window.__WORKFLOW_CTX__){window.__WORKFLOW_CTX__.pages.push({name:'단가관리',rows:0});}return JSON.stringify(R);}const testRow=rows.find(r=>r.innerText?.includes('E2E_TEST_'));const targetRow=testRow||rows[0];R.usedTestRow=!!testRow;const cells=targetRow.querySelectorAll('td');let val='';const indices=[1,2,3];for(const i of indices){const t=cells[i]?.innerText?.trim();if(t&&t.length>=2&&t.length<=40&&!/^[\\d,.]+$/.test(t)&&!/^\\d{4}[-/]/.test(t)){val=t;break;}}R.itemName=val;if(!window.__WORKFLOW_CTX__)window.__WORKFLOW_CTX__={pages:[],totalRows:0,crossPageMatches:0,perfMetrics:[],errors:[]};if(val)window.__WORKFLOW_CTX__.itemName=val;window.__WORKFLOW_CTX__.pages.push({name:'단가관리',rows:rows.length});window.__WORKFLOW_CTX__.totalRows+=rows.length;R.ok=true;R.info='pass: 단가 품목 \"'+(val||'N/A')+'\" 캡처, '+rows.length+'건 존재';return JSON.stringify(R);})()",
"phase": "CAPTURE_PRICE_ITEM"
},
{
"id": 10,
"name": "[판매 > 단가관리] 페이지 로드 성능 + JS 에러 확인",
"action": "evaluate",
"script": "(()=>{const R={phase:'PERF_단가관리'};const nav=performance.getEntriesByType('navigation')[0];R.loadTime=nav?Math.round(nav.loadEventEnd-nav.startTime):'N/A';const errors=window.__CONSOLE_ERRORS__||[];R.jsErrors=errors.length;if(window.__WORKFLOW_CTX__){window.__WORKFLOW_CTX__.perfMetrics.push({page:'단가관리',loadTime:R.loadTime});window.__WORKFLOW_CTX__.errors.push({page:'단가관리',count:errors.length});}R.ok=true;R.info='pass: page load '+R.loadTime+'ms, '+errors.length+' JS errors';return JSON.stringify(R);})()",
"timeout": 5000,
"phase": "VERIFY"
},
{
"id": 11,
"name": "[판매 > 수주관리] 메뉴 이동",
"action": "menu_navigate",
"level1": "판매관리",
"level2": "수주관리",
"timeout": 10000
},
{
"id": 12,
"name": "[판매 > 수주관리] wait",
"action": "wait",
"timeout": 3000
},
{
"id": 13,
"name": "[판매 > 수주관리] wait_for_table",
"action": "wait_for_table",
"timeout": 5000
},
{
"id": 14,
"name": "[판매 > 수주관리] CHECK_ORDERS + 거래처 교차 검증",
"action": "evaluate",
"script": "(async()=>{const w=ms=>new Promise(r=>setTimeout(r,ms));const R={phase:'CHECK_ORDERS'};await w(1500);const rows=Array.from(document.querySelectorAll('table tbody tr')).filter(r=>r.offsetParent!==null);R.rowCount=rows.length;if(rows.length===0){R.ok=true;R.info='warn: 수주관리 테이블에 데이터 0건';if(window.__WORKFLOW_CTX__){window.__WORKFLOW_CTX__.pages.push({name:'수주관리',rows:0});}return JSON.stringify(R);}const vendorName=window.__E2E_VENDOR__||window.__WORKFLOW_CTX__?.clientName||'';R.vendorSearched=vendorName;let vendorFound=false;if(vendorName){vendorFound=Array.from(rows).some(r=>r.innerText?.includes(vendorName));}R.vendorFoundInOrders=vendorFound;if(!window.__WORKFLOW_CTX__)window.__WORKFLOW_CTX__={pages:[],totalRows:0,crossPageMatches:0,perfMetrics:[],errors:[]};window.__WORKFLOW_CTX__.pages.push({name:'수주관리',rows:rows.length,vendorFound});window.__WORKFLOW_CTX__.totalRows+=rows.length;if(vendorFound)window.__WORKFLOW_CTX__.crossPageMatches++;R.ok=true;R.info='pass: 수주 '+rows.length+'건 존재'+(vendorName?(vendorFound?' + 거래처 \"'+vendorName+'\" 발견':' + 거래처 \"'+vendorName+'\" 미발견'):'');return JSON.stringify(R);})()",
"phase": "CHECK_ORDERS"
},
{
"id": 15,
"name": "[판매 > 수주관리] 페이지 로드 성능 + JS 에러 확인",
"action": "evaluate",
"script": "(()=>{const R={phase:'PERF_수주관리'};const nav=performance.getEntriesByType('navigation')[0];R.loadTime=nav?Math.round(nav.loadEventEnd-nav.startTime):'N/A';const errors=window.__CONSOLE_ERRORS__||[];R.jsErrors=errors.length;if(window.__WORKFLOW_CTX__){window.__WORKFLOW_CTX__.perfMetrics.push({page:'수주관리',loadTime:R.loadTime});window.__WORKFLOW_CTX__.errors.push({page:'수주관리',count:errors.length});}R.ok=true;R.info='pass: page load '+R.loadTime+'ms, '+errors.length+' JS errors';return JSON.stringify(R);})()",
"timeout": 5000,
"phase": "VERIFY"
},
{
"id": 16,
"name": "[회계 > 매출관리] 메뉴 이동",
"action": "menu_navigate",
"level1": "회계관리",
"level2": "매출관리",
"timeout": 10000
},
{
"id": 17,
"name": "[회계 > 매출관리] wait",
"action": "wait",
"timeout": 3000
},
{
"id": 18,
"name": "[회계 > 매출관리] wait_for_table",
"action": "wait_for_table",
"timeout": 5000
},
{
"id": 19,
"name": "[회계 > 매출관리] CHECK_SALES + 거래처 교차 검증",
"action": "evaluate",
"script": "(async()=>{const w=ms=>new Promise(r=>setTimeout(r,ms));const R={phase:'CHECK_SALES'};await w(1500);const rows=Array.from(document.querySelectorAll('table tbody tr')).filter(r=>r.offsetParent!==null);R.rowCount=rows.length;if(rows.length===0){R.ok=true;R.info='warn: 매출관리 테이블에 데이터 0건';if(window.__WORKFLOW_CTX__){window.__WORKFLOW_CTX__.pages.push({name:'매출관리',rows:0});}return JSON.stringify(R);}const vendorName=window.__E2E_VENDOR__||window.__WORKFLOW_CTX__?.clientName||'';R.vendorSearched=vendorName;let vendorFound=false;if(vendorName){vendorFound=Array.from(rows).some(r=>r.innerText?.includes(vendorName));}R.vendorFoundInSales=vendorFound;if(!window.__WORKFLOW_CTX__)window.__WORKFLOW_CTX__={pages:[],totalRows:0,crossPageMatches:0,perfMetrics:[],errors:[]};window.__WORKFLOW_CTX__.pages.push({name:'매출관리',rows:rows.length,vendorFound});window.__WORKFLOW_CTX__.totalRows+=rows.length;if(vendorFound)window.__WORKFLOW_CTX__.crossPageMatches++;R.ok=true;R.info='pass: 매출 '+rows.length+'건 존재'+(vendorName?(vendorFound?' + 거래처 \"'+vendorName+'\" 발견':' + 거래처 \"'+vendorName+'\" 미발견'):'');return JSON.stringify(R);})()",
"phase": "CHECK_SALES"
},
{
"id": 20,
"name": "[회계 > 매출관리] 페이지 로드 성능 + JS 에러 확인",
"action": "evaluate",
"script": "(()=>{const R={phase:'PERF_매출관리'};const nav=performance.getEntriesByType('navigation')[0];R.loadTime=nav?Math.round(nav.loadEventEnd-nav.startTime):'N/A';const errors=window.__CONSOLE_ERRORS__||[];R.jsErrors=errors.length;if(window.__WORKFLOW_CTX__){window.__WORKFLOW_CTX__.perfMetrics.push({page:'매출관리',loadTime:R.loadTime});window.__WORKFLOW_CTX__.errors.push({page:'매출관리',count:errors.length});}R.ok=true;R.info='pass: page load '+R.loadTime+'ms, '+errors.length+' JS errors';return JSON.stringify(R);})()",
"timeout": 5000,
"phase": "VERIFY"
},
{
"id": 21,
"name": "[VERIFY] 콘솔 에러 전체 확인",
"description": "전체 워크플로우 동안 발생한 JS 콘솔 에러 확인",
"action": "evaluate",
"script": "(()=>{const R={phase:'CONSOLE_CHECK'};const errors=window.__CONSOLE_ERRORS__||[];R.totalErrors=errors.length;if(errors.length===0){R.info='pass: 0 JS console errors across all pages';R.ok=true;}else{R.info='warn: '+errors.length+' JS errors total: '+errors.slice(0,5).join(' | ').substring(0,300);R.errors=errors.slice(0,10);R.ok=true;}return JSON.stringify(R);})()",
"timeout": 5000,
"phase": "VERIFY"
},
{
"id": 22,
"name": "[SUMMARY] 워크플로우 최종 요약",
"description": "4개 페이지 방문 결과, 전체 행 수, 교차 검증 결과, 성능 메트릭, JS 에러를 종합 보고",
"action": "evaluate",
"script": "(()=>{const ctx=window.__WORKFLOW_CTX__||{};const R={phase:'WORKFLOW_SUMMARY'};R.pagesVisited=(ctx.pages||[]).length;R.totalRows=ctx.totalRows||0;R.crossPageMatches=ctx.crossPageMatches||0;R.vendorName=ctx.clientName||'N/A';R.itemName=ctx.itemName||'N/A';R.pageDetails=(ctx.pages||[]).map(p=>p.name+': '+p.rows+'rows'+(p.vendorFound?' (vendor found)':'')).join(' | ');R.perfSummary=(ctx.perfMetrics||[]).map(p=>p.page+': '+p.loadTime+'ms').join(' | ');const totalErrors=(ctx.errors||[]).reduce((s,e)=>s+e.count,0);R.totalJsErrors=totalErrors;R.errorDetails=(ctx.errors||[]).map(e=>e.page+': '+e.count).join(' | ');const allPagesHaveData=(ctx.pages||[]).every(p=>p.rows>0);R.allPagesHaveData=allPagesHaveData;R.ok=true;R.info='Workflow complete: '+R.pagesVisited+' pages, '+R.totalRows+' total rows, '+R.crossPageMatches+' cross-page vendor matches, '+(allPagesHaveData?'all pages have data':'some pages empty')+', '+totalErrors+' JS errors';return JSON.stringify(R);})()",
"timeout": 5000,
"phase": "SUMMARY"
}
]
}