front-prod/packages/client/jest.setup.ts

160 lines
3.7 KiB
TypeScript
Raw Normal View History

import '@testing-library/jest-dom';
// Mock import.meta.env for Vite compatibility
// eslint-disable-next-line @typescript-eslint/no-explicit-any
(global as any).importMetaEnv = {
MODE: 'test',
DEV: true,
PROD: false,
};
Object.defineProperty(globalThis, 'import', {
value: {
meta: {
env: {
MODE: 'test',
DEV: true,
PROD: false,
},
},
},
});
// Mock @dicebear modules (ESM-only modules)
jest.mock('@dicebear/core', () => ({
createAvatar: jest.fn(() => ({
toDataUri: jest.fn(() => 'data:image/svg+xml;base64,mock'),
})),
}));
jest.mock('@dicebear/collection', () => ({
initials: {},
}));
// Mock window.matchMedia
Object.defineProperty(window, 'matchMedia', {
writable: true,
value: jest.fn().mockImplementation((query: string) => ({
matches: false,
media: query,
onchange: null,
addListener: jest.fn(),
removeListener: jest.fn(),
addEventListener: jest.fn(),
removeEventListener: jest.fn(),
dispatchEvent: jest.fn(),
})),
});
// Mock ResizeObserver
class MockResizeObserver {
callback: ResizeObserverCallback;
constructor(callback: ResizeObserverCallback) {
this.callback = callback;
}
observe = jest.fn();
unobserve = jest.fn();
disconnect = jest.fn();
}
Object.defineProperty(window, 'ResizeObserver', {
writable: true,
value: MockResizeObserver,
});
// Mock IntersectionObserver
class MockIntersectionObserver {
callback: IntersectionObserverCallback;
options?: IntersectionObserverInit;
constructor(callback: IntersectionObserverCallback, options?: IntersectionObserverInit) {
this.callback = callback;
this.options = options;
}
observe = jest.fn();
unobserve = jest.fn();
disconnect = jest.fn();
takeRecords = jest.fn().mockReturnValue([]);
root = null;
rootMargin = '';
thresholds = [0];
}
Object.defineProperty(window, 'IntersectionObserver', {
writable: true,
value: MockIntersectionObserver,
});
// Mock scrollTo
Object.defineProperty(window, 'scrollTo', {
writable: true,
value: jest.fn(),
});
// Mock requestAnimationFrame and cancelAnimationFrame
let rafId = 0;
Object.defineProperty(window, 'requestAnimationFrame', {
writable: true,
value: jest.fn((callback: FrameRequestCallback) => {
rafId += 1;
setTimeout(() => callback(performance.now()), 0);
return rafId;
}),
});
Object.defineProperty(window, 'cancelAnimationFrame', {
writable: true,
value: jest.fn(),
});
// Mock react-i18next
jest.mock('react-i18next', () => ({
useTranslation: () => ({
t: (key: string, options?: Record<string, unknown>) => {
if (options && typeof options === 'object') {
let result = key;
Object.entries(options).forEach(([k, v]) => {
result = result.replace(`{{${k}}}`, String(v));
result = result.replace(`{${k}}`, String(v));
});
return result;
}
return key;
},
i18n: {
changeLanguage: jest.fn(),
language: 'en',
},
}),
Trans: ({ children }: { children: React.ReactNode }) => children,
initReactI18next: {
type: '3rdParty',
init: jest.fn(),
},
}));
// Mock useLocalize hook
jest.mock('~/hooks', () => ({
...jest.requireActual('~/hooks'),
useLocalize: () => (key: string, options?: Record<string, unknown>) => {
if (options && typeof options === 'object') {
let result = key;
Object.entries(options).forEach(([k, v]) => {
result = result.replace(`{{${k}}}`, String(v));
result = result.replace(`{${k}}`, String(v));
});
return result;
}
return key;
},
useMediaQuery: jest.fn(() => false),
}));
// Clear mocks before each test
beforeEach(() => {
jest.clearAllMocks();
});