X-Git-Url: https://adrianiainlam.tk/git/?a=blobdiff_plain;f=auto_tests%2Ftests%2FCanvasAssertions.js;h=ef37fb9d54bf305dfec60e69660ff6457eb71cac;hb=ce31caf22475e3e1fd6d9fea192d61ff4fcd7fac;hp=cd9994d3962dba29dbec6aedd69a55ebc6d44ed3;hpb=644eff8b76ca1a39ac2841d4f76a46a32042f071;p=dygraphs.git diff --git a/auto_tests/tests/CanvasAssertions.js b/auto_tests/tests/CanvasAssertions.js index cd9994d..ef37fb9 100644 --- a/auto_tests/tests/CanvasAssertions.js +++ b/auto_tests/tests/CanvasAssertions.js @@ -1,4 +1,4 @@ -// Copyright (c) 2011 Google, Inc. +// Copyright (c) 2011 Google, Inc. // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal @@ -27,6 +27,36 @@ var CanvasAssertions = {}; /** + * Updates path attributes to match fill/stroke operations. + * + * This sets fillStyle to undefined for stroked paths, + * and strokeStyle to undefined for filled paths, to simplify + * matchers such as numLinesDrawn. + * + * @private + * @param {Array.} List of operations. + */ +CanvasAssertions.cleanPathAttrs_ = function(calls) { + var isStroked = true; + for (var i = calls.length - 1; i >= 0; --i) { + var call = calls[i]; + var name = call.name; + if (name == 'stroke') { + isStroked = true; + } else if (name == 'fill') { + isStroked = false; + } else if (name == 'lineTo') { + if (isStroked) { + call.properties.fillStyle = undefined; + } else { + call.properties.strokeStyle = undefined; + } + } + } +}; + + +/** * Assert that a line is drawn between the two points * * This merely looks for one of these four possibilities: @@ -35,15 +65,17 @@ var CanvasAssertions = {}; * lineTo(p1) -> lineTo(p2) * lineTo(p2) -> lineTo(p1) * - * attrs is meant to be used when you want to track things like - * color and stroke width. + * predicate is meant to be used when you want to track things like + * color and stroke width. It can either be a hash of context properties, + * or a function that accepts the current call. */ -CanvasAssertions.assertLineDrawn = function(proxy, p1, p2, attrs) { +CanvasAssertions.assertLineDrawn = function(proxy, p1, p2, predicate) { + CanvasAssertions.cleanPathAttrs_(proxy.calls__); // found = 1 when prior loop found p1. // found = 2 when prior loop found p2. var priorFound = 0; - for (var callNum in proxy.calls__) { - var call = proxy.calls__[callNum]; + for (var i = 0; i < proxy.calls__.length; i++) { + var call = proxy.calls__[i]; // This disables lineTo -> moveTo pairs. if (call.name == "moveTo" && priorFound > 0) { @@ -56,12 +88,14 @@ CanvasAssertions.assertLineDrawn = function(proxy, p1, p2, attrs) { var matchp2 = CanvasAssertions.matchPixels(p2, call.args); if (matchp1 || matchp2) { if (priorFound == 1 && matchp2) { -// TODO -- add property test here CanvasAssertions.matchAttributes(attrs, call.properties) - return; + if (CanvasAssertions.match(predicate, call)) { + return; + } } if (priorFound == 2 && matchp1) { - // TODO -- add property test here CanvasAssertions.matchAttributes(attrs, call.properties) - return; + if (CanvasAssertions.match(predicate, call)) { + return; + } } found = matchp1 ? 1 : 2; } @@ -81,8 +115,104 @@ CanvasAssertions.assertLineDrawn = function(proxy, p1, p2, attrs) { } return s + "}"; }; - fail("Can't find a line drawn between " + p1 + - " and " + p2 + " with attributes " + toString(attrs)); + throw "Can't find a line drawn between " + p1 + + " and " + p2 + " with attributes " + toString(predicate); +}; + +/** + * Return the lines drawn with specific attributes. + * + * This merely looks for one of these four possibilities: + * moveTo(p1) -> lineTo(p2) + * moveTo(p2) -> lineTo(p1) + * lineTo(p1) -> lineTo(p2) + * lineTo(p2) -> lineTo(p1) + * + * attrs is meant to be used when you want to track things like + * color and stroke width. + */ +CanvasAssertions.getLinesDrawn = function(proxy, predicate) { + CanvasAssertions.cleanPathAttrs_(proxy.calls__); + var lastCall; + var lines = []; + for (var i = 0; i < proxy.calls__.length; i++) { + var call = proxy.calls__[i]; + + if (call.name == "lineTo") { + if (lastCall != null) { + if (CanvasAssertions.match(predicate, call)) { + lines.push([lastCall, call]); + } + } + } + + lastCall = (call.name === "lineTo" || call.name === "moveTo") ? call : null; + } + return lines; +}; + +/** + * Verifies that every call to context.save() has a matching call to + * context.restore(). + */ +CanvasAssertions.assertBalancedSaveRestore = function(proxy) { + var depth = 0; + for (var i = 0; i < proxy.calls__.length; i++) { + var call = proxy.calls__[i]; + if (call.name == "save") depth++ + if (call.name == "restore") { + if (depth == 0) { + fail("Too many calls to restore()"); + } + depth--; + } + } + + if (depth > 0) { + fail("Missing matching 'context.restore()' calls."); + } +}; + +/** + * Checks how many lines of the given color have been drawn. + * @return {Integer} The number of lines of the given color. + */ +// TODO(konigsberg): change 'color' to predicate? color is the +// common case. Possibly allow predicate to be function, hash, or +// string representing color? +CanvasAssertions.numLinesDrawn = function(proxy, color) { + CanvasAssertions.cleanPathAttrs_(proxy.calls__); + var num_lines = 0; + var num_potential_calls = 0; + for (var i = 0; i < proxy.calls__.length; i++) { + var call = proxy.calls__[i]; + if (call.name == "beginPath") { + num_potential_calls = 0; + } else if (call.name == "lineTo") { + num_potential_calls++; + } else if (call.name == "stroke") { + // note: Don't simplify these two conditionals into one. The + // separation simplifies debugging tricky tests. + if (call.properties.strokeStyle == color) { + num_lines += num_potential_calls; + } + num_potential_calls = 0; + } + } + return num_lines; +}; + +/** + * Asserts that a series of lines are connected. For example, + * assertConsecutiveLinesDrawn(proxy, [[x1, y1], [x2, y2], [x3, y3]], predicate) + * is shorthand for + * assertLineDrawn(proxy, [x1, y1], [x2, y2], predicate) + * assertLineDrawn(proxy, [x2, y2], [x3, y3], predicate) + */ +CanvasAssertions.assertConsecutiveLinesDrawn = function(proxy, segments, predicate) { + for (var i = 0; i < segments.length - 1; i++) { + CanvasAssertions.assertLineDrawn(proxy, segments[i], segments[i+1], predicate); + } } CanvasAssertions.matchPixels = function(expected, actual) { @@ -91,13 +221,28 @@ CanvasAssertions.matchPixels = function(expected, actual) { // who knows what pixel a value of 5.8888 results in. return Math.abs(expected[0] - actual[0]) < 1 && Math.abs(expected[1] - actual[1]) < 1; -} +}; -CanvasAssertions.matchAttributes = function(expected, actual) { - for (var attr in expected) { - if (expected.hasOwnProperty(attr) && expected[attr] != actual[attr]) { - return false; +/** + * For matching a proxy call against defined conditions. + * predicate can either by a hash of items compared against call.properties, + * or it can be a function that accepts the call, and returns true or false. + * If it's null, this function returns true. + */ +CanvasAssertions.match = function(predicate, call) { + if (predicate === null) { + return true; + } + if (typeof(predicate) === "function") { + return predicate(call); + } else { + for (var attr in predicate) { + if (predicate.hasOwnProperty(attr) && predicate[attr] != call.properties[attr]) { + return false; + } } } return true; -} +}; + +export default CanvasAssertions;