Playwright E2E Smoke 테스트 디버깅 가이드
이 문서는 소비 포털의 e2e:smoke 테스트가 실패했을 때 원인을 재현하고, CI artifact를 분석하고, 수정 사항을 검증하는 절차를 설명한다. 현재 smoke suite는 공통 Portal Shell 렌더링, 관리자 화면 이동, 계정 설정의 dark mode 전환, /admin 직접 진입, browser console error와 uncaught page error를 검증한다.
1. CI 실패 결과 확인
GitHub Actions의 Consumer portal CI 실행 화면에서 먼저 실패한 step을 확인한다. Typecheck, Build, Run consumer portal E2E smoke 중 어느 단계에서 실패했는지에 따라 조사 범위가 달라진다.
E2E 단계가 실패하면 다음 artifact를 다운로드한다.
| Artifact | 내용 | 우선 확인 대상 |
|---|---|---|
playwright-report | HTML report와 테스트별 요약 | 어떤 테스트와 assertion이 실패했는지 확인 |
playwright-test-results | 실패 시에만 업로드되는 trace, screenshot, video, error context | 실제 화면, 네트워크·콘솔·DOM 상태 확인 |
consumer-portal-dist | 해당 commit에서 생성된 production bundle | build 산출물과 로컬 재현 결과 비교 |
실패한 commit SHA가 로컬에서 확인한 commit과 같은지도 먼저 확인한다. 다른 commit을 조사하면 이미 해결된 실패를 재현하게 될 수 있다.
2. 로컬 재현 준비
소비 포털은 GitHub Packages의 private @hohyun94/portal-foundation package를 사용한다. 로컬 설치 전에 package read 권한이 있는 token을 설정한다.
export NODE_AUTH_TOKEN="<GitHub Packages read token>"
pnpm install
pnpm exec playwright install chromiumCI와 동일한 검증 순서는 다음과 같다.
pnpm run check
pnpm run build
pnpm run e2e:smoke실패한 테스트만 빠르게 재현하려면 다음과 같이 실행한다.
pnpm exec playwright test e2e/portal-foundation.smoke.spec.ts -g "renders the shared shell"
pnpm exec playwright test e2e/portal-foundation.smoke.spec.ts -g "theme controls"
pnpm exec playwright test e2e/portal-foundation.smoke.spec.ts -g "direct navigation"3. headed mode와 inspector 사용
CI에서만 발생하는지, 브라우저 화면에서도 재현되는지 구분하려면 headed mode를 사용한다.
pnpm exec playwright test --headedPlaywright Inspector를 사용하면 locator, action, DOM 상태를 단계별로 확인할 수 있다.
PWDEBUG=1 pnpm exec playwright test e2e/portal-foundation.smoke.spec.ts특정 테스트를 일시 정지하면서 확인하려면 테스트에 임시로 await page.pause()를 추가하고 실행한다. 디버깅이 끝난 뒤 page.pause()와 임시 로그는 반드시 제거한다.
4. Trace 분석
실패 artifact의 trace.zip을 다운로드한 뒤 다음 명령으로 연다.
pnpm exec playwright show-trace path/to/trace.zipTrace Viewer에서 다음 순서로 확인한다.
- Actions: 어떤 locator action 직후 실패했는지 확인한다.
- Before/After: click 또는 navigation 전후의 DOM과 screenshot을 비교한다.
- Console: React error, Ant Design warning, hydration warning을 확인한다.
- Network: JS/CSS 404, private package와 무관한 runtime request 실패, navigation 실패를 확인한다.
- Metadata: browser version, viewport, URL, retry 여부를 확인한다.
5. 실패 유형별 진단
5.1 Shell heading이 보이지 않는 경우
대표 오류:
expect(locator).toBeVisible() failed
Locator: getByRole('heading', ...)확인 순서:
- 페이지 URL이
/인지 확인한다. page.content()또는 trace의 DOM snapshot에서 heading이 존재하는지 확인한다.- heading이 존재하지만 hidden이면 부모 layout의 width, height,
display,visibility,opacity를 확인한다. .pf-shell,.pf-shell__body,.pf-shell-main,.pf-shell-main__inner의 computed style을 확인한다.- Ant Design runtime CSS가 Portal Foundation의 grid layout을 덮어쓰는지 확인한다.
임시 진단 코드:
console.log(await page.getByRole("heading", { name: /공통 기반이 준비되었습니다/ }).evaluate(element => {
const style = getComputedStyle(element);
const rect = element.getBoundingClientRect();
return {
display: style.display,
visibility: style.visibility,
opacity: style.opacity,
rect: rect.toJSON(),
parent: element.parentElement?.className,
};
}));width: 0 또는 height: 0이면 assertion을 약화시키기보다 shell layout integration CSS를 먼저 수정한다. consumer CSS에서 !important override를 추가하기 전에는 Ant Design CSS의 import 순서와 적용 범위를 확인한다.
5.2 관리자 이동 실패
대표 오류:
page.toHaveURL(/\/admin$/) failed확인 순서:
메뉴 관리 열기버튼이 실제로 click 되었는지 trace에서 확인한다.window.history.pushState이후 React state가 갱신되는지 확인한다.- 버튼이 다른 element에 가려져 있거나 disabled인지 확인한다.
- 직접
/admin으로 진입했을 때도 관리자 화면이 렌더링되는지 별도 테스트한다. - 새로고침 후 client-side route가 Vite 또는 production server에서 fallback되는지 확인한다.
현재 앱은 pushState 기반의 간단한 navigation을 사용하므로, 실제 production router를 도입할 경우 route fallback과 browser back/forward 처리를 추가로 검증해야 한다.
5.3 Theme 전환 실패
대표 오류:
expected html to have class "dark"확인 순서:
- 사용자 설정 popup이 열렸는지 확인한다.
다크radio control이 실제로 선택 가능한지 확인한다.document.documentElement.dataset.portalMode값이dark인지 확인한다.document.documentElement.classList.contains("dark")결과를 확인한다.PortalThemeProvider가 실제로PortalShell보다 상위에 있는지 확인한다.applicationPolicy.allowDarkMode === false또는 forced theme 정책이 적용된 것은 아닌지 확인한다.
임시 진단 코드:
console.log(await page.evaluate(() => ({
className: document.documentElement.className,
portalMode: document.documentElement.dataset.portalMode,
portalBackground: document.documentElement.dataset.portalBackground,
})));5.4 직접 /admin 진입 실패
대표 오류:
page.goto("/admin") succeeded, but the admin heading was not foundVite dev server는 history fallback을 제공하지만 실제 hosting 환경은 다를 수 있다. 다음을 확인한다.
- web server가
/admin을index.html로 fallback하는지 - static hosting rewrite 설정이 있는지
- client-side
currentPath()가 pathname을 읽는 시점이 올바른지 /admin에서 필요한 localStorage와 menu seed가 초기화되는지
5.5 Browser console 또는 page error 발생
smoke 테스트는 browser console의 error와 pageerror를 수집한다. 실패 메시지에는 다음이 포함될 수 있다.
- React rendering exception
- hydration mismatch
- missing export 또는 undefined component
- chunk loading failure
- CSS 또는 asset 404
- Ant Design runtime exception
오류를 무시하기 위해 consoleErrors assertion을 제거하지 않는다. 오류가 예상 가능한 third-party warning이라면 원인을 먼저 제거하거나, 정말 불가피한 경우에만 정확한 message prefix를 기록하고 이유를 주석으로 남긴다.
6. SSR 및 hydration 관련 조사
소비 포털에 SSR을 추가하거나 SSR 결과를 사용하는 hosting으로 전환할 경우 다음을 별도 확인한다.
const serverMarkup = renderToString(<App />);
container.innerHTML = serverMarkup;
hydrateRoot(container, <App />);확인 항목:
- 서버와 client의 초기 theme 값이 같은지
window,document,localStorage를 render phase에서 직접 참조하지 않는지- Modal portal이 server render에서 열리지 않는지
- client mount 뒤 focus와 open 상태가 안정적으로 전환되는지
- hydration 직후 console에 mismatch warning이 없는지
Portal Foundation의 PortalExploreDialog는 client mount guard와 SSR 테스트를 포함하지만, 소비 포털이 추가하는 wrapper·theme storage·auth provider도 함께 검증해야 한다.
7. Private package와 dependency 문제
다음 오류는 E2E 문제가 아니라 설치 단계 문제일 가능성이 높다.
401 Unauthorized
No authorization header was set확인 순서:
NODE_AUTH_TOKEN이 GitHub Packages read 권한을 가진 token인지 확인한다.- workflow job에
packages: readpermission이 있는지 확인한다. .npmrc의 scope registry가https://npm.pkg.github.com인지 확인한다.- package version
0.6.80이 실제 registry에 게시되어 있는지 확인한다. - lockfile이 오래된 package version을 가리키지 않는지 확인한다.
이 문제를 E2E assertion 수정으로 해결하려고 하지 않는다.
8. CI와 로컬 차이
CI에서만 실패하면 다음 환경 차이를 확인한다.
| 항목 | CI 기준 |
|---|---|
| OS | Ubuntu latest |
| Node | 22 |
| pnpm | 10.4.1 |
| Browser | Playwright Chromium |
| Viewport | Desktop Chrome 기본 viewport |
| Web server | pnpm dev --host 127.0.0.1 --port 4173 |
| Retry | CI에서 최대 2회 |
로컬도 동일한 조건으로 실행한다.
CI=1 pnpm exec playwright test --config=playwright.config.ts화면 크기 의존 문제가 의심되면 Playwright config에 임의의 viewport를 추가하기 전에 소비 포털이 지원해야 하는 실제 viewport를 명확히 정한다.
9. 수정 후 검증 체크리스트
수정 후 다음 명령이 모두 통과해야 한다.
pnpm run check
pnpm run build
pnpm run e2e:smoke추가로 확인한다.
- 실패를 재현하던 단일 test가 통과한다.
- 전체 smoke suite가 통과한다.
- browser console error와 page error가 없다.
- trace·screenshot·video artifact가 더 이상 실패 결과로 생성되지 않는다.
- 임시
page.pause(),console.log, broad timeout 증가가 제거되었다. - 변경이 layout integration 문제라면 desktop과 mobile viewport를 모두 확인했다.
- CI workflow가 사용하는
GITHUB_TOKENpackage 권한이 유지된다.
10. 재발 방지 원칙
E2E test를 통과시키기 위해 locator를 지나치게 약하게 만들거나 무조건 timeout을 늘리지 않는다. 사용자가 실제로 보는 semantic role, accessible name, URL, theme attribute를 기준으로 assertion을 유지한다. layout 문제는 screenshot과 computed style로 원인을 확인한 뒤 consumer integration CSS 또는 Portal Foundation component에서 수정한다. 반복적으로 발견되는 문제는 smoke test 또는 unit/contract test로 승격해 동일한 regression이 다시 발생하지 않도록 한다.