import '@testing-library/jest-dom/vitest'; /** * SVG polyfills for jsdom so JointJS (@joint/core) can run in tests. * Vectorizer feature-detects `window.SVGAngle` at module load and jsdom * implements neither it nor the SVG geometry APIs (matrices, points, bbox). * These must be installed before @joint/core is imported. */ class Matrix { a = 1; b = 0; c = 0; d = 1; e = 0; f = 0; multiply(m: Matrix): Matrix { const r = new Matrix(); r.a = this.a * m.a + this.c * m.b; r.b = this.b * m.a + this.d * m.b; r.c = this.a * m.c + this.c * m.d; r.d = this.b * m.c + this.d * m.d; r.e = this.a * m.e + this.c * m.f + this.e; r.f = this.b * m.e + this.d * m.f + this.f; return r; } translate(tx: number, ty: number): Matrix { const m = new Matrix(); m.e = tx; m.f = ty; return this.multiply(m); } scale(s: number): Matrix { return this.scaleNonUniform(s, s); } scaleNonUniform(sx: number, sy: number): Matrix { const m = new Matrix(); m.a = sx; m.d = sy; return this.multiply(m); } rotate(deg: number): Matrix { const rad = (deg * Math.PI) / 180; const m = new Matrix(); m.a = Math.cos(rad); m.b = Math.sin(rad); m.c = -Math.sin(rad); m.d = Math.cos(rad); return this.multiply(m); } rotateFromVector(): Matrix { return new Matrix(); } flipX(): Matrix { return this.scaleNonUniform(-1, 1); } flipY(): Matrix { return this.scaleNonUniform(1, -1); } skewX(): Matrix { return new Matrix(); } skewY(): Matrix { return new Matrix(); } inverse(): Matrix { const det = this.a * this.d - this.b * this.c; if (det === 0) throw new Error('non-invertible matrix'); const r = new Matrix(); r.a = this.d / det; r.b = -this.b / det; r.c = -this.c / det; r.d = this.a / det; r.e = (this.c * this.f - this.d * this.e) / det; r.f = (this.b * this.e - this.a * this.f) / det; return r; } } class Point { x = 0; y = 0; matrixTransform(m: Matrix): Point { const p = new Point(); p.x = m.a * this.x + m.c * this.y + m.e; p.y = m.b * this.x + m.d * this.y + m.f; return p; } } const g = globalThis as Record; if (!('SVGAngle' in g)) { g.SVGAngle = class SVGAngle {}; } const svgElementProto = (window.SVGSVGElement ?? window.SVGElement)?.prototype as unknown as Record; if (svgElementProto) { svgElementProto.createSVGMatrix = () => new Matrix(); svgElementProto.createSVGPoint = () => new Point(); svgElementProto.createSVGTransform = () => ({ matrix: new Matrix(), setMatrix(m: Matrix) { this.matrix = m; }, setTranslate() {}, }); } const graphicsProto = window.SVGElement?.prototype as unknown as Record; if (graphicsProto) { graphicsProto.getBBox = function getBBox() { return { x: 0, y: 0, width: 0, height: 0 }; }; graphicsProto.getScreenCTM = function getScreenCTM() { return new Matrix(); }; graphicsProto.getCTM = function getCTM() { return new Matrix(); }; } if (!window.Element.prototype.checkVisibility) { window.Element.prototype.checkVisibility = function checkVisibility() { return this.isConnected; }; } const pathProto = (window.SVGPathElement?.prototype ?? graphicsProto) as unknown as Record; if (pathProto) { pathProto.getTotalLength = function getTotalLength() { return 0; }; pathProto.getPointAtLength = function getPointAtLength() { const p = new Point(); return p; }; }