테스트 코드 작성하려는데, Canvas가 문제다.
문제: jsdom에 Canvas 없음
Vitest는 기본적으로 jsdom 환경. 근데 jsdom에는 Canvas API가 없다.
// 이런 테스트가 안 됨
test('Stage 생성', () => {
const stage = new Konva.Stage({
container: 'container',
width: 800,
height: 600
});
// Error: Cannot read property 'getContext' of null
});
해결: canvas 패키지
npm install -D canvas
vitest.config.ts:
export default defineConfig({
test: {
environment: 'jsdom',
setupFiles: ['./tests/setup.ts']
}
});
tests/setup.ts:
import { vi } from 'vitest';
// Canvas 모킹
HTMLCanvasElement.prototype.getContext = vi.fn(() => ({
fillRect: vi.fn(),
clearRect: vi.fn(),
getImageData: vi.fn(() => ({ data: [] })),
putImageData: vi.fn(),
createImageData: vi.fn(() => []),
setTransform: vi.fn(),
drawImage: vi.fn(),
save: vi.fn(),
restore: vi.fn(),
scale: vi.fn(),
rotate: vi.fn(),
translate: vi.fn(),
transform: vi.fn(),
beginPath: vi.fn(),
closePath: vi.fn(),
moveTo: vi.fn(),
lineTo: vi.fn(),
stroke: vi.fn(),
fill: vi.fn(),
arc: vi.fn(),
rect: vi.fn()
})) as any;
전부 모킹. 실제 렌더링은 안 되지만 에러는 안 남.
스토어 테스트
Konva 없이도 테스트 가능한 건 따로:
import { setActivePinia, createPinia } from 'pinia';
import { useFurnitureStore } from '@/stores/furniture';
describe('FurnitureStore', () => {
beforeEach(() => {
setActivePinia(createPinia());
});
test('가구 추가', () => {
const store = useFurnitureStore();
store.addFurniture({
id: 'test-1',
type: 'bed',
name: '침대',
x: 100,
y: 100,
width: 200,
height: 150,
rotation: 0,
color: '#8B4513',
shape: 'rect'
});
expect(store.items).toHaveLength(1);
expect(store.items[0].type).toBe('bed');
});
test('가구 삭제', () => {
const store = useFurnitureStore();
store.addFurniture({ id: 'test-1', ... });
store.deleteFurniture('test-1');
expect(store.items).toHaveLength(0);
});
});
유틸 함수 테스트
좌표 변환, 거리 계산 같은 건 Canvas 없이 테스트 가능:
import { calcDistance, getLShapePath } from '@/utils/geometry';
describe('Geometry Utils', () => {
test('거리 계산', () => {
const distance = calcDistance(
{ x: 0, y: 0 },
{ x: 3, y: 4 }
);
expect(distance).toBe(5);
});
test('L자형 Path 생성', () => {
const path = getLShapePath(100, 100, 0.5, 'bottomRight');
expect(path).toContain('M 0 0');
expect(path).toContain('Z');
});
});
컴포넌트 테스트
vue-test-utils + Canvas 모킹:
import { mount } from '@vue/test-utils';
import FurniturePanel from '@/components/FurniturePanel.vue';
test('가구 팔레트 렌더링', () => {
const wrapper = mount(FurniturePanel);
expect(wrapper.text()).toContain('침대');
expect(wrapper.text()).toContain('책상');
});
test('가구 클릭 시 이벤트 발생', async () => {
const wrapper = mount(FurniturePanel);
await wrapper.find('[data-testid="furniture-bed"]').trigger('click');
expect(wrapper.emitted('add')).toBeTruthy();
expect(wrapper.emitted('add')[0]).toEqual(['bed']);
});
테스트 커버리지
--------------------|---------|----------|---------|---------|
File | % Stmts | % Branch | % Funcs | % Lines |
--------------------|---------|----------|---------|---------|
stores/furniture.ts | 100 | 90 | 100 | 100 |
utils/geometry.ts | 100 | 100 | 100 | 100 |
... | ... | ... | ... | ... |
--------------------|---------|----------|---------|---------|
All files | 85 | 78 | 82 | 85 |
Canvas 렌더링 부분은 제외하고 85% 정도.
다음 글에서 Playwright E2E 테스트.