{ "id": "draft-box", "name": "기안함 테스트", "screenshotPolicy": { "onErrorOnly": true, "captureOn": ["error", "fail", "timeout", "404", "500", "blocked"] }, "description": "결재관리 > 기안함 메뉴의 문서 목록 조회, 검색, 필터, 정렬, 문서 상세, 상신, 삭제 기능 테스트", "baseUrl": "https://dev.codebridge-x.com", "testFocus": { "primary": "기안 문서 목록 관리 및 결재 상신 프로세스 검증", "description": "기안함 목록 표시, 통계 카드, 검색/필터/정렬, 체크박스 선택, 상신/삭제 버튼, 문서 상세 모달, 페이지네이션 동작 확인" }, "navigation": { "targetUrl": "/approval/draft", "urlPattern": "/approval/draft|/ko/approval/draft", "menuHints": ["기안함", "기안 함", "결재관리"] }, "menuNavigation": { "level1": "결재관리", "level2": "기안함", "expectedUrl": "/ko/approval/draft", "searchWithinParent": true, "closeOtherMenus": true }, "auth": { "username": "TestUser5", "password": "password123!" }, "menuNavigationEnhanced": { "strategy": "scroll-and-search", "description": "사이드바를 스크롤하며 메뉴를 찾고 클릭하여 404를 방지", "level1": "결재관리", "level2": "기안함", "alternativeLevel1Names": ["결재관리", "결재 관리", "Approval", "전자결재"], "alternativeLevel2Names": ["기안함", "기안 함", "Draft", "기안문서", "내 기안"], "scrollConfig": { "sidebarSelector": "nav, aside, [role='navigation'], .sidebar, #sidebar", "menuItemSelector": "a, button, [role='menuitem'], [role='treeitem']", "scrollStep": 200, "maxScrollAttempts": 10, "scrollDelay": 300 } }, "prerequisites": { "authentication": true, "testData": { "description": "결재 문서 데이터가 최소 1개 이상 존재해야 함 (다양한 상태: 임시저장, 결재대기, 진행중, 완료, 반려)" } }, "expectedAPIs": [ { "method": "GET", "endpoint": "/api/v1/approvals/drafts", "params": "page=1&per_page=20&sort_by=created_at&sort_dir=desc", "description": "기안함 목록 조회 (페이지네이션, 검색, 필터, 정렬)" }, { "method": "GET", "endpoint": "/api/v1/approvals/drafts/summary", "params": "", "description": "기안함 통계 카드 (전체, 진행, 완료, 반려, 임시저장 건수)" }, { "method": "GET", "endpoint": "/api/v1/approvals/{id}", "params": "", "description": "결재 문서 상세 조회 (content 포함)" }, { "method": "POST", "endpoint": "/api/v1/approvals/{id}/submit", "params": "", "description": "결재 상신" }, { "method": "DELETE", "endpoint": "/api/v1/approvals/{id}", "params": "", "description": "결재 문서 삭제 (임시저장 상태만)" } ], "steps": [ { "id": "step-0", "name": "사이드바 메뉴 전체 펼치기", "description": "모두 펼치기 버튼을 클릭하여 전체 메뉴를 펼친 후 메뉴 탐색 준비", "actions": [ { "type": "scroll", "target": "sidebar", "direction": "top", "description": "사이드바 최상단으로 스크롤" }, { "type": "wait", "duration": 300 }, { "type": "evaluate", "script": "Array.from(document.querySelectorAll('button')).find(b => b.innerText?.includes('모두 펼치기'))?.click()" }, { "type": "wait", "duration": 2000 } ] }, { "id": "step-1", "name": "2단계 메뉴 진입: 결재관리 > 기안함", "description": "사이드바를 스크롤하며 결재관리 > 기안함 메뉴를 찾아 클릭", "actions": [ { "type": "scrollAndFind", "target": "결재관리", "alternativeTexts": ["결재관리", "결재 관리", "Approval", "전자결재"], "scrollContainer": "sidebar", "maxAttempts": 10, "description": "스크롤하며 결재관리 메뉴 찾기" }, { "type": "click", "target": "결재관리", "description": "결재관리 메뉴 클릭" }, { "type": "wait", "duration": 500, "description": "서브메뉴 펼쳐지기 대기" }, { "type": "scrollAndFind", "target": "기안함", "alternativeTexts": ["기안함", "기안 함", "Draft", "내 기안"], "scrollContainer": "submenu", "maxAttempts": 5, "description": "서브메뉴에서 기안함 찾기" }, { "type": "click", "target": "기안함", "description": "기안함 메뉴 클릭" }, { "type": "wait", "target": "페이지 로드 완료", "timeout": 10000 } ], "expected": { "url": "/ko/approval/draft", "pageTitle": "기안함", "elements": ["통계 카드", "검색바", "테이블", "페이지네이션"] }, "verification": [ "결재관리 메뉴가 펼쳐졌는지 확인", "기안함 서브메뉴 클릭 성공", "404 에러 없이 페이지 로드 완료" ] }, { "id": "step-2", "name": "페이지 구조 확인", "description": "페이지 타이틀, 설명, 통계 카드, 헤더 액션 버튼 확인", "actions": [ { "type": "verify", "target": "페이지 구조" } ], "expected": { "pageTitle": "기안함", "pageDescription": "작성한 결재 문서를 관리합니다", "icon": "FileText", "statCards": ["진행", "완료", "반려", "임시 저장"], "headerActions": ["날짜 범위 선택", "문서 작성 버튼"] } }, { "id": "step-3", "name": "통계 카드 표시 확인", "description": "4개의 통계 카드(진행, 완료, 반려, 임시 저장) 표시 및 건수 확인", "actions": [ { "type": "verify", "target": "통계 카드" } ], "expected": { "statCards": [ {"label": "진행", "format": "N건", "icon": "FileText", "color": "blue"}, {"label": "완료", "format": "N건", "icon": "FileText", "color": "green"}, {"label": "반려", "format": "N건", "icon": "FileText", "color": "red"}, {"label": "임시 저장", "format": "N건", "icon": "FileText", "color": "gray"} ], "apiCalled": "GET /api/v1/approvals/drafts/summary" } }, { "id": "step-4", "name": "테이블 컬럼 구조 확인", "description": "기안함 테이블의 컬럼 헤더 확인 (8개 컬럼)", "actions": [ { "type": "verify", "target": "table columns" } ], "expected": { "columns": [ "번호", "문서번호", "문서유형", "제목", "결재자", "기안일시", "상태", "작업" ], "hasCheckboxColumn": true } }, { "id": "step-5", "name": "데이터 로드 확인", "description": "기안 문서 데이터가 테이블에 표시되는지 확인", "actions": [ { "type": "verify", "target": "table data" } ], "expected": { "dataExists": "데이터 행 존재 또는 '데이터가 없습니다' 메시지", "apiCalled": "GET /api/v1/approvals/drafts?page=1&per_page=20", "defaultSort": "최신순 (created_at desc)", "defaultFilter": "전체" } }, { "id": "step-6", "name": "문서번호 형식 확인", "description": "문서번호가 정상적으로 표시되는지 확인", "actions": [ { "type": "verify", "target": "document number format" } ], "expected": { "format": "문서번호 형식 (예: DR-2026-001)", "column": "문서번호" } }, { "id": "step-7", "name": "문서유형 뱃지 표시 확인", "description": "문서유형이 뱃지 형태로 표시되는지 확인", "actions": [ { "type": "verify", "target": "document type badge" } ], "expected": { "displayFormat": "Badge (outline)", "possibleValues": ["품의서", "지출결의서", "예상지출내역"] } }, { "id": "step-8", "name": "결재자 표시 형식 확인", "description": "결재자가 '이름 외 N명' 형식으로 표시되는지 확인", "actions": [ { "type": "verify", "target": "approvers format" } ], "expected": { "format": "단일: '홍길동', 복수: '홍길동 외 2명'", "emptyFormat": "-" } }, { "id": "step-9", "name": "상태 뱃지 색상 확인", "description": "문서 상태별로 다른 색상의 뱃지가 표시되는지 확인", "actions": [ { "type": "verify", "target": "status badge colors" } ], "expected": { "statusColors": { "임시저장": "gray", "결재대기": "yellow", "진행중": "blue", "완료": "green", "반려": "red" } } }, { "id": "step-10", "name": "검색 기능 테스트", "description": "검색바에 키워드 입력 후 필터링 확인", "actions": [ { "type": "input", "target": "검색 입력 필드", "value": "테스트" }, { "type": "wait", "target": "검색 결과 로드" } ], "expected": { "searchPlaceholder": "문서번호, 제목, 기안자 검색...", "apiCalled": "GET /api/v1/approvals/drafts?search=테스트", "dataFiltered": "검색어 포함된 문서만 표시", "pageReset": "1페이지로 초기화" } }, { "id": "step-11", "name": "검색어 초기화", "description": "검색어를 지우고 전체 목록으로 복귀", "actions": [ { "type": "clear", "target": "검색 입력 필드" }, { "type": "wait", "target": "데이터 로드" } ], "expected": { "dataRestored": "전체 목록 표시", "apiCalled": "GET /api/v1/approvals/drafts?page=1" } }, { "id": "step-12", "name": "필터 셀렉트박스 존재 확인", "description": "상태 필터 드롭다운이 표시되는지 확인", "actions": [ { "type": "verify", "target": "filter select" } ], "expected": { "selectExists": true, "defaultValue": "전체", "options": ["전체", "임시저장", "결재대기", "진행중", "완료", "반려"] } }, { "id": "step-13", "name": "필터 적용 테스트 (임시저장)", "description": "필터를 '임시저장'으로 변경하여 필터링 확인", "actions": [ { "type": "select", "target": "필터 셀렉트박스", "value": "임시저장" }, { "type": "wait", "target": "데이터 로드" } ], "expected": { "apiCalled": "GET /api/v1/approvals/drafts?status=draft", "dataFiltered": "임시저장 상태만 표시", "pageReset": "1페이지로 초기화" } }, { "id": "step-14", "name": "필터 초기화", "description": "필터를 '전체'로 변경하여 전체 목록 표시", "actions": [ { "type": "select", "target": "필터 셀렉트박스", "value": "전체" }, { "type": "wait", "target": "데이터 로드" } ], "expected": { "apiCalled": "GET /api/v1/approvals/drafts?page=1", "dataRestored": "전체 상태 표시" } }, { "id": "step-15", "name": "정렬 셀렉트박스 존재 확인", "description": "정렬 옵션 드롭다운이 표시되는지 확인", "actions": [ { "type": "verify", "target": "sort select" } ], "expected": { "selectExists": true, "defaultValue": "최신순", "options": ["최신순", "오래된순", "제목 오름차순", "제목 내림차순"] } }, { "id": "step-16", "name": "정렬 변경 테스트 (제목 오름차순)", "description": "정렬을 '제목 오름차순'으로 변경", "actions": [ { "type": "select", "target": "정렬 셀렉트박스", "value": "제목 오름차순" }, { "type": "wait", "target": "데이터 로드" } ], "expected": { "apiCalled": "GET /api/v1/approvals/drafts?sort_by=title&sort_dir=asc", "dataSorted": "제목 알파벳 순서로 정렬", "pageReset": "1페이지로 초기화" } }, { "id": "step-17", "name": "정렬 초기화", "description": "정렬을 '최신순'으로 복귀", "actions": [ { "type": "select", "target": "정렬 셀렉트박스", "value": "최신순" }, { "type": "wait", "target": "데이터 로드" } ], "expected": { "apiCalled": "GET /api/v1/approvals/drafts?sort_by=created_at&sort_dir=desc", "dataRestored": "최신순 정렬" } }, { "id": "step-18", "name": "체크박스 선택 (단일)", "description": "첫 번째 문서의 체크박스 선택", "actions": [ { "type": "click", "target": "첫 번째 행 체크박스" } ], "expected": { "checkboxChecked": true, "selectedCount": 1, "actionButtonsVisible": "상신, 삭제 버튼 표시" } }, { "id": "step-19", "name": "임시저장 문서 수정/삭제 버튼 표시 확인", "description": "임시저장 상태 문서 선택 시 작업 컬럼에 수정/삭제 버튼 표시", "actions": [ { "type": "verify", "target": "action buttons for draft status" } ], "expected": { "condition": "status === 'draft' && isSelected", "buttonsVisible": ["수정 (Pencil 아이콘)", "삭제 (Trash2 아이콘)"], "buttonColors": { "수정": "gray", "삭제": "red" } } }, { "id": "step-20", "name": "체크박스 해제", "description": "선택한 체크박스를 다시 클릭하여 해제", "actions": [ { "type": "click", "target": "첫 번째 행 체크박스" } ], "expected": { "checkboxChecked": false, "selectedCount": 0, "actionButtonsHidden": "상신, 삭제 버튼 숨김" } }, { "id": "step-21", "name": "전체 선택 체크박스 클릭", "description": "테이블 헤더의 전체 선택 체크박스 클릭", "actions": [ { "type": "click", "target": "헤더 체크박스 (전체 선택)" } ], "expected": { "allCheckboxesChecked": true, "selectedCount": "현재 페이지의 모든 행 수", "actionButtonsVisible": "상신, 삭제 버튼 표시" } }, { "id": "step-22", "name": "전체 선택 해제", "description": "전체 선택 체크박스를 다시 클릭하여 모두 해제", "actions": [ { "type": "click", "target": "헤더 체크박스 (전체 선택)" } ], "expected": { "allCheckboxesUnchecked": true, "selectedCount": 0, "actionButtonsHidden": "상신, 삭제 버튼 숨김" } }, { "id": "step-23", "name": "문서 작성 버튼 확인", "description": "헤더 액션에 '문서 작성' 버튼이 표시되는지 확인", "actions": [ { "type": "verify", "target": "문서 작성 버튼" } ], "expected": { "buttonExists": true, "buttonText": "문서 작성", "icon": "Plus" } }, { "id": "step-24", "name": "문서 클릭 (임시저장)", "description": "임시저장 상태의 문서 행 클릭 (수정 모드로 이동)", "actions": [ { "type": "click", "target": "임시저장 상태의 문서 행" } ], "expected": { "urlChange": "/ko/approval/draft/new?id={id}&mode=edit", "behavior": "문서 작성 페이지로 이동 (수정 모드)" } }, { "id": "step-25", "name": "기안함으로 복귀", "description": "문서 작성 페이지에서 기안함으로 돌아오기", "actions": [ { "type": "navigate", "target": "/ko/approval/draft" } ], "expected": { "url": "/ko/approval/draft", "dataReloaded": "목록 재로드" } }, { "id": "step-26", "name": "문서 클릭 (결재대기/진행중/완료)", "description": "임시저장이 아닌 문서 행 클릭 (상세 모달 오픈)", "actions": [ { "type": "click", "target": "결재대기/진행중/완료 상태의 문서 행" }, { "type": "wait", "target": "모달 오픈 및 상세 데이터 로드" } ], "expected": { "modalOpened": true, "apiCalled": "GET /api/v1/approvals/{id}", "modalTitle": "문서 상세" } }, { "id": "step-27", "name": "문서 상세 모달 구조 확인", "description": "문서 상세 모달의 구조 및 내용 확인", "actions": [ { "type": "verify", "target": "document detail modal" } ], "expected": { "modalContent": [ "문서번호", "기안일시", "결재자 목록 (최대 3명)", "문서 내용 (문서 유형에 따라 다름)" ], "documentTypes": ["품의서 (proposal)", "지출결의서 (expenseReport)", "예상지출내역 (expenseEstimate)"] } }, { "id": "step-28", "name": "모달 수정 버튼 확인", "description": "모달 하단에 수정 버튼이 표시되는지 확인", "actions": [ { "type": "verify", "target": "modal edit button" } ], "expected": { "buttonExists": true, "buttonText": "수정", "behavior": "클릭 시 문서 작성 페이지로 이동 (수정 모드)" } }, { "id": "step-29", "name": "모달 복제 버튼 확인", "description": "모달 하단에 복제 버튼이 표시되는지 확인", "actions": [ { "type": "verify", "target": "modal copy button" } ], "expected": { "buttonExists": true, "buttonText": "복제", "behavior": "클릭 시 문서 작성 페이지로 이동 (복제 모드, copyFrom 파라미터)" } }, { "id": "step-30", "name": "모달 상신 버튼 확인 (임시저장 시)", "description": "임시저장 문서의 모달에서 상신 버튼 확인", "actions": [ { "type": "verify", "target": "modal submit button" } ], "expected": { "buttonExists": "임시저장 상태일 때만", "buttonText": "상신", "behavior": "클릭 시 결재 상신 (POST /api/v1/approvals/{id}/submit)" } }, { "id": "step-31", "name": "모달 닫기", "description": "문서 상세 모달을 닫기", "actions": [ { "type": "click", "target": "모달 외부 또는 닫기 버튼" } ], "expected": { "modalClosed": true, "returnToList": "기안함 목록으로 복귀" } }, { "id": "step-31-pdf-1", "name": "⚠️ 필수 검증: PDF 다운로드 전 모달 스크린샷", "critical": true, "description": "PDF 생성 전 모달 상태를 스크린샷으로 캡처하여 CSS 문제 감지용 기준 이미지 확보", "prerequisite": "step-26의 문서 상세 모달이 열려있는 상태에서 실행", "actions": [ { "type": "click", "target": "결재대기/진행중/완료 상태의 문서 행", "description": "모달 다시 열기" }, { "type": "wait", "duration": 1000, "description": "모달 로드 대기" }, { "type": "screenshot", "name": "pdf-preview-before-download-draft-box", "fullPage": false, "selector": "[role='dialog'], .modal, [data-state='open']", "savePath": "tests/e2e/results/hotfix/screenshots/", "description": "PDF 생성 대상 모달 전체 캡처" } ], "verify": { "screenshotCaptured": true, "purpose": "PDF CSS 문제 감지를 위한 기준 이미지" } }, { "id": "step-31-pdf-2", "name": "⚠️ 필수 검증: PDF 다운로드 실행 및 파일 보관", "critical": true, "description": "PDF 다운로드 후 파일을 지정 폴더에 보관하여 수동 검증 가능하게 함", "actions": [ { "type": "verify", "target": "PDF 버튼 존재", "selector": "button:has-text('PDF'), [aria-label*='PDF']", "description": "PDF 다운로드 버튼 존재 확인" }, { "type": "expectResponse", "id": "pdf-download-response-draft-box", "urlPattern": "/api/v1/approvals/*/pdf", "description": "PDF 다운로드 API 응답 대기 설정" }, { "type": "click", "target": "PDF 버튼", "selector": "button:has-text('PDF')", "description": "PDF 다운로드 버튼 클릭" }, { "type": "wait", "duration": 3000, "description": "PDF 생성 및 다운로드 대기" }, { "type": "assertResponse", "id": "pdf-download-response-draft-box", "checks": { "status": 200, "contentType": "application/pdf" } }, { "type": "saveDownloadedFile", "targetPath": "tests/e2e/results/hotfix/pdf-samples/", "fileNamePattern": "draft-box-{timestamp}.pdf", "description": "다운로드된 PDF 파일을 지정 폴더에 보관" } ], "verify": { "apiSuccess": true, "fileDownloaded": true, "fileSaved": "tests/e2e/results/hotfix/pdf-samples/" } }, { "id": "step-31-pdf-3", "name": "⚠️ PDF 파일 유효성 검증", "critical": true, "description": "다운로드된 PDF 파일의 기본 유효성 검사", "actions": [ { "type": "verifyDownloadedFile", "checks": { "fileExists": true, "fileSize": "> 1024", "pdfSignature": "%PDF-", "description": "PDF 파일 헤더 검증" } } ], "verify": { "pdfValid": true, "minFileSize": "1KB 이상" } }, { "id": "step-31-pdf-4", "name": "📋 PDF 스타일 수동 확인 체크리스트", "type": "manualVerification", "critical": true, "description": "개발자가 다운로드된 PDF를 열어 시각적으로 확인해야 하는 항목", "manualChecklist": [ {"id": "css-1", "item": "테이블 경계선이 올바르게 표시되는가?", "category": "테이블 스타일"}, {"id": "css-2", "item": "한글 폰트가 깨지지 않고 정상 표시되는가?", "category": "폰트"}, {"id": "css-3", "item": "숫자/금액 정렬이 올바른가? (우측 정렬)", "category": "정렬"}, {"id": "css-4", "item": "여백(margin/padding)이 적절한가?", "category": "레이아웃"}, {"id": "css-5", "item": "헤더/푸터가 각 페이지에 올바르게 표시되는가?", "category": "페이지 구조"}, {"id": "css-6", "item": "로고/이미지가 정상 표시되는가?", "category": "이미지"}, {"id": "css-7", "item": "페이지 나눔(page break)이 적절한 위치에서 발생하는가?", "category": "페이지 나눔"}, {"id": "css-8", "item": "배경색/강조색이 올바르게 적용되었는가?", "category": "색상"}, {"id": "css-9", "item": "텍스트가 잘리거나 겹치지 않는가?", "category": "오버플로우"}, {"id": "css-10", "item": "결재선 정보가 정상적으로 표시되는가?", "category": "결재선"} ], "outputFiles": { "screenshot": "tests/e2e/results/hotfix/screenshots/pdf-preview-before-download-draft-box-*.png", "pdfFile": "tests/e2e/results/hotfix/pdf-samples/draft-box-*.pdf" }, "reportFlag": { "requiresManualReview": true, "message": "⚠️ PDF 스타일 수동 확인 필요 - 위 체크리스트 항목을 PDF 파일에서 직접 확인하세요" } }, { "id": "step-31-pdf-5", "name": "모달 닫기 (PDF 테스트 후)", "description": "PDF 테스트 완료 후 모달 닫기", "actions": [ { "type": "click", "target": "모달 외부 또는 닫기 버튼" } ], "expected": { "modalClosed": true } }, { "id": "step-32", "name": "날짜 범위 선택 확인", "description": "헤더 액션에 날짜 범위 선택 컴포넌트가 표시되는지 확인", "actions": [ { "type": "verify", "target": "date range selector" } ], "expected": { "componentExists": true, "defaultStartDate": "2025-01-01", "defaultEndDate": "2025-12-31", "inputs": ["시작일 입력", "종료일 입력"] } }, { "id": "step-33", "name": "페이지네이션 존재 확인", "description": "테이블 하단에 페이지네이션이 표시되는지 확인", "actions": [ { "type": "verify", "target": "pagination component" } ], "expected": { "paginationExists": true, "showsCurrentPage": "현재 페이지 번호", "showsTotalPages": "전체 페이지 수", "showsTotalItems": "전체 항목 수", "itemsPerPage": 20 } }, { "id": "step-34", "name": "페이지네이션 이동 테스트", "description": "2페이지가 있는 경우 페이지 이동 테스트", "actions": [ { "type": "click", "target": "페이지 2 버튼 (또는 다음 버튼)" }, { "type": "wait", "target": "데이터 로드" } ], "expected": { "currentPage": 2, "apiCalled": "GET /api/v1/approvals/drafts?page=2", "dataChanged": "2페이지 데이터 표시", "scrollToTop": "페이지 상단으로 스크롤" } }, { "id": "step-35", "name": "1페이지로 복귀", "description": "페이지네이션에서 1페이지로 이동", "actions": [ { "type": "click", "target": "페이지 1 버튼" }, { "type": "wait", "target": "데이터 로드" } ], "expected": { "currentPage": 1, "apiCalled": "GET /api/v1/approvals/drafts?page=1", "dataRestored": "1페이지 데이터 표시" } }, { "id": "step-36", "name": "테이블 hover 효과 확인", "description": "테이블 행에 마우스 오버 시 배경색 변경 확인", "actions": [ { "type": "hover", "target": "첫 번째 테이블 행" } ], "expected": { "hoverEffect": "hover:bg-muted/50", "backgroundChanges": true, "cursorPointer": true } }, { "id": "step-37", "name": "로딩 상태 확인", "description": "데이터 로드 중 로딩 인디케이터 표시 확인", "actions": [ { "type": "verify", "target": "loading state" } ], "expected": { "loadingIndicator": "스피너 또는 로딩 메시지", "isLoading": "true during data fetch" } }, { "id": "step-38", "name": "빈 상태 메시지 확인", "description": "검색/필터 결과가 없을 때 빈 상태 메시지 표시", "actions": [ { "type": "input", "target": "검색 입력 필드", "value": "존재하지않는문서번호999999" }, { "type": "wait", "target": "검색 결과" } ], "expected": { "emptyMessage": "데이터가 없습니다.", "messagePosition": "테이블 중앙" } }, { "id": "step-39", "name": "검색어 초기화 (빈 상태 해제)", "description": "검색어를 지워서 전체 목록으로 복귀", "actions": [ { "type": "clear", "target": "검색 입력 필드" }, { "type": "wait", "target": "데이터 로드" } ], "expected": { "dataRestored": "전체 목록 표시" } }, { "id": "step-40", "name": "콘솔 에러 확인", "description": "페이지 동작 중 콘솔에 에러가 발생하지 않는지 확인", "actions": [ { "type": "verify", "target": "console errors" } ], "expected": { "noErrors": "콘솔 에러 없음", "warningsAcceptable": "경고는 허용" } }, { "id": "step-41", "name": "반응형 레이아웃 확인", "description": "모바일 뷰에서 카드 레이아웃으로 표시되는지 확인", "actions": [ { "type": "verify", "target": "mobile card layout" } ], "expected": { "mobileCardExists": "화면 크기에 따라", "cardTitle": "문서 제목", "cardFields": ["문서번호", "기안일자", "기안자", "결재자"] } }, { "id": "step-42", "name": "모바일 카드 액션 버튼 확인", "description": "모바일 카드에서 임시저장 문서 선택 시 수정/삭제 버튼 표시", "actions": [ { "type": "verify", "target": "mobile card actions" } ], "expected": { "condition": "status === 'draft' && isSelected", "buttons": ["수정", "삭제"], "buttonIcons": ["Pencil", "Trash2"] } }, { "id": "step-43", "name": "통계 카드 실시간 업데이트 확인", "description": "문서 상신/삭제 후 통계 카드가 업데이트되는지 확인", "actions": [ { "type": "verify", "target": "stat cards update after action" } ], "expected": { "updateTriggers": ["상신 성공", "삭제 성공"], "apiCalled": "GET /api/v1/approvals/drafts/summary" } }, { "id": "step-44", "name": "IntegratedListTemplateV2 사용 확인", "description": "IntegratedListTemplateV2 템플릿 컴포넌트 사용 확인", "actions": [ { "type": "verify", "target": "template component" } ], "expected": { "templateComponent": "IntegratedListTemplateV2", "responsive": "모바일/데스크톱 대응" } }, { "id": "step-45", "name": "상신 버튼 조건부 표시 확인", "description": "항목 선택 시에만 상신 버튼이 표시되는지 확인", "actions": [ { "type": "verify", "target": "submit button visibility" } ], "expected": { "condition": "selectedItems.size > 0", "buttonVisible": true, "buttonText": "상신", "icon": "Send" } }, { "id": "step-46", "name": "삭제 버튼 조건부 표시 확인", "description": "항목 선택 시에만 삭제 버튼이 표시되는지 확인", "actions": [ { "type": "verify", "target": "delete button visibility" } ], "expected": { "condition": "selectedItems.size > 0", "buttonVisible": true, "buttonText": "삭제", "icon": "Trash2", "variant": "destructive (red)" } }, { "id": "step-47", "name": "결재자 상태 뱃지 확인", "description": "모달 내 결재자 목록의 상태 뱃지 색상 확인", "actions": [ { "type": "verify", "target": "approver status badges in modal" } ], "expected": { "statusColors": { "none": "gray", "pending": "yellow", "approved": "green", "rejected": "red" } } }, { "id": "step-48", "name": "문서 유형별 모달 내용 확인", "description": "문서 유형(품의서, 지출결의서, 예상지출내역)에 따라 다른 내용 표시", "actions": [ { "type": "verify", "target": "document type specific content" } ], "expected": { "proposal": ["거래처", "거래처 지급일", "제목", "내용", "사유", "예상금액", "첨부파일"], "expenseReport": ["신청일", "지급일", "지출 내역", "카드 정보", "총액", "첨부파일"], "expenseEstimate": ["예상지급일", "카테고리", "금액", "거래처", "계좌", "총 지출", "계좌 잔액", "최종 차액"] } }, { "id": "step-49", "name": "API 응답 구조 확인", "description": "기안함 목록 API 응답이 올바른 구조인지 확인", "actions": [ { "type": "verify", "target": "API response structure" } ], "expected": { "responseStructure": { "success": true, "data": { "current_page": "number", "data": "Array", "total": "number", "per_page": "number", "last_page": "number" } } } }, { "id": "step-50", "name": "데이터 변환 확인", "description": "API 데이터가 프론트엔드 형식으로 변환되는지 확인", "actions": [ { "type": "verify", "target": "data transformation" } ], "expected": { "apiFormat": "snake_case (document_number, created_at, approval_steps)", "frontendFormat": "camelCase (documentNo, draftDate, approvers)", "transformFunction": "transformApiToFrontend", "statusMapping": { "draft": "draft", "pending": "pending", "in_progress": "inProgress", "approved": "approved", "rejected": "rejected" } } } ], "cleanup": { "description": "테스트 후 정리 작업 (없음)", "actions": [] }, "notes": [ "20개씩 페이지네이션 (itemsPerPage: 20)", "검색 필드: 문서번호, 제목, 기안자 검색 가능", "필터: 전체, 임시저장, 결재대기, 진행중, 완료, 반려", "정렬: 최신순, 오래된순, 제목 오름차순, 제목 내림차순", "체크박스: 개별 선택, 전체 선택 가능", "상신/삭제: 선택된 항목이 있을 때만 버튼 표시", "임시저장 문서: 선택 시 작업 컬럼에 수정/삭제 버튼 표시", "문서 클릭 동작: 임시저장 → 수정 페이지, 그 외 → 상세 모달", "통계 카드: API summary로 실시간 업데이트", "IntegratedListTemplateV2 템플릿 사용으로 반응형 지원", "날짜 범위 선택 기본값: 2025-01-01 ~ 2025-12-31", "결재자 표시: 단일(이름), 복수(이름 외 N명)", "모달 버튼: 수정, 복제, 상신(임시저장만)", "승인/반려 버튼 없음 (기안함에서는 본인 문서 승인/반려 불가)" ] }