Files
Gnuboard7/resources/js/tests/setup.ts
T
2026-04-21 12:50:07 +09:00

162 lines
4.9 KiB
TypeScript

/**
* Vitest 테스트 환경 설정
*/
import '@testing-library/jest-dom';
import { vi } from 'vitest';
// 전역 mocks
global.fetch = vi.fn();
/**
* IntersectionObserver 폴리필 — jsdom은 IntersectionObserver를 기본 제공하지 않으므로
* 컴포넌트가 무한스크롤/가시성 추적을 위해 사용하는 경우를 대비해 no-op 폴리필을 전역 제공.
* 개별 테스트에서 세부 동작 제어가 필요하면 `vi.stubGlobal('IntersectionObserver', ...)` 으로 덮어쓴다.
*/
class NoopIntersectionObserver {
root: Element | null = null;
rootMargin = '';
thresholds: number[] = [];
observe(): void {}
unobserve(): void {}
disconnect(): void {}
takeRecords(): IntersectionObserverEntry[] { return []; }
}
(global as any).IntersectionObserver = NoopIntersectionObserver;
(window as any).IntersectionObserver = NoopIntersectionObserver;
/**
* window.matchMedia 모킹
* 테스트 환경에서 CSS 미디어 쿼리를 지원하기 위함
*/
Object.defineProperty(window, 'matchMedia', {
writable: true,
value: vi.fn().mockImplementation((query: string) => ({
matches: false,
media: query,
onchange: null,
addListener: vi.fn(),
removeListener: vi.fn(),
addEventListener: vi.fn(),
removeEventListener: vi.fn(),
dispatchEvent: vi.fn(),
})),
});
/**
* 테스트용 번역 맵
* 컴포넌트에서 사용하는 번역 키에 대한 한글 번역
*/
const testTranslations: Record<string, string> = {
// 공통
'common.close': '닫기',
'common.close_modal': '모달 닫기',
'common.close_dialog': '대화상자 닫기',
'common.close_notification': '알림 닫기',
'common.confirm': '확인',
'common.cancel': '취소',
'common.save': '저장',
'common.delete': '삭제',
'common.edit': '편집',
'common.edit_layout': '레이아웃 편집',
'common.search': '검색',
'common.search_placeholder': '검색...',
'common.loading': '로딩 중...',
'common.first_page': '첫 페이지',
'common.last_page': '마지막 페이지',
'common.previous_page': '이전 페이지',
'common.prev_page': '이전 페이지',
'common.next_page': '다음 페이지',
'common.page': '페이지',
'common.page_n': '페이지 {{n}}',
'common.pagination': '페이지네이션',
'common.activate': '활성화',
'common.deactivate': '비활성화',
'common.enabled': '활성화됨',
'common.disabled': '비활성화됨',
'common.update_available': '업데이트 가능',
'common.preview': '미리보기',
'common.dependencies': '의존성',
'common.no_data': '데이터가 없습니다',
'common.notifications': '알림',
'common.no_notifications': '알림이 없습니다',
'common.profile_settings': '프로필 설정',
'common.logout': '로그아웃',
'common.reset': '초기화',
'common.filter': '필터',
// 상태
'common.status_active': '활성화',
'common.status_inactive': '비활성화',
'common.status_pending': '대기중',
'common.status_error': '오류',
// 토스트
'toast.close': '알림 닫기',
// 템플릿
'template.activate': '활성화',
'template.deactivate': '비활성화',
'template.update_available': '업데이트 가능',
'template.edit_layout': '레이아웃 편집',
'template.preview': '미리보기',
'common.template_preview': '{{vendor}}/{{name}} 미리보기',
// 사이드바
'sidebar.collapse': '사이드바 접기',
'sidebar.expand': '사이드바 펼치기',
'common.collapse_sidebar': '사이드바 접기',
'common.expand_sidebar': '사이드바 펼치기',
};
/**
* G7Core 전역 모킹
* 컴포넌트에서 window.G7Core를 사용하므로 테스트 환경에서 모킹 필요
*/
(window as any).G7Core = {
createChangeEvent: vi.fn((data: { checked?: boolean; name?: string; value?: any }) => ({
target: {
checked: data.checked ?? false,
name: data.name ?? '',
value: data.value ?? (data.checked ? 'on' : 'off'),
type: 'checkbox',
},
currentTarget: {
checked: data.checked ?? false,
name: data.name ?? '',
value: data.value ?? (data.checked ? 'on' : 'off'),
type: 'checkbox',
},
preventDefault: vi.fn(),
stopPropagation: vi.fn(),
})),
state: {
get: vi.fn(),
set: vi.fn(),
update: vi.fn(),
subscribe: vi.fn(() => vi.fn()),
},
toast: {
success: vi.fn(),
error: vi.fn(),
warning: vi.fn(),
info: vi.fn(),
},
modal: {
open: vi.fn(),
close: vi.fn(),
},
events: {
emit: vi.fn(),
on: vi.fn(() => vi.fn()),
off: vi.fn(),
},
t: (key: string, params?: Record<string, string | number>) => {
// 번역 맵에서 찾거나, 키 자체를 반환
let translation = testTranslations[key] ?? key;
// params가 있으면 치환
if (params) {
Object.entries(params).forEach(([paramKey, paramValue]) => {
translation = translation.replace(`{{${paramKey}}}`, String(paramValue));
});
}
return translation;
},
};