merge: 공개 지도 미리보기 정보 정리를 main에 반영

This commit is contained in:
2026-08-17 16:07:28 +00:00
3 changed files with 88 additions and 24 deletions
@@ -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 {
+30 -10
View File
@@ -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 {