단위 테스트로는 한계가 있다. 실제 브라우저에서 동작하는지 E2E 테스트.
Playwright 설정
npm install -D @playwright/test
npx playwright install
playwright.config.ts:
export default defineConfig({
testDir: './e2e',
webServer: {
command: 'npm run dev',
url: 'http://localhost:3000',
reuseExistingServer: true
}
});
문제: Canvas 요소 선택
일반 DOM이면 page.click('button')으로 클릭. 근데 Canvas 안의 요소는?
Canvas는 하나의 <canvas> 태그. 안에 뭐가 있는지 Playwright가 모름.
해결 1: 좌표 클릭
Canvas 특정 위치 클릭:
test('가구 선택', async ({ page }) => {
await page.goto('/');
// 가구 추가
await page.click('[data-testid="add-bed"]');
// 캔버스에서 가구 위치 클릭
const canvas = page.locator('canvas');
await canvas.click({ position: { x: 200, y: 200 } });
// 선택 확인
await expect(page.locator('[data-testid="edit-form"]')).toBeVisible();
});
좌표 하드코딩은 별로지만 Canvas에선 어쩔 수 없음.
해결 2: data-testid 활용
Canvas 위에 투명 div 올려서 테스트용 마커:
<div class="relative">
<canvas ... />
<!-- 테스트용 오버레이 -->
<div
v-for="furniture in store.items"
:key="furniture.id"
:data-testid="`furniture-${furniture.id}`"
class="absolute pointer-events-none"
:style="{
left: `${furniture.x}px`,
top: `${furniture.y}px`,
width: `${furniture.width}px`,
height: `${furniture.height}px`
}"
/>
</div>
test('가구 선택', async ({ page }) => {
await page.click('[data-testid="furniture-test-1"]');
});
프로덕션에서는 이 div 숨기면 됨.
드래그 테스트
가구 드래그 이동:
test('가구 드래그 이동', async ({ page }) => {
await page.goto('/');
await page.click('[data-testid="add-bed"]');
const canvas = page.locator('canvas');
// 드래그
await canvas.dragTo(canvas, {
sourcePosition: { x: 200, y: 200 },
targetPosition: { x: 400, y: 300 }
});
// 위치 변경 확인
// ...
});
키보드 테스트
test('R 키로 회전', async ({ page }) => {
await page.goto('/');
await page.click('[data-testid="add-bed"]');
// 가구 선택
const canvas = page.locator('canvas');
await canvas.click({ position: { x: 200, y: 200 } });
// R 키
await page.keyboard.press('r');
// 회전 확인 (어떻게?)
});
회전 확인은… 스토어 값 체크하거나 스크린샷 비교.
스크린샷 비교
test('초기 화면', async ({ page }) => {
await page.goto('/');
await expect(page).toHaveScreenshot('initial.png');
});
첫 실행 시 스크린샷 저장. 이후 실행에서 비교.
픽셀 차이 있으면 실패.
테스트 결과
Running 39 tests using 4 workers
✓ 초기 화면 렌더링 (1.2s)
✓ 가구 추가 (0.8s)
✓ 가구 선택 (0.6s)
✓ 가구 드래그 (1.1s)
✓ 가구 삭제 (0.5s)
...
39 passed (45s)
다음 글에서 성능 최적화.