import process from 'node:process'; import { chromium } from 'playwright'; import { ensureDirectory, getKstDate, resolveCapturePaths, updateWorklogCaptureSection } from './worklog-capture-utils.mjs'; const FEATURE_CAPTURE_PRESETS = { 'docs-worklogs': { topMenu: 'docs', screenshotFileName: 'feature-docs-worklogs.png', targetSelector: '.app-main-card', }, 'play-layout': { topMenu: 'play', screenshotFileName: 'feature-play-layout.png', targetSelector: '.app-main-card', query: { playSection: 'layout' }, }, 'apis-components': { topMenu: 'apis', screenshotFileName: 'feature-apis-components.png', targetSelector: '.app-main-card', }, 'apis-widgets': { topMenu: 'apis', screenshotFileName: 'feature-apis-widgets.png', targetSelector: '.app-main-card', afterNavigation: async (page) => { await page.getByRole('menuitem', { name: 'Widgets' }).click(); }, }, 'plans-board': { topMenu: 'plans', screenshotFileName: 'feature-plans-board.png', targetSelector: '.app-main-card', }, 'plans-charts': { topMenu: 'plans', screenshotFileName: 'feature-plans-charts.png', targetSelector: '.app-main-card', query: { planSection: 'charts' }, }, 'chat-live': { topMenu: 'chat', screenshotFileName: 'feature-chat-live.png', targetSelector: '.app-main-card, .app-chat-panel', }, 'chat-errors': { topMenu: 'chat', screenshotFileName: 'feature-chat-errors.png', targetSelector: '.app-main-card, .app-chat-panel', afterNavigation: async (page) => { await page.getByRole('menuitem', { name: '에러 로그' }).click(); }, }, }; const cwd = process.cwd(); const presetKey = process.argv[2]; const captureDate = process.argv[3] ?? getKstDate(); const baseUrl = process.env.CAPTURE_BASE_URL ?? 'http://127.0.0.1:5174'; if (!presetKey || !(presetKey in FEATURE_CAPTURE_PRESETS)) { console.error(`Usage: node scripts/capture-feature-screenshot.mjs <${Object.keys(FEATURE_CAPTURE_PRESETS).join('|')}> [YYYY-MM-DD]`); process.exit(1); } const preset = FEATURE_CAPTURE_PRESETS[presetKey]; const { screenshotDir, screenshotPath, worklogPath, markdownImagePath } = resolveCapturePaths({ cwd, captureDate, screenshotFileName: preset.screenshotFileName, }); const browser = await chromium.launch({ headless: true }); const page = await browser.newPage({ viewport: { width: 1600, height: 1200 }, deviceScaleFactor: 2, }); try { await ensureDirectory(screenshotDir); const targetUrl = new URL(baseUrl); targetUrl.searchParams.set('topMenu', preset.topMenu); if (preset.query) { for (const [key, value] of Object.entries(preset.query)) { targetUrl.searchParams.set(key, value); } } await page.goto(targetUrl.toString(), { waitUntil: 'networkidle' }); if (preset.afterNavigation) { await preset.afterNavigation(page); await page.waitForLoadState('networkidle').catch(() => {}); } const target = page.locator(preset.targetSelector).first(); await target.waitFor({ state: 'visible', timeout: 30000 }); await target.scrollIntoViewIfNeeded(); await target.screenshot({ path: screenshotPath, animations: 'disabled', }); await updateWorklogCaptureSection({ worklogPath, captureDate, imageAlt: preset.screenshotFileName.replace('.png', ''), markdownImagePath, }); console.log(`Saved: ${screenshotPath}`); console.log(`Linked in: ${worklogPath}`); } finally { await browser.close(); }