From efcc1ee077fce5e32ef19d80f0ce9933fb5ba679 Mon Sep 17 00:00:00 2001 From: hided62 Date: Fri, 21 Aug 2026 04:32:01 +0000 Subject: [PATCH] =?UTF-8?q?fix(game-ui):=20=EA=B3=A0=EA=B8=89=20=EC=98=88?= =?UTF-8?q?=ED=84=B4=20=EC=B5=9C=EA=B7=BC=20=EB=AA=85=EB=A0=B9=20=EC=9A=94?= =?UTF-8?q?=EC=95=BD=EC=9D=84=20=EB=B3=B5=EC=9B=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 고급 모드의 최근 실행 항목도 큐 행과 같은 예약 명령 formatter를 사용하게 한다. 데스크톱 hover와 모바일 focus·overflow를 production Chromium 회귀로 검증한다. --- .../e2e/commandArguments.spec.ts | 36 +++++++++++++++++++ .../command/ReservedCommandEditor.vue | 13 +++---- 2 files changed, 43 insertions(+), 6 deletions(-) diff --git a/app/game-frontend/e2e/commandArguments.spec.ts b/app/game-frontend/e2e/commandArguments.spec.ts index a9580002..d9ae12af 100644 --- a/app/game-frontend/e2e/commandArguments.spec.ts +++ b/app/game-frontend/e2e/commandArguments.spec.ts @@ -2291,6 +2291,7 @@ test('keeps Ref command briefs and autonomous-action state after a turn mutation test('uses drag selection, clipboard paste, and a stored template in advanced mode', async ({ page }) => { const requests = await install(page); + await page.setViewportSize({ width: 1200, height: 900 }); await page.goto('/'); const editor = page.locator('[data-command-scope="general"]'); @@ -2318,6 +2319,41 @@ test('uses drag selection, clipboard paste, and a stored template in advanced mo await picker.getByRole('button', { name: '입력', exact: true }).click(); await expect(editor.locator('.action-column > div').nth(2)).toHaveText('【허창】에 화계실행'); + const recentMenu = editor.locator('details').filter({ has: page.getByText('최근 실행', { exact: true }) }); + await recentMenu.locator('summary').click(); + const recentBriefButton = recentMenu.getByRole('button', { name: '【허창】에 화계실행', exact: true }); + await expect(recentBriefButton).toBeVisible(); + await recentBriefButton.hover(); + await page.screenshot({ + path: test.info().outputPath('advanced-recent-command-brief-desktop-1200.png'), + fullPage: true, + }); + await recentMenu.locator('summary').click(); + await page.setViewportSize({ width: 500, height: 900 }); + await recentMenu.locator('summary').click(); + await expect(recentBriefButton).toBeVisible(); + await recentBriefButton.focus(); + await expect(recentBriefButton).toBeFocused(); + const mobileRecentGeometry = await editor.evaluate((element) => { + const menu = element.querySelector('details[open] .menu-items'); + const recentButton = menu?.querySelector('button'); + if (!menu || !recentButton) throw new Error('advanced recent command menu is missing'); + return { + horizontalOverflow: element.scrollWidth - element.clientWidth, + menuRight: menu.getBoundingClientRect().right, + buttonRight: recentButton.getBoundingClientRect().right, + }; + }); + expect(mobileRecentGeometry.horizontalOverflow).toBeLessThanOrEqual(0); + expect(mobileRecentGeometry.menuRight).toBeLessThanOrEqual(500); + expect(mobileRecentGeometry.buttonRight).toBeLessThanOrEqual(500); + await page.screenshot({ + path: test.info().outputPath('advanced-recent-command-brief-mobile-500.png'), + fullPage: true, + }); + await recentMenu.locator('summary').click(); + await page.setViewportSize({ width: 1200, height: 900 }); + await drag(0, 2); await editor.locator('details.selected-menu > summary').click(); await editor.getByRole('button', { name: '복사하기', exact: true }).click(); diff --git a/app/game-frontend/src/components/command/ReservedCommandEditor.vue b/app/game-frontend/src/components/command/ReservedCommandEditor.vue index 10ac3c95..d46f5791 100644 --- a/app/game-frontend/src/components/command/ReservedCommandEditor.vue +++ b/app/game-frontend/src/components/command/ReservedCommandEditor.vue @@ -142,11 +142,12 @@ const isRecruitmentCommand = computed( () => selectedCommand.value?.key === 'che_징병' || selectedCommand.value?.key === 'che_모병' ); const isRecruitmentOverlayOpen = computed(() => pickerOpen.value && isRecruitmentCommand.value); -const rowLabel = (row: ReservedCommandRow): string => - formatReservedCommandBrief(props.scope, row.action, row.args, props.commandTable) || - row.label || - labelMap.value.get(row.action) || - row.action; +const commandBrief = (entry: { action: string; args: unknown; label?: string }): string => + formatReservedCommandBrief(props.scope, entry.action, entry.args, props.commandTable) || + entry.label || + labelMap.value.get(entry.action) || + entry.action; +const rowLabel = (row: ReservedCommandRow): string => commandBrief(row); const selectedIndices = () => normalizedSelection(selected.value, previousSelected.value, props.rows.length); const pattern = () => extractPattern(props.rows, selectedIndices()); const touchMenus = () => (menuRevision.value += 1); @@ -467,7 +468,7 @@ const clickOutsideMenu = (event: Event) => { clickOutsideMenu($event); " > - {{ entry.label ?? labelMap.get(entry.action) ?? entry.action }} + {{ commandBrief(entry) }} 비어 있음