- Fix router import path in main.js - Handle Django REST Framework pagination format in API calls - Add getTemplates function to project API - Restart frontend development server
348 lines
9.5 KiB
TypeScript
348 lines
9.5 KiB
TypeScript
import { Polyline } from './Polyline';
|
|
import { Point } from '../Point';
|
|
|
|
import { describe, expect, it } from 'vitest';
|
|
import { Polygon } from './Polygon';
|
|
import { FabricObject } from './Object/FabricObject';
|
|
import { createReferenceObject, createSVGElement } from '../../test/utils';
|
|
|
|
const points = [
|
|
{ x: 2, y: 2 },
|
|
{ x: 12, y: 2 },
|
|
{ x: 12, y: 7 },
|
|
];
|
|
|
|
const REFERENCE_OBJECT = createReferenceObject('Polyline', {
|
|
left: 15,
|
|
top: 17,
|
|
width: 10,
|
|
height: 10,
|
|
points: getPoints(),
|
|
});
|
|
|
|
describe('Polyline', () => {
|
|
describe('_calcDimensions and pathOffset', () => {
|
|
it('returns dimensions of the polyline regardless of transform or strokeWidth', () => {
|
|
const polyline = new Polyline(points, {
|
|
scaleX: 2,
|
|
scaleY: 2,
|
|
angle: 5,
|
|
strokeWidth: 4,
|
|
});
|
|
const dim = polyline._calcDimensions();
|
|
expect(dim).toEqual({
|
|
left: 2,
|
|
top: 2,
|
|
width: 10,
|
|
height: 5,
|
|
pathOffset: new Point(7, 4.5),
|
|
strokeDiff: new Point(0, 0),
|
|
strokeOffset: new Point(0, 0),
|
|
});
|
|
});
|
|
it('returns dimensions of the polyline regardless of transform or strokeWidth and skew', () => {
|
|
const polyline = new Polyline(points, {
|
|
scaleX: 2,
|
|
scaleY: 2,
|
|
angle: 5,
|
|
strokeWidth: 4,
|
|
skewX: 10,
|
|
skewY: 5,
|
|
});
|
|
const dim = polyline._calcDimensions();
|
|
expect(dim).toEqual({
|
|
left: 2,
|
|
top: 2,
|
|
width: 10,
|
|
height: 5,
|
|
pathOffset: new Point(7, 4.5),
|
|
strokeDiff: expect.any(Point),
|
|
strokeOffset: expect.any(Point),
|
|
});
|
|
});
|
|
it('returns dimensions of the polyline exactBounds and no strokeWidth', () => {
|
|
const polyline = new Polyline(points, {
|
|
scaleX: 2,
|
|
scaleY: 2,
|
|
angle: 5,
|
|
strokeWidth: 0,
|
|
exactBoundingBox: true,
|
|
});
|
|
const dim = polyline._calcDimensions();
|
|
expect(dim).toEqual({
|
|
left: 2,
|
|
top: 2,
|
|
width: 10,
|
|
height: 5,
|
|
pathOffset: new Point(7, 4.5),
|
|
strokeDiff: new Point(0, 0),
|
|
strokeOffset: new Point(0, 0),
|
|
});
|
|
});
|
|
it('returns dimensions of the polyline exactBounds and strokeWidth', () => {
|
|
const polyline = new Polyline(points, {
|
|
scaleX: 2,
|
|
scaleY: 2,
|
|
angle: 5,
|
|
strokeWidth: 4,
|
|
exactBoundingBox: true,
|
|
});
|
|
const dim = polyline._calcDimensions();
|
|
expect(dim).toEqual({
|
|
left: 2,
|
|
top: 0,
|
|
width: 12,
|
|
height: 7,
|
|
pathOffset: new Point(8, 3.5),
|
|
strokeDiff: new Point(4, 4),
|
|
strokeOffset: new Point(0, 4),
|
|
});
|
|
});
|
|
it('returns dimensions of the polyline exactBounds and strokeWidth with skew', () => {
|
|
const polyline = new Polyline(points, {
|
|
scaleX: 2,
|
|
scaleY: 2,
|
|
angle: 5,
|
|
strokeWidth: 4,
|
|
skewX: 10,
|
|
exactBoundingBox: true,
|
|
});
|
|
const dim = polyline._calcDimensions();
|
|
expect(dim).toEqual({
|
|
left: 2,
|
|
top: 0,
|
|
width: 13.234288864959254,
|
|
height: 7,
|
|
pathOffset: new Point(8, 3.5),
|
|
strokeDiff: new Point(4.70530792283386, 4),
|
|
strokeOffset: new Point(0.7053079228338603, 4),
|
|
});
|
|
});
|
|
});
|
|
it('should safeguard passing points in options', () => {
|
|
expect(new Polyline(points, { points: [{ x: 1, y: 1 }] })).toEqual(
|
|
expect.objectContaining({
|
|
points: points,
|
|
}),
|
|
);
|
|
});
|
|
|
|
const REFERENCE_EMPTY_OBJECT = {
|
|
points: [],
|
|
width: 0,
|
|
height: 0,
|
|
top: 0,
|
|
left: 0,
|
|
};
|
|
|
|
it('initializes constructor correctly', () => {
|
|
expect(Polyline).toBeTruthy();
|
|
|
|
const polyline = new Polyline(getPoints());
|
|
|
|
expect(polyline).toBeInstanceOf(Polyline);
|
|
expect(polyline).toBeInstanceOf(FabricObject);
|
|
|
|
expect(polyline.constructor).toHaveProperty('type', 'Polyline');
|
|
expect(polyline.get('points')).toEqual([
|
|
{ x: 10, y: 12 },
|
|
{ x: 20, y: 22 },
|
|
]);
|
|
});
|
|
|
|
it('positions with strokeWidth top-left and origins top-left', () => {
|
|
const polyline = new Polyline(getPoints(), {
|
|
strokeWidth: 2,
|
|
originX: 'left',
|
|
originY: 'top',
|
|
});
|
|
|
|
expect(polyline.left).toBe(9);
|
|
expect(polyline.top).toBe(11);
|
|
});
|
|
|
|
it('positions with strokeWidth top-left and origins center-center', () => {
|
|
const polyline = new Polyline(getPoints(), {
|
|
strokeWidth: 2,
|
|
originX: 'center',
|
|
originY: 'center',
|
|
});
|
|
|
|
expect(polyline.left).toBe(15);
|
|
expect(polyline.top).toBe(17);
|
|
});
|
|
|
|
it('positions with strokeWidth top-left and origins bottom-right', () => {
|
|
const polyline = new Polyline(getPoints(), {
|
|
strokeWidth: 2,
|
|
originX: 'right',
|
|
originY: 'bottom',
|
|
});
|
|
|
|
expect(polyline.left).toBe(21);
|
|
expect(polyline.top).toBe(23);
|
|
});
|
|
|
|
it('has complexity function', () => {
|
|
const polyline = new Polyline(getPoints());
|
|
expect(polyline.complexity).toBeTypeOf('function');
|
|
});
|
|
|
|
it('converts to object correctly', () => {
|
|
const polyline = new Polyline(getPoints());
|
|
expect(polyline.toObject).toBeTypeOf('function');
|
|
|
|
expect({
|
|
...polyline.toObject(),
|
|
}).toEqual(REFERENCE_OBJECT);
|
|
});
|
|
|
|
it('generates SVG correctly', () => {
|
|
const polyline = new Polygon(getPoints(), { fill: 'red', stroke: 'blue' });
|
|
expect(polyline.toSVG).toBeTypeOf('function');
|
|
const EXPECTED_SVG =
|
|
'<g transform="matrix(1 0 0 1 15 17)" >\n<polygon style="stroke: rgb(0,0,255); stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-dashoffset: 0; stroke-linejoin: miter; stroke-miterlimit: 4; fill: rgb(255,0,0); fill-rule: nonzero; opacity: 1;" points="-5,-5 5,5" />\n</g>\n';
|
|
expect(polyline.toSVG()).toEqual(EXPECTED_SVG);
|
|
});
|
|
|
|
it('creates from object correctly', async () => {
|
|
expect(Polyline.fromObject).toBeTypeOf('function');
|
|
const polyline = await Polyline.fromObject(REFERENCE_OBJECT);
|
|
expect(polyline).toBeInstanceOf(Polyline);
|
|
expect(polyline.toObject()).toEqual(REFERENCE_OBJECT);
|
|
});
|
|
|
|
it('creates from element without points nor strokeWidth', async () => {
|
|
expect(Polyline.fromElement).toBeTypeOf('function');
|
|
const elPolylineWithoutPoints = createSVGElement('polyline', {
|
|
'stroke-width': 0,
|
|
});
|
|
|
|
const polyline = await Polyline.fromElement(elPolylineWithoutPoints);
|
|
expect(polyline.toObject()).toEqual({
|
|
...REFERENCE_OBJECT,
|
|
...REFERENCE_EMPTY_OBJECT,
|
|
strokeWidth: 0,
|
|
});
|
|
});
|
|
|
|
it('creates from element without points but takes strokeWidth into account', async () => {
|
|
const elPolylineWithoutPoints = createSVGElement('polyline', {
|
|
'stroke-width': 8,
|
|
});
|
|
|
|
const polyline = await Polyline.fromElement(elPolylineWithoutPoints);
|
|
expect(polyline.toObject()).toEqual({
|
|
...REFERENCE_OBJECT,
|
|
...REFERENCE_EMPTY_OBJECT,
|
|
left: 0,
|
|
top: 0,
|
|
strokeWidth: 8,
|
|
});
|
|
});
|
|
|
|
it('creates from element with empty points', async () => {
|
|
const elPolylineWithEmptyPoints = createSVGElement('polyline', {
|
|
points: '',
|
|
});
|
|
|
|
const polyline = await Polyline.fromElement(elPolylineWithEmptyPoints);
|
|
expect(polyline.toObject()).toEqual({
|
|
...REFERENCE_OBJECT,
|
|
...REFERENCE_EMPTY_OBJECT,
|
|
left: 0,
|
|
top: 0,
|
|
});
|
|
});
|
|
|
|
it('creates from element with points and strokeWidth', async () => {
|
|
const elPolyline = createSVGElement('polyline', {
|
|
points: '10,12 20,22',
|
|
'stroke-width': 1,
|
|
});
|
|
|
|
const polyline = await Polyline.fromElement(elPolyline);
|
|
expect(polyline.toObject()).toEqual({
|
|
...REFERENCE_OBJECT,
|
|
left: 15,
|
|
top: 17,
|
|
});
|
|
});
|
|
|
|
it('creates from element without strokeWidth with top-left on top-left point', async () => {
|
|
const elPolyline = createSVGElement('polyline', {
|
|
points: '10,12 20,22',
|
|
'stroke-width': 0,
|
|
});
|
|
|
|
const polyline = await Polyline.fromElement(elPolyline);
|
|
expect(polyline).toBeInstanceOf(Polyline);
|
|
expect(polyline.toObject()).toEqual({
|
|
...REFERENCE_OBJECT,
|
|
strokeWidth: 0,
|
|
left: 15,
|
|
top: 17,
|
|
});
|
|
});
|
|
|
|
it('creates from element with strokeWidth and adjusts space for stroke', async () => {
|
|
const elPolyline = createSVGElement('polyline', {
|
|
points: '10,12 20,22',
|
|
});
|
|
|
|
const polyline = await Polyline.fromElement(elPolyline);
|
|
expect(polyline).toBeInstanceOf(Polyline);
|
|
expect(polyline.toObject()).toEqual({
|
|
...REFERENCE_OBJECT,
|
|
left: 15,
|
|
top: 17,
|
|
});
|
|
});
|
|
|
|
it('creates from element with custom attributes', async () => {
|
|
const elPolylineWithAttrs = createSVGElement('polyline', {
|
|
points: '10,10 20,20 30,30 10,10',
|
|
fill: 'rgb(255,255,255)',
|
|
opacity: 0.34,
|
|
'stroke-width': 3,
|
|
stroke: 'blue',
|
|
transform: 'translate(-10,-20) scale(2)',
|
|
'stroke-dasharray': '5, 2',
|
|
'stroke-linecap': 'round',
|
|
'stroke-linejoin': 'bevel',
|
|
'stroke-miterlimit': 5,
|
|
});
|
|
|
|
const polylineWithAttrs = await Polyline.fromElement(elPolylineWithAttrs);
|
|
const expectedPoints = [
|
|
{ x: 10, y: 10 },
|
|
{ x: 20, y: 20 },
|
|
{ x: 30, y: 30 },
|
|
{ x: 10, y: 10 },
|
|
];
|
|
expect(polylineWithAttrs.toObject()).toEqual({
|
|
...REFERENCE_OBJECT,
|
|
width: 20,
|
|
height: 20,
|
|
fill: 'rgb(255,255,255)',
|
|
stroke: 'blue',
|
|
strokeWidth: 3,
|
|
strokeDashArray: [5, 2],
|
|
strokeLineCap: 'round',
|
|
strokeLineJoin: 'bevel',
|
|
strokeMiterLimit: 5,
|
|
opacity: 0.34,
|
|
points: expectedPoints,
|
|
left: 20,
|
|
top: 20,
|
|
});
|
|
});
|
|
});
|
|
|
|
function getPoints() {
|
|
return [
|
|
{ x: 10, y: 12 },
|
|
{ x: 20, y: 22 },
|
|
];
|
|
}
|