Files
jongryangje/e2e/redesign.spec.js
taekyoungc c15e01bfa7 워크스페이스(탭) 도입 — 로그인 후 기본 화면을 탭 작업공간으로.
- /workspace: 헤더+사이드바+탭바+iframe 패널. 메뉴 클릭=탭 열기,
  전환해도 폼·스크롤·조회결과 등 작업 상태 유지(세션 동안)
- 로그인 후 / = 워크스페이스(첫 탭=대시보드). iframe 내부는 임베드 렌더
- 임베드 레이아웃(bag/layout/embed): 헤더·사이드바 없이 본문만
- 임베드 판정: ?embed=1 또는 Sec-Fetch-Dest=iframe (iframe 내 링크·폼·
  리다이렉트까지 중첩 크롬 없이 처리)
- iframe 안 세션만료 시 상위 창을 로그인으로 전환(auth/_shell)
- 포털 헤더에 워크스페이스 진입 링크, E2E(workspace.spec) 추가

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-08 13:32:53 +09:00

76 lines
3.3 KiB
JavaScript

const { test, expect } = require('@playwright/test');
const { login } = require('./helpers/auth');
/**
* gov-portal 디자인 전면 적용 검증
* - 메인(/) = 포털 대시보드(실데이터 카드)
* - 업무 페이지에 포털 셸(헤더+대메뉴+사이드바) 적용
* - 대메뉴 클릭 → 좌측 사이드바에 소메뉴 표시
*/
test.describe('gov-portal 전면 적용', () => {
test('메인(/)이 워크스페이스(탭) + 첫 탭 대시보드로 렌더', async ({ page }) => {
await login(page, 'user');
await page.goto('/');
await expect(page.locator('header.portal-header')).toBeVisible();
await expect(page.locator('.sidebar')).toBeVisible();
await expect(page.locator('.ws-tabbar')).toBeVisible();
// 첫 탭(대시보드) iframe 안에 실데이터 KPI
await expect(page.frameLocator('.ws-frame.active').getByText('봉투 재고 총량')).toBeVisible({ timeout: 10000 });
// 목업 흔적 없음
await expect(page.getByText('서비스 데스크')).toHaveCount(0);
});
test('업무 페이지에 포털 셸 적용', async ({ page }) => {
await login(page, 'user');
await page.goto('/bag/help');
await expect(page.locator('header.portal-header')).toBeVisible();
await expect(page.locator('#portalSidebarList')).toBeAttached();
await expect(page.locator('#portalTopNavClick')).toBeAttached();
});
test('관리자 계정은 상단에 관리자 링크 노출', async ({ page }) => {
await login(page, 'local');
await page.goto('/');
const adminLink = page.locator('header.portal-header a[href$="/admin"]');
await expect(adminLink).toBeVisible();
await expect(adminLink).toContainText('관리자');
});
test('로그인 페이지가 gov-portal 스타일(Pretendard)로 렌더', async ({ page }) => {
await page.goto('/login');
const hasPretendard = await page.evaluate(() =>
[...document.styleSheets, ...document.querySelectorAll('link')].some(
(n) => (n.href || '').includes('pretendard')));
expect(hasPretendard).toBeTruthy();
await expect(page.locator('input[name="login_id"]')).toBeVisible();
});
test('관리자 페이지에도 포털 셸 적용', async ({ page }) => {
await login(page, 'admin');
await page.goto('/admin/select-local-government');
await expect(page.locator('header.portal-header')).toBeVisible();
await expect(page.locator('#portalSidebarList')).toBeAttached();
await expect(page.locator('#portalTopNavClick')).toBeAttached();
});
test('로그인·메인 로고가 사이트 공통 로고로 통일', async ({ page }) => {
for (const url of ['/login', '/']) {
await page.goto(url);
const brand = page.locator('header a[href]').first();
await expect(brand).toContainText('종량제 시스템');
await expect(brand.locator('svg path')).toHaveCount(1); // 휴지통 SVG
}
});
test('대메뉴 클릭 시 사이드바에 소메뉴 표시', async ({ page }) => {
await login(page, 'user');
await page.goto('/');
const triggers = page.locator('.portal-nav-trigger[data-parent-idx]');
const n = await triggers.count();
test.skip(n === 0, '이 계정에 하위메뉴를 가진 대메뉴가 없음');
await triggers.first().click();
// 사이드바 목록에 항목이 채워짐
await expect(page.locator('#portalSidebarList li').first()).toBeVisible();
});
});