2026-01-30 10:50:38 +09:00
|
|
|
{
|
|
|
|
|
"id": "crud-delete-freeboard",
|
|
|
|
|
"name": "자유게시판 CRUD 삭제 기능 테스트",
|
|
|
|
|
"screenshotPolicy": {
|
|
|
|
|
"onErrorOnly": true,
|
|
|
|
|
"captureOn": ["error", "fail", "timeout", "404", "500", "blocked"]
|
|
|
|
|
},
|
|
|
|
|
"description": "자유게시판에서 생성 → 수정 → 삭제 전체 CRUD 흐름 테스트. 테스트용 게시글을 생성하고, 수정한 후, 삭제하여 기존 데이터에 영향 없이 삭제 기능을 검증",
|
|
|
|
|
"baseUrl": "https://dev.codebridge-x.com",
|
|
|
|
|
"menuNavigation": {
|
2026-02-02 08:08:44 +09:00
|
|
|
"level1": "게시판",
|
2026-01-30 10:50:38 +09:00
|
|
|
"level2": "자유게시판",
|
2026-02-02 08:08:44 +09:00
|
|
|
"expectedUrl": "/ko/boards/free"
|
2026-01-30 10:50:38 +09:00
|
|
|
},
|
|
|
|
|
"auth": {
|
|
|
|
|
"username": "TestUser5",
|
|
|
|
|
"password": "password123!"
|
|
|
|
|
},
|
|
|
|
|
"testPolicy": {
|
|
|
|
|
"deleteAllowed": true,
|
|
|
|
|
"deleteCondition": "CRUD 흐름 내에서만 허용 (생성 → 수정 → 삭제)",
|
|
|
|
|
"protectExistingData": true,
|
|
|
|
|
"description": "이 시나리오에서 생성한 테스트 데이터만 삭제"
|
|
|
|
|
},
|
|
|
|
|
"modalHandling": {
|
|
|
|
|
"description": "모달 창 처리 규칙",
|
|
|
|
|
"closeMethods": [
|
|
|
|
|
{"priority": 1, "method": "완료 버튼", "selector": "button:has-text('확인'), button:has-text('등록'), button:has-text('저장')"},
|
|
|
|
|
{"priority": 2, "method": "취소 버튼", "selector": "button:has-text('취소'), [class*='cancel']"},
|
|
|
|
|
{"priority": 3, "method": "X 버튼", "selector": "button[class*='close'], [aria-label='닫기'], [aria-label='Close']"},
|
|
|
|
|
{"priority": 4, "method": "ESC 키", "action": "press_key('Escape')"},
|
|
|
|
|
{"priority": 5, "method": "외부 클릭", "selector": "[class*='backdrop'], [class*='overlay']"}
|
|
|
|
|
],
|
|
|
|
|
"deleteDialogSelector": "[role='alertdialog'] button:has-text('삭제')",
|
|
|
|
|
"note": "삭제 확인 다이얼로그는 Playwright 네이티브 셀렉터 사용 필수 (JavaScript click 미동작)",
|
|
|
|
|
"rule": "모달이 열린 상태로 다음 단계 진행 금지"
|
|
|
|
|
},
|
|
|
|
|
"testData": {
|
|
|
|
|
"newPost": {
|
|
|
|
|
"title": "E2E테스트_삭제용_",
|
|
|
|
|
"content": "이 게시글은 E2E 테스트용으로 생성되었습니다. 테스트 완료 후 자동 삭제됩니다."
|
|
|
|
|
},
|
|
|
|
|
"updateData": {
|
|
|
|
|
"title": "E2E테스트_수정완료_"
|
|
|
|
|
},
|
|
|
|
|
"uniqueIdentifier": "timestamp를 붙여서 고유성 보장 (MMDDHHmmss)"
|
|
|
|
|
},
|
|
|
|
|
"steps": [
|
|
|
|
|
{
|
|
|
|
|
"id": "step-0",
|
|
|
|
|
"name": "사이드바 메뉴 탐색",
|
2026-02-02 08:08:44 +09:00
|
|
|
"description": "게시판 > 자유게시판 메뉴로 이동",
|
2026-01-30 10:50:38 +09:00
|
|
|
"actions": [
|
2026-02-02 08:08:44 +09:00
|
|
|
{"type": "scroll", "target": "sidebar", "direction": "top", "description": "사이드바 상단으로 스크롤"},
|
2026-01-30 10:50:38 +09:00
|
|
|
{"type": "wait", "duration": 300},
|
2026-02-02 08:08:44 +09:00
|
|
|
{"type": "click", "target": "게시판", "description": "1차 메뉴 클릭"},
|
2026-01-30 10:50:38 +09:00
|
|
|
{"type": "wait", "duration": 500},
|
|
|
|
|
{"type": "click", "target": "자유게시판", "description": "2차 메뉴 클릭"},
|
|
|
|
|
{"type": "wait", "duration": 2000}
|
|
|
|
|
],
|
|
|
|
|
"expect": {
|
2026-02-02 08:08:44 +09:00
|
|
|
"url": "/ko/boards/free",
|
2026-01-30 10:50:38 +09:00
|
|
|
"no404": true
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"id": "step-1",
|
|
|
|
|
"phase": "CREATE",
|
|
|
|
|
"name": "[CREATE] 초기 상태 확인",
|
|
|
|
|
"description": "등록 전 게시글 수 확인",
|
|
|
|
|
"actions": [
|
|
|
|
|
{"type": "capture", "variable": "initialRowCount", "selector": "table tbody tr", "extract": "count", "description": "등록 전 행 수 저장"},
|
|
|
|
|
{"type": "wait", "duration": 500}
|
|
|
|
|
],
|
|
|
|
|
"expect": {
|
|
|
|
|
"tableExists": true
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"id": "step-2",
|
|
|
|
|
"phase": "CREATE",
|
|
|
|
|
"name": "[CREATE] 등록 버튼 클릭",
|
|
|
|
|
"description": "새 게시글을 등록하기 위해 등록 버튼 클릭",
|
|
|
|
|
"actions": [
|
|
|
|
|
{"type": "click", "target": "button:has-text('등록')", "description": "등록 버튼 클릭"},
|
|
|
|
|
{"type": "wait", "duration": 1500}
|
|
|
|
|
],
|
|
|
|
|
"expect": {
|
2026-02-02 08:08:44 +09:00
|
|
|
"url": "/ko/boards/free/new",
|
2026-01-30 10:50:38 +09:00
|
|
|
"pageTitle": "게시글 작성"
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"id": "step-3",
|
|
|
|
|
"phase": "CREATE",
|
|
|
|
|
"name": "[CREATE] 게시글 정보 입력",
|
|
|
|
|
"description": "테스트용 게시글 정보 입력 (타임스탬프로 고유성 보장)",
|
|
|
|
|
"actions": [
|
|
|
|
|
{"type": "generateTimestamp", "variable": "testTimestamp", "format": "MMDDHHmmss"},
|
|
|
|
|
{"type": "fill", "target": "input[name='title'], input[placeholder*='제목']", "value": "E2E테스트_삭제용_{testTimestamp}", "description": "고유한 제목 입력"},
|
|
|
|
|
{"type": "fill", "target": "textarea, [class*='editor'], [contenteditable='true']", "value": "E2E 테스트용 게시글입니다. 자동 삭제 예정.", "description": "본문 입력"}
|
|
|
|
|
],
|
|
|
|
|
"note": "타임스탬프를 사용하여 매 테스트마다 고유한 데이터 생성"
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"id": "step-4",
|
|
|
|
|
"phase": "CREATE",
|
|
|
|
|
"name": "[CREATE] 등록 실행",
|
|
|
|
|
"description": "입력된 정보로 게시글 등록 실행",
|
|
|
|
|
"actions": [
|
|
|
|
|
{"type": "click", "target": "button:has-text('등록')", "description": "등록 버튼 클릭"},
|
|
|
|
|
{"type": "wait", "duration": 2000}
|
|
|
|
|
],
|
|
|
|
|
"expect": {
|
|
|
|
|
"toast": "등록|완료|성공",
|
2026-02-02 08:08:44 +09:00
|
|
|
"redirect": "/ko/boards/free"
|
2026-01-30 10:50:38 +09:00
|
|
|
},
|
|
|
|
|
"verification": {
|
|
|
|
|
"level": 4,
|
|
|
|
|
"checks": ["성공 토스트 표시", "목록 페이지로 이동"]
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"id": "step-5",
|
|
|
|
|
"phase": "CREATE",
|
|
|
|
|
"name": "[CREATE] 등록 결과 확인",
|
|
|
|
|
"description": "테이블에 새로 등록한 게시글이 표시되는지 확인",
|
|
|
|
|
"actions": [
|
|
|
|
|
{"type": "wait", "duration": 1000},
|
|
|
|
|
{"type": "capture", "variable": "afterCreateCount", "selector": "table tbody tr", "extract": "count"},
|
|
|
|
|
{"type": "verify", "condition": "afterCreateCount > initialRowCount", "description": "행 수 증가 확인"}
|
|
|
|
|
],
|
|
|
|
|
"expect": {
|
|
|
|
|
"rowCountIncreased": true,
|
|
|
|
|
"rowContains": "E2E테스트_삭제용"
|
|
|
|
|
},
|
|
|
|
|
"verification": {
|
|
|
|
|
"level": 4,
|
|
|
|
|
"description": "생성된 데이터가 목록에 표시되어야 함"
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"id": "step-6",
|
|
|
|
|
"phase": "UPDATE",
|
|
|
|
|
"name": "[UPDATE] 생성된 게시글 상세 페이지 진입",
|
|
|
|
|
"description": "생성한 테스트 게시글의 상세 페이지로 이동",
|
|
|
|
|
"actions": [
|
|
|
|
|
{"type": "click", "target": "table tbody tr:first-child td:nth-child(2)", "description": "첫 번째 행 (방금 생성한 게시글) 클릭"},
|
|
|
|
|
{"type": "wait", "duration": 2000}
|
|
|
|
|
],
|
|
|
|
|
"expect": {
|
2026-02-02 08:08:44 +09:00
|
|
|
"url": "/ko/boards/free/",
|
2026-01-30 10:50:38 +09:00
|
|
|
"pageContains": "E2E테스트_삭제용"
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"id": "step-7",
|
|
|
|
|
"phase": "UPDATE",
|
|
|
|
|
"name": "[UPDATE] 수정 버튼 클릭",
|
|
|
|
|
"description": "수정 버튼을 클릭하여 편집 모드로 전환",
|
|
|
|
|
"actions": [
|
|
|
|
|
{"type": "click", "target": "button:has-text('수정')", "description": "수정 버튼 클릭"},
|
|
|
|
|
{"type": "wait", "duration": 1500}
|
|
|
|
|
],
|
|
|
|
|
"expect": {
|
|
|
|
|
"url": "/edit",
|
|
|
|
|
"fieldsEditable": true
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"id": "step-8",
|
|
|
|
|
"phase": "UPDATE",
|
|
|
|
|
"name": "[UPDATE] 제목 수정",
|
|
|
|
|
"description": "게시글 제목을 수정하여 UPDATE 동작 확인",
|
|
|
|
|
"actions": [
|
|
|
|
|
{"type": "clear", "target": "input[name='title'], input[placeholder*='제목']", "description": "기존 제목 삭제"},
|
|
|
|
|
{"type": "fill", "target": "input[name='title'], input[placeholder*='제목']", "value": "E2E테스트_수정완료_{testTimestamp}", "description": "수정된 제목 입력"}
|
|
|
|
|
]
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"id": "step-9",
|
|
|
|
|
"phase": "UPDATE",
|
|
|
|
|
"name": "[UPDATE] 수정 저장",
|
|
|
|
|
"description": "수정된 내용 저장",
|
|
|
|
|
"actions": [
|
|
|
|
|
{"type": "click", "target": "button:has-text('수정')", "description": "수정 버튼 클릭"},
|
|
|
|
|
{"type": "wait", "duration": 2000}
|
|
|
|
|
],
|
|
|
|
|
"expect": {
|
|
|
|
|
"toast": "수정|완료|성공",
|
2026-02-02 08:08:44 +09:00
|
|
|
"redirect": "/ko/boards/free/"
|
2026-01-30 10:50:38 +09:00
|
|
|
},
|
|
|
|
|
"verification": {
|
|
|
|
|
"level": 4,
|
|
|
|
|
"description": "수정 성공 토스트 확인"
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"id": "step-10",
|
|
|
|
|
"phase": "UPDATE",
|
|
|
|
|
"name": "[UPDATE] 수정 결과 확인",
|
|
|
|
|
"description": "수정된 내용이 반영되었는지 확인",
|
|
|
|
|
"actions": [
|
|
|
|
|
{"type": "wait", "duration": 1000},
|
|
|
|
|
{"type": "verify", "target": "page", "contains": "E2E테스트_수정완료", "description": "수정된 제목 표시 확인"}
|
|
|
|
|
],
|
|
|
|
|
"expect": {
|
|
|
|
|
"contains": "E2E테스트_수정완료"
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"id": "step-11",
|
|
|
|
|
"phase": "DELETE",
|
|
|
|
|
"name": "[DELETE] 삭제 버튼 클릭",
|
|
|
|
|
"description": "테스트용으로 생성한 게시글 삭제 시작",
|
|
|
|
|
"critical": true,
|
|
|
|
|
"actions": [
|
|
|
|
|
{"type": "click", "target": "button:has-text('삭제')", "description": "삭제 버튼 클릭"},
|
|
|
|
|
{"type": "wait", "duration": 500}
|
|
|
|
|
],
|
|
|
|
|
"expect": {
|
|
|
|
|
"confirmDialog": true,
|
|
|
|
|
"dialogRole": "alertdialog"
|
|
|
|
|
},
|
|
|
|
|
"warning": "이 단계에서 삭제 확인 다이얼로그가 표시되어야 함"
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"id": "step-12",
|
|
|
|
|
"phase": "DELETE",
|
|
|
|
|
"name": "[DELETE] 삭제 확인",
|
|
|
|
|
"description": "삭제 확인 다이얼로그에서 삭제 버튼 클릭",
|
|
|
|
|
"critical": true,
|
|
|
|
|
"actions": [
|
|
|
|
|
{"type": "click", "target": "[role='alertdialog'] button:has-text('삭제')", "usePlaywrightNative": true, "description": "삭제 확인 클릭 (Playwright 네이티브 셀렉터 필수)"},
|
|
|
|
|
{"type": "wait", "duration": 2000}
|
|
|
|
|
],
|
|
|
|
|
"expect": {
|
|
|
|
|
"toast": "삭제|완료|성공",
|
2026-02-02 08:08:44 +09:00
|
|
|
"redirect": "/ko/boards/free"
|
2026-01-30 10:50:38 +09:00
|
|
|
},
|
|
|
|
|
"verification": {
|
|
|
|
|
"level": 4,
|
|
|
|
|
"checks": ["성공 토스트", "목록 페이지로 리다이렉트"]
|
|
|
|
|
},
|
|
|
|
|
"note": "JavaScript click()은 동작하지 않음. Playwright playwright_click 사용 필수"
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"id": "step-13",
|
|
|
|
|
"phase": "VERIFY",
|
|
|
|
|
"name": "[VERIFY] 삭제 결과 확인",
|
|
|
|
|
"description": "삭제된 게시글이 목록에서 제거되었는지 확인",
|
|
|
|
|
"actions": [
|
|
|
|
|
{"type": "wait", "duration": 1000},
|
2026-02-02 08:08:44 +09:00
|
|
|
{"type": "verifyUrl", "contains": "/ko/boards/free", "description": "목록 페이지 확인"},
|
2026-01-30 10:50:38 +09:00
|
|
|
{"type": "capture", "variable": "afterDeleteCount", "selector": "table tbody tr", "extract": "count"}
|
|
|
|
|
],
|
|
|
|
|
"expect": {
|
|
|
|
|
"rowCountDecreased": true,
|
|
|
|
|
"condition": "afterDeleteCount === initialRowCount"
|
|
|
|
|
},
|
|
|
|
|
"verification": {
|
|
|
|
|
"level": 4,
|
|
|
|
|
"description": "행 수가 원래대로 복구되어야 함"
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"id": "step-14",
|
|
|
|
|
"phase": "VERIFY",
|
|
|
|
|
"name": "[VERIFY] 최종 검증",
|
|
|
|
|
"description": "테스트 데이터가 완전히 삭제되었는지 확인",
|
|
|
|
|
"actions": [
|
|
|
|
|
{"type": "verify", "target": "table", "notContains": "E2E테스트_수정완료", "description": "삭제된 게시글이 목록에 없음 확인"}
|
|
|
|
|
],
|
|
|
|
|
"expect": {
|
|
|
|
|
"testDataDeleted": true,
|
|
|
|
|
"noTestDataInList": true
|
|
|
|
|
},
|
|
|
|
|
"verification": {
|
|
|
|
|
"level": 4,
|
|
|
|
|
"description": "테스트 데이터가 완전히 삭제되어 목록에 표시되지 않아야 함"
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
],
|
|
|
|
|
"expectedAPIs": [
|
|
|
|
|
{
|
|
|
|
|
"phase": "CREATE",
|
|
|
|
|
"method": "POST",
|
|
|
|
|
"endpoint": "/api/v1/free-board",
|
|
|
|
|
"description": "게시글 등록"
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"phase": "UPDATE",
|
|
|
|
|
"method": "PUT",
|
|
|
|
|
"endpoint": "/api/v1/free-board/{id}",
|
|
|
|
|
"description": "게시글 수정"
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"phase": "DELETE",
|
|
|
|
|
"method": "DELETE",
|
|
|
|
|
"endpoint": "/api/v1/free-board/{id}",
|
|
|
|
|
"description": "게시글 삭제"
|
|
|
|
|
}
|
|
|
|
|
],
|
|
|
|
|
"requiredVerifications": [
|
|
|
|
|
{
|
|
|
|
|
"id": 1,
|
|
|
|
|
"name": "CREATE - 등록 기능",
|
|
|
|
|
"steps": ["step-2", "step-3", "step-4", "step-5"],
|
|
|
|
|
"criteria": "게시글 생성 + 목록에 표시"
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"id": 2,
|
|
|
|
|
"name": "UPDATE - 수정 기능",
|
|
|
|
|
"steps": ["step-7", "step-8", "step-9", "step-10"],
|
|
|
|
|
"criteria": "게시글 수정 + 변경 내용 반영"
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"id": 3,
|
|
|
|
|
"name": "DELETE - 삭제 기능",
|
|
|
|
|
"steps": ["step-11", "step-12", "step-13", "step-14"],
|
|
|
|
|
"criteria": "게시글 삭제 + 목록에서 제거"
|
|
|
|
|
}
|
|
|
|
|
],
|
|
|
|
|
"knownIssues": [
|
|
|
|
|
{
|
|
|
|
|
"issue": "삭제 확인 다이얼로그 JavaScript click 미동작",
|
|
|
|
|
"description": "JavaScript의 element.click() 또는 dispatchEvent로는 삭제가 실행되지 않음",
|
|
|
|
|
"workaround": "Playwright의 playwright_click 도구와 [role='alertdialog'] button:has-text('삭제') 셀렉터 사용",
|
|
|
|
|
"testedOn": "2026-01-29"
|
|
|
|
|
}
|
|
|
|
|
],
|
|
|
|
|
"rollbackPlan": {
|
|
|
|
|
"description": "테스트 실패 시 롤백 계획",
|
|
|
|
|
"onCreateFail": "영향 없음 - 다음 테스트 정상 진행",
|
|
|
|
|
"onUpdateFail": "테스트 데이터 수동 삭제 필요",
|
|
|
|
|
"onDeleteFail": "테스트 데이터 수동 삭제 필요",
|
|
|
|
|
"cleanupRequired": "E2E테스트_ 로 시작하는 게시글은 테스트 데이터이므로 수동 삭제 가능"
|
|
|
|
|
}
|
|
|
|
|
}
|