위협 가이드를 관리자 전용 옵션으로(기본 꺼짐) + 최고관리자 추가 + 계정 메뉴에 관리자 메뉴

- 엔진: GameDefinition.adminOnlyOptions — 방은 항상 관리자 값 사용(잠금처럼 강제, 잠금 안내는 안 띄움)
- 오목·체스·장기 threatHints, 바둑 atariWarning: 기본 false, 대기실 설정에서 뺌, 관리자 화면 게임 기본 규칙에서만 켬
- 체스·장기 hints는 off / moves만 남김
- 최고관리자 기본값에 1352267557213573160 추가(.env.example·문서 포함)
- 상단 계정 메뉴: 관리자·최고관리자면 [🛠 관리자 메뉴] → /admin
- 테스트: admin.test(관리자 전용 옵션 강제, 두 번째 최고관리자), admin.e2e(계정 메뉴, 위협 가이드 켜기 저장)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
EJClaw
2026-10-07 15:59:32 +09:00
parent 4cb71d8cbe
commit 373231b553
32 changed files with 207 additions and 45 deletions

View File

@@ -69,7 +69,15 @@ try {
await a.screenshot({ path: join(SHOTS, 'admin-1-dashboard.png') });
});
await step('게임 설정: 오목 렌주룰 고정 + 한 수 45초 저장', async () => {
await step('상단 계정 메뉴에 [관리자 메뉴] → 관리자 화면', async () => {
await a.goto(ORIGIN + '/');
await a.getByRole('button', { name: /내 계정:/ }).click();
await a.getByRole('menuitem', { name: /관리자 메뉴/ }).click();
await a.waitForURL(`${ORIGIN}/admin`);
await a.getByText('지금 접속').waitFor();
});
await step('게임 설정: 오목 렌주룰 고정 + 한 수 45초 + 위협 가이드 켜기 저장', async () => {
await a.locator('.admin-side').getByRole('link', { name: '게임', exact: true }).click();
await a.getByRole('button', { name: /오목/ }).click();
await a.getByText('기본 규칙').waitFor();
@@ -78,9 +86,13 @@ try {
await rule.getByLabel(/방장 변경 금지/).check();
const per = a.locator('div.stack:has(> div.row > strong:text-is("한 수 제한(초)"))').first();
await per.locator('input[type=number]').fill('45');
const threat = a.locator('div.stack:has(> div.row > strong:text-is("위협 가이드(관리자 전용): 상대 3·4를 막을 자리 표시"))').first();
await threat.getByRole('button', { name: '켜기', exact: true }).click();
await a.screenshot({ path: join(SHOTS, 'admin-2-game-editor.png') });
await a.getByRole('button', { name: '저장', exact: true }).click();
await a.getByText('저장했어요.').waitFor();
const saved = await a.evaluate(async () => (await (await fetch('/api/admin/games')).json()).games.find((x: any) => x.id === 'omok').effective.defaultOptions.threatHints);
if (saved !== true) throw new Error(`threatHints not saved: ${saved}`);
});
await step('관리자 탭: 디스코드 ID로 어드민 추가', async () => {
@@ -109,8 +121,10 @@ try {
await g.waitForURL(/\/r\/\d{6}$/);
await g.getByText('렌주룰 · 15줄 · 한 수 45초').waitFor();
await g.getByText('일부 규칙은 관리자가 정해 두어서').waitFor();
// The admin turned the threat guide on; the host has no switch for it (checked below).
// Trying to switch to 한국식 is overridden by the server.
await g.getByRole('button', { name: '설정 바꾸기' }).click();
if (await g.getByText(/위험한 자리 알려|위협 가이드/).count()) throw new Error('host sees a threat-guide switch');
await g.getByRole('button', { name: '한국식(쌍삼 금지)' }).click();
await g.getByRole('button', { name: '저장' }).click();
await g.waitForTimeout(300);