jskim-node #396

Merged
kjs merged 44 commits from jskim-node into main 2026-02-28 14:37:11 +09:00
2 changed files with 93 additions and 6 deletions
Showing only changes of commit afc66a4971 - Show all commits

85
bom-restore-verify.mjs Normal file
View File

@ -0,0 +1,85 @@
/**
* BOM Screen - Restoration Verification
* Screen 4168 - verify split panel, BOM list, and tree with child items
*/
import { chromium } from 'playwright';
import { mkdirSync, existsSync } from 'fs';
import { join } from 'path';
const SCREENSHOT_DIR = join(process.cwd(), 'bom-detail-test-screenshots');
async function ensureDir(dir) {
if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
}
async function screenshot(page, name) {
ensureDir(SCREENSHOT_DIR);
await page.screenshot({ path: join(SCREENSHOT_DIR, `${name}.png`), fullPage: true });
console.log(` [Screenshot] ${name}.png`);
}
async function sleep(ms) {
return new Promise((r) => setTimeout(r, ms));
}
async function main() {
const browser = await chromium.launch({ headless: true });
const page = await browser.newPage({ viewport: { width: 1400, height: 900 } });
try {
console.log('\n--- Step 1-2: Login ---');
await page.goto('http://localhost:9771/login', { waitUntil: 'load', timeout: 45000 });
await page.locator('input[type="text"], input[placeholder*="ID"]').first().fill('topseal_admin');
await page.locator('input[type="password"]').first().fill('qlalfqjsgh11');
await Promise.all([
page.waitForNavigation({ waitUntil: 'domcontentloaded', timeout: 20000 }).catch(() => {}),
page.locator('button:has-text("로그인")').first().click(),
]);
await sleep(3000);
console.log('\n--- Step 4-5: Navigate to screen 4168 ---');
await page.goto('http://localhost:9771/screens/4168', { waitUntil: 'load', timeout: 45000 });
await sleep(5000);
console.log('\n--- Step 6: Screenshot after load ---');
await screenshot(page, '10-bom-4168-initial');
const hasBomList = (await page.locator('text="BOM 목록"').count()) > 0;
const hasSplitPanel = (await page.locator('text="BOM 상세정보"').count()) > 0 || hasBomList;
const rowCount = await page.locator('table tbody tr').count();
const hasBomRows = rowCount > 0;
console.log('\n========== INITIAL STATE (Step 7) ==========');
console.log('BOM management screen loaded:', hasBomList || hasSplitPanel ? 'YES' : 'CHECK');
console.log('Split panel (BOM list left):', hasSplitPanel ? 'YES' : 'NO');
console.log('BOM data rows visible:', hasBomRows ? `YES (${rowCount} rows)` : 'NO');
if (hasBomRows) {
console.log('\n--- Step 8-9: Click first row ---');
await page.locator('table tbody tr').first().click();
await sleep(5000);
console.log('\n--- Step 10: Screenshot after row click ---');
await screenshot(page, '11-bom-4168-after-click');
const noDataMsg = (await page.locator('text="등록된 하위 품목이 없습니다"').count()) > 0;
const treeArea = page.locator('div:has-text("BOM 구성"), div:has-text("BOM 상세정보")').first();
const treeText = (await treeArea.textContent().catch(() => '') || '').substring(0, 600);
const hasChildItems = !noDataMsg && (treeText.includes('품번') || treeText.includes('레벨') || treeText.length > 150);
console.log('\n========== AFTER ROW CLICK (Step 11) ==========');
console.log('BOM tree shows child items:', hasChildItems ? 'YES' : noDataMsg ? 'NO (empty message)' : 'CHECK');
console.log('Tree preview:', treeText.substring(0, 300) + (treeText.length > 300 ? '...' : ''));
} else {
console.log('\n--- No BOM rows to click ---');
}
} catch (err) {
console.error('Error:', err.message);
try { await page.screenshot({ path: join(SCREENSHOT_DIR, '99-error.png'), fullPage: true }); } catch (e) {}
} finally {
await browser.close();
}
}
main();

View File

@ -6,7 +6,7 @@ import { Loader2 } from "lucide-react";
import { apiClient } from "@/lib/api/client"; import { apiClient } from "@/lib/api/client";
/** /**
* /screen/COMPANY_7_167 /screens/4153 * /screen/{screenCode} /screens/{screenId}
* URL이 screenCode , screenId로 * URL이 screenCode , screenId로
*/ */
export default function ScreenCodeRedirectPage() { export default function ScreenCodeRedirectPage() {
@ -26,12 +26,14 @@ export default function ScreenCodeRedirectPage() {
const resolve = async () => { const resolve = async () => {
try { try {
const res = await apiClient.get("/screen-management/screens", { const res = await apiClient.get("/screen-management/screens", {
params: { screenCode }, params: { searchTerm: screenCode, size: 50 },
}); });
const screens = res.data?.data || []; const items = res.data?.data?.data || res.data?.data || [];
if (screens.length > 0) { const arr = Array.isArray(items) ? items : [];
const id = screens[0].screenId || screens[0].screen_id; const exact = arr.find((s: any) => s.screenCode === screenCode);
router.replace(`/screens/${id}`); const target = exact || arr[0];
if (target) {
router.replace(`/screens/${target.screenId || target.screen_id}`);
} else { } else {
router.replace("/"); router.replace("/");
} }