From 21f27f2a79739fb5e5f1f4b89b3fe6951bd8bce2 Mon Sep 17 00:00:00 2001 From: hided62 Date: Fri, 21 Aug 2026 22:46:15 +0000 Subject: [PATCH] =?UTF-8?q?fix(game-ui):=20=EB=8F=99=EC=A0=81=20=ED=95=9C?= =?UTF-8?q?=EA=B5=AD=EC=96=B4=20=EC=A1=B0=EC=82=AC=20=EC=B2=98=EB=A6=AC?= =?UTF-8?q?=EB=A5=BC=20=ED=86=B5=EC=9D=BC=ED=95=9C=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 세력도시 임명 toast와 접근성 이름, 아이템 파기 확인 문구를 JosaUtil로 조립한다. 받침 유무를 production Chromium 회귀로 고정하고 작업 지침에 병기 조사 금지 규칙을 추가한다. --- AGENTS.md | 4 ++++ app/game-frontend/e2e/inGameMenus.spec.ts | 22 +++++++++++++++++++ .../e2e/nationCityOfficeIntegration.spec.ts | 5 +++-- app/game-frontend/src/views/MyPageView.vue | 3 ++- .../src/views/NationCitiesView.vue | 7 ++++-- 5 files changed, 36 insertions(+), 5 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 29748416..f5c953f8 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -340,6 +340,10 @@ docs에서 확인해 주세요. 존재하지 않는 명령을 오래된 report - Vue component는 PascalCase, composable은 `useX`, 변수/함수는 camelCase, type/class는 PascalCase를 사용해 주세요. - 한국어 domain identifier와 설명은 의미가 더 명확할 때 유지해 주세요. +- toast·dialog·aria-label·로그처럼 사용자에게 노출하는 동적 한국어 문구에 조사를 + 붙일 때는 `@sammo-ts/common/util/JosaUtil`의 `put()` 또는 `pick()`을 사용해 주세요. + `` `${value}을(를)` ``, `` `${value}이(가)` ``, `` `${value}(으)로` `` 같은 병기 표기를 + 실제 제품 문구에 남기지 말고, 받침 있는 값과 없는 값의 최종 표시 문구를 검증해 주세요. - action/command/전투 코드에는 한국 독자가 side effect와 ref 근거를 이해할 수 있는 주석을 남기되 코드의 반복 설명은 피해 주세요. - 기능 이관과 무관한 대규모 formatting/refactor를 같은 변경에 섞지 말아 주세요. diff --git a/app/game-frontend/e2e/inGameMenus.spec.ts b/app/game-frontend/e2e/inGameMenus.spec.ts index e38c78f8..7b51451d 100644 --- a/app/game-frontend/e2e/inGameMenus.spec.ts +++ b/app/game-frontend/e2e/inGameMenus.spec.ts @@ -1781,6 +1781,28 @@ test('내 정보에서 사람 장수의 등록 전콘을 골라 변경한다', a ); }); +test('내 정보 아이템 파기 확인은 이름의 받침에 맞는 조사를 쓴다', async ({ page }) => { + const state: FixtureState = { + permission: 'member', + myset: 1, + richMyInfo: true, + settingMutations: [], + accessPages: [], + }; + const prompts: string[] = []; + page.on('dialog', async (dialog) => { + prompts.push(dialog.message()); + await dialog.dismiss(); + }); + await install(page, state); + await page.goto('my-page'); + + await page.getByRole('button', { name: '명마', exact: true }).click(); + await page.getByRole('button', { name: '효경전', exact: true }).click(); + + expect(prompts).toEqual(['명마를 버리시겠습니까?', '효경전을 버리시겠습니까?']); +}); + test('장수 생성에서 등록 전콘을 골라 생성 요청에 전달한다', async ({ page }) => { const firstIconId = '3f804277-584f-4f44-b39c-9ecf40d1ed31'; const secondIconId = 'f6af46a2-809a-481d-b66d-0f7bbb706780'; diff --git a/app/game-frontend/e2e/nationCityOfficeIntegration.spec.ts b/app/game-frontend/e2e/nationCityOfficeIntegration.spec.ts index 08d20ab1..9c3e8861 100644 --- a/app/game-frontend/e2e/nationCityOfficeIntegration.spec.ts +++ b/app/game-frontend/e2e/nationCityOfficeIntegration.spec.ts @@ -397,7 +397,7 @@ test('암행부 행을 도시별로 나누고 수뇌의 인사부 즉시 임명 return { borderTopWidth: style.borderTopWidth, backgroundColor: style.backgroundColor }; }); expect(disabledStyle).toEqual({ borderTopWidth: '0px', backgroundColor: 'rgba(0, 0, 0, 0)' }); - const appointButton = page.getByRole('button', { name: '장료을(를) 허창 태수로 임명' }); + const appointButton = page.getByRole('button', { name: '장료를 허창 태수로 임명' }); await appointButton.hover(); expect(await appointButton.evaluate((button) => getComputedStyle(button).cursor)).toBe('pointer'); await appointButton.focus(); @@ -406,6 +406,7 @@ test('암행부 행을 도시별로 나누고 수뇌의 인사부 즉시 임명 await page.screenshot({ path: testInfo.outputPath('nation-city-integrated-desktop.png'), fullPage: true }); await appointButton.click(); await expect.poll(() => state.appointmentInputs).toEqual([{ destGeneralId: 21, destCityId: 1, officerLevel: 4 }]); + await expect(page.getByTestId('game-toast')).toContainText('장료를 허창 태수로 임명했습니다.'); await expect(page.locator('.city[data-city-id="1"] .officer-4-value')).toHaveText('장료'); await expect(page.locator('.city[data-city-id="1"] .officer-4-value')).toHaveClass(/effective-officer/u); await expect(page.locator('.city[data-city-id="1"] tr[data-general-id="21"] .mode-4')).toBeDisabled(); @@ -425,7 +426,7 @@ test('수뇌 대상은 재확인하고 일반 장수에게는 임명 버튼을 await page.getByRole('button', { name: '암행부 연동' }).click(); await page.getByRole('button', { name: '인사부 연동' }).click(); - const chiefButton = page.getByRole('button', { name: '순욱을(를) 허창 태수로 임명' }); + const chiefButton = page.getByRole('button', { name: '순욱을 허창 태수로 임명' }); expect(await chiefButton.evaluate((button) => getComputedStyle(button).color)).toBe('rgb(255, 0, 0)'); page.once('dialog', async (dialog) => { expect(dialog.message()).toBe('수뇌입니다. 임명할까요?'); diff --git a/app/game-frontend/src/views/MyPageView.vue b/app/game-frontend/src/views/MyPageView.vue index bb647408..7e1cb673 100644 --- a/app/game-frontend/src/views/MyPageView.vue +++ b/app/game-frontend/src/views/MyPageView.vue @@ -1,4 +1,5 @@