레이아웃 편집기 spec 중 저장(PUT)까지 수행하는 것들이 제품 화면에 편집 결과를 영속시켜, 실행할 때마다 개발 사이트에 노드가 누적됐다(home 에 빈 표 7개, 관리자 대시보드에 빈 차트 5개). spec 안에 "추가한 노드 삭제 후 재저장" 원복을 넣어도 소용이 없었다 — 원복 후에도 레이아웃이 오염 시점과 정확히 같은 크기로 되돌아왔다. 원복에 기대는 대신 저장 대상 자체를 E2E 전용 시드 화면으로 분리한다. 시드 화면은 활성 템플릿 디렉토리에만 설치되므로 배포 원본과 릴리스 산출물은 변하지 않는다. globalSetup 이 매 실행 fixture 원본으로 덮어써 회차 간 누적이 성립하지 않으므로 저장 spec 에 원복 절차가 필요 없다. 설치는 레이아웃 파일과 라우트, DB 행 세 가지를 함께 다루되 시드 행만 건드린다 — 전체 재동기화를 쓰면 편집기로 저장한(파일에 없는) 변경이 실행할 때마다 사라지기 때문이다. 전수 실행에서 드러난 기존 실패도 함께 처리했다. 35건 중 27건은 절전·부하 아티팩트였고 나머지는 원인을 확정해 고쳤다. 템플릿 식별자 자리에 모듈 id 를 넣어 라우트 트리가 비어 있었고, "캔버스 텍스트가 길어진다"는 대리 지표가 렌더 여부와 무관했으며(정상 렌더에도 짧아진다), 팔레트 삽입 위치가 잠금 서브트리 안이면 선택이 조상으로 밀려 노드를 지목할 수 없었고, 상태 개수 단언이 상태 추가로 낡았고, if 게이트상 그 탭에 등록되지 않는 소스를 refetch 하고 있었고, 무통신 구간이 오지 않는 관리자 화면에 networkidle 을 기다렸고, 테스트 종료 후 도착한 route 콜백이 워커를 중단시켰고, 같은 설정 화면에 저장하는 테스트들이 병렬로 충돌했다. 측정 방법에서 반복해 틀린 지점들은 E2E 가이드에 표로 남겼다 — 가림은 가시성 판정으로 잡히지 않고, 길이 증감은 렌더 신호가 아니며, 총 개수 단언은 스펙이 늘면 깨지고, networkidle 은 실시간 연결이 있는 화면에서 오지 않는다.
94 lines
4.1 KiB
TypeScript
94 lines
4.1 KiB
TypeScript
/**
|
|
* Playwright 코어 E2E 설정 (G7 코어 영역)
|
|
*
|
|
* 위치 규약 (코어/확장 분리 원칙):
|
|
* - 코어 spec : tests/Playwright/specs/
|
|
* - 모듈 spec : modules/_bundled/{id}/tests/Playwright/specs/ (모듈 자체 config)
|
|
* - 플러그인 : plugins/_bundled/{id}/tests/Playwright/specs/ (플러그인 자체 config)
|
|
* - 템플릿 : templates/_bundled/{id}/tests/Playwright/specs/ (템플릿 자체 config)
|
|
*
|
|
* Base URL 해석 우선순위 (하드코딩 회피 — 도메인/디렉토리 변경 무관):
|
|
* 1. PLAYWRIGHT_BASE_URL 환경변수 (CI/명시적 오버라이드)
|
|
* 2. .env 의 APP_URL (단 'localhost' 류는 fallback 으로 부적합 — Apache vhost 미경유)
|
|
* 3. 그 외 — 명시 에러
|
|
*
|
|
* `.env` 파일을 자체 파싱하지 않고 Node.js 환경변수만 사용한다.
|
|
* PowerShell 호출 예: `$env:PLAYWRIGHT_BASE_URL='https://g7.dev'; npm run test:e2e`
|
|
*/
|
|
import { defineConfig, devices } from '@playwright/test';
|
|
import { readFileSync, existsSync } from 'node:fs';
|
|
import { dirname, resolve } from 'node:path';
|
|
import { fileURLToPath } from 'node:url';
|
|
|
|
// ESM 환경(package.json "type": "module")에서는 __dirname 이 정의되지 않으므로
|
|
// import.meta.url 로 재구성한다.
|
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
|
|
/**
|
|
* .env 파일에서 단일 키의 값을 추출한다 (간이 파서 — dotenv 의존 회피).
|
|
* 파일 부재 / 키 부재 시 null 반환.
|
|
*/
|
|
function readEnvFile(filePath: string, key: string): string | null {
|
|
if (!existsSync(filePath)) return null;
|
|
const content = readFileSync(filePath, { encoding: 'utf-8' });
|
|
const pattern = new RegExp(`^${key}=(.*)$`, 'm');
|
|
const match = content.match(pattern);
|
|
if (!match) return null;
|
|
let value = match[1].trim();
|
|
// dotenv 호환 — 양 끝 따옴표 제거
|
|
if ((value.startsWith('"') && value.endsWith('"')) || (value.startsWith("'") && value.endsWith("'"))) {
|
|
value = value.slice(1, -1);
|
|
}
|
|
return value || null;
|
|
}
|
|
|
|
/**
|
|
* E2E base URL 을 결정한다. 우선순위는 모듈 상단 주석 참조.
|
|
*/
|
|
function resolveBaseUrl(): string {
|
|
if (process.env.PLAYWRIGHT_BASE_URL) {
|
|
return process.env.PLAYWRIGHT_BASE_URL;
|
|
}
|
|
const envPath = resolve(__dirname, '.env');
|
|
const appUrl = readEnvFile(envPath, 'APP_URL');
|
|
if (appUrl && !/^https?:\/\/localhost(:\d+)?\/?$/i.test(appUrl)) {
|
|
return appUrl;
|
|
}
|
|
throw new Error(
|
|
'Playwright base URL 미설정. PLAYWRIGHT_BASE_URL 환경변수를 지정하거나 .env 의 APP_URL 을 활성 호스트로 설정하세요. ' +
|
|
`(.env 의 APP_URL=${appUrl ?? '<없음>'})`
|
|
);
|
|
}
|
|
|
|
export default defineConfig({
|
|
testDir: './tests/Playwright/specs',
|
|
// 레이아웃 편집기 저장(PUT) spec 전용 시드 화면 설치/제거.
|
|
// 저장 spec 이 제품 화면(home/admin_dashboard)을 대상으로 하면 실행마다 편집 결과가
|
|
// 누적돼 개발 사이트가 오염된다 — 상세는 tests/Playwright/fixtures/seed-layout.ts.
|
|
globalSetup: './tests/Playwright/global-setup.ts',
|
|
globalTeardown: './tests/Playwright/global-teardown.ts',
|
|
fullyParallel: true,
|
|
forbidOnly: !!process.env.CI,
|
|
retries: process.env.CI ? 2 : 0,
|
|
workers: process.env.CI ? 1 : undefined,
|
|
reporter: [
|
|
['html', { outputFolder: 'playwright-report', open: 'never' }],
|
|
['list'],
|
|
],
|
|
use: {
|
|
baseURL: resolveBaseUrl(),
|
|
// spec 이 한국어 화면 문구를 단언하므로 로케일을 고정한다.
|
|
// 로케일 우선순위는 localStorage g7_locale → 서버 응답값 → 'ko' 이고, 서버값은 미인증
|
|
// 요청에서 Accept-Language 로 결정된다(SetLocale 미들웨어). Playwright 의 locale 옵션이
|
|
// 그 헤더를 만들므로, 지정하지 않으면 첫 페이지 로드가 en-US 로 나가 화면이 영어로 렌더되고
|
|
// 엔진이 그 값을 localStorage 에 저장해 이후 인증해도 세션 전체가 영어로 고정된다.
|
|
locale: 'ko-KR',
|
|
trace: 'retain-on-failure',
|
|
screenshot: 'only-on-failure',
|
|
ignoreHTTPSErrors: true,
|
|
},
|
|
projects: [
|
|
{ name: 'chromium', use: { ...devices['Desktop Chrome'] } },
|
|
],
|
|
});
|