Merge branch 'main' into refactor/frontend-time-format-options-20260813
This commit is contained in:
@@ -1175,6 +1175,125 @@ test('the 939/940 boundary switches to the Ref-style 500px single document', asy
|
|||||||
await persistArtifact(page, `${basePath.slice(1)}-mobile-500`);
|
await persistArtifact(page, `${basePath.slice(1)}-mobile-500`);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('real mobile devices initially fit the complete 500px game canvas', async ({ browser }, testInfo) => {
|
||||||
|
test.setTimeout(60_000);
|
||||||
|
const configuredBaseUrl = testInfo.project.use.baseURL;
|
||||||
|
if (typeof configuredBaseUrl !== 'string') {
|
||||||
|
throw new Error('Playwright baseURL is required for the mobile viewport contract');
|
||||||
|
}
|
||||||
|
|
||||||
|
const deviceWidths = [360, 390, 480];
|
||||||
|
const measurements: Record<string, unknown> = {};
|
||||||
|
|
||||||
|
for (const deviceWidth of deviceWidths) {
|
||||||
|
const context = await browser.newContext({
|
||||||
|
baseURL: configuredBaseUrl,
|
||||||
|
viewport: { width: deviceWidth, height: 844 },
|
||||||
|
screen: { width: deviceWidth, height: 844 },
|
||||||
|
deviceScaleFactor: 1,
|
||||||
|
isMobile: true,
|
||||||
|
hasTouch: true,
|
||||||
|
colorScheme: 'dark',
|
||||||
|
});
|
||||||
|
const mobilePage = await context.newPage();
|
||||||
|
const state: NavigationFixture = {
|
||||||
|
officerLevel: 5,
|
||||||
|
permission: 2,
|
||||||
|
nationLevel: 3,
|
||||||
|
stage: 6,
|
||||||
|
npcMode: 1,
|
||||||
|
generalMeCalls: 0,
|
||||||
|
operations: [],
|
||||||
|
};
|
||||||
|
await installFixture(mobilePage, state);
|
||||||
|
await waitForMain(mobilePage);
|
||||||
|
|
||||||
|
const mainGeometry = await mobilePage.locator('.main-page').evaluate((element) => {
|
||||||
|
const rect = element.getBoundingClientRect();
|
||||||
|
return {
|
||||||
|
viewportMeta: document.querySelector<HTMLMetaElement>('meta[name="viewport"]')?.content,
|
||||||
|
screenWidth: screen.availWidth,
|
||||||
|
innerWidth: window.innerWidth,
|
||||||
|
layoutViewportWidth: document.documentElement.clientWidth,
|
||||||
|
visualViewportWidth: window.visualViewport?.width ?? null,
|
||||||
|
visualViewportScale: window.visualViewport?.scale ?? null,
|
||||||
|
documentScrollWidth: document.documentElement.scrollWidth,
|
||||||
|
canvas: {
|
||||||
|
left: rect.left,
|
||||||
|
right: rect.right,
|
||||||
|
width: rect.width,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(mainGeometry.viewportMeta).toBe('width=500');
|
||||||
|
expect(mainGeometry.screenWidth).toBe(deviceWidth);
|
||||||
|
expect(mainGeometry.layoutViewportWidth).toBe(500);
|
||||||
|
expect(mainGeometry.visualViewportWidth).toBeCloseTo(500, 2);
|
||||||
|
expect(mainGeometry.visualViewportScale).toBeCloseTo(deviceWidth / 500, 2);
|
||||||
|
expect(mainGeometry.documentScrollWidth).toBeLessThanOrEqual(mainGeometry.innerWidth);
|
||||||
|
expect(mainGeometry.canvas).toEqual({ left: 0, right: 500, width: 500 });
|
||||||
|
expect(mainGeometry.canvas.right).toBeLessThanOrEqual((mainGeometry.visualViewportWidth ?? 0) + 0.01);
|
||||||
|
if (artifactRoot) {
|
||||||
|
await mkdir(artifactRoot, { recursive: true });
|
||||||
|
await mobilePage.screenshot({
|
||||||
|
path: resolve(artifactRoot, `initial-mobile-fit-${deviceWidth}.png`),
|
||||||
|
fullPage: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const routeGeometry: Record<string, unknown> = {};
|
||||||
|
if (deviceWidth === 390) {
|
||||||
|
for (const target of [
|
||||||
|
'chief-center',
|
||||||
|
'battle-center',
|
||||||
|
'inherit',
|
||||||
|
'nation-betting',
|
||||||
|
]) {
|
||||||
|
await mobilePage.goto(target);
|
||||||
|
await expect
|
||||||
|
.poll(() => mobilePage.locator('#app').evaluate((element) => getComputedStyle(element).minWidth))
|
||||||
|
.toBe('500px');
|
||||||
|
routeGeometry[target] = await mobilePage.locator('#app').evaluate((element) => {
|
||||||
|
const rect = element.getBoundingClientRect();
|
||||||
|
return {
|
||||||
|
viewportMeta: document.querySelector<HTMLMetaElement>('meta[name="viewport"]')?.content,
|
||||||
|
layoutViewportWidth: document.documentElement.clientWidth,
|
||||||
|
visualViewportWidth: window.visualViewport?.width ?? null,
|
||||||
|
left: rect.left,
|
||||||
|
right: rect.right,
|
||||||
|
width: rect.width,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
const geometry = routeGeometry[target] as {
|
||||||
|
viewportMeta: string;
|
||||||
|
layoutViewportWidth: number;
|
||||||
|
visualViewportWidth: number;
|
||||||
|
left: number;
|
||||||
|
right: number;
|
||||||
|
width: number;
|
||||||
|
};
|
||||||
|
expect(geometry.viewportMeta).toBe('width=500');
|
||||||
|
expect(geometry.layoutViewportWidth).toBe(500);
|
||||||
|
expect(geometry.visualViewportWidth).toBeCloseTo(500, 2);
|
||||||
|
expect(geometry.left).toBeCloseTo(0, 2);
|
||||||
|
expect(geometry.right).toBeCloseTo(500, 2);
|
||||||
|
expect(geometry.width).toBeCloseTo(500, 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
measurements[String(deviceWidth)] = { main: mainGeometry, routes: routeGeometry };
|
||||||
|
await context.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (artifactRoot) {
|
||||||
|
await writeFile(
|
||||||
|
resolve(artifactRoot, 'initial-mobile-fit-computed-dom.json'),
|
||||||
|
`${JSON.stringify(measurements, null, 2)}\n`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
test('nation menu presentation follows the server-derived permission matrix', async ({ page }) => {
|
test('nation menu presentation follows the server-derived permission matrix', async ({ page }) => {
|
||||||
const state: NavigationFixture = {
|
const state: NavigationFixture = {
|
||||||
officerLevel: 1,
|
officerLevel: 1,
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
<html lang="ko">
|
<html lang="ko">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=500" />
|
||||||
<title>Sammo HiDCHe - Game</title>
|
<title>Sammo HiDCHe - Game</title>
|
||||||
</head>
|
</head>
|
||||||
<body class="bg-black text-white">
|
<body class="bg-black text-white">
|
||||||
|
|||||||
Reference in New Issue
Block a user