import { describe, it, expect } from 'vitest';
import { Ellipse } from './Ellipse';
import { FabricObject } from './Object/Object';
import { getFabricDocument, version } from '../../fabric';
describe('Ellipse', () => {
it('initializes constructor correctly', () => {
expect(Ellipse).toBeTruthy();
const ellipse = new Ellipse();
expect(ellipse).toBeInstanceOf(Ellipse);
expect(ellipse).toBeInstanceOf(FabricObject);
expect(ellipse.constructor).toHaveProperty('type', 'Ellipse');
});
it('calculates complexity correctly', () => {
const ellipse = new Ellipse();
expect(ellipse.complexity).toBeTypeOf('function');
expect(ellipse.complexity()).toBe(1);
});
it('converts to object with correct properties', () => {
const ellipse = new Ellipse();
const defaultProperties = {
version: version,
type: 'Ellipse',
originX: 'left',
originY: 'top',
left: 0,
top: 0,
width: 0,
height: 0,
fill: 'rgb(0,0,0)',
stroke: null,
strokeWidth: 1,
strokeDashArray: null,
strokeLineCap: 'butt',
strokeDashOffset: 0,
strokeLineJoin: 'miter',
strokeMiterLimit: 4,
scaleX: 1,
scaleY: 1,
angle: 0,
flipX: false,
flipY: false,
opacity: 1,
skewX: 0,
skewY: 0,
rx: 0,
ry: 0,
shadow: null,
visible: true,
backgroundColor: '',
fillRule: 'nonzero',
paintFirst: 'fill',
globalCompositeOperation: 'source-over',
strokeUniform: false,
};
expect(ellipse.toObject).toBeTypeOf('function');
expect(ellipse.toObject()).toEqual(defaultProperties);
ellipse.set('left', 100);
ellipse.set('top', 200);
ellipse.set('rx', 15);
ellipse.set('ry', 25);
expect(ellipse.toObject()).toEqual({
...defaultProperties,
left: 100,
top: 200,
rx: 15,
ry: 25,
width: 30,
height: 50,
});
ellipse.set('rx', 30);
expect(ellipse.width).toBe(ellipse.rx * 2);
ellipse.set('scaleX', 2);
expect(ellipse.getRx()).toBe(ellipse.rx * ellipse.scaleX);
});
it('generates object without defaults', () => {
const circle = new Ellipse({
includeDefaultValues: false,
});
expect(circle.toObject()).toEqual({
type: 'Ellipse',
version: version,
left: 0,
top: 0,
});
});
it('determines visibility correctly', () => {
const ellipse = new Ellipse();
ellipse.set('rx', 0);
ellipse.set('ry', 0);
expect(ellipse.isNotVisible()).toBe(false);
ellipse.set('strokeWidth', 0);
expect(ellipse.isNotVisible()).toBe(true);
});
it('generates SVG correctly', () => {
const ellipse = new Ellipse({
rx: 100,
ry: 12,
fill: 'red',
stroke: 'blue',
});
expect(ellipse.toSVG()).toEqualSVG(
'\n\n\n',
);
expect(ellipse.toClipPathSVG()).toEqualSVG(
'\t\n',
);
});
it('generates SVG with clipPath correctly', () => {
const ellipse = new Ellipse({
rx: 100,
ry: 12,
fill: 'red',
stroke: 'blue',
});
ellipse.clipPath = new Ellipse({ rx: 12, ry: 100, left: 60, top: -50 });
expect(ellipse.toSVG()).toEqualSVG(
'\n\n\t\n\n\n\n',
);
});
it('generates SVG with absolute positioned clipPath correctly', () => {
const ellipse = new Ellipse({
rx: 100,
ry: 12,
fill: 'red',
stroke: 'blue',
});
ellipse.clipPath = new Ellipse({ rx: 12, ry: 100, left: 60, top: -50 });
ellipse.clipPath.absolutePositioned = true;
expect(ellipse.toSVG()).toEqualSVG(
'\n\n\n\t\n\n\n\n\n',
);
});
it('creates from SVG element correctly', async () => {
expect(Ellipse.fromElement).toBeTypeOf('function');
const namespace = 'http://www.w3.org/2000/svg';
const elEllipse = getFabricDocument().createElementNS(
namespace,
'ellipse',
) as unknown as HTMLElement;
const rx = 5;
const ry = 7;
const left = 12;
const top = 15;
const fill = 'ff5555';
const opacity = 0.5;
const strokeWidth = 2;
const strokeDashArray = [5, 2];
const strokeLineCap = 'round';
const strokeLineJoin = 'bevel';
const strokeMiterLimit = 5;
elEllipse.setAttributeNS(namespace, 'rx', String(rx));
elEllipse.setAttributeNS(namespace, 'ry', String(ry));
elEllipse.setAttributeNS(namespace, 'cx', String(left));
elEllipse.setAttributeNS(namespace, 'cy', String(top));
elEllipse.setAttributeNS(namespace, 'fill', fill);
elEllipse.setAttributeNS(namespace, 'opacity', String(opacity));
elEllipse.setAttributeNS(namespace, 'stroke-width', String(strokeWidth));
elEllipse.setAttributeNS(namespace, 'stroke-dasharray', '5, 2');
elEllipse.setAttributeNS(namespace, 'stroke-linecap', strokeLineCap);
elEllipse.setAttributeNS(namespace, 'stroke-linejoin', strokeLineJoin);
elEllipse.setAttributeNS(
namespace,
'stroke-miterlimit',
String(strokeMiterLimit),
);
const oEllipse = await Ellipse.fromElement(elEllipse, {});
expect(oEllipse).toBeInstanceOf(Ellipse);
expect(oEllipse.get('rx')).toBe(rx);
expect(oEllipse.get('ry')).toBe(ry);
expect(oEllipse.get('left')).toBe(left - rx);
expect(oEllipse.get('top')).toBe(top - ry);
expect(oEllipse.get('fill')).toBe(fill);
expect(oEllipse.get('opacity')).toBe(opacity);
expect(oEllipse.get('strokeWidth')).toBe(strokeWidth);
expect(oEllipse.get('strokeDashArray')).toEqual(strokeDashArray);
expect(oEllipse.get('strokeLineCap')).toBe(strokeLineCap);
expect(oEllipse.get('strokeLineJoin')).toBe(strokeLineJoin);
expect(oEllipse.get('strokeMiterLimit')).toBe(strokeMiterLimit);
});
it('creates from object correctly', async () => {
expect(Ellipse).toBeTypeOf('function');
const left = 112;
const top = 234;
const rx = 13.45;
const ry = 14.78;
const fill = 'ff5555';
const ellipse = await Ellipse.fromObject({
left,
top,
rx,
ry,
fill,
});
expect(ellipse).toBeInstanceOf(Ellipse);
expect(ellipse.get('left')).toBe(left);
expect(ellipse.get('top')).toBe(top);
expect(ellipse.get('rx')).toBe(rx);
expect(ellipse.get('ry')).toBe(ry);
expect(ellipse.get('fill')).toBe(fill);
const expected = ellipse.toObject();
const actual = await Ellipse.fromObject(expected);
expect(actual.toObject()).toEqual(expected);
});
});