1 // Copyright (c) 2011 Google, Inc.
3 // Permission is hereby granted, free of charge, to any person obtaining a copy
4 // of this software and associated documentation files (the "Software"), to deal
5 // in the Software without restriction, including without limitation the rights
6 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 // copies of the Software, and to permit persons to whom the Software is
8 // furnished to do so, subject to the following conditions:
10 // The above copyright notice and this permission notice shall be included in
11 // all copies or substantial portions of the Software.
13 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * @fileoverview Assertions and other code used to test a canvas proxy.
24 * @author konigsberg@google.com (Robert Konigsberg)
27 var CanvasAssertions
= {};
30 * Assert that a line is drawn between the two points
32 * This merely looks for one of these four possibilities:
33 * moveTo(p1) -> lineTo(p2)
34 * moveTo(p2) -> lineTo(p1)
35 * lineTo(p1) -> lineTo(p2)
36 * lineTo(p2) -> lineTo(p1)
38 * predicate is meant to be used when you want to track things like
39 * color and stroke width. It can either be a hash of context properties,
40 * or a function that accepts the current call.
42 CanvasAssertions
.assertLineDrawn
= function(proxy
, p1
, p2
, predicate
) {
43 // found = 1 when prior loop found p1.
44 // found = 2 when prior loop found p2.
46 for (var i
= 0; i
< proxy
.calls__
.length
; i
++) {
47 var call
= proxy
.calls__
[i
];
49 // This disables lineTo -> moveTo pairs.
50 if (call
.name
== "moveTo" && priorFound
> 0) {
55 if (call
.name
== "moveTo" || call
.name
== "lineTo") {
56 var matchp1
= CanvasAssertions
.matchPixels(p1
, call
.args
);
57 var matchp2
= CanvasAssertions
.matchPixels(p2
, call
.args
);
58 if (matchp1
|| matchp2
) {
59 if (priorFound
== 1 && matchp2
) {
60 if (CanvasAssertions
.match(predicate
, call
)) {
64 if (priorFound
== 2 && matchp1
) {
65 if (CanvasAssertions
.match(predicate
, call
.properties
)) {
69 found
= matchp1
? 1 : 2;
75 var toString
= function(x
) {
78 if (x
.hasOwnProperty(prop
)) {
82 s
= s
+ prop
+ ": " + x
[prop
];
87 fail("Can't find a line drawn between " + p1
+
88 " and " + p2
+ " with attributes " + toString(attrs
));
92 * Return the lines drawn with specific attributes.
94 * This merely looks for one of these four possibilities:
95 * moveTo(p1) -> lineTo(p2)
96 * moveTo(p2) -> lineTo(p1)
97 * lineTo(p1) -> lineTo(p2)
98 * lineTo(p2) -> lineTo(p1)
100 * attrs is meant to be used when you want to track things like
101 * color and stroke width.
103 CanvasAssertions
.getLinesDrawn
= function(proxy
, predicate
) {
106 for (var i
= 0; i
< proxy
.calls__
.length
; i
++) {
107 var call
= proxy
.calls__
[i
];
109 if (call
.name
== "lineTo") {
110 if (lastCall
!= null) {
111 if (!predicate
|| predicate(lastCall
, call
)) {
112 lines
.push([lastCall
, call
]);
117 lastCall
= (call
.name
=== "lineTo" || call
.name
=== "moveTo") ? call
: null;
123 * Verifies that every call to context.save() has a matching call to
126 CanvasAssertions
.assertBalancedSaveRestore
= function(proxy
) {
128 for (var i
= 0; i
< proxy
.calls__
.length
; i
++) {
129 var call
= proxy
.calls__
[i
];
130 if (call
.name
== "save") depth
++
131 if (call
.name
== "restore") {
133 fail("Too many calls to restore()");
140 fail("Missing matching 'context.restore()' calls.");
145 * Checks how many lines of the given color have been drawn.
146 * @return {Integer} The number of lines of the given color.
148 // TODO(konigsberg): change 'color' to predicate? color is the
149 // common case. Possibly allow predicate to be function, hash, or
150 // string representing color?
151 CanvasAssertions
.numLinesDrawn
= function(proxy
, color
) {
153 for (var i
= 0; i
< proxy
.calls__
.length
; i
++) {
154 var call
= proxy
.calls__
[i
];
155 if (call
.name
== "lineTo" && call
.properties
.strokeStyle
== color
) {
162 CanvasAssertions
.matchPixels
= function(expected
, actual
) {
163 // Expect array of two integers. Assuming the values are within one
164 // integer unit of each other. This should be tightened down by someone
165 // who knows what pixel a value of 5.8888 results in.
166 return Math
.abs(expected
[0] - actual
[0]) < 1 &&
167 Math
.abs(expected
[1] - actual
[1]) < 1;
171 * For matching a proxy call against defined conditions.
172 * predicate can either by a hash of items compared against call.properties,
173 * or it can be a function that accepts the call, and returns true or false.
175 CanvasAssertions
.match
= function(predicate
, call
) {
176 if (typeof(predicate
) === "function") {
177 return predicate(call
);
179 for (var attr
in predicate
) {
180 if (predicate
.hasOwnProperty(attr
) && predicate
[attr
] != call
.properties
[attr
]) {