Files
sam-hotfix/e2e/runner/gen-accessibility-audit.js
김보곤 67d0a4c2fd feat: E2E 시나리오 생성기 및 감사 스크립트 17종 추가
- gen-*.js: 시나리오 자동 생성기 12종 (CRUD, edge, a11y, perf 등)
- search-*.js: 검색/버튼 감사 수집기 3종
- revert-hard-actions.js: 하드 액션 복원 유틸
- _gen_writer.py: 생성기 보조 스크립트

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 16:59:15 +09:00

144 lines
6.1 KiB
JavaScript

#!/usr/bin/env node
/**
* 접근성 감사 시나리오 생성기
*
* 주요 18개 페이지에 대해 WCAG 2.1 AA 접근성 감사 시나리오를 자동 생성한다.
* 각 시나리오는:
* 1. 페이지 로드 대기
* 2. 테이블/콘텐츠 로드 대기
* 3. accessibility_audit - 이미지 alt, 폼 레이블, 버튼 이름, 제목 순서, 페이지 언어 검사
* 4. keyboard_navigate - 탭 키 네비게이션, 포커스 표시 검사
*
* Usage: node e2e/runner/gen-accessibility-audit.js
*
* Output:
* e2e/scenarios/a11y-{page-id}.json (18개 파일)
*
* Run generated scenarios:
* node e2e/runner/run-all.js --filter a11y
*/
const fs = require('fs');
const path = require('path');
const SCENARIOS_DIR = path.resolve(__dirname, '..', 'scenarios');
// ════════════════════════════════════════════════════════════════
// 페이지 매니페스트 (18개)
// ════════════════════════════════════════════════════════════════
const PAGES = [
// 판매관리
{ id: 'sales-client', name: '판매관리 > 거래처관리', level1: '판매관리', level2: '거래처관리' },
{ id: 'sales-estimate', name: '판매관리 > 견적관리', level1: '판매관리', level2: '견적관리' },
{ id: 'sales-order', name: '판매관리 > 수주관리', level1: '판매관리', level2: '수주관리' },
// 회계관리
{ id: 'acc-client', name: '회계관리 > 거래처관리', level1: '회계관리', level2: '거래처관리' },
{ id: 'acc-sales', name: '회계관리 > 매출관리', level1: '회계관리', level2: '매출관리', tableTimeout: 20000 },
{ id: 'acc-purchase', name: '회계관리 > 매입관리', level1: '회계관리', level2: '매입관리' },
{ id: 'acc-deposit', name: '회계관리 > 입금관리', level1: '회계관리', level2: '입금관리' },
// 인사관리
{ id: 'hr-employee', name: '인사관리 > 사원관리', level1: '인사관리', level2: '사원관리' },
{ id: 'hr-attendance', name: '인사관리 > 근태관리', level1: '인사관리', level2: '근태관리' },
{ id: 'hr-salary', name: '인사관리 > 급여관리', level1: '인사관리', level2: '급여관리' },
{ id: 'hr-department', name: '인사관리 > 부서관리', level1: '인사관리', level2: '부서관리', tableTimeout: 20000 },
// 생산관리
{ id: 'prod-work-order', name: '생산관리 > 작업지시', level1: '생산관리', level2: '작업지시' },
{ id: 'prod-item', name: '생산관리 > 품목관리', level1: '생산관리', level2: '품목관리', tableTimeout: 20000 },
// 자재관리
{ id: 'material-stock', name: '자재관리 > 재고현황', level1: '자재관리', level2: '재고현황' },
{ id: 'material-receiving', name: '자재관리 > 입고관리', level1: '자재관리', level2: '입고관리' },
// 게시판
{ id: 'board-free', name: '게시판 > 자유게시판', level1: '게시판', level2: '자유게시판' },
// 결재관리
{ id: 'approval-draft', name: '결재관리 > 기안함', level1: '결재관리', level2: '기안함' },
{ id: 'approval-box', name: '결재관리 > 결재함', level1: '결재관리', level2: '결재함' },
];
// ════════════════════════════════════════════════════════════════
// 시나리오 생성 함수
// ════════════════════════════════════════════════════════════════
function generateScenario(page) {
const steps = [];
let stepId = 1;
// Step 1: 페이지 로드 대기
steps.push({
id: stepId++,
name: '페이지 로드 대기',
action: 'wait',
timeout: 3000,
});
// Step 2: 테이블/콘텐츠 로드 대기
steps.push({
id: stepId++,
name: '테이블/콘텐츠 로드 대기',
action: 'wait_for_table',
timeout: page.tableTimeout || 5000,
});
// Step 3: 접근성 감사 (WCAG 2.1 AA)
steps.push({
id: stepId++,
name: '접근성 감사',
action: 'accessibility_audit',
timeout: 15000,
phase: 'A11Y_AUDIT',
});
// Step 4: 키보드 네비게이션 검사
steps.push({
id: stepId++,
name: '키보드 네비게이션 검사',
action: 'keyboard_navigate',
timeout: 15000,
phase: 'KBD_NAV',
});
return {
id: `a11y-${page.id}`,
name: `접근성 검사: ${page.name}`,
version: '1.0.0',
auth: { role: 'admin' },
menuNavigation: {
level1: page.level1,
level2: page.level2,
},
screenshotPolicy: {
captureOnFail: true,
captureOnPass: false,
},
steps,
};
}
// ════════════════════════════════════════════════════════════════
// 메인 실행
// ════════════════════════════════════════════════════════════════
function main() {
if (!fs.existsSync(SCENARIOS_DIR)) {
fs.mkdirSync(SCENARIOS_DIR, { recursive: true });
}
console.log('\n === Accessibility Audit Scenario Generator ===\n');
let count = 0;
for (const page of PAGES) {
const scenario = generateScenario(page);
const fp = path.join(SCENARIOS_DIR, `${scenario.id}.json`);
fs.writeFileSync(fp, JSON.stringify(scenario, null, 2), 'utf-8');
console.log(` ${scenario.id}.json (${scenario.steps.length} steps)`);
count++;
}
console.log(`\n Generated ${count} accessibility scenarios`);
console.log(` Run: node e2e/runner/run-all.js --filter a11y\n`);
}
main();