require('@testing-library/jest-dom'); const { TextEncoder, TextDecoder } = require('util'); global.TextEncoder = TextEncoder; global.TextDecoder = TextDecoder; if (typeof global.Request === 'undefined') { global.Request = class Request { constructor(input, init = {}) { this.url = typeof input === 'string' ? input : input.url; this.method = init.method || 'GET'; this.headers = new Map(Object.entries(init.headers || {})); this.body = init.body; } async json() { return typeof this.body === 'string' ? JSON.parse(this.body) : this.body; } }; } if (typeof global.Response === 'undefined') { global.Response = class Response { constructor(body, init = {}) { this.body = body; this.status = init.status || 200; this.statusText = init.statusText || 'OK'; this.headers = new Map(Object.entries(init.headers || {})); } async json() { return typeof this.body === 'string' ? JSON.parse(this.body) : this.body; } async text() { return typeof this.body === 'string' ? this.body : JSON.stringify(this.body); } }; } if (typeof global.Headers === 'undefined') { global.Headers = class Headers { constructor(init = {}) { this._headers = new Map(Object.entries(init)); } get(name) { return this._headers.get(name); } set(name, value) { this._headers.set(name, value); } }; } const { setupAllMocks } = require('./src/__mocks__/shared-mocks'); setupAllMocks(); global.console = { ...console, error: jest.fn(), warn: jest.fn(), log: jest.fn(), }; class MockIntersectionObserver { constructor(callback, options = {}) { this.callback = callback; this.options = options; this.elements = new Set(); this.observationEntries = []; } observe(element) { this.elements.add(element); const entry = { isIntersecting: true, target: element, boundingClientRect: element.getBoundingClientRect ? element.getBoundingClientRect() : {}, intersectionRatio: 1, intersectionRect: {}, rootBounds: {}, time: Date.now(), }; this.observationEntries.push(entry); this.callback(this.observationEntries, this); } unobserve(element) { this.elements.delete(element); } disconnect() { this.elements.clear(); this.observationEntries = []; } } global.IntersectionObserver = MockIntersectionObserver; class MockResizeObserver { constructor(callback) { this.callback = callback; this.elements = new Set(); } observe(element) { this.elements.add(element); this.callback([{ target: element, contentRect: { width: 100, height: 100 } }], this); } unobserve(element) { this.elements.delete(element); } disconnect() { this.elements.clear(); } } global.ResizeObserver = MockResizeObserver; Object.defineProperty(window, 'matchMedia', { writable: true, value: jest.fn().mockImplementation(query => ({ matches: false, media: query, onchange: null, addListener: jest.fn(), removeListener: jest.fn(), addEventListener: jest.fn(), removeEventListener: jest.fn(), dispatchEvent: jest.fn(), })), }); Object.defineProperty(window, 'scrollTo', { writable: true, value: jest.fn(), }); Object.defineProperty(window, 'localStorage', { value: { store: {}, getItem(key) { return this.store[key] || null; }, setItem(key, value) { this.store[key] = value; }, removeItem(key) { delete this.store[key]; }, clear() { this.store = {}; }, }, }); jest.mock('@/db', () => ({ db: { select: jest.fn().mockReturnValue({ from: jest.fn().mockReturnThis(), where: jest.fn().mockReturnThis(), orderBy: jest.fn().mockReturnThis(), limit: jest.fn().mockReturnThis(), execute: jest.fn().mockResolvedValue([]), }), insert: jest.fn().mockReturnValue({ values: jest.fn().mockReturnThis(), returning: jest.fn().mockResolvedValue([{ id: 1 }]), }), update: jest.fn().mockReturnValue({ set: jest.fn().mockReturnThis(), where: jest.fn().mockReturnThis(), returning: jest.fn().mockResolvedValue([{ id: 1 }]), }), delete: jest.fn().mockReturnValue({ where: jest.fn().mockReturnThis(), returning: jest.fn().mockResolvedValue([{ id: 1 }]), }), }, }));