- Implemented automatic detection of sourceKeyField based on component configuration, improving flexibility in data handling. - Enhanced the SelectedItemsDetailInputConfigPanel to support automatic FK detection and mapping, streamlining the configuration process. - Updated the database connection logic to handle DATE types correctly, preventing timezone-related issues. - Improved overall component performance by optimizing memoization and state management for better user experience.
171 lines
5.7 KiB
JavaScript
171 lines
5.7 KiB
JavaScript
/**
|
|
* 프로덕션에서 "관리자 메뉴로 전환" 버튼 가시성 테스트
|
|
* 두 계정 (topseal_admin, rsw1206)으로 로그인하여 버튼 표시 여부 확인
|
|
*
|
|
* 실행: node scripts/browser-test-admin-switch-button.js
|
|
* 브라우저 표시: HEADLESS=0 node scripts/browser-test-admin-switch-button.js
|
|
*/
|
|
const { chromium } = require("playwright");
|
|
const fs = require("fs");
|
|
|
|
const BASE_URL = "https://v1.vexplor.com";
|
|
const SCREENSHOT_DIR = "test-screenshots/admin-switch-test";
|
|
|
|
const ACCOUNTS = [
|
|
{ userId: "topseal_admin", password: "qlalfqjsgh11", name: "topseal_admin" },
|
|
{ userId: "rsw1206", password: "qlalfqjsgh11", name: "rsw1206" },
|
|
];
|
|
|
|
async function runTest() {
|
|
const results = { topseal_admin: {}, rsw1206: {} };
|
|
const browser = await chromium.launch({
|
|
headless: process.env.HEADLESS !== "0",
|
|
});
|
|
const context = await browser.newContext({
|
|
viewport: { width: 1280, height: 900 },
|
|
ignoreHTTPSErrors: true,
|
|
});
|
|
const page = await context.newPage();
|
|
|
|
try {
|
|
if (!fs.existsSync(SCREENSHOT_DIR)) {
|
|
fs.mkdirSync(SCREENSHOT_DIR, { recursive: true });
|
|
}
|
|
|
|
const screenshot = async (name) => {
|
|
const path = `${SCREENSHOT_DIR}/${name}.png`;
|
|
await page.screenshot({ path, fullPage: true });
|
|
console.log(` [스크린샷] ${path}`);
|
|
return path;
|
|
};
|
|
|
|
for (let i = 0; i < ACCOUNTS.length; i++) {
|
|
const acc = ACCOUNTS[i];
|
|
console.log(`\n========== ${acc.name} 테스트 (${i + 1}/${ACCOUNTS.length}) ==========\n`);
|
|
|
|
// 로그인 페이지로 이동
|
|
await page.goto(`${BASE_URL}/login`, {
|
|
waitUntil: "networkidle",
|
|
timeout: 20000,
|
|
});
|
|
await page.waitForTimeout(1000);
|
|
|
|
// 로그인
|
|
await page.fill("#userId", acc.userId);
|
|
await page.fill("#password", acc.password);
|
|
await page.click('button[type="submit"]');
|
|
await page.waitForTimeout(3000);
|
|
|
|
// 로그인 성공 시 대시보드 또는 메인으로 리다이렉트될 것임
|
|
const currentUrl = page.url();
|
|
if (currentUrl.includes("/login") && !currentUrl.includes("error")) {
|
|
// 아직 로그인 페이지에 있다면 조금 더 대기
|
|
await page.waitForTimeout(3000);
|
|
}
|
|
|
|
const afterLoginUrl = page.url();
|
|
const screenshotPath = await screenshot(`01_${acc.name}_after_login`);
|
|
|
|
// "관리자 메뉴로 전환" 버튼 찾기
|
|
const buttonSelectors = [
|
|
'button:has-text("관리자 메뉴로 전환")',
|
|
'[class*="button"]:has-text("관리자 메뉴로 전환")',
|
|
'button >> text=관리자 메뉴로 전환',
|
|
];
|
|
|
|
let buttonVisible = false;
|
|
for (const sel of buttonSelectors) {
|
|
try {
|
|
const btn = page.locator(sel).first();
|
|
const count = await btn.count();
|
|
if (count > 0) {
|
|
const isVisible = await btn.isVisible();
|
|
if (isVisible) {
|
|
buttonVisible = true;
|
|
break;
|
|
}
|
|
}
|
|
} catch (_) {}
|
|
}
|
|
|
|
// 추가: 페이지 내 텍스트로 버튼 존재 여부 확인
|
|
if (!buttonVisible) {
|
|
const pageText = await page.textContent("body");
|
|
buttonVisible = pageText && pageText.includes("관리자 메뉴로 전환");
|
|
}
|
|
|
|
results[acc.name] = {
|
|
buttonVisible,
|
|
screenshotPath,
|
|
afterLoginUrl,
|
|
};
|
|
|
|
console.log(` 버튼 가시성: ${buttonVisible ? "표시됨" : "표시 안 됨"}`);
|
|
console.log(` URL: ${afterLoginUrl}`);
|
|
|
|
// 로그아웃 (다음 계정 테스트 전)
|
|
if (i < ACCOUNTS.length - 1) {
|
|
console.log("\n 로그아웃 중...");
|
|
try {
|
|
// 프로필 드롭다운 클릭 (좌측 하단)
|
|
const profileBtn = page.locator(
|
|
'button:has-text("로그아웃"), [class*="dropdown"]:has-text("로그아웃"), [data-radix-collection-item]:has-text("로그아웃")'
|
|
);
|
|
const profileTrigger = page.locator(
|
|
'button[class*="flex w-full"][class*="gap-3"]'
|
|
).first();
|
|
if (await profileTrigger.count() > 0) {
|
|
await profileTrigger.click();
|
|
await page.waitForTimeout(500);
|
|
const logoutItem = page.locator('text=로그아웃').first();
|
|
if (await logoutItem.count() > 0) {
|
|
await logoutItem.click();
|
|
await page.waitForTimeout(2000);
|
|
}
|
|
}
|
|
// 또는 직접 로그아웃 URL
|
|
if (page.url().includes("/login") === false) {
|
|
await page.goto(`${BASE_URL}/api/auth/logout`, {
|
|
waitUntil: "networkidle",
|
|
timeout: 5000,
|
|
}).catch(() => {});
|
|
await page.goto(`${BASE_URL}/login`, {
|
|
waitUntil: "networkidle",
|
|
timeout: 10000,
|
|
});
|
|
}
|
|
} catch (e) {
|
|
console.log(" 로그아웃 대체: 로그인 페이지로 직접 이동");
|
|
await page.goto(`${BASE_URL}/login`, {
|
|
waitUntil: "networkidle",
|
|
timeout: 10000,
|
|
});
|
|
}
|
|
await page.waitForTimeout(1500);
|
|
}
|
|
}
|
|
|
|
console.log("\n========== 최종 결과 ==========\n");
|
|
console.log("topseal_admin: 관리자 메뉴로 전환 버튼 =", results.topseal_admin.buttonVisible ? "표시됨" : "표시 안 됨");
|
|
console.log("rsw1206: 관리자 메뉴로 전환 버튼 =", results.rsw1206.buttonVisible ? "표시됨" : "표시 안 됨");
|
|
console.log("\n스크린샷:", SCREENSHOT_DIR);
|
|
|
|
return results;
|
|
} catch (err) {
|
|
console.error("테스트 오류:", err);
|
|
throw err;
|
|
} finally {
|
|
await browser.close();
|
|
}
|
|
}
|
|
|
|
runTest()
|
|
.then((r) => {
|
|
console.log("\n테스트 완료.");
|
|
process.exit(0);
|
|
})
|
|
.catch((e) => {
|
|
console.error(e);
|
|
process.exit(1);
|
|
});
|