81 lines
2.5 KiB
TypeScript
81 lines
2.5 KiB
TypeScript
|
|
import '@testing-library/jest-dom/vitest';
|
||
|
|
import { afterEach, vi } from 'vitest';
|
||
|
|
import { cleanup } from '@testing-library/react';
|
||
|
|
|
||
|
|
// jsdom is missing a handful of browser APIs that antd / pro-components touch on
|
||
|
|
// mount. Provide minimal stand-ins so component pages can render in tests.
|
||
|
|
|
||
|
|
if (!window.matchMedia) {
|
||
|
|
window.matchMedia = 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(),
|
||
|
|
}));
|
||
|
|
}
|
||
|
|
|
||
|
|
class ResizeObserverStub {
|
||
|
|
observe() {}
|
||
|
|
unobserve() {}
|
||
|
|
disconnect() {}
|
||
|
|
}
|
||
|
|
// @ts-expect-error -- assigning test stub
|
||
|
|
window.ResizeObserver = window.ResizeObserver || ResizeObserverStub;
|
||
|
|
|
||
|
|
class IntersectionObserverStub {
|
||
|
|
root = null;
|
||
|
|
rootMargin = '';
|
||
|
|
thresholds = [];
|
||
|
|
observe() {}
|
||
|
|
unobserve() {}
|
||
|
|
disconnect() {}
|
||
|
|
takeRecords() {
|
||
|
|
return [];
|
||
|
|
}
|
||
|
|
}
|
||
|
|
// @ts-expect-error -- assigning test stub
|
||
|
|
window.IntersectionObserver = window.IntersectionObserver || IntersectionObserverStub;
|
||
|
|
|
||
|
|
if (!window.scrollTo) {
|
||
|
|
// @ts-expect-error -- jsdom does not implement scrollTo
|
||
|
|
window.scrollTo = vi.fn();
|
||
|
|
}
|
||
|
|
|
||
|
|
// Some pages read auth tokens from localStorage during render; ensure a working
|
||
|
|
// Storage implementation is present regardless of the jsdom build.
|
||
|
|
if (typeof window.localStorage?.getItem !== 'function') {
|
||
|
|
const store = new Map<string, string>();
|
||
|
|
const storage: Storage = {
|
||
|
|
get length() {
|
||
|
|
return store.size;
|
||
|
|
},
|
||
|
|
clear: () => store.clear(),
|
||
|
|
getItem: (k: string) => (store.has(k) ? store.get(k)! : null),
|
||
|
|
key: (i: number) => Array.from(store.keys())[i] ?? null,
|
||
|
|
removeItem: (k: string) => void store.delete(k),
|
||
|
|
setItem: (k: string, v: string) => void store.set(k, String(v)),
|
||
|
|
};
|
||
|
|
Object.defineProperty(window, 'localStorage', { value: storage, configurable: true });
|
||
|
|
}
|
||
|
|
|
||
|
|
// jsdom's getContext is unimplemented; the CRM graph page guards against a null
|
||
|
|
// context, so returning null keeps it on its safe path.
|
||
|
|
if (!HTMLCanvasElement.prototype.getContext) {
|
||
|
|
HTMLCanvasElement.prototype.getContext = () => null;
|
||
|
|
}
|
||
|
|
|
||
|
|
// jsdom throws "Not implemented" when getComputedStyle is called with a
|
||
|
|
// pseudo-element (rc-table does this while measuring scrollbars). Drop the
|
||
|
|
// unsupported second argument so the call succeeds quietly.
|
||
|
|
const originalGetComputedStyle = window.getComputedStyle.bind(window);
|
||
|
|
window.getComputedStyle = ((elt: Element) =>
|
||
|
|
originalGetComputedStyle(elt)) as typeof window.getComputedStyle;
|
||
|
|
|
||
|
|
afterEach(() => {
|
||
|
|
cleanup();
|
||
|
|
});
|