From 8b9f9a3a67bc312f859af04823c19eb88f05102c Mon Sep 17 00:00:00 2001 From: DDD1542 Date: Sat, 7 Mar 2026 04:34:44 +0900 Subject: [PATCH] [agent-pipeline] pipe-20260306183434-ewn8 round-2 --- .../(main)/admin/batch-management/page.tsx | 34 ++--- .../components/common/EditableSpreadsheet.tsx | 4 +- frontend/components/v2/V2Date.tsx | 2 +- frontend/components/v2/V2Input.tsx | 2 +- frontend/components/v2/V2Select.tsx | 2 +- run-responsive-e2e.mjs | 119 ++++++++++++++++++ 6 files changed, 141 insertions(+), 22 deletions(-) create mode 100644 run-responsive-e2e.mjs diff --git a/frontend/app/(main)/admin/batch-management/page.tsx b/frontend/app/(main)/admin/batch-management/page.tsx index 666dfa69..f191acc7 100644 --- a/frontend/app/(main)/admin/batch-management/page.tsx +++ b/frontend/app/(main)/admin/batch-management/page.tsx @@ -540,42 +540,42 @@ export default function BatchManagementPage() { {/* 배치 타입 선택 모달 */} {isBatchTypeModalOpen && ( -
- +
+ 배치 타입 선택 -
+
{/* DB → DB */}
handleBatchTypeSelect('db-to-db')} > -
- - - +
+ + +
-
DB → DB
-
데이터베이스 간 데이터 동기화
+
DB → DB
+
데이터베이스 간 데이터 동기화
{/* REST API → DB */}
handleBatchTypeSelect('restapi-to-db')} > -
- - - +
+ + +
-
REST API → DB
-
REST API에서 데이터베이스로 데이터 수집
+
REST API → DB
+
REST API에서 데이터베이스로 데이터 수집
diff --git a/frontend/components/common/EditableSpreadsheet.tsx b/frontend/components/common/EditableSpreadsheet.tsx index 1c5078d5..a5d44b4f 100644 --- a/frontend/components/common/EditableSpreadsheet.tsx +++ b/frontend/components/common/EditableSpreadsheet.tsx @@ -894,7 +894,7 @@ export const EditableSpreadsheet: React.FC = ({ const colName = columns[col]; const increment = columnIncrements.get(col); - if (increment !== null) { + if (typeof increment === 'number') { // 숫자 패턴 증가 모드 // 마지막 선택 행의 값을 기준으로 증가 const lastValue = String(data[norm.endRow]?.[colName] ?? ""); @@ -929,7 +929,7 @@ export const EditableSpreadsheet: React.FC = ({ const colName = columns[col]; const increment = columnIncrements.get(col); - if (increment !== null) { + if (typeof increment === 'number') { // 숫자 패턴 감소 모드 const firstValue = String(data[norm.startRow]?.[colName] ?? ""); const step = (targetRow - norm.startRow) * increment; diff --git a/frontend/components/v2/V2Date.tsx b/frontend/components/v2/V2Date.tsx index 04877b6a..f1a2da90 100644 --- a/frontend/components/v2/V2Date.tsx +++ b/frontend/components/v2/V2Date.tsx @@ -700,7 +700,7 @@ export const V2Date = forwardRef((props, ref) => { } }; - const showLabel = label && style?.labelDisplay !== false && style?.labelDisplay !== "false"; + const showLabel = label && style?.labelDisplay !== false; const componentWidth = size?.width || style?.width; const componentHeight = size?.height || style?.height; diff --git a/frontend/components/v2/V2Input.tsx b/frontend/components/v2/V2Input.tsx index c2313f5d..eade1dfd 100644 --- a/frontend/components/v2/V2Input.tsx +++ b/frontend/components/v2/V2Input.tsx @@ -962,7 +962,7 @@ export const V2Input = forwardRef((props, ref) => }; const actualLabel = label || style?.labelText; - const showLabel = actualLabel && style?.labelDisplay !== false && style?.labelDisplay !== "false"; + const showLabel = actualLabel && style?.labelDisplay !== false; const componentWidth = size?.width || style?.width; const componentHeight = size?.height || style?.height; diff --git a/frontend/components/v2/V2Select.tsx b/frontend/components/v2/V2Select.tsx index b4e30ee4..a7939db2 100644 --- a/frontend/components/v2/V2Select.tsx +++ b/frontend/components/v2/V2Select.tsx @@ -1145,7 +1145,7 @@ export const V2Select = forwardRef( } }; - const showLabel = label && style?.labelDisplay !== false && style?.labelDisplay !== "false"; + const showLabel = label && style?.labelDisplay !== false; const componentWidth = size?.width || style?.width; const componentHeight = size?.height || style?.height; diff --git a/run-responsive-e2e.mjs b/run-responsive-e2e.mjs new file mode 100644 index 00000000..d3e57f06 --- /dev/null +++ b/run-responsive-e2e.mjs @@ -0,0 +1,119 @@ +import { chromium } from '/Users/gbpark/ERP-node/node_modules/playwright/index.mjs'; +import { writeFileSync } from 'fs'; + +const results = []; +let passed = true; +let failReason = ''; + +async function login(page) { + await page.goto('http://localhost:9771/login'); + await page.waitForLoadState('networkidle'); + + await page.getByPlaceholder('사용자 ID를 입력하세요').fill('wace'); + await page.getByPlaceholder('비밀번호를 입력하세요').fill('qlalfqjsgh11'); + + await Promise.all([ + page.waitForURL(url => !url.toString().includes('/login'), { timeout: 30000 }), + page.getByRole('button', { name: '로그인' }).click(), + ]); + await page.waitForLoadState('networkidle'); +} + +async function run() { + const browser = await chromium.launch({ headless: true }); + const page = await browser.newPage(); + + try { + // 로그인 + await login(page); + results.push('✅ 로그인 성공'); + + // ─── 1. batch-management 375px 카드 뷰 전환 확인 ─── + await page.setViewportSize({ width: 375, height: 812 }); + await page.goto('http://localhost:9771/admin/batch-management'); + await page.waitForLoadState('domcontentloaded'); + await page.waitForTimeout(3000); + + const batchHasError = await page.locator('[id="__next"] .nextjs-container-errors-body').isVisible().catch(() => false); + if (batchHasError) throw new Error('batch-management 에러 오버레이 발견'); + results.push('✅ batch-management 에러 없음'); + + // 페이지 정상 렌더링 확인 + const batchBodyVisible = await page.locator('body').isVisible(); + if (!batchBodyVisible) throw new Error('batch-management body 렌더링 실패'); + results.push('✅ batch-management body 렌더링 정상'); + + // 가로 오버플로우 확인 (카드 뷰는 375px 내에 들어와야 함) + const batchScrollWidth = await page.evaluate(() => document.body.scrollWidth); + results.push(`ℹ️ batch-management scrollWidth: ${batchScrollWidth}px`); + if (batchScrollWidth > 420) throw new Error(`batch-management 가로 오버플로우: ${batchScrollWidth}px`); + results.push('✅ batch-management 375px 레이아웃 정상'); + + await page.screenshot({ path: '/Users/gbpark/ERP-node/.agent-pipeline/browser-tests/result-batch-375.png', fullPage: true }); + results.push('✅ batch-management 스크린샷 저장'); + + // ─── 2. audit-log 375px 카드 뷰 전환 확인 ─── + await page.goto('http://localhost:9771/admin/audit-log'); + await page.waitForLoadState('domcontentloaded'); + await page.waitForTimeout(3000); + + const auditHasError = await page.locator('[id="__next"] .nextjs-container-errors-body').isVisible().catch(() => false); + if (auditHasError) throw new Error('audit-log 에러 오버레이 발견'); + results.push('✅ audit-log 에러 없음'); + + const auditBodyVisible = await page.locator('body').isVisible(); + if (!auditBodyVisible) throw new Error('audit-log body 렌더링 실패'); + results.push('✅ audit-log body 렌더링 정상'); + + const auditScrollWidth = await page.evaluate(() => document.body.scrollWidth); + results.push(`ℹ️ audit-log scrollWidth: ${auditScrollWidth}px`); + if (auditScrollWidth > 420) throw new Error(`audit-log 가로 오버플로우: ${auditScrollWidth}px`); + results.push('✅ audit-log 375px 레이아웃 정상'); + + await page.screenshot({ path: '/Users/gbpark/ERP-node/.agent-pipeline/browser-tests/result-audit-375.png', fullPage: true }); + results.push('✅ audit-log 스크린샷 저장'); + + // ─── 3. standards 375px 레이아웃 깨짐 확인 ─── + await page.goto('http://localhost:9771/admin/standards'); + await page.waitForLoadState('domcontentloaded'); + await page.waitForTimeout(3000); + + const standardsHasError = await page.locator('[id="__next"] .nextjs-container-errors-body').isVisible().catch(() => false); + if (standardsHasError) throw new Error('standards 에러 오버레이 발견'); + results.push('✅ standards 에러 없음'); + + const standardsBodyVisible = await page.locator('body').isVisible(); + if (!standardsBodyVisible) throw new Error('standards body 렌더링 실패'); + results.push('✅ standards body 렌더링 정상'); + + const standardsScrollWidth = await page.evaluate(() => document.body.scrollWidth); + results.push(`ℹ️ standards scrollWidth: ${standardsScrollWidth}px`); + if (standardsScrollWidth > 420) throw new Error(`standards 가로 오버플로우: ${standardsScrollWidth}px`); + results.push('✅ standards 375px 레이아웃 정상'); + + await page.screenshot({ path: '/Users/gbpark/ERP-node/.agent-pipeline/browser-tests/result.png', fullPage: true }); + results.push('✅ standards 스크린샷 저장'); + + } catch (err) { + passed = false; + failReason = err.message; + results.push(`❌ 실패: ${err.message}`); + await page.screenshot({ path: '/Users/gbpark/ERP-node/.agent-pipeline/browser-tests/result-fail.png', fullPage: true }).catch(() => {}); + } finally { + await browser.close(); + } +} + +run().then(() => { + const output = results.join('\n'); + console.log(output); + const finalResult = passed ? 'RESULT: PASS' : `RESULT: FAIL - ${failReason}`; + writeFileSync('/tmp/pw-responsive-result.txt', output + '\n' + finalResult); + console.log(finalResult); + process.exit(passed ? 0 : 1); +}).catch(err => { + const msg = `치명적 오류: ${err.message}`; + console.error(msg); + writeFileSync('/tmp/pw-responsive-result.txt', msg + '\nRESULT: FAIL - ' + err.message); + process.exit(1); +});