fix: display main turn time in server timezone

This commit is contained in:
2026-08-13 00:06:37 +00:00
parent de804a6c2a
commit 6589aee954
4 changed files with 80 additions and 2 deletions
+62 -1
View File
@@ -20,6 +20,7 @@ type NavigationFixture = {
generalMeCalls: number;
operations: string[];
generalName?: string;
generalTurnTime?: string;
cityDefence?: number;
cityState?: number;
nationRate?: number;
@@ -239,7 +240,7 @@ const generalContext = (state: NavigationFixture) => ({
dex: [350, 100_000, 500_000, 1_000_000, 1_275_975],
},
items: { horse: null, weapon: null, book: null, item: null },
turnTime: '0185-01-01T00:00:00.000Z',
turnTime: state.generalTurnTime ?? '0185-01-01T00:00:00.000Z',
},
city: {
id: 1,
@@ -666,6 +667,66 @@ test('desktop menus preserve ref columns, prefix-safe routes, and controlled dro
await persistArtifact(page, `${basePath.slice(1)}-desktop-1200`);
});
test('main general card renders the next turn in the Seoul server timezone', async ({ page }) => {
const state: NavigationFixture = {
officerLevel: 0,
permission: 0,
nationLevel: 0,
stage: 0,
npcMode: 1,
generalMeCalls: 0,
operations: [],
generalName: 'Administrator',
generalTurnTime: '2026-08-13T00:07:06.713Z',
currentYear: 179,
currentMonth: 8,
};
await installFixture(page, state);
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('다음 턴 09:07');
await expect(title).not.toContainText('00:07');
const desktopGeometry = await title.evaluate((element) => {
const rect = element.getBoundingClientRect();
const style = getComputedStyle(element);
return {
width: rect.width,
height: rect.height,
fontSize: style.fontSize,
lineHeight: style.lineHeight,
overflow: style.overflow,
};
});
expect(desktopGeometry.width).toBeGreaterThan(0);
expect(desktopGeometry.height).toBeGreaterThan(0);
if (artifactRoot) {
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 }),
writeFile(
resolve(target, 'main-turn-time-seoul-desktop-1200.json'),
`${JSON.stringify(desktopGeometry, null, 2)}\n`
),
]);
}
await page.setViewportSize({ width: 500, height: 900 });
const mobileTitle = page.locator('[data-main-target="general"] .general-title').first();
await expect(mobileTitle).toContainText('다음 턴 09:07');
expect(await mobileTitle.evaluate((element) => element.scrollWidth - element.clientWidth)).toBeLessThanOrEqual(0);
if (artifactRoot) {
await page.screenshot({
path: resolve(artifactRoot, 'main-turn-time-seoul-mobile-500.png'),
fullPage: true,
});
}
});
test('pure NPC message senders are not rendered as reply targets', async ({ page }) => {
const target = (generalId: number, generalName: string) => ({
generalId,
@@ -2,6 +2,7 @@
import { computed } from 'vue';
import SkeletonLines from '../ui/SkeletonLines.vue';
import LegacyProgressBar from '../ui/LegacyProgressBar.vue';
import { formatSeoulHourMinute } from '../../utils/legacyDateTime';
import { legacyExperiencePercent, ratioPercent } from '../../utils/legacyProgress';
interface GeneralStats {
@@ -80,7 +81,7 @@ const experiencePercent = computed(() =>
<div class="general-title">
{{ props.general.name }} · 관직 {{ props.general.officerLevel }} · {{ props.general.age ?? '-' }} ·
다음
{{ props.general.turnTime?.slice(11, 16) ?? '-' }}
{{ props.general.turnTime ? formatSeoulHourMinute(props.general.turnTime) : '-' }}
</div>
<div class="stat-progress-grid">
@@ -20,3 +20,5 @@ export const formatSeoulDateTime = (value: string | Date): string => {
koreaTime.getUTCSeconds()
)}`;
};
export const formatSeoulHourMinute = (value: string | Date): string => formatSeoulDateTime(value).slice(11, 16);
@@ -0,0 +1,14 @@
import assert from 'node:assert/strict';
import test from 'node:test';
import { formatSeoulDateTime, formatSeoulHourMinute } from '../src/utils/legacyDateTime.ts';
void test('formats API UTC timestamps in the server Seoul timezone', () => {
assert.equal(formatSeoulDateTime('2026-08-13T00:07:06.713Z'), '2026-08-13 09:07:06');
assert.equal(formatSeoulHourMinute('2026-08-13T00:07:06.713Z'), '09:07');
});
void test('keeps legacy timezone-less server timestamps unchanged', () => {
assert.equal(formatSeoulDateTime('2026-08-13 09:07:06'), '2026-08-13 09:07:06');
assert.equal(formatSeoulHourMinute('2026-08-13 09:07:06'), '09:07');
});