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('