fix(ui): Gateway 관리자 메뉴와 로비 복귀 링크 겹침 수정
This commit is contained in:
@@ -8,7 +8,7 @@ const operationNames = (route: Route): string[] => {
|
||||
return decodeURIComponent(url.pathname.slice(url.pathname.lastIndexOf('/trpc/') + 6)).split(',');
|
||||
};
|
||||
|
||||
const installGatewayFixture = async (page: Page, roles: string[]) => {
|
||||
const installGatewayFixture = async (page: Page, roles: string[], manyProfiles = false) => {
|
||||
const requests: Array<{ method: string; url: string; body: unknown }> = [];
|
||||
await page.addInitScript(() => {
|
||||
window.localStorage.setItem('sammo-session-token', 'playwright-admin-session');
|
||||
@@ -62,6 +62,16 @@ const installGatewayFixture = async (page: Page, roles: string[]) => {
|
||||
);
|
||||
}
|
||||
if (operation === 'admin.profiles.listNavigation') {
|
||||
if (manyProfiles)
|
||||
return response(
|
||||
['che', 'kwe', 'twe', 'hwe', 'nya', 'pwe', 'pya'].map((profile) => ({
|
||||
profileName: `${profile}:default`,
|
||||
profile,
|
||||
instanceKey: 'default',
|
||||
displayName: `${profile.toUpperCase()} 서버`,
|
||||
currentScenario: '1010',
|
||||
}))
|
||||
);
|
||||
return response(
|
||||
roles.some((role) => role === 'superuser' || role.includes(':hwe:2'))
|
||||
? [
|
||||
@@ -378,3 +388,54 @@ test('scoped administrators see the same navigation while ordinary users do not'
|
||||
await expect(userPage.getByRole('link', { name: '관리자 페이지' })).toHaveCount(0);
|
||||
await userContext.close();
|
||||
});
|
||||
|
||||
for (const viewport of [
|
||||
{ width: 1280, height: 720 },
|
||||
{ width: 1200, height: 500 },
|
||||
{ width: 390, height: 844 },
|
||||
]) {
|
||||
test(`administrator exit stays separate from seven-profile navigation at ${viewport.width}x${viewport.height}`, async ({
|
||||
page,
|
||||
}, testInfo) => {
|
||||
await page.setViewportSize(viewport);
|
||||
await installGatewayFixture(page, ['superuser'], true);
|
||||
await page.goto('admin');
|
||||
if (viewport.width < 860) await page.getByRole('button', { name: '관리자 메뉴' }).click();
|
||||
else await page.evaluate(() => window.scrollTo(0, 76));
|
||||
const nav = page.getByRole('navigation', { name: '관리자 메뉴' });
|
||||
await expect(nav.getByRole('link', { name: 'PYA 서버' })).toBeVisible();
|
||||
const lastLink = nav.getByRole('link', { name: '감사 로그' });
|
||||
await lastLink.scrollIntoViewIfNeeded();
|
||||
await lastLink.focus();
|
||||
await expect(lastLink).toBeFocused();
|
||||
const exit = page.getByRole('link', { name: '← 로비로 돌아가기', exact: true });
|
||||
await exit.scrollIntoViewIfNeeded();
|
||||
const geometry = await page.locator('#admin-navigation').evaluate((sidebar) => {
|
||||
const nav = sidebar.querySelector('nav')!;
|
||||
const exit = sidebar.querySelector('.admin-exit')!;
|
||||
const last = sidebar.querySelector('.admin-nav-group:last-child .admin-nav-link:last-child')!;
|
||||
return {
|
||||
navBottom: nav.getBoundingClientRect().bottom,
|
||||
exitTop: exit.getBoundingClientRect().top,
|
||||
lastBottom: last.getBoundingClientRect().bottom,
|
||||
width: document.documentElement.scrollWidth,
|
||||
navHeight: nav.clientHeight,
|
||||
navScrollHeight: nav.scrollHeight,
|
||||
exitPosition: getComputedStyle(exit).position,
|
||||
};
|
||||
});
|
||||
expect(geometry.navBottom).toBeLessThanOrEqual(geometry.exitTop);
|
||||
expect(geometry.lastBottom).toBeLessThanOrEqual(geometry.exitTop);
|
||||
expect(geometry.width).toBeLessThanOrEqual(viewport.width);
|
||||
if (viewport.width >= 860) expect(geometry.navScrollHeight).toBeGreaterThan(geometry.navHeight);
|
||||
await page.evaluate(() => document.fonts.ready);
|
||||
await writeFile(testInfo.outputPath('sidebar-geometry.json'), JSON.stringify(geometry));
|
||||
await writeFile(testInfo.outputPath('sidebar.html'), await page.content());
|
||||
await page.screenshot({ path: testInfo.outputPath('sidebar.png'), fullPage: true });
|
||||
await exit.hover();
|
||||
await exit.focus();
|
||||
await expect(exit).toBeFocused();
|
||||
await exit.click();
|
||||
await expect(page).toHaveURL(/\/gateway\/lobby$/);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -212,12 +212,22 @@ onMounted(async () => {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
height: 100vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
border-right: 1px solid #27272a;
|
||||
background: #111113;
|
||||
padding: 24px 16px;
|
||||
}
|
||||
|
||||
.admin-sidebar > nav {
|
||||
flex: 1;
|
||||
min-height: 0;
|
||||
overflow-y: auto;
|
||||
overscroll-behavior-y: contain;
|
||||
}
|
||||
|
||||
.admin-identity {
|
||||
flex-shrink: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 11px;
|
||||
@@ -317,10 +327,9 @@ onMounted(async () => {
|
||||
}
|
||||
|
||||
.admin-exit {
|
||||
position: absolute;
|
||||
right: 24px;
|
||||
bottom: 24px;
|
||||
left: 24px;
|
||||
flex-shrink: 0;
|
||||
display: block;
|
||||
margin: 16px 8px 0;
|
||||
border-top: 1px solid #27272a;
|
||||
padding-top: 17px;
|
||||
color: #71717a;
|
||||
@@ -418,6 +427,10 @@ onMounted(async () => {
|
||||
padding: 18px 14px 14px;
|
||||
}
|
||||
|
||||
.admin-sidebar > nav {
|
||||
overflow-y: visible;
|
||||
}
|
||||
|
||||
.admin-sidebar.open {
|
||||
display: block;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user