fix: 자율 행동 상태를 행 툴팁으로 표시
This commit is contained in:
@@ -1300,18 +1300,36 @@ test('keeps the entered command visible and reports a server validation error',
|
|||||||
await expect(page.getByTestId('command-argument-form').locator('select')).toHaveValue('2');
|
await expect(page.getByTestId('command-argument-form').locator('select')).toHaveValue('2');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('keeps Ref command briefs and autonomous-action state after a turn mutation', async ({ page }) => {
|
test('keeps Ref command briefs and autonomous-action state after a turn mutation', async ({ page, context }) => {
|
||||||
await install(page);
|
await install(page);
|
||||||
await page.setViewportSize({ width: 1200, height: 900 });
|
await page.setViewportSize({ width: 1200, height: 900 });
|
||||||
await page.goto('/');
|
await page.goto('/');
|
||||||
|
|
||||||
const editor = page.locator('[data-command-scope="general"]');
|
const editor = page.locator('[data-command-scope="general"]');
|
||||||
const status = editor.locator('[data-command-autorun-status]');
|
|
||||||
const firstRow = editor.locator('.action-column > div').first();
|
const firstRow = editor.locator('.action-column > div').first();
|
||||||
await expect(status).toHaveText(/자율 행동: 200年 3月 · \d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}까지/u);
|
await expect(editor.locator('[data-command-autorun-status]')).toHaveCount(0);
|
||||||
await expect(firstRow).toContainText('휴식(자율 행동)');
|
await expect(firstRow).toContainText('휴식(자율 행동)');
|
||||||
|
await expect(firstRow).toHaveAttribute(
|
||||||
|
'data-autorun-tooltip',
|
||||||
|
/자율 행동: 200年 3月 · \d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}까지/u
|
||||||
|
);
|
||||||
expect(await firstRow.evaluate((element) => getComputedStyle(element).color)).toBe('rgb(170, 255, 255)');
|
expect(await firstRow.evaluate((element) => getComputedStyle(element).color)).toBe('rgb(170, 255, 255)');
|
||||||
|
|
||||||
|
const tooltipStyle = () =>
|
||||||
|
firstRow.evaluate((element) => {
|
||||||
|
const style = getComputedStyle(element, '::after');
|
||||||
|
return { content: style.content, opacity: style.opacity, visibility: style.visibility };
|
||||||
|
});
|
||||||
|
expect((await tooltipStyle()).visibility).toBe('hidden');
|
||||||
|
const heightBeforeHover = await editor.evaluate((element) => element.getBoundingClientRect().height);
|
||||||
|
await firstRow.hover();
|
||||||
|
await expect.poll(async () => (await tooltipStyle()).visibility).toBe('visible');
|
||||||
|
expect((await tooltipStyle()).content).toContain('자율 행동: 200年 3月');
|
||||||
|
expect(await editor.evaluate((element) => element.getBoundingClientRect().height)).toBe(heightBeforeHover);
|
||||||
|
await page.screenshot({ path: test.info().outputPath('command-brief-autorun-hover-desktop-1200.png'), fullPage: true });
|
||||||
|
await page.mouse.move(0, 0);
|
||||||
|
await expect.poll(async () => (await tooltipStyle()).visibility).toBe('hidden');
|
||||||
|
|
||||||
await page.getByRole('button', { name: '1턴 명령 입력', exact: true }).click();
|
await page.getByRole('button', { name: '1턴 명령 입력', exact: true }).click();
|
||||||
const picker = page.getByTestId('command-picker');
|
const picker = page.getByTestId('command-picker');
|
||||||
await picker.getByRole('button', { name: '군사', exact: true }).click();
|
await picker.getByRole('button', { name: '군사', exact: true }).click();
|
||||||
@@ -1320,31 +1338,46 @@ test('keeps Ref command briefs and autonomous-action state after a turn mutation
|
|||||||
await picker.getByRole('button', { name: '입력', exact: true }).click();
|
await picker.getByRole('button', { name: '입력', exact: true }).click();
|
||||||
|
|
||||||
await expect(firstRow).toHaveText('【단양】으로 출병');
|
await expect(firstRow).toHaveText('【단양】으로 출병');
|
||||||
await expect(firstRow).toHaveAttribute('title', /자율 행동/u);
|
await expect(firstRow).toHaveAttribute('data-autorun-tooltip', /자율 행동: 200年 3月 · .*까지/u);
|
||||||
expect(await firstRow.evaluate((element) => getComputedStyle(element).color)).toBe('rgb(170, 255, 255)');
|
expect(await firstRow.evaluate((element) => getComputedStyle(element).color)).toBe('rgb(170, 255, 255)');
|
||||||
await expect(status).toHaveText(/자율 행동: 200年 3月 · .*까지/u);
|
await firstRow.focus();
|
||||||
|
await expect.poll(async () => (await tooltipStyle()).visibility).toBe('visible');
|
||||||
|
await expect(firstRow).toBeFocused();
|
||||||
|
|
||||||
const desktopGeometry = await editor.evaluate((element) => {
|
const desktopGeometry = await editor.evaluate((element) => {
|
||||||
const statusElement = element.querySelector<HTMLElement>('[data-command-autorun-status]');
|
const layout = element.querySelector<HTMLElement>('.editor-layout');
|
||||||
|
const controlPad = element.querySelector<HTMLElement>('.control-pad');
|
||||||
const row = element.querySelector<HTMLElement>('.action-column > div');
|
const row = element.querySelector<HTMLElement>('.action-column > div');
|
||||||
if (!statusElement || !row) throw new Error('autonomous command geometry is missing');
|
if (!layout || !controlPad || !row) throw new Error('autonomous command geometry is missing');
|
||||||
return {
|
return {
|
||||||
horizontalOverflow: element.scrollWidth - element.clientWidth,
|
horizontalOverflow: element.scrollWidth - element.clientWidth,
|
||||||
statusWidth: statusElement.getBoundingClientRect().width,
|
controlPadOffset: controlPad.getBoundingClientRect().top - layout.getBoundingClientRect().top,
|
||||||
editorWidth: element.getBoundingClientRect().width,
|
|
||||||
rowHeight: row.getBoundingClientRect().height,
|
rowHeight: row.getBoundingClientRect().height,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
expect(desktopGeometry.horizontalOverflow).toBeLessThanOrEqual(0);
|
expect(desktopGeometry.horizontalOverflow).toBeLessThanOrEqual(0);
|
||||||
expect(desktopGeometry.statusWidth).toBeLessThanOrEqual(desktopGeometry.editorWidth);
|
expect(desktopGeometry.controlPadOffset).toBe(0);
|
||||||
expect(desktopGeometry.rowHeight).toBeGreaterThanOrEqual(20);
|
expect(desktopGeometry.rowHeight).toBeGreaterThanOrEqual(20);
|
||||||
await page.screenshot({ path: test.info().outputPath('command-brief-autorun-desktop-1200.png'), fullPage: true });
|
await page.screenshot({ path: test.info().outputPath('command-brief-autorun-focus-desktop-1200.png'), fullPage: true });
|
||||||
|
|
||||||
await page.setViewportSize({ width: 500, height: 900 });
|
const mobilePage = await context.newPage();
|
||||||
await expect(firstRow).toHaveText('【단양】으로 출병');
|
await install(mobilePage);
|
||||||
await expect(status).toBeVisible();
|
await mobilePage.setViewportSize({ width: 500, height: 900 });
|
||||||
expect(await editor.evaluate((element) => element.scrollWidth - element.clientWidth)).toBeLessThanOrEqual(0);
|
await mobilePage.goto('/');
|
||||||
await page.screenshot({ path: test.info().outputPath('command-brief-autorun-mobile-500.png'), fullPage: true });
|
const mobileEditor = mobilePage.locator('[data-command-scope="general"]');
|
||||||
|
const mobileFirstRow = mobileEditor.locator('.action-column > div').first();
|
||||||
|
await expect(mobileFirstRow).toContainText('휴식(자율 행동)');
|
||||||
|
await expect(mobileFirstRow).toHaveAttribute('data-autorun-tooltip', /자율 행동: 200年 3月 · .*까지/u);
|
||||||
|
await mobileFirstRow.focus();
|
||||||
|
await expect
|
||||||
|
.poll(() => mobileFirstRow.evaluate((element) => getComputedStyle(element, '::after').visibility))
|
||||||
|
.toBe('visible');
|
||||||
|
expect(await mobileEditor.evaluate((element) => element.scrollWidth - element.clientWidth)).toBeLessThanOrEqual(0);
|
||||||
|
await mobilePage.screenshot({
|
||||||
|
path: test.info().outputPath('command-brief-autorun-focus-mobile-500.png'),
|
||||||
|
fullPage: true,
|
||||||
|
});
|
||||||
|
await mobilePage.close();
|
||||||
});
|
});
|
||||||
|
|
||||||
test('uses drag selection, clipboard paste, and a stored template in advanced mode', async ({ page }) => {
|
test('uses drag selection, clipboard paste, and a stored template in advanced mode', async ({ page }) => {
|
||||||
|
|||||||
@@ -348,10 +348,6 @@ const clickOutsideMenu = (event: Event) => {
|
|||||||
<span>{{ props.title }} :</span><strong>{{ props.name ?? '-' }}</strong>
|
<span>{{ props.title }} :</span><strong>{{ props.name ?? '-' }}</strong>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
<div v-if="props.autonomousUntil" class="autorun-status" data-command-autorun-status role="status">
|
|
||||||
자율 행동: {{ props.autonomousUntil }}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="editor-layout">
|
<div class="editor-layout">
|
||||||
<aside class="control-pad">
|
<aside class="control-pad">
|
||||||
<div v-if="props.mobile && props.compact" class="mobile-identity legacy-bg1">
|
<div v-if="props.mobile && props.compact" class="mobile-identity legacy-bg1">
|
||||||
@@ -640,10 +636,17 @@ const clickOutsideMenu = (event: Event) => {
|
|||||||
<div
|
<div
|
||||||
v-for="row in displayRows"
|
v-for="row in displayRows"
|
||||||
:key="row.index"
|
:key="row.index"
|
||||||
:title="
|
:title="row.autonomous ? undefined : rowLabel(row)"
|
||||||
row.autonomous
|
:data-autorun-tooltip="
|
||||||
? `${rowLabel(row)} · 자율 행동${props.autonomousUntil ? ` (${props.autonomousUntil})` : ''}`
|
row.autonomous && props.autonomousUntil
|
||||||
: rowLabel(row)
|
? `자율 행동: ${props.autonomousUntil}`
|
||||||
|
: undefined
|
||||||
|
"
|
||||||
|
:tabindex="row.autonomous && props.autonomousUntil ? 0 : undefined"
|
||||||
|
:aria-label="
|
||||||
|
row.autonomous && props.autonomousUntil
|
||||||
|
? `${rowLabel(row)}. 자율 행동: ${props.autonomousUntil}`
|
||||||
|
: undefined
|
||||||
"
|
"
|
||||||
:class="{ autonomous: row.autonomous }"
|
:class="{ autonomous: row.autonomous }"
|
||||||
>
|
>
|
||||||
@@ -887,15 +890,6 @@ const clickOutsideMenu = (event: Event) => {
|
|||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: 75px 40px minmax(0, 1fr) 38px;
|
grid-template-columns: 75px 40px minmax(0, 1fr) 38px;
|
||||||
}
|
}
|
||||||
.autorun-status {
|
|
||||||
padding: 3px 6px;
|
|
||||||
border-bottom: 1px solid #2d6574;
|
|
||||||
background: #102c35;
|
|
||||||
color: #aaffff;
|
|
||||||
font-size: 0.78rem;
|
|
||||||
line-height: 1.35;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
.queue-grid.advanced {
|
.queue-grid.advanced {
|
||||||
grid-template-columns: 34px 75px 40px minmax(0, 1fr);
|
grid-template-columns: 34px 75px 40px minmax(0, 1fr);
|
||||||
}
|
}
|
||||||
@@ -965,6 +959,52 @@ const clickOutsideMenu = (event: Event) => {
|
|||||||
.action-column > div.autonomous {
|
.action-column > div.autonomous {
|
||||||
color: #aaffff;
|
color: #aaffff;
|
||||||
}
|
}
|
||||||
|
.action-column > div.autonomous[data-autorun-tooltip] {
|
||||||
|
position: relative;
|
||||||
|
overflow: visible;
|
||||||
|
outline-offset: -2px;
|
||||||
|
}
|
||||||
|
.action-column > div.autonomous[data-autorun-tooltip] > span {
|
||||||
|
min-width: 0;
|
||||||
|
max-width: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
.action-column > div.autonomous[data-autorun-tooltip]::after {
|
||||||
|
content: attr(data-autorun-tooltip);
|
||||||
|
position: absolute;
|
||||||
|
z-index: 30;
|
||||||
|
right: 0;
|
||||||
|
bottom: calc(100% + 3px);
|
||||||
|
box-sizing: border-box;
|
||||||
|
width: min(200px, calc(100vw - 16px));
|
||||||
|
padding: 5px 7px;
|
||||||
|
border: 1px solid #2d6574;
|
||||||
|
border-radius: 3px;
|
||||||
|
background: #102c35;
|
||||||
|
box-shadow: 0 3px 8px #000;
|
||||||
|
color: #aaffff;
|
||||||
|
font-size: 0.78rem;
|
||||||
|
font-weight: 400;
|
||||||
|
line-height: 1.35;
|
||||||
|
text-align: left;
|
||||||
|
white-space: normal;
|
||||||
|
opacity: 0;
|
||||||
|
visibility: hidden;
|
||||||
|
pointer-events: none;
|
||||||
|
transition:
|
||||||
|
opacity 80ms ease-out,
|
||||||
|
visibility 80ms ease-out;
|
||||||
|
}
|
||||||
|
.action-column > div.autonomous[data-autorun-tooltip]:hover,
|
||||||
|
.action-column > div.autonomous[data-autorun-tooltip]:focus {
|
||||||
|
z-index: 25;
|
||||||
|
}
|
||||||
|
.action-column > div.autonomous[data-autorun-tooltip]:hover::after,
|
||||||
|
.action-column > div.autonomous[data-autorun-tooltip]:focus::after {
|
||||||
|
opacity: 1;
|
||||||
|
visibility: visible;
|
||||||
|
}
|
||||||
.action-column small {
|
.action-column small {
|
||||||
font-size: 0.72em;
|
font-size: 0.72em;
|
||||||
line-height: 1;
|
line-height: 1;
|
||||||
|
|||||||
Reference in New Issue
Block a user