Форк Rambox
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

674 lines
26 KiB

describe("Ext.draw.Draw", function() {
var approximateComparison;
// Many calculations will propagate the rounding error, thus
// exact comparison which does not take machine epsilon will not work.
// For the test purposes, we use "approximate" comparison 'toEqualNumber'.
// prec = 1e10 means comparison up to 10 decimal digits.
beforeEach(function() {
var prec = 1e10;
approximateComparison = function(a, b) {
return Math.round(a * prec) === Math.round(b * prec);
};
this.addMatchers({
toEqualNumber: function(n) {
return approximateComparison(this.actual, n);
},
toEqualAbsolutePath: function(path) {
var length = path.length, i, p;
for (i = 0; i < length; i++) {
p = path[i];
if (typeof p === "number") {
if (!approximateComparison(this.actual[i], p)) {
return false;
}
}
}
return true;
}
});
});
describe("Ext.draw.Draw.ellipsePath", function() {
it("should return path string from ellipse", function() {
expect(Ext.draw.Draw.ellipsePath({ attr: { x: -100, y: 50, rx: 10, ry: 13 } })).toEqual("M-100,37A10,13,0,1,1,-100,63A10,13,0,1,1,-100,37z");
});
it("should return path string from zero-radius ellipse", function() {
expect(Ext.draw.Draw.ellipsePath({ attr: { x: 0, y: 0, rx: 0, ry: 0 } })).toEqual("M0,0A0,0,0,1,1,0,0A0,0,0,1,1,0,0z");
});
});
describe("Ext.draw.Draw.rectPath", function() {
it("should return path string from rectangle", function() {
expect(Ext.draw.Draw.rectPath({ attr: { x: -100, y: 50, width: 400, height: 42 } })).toEqual("M-100,50L300,50,300,92,-100,92z");
});
it("should return path string from rounded rectangle", function() {
expect(Ext.draw.Draw.rectPath({ attr: { radius: 15, x: -100, y: 50, width: 400, height: 42 } })).toEqual("M-85,50l370,0a15,15,0,0,1,15,15l0,12a15,15,0,0,1,-15,15l-370,0a15,15,0,0,1,-15,-15l0,-12a15,15,0,0,1,15,-15z");
});
});
describe("Ext.draw.Draw.quadratic2curve", function() {
it("should convert simple 'quadratic' into 'cubic'", function() {
expect(Ext.draw.Draw.quadratic2curve(-30, 60, 0, 0, 120, 0)).toEqual([-10, 20, 40, 0, 120, 0]);
});
it("should convert complicated 'quadratic' into 'cubic'", function() {
expect(Ext.draw.Draw.quadratic2curve(-30, 60, 3, 12, 120, -300)).toEqual([-8, 28, 42, -92, 120, -300]);
});
});
describe("Ext.draw.Draw.arc2curve", function() {
it("should convert simple 'arc' into two 'cubic' commands", function() {
// each cubic needs 6 values
expect(Ext.draw.Draw.arc2curve(0, 0, 50, 60, 0, 0, 0, 100, 100).length).toEqual(12);
});
it("should correctly compute the initial cubic starting point", function() {
expect(Ext.draw.Draw.arc2curve(0, 0, 50, 60, 0, 0, 0, 100, 100)[0]).toEqualNumber(-32.07501497178969);
expect(Ext.draw.Draw.arc2curve(0, 0, 50, 60, 0, 0, 0, 100, 100)[1]).toEqualNumber(46.188021518359555);
});
it("should keep the arc end point the same as the cubic end point", function() {
expect(Ext.draw.Draw.arc2curve(0, 0, 50, 60, 0, 0, 0, 200, 100)[10]).toEqual(200);
expect(Ext.draw.Draw.arc2curve(0, 0, 50, 60, 0, 0, 0, 200, 100)[11]).toEqual(100);
});
});
describe("Ext.draw.Draw.rotatePoint rotates (x,y) with (cx, cy) as the rotation center", function() {
it("should return an object which has a property x (Number)", function() {
expect(typeof Ext.draw.Draw.rotatePoint(100, 50, 0).x).toEqual("number");
});
it("should return an object which has a property y (Number)", function() {
expect(typeof Ext.draw.Draw.rotatePoint(100, 50, 0).y).toEqual("number");
});
it("should return x:0 when rotating (0, 0) with 0 deg", function() {
expect(Ext.draw.Draw.rotatePoint(0, 0, 0).x).toEqualNumber(0);
});
it("should return y:0 when rotating (0, 0) with 0 deg", function() {
expect(Ext.draw.Draw.rotatePoint(0, 0, 0).y).toEqualNumber(0);
});
it("should return x:0 when rotating (100, 0) with 90 deg", function() {
expect(Ext.draw.Draw.rotatePoint(100, 0, 90).x).toEqualNumber(0);
});
it("should return y:100 when rotating (0, 100) with 90 deg", function() {
expect(Ext.draw.Draw.rotatePoint(100, 0, 90).y).toEqualNumber(100);
});
it("should return x:-100 when rotating (100, 0) with 180 deg", function() {
expect(Ext.draw.Draw.rotatePoint(100, 0, 180).x).toEqualNumber(-100);
});
it("should return y:0 when rotating (0, 100) with 180 deg", function() {
expect(Ext.draw.Draw.rotatePoint(100, 0, 180).y).toEqualNumber(0);
});
it("should return x:0 when rotating (100, 0) centered at (50, 0) with 180 deg", function() {
expect(Ext.draw.Draw.rotatePoint(100, 0, 180, 50, 0).x).toEqualNumber(0);
});
it("should return y:0 when rotating (0, 100) centered at (50, 0) with 180 deg", function() {
expect(Ext.draw.Draw.rotatePoint(100, 0, 180, 50, 0).y).toEqualNumber(0);
});
});
describe("Ext.draw.Draw.rotate rotates (x,y) with the origin as the rotation center", function() {
it("should return an object which has a property x (Number)", function() {
expect(typeof Ext.draw.Draw.rotate(100, 50, 0).x).toEqual("number");
});
it("should return an object which has a property y (Number)", function() {
expect(typeof Ext.draw.Draw.rotate(100, 50, 0).y).toEqual("number");
});
it("should return x:0 when rotating (0, 0) with 0 rad", function() {
expect(Ext.draw.Draw.rotate(0, 0, 0).x).toEqualNumber(0);
});
it("should return y:0 when rotating (0, 0) with 0 rad", function() {
expect(Ext.draw.Draw.rotate(0, 0, 0).y).toEqualNumber(0);
});
it("should return x:0 when rotating (100, 0) with PI/2 rad", function() {
expect(Ext.draw.Draw.rotate(100, 0, Math.PI / 2).x).toEqualNumber(0);
});
it("should return y:100 when rotating (0, 100) with PI/2 rad", function() {
expect(Ext.draw.Draw.rotate(100, 0, Math.PI / 2).y).toEqualNumber(100);
});
it("should return x:-100 when rotating (100, 0) with PI rad", function() {
expect(Ext.draw.Draw.rotate(100, 0, Math.PI).x).toEqualNumber(-100);
});
it("should return y:0 when rotating (0, 100) with PI/2 rad", function() {
expect(Ext.draw.Draw.rotate(100, 0, Math.PI).y).toEqualNumber(0);
});
});
describe("Ext.draw.Draw.degrees converts from radian to degree", function() {
it("should return a number", function() {
expect(typeof Ext.draw.Draw.degrees(1)).toEqual("number");
});
it("should convert 0 rad to 0 deg", function() {
expect(Ext.draw.Draw.degrees(0)).toEqual(0);
});
it("should convert 1 rad to 57.296 deg", function() {
expect(Ext.draw.Draw.degrees(1)).toEqual(180 / Math.PI);
});
it("should convert 2 rad to 114.592 deg", function() {
expect(Ext.draw.Draw.degrees(2)).toEqual(360 / Math.PI);
});
it("should convert 3 rad to 171.888 deg", function() {
expect(Ext.draw.Draw.degrees(3)).toEqual(540 / Math.PI);
});
it("should convert 7 rad to 41.07 deg", function() {
expect(Ext.draw.Draw.degrees(7)).toEqual((1260 / Math.PI) % 360);
});
it("should convert PI rad to 180 deg", function() {
expect(Ext.draw.Draw.degrees(Math.PI)).toEqual(180);
});
it("should convert 2*PI rad to 360 deg", function() {
expect(Ext.draw.Draw.degrees(2 * Math.PI)).toEqual(0);
});
it("should convert 3*PI rad to 180 deg", function() {
expect(Ext.draw.Draw.degrees(3 * Math.PI)).toEqual(180);
});
it("should convert 4*PI rad to 360 deg", function() {
expect(Ext.draw.Draw.degrees(4 * Math.PI)).toEqual(0);
});
});
describe("Ext.draw.Draw.rad converts from degree to radian", function() {
it("should return a number", function() {
expect(typeof Ext.draw.Draw.rad(1)).toEqual("number");
});
it("should convert 0 deg to 0 rad", function() {
expect(Ext.draw.Draw.rad(0)).toEqual(0);
});
it("should convert 90 deg to PI/2 rad", function() {
expect(Ext.draw.Draw.rad(90)).toEqual(Math.PI / 2);
});
it("should convert 180 deg to PI rad", function() {
expect(Ext.draw.Draw.rad(180)).toEqual(Math.PI);
});
it("should convert 270 deg to 3*PI/2 rad", function() {
expect(Ext.draw.Draw.rad(270)).toEqual(3 * Math.PI / 2);
});
it("should convert 360 deg to 0 rad", function() {
expect(Ext.draw.Draw.rad(360)).toEqual(0);
});
it("should convert 540 deg to PI rad", function() {
expect(Ext.draw.Draw.rad(540)).toEqual(Math.PI);
});
it("should convert 720 deg to 0 rad", function() {
expect(Ext.draw.Draw.rad(720)).toEqual(0);
});
});
describe("Ext.draw.Draw.rotateAndTranslatePath", function() {
it("should return an absolute path even if there is no rotation or translation", function() {
var path = [['M', 0, 0], ['L', 100, 0], ['L', 100, 100], ['L', 0, 100], ['Z']];
expect(Ext.draw.Draw.rotateAndTranslatePath({
attr: {
path: path
},
rotation: {
degrees: 0,
x: 0,
y: 0
},
translation: {
x: 0,
y: 0
}
})).toEqualAbsolutePath(path);
});
it("should be able to translate path only", function() {
expect(Ext.draw.Draw.rotateAndTranslatePath({
attr: {
path: [['M', 0, 0], ['L', 100, 0], ['L', 100, 100], ['L', 0, 100], ['Z']]
},
rotation: {
degrees: 0,
x: 0,
y: 0
},
translation: {
x: 100,
y: 100
}
})).toEqualAbsolutePath([['M', 100, 100], ['L', 200, 100], ['L', 200, 200], ['L', 100, 200], ['Z']]);
});
it("should be able to rotate path only", function() {
expect(Ext.draw.Draw.rotateAndTranslatePath({
attr: {
path: [['M', 0, 0], ['L', 100, 0], ['L', 100, 100], ['L', 0, 100], ['Z']]
},
rotation: {
degrees: 90,
x: 0,
y: 0
},
translation: {
x: 0,
y: 0
}
})).toEqualAbsolutePath([['M', 0, 0], ['L', 0, 100], ['L', -100, 100], ['L', -100, 0], ['Z']]);
});
it("should be able to do both simultaneously", function() {
expect(Ext.draw.Draw.rotateAndTranslatePath({
attr: {
path: [['M', 0, 0], ['L', 100, 0], ['L', 100, 100], ['L', 0, 100], ['Z']]
},
rotation: {
degrees: 90,
x: 0,
y: 0
},
translation: {
x: 100,
y: 100
}
})).toEqualAbsolutePath([['M', 0, 100], ['L', 0, 200], ['L', -100, 200], ['L', -100, 100], ['Z']]);
});
});
describe("pathDimensions", function() {
var path = [['M', 0, 0], ['L', 100, 0], ['L', 100, 50], ['L', 0, 50], ['Z']];
describe("a rectangle with origin in (0,0)", function() {
it("should return an x:0 property", function() {
expect(Ext.draw.Draw.pathDimensions(path).x).toBe(0);
});
it("should return an y:0 property", function() {
expect(Ext.draw.Draw.pathDimensions(path).y).toBe(0);
});
it("should have an height of 50", function() {
expect(Ext.draw.Draw.pathDimensions(path).height).toBe(50);
});
it("should have an width of 100", function() {
expect(Ext.draw.Draw.pathDimensions(path).width).toBe(100);
});
});
});
describe("smooth", function() {
describe("a simple path with (4 points connected by a line)", function() {
var path;
beforeEach(function() {
path = Ext.draw.Draw.smooth([['M', 0, 0], ['L', 10, 10], ['L', 20, 0], ['L',30, 10]]);
});
it("should have an initial position at 0 0", function() {
expect(path[0][1]).toBe(0);
expect(path[0][2]).toBe(0);
});
describe("bezier curves", function() {
var curve;
it("should return a path with 3 bezier curves", function() {
expect(path[1][0]).toBe("C");
expect(path[2][0]).toBe("C");
expect(path[3][0]).toBe("C");
});
describe("first bezier curve", function() {
beforeEach(function() {
curve = path[1];
});
it("should have a first control point at 0 0", function() {
expect(curve[1]).toEqualNumber(0);
expect(curve[2]).toEqualNumber(0);
});
it("should have the second control point at west of the end point", function() {
expect(curve[3] < 10).toBe(true);
expect(curve[4]).toEqualNumber(10);
});
it("should have the end point at 10 10", function() {
expect(curve[5]).toEqualNumber(10);
expect(curve[6]).toEqualNumber(10);
});
});
describe("second bezier curve", function() {
beforeEach(function() {
curve = path[2];
});
it("should have a first control point at east of origin point", function() {
expect(curve[1] > 10).toBe(true);
expect(curve[2]).toEqualNumber(10);
});
it("should have the second control point at west of end point", function() {
expect(curve[3] > 10).toBe(true);
expect(curve[4]).toEqualNumber(0);
});
it("should have the end point at 20 0", function() {
expect(curve[5]).toBe(20);
expect(curve[6]).toBe(0);
});
});
describe("third bezier curve (the last one)", function() {
beforeEach(function() {
curve = path[3];
});
it("should have a first control point at east of origin point", function() {
expect(curve[1] > 20).toBe(true);
expect(curve[2]).toEqualNumber(0);
});
it("should have the second control point at 30 10", function() {
expect(curve[3]).toEqualNumber(30);
expect(curve[4]).toEqualNumber(10);
});
it("should have it's end point at 30 10", function() {
expect(curve[5]).toEqualNumber(30);
expect(curve[6]).toEqualNumber(10);
});
});
});
});
describe("value argument reduce the convex hull size of each bezier curve when value is increased", function() {
var path1, path2, controlPoint1, controlPoint2;
beforeEach(function() {
path1 = Ext.draw.Draw.smooth([['M', 0, 0], ['L', 10, 10], ['L', 20, 0], ['L',30, 10]]);
path2 = Ext.draw.Draw.smooth([['M', 0, 0], ['L', 10, 10], ['L', 20, 0], ['L',30, 10]], 10);
});
describe("second control point of the first curve", function() {
it("should decrease distance between the second control point and end point", function() {
controlPoint1 = {x : path1[1][3], y : path1[1][4]};
controlPoint2 = {x : path2[1][3], y : path2[1][4]};
expect(controlPoint1.x < controlPoint2.x).toBe(true);
expect(controlPoint1.y).toEqualNumber(controlPoint2.y);
});
});
describe("first control point of the second curve", function() {
it("should decrease distance between the first control point and origin", function() {
controlPoint1 = {x : path1[2][1], y : path1[2][2]};
controlPoint2 = {x : path2[2][1], y : path2[2][2]};
expect(controlPoint1.x > controlPoint2.x).toBe(true);
expect(controlPoint1.y).toEqualNumber(controlPoint2.y);
});
});
describe("second control point of the second curve", function() {
it("should decrease distance between the second control point and end point", function() {
controlPoint1 = {x : path1[2][3], y : path1[2][4]};
controlPoint2 = {x : path2[2][3], y : path2[2][4]};
expect(controlPoint1.x < controlPoint2.x).toBe(true);
expect(controlPoint1.y).toEqualNumber(controlPoint2.y);
});
});
describe("first control point of the third curve (last one)", function() {
it("should decrease distance between the first control point and origin", function() {
controlPoint1 = {x : path1[3][1], y : path1[3][2]};
controlPoint2 = {x : path2[3][1], y : path2[3][2]};
expect(controlPoint1.x > controlPoint2.x).toBe(true);
expect(controlPoint1.y).toEqualNumber(controlPoint2.y);
});
});
});
});
//TODO: finish this when snapEnds function will be done.
describe("snapEnds", function() {
var object;
beforeEach(function() {
object = Ext.draw.Draw.snapEnds(0, 100, 10);
});
describe("returned object", function() {
it("should have a from property equal to first argument", function() {
expect(object.from).toEqual(0);
});
it("should have a to property greater than or equal to second argument", function() {
expect(object.to >= 100).toBe(true);
});
it("should have a steps property lesser than or equal to third argument", function() {
expect(object.steps <= 10).toBe(true);
});
});
});
describe("parseGradient", function() {
var gradient,
rawGradient,
generateIdTypeAndStopSpec = function() {
it("should have an id inherited from the passed object", function() {
expect(gradient.id).toBe(rawGradient.id);
});
it("should have a type inherited from the passed object", function() {
expect(gradient.type).toBe(rawGradient.type || "linear");
});
describe("stops property", function() {
var stops;
beforeEach(function() {
stops = gradient.stops;
});
it("should be an array", function() {
expect(Ext.isArray(stops)).toBe(true);
});
describe("array members", function() {
var member1, member2, offsets, colors, opacities;
beforeEach(function() {
var rawStops, offset;
member1 = stops[0];
member2 = stops[1];
offsets = [];
colors = [];
opacities = [];
rawStops = rawGradient.stops;
for (offset in rawStops) {
if (rawStops.hasOwnProperty(offset)) {
offsets.push(parseInt(offset, 10));
colors.push(rawStops[offset].color);
opacities.push(rawStops[offset].opacity);
}
}
});
describe("first member", function() {
it("should have color inherited from raw gradient or equal to #ffffff", function() {
expect(member1.color).toBe(Ext.draw.Color.toHex(colors[0]) || "#ffffff");
});
it("should have offset inherited from raw gradient", function() {
expect(member1.offset).toBe(offsets[0]);
});
it("should have opacity inherited from raw gradient", function() {
expect(member1.opacity).toBe(opacities[0] || 1);
});
});
describe("second member", function() {
it("should have color inherited from raw gradient or equal to #ffffff", function() {
expect(member2.color).toBe(Ext.draw.Color.toHex(colors[1]) || "#ffffff");
});
it("should have offset inherited from raw gradient", function() {
expect(member2.offset).toBe(offsets[1]);
});
it("should have opacity inherited from raw gradient or equal to 1", function() {
expect(member2.opacity).toBe(opacities[1] || 1);
});
});
});
});
};
describe("with a linear gradient object passed as first argument", function() {
beforeEach(function() {
rawGradient = {
id: "linear-1",
angle: 45,
stops: {
0: {
color: "#0000ff",
opacity: 0.75
},
100: {
color: "#ff0000",
opacity: 1
}
}
};
gradient = Ext.draw.Draw.parseGradient(rawGradient);
});
describe("returned gradient", function() {
generateIdTypeAndStopSpec();
describe("vector property", function() {
var vector;
beforeEach(function() {
vector = gradient.vector;
});
it("should have an initial point in 0 0", function() {
expect([vector[0], vector[1]]).toEqual([0, 0]);
});
it("should have a termination point in 1 1", function() {
expect(1 - vector[2]).toEqualNumber(0);
expect(1 - vector[3]).toEqualNumber(0);
});
});
});
});
describe("with radial gradient object passed as first argument", function() {
beforeEach(function() {
rawGradient = {
id: "radial-1",
type: "radial",
centerX: 1,
centerY: 2,
focalX: 3,
focalY: 4,
radius: 20,
stops: {
0: {
opacity: 0.5
},
100: {
color: "rgb(255, 0, 0)"
}
}
};
gradient = Ext.draw.Draw.parseGradient(rawGradient);
});
describe("returned gradient", function() {
generateIdTypeAndStopSpec();
it("should have centerX property inherited from the passed object", function() {
expect(gradient.centerX).toEqual(rawGradient.centerX);
});
it("should have centerY property inherited from the passed object", function() {
expect(gradient.centerY).toEqual(rawGradient.centerY);
});
it("should have focalX property inherited from the passed object", function() {
expect(gradient.focalX).toEqual(rawGradient.focalX);
});
it("should have focalY property inherited from the passed object", function() {
expect(gradient.focalY).toEqual(rawGradient.focalY);
});
it("should have radius property inherited from the passed object", function() {
expect(gradient.radius).toEqual(rawGradient.radius);
});
it("should have an undefined vector property", function() {
expect(gradient.vector).toBe(undefined);
});
});
});
});
});