setup.ts 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. /**
  2. * Test setup file for Vitest.
  3. * Configures testing environment, mocks, and MSW server.
  4. */
  5. import '@testing-library/jest-dom';
  6. import { afterAll, afterEach, beforeAll, vi } from 'vitest';
  7. import { cleanup } from '@testing-library/react';
  8. import { server } from './mocks/server';
  9. // Initialize i18n for tests (suppresses react-i18next warnings)
  10. import '../i18n';
  11. // Setup MSW server
  12. beforeAll(() =>
  13. server.listen({
  14. // Bypass unhandled requests silently (don't warn, just let them through)
  15. // Handlers use wildcard (*) prefix to match any origin
  16. onUnhandledRequest: 'bypass',
  17. })
  18. );
  19. afterEach(() => {
  20. cleanup();
  21. server.resetHandlers();
  22. });
  23. afterAll(() => server.close());
  24. // Mock window.matchMedia for responsive components
  25. Object.defineProperty(window, 'matchMedia', {
  26. writable: true,
  27. value: vi.fn().mockImplementation((query: string) => ({
  28. matches: false,
  29. media: query,
  30. onchange: null,
  31. addListener: vi.fn(),
  32. removeListener: vi.fn(),
  33. addEventListener: vi.fn(),
  34. removeEventListener: vi.fn(),
  35. dispatchEvent: vi.fn(),
  36. })),
  37. });
  38. // Mock ResizeObserver
  39. class ResizeObserverMock {
  40. observe = vi.fn();
  41. unobserve = vi.fn();
  42. disconnect = vi.fn();
  43. }
  44. vi.stubGlobal('ResizeObserver', ResizeObserverMock);
  45. // Mock IntersectionObserver
  46. class IntersectionObserverMock {
  47. observe = vi.fn();
  48. unobserve = vi.fn();
  49. disconnect = vi.fn();
  50. root = null;
  51. rootMargin = '';
  52. thresholds = [];
  53. }
  54. vi.stubGlobal('IntersectionObserver', IntersectionObserverMock);
  55. // Mock WebSocket
  56. class MockWebSocket {
  57. static readonly CONNECTING = 0;
  58. static readonly OPEN = 1;
  59. static readonly CLOSING = 2;
  60. static readonly CLOSED = 3;
  61. readyState = MockWebSocket.OPEN;
  62. onopen: ((event: Event) => void) | null = null;
  63. onclose: ((event: CloseEvent) => void) | null = null;
  64. onmessage: ((event: MessageEvent) => void) | null = null;
  65. onerror: ((event: Event) => void) | null = null;
  66. url: string;
  67. constructor(url: string) {
  68. this.url = url;
  69. setTimeout(() => this.onopen?.(new Event('open')), 0);
  70. }
  71. send = vi.fn();
  72. close = vi.fn();
  73. }
  74. vi.stubGlobal('WebSocket', MockWebSocket);
  75. // Mock scrollTo
  76. window.scrollTo = vi.fn();
  77. // Mock localStorage
  78. const localStorageMock = {
  79. getItem: vi.fn(),
  80. setItem: vi.fn(),
  81. removeItem: vi.fn(),
  82. clear: vi.fn(),
  83. };
  84. Object.defineProperty(window, 'localStorage', { value: localStorageMock });
  85. // Suppress console output during tests (reduces noise)
  86. // Remove these lines if you need to debug test output
  87. vi.spyOn(console, 'log').mockImplementation(() => {});
  88. vi.spyOn(console, 'warn').mockImplementation(() => {});
  89. vi.spyOn(console, 'error').mockImplementation(() => {});