UNPKG

fabric

Version:

Object model for HTML5 canvas, and SVG-to-canvas parser. Backed by jsdom and node-canvas.

277 lines (260 loc) 9.4 kB
import { describe, expect, it } from 'vitest'; import { version } from '../../package.json'; import { Rect } from './Rect'; import { FabricObject } from './Object/FabricObject'; import { Gradient } from '../gradient'; import { Pattern } from '../Pattern'; // will require some kind of handling here import { getEnv } from '../env'; import { loadSVGFromString } from '../parser/loadSVGFromString'; const REFERENCE_RECT = { version, type: 'Rect', originX: 'center', originY: 'center', 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, shadow: null, visible: true, backgroundColor: '', fillRule: 'nonzero', paintFirst: 'fill', globalCompositeOperation: 'source-over', rx: 0, ry: 0, skewX: 0, skewY: 0, strokeUniform: false, }; describe('Rect', () => { it('constructor', function () { const rect = new Rect(); expect(rect).toBeInstanceOf(Rect); expect(rect, 'Inherits from FabricObject').toBeInstanceOf(FabricObject); expect(rect.constructor.type).toBe('Rect'); }); it('cache properties', function () { expect(Rect.cacheProperties, 'rx is in cacheProperties array').toContain( 'rx', ); expect(Rect.cacheProperties, 'ry is in cacheProperties array').toContain( 'ry', ); }); it('toObject', function () { const rect = new Rect(); const object = rect.toObject(); expect(object).toEqual(REFERENCE_RECT); }); it('fromObject', async () => { const rect = await Rect.fromObject(REFERENCE_RECT); expect(rect).toBeInstanceOf(Rect); expect(rect.toObject()).toEqual(REFERENCE_RECT); const expectedObject = { ...REFERENCE_RECT, fill: { type: 'linear', coords: { x1: 0, y1: 0, x2: 200, y2: 0 }, colorStops: [ { offset: '0', color: 'rgb(255,0,0)', opacity: 1 }, { offset: '1', color: 'rgb(0,0,255)', opacity: 1 }, ], offsetX: 0, offsetY: 0, }, stroke: { type: 'linear', coords: { x1: 0, y1: 0, x2: 200, y2: 0 }, colorStops: [ { offset: '0', color: 'rgb(255,0,0)', opacity: 1 }, { offset: '1', color: 'rgb(0,0,255)', opacity: 1 }, ], offsetX: 0, offsetY: 0, }, }; const rect2 = await Rect.fromObject(expectedObject); expect(rect2.fill).toBeInstanceOf(Gradient); expect(rect2.stroke).toBeInstanceOf(Gradient); }); it('Rect.fromObject with pattern fill', async () => { const fillObj = { type: 'Pattern', source: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8z/C/HgAGgwJ/lK3Q6wAAAABJRU5ErkJggg==', }; const rect = await Rect.fromObject({ fill: fillObj }); expect(rect.fill).toBeInstanceOf(Pattern); }); it('Rect.fromElement', async () => { const elRect = getEnv().document.createElementNS( 'http://www.w3.org/2000/svg', 'rect', ); const rect = await Rect.fromElement(elRect); expect(rect).toBeInstanceOf(Rect); expect(rect.toObject()).toEqual({ ...REFERENCE_RECT, visible: false }); }); it('fromElement with custom attributes', async () => { const namespace = 'http://www.w3.org/2000/svg'; const elRectWithAttrs = getEnv().document.createElementNS( namespace, 'rect', ); elRectWithAttrs.setAttributeNS(namespace, 'x', '10'); elRectWithAttrs.setAttributeNS(namespace, 'y', '20'); elRectWithAttrs.setAttributeNS(namespace, 'width', '222'); elRectWithAttrs.setAttributeNS(namespace, 'height', '333'); elRectWithAttrs.setAttributeNS(namespace, 'rx', '11'); elRectWithAttrs.setAttributeNS(namespace, 'ry', '12'); elRectWithAttrs.setAttributeNS(namespace, 'fill', 'rgb(255,255,255)'); elRectWithAttrs.setAttributeNS(namespace, 'opacity', '0.45'); elRectWithAttrs.setAttributeNS(namespace, 'stroke', 'blue'); elRectWithAttrs.setAttributeNS(namespace, 'stroke-width', '3'); elRectWithAttrs.setAttributeNS(namespace, 'stroke-dasharray', '5, 2'); elRectWithAttrs.setAttributeNS(namespace, 'stroke-linecap', 'round'); elRectWithAttrs.setAttributeNS(namespace, 'stroke-linejoin', 'bevel'); elRectWithAttrs.setAttributeNS(namespace, 'stroke-miterlimit', '5'); elRectWithAttrs.setAttributeNS( namespace, 'vector-effect', 'non-scaling-stroke', ); const rectWithAttrs = await Rect.fromElement(elRectWithAttrs); expect(rectWithAttrs).toBeInstanceOf(Rect); expect(rectWithAttrs.strokeUniform, 'strokeUniform is parsed').toBe(true); const expectedObject = { ...REFERENCE_RECT, left: 10, top: 20, width: 222, height: 333, fill: 'rgb(255,255,255)', opacity: 0.45, stroke: 'blue', strokeWidth: 3, strokeDashArray: [5, 2], strokeLineCap: 'round', strokeLineJoin: 'bevel', strokeMiterLimit: 5, rx: 11, ry: 12, strokeUniform: true, }; expect(rectWithAttrs.toObject()).toEqual(expectedObject); }); it('clone with rounded corners', async () => { const rect = new Rect({ width: 100, height: 100, rx: 20, ry: 30 }); const clone = await rect.clone(); expect(clone.get('rx'), rect.get('rx')); expect(clone.get('ry'), rect.get('ry')); }); it('toSVG with rounded corners', async () => { const rect = new Rect({ left: 50, top: 50, width: 100, height: 100, rx: 20, ry: 30, strokeWidth: 0, }); const svg = rect.toSVG(); expect(svg).toBe( '<g transform="matrix(1 0 0 1 50 50)" >\n<rect style="stroke: none; stroke-width: 0; stroke-dasharray: none; stroke-linecap: butt; stroke-dashoffset: 0; stroke-linejoin: miter; stroke-miterlimit: 4; fill: rgb(0,0,0); fill-rule: nonzero; opacity: 1;" x="-50" y="-50" rx="20" ry="30" width="100" height="100" />\n</g>\n', ); }); it('toSVG with alpha colors fill', async () => { const rect = new Rect({ left: 50, top: 50, width: 100, height: 100, strokeWidth: 0, fill: 'rgba(255, 0, 0, 0.5)', }); const svg = rect.toSVG(); expect(svg).toBe( '<g transform="matrix(1 0 0 1 50 50)" >\n<rect style="stroke: none; stroke-width: 0; stroke-dasharray: none; stroke-linecap: butt; stroke-dashoffset: 0; stroke-linejoin: miter; stroke-miterlimit: 4; fill: rgb(255,0,0); fill-opacity: 0.5; fill-rule: nonzero; opacity: 1;" x="-50" y="-50" rx="0" ry="0" width="100" height="100" />\n</g>\n', ); }); it('toSVG with id', async () => { const rect = new Rect({ id: 'myRect', width: 100, height: 100, strokeWidth: 0, fill: 'rgba(255, 0, 0, 0.5)', }); const svg = rect.toSVG(); expect(svg).toBe( '<g transform="matrix(1 0 0 1 0 0)" id="myRect" >\n<rect style="stroke: none; stroke-width: 0; stroke-dasharray: none; stroke-linecap: butt; stroke-dashoffset: 0; stroke-linejoin: miter; stroke-miterlimit: 4; fill: rgb(255,0,0); fill-opacity: 0.5; fill-rule: nonzero; opacity: 1;" x="-50" y="-50" rx="0" ry="0" width="100" height="100" />\n</g>\n', ); }); it('toSVG with alpha colors stroke', async () => { const rect = new Rect({ top: 50, width: 100, height: 100, strokeWidth: 0, fill: '', stroke: 'rgba(255, 0, 0, 0.5)', }); const svg = rect.toSVG(); expect(svg).toBe( '<g transform="matrix(1 0 0 1 0 50)" >\n<rect style="stroke: rgb(255,0,0); stroke-opacity: 0.5; stroke-width: 0; stroke-dasharray: none; stroke-linecap: butt; stroke-dashoffset: 0; stroke-linejoin: miter; stroke-miterlimit: 4; fill: none; fill-rule: nonzero; opacity: 1;" x="-50" y="-50" rx="0" ry="0" width="100" height="100" />\n</g>\n', ); }); it('toSVG with paintFirst set to stroke', async () => { const rect = new Rect({ left: 50, width: 100, height: 100, paintFirst: 'stroke', }); const svg = rect.toSVG(); expect(svg).toBe( '<g transform="matrix(1 0 0 1 50 0)" >\n<rect style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-dashoffset: 0; stroke-linejoin: miter; stroke-miterlimit: 4; fill: rgb(0,0,0); fill-rule: nonzero; opacity: 1;" paint-order="stroke" x="-50" y="-50" rx="0" ry="0" width="100" height="100" />\n</g>\n', ); }); it('toObject without default values', async () => { const options = { width: 69, height: 50, left: 10, top: 20, version, }; const rect = new Rect(options); rect.includeDefaultValues = false; expect(rect.toObject()).toEqual({ type: 'Rect', ...options }); }); it('paintFirst life cycle', async () => { const svg = '<svg><rect x="10" y="10" height="50" width="55" fill="red" stroke="blue" paint-order="stroke" /></svg>'; const { objects } = await loadSVGFromString(svg); const rect = objects[0]; expect(rect).toBeTruthy(); const rectObject = rect!.toObject(); const rectSvg = rect!.toSVG(); expect(rect?.paintFirst).toBe('stroke'); expect(rectObject.paintFirst).toBe('stroke'); expect(rectSvg).toContain('paint-order="stroke"'); }); });