Files
core2026/tools/frontend-legacy-parity/reference-progress-bars.mjs
T

115 lines
5.2 KiB
JavaScript

import { createHash } from 'node:crypto';
import { chmod, mkdir, readFile, writeFile } from 'node:fs/promises';
import { resolve } from 'node:path';
import { chromium } from '@playwright/test';
const baseUrl = process.env.REF_MAIN_URL ?? 'http://127.0.0.1:3400/sam/';
const username = process.env.REF_USER_ID ?? 'refuser1';
const passwordFile =
process.env.REF_USER_PASSWORD_FILE ??
'/home/letrhee/sam_rebuild/docker_compose_files/reference/secrets/user1_password';
const artifactRoot = resolve(process.env.REF_PROGRESS_ARTIFACT_DIR ?? 'artifacts/ref-progress-bars');
const password = (await readFile(passwordFile, 'utf8')).trim();
await mkdir(artifactRoot, { recursive: true, mode: 0o700 });
const browser = await chromium.launch({ headless: true });
try {
const context = await browser.newContext({
colorScheme: 'dark',
deviceScaleFactor: 1,
locale: 'ko-KR',
timezoneId: 'UTC',
});
const page = await context.newPage();
await page.goto(baseUrl, { waitUntil: 'networkidle' });
const globalSalt = await page.locator('#global_salt').inputValue();
const passwordHash = createHash('sha512')
.update(globalSalt + password + globalSalt)
.digest('hex');
const response = await context.request.post(new URL('api.php?path=Login/LoginByID', baseUrl).toString(), {
data: { username, password: passwordHash },
});
if (!response.ok()) throw new Error(`reference login failed: HTTP ${response.status()}`);
const loginPayload = await response.json();
if (loginPayload?.result !== true) {
throw new Error(`reference login rejected: ${String(loginPayload?.reason ?? loginPayload)}`);
}
if (process.env.REF_CREATE_GENERAL === '1') {
await page.goto(new URL('hwe/v_join.php', baseUrl).toString(), { waitUntil: 'networkidle' });
const createButton = page.getByRole('button', { name: '장수 생성', exact: true });
if (await createButton.isVisible()) {
page.on('dialog', (dialog) => dialog.accept());
await createButton.click();
await page.waitForURL(/\/hwe\/?$/u);
}
}
for (const viewport of [
{ name: 'desktop-1000', width: 1000, height: 900 },
{ name: 'mobile-500', width: 500, height: 900 },
]) {
await page.setViewportSize(viewport);
await page.goto(new URL('hwe/', baseUrl).toString(), { waitUntil: 'networkidle' });
try {
await page
.locator('.city-card-basic .sammo-bar, .bar_out')
.first()
.waitFor({ state: 'visible', timeout: 8_000 });
} catch {
throw new Error(
`reference main progress bars missing: ${JSON.stringify({
url: page.url(),
title: await page.title(),
cityCards: await page.locator('.city-card-basic').count(),
generalCards: await page.locator('.general-card-basic').count(),
legacyBars: await page.locator('.bar_out').count(),
})}`
);
}
const measurement = await page.evaluate(() => {
const inspect = (element) => {
const rect = element.getBoundingClientRect();
const style = getComputedStyle(element);
const fill = element.querySelector('.sammo-bar-in');
const fillStyle = fill ? getComputedStyle(fill) : null;
return {
rect: { x: rect.x, y: rect.y, width: rect.width, height: rect.height },
borderTop: style.borderTop,
borderBottom: style.borderBottom,
backgroundImage: getComputedStyle(element.querySelector('.sammo-bar-base')).backgroundImage,
fillWidth: fill?.getBoundingClientRect().width ?? 0,
fillBackgroundImage: fillStyle?.backgroundImage ?? '',
};
};
return {
viewport: { width: innerWidth, height: innerHeight },
city: [...document.querySelectorAll('.city-card-basic .sammo-bar')].map(inspect),
general: [...document.querySelectorAll('.general-card-basic .sammo-bar')].map(inspect),
cityCard: document.querySelector('.city-card-basic').getBoundingClientRect().toJSON(),
generalCard: document.querySelector('.general-card-basic').getBoundingClientRect().toJSON(),
};
});
await Promise.all([
page.screenshot({ path: resolve(artifactRoot, `ref-${viewport.name}.png`), fullPage: true }),
writeFile(resolve(artifactRoot, `ref-${viewport.name}.json`), `${JSON.stringify(measurement, null, 2)}\n`, {
mode: 0o600,
}),
]);
await chmod(resolve(artifactRoot, `ref-${viewport.name}.png`), 0o600);
console.log(
JSON.stringify({
viewport: viewport.name,
cityBars: measurement.city.length,
generalBars: measurement.general.length,
cityHeight: measurement.city[0]?.rect.height,
generalHeight: measurement.general[0]?.rect.height,
})
);
}
} finally {
await browser.close();
}