메인 턴 당기기와 미루기를 1턴 기본 분할 버튼으로 변경
This commit is contained in:
@@ -987,6 +987,20 @@ const install = async (
|
||||
if (name === 'messages.getContacts') return response({ nation: [] });
|
||||
if (name === 'board.getAccess') return response({ canMeeting: false, canSecret: false });
|
||||
if (name === 'tournament.getState') return response({ stage: 0 });
|
||||
if (name === 'turns.reserved.shiftGeneral') {
|
||||
const input = (body as Record<string, { generalId: number; amount: number; expectedRevision: number }>)[
|
||||
String(names.indexOf(name))
|
||||
];
|
||||
expect(route.request().method()).toBe('POST');
|
||||
expect(input.generalId).toBe(generalId);
|
||||
expect(input.expectedRevision).toBe(generalRevision);
|
||||
expect(
|
||||
Number.isInteger(input.amount) && Math.abs(input.amount) >= 1 && Math.abs(input.amount) <= 6
|
||||
).toBe(true);
|
||||
requests.push(input);
|
||||
generalRevision += 1;
|
||||
return response({ ok: true, revision: generalRevision, turns: generalTurns, autorunLimit: 2403 });
|
||||
}
|
||||
if (name === 'turns.reserved.setGeneralBulk') {
|
||||
requests.push(body);
|
||||
if (rejectGeneral) return errorResponse(name, '대상 도시를 선택할 수 없습니다.');
|
||||
@@ -1019,6 +1033,80 @@ const install = async (
|
||||
return requests;
|
||||
};
|
||||
|
||||
for (const width of [1200, 500]) {
|
||||
test(`split turn shift applies one turn or the chosen count in both modes at ${width}px`, async ({
|
||||
page,
|
||||
}, testInfo) => {
|
||||
const requests = await install(page);
|
||||
const shifts = () =>
|
||||
requests.filter((entry) => typeof entry === 'object' && entry !== null && 'amount' in entry);
|
||||
await page.setViewportSize({ width, height: 900 });
|
||||
await page.goto('/');
|
||||
const editor = page.locator('[data-command-scope="general"]:visible');
|
||||
const evidence: unknown[] = [];
|
||||
for (const advanced of [false, true]) {
|
||||
if (advanced) await editor.getByRole('button', { name: '고급 모드', exact: true }).click();
|
||||
for (const [index, label] of ['당기기', '미루기'].entries()) {
|
||||
const direction = index === 0 ? -1 : 1;
|
||||
const control = editor.locator('.bottom-shift-control').nth(index);
|
||||
const main = control.getByRole('button', { name: label, exact: true });
|
||||
const menu = control.locator('details');
|
||||
const toggle = menu.locator('summary');
|
||||
const before = shifts().length;
|
||||
await main.click();
|
||||
await expect.poll(() => shifts().length).toBe(before + 1);
|
||||
expect(shifts().at(-1)).toMatchObject({ amount: direction });
|
||||
await expect(menu).not.toHaveAttribute('open');
|
||||
await toggle.focus();
|
||||
await page.keyboard.press('Enter');
|
||||
await expect(menu).toHaveAttribute('open');
|
||||
expect(shifts().length).toBe(before + 1);
|
||||
await expect(menu.locator('.menu-items > button')).toHaveText([
|
||||
'1턴',
|
||||
'2턴',
|
||||
'3턴',
|
||||
'4턴',
|
||||
'5턴',
|
||||
'6턴',
|
||||
]);
|
||||
const geometry = await control.evaluate((element) => {
|
||||
const main = element.querySelector('button')!;
|
||||
const toggle = element.querySelector('summary')!;
|
||||
const menu = element.querySelector('.menu-items')!;
|
||||
return {
|
||||
main: main.getBoundingClientRect().toJSON(),
|
||||
toggle: toggle.getBoundingClientRect().toJSON(),
|
||||
menu: menu.getBoundingClientRect().toJSON(),
|
||||
style: { radius: getComputedStyle(main).borderRadius, font: getComputedStyle(main).fontFamily },
|
||||
overflow: document.documentElement.scrollWidth - document.documentElement.clientWidth,
|
||||
};
|
||||
});
|
||||
expect(geometry.main.right).toBeCloseTo(geometry.toggle.left, 1);
|
||||
expect(geometry.menu.right).toBeLessThanOrEqual(width);
|
||||
expect(geometry.menu.left).toBeGreaterThanOrEqual(0);
|
||||
expect(geometry.overflow).toBeLessThanOrEqual(0);
|
||||
evidence.push({ advanced, label, geometry });
|
||||
await page.screenshot({
|
||||
path: testInfo.outputPath(`split-${advanced}-${index}-${width}.png`),
|
||||
fullPage: true,
|
||||
});
|
||||
await menu.getByRole('button', { name: '6턴', exact: true }).click();
|
||||
await expect.poll(() => shifts().length).toBe(before + 2);
|
||||
expect(shifts().at(-1)).toMatchObject({ amount: direction * 6 });
|
||||
await expect(menu).not.toHaveAttribute('open');
|
||||
await main.click();
|
||||
await expect.poll(() => shifts().length).toBe(before + 3);
|
||||
expect(shifts().at(-1)).toMatchObject({ amount: direction });
|
||||
}
|
||||
}
|
||||
await writeFile(testInfo.outputPath('split-evidence.json'), JSON.stringify(evidence, null, 2));
|
||||
await writeFile(
|
||||
testInfo.outputPath('split-editor.html'),
|
||||
await editor.evaluate((element) => element.outerHTML)
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
test('offers 12 repeat turns and six shift turns for general turns while keeping the chief range', async ({ page }) => {
|
||||
await install(page);
|
||||
await page.setViewportSize({ width: 1200, height: 900 });
|
||||
|
||||
@@ -4393,10 +4393,12 @@ test('all main Lumen button families share the rounded pressed geometry', async
|
||||
[
|
||||
'당기기',
|
||||
page.locator('[data-main-target="commands"] .bottom-actions').getByRole('button', { name: '당기기' }),
|
||||
{ radius: '5.25px 0px 0px 5.25px' },
|
||||
],
|
||||
[
|
||||
'미루기',
|
||||
page.locator('[data-main-target="commands"] .bottom-actions').getByRole('button', { name: '미루기' }),
|
||||
{ radius: '5.25px 0px 0px 5.25px' },
|
||||
],
|
||||
[
|
||||
'펼치기',
|
||||
@@ -4457,7 +4459,7 @@ test('all main Lumen button families share the rounded pressed geometry', async
|
||||
filter: 'none',
|
||||
});
|
||||
if (label === '당기기' || label === '미루기') {
|
||||
expect(base.width, `${label} fills its menu column`).toBeCloseTo(base.parentWidth, 2);
|
||||
expect(base.width, `${label} leaves room for the split button`).toBeCloseTo(base.parentWidth - 28, 2);
|
||||
}
|
||||
|
||||
await control.focus();
|
||||
@@ -4702,7 +4704,7 @@ test('mobile main Lumen button families keep the same state geometry without ove
|
||||
await expect(control).toHaveClass(/legacy-button/u);
|
||||
await expect(control).toHaveCSS(
|
||||
'border-radius',
|
||||
index === 7 ? '0px 5.25px 5.25px 0px' : index === 8 ? '5.25px 0px 0px 5.25px' : '5.25px'
|
||||
index === 7 ? '0px 5.25px 5.25px 0px' : [4, 5, 8].includes(index) ? '5.25px 0px 0px 5.25px' : '5.25px'
|
||||
);
|
||||
await expect(control).toHaveCSS('border-bottom-width', '4px');
|
||||
}
|
||||
|
||||
@@ -701,38 +701,38 @@ const clickOutsideMenu = (event: Event) => {
|
||||
</div>
|
||||
|
||||
<div v-if="!props.compact" class="bottom-actions">
|
||||
<details class="legacy-menu bottom-shift-menu">
|
||||
<summary class="legacy-button legacy-button--secondary" role="button">당기기</summary>
|
||||
<div class="menu-items">
|
||||
<button
|
||||
v-for="amount in props.maxShiftTurn"
|
||||
:key="amount"
|
||||
type="button"
|
||||
@click="
|
||||
emit('shift', -amount);
|
||||
clickOutsideMenu($event);
|
||||
"
|
||||
<div v-for="direction in [-1, 1]" :key="direction" class="bottom-shift-control">
|
||||
<button
|
||||
class="legacy-button legacy-button--secondary shift-main"
|
||||
type="button"
|
||||
:title="direction < 0 ? '1턴 당기기' : '1턴 미루기'"
|
||||
@click="emit('shift', direction)"
|
||||
>
|
||||
{{ direction < 0 ? '당기기' : '미루기' }}
|
||||
</button>
|
||||
<details class="legacy-menu bottom-shift-menu">
|
||||
<summary
|
||||
class="legacy-button legacy-button--secondary"
|
||||
role="button"
|
||||
:aria-label="direction < 0 ? '당길 턴 수 선택' : '미룰 턴 수 선택'"
|
||||
>
|
||||
{{ amount }}턴
|
||||
</button>
|
||||
</div>
|
||||
</details>
|
||||
<details class="legacy-menu bottom-shift-menu">
|
||||
<summary class="legacy-button legacy-button--secondary" role="button">미루기</summary>
|
||||
<div class="menu-items">
|
||||
<button
|
||||
v-for="amount in props.maxShiftTurn"
|
||||
:key="amount"
|
||||
type="button"
|
||||
@click="
|
||||
emit('shift', amount);
|
||||
clickOutsideMenu($event);
|
||||
"
|
||||
>
|
||||
{{ amount }}턴
|
||||
</button>
|
||||
</div>
|
||||
</details>
|
||||
<span aria-hidden="true">▾</span>
|
||||
</summary>
|
||||
<div class="menu-items">
|
||||
<button
|
||||
v-for="amount in props.maxShiftTurn"
|
||||
:key="amount"
|
||||
type="button"
|
||||
@click="
|
||||
emit('shift', direction * amount);
|
||||
clickOutsideMenu($event);
|
||||
"
|
||||
>
|
||||
{{ amount }}턴
|
||||
</button>
|
||||
</div>
|
||||
</details>
|
||||
</div>
|
||||
<button class="legacy-button legacy-button--secondary" type="button" @click="expanded = !expanded">
|
||||
{{ expanded ? '접기' : '펼치기' }}
|
||||
</button>
|
||||
@@ -1098,8 +1098,29 @@ const clickOutsideMenu = (event: Event) => {
|
||||
gap: 4px;
|
||||
padding-top: 3px;
|
||||
}
|
||||
.bottom-shift-control {
|
||||
display: flex;
|
||||
min-width: 0;
|
||||
}
|
||||
.shift-main {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
border-top-right-radius: 0;
|
||||
border-bottom-right-radius: 0;
|
||||
}
|
||||
.bottom-shift-menu {
|
||||
flex: 0 0 28px;
|
||||
}
|
||||
.bottom-shift-menu > summary {
|
||||
width: 100%;
|
||||
padding-inline: 0;
|
||||
border-left: 0;
|
||||
border-top-left-radius: 0;
|
||||
border-bottom-left-radius: 0;
|
||||
}
|
||||
.bottom-shift-menu .menu-items {
|
||||
left: auto;
|
||||
right: 0;
|
||||
}
|
||||
.command-picker {
|
||||
position: absolute;
|
||||
|
||||
Reference in New Issue
Block a user