fix: 게임 시작 후 사전 거병 숨김
현재 턴 판정에 lastTurnTime을 우선 사용해 장수 삭제와 같은 가오픈 경계로 맞춘다.\n\n구형 turntime이 남은 시작 후 상태를 데스크톱과 모바일 Chromium 회귀로 고정한다.
This commit is contained in:
@@ -66,6 +66,7 @@ type FixtureState = {
|
|||||||
instantRetreatAttempts?: number;
|
instantRetreatAttempts?: number;
|
||||||
instantRetreatInputs?: Array<Record<string, unknown>>;
|
instantRetreatInputs?: Array<Record<string, unknown>>;
|
||||||
buildNationCandidateEnabled?: boolean;
|
buildNationCandidateEnabled?: boolean;
|
||||||
|
gameStarted?: boolean;
|
||||||
buildNationCandidateAttempts?: number;
|
buildNationCandidateAttempts?: number;
|
||||||
buildNationCandidateInputs?: Array<Record<string, unknown>>;
|
buildNationCandidateInputs?: Array<Record<string, unknown>>;
|
||||||
dieOnPrestartShow?: boolean;
|
dieOnPrestartShow?: boolean;
|
||||||
@@ -517,6 +518,9 @@ const install = async (page: Page, state: FixtureState) => {
|
|||||||
},
|
},
|
||||||
meta: {
|
meta: {
|
||||||
turntime: '2026-01-01T00:00:00.000Z',
|
turntime: '2026-01-01T00:00:00.000Z',
|
||||||
|
lastTurnTime: state.gameStarted
|
||||||
|
? '2026-03-01T00:00:00.000Z'
|
||||||
|
: '2026-01-01T00:00:00.000Z',
|
||||||
opentime: state.buildNationCandidateEnabled
|
opentime: state.buildNationCandidateEnabled
|
||||||
? '2026-02-01T00:00:00.000Z'
|
? '2026-02-01T00:00:00.000Z'
|
||||||
: '2025-12-01T00:00:00.000Z',
|
: '2025-12-01T00:00:00.000Z',
|
||||||
@@ -2225,6 +2229,53 @@ test('사전 거병은 timeout reload 뒤 같은 ID를 재시도하고 성공 re
|
|||||||
expect(requestIds?.[2]).not.toBe(requestIds?.[1]);
|
expect(requestIds?.[2]).not.toBe(requestIds?.[1]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('게임 시작 뒤에는 구형 turntime이 남아 있어도 사전 거병을 숨긴다', async ({ page }) => {
|
||||||
|
const state: FixtureState = {
|
||||||
|
permission: 'member',
|
||||||
|
myset: 3,
|
||||||
|
buildNationCandidateEnabled: true,
|
||||||
|
gameStarted: true,
|
||||||
|
dieOnPrestartShow: false,
|
||||||
|
settingMutations: [],
|
||||||
|
accessPages: [],
|
||||||
|
};
|
||||||
|
await install(page, state);
|
||||||
|
for (const viewport of [
|
||||||
|
{ name: 'desktop', width: 1000, height: 900 },
|
||||||
|
{ name: 'mobile', width: 390, height: 900 },
|
||||||
|
]) {
|
||||||
|
await page.setViewportSize(viewport);
|
||||||
|
await page.goto('my-page');
|
||||||
|
await waitForVisualAssets(page);
|
||||||
|
|
||||||
|
await expect(page.getByRole('button', { name: '장수 삭제' })).toHaveCount(0);
|
||||||
|
await expect(page.getByRole('button', { name: '사전 거병' })).toHaveCount(0);
|
||||||
|
const save = page.getByRole('button', { name: '설정저장' });
|
||||||
|
await expect(save).toBeVisible();
|
||||||
|
await save.focus();
|
||||||
|
await expect(save).toBeFocused();
|
||||||
|
const geometry = await save.evaluate((element) => {
|
||||||
|
const rect = element.getBoundingClientRect();
|
||||||
|
const style = getComputedStyle(element);
|
||||||
|
return {
|
||||||
|
viewportWidth: window.innerWidth,
|
||||||
|
documentScrollWidth: document.documentElement.scrollWidth,
|
||||||
|
rect: { x: rect.x, y: rect.y, width: rect.width, height: rect.height },
|
||||||
|
backgroundColor: style.backgroundColor,
|
||||||
|
fontSize: style.fontSize,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
expect(geometry).toMatchObject({
|
||||||
|
viewportWidth: viewport.width,
|
||||||
|
documentScrollWidth: viewport.width,
|
||||||
|
rect: { width: 160, height: 30 },
|
||||||
|
backgroundColor: 'rgb(34, 85, 0)',
|
||||||
|
fontSize: '14px',
|
||||||
|
});
|
||||||
|
await persistParityArtifact(page, `core-my-page-started-hidden-actions-${viewport.name}`, geometry);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
test('감찰부 keeps the selector interaction and shows the permission error path', async ({ page }) => {
|
test('감찰부 keeps the selector interaction and shows the permission error path', async ({ page }) => {
|
||||||
const head: FixtureState = { permission: 'head', myset: 3, settingMutations: [], accessPages: [] };
|
const head: FixtureState = { permission: 'head', myset: 3, settingMutations: [], accessPages: [] };
|
||||||
await install(page, head);
|
await install(page, head);
|
||||||
|
|||||||
@@ -183,7 +183,10 @@ const actionAvailability = computed(() => {
|
|||||||
const config = world.value?.config ?? {};
|
const config = world.value?.config ?? {};
|
||||||
const constConfig = asRecord(config.const);
|
const constConfig = asRecord(config.const);
|
||||||
const availableInstantAction = asRecord(constConfig.availableInstantAction ?? config.availableInstantAction);
|
const availableInstantAction = asRecord(constConfig.availableInstantAction ?? config.availableInstantAction);
|
||||||
const turnTime = meta.turntime ? new Date(String(meta.turntime)) : null;
|
// 엔진은 현재 턴을 lastTurnTime으로 진행하고 호환용 turntime 투영값은 유지할 수 있다.
|
||||||
|
// 장수 삭제와 같은 현재 시계를 사용해야 게임 시작 뒤 가오픈 행동이 다시 노출되지 않는다.
|
||||||
|
const rawTurnTime = meta.lastTurnTime ?? meta.turntime;
|
||||||
|
const turnTime = rawTurnTime ? new Date(String(rawTurnTime)) : null;
|
||||||
const openTime = meta.opentime ? new Date(String(meta.opentime)) : null;
|
const openTime = meta.opentime ? new Date(String(meta.opentime)) : null;
|
||||||
const preopen = Boolean(turnTime && openTime && turnTime.getTime() <= openTime.getTime());
|
const preopen = Boolean(turnTime && openTime && turnTime.getTime() <= openTime.getTime());
|
||||||
const npcMode = numberValue(config.npcMode ?? config.npcmode, 0);
|
const npcMode = numberValue(config.npcMode ?? config.npcmode, 0);
|
||||||
|
|||||||
Reference in New Issue
Block a user