fix: 공개 지도 미리보기 정보를 간결하게 정리
서버 탭 아래 중복 이름과 내부 지도 테마명을 제거하고 런타임 상태를 하단 요약으로 옮긴다. 연월은 레거시 지도 제목과 같은 20px 중앙 띠로 표시하고 데스크톱·모바일 Chromium 검증을 보강한다.
This commit is contained in:
@@ -219,7 +219,13 @@ test('shows one public map panel and switches it by hover, click, and keyboard',
|
|||||||
await expect(tablist.getByRole('tab', { name: '퀘섭' })).toHaveCount(0);
|
await expect(tablist.getByRole('tab', { name: '퀘섭' })).toHaveCount(0);
|
||||||
await expect(panel).toHaveCount(1);
|
await expect(panel).toHaveCount(1);
|
||||||
await expect(cheTab).toHaveAttribute('aria-selected', 'true');
|
await expect(cheTab).toHaveAttribute('aria-selected', 'true');
|
||||||
await expect(panel).toContainText('유저 11 / 500');
|
await expect(panel.getByText('체섭', { exact: true })).toHaveCount(0);
|
||||||
|
await expect(panel.locator('.map-preview-title')).toHaveCount(0);
|
||||||
|
const dateBar = panel.locator('.map-preview-date-bar');
|
||||||
|
await expect(dateBar).toHaveText('200년 1월');
|
||||||
|
const summary = panel.getByTestId('public-map-preview-summary');
|
||||||
|
await expect(summary).toContainText('RUNNING');
|
||||||
|
await expect(summary).toContainText('유저 11 / 500');
|
||||||
|
|
||||||
const roadLayer = panel.getByTestId('map-preview-road');
|
const roadLayer = panel.getByTestId('map-preview-road');
|
||||||
const castles = panel.getByTestId('map-preview-castle');
|
const castles = panel.getByTestId('map-preview-castle');
|
||||||
@@ -251,6 +257,32 @@ test('shows one public map panel and switches it by hover, click, and keyboard',
|
|||||||
largeCastle: { width: 32, height: 24 },
|
largeCastle: { width: 32, height: 24 },
|
||||||
largeNationBackground: { width: 96, height: 72 },
|
largeNationBackground: { width: 96, height: 72 },
|
||||||
});
|
});
|
||||||
|
const dateGeometry = await dateBar.evaluate((element) => {
|
||||||
|
const rect = element.getBoundingClientRect();
|
||||||
|
const bodyRect = element.nextElementSibling?.getBoundingClientRect();
|
||||||
|
const style = getComputedStyle(element);
|
||||||
|
const textStyle = getComputedStyle(element.firstElementChild!);
|
||||||
|
return {
|
||||||
|
width: rect.width,
|
||||||
|
height: rect.height,
|
||||||
|
bottom: rect.bottom,
|
||||||
|
bodyTop: bodyRect?.top,
|
||||||
|
backgroundColor: style.backgroundColor,
|
||||||
|
justifyContent: style.justifyContent,
|
||||||
|
fontSize: textStyle.fontSize,
|
||||||
|
lineHeight: textStyle.lineHeight,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
expect(dateGeometry).toEqual({
|
||||||
|
width: 700,
|
||||||
|
height: 20,
|
||||||
|
bottom: dateGeometry.bodyTop,
|
||||||
|
bodyTop: dateGeometry.bodyTop,
|
||||||
|
backgroundColor: 'rgb(0, 0, 0)',
|
||||||
|
justifyContent: 'center',
|
||||||
|
fontSize: '14px',
|
||||||
|
lineHeight: '20px',
|
||||||
|
});
|
||||||
if (requestedAssets) {
|
if (requestedAssets) {
|
||||||
await expect.poll(() => requestedAssets.has('/game/map/che/che_road.png')).toBe(true);
|
await expect.poll(() => requestedAssets.has('/game/map/che/che_road.png')).toBe(true);
|
||||||
await expect.poll(() => requestedAssets.has('/game/cast_8.gif')).toBe(true);
|
await expect.poll(() => requestedAssets.has('/game/cast_8.gif')).toBe(true);
|
||||||
@@ -297,7 +329,9 @@ test('shows one public map panel and switches it by hover, click, and keyboard',
|
|||||||
|
|
||||||
await hweTab.hover();
|
await hweTab.hover();
|
||||||
await expect(hweTab).toHaveAttribute('aria-selected', 'true');
|
await expect(hweTab).toHaveAttribute('aria-selected', 'true');
|
||||||
await expect(panel).toContainText('유저 22 / 500');
|
await expect(panel.getByText('훼섭', { exact: true })).toHaveCount(0);
|
||||||
|
await expect(summary).toContainText('PAUSED');
|
||||||
|
await expect(summary).toContainText('유저 22 / 500');
|
||||||
|
|
||||||
await cheTab.click();
|
await cheTab.click();
|
||||||
await expect(cheTab).toHaveAttribute('aria-selected', 'true');
|
await expect(cheTab).toHaveAttribute('aria-selected', 'true');
|
||||||
@@ -322,7 +356,7 @@ test('shows one public map panel and switches it by hover, click, and keyboard',
|
|||||||
await page.screenshot({ path: testInfo.outputPath('public-map-tabs-desktop.png'), fullPage: true });
|
await page.screenshot({ path: testInfo.outputPath('public-map-tabs-desktop.png'), fullPage: true });
|
||||||
await testInfo.attach('public-map-tabs-desktop-geometry', {
|
await testInfo.attach('public-map-tabs-desktop-geometry', {
|
||||||
body: Buffer.from(
|
body: Buffer.from(
|
||||||
`${JSON.stringify({ panel: geometry, map: mapGeometry, tooltip: tooltipGeometry }, null, 2)}\n`
|
`${JSON.stringify({ panel: geometry, date: dateGeometry, map: mapGeometry, tooltip: tooltipGeometry }, null, 2)}\n`
|
||||||
),
|
),
|
||||||
contentType: 'application/json',
|
contentType: 'application/json',
|
||||||
});
|
});
|
||||||
@@ -344,13 +378,20 @@ test.describe('touch navigation', () => {
|
|||||||
await hweTab.tap();
|
await hweTab.tap();
|
||||||
await expect(hweTab).toHaveAttribute('aria-selected', 'true');
|
await expect(hweTab).toHaveAttribute('aria-selected', 'true');
|
||||||
const panel = page.getByTestId('public-map-preview-panel');
|
const panel = page.getByTestId('public-map-preview-panel');
|
||||||
await expect(panel).toContainText('유저 22 / 500');
|
await expect(panel.getByText('훼섭', { exact: true })).toHaveCount(0);
|
||||||
|
await expect(panel.locator('.map-preview-title')).toHaveCount(0);
|
||||||
|
await expect(panel.locator('.map-preview-date-bar')).toHaveText('200년 1월');
|
||||||
|
const summary = panel.getByTestId('public-map-preview-summary');
|
||||||
|
await expect(summary).toContainText('PAUSED');
|
||||||
|
await expect(summary).toContainText('유저 22 / 500');
|
||||||
await expect(panel.getByTestId('map-preview-road')).toBeVisible();
|
await expect(panel.getByTestId('map-preview-road')).toBeVisible();
|
||||||
await expect(panel.getByTestId('map-preview-castle')).toHaveCount(2);
|
await expect(panel.getByTestId('map-preview-castle')).toHaveCount(2);
|
||||||
const mapBox = await panel.locator('.map-preview-body').boundingBox();
|
const mapBox = await panel.locator('.map-preview-body').boundingBox();
|
||||||
expect(mapBox?.width).toBeGreaterThan(280);
|
expect(mapBox?.width).toBeGreaterThan(280);
|
||||||
expect(mapBox?.width).toBeLessThanOrEqual(366);
|
expect(mapBox?.width).toBeLessThanOrEqual(366);
|
||||||
expect(mapBox?.height).toBeCloseTo((mapBox?.width ?? 0) * (5 / 7), 0);
|
expect(mapBox?.height).toBeCloseTo((mapBox?.width ?? 0) * (5 / 7), 0);
|
||||||
|
const horizontalOverflow = await panel.evaluate((element) => element.scrollWidth - element.clientWidth);
|
||||||
|
expect(horizontalOverflow).toBe(0);
|
||||||
const rightCity = panel.getByTestId('map-preview-city').nth(1);
|
const rightCity = panel.getByTestId('map-preview-city').nth(1);
|
||||||
await rightCity.hover();
|
await rightCity.hover();
|
||||||
const tooltip = panel.getByTestId('map-preview-city-tooltip');
|
const tooltip = panel.getByTestId('map-preview-city-tooltip');
|
||||||
|
|||||||
@@ -276,8 +276,7 @@ const stateClass = (state: number): string => {
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="map-preview" :class="`map-preview-${props.mode}`">
|
<div class="map-preview" :class="`map-preview-${props.mode}`">
|
||||||
<div class="map-preview-header">
|
<div class="map-preview-date-bar">
|
||||||
<span class="map-preview-title">{{ props.mapLayout.mapName }}</span>
|
|
||||||
<span class="map-preview-date">{{ props.mapData.year }}년 {{ props.mapData.month }}월</span>
|
<span class="map-preview-date">{{ props.mapData.year }}년 {{ props.mapData.month }}월</span>
|
||||||
</div>
|
</div>
|
||||||
<div ref="mapBody" class="map-preview-body" :style="{ backgroundImage: `url('${mapBackground}')` }">
|
<div ref="mapBody" class="map-preview-body" :style="{ backgroundImage: `url('${mapBackground}')` }">
|
||||||
@@ -358,18 +357,22 @@ const stateClass = (state: number): string => {
|
|||||||
width: min(100%, 700px);
|
width: min(100%, 700px);
|
||||||
margin-inline: auto;
|
margin-inline: auto;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 6px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.map-preview-header {
|
.map-preview-date-bar {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
height: 20px;
|
||||||
font-size: 0.7rem;
|
justify-content: center;
|
||||||
color: rgba(232, 221, 196, 0.7);
|
background: #000;
|
||||||
|
color: rgba(232, 221, 196, 0.82);
|
||||||
}
|
}
|
||||||
|
|
||||||
.map-preview-title {
|
.map-preview-date {
|
||||||
font-weight: 600;
|
display: block;
|
||||||
|
width: 160px;
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 20px;
|
||||||
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.map-preview-body {
|
.map-preview-body {
|
||||||
|
|||||||
@@ -700,12 +700,6 @@ const handleEnter = async (profile: LobbyProfile, targetPath: string) => {
|
|||||||
class="map-preview-panel"
|
class="map-preview-panel"
|
||||||
data-testid="public-map-preview-panel"
|
data-testid="public-map-preview-panel"
|
||||||
>
|
>
|
||||||
<div class="flex items-center justify-between text-xs text-zinc-400 mb-2">
|
|
||||||
<span class="font-semibold" :style="{ color: selectedMapProfile.color }">
|
|
||||||
{{ selectedMapProfile.korName }}섭
|
|
||||||
</span>
|
|
||||||
<span>{{ selectedMapProfile.status }}</span>
|
|
||||||
</div>
|
|
||||||
<div v-if="selectedMapPreview">
|
<div v-if="selectedMapPreview">
|
||||||
<MapPreview
|
<MapPreview
|
||||||
:map-data="selectedMapPreview.mapData"
|
:map-data="selectedMapPreview.mapData"
|
||||||
@@ -714,12 +708,18 @@ const handleEnter = async (profile: LobbyProfile, targetPath: string) => {
|
|||||||
/>
|
/>
|
||||||
<div
|
<div
|
||||||
v-if="profileDetails[selectedMapProfile.profileName]"
|
v-if="profileDetails[selectedMapProfile.profileName]"
|
||||||
class="text-xs text-zinc-400 mt-2"
|
class="map-preview-summary"
|
||||||
|
data-testid="public-map-preview-summary"
|
||||||
>
|
>
|
||||||
|
<span class="map-preview-runtime-status" :style="{ color: selectedMapProfile.color }">
|
||||||
|
{{ selectedMapProfile.status }}
|
||||||
|
</span>
|
||||||
|
<span>
|
||||||
유저 {{ profileDetails[selectedMapProfile.profileName]?.userCnt ?? '-' }} /
|
유저 {{ profileDetails[selectedMapProfile.profileName]?.userCnt ?? '-' }} /
|
||||||
{{ profileDetails[selectedMapProfile.profileName]?.maxUserCnt ?? '-' }} ·
|
{{ profileDetails[selectedMapProfile.profileName]?.maxUserCnt ?? '-' }}
|
||||||
{{ profileDetails[selectedMapProfile.profileName]?.nationCnt ?? '-' }}국 ·
|
</span>
|
||||||
{{ profileDetails[selectedMapProfile.profileName]?.turnTerm ?? '-' }}분 턴
|
<span>{{ profileDetails[selectedMapProfile.profileName]?.nationCnt ?? '-' }}국</span>
|
||||||
|
<span>{{ profileDetails[selectedMapProfile.profileName]?.turnTerm ?? '-' }}분 턴</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div v-else class="text-xs text-zinc-500 py-8 text-center">지도를 불러오는 중...</div>
|
<div v-else class="text-xs text-zinc-500 py-8 text-center">지도를 불러오는 중...</div>
|
||||||
@@ -832,6 +832,26 @@ const handleEnter = async (profile: LobbyProfile, targetPath: string) => {
|
|||||||
padding: 12px;
|
padding: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.map-preview-summary {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 2px 0;
|
||||||
|
margin-top: 8px;
|
||||||
|
color: #a1a1aa;
|
||||||
|
font-size: 12px;
|
||||||
|
line-height: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.map-preview-summary > span + span::before {
|
||||||
|
margin-inline: 6px;
|
||||||
|
color: #52525b;
|
||||||
|
content: '·';
|
||||||
|
}
|
||||||
|
|
||||||
|
.map-preview-runtime-status {
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
.legacy-logout-button:hover,
|
.legacy-logout-button:hover,
|
||||||
.legacy-logout-button:focus,
|
.legacy-logout-button:focus,
|
||||||
.legacy-logout-button:active {
|
.legacy-logout-button:active {
|
||||||
|
|||||||
Reference in New Issue
Block a user