// Angular + Zone - Using AnalogJS setup for proper Zone.js integration import "@angular/compiler"; import "@analogjs/vitest-angular/setup-zone"; import { getTestBed } from "@angular/core/testing"; // eslint-disable-next-line @typescript-eslint/no-unused-vars import { Injector } from "@angular/core"; import { BrowserDynamicTestingModule, platformBrowserDynamicTesting, } from "@angular/platform-browser-dynamic/testing"; // JSDOM polyfills commonly needed by Angular/CDK/components // ResizeObserver if (!(globalThis as any).ResizeObserver) { class RO { callback: ResizeObserverCallback; constructor(cb: ResizeObserverCallback) { this.callback = cb; } observe() { /* noop */ } unobserve() { /* noop */ } disconnect() { /* noop */ } } (globalThis as any).ResizeObserver = RO as any; } // IntersectionObserver if (!(globalThis as any).IntersectionObserver) { class IO { constructor(_: IntersectionObserverCallback) {} observe() {} unobserve() {} disconnect() {} takeRecords() { return []; } root = null; rootMargin = ""; thresholds: number[] = []; } (globalThis as any).IntersectionObserver = IO as any; } // matchMedia if (!window.matchMedia) { (window as any).matchMedia = () => ({ matches: false, media: "", onchange: null, addListener: () => {}, removeListener: () => {}, addEventListener: () => {}, removeEventListener: () => {}, dispatchEvent: () => false, }); } // requestAnimationFrame if (!globalThis.requestAnimationFrame) { (globalThis as any).requestAnimationFrame = (cb: FrameRequestCallback) => setTimeout(() => cb(Date.now()), 16) as unknown as number; (globalThis as any).cancelAnimationFrame = (id: number) => clearTimeout(id); } // Canvas context - provide a mock implementation for testing Object.defineProperty(HTMLCanvasElement.prototype, "getContext", { // eslint-disable-next-line @typescript-eslint/no-unused-vars value: function (contextType: string) { // Return mock context for testing return { fillRect: () => {}, clearRect: () => {}, getImageData: () => ({ data: [] }), putImageData: () => {}, createImageData: () => [], setTransform: () => {}, drawImage: () => {}, save: () => {}, fillText: () => {}, restore: () => {}, beginPath: () => {}, moveTo: () => {}, lineTo: () => {}, closePath: () => {}, stroke: () => {}, translate: () => {}, scale: () => {}, rotate: () => {}, arc: () => {}, fill: () => {}, measureText: () => ({ width: 0 }), transform: () => {}, rect: () => {}, clip: () => {}, lineWidth: 1, strokeStyle: "#000", fillStyle: "#000", canvas: this, }; }, writable: true, configurable: true, }); // DOMRect if (!(globalThis as any).DOMRect) { (globalThis as any).DOMRect = class { constructor( public x = 0, public y = 0, public width = 0, public height = 0, ) {} } as any; } // Initialize Angular testing environment once per worker console.info("[vitest] test-setup.ts running in pid", process.pid); const testBed = getTestBed(); // Store platform instance globally to reuse across test files const globalAny = globalThis as any; if (!globalAny.__ANGULAR_TEST_PLATFORM__) { console.info("[vitest] Creating Angular test platform"); globalAny.__ANGULAR_TEST_PLATFORM__ = platformBrowserDynamicTesting(); } // Check if TestBed has already been initialized by checking the platform if (!testBed.platform) { console.info("[vitest] Initializing TestBed"); testBed.initTestEnvironment( BrowserDynamicTestingModule, globalAny.__ANGULAR_TEST_PLATFORM__, { teardown: { destroyAfterEach: false } }, // Don't tear down after each test ); console.info("[vitest] TestBed initialized"); } else { console.info("[vitest] TestBed already initialized, skipping"); }