import { FabricObject } from '../shapes/Object/FabricObject'; import { Gradient } from './Gradient'; import type { GradientUnits, RadialGradientCoords, SVGOptions, } from './typedefs'; import { classRegistry } from '../ClassRegistry'; import { describe, expect, it, test } from 'vitest'; import { StaticCanvas } from '../canvas/StaticCanvas'; import { createSVGElement } from '../../test/utils'; function createLinearGradient(units: GradientUnits = 'pixels', id?: string) { return new Gradient({ type: 'linear', id, gradientUnits: units, coords: { x1: 0, y1: 10, x2: 100, y2: 200, }, colorStops: [ { offset: 0, color: 'rgba(255,0,0,0)' }, { offset: 1, color: 'green' }, ], }); } function createRadialGradient(units: GradientUnits = 'pixels') { return new Gradient({ type: 'radial', gradientUnits: units, coords: { x1: 0, y1: 10, x2: 100, y2: 200, r1: 0, r2: 50, }, colorStops: [ { offset: 0, color: 'red' }, { offset: 1, color: 'rgba(0,255,0,0)' }, ], }); } function createRadialGradientWithInternalRadius() { return new Gradient({ type: 'radial', coords: { x1: 0, y1: 10, x2: 100, y2: 200, r1: 10, r2: 50, }, colorStops: [ { offset: 0, color: 'red' }, { offset: 1, color: 'rgba(0,255,0,0)' }, ], }); } function createRadialGradientSwapped() { return new Gradient({ type: 'radial', coords: { x1: 0, y1: 10, x2: 100, y2: 200, r1: 50, r2: 10, }, colorStops: [ { offset: 0, color: 'red' }, { offset: 1, color: 'rgba(0,255,0,0)' }, ], }); } const SVG_LINEAR = '\n\n\n\n'; const SVG_RADIAL = '\n\n\n\n'; const SVG_INTERNALRADIUS = '\n\n\n\n'; const SVG_SWAPPED = '\n\n\n\n'; const SVG_LINEAR_PERCENTAGE = '\n\n\n\n'; const SVG_RADIAL_PERCENTAGE = '\n\n\n\n'; describe('Gradient', () => { function fromElement( gradientDef: SVGGradientElement, obj: FabricObject, options: Partial = {}, ) { return Gradient.fromElement(gradientDef, obj, { width: 0, height: 0, viewBoxHeight: 0, viewBoxWidth: 0, opacity: 1, ...options, } as SVGOptions); } test('constructor linearGradient', () => { const gradient = createLinearGradient(); expect(gradient instanceof Gradient).toBe(true); }); test('constructor radialGradient', () => { const gradient = createRadialGradient(); expect(gradient instanceof Gradient).toBe(true); }); test('properties linearGradient', () => { const gradient = createLinearGradient(); expect(gradient.coords.x1).toBe(0); expect(gradient.coords.y1).toBe(10); expect(gradient.coords.x2).toBe(100); expect(gradient.coords.y2).toBe(200); expect(gradient.type).toBe('linear'); expect(gradient.colorStops[0].offset).toBe(0); expect(gradient.colorStops[0].color).toBe('rgba(255,0,0,0)'); expect(gradient.colorStops[1].offset).toBe(1); expect(gradient.colorStops[1].color).toBe('green'); }); test('toSVG', () => { const gradient = createLinearGradient(); expect(gradient.toSVG, 'toSVG function exists').toBeTruthy(); }); describe('SVG exports', () => { test('toSVG linear', () => { const gradient = createLinearGradient(); const baseObj = new FabricObject({ width: 100, height: 100 }); expect(gradient.toSVG(baseObj)).toEqualSVG(SVG_LINEAR); }); test('toSVG radial', () => { const gradient = createRadialGradient(); const baseObj = new FabricObject({ width: 100, height: 100 }); expect(gradient.toSVG(baseObj)).toEqualSVG(SVG_RADIAL); }); test('toSVG linear sanitizes coord injection', () => { const gradient = new Gradient({ type: 'linear', coords: { x1: '0" />' as unknown as number, y1: '0" />' as unknown as number, x2: '0" />' as unknown as number, y2: '0" />' as unknown as number, }, colorStops: [ { offset: 0, color: 'rgba(255,0,0,0)' }, { offset: 1, color: 'green' }, ], }); const baseObj = new FabricObject({ width: 100, height: 100 }); const svg = gradient.toSVG(baseObj); expect(svg).not.toContain('' as unknown as number, y1: '0" />' as unknown as number, x2: '0" />' as unknown as number, y2: '0" />' as unknown as number, r1: '0" />' as unknown as number, r2: '50" />' as unknown as number, }, colorStops: [ { offset: 0, color: 'red' }, { offset: 1, color: 'rgba(0,255,0,0)' }, ], }); const baseObj = new FabricObject({ width: 100, height: 100 }); const svg = gradient.toSVG(baseObj); expect(svg).not.toContain('