merge: 최신 core2026 main을 특수 명령 작업에 통합

This commit is contained in:
2026-08-15 18:42:17 +00:00
12 changed files with 254 additions and 48 deletions
+52 -7
View File
@@ -179,26 +179,54 @@ test('prioritizes core general fields and keeps context and inheritance progress
const rect = element.getBoundingClientRect();
const style = getComputedStyle(element);
return {
top: rect.top,
height: rect.height,
backgroundColor: style.backgroundColor,
color: style.color,
borderTopWidth: style.borderTopWidth,
borderRightWidth: style.borderRightWidth,
borderBottomWidth: style.borderBottomWidth,
borderBottomColor: style.borderBottomColor,
marginTop: style.marginTop,
fontSize: style.fontSize,
fontWeight: style.fontWeight,
cursor: style.cursor,
};
});
expect(defaultButtonStyle).toEqual({
expect(defaultButtonStyle).toMatchObject({
height: 40,
backgroundColor: 'rgb(0, 88, 44)',
color: 'rgb(255, 255, 255)',
borderTopWidth: '0px',
borderRightWidth: '1px',
borderBottomWidth: '4px',
borderBottomColor: 'rgb(0, 79, 40)',
marginTop: '0px',
fontSize: '14px',
fontWeight: '700',
cursor: 'pointer',
});
await randomButton.hover();
await expect
.poll(() => randomButton.evaluate((element) => getComputedStyle(element).backgroundColor))
.toBe('rgb(0, 109, 55)');
const hoverButtonStyle = await randomButton.evaluate((element) => {
const rect = element.getBoundingClientRect();
const style = getComputedStyle(element);
return {
top: rect.top,
height: rect.height,
backgroundColor: style.backgroundColor,
borderBottomWidth: style.borderBottomWidth,
borderBottomColor: style.borderBottomColor,
marginTop: style.marginTop,
};
});
expect(hoverButtonStyle).toMatchObject({
top: defaultButtonStyle.top + 1,
height: 39,
backgroundColor: 'rgb(0, 88, 44)',
borderBottomWidth: '3px',
borderBottomColor: 'rgb(0, 79, 40)',
marginTop: '1px',
});
await page.screenshot({ path: testInfo.outputPath('join-stat-actions-hover-desktop.png'), fullPage: true });
await randomButton.focus();
await expect(randomButton).toBeFocused();
@@ -210,9 +238,26 @@ test('prioritizes core general fields and keeps context and inheritance progress
randomButtonBox!.y + randomButtonBox!.height / 2
);
await page.mouse.down();
await expect
.poll(() => randomButton.evaluate((element) => getComputedStyle(element).backgroundColor))
.toBe('rgb(0, 69, 35)');
const activeButtonStyle = await randomButton.evaluate((element) => {
const rect = element.getBoundingClientRect();
const style = getComputedStyle(element);
return {
top: rect.top,
height: rect.height,
backgroundColor: style.backgroundColor,
borderBottomWidth: style.borderBottomWidth,
borderBottomColor: style.borderBottomColor,
marginTop: style.marginTop,
};
});
expect(activeButtonStyle).toMatchObject({
top: defaultButtonStyle.top + 2,
height: 38,
backgroundColor: 'rgb(0, 88, 44)',
borderBottomWidth: '2px',
borderBottomColor: 'rgb(0, 79, 40)',
marginTop: '2px',
});
await page.screenshot({ path: testInfo.outputPath('join-stat-actions-active-desktop.png'), fullPage: true });
await page.mouse.up();
const setRandomValues = async (values: number[]) => {
+29 -10
View File
@@ -21,6 +21,8 @@ type NavigationFixture = {
operations: string[];
generalName?: string;
generalTurnTime?: string;
serverTime?: string;
clockMode?: 'realtime' | 'manual';
cityDefence?: number;
cityState?: number;
nationRate?: number;
@@ -363,6 +365,8 @@ const installFixture = async (page: Page, state: NavigationFixture) => {
year: state.currentYear ?? 185,
month: state.currentMonth ?? 1,
turnTerm: 10,
serverTime: state.serverTime ?? '2026-08-13T00:00:00.000Z',
clockMode: state.clockMode ?? 'realtime',
scenarioTitle: state.scenarioTitle ?? '',
});
}
@@ -787,7 +791,7 @@ test('desktop menus preserve ref columns, prefix-safe routes, and controlled dro
await persistArtifact(page, `${basePath.slice(1)}-desktop-1200`);
});
test('main general card and command clock render the next turn with second precision', async ({ page }) => {
test('main general card uses local turn time and command clock tracks corrected server time', async ({ page }) => {
const state: NavigationFixture = {
officerLevel: 0,
permission: 0,
@@ -797,22 +801,29 @@ test('main general card and command clock render the next turn with second preci
generalMeCalls: 0,
operations: [],
generalName: 'Administrator',
generalTurnTime: '2026-08-13T00:07:06.713Z',
generalTurnTime: '2026-08-13T00:09:10.713Z',
serverTime: '2026-08-13T00:07:06.250Z',
clockMode: 'realtime',
currentYear: 179,
currentMonth: 8,
};
await installFixture(page, state);
await page.clock.install({ time: new Date('2026-08-13T00:00:00.000Z') });
const cdp = await page.context().newCDPSession(page);
await cdp.send('Emulation.setTimezoneOverride', { timezoneId: 'Asia/Seoul' });
await page.setViewportSize({ width: 1200, height: 900 });
await waitForMain(page);
const title = page.locator('[data-main-target="general"] .general-title').first();
await expect(title).toContainText('Administrator');
await expect(title).toContainText('용장');
await expect(title).toContainText('09:07:06');
await expect(title).not.toContainText('00:07');
await expect(title).toContainText('09:09:10');
await expect(title).not.toContainText('00:09');
const commandClock = page.locator('[data-main-target="commands"] [data-command-current-time]').first();
await expect(commandClock).toHaveText('09:07:06');
await expect(commandClock).not.toHaveText('00:07');
await page.clock.runFor(1_000);
await expect(commandClock).toHaveText('09:07:07');
const generalCard = page.locator('[data-main-target="general"] [data-general-basic-card]').first();
await expect(generalCard).toContainText('수비 함(훈사80)');
await expect(generalCard).toContainText('5 턴');
@@ -857,9 +868,9 @@ test('main general card and command clock render the next turn with second preci
const target = resolve(artifactRoot);
await mkdir(target, { recursive: true });
await Promise.all([
page.screenshot({ path: resolve(target, 'main-turn-time-seoul-desktop-1200.png'), fullPage: true }),
page.screenshot({ path: resolve(target, 'main-turn-time-local-desktop-1200.png'), fullPage: true }),
writeFile(
resolve(target, 'main-turn-time-seoul-desktop-1200.json'),
resolve(target, 'main-turn-time-local-desktop-1200.json'),
`${JSON.stringify({ title: desktopGeometry, commandClock: desktopClockGeometry }, null, 2)}\n`
),
]);
@@ -867,9 +878,9 @@ test('main general card and command clock render the next turn with second preci
await page.setViewportSize({ width: 500, height: 900 });
const mobileTitle = page.locator('[data-main-target="general"] .general-title').first();
await expect(mobileTitle).toContainText('09:07:06');
await expect(mobileTitle).toContainText('09:09:10');
const mobileCommandClock = page.locator('[data-main-target="commands"] [data-command-current-time]').first();
await expect(mobileCommandClock).toHaveText('09:07:06');
await expect(mobileCommandClock).toHaveText('09:07:07');
const mobileGeometry = {
title: await mobileTitle.evaluate((element) => ({
width: element.getBoundingClientRect().width,
@@ -895,15 +906,23 @@ test('main general card and command clock render the next turn with second preci
if (artifactRoot) {
await Promise.all([
page.screenshot({
path: resolve(artifactRoot, 'main-turn-time-seoul-mobile-500.png'),
path: resolve(artifactRoot, 'main-turn-time-local-mobile-500.png'),
fullPage: true,
}),
writeFile(
resolve(artifactRoot, 'main-turn-time-seoul-mobile-500.json'),
resolve(artifactRoot, 'main-turn-time-local-mobile-500.json'),
`${JSON.stringify(mobileGeometry, null, 2)}\n`
),
]);
}
state.clockMode = 'manual';
state.serverTime = '2026-08-13T00:08:30.000Z';
await page.reload();
const frozenClock = page.locator('[data-main-target="commands"] [data-command-current-time]').first();
await expect(frozenClock).toHaveText('09:08:30');
await page.clock.runFor(2_000);
await expect(frozenClock).toHaveText('09:08:30');
});
test('pure NPC message senders are not rendered as reply targets', async ({ page }) => {