123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238 |
- (function() {
- // Code from http://stackoverflow.com/questions/4406864/html-canvas-unit-testing
- var Context = function() {
- this._calls = []; // names/args of recorded calls
- this._initMethods();
- this._fillStyle = null;
- this._lineCap = null;
- this._lineDashOffset = null;
- this._lineJoin = null;
- this._lineWidth = null;
- this._strokeStyle = null;
- // Define properties here so that we can record each time they are set
- Object.defineProperties(this, {
- "fillStyle": {
- 'get': function() { return this._fillStyle; },
- 'set': function(style) {
- this._fillStyle = style;
- this.record('setFillStyle', [style]);
- }
- },
- 'lineCap': {
- 'get': function() { return this._lineCap; },
- 'set': function(cap) {
- this._lineCap = cap;
- this.record('setLineCap', [cap]);
- }
- },
- 'lineDashOffset': {
- 'get': function() { return this._lineDashOffset; },
- 'set': function(offset) {
- this._lineDashOffset = offset;
- this.record('setLineDashOffset', [offset]);
- }
- },
- 'lineJoin': {
- 'get': function() { return this._lineJoin; },
- 'set': function(join) {
- this._lineJoin = join;
- this.record('setLineJoin', [join]);
- }
- },
- 'lineWidth': {
- 'get': function() { return this._lineWidth; },
- 'set': function (width) {
- this._lineWidth = width;
- this.record('setLineWidth', [width]);
- }
- },
- 'strokeStyle': {
- 'get': function() { return this._strokeStyle; },
- 'set': function(style) {
- this._strokeStyle = style;
- this.record('setStrokeStyle', [style]);
- }
- },
- });
- };
- Context.prototype._initMethods = function() {
- // define methods to test here
- // no way to introspect so we have to do some extra work :(
- var methods = {
- arc: function() {},
- beginPath: function() {},
- bezierCurveTo: function() {},
- clearRect: function() {},
- closePath: function() {},
- fill: function() {},
- fillRect: function() {},
- fillText: function() {},
- lineTo: function(x, y) {},
- measureText: function(text) {
- // return the number of characters * fixed size
- return text ? { width: text.length * 10 } : {width: 0};
- },
- moveTo: function(x, y) {},
- quadraticCurveTo: function() {},
- restore: function() {},
- rotate: function() {},
- save: function() {},
- setLineDash: function() {},
- stroke: function() {},
- strokeRect: function(x, y, w, h) {},
- setTransform: function(a, b, c, d, e, f) {},
- translate: function(x, y) {},
- };
- // attach methods to the class itself
- var scope = this;
- var addMethod = function(name, method) {
- scope[methodName] = function() {
- scope.record(name, arguments);
- return method.apply(scope, arguments);
- };
- }
- for (var methodName in methods) {
- var method = methods[methodName];
- addMethod(methodName, method);
- }
- };
- Context.prototype.record = function(methodName, args) {
- this._calls.push({
- name: methodName,
- args: Array.prototype.slice.call(args)
- });
- },
- Context.prototype.getCalls = function() {
- return this._calls;
- }
- Context.prototype.resetCalls = function() {
- this._calls = [];
- };
- window.createMockContext = function() {
- return new Context();
- };
- // Custom matcher
- function toBeCloseToPixel() {
- return {
- compare: function(actual, expected) {
- var result = false;
- if (!isNaN(actual) && !isNaN(expected)) {
- var diff = Math.abs(actual - expected);
- var A = Math.abs(actual);
- var B = Math.abs(expected);
- var percentDiff = 0.005; // 0.5% diff
- result = (diff <= (A > B ? A : B) * percentDiff) || diff < 2; // 2 pixels is fine
- }
- return { pass: result };
- }
- }
- };
- function toEqualOneOf() {
- return {
- compare: function(actual, expecteds) {
- var result = false;
- for (var i = 0, l = expecteds.length; i < l; i++) {
- if (actual === expecteds[i]) {
- result = true;
- break;
- }
- }
- return {
- pass: result
- };
- }
- };
- }
- window.addDefaultMatchers = function(jasmine) {
- jasmine.addMatchers({
- toBeCloseToPixel: toBeCloseToPixel,
- toEqualOneOf: toEqualOneOf
- });
- }
- // Canvas injection helpers
- var charts = {};
- function acquireChart(config, style) {
- var wrapper = document.createElement("div");
- var canvas = document.createElement("canvas");
- wrapper.className = 'chartjs-wrapper';
- style = style || { height: '512px', width: '512px' };
- for (var k in style) {
- wrapper.style[k] = style[k];
- canvas.style[k] = style[k];
- }
- canvas.height = canvas.style.height && parseInt(canvas.style.height);
- canvas.width = canvas.style.width && parseInt(canvas.style.width);
- // by default, remove chart animation and auto resize
- var options = config.options = config.options || {};
- options.animation = options.animation === undefined? false : options.animation;
- options.responsive = options.responsive === undefined? false : options.responsive;
- options.defaultFontFamily = options.defaultFontFamily || 'Arial';
- wrapper.appendChild(canvas);
- window.document.body.appendChild(wrapper);
- var chart = new Chart(canvas.getContext("2d"), config);
- charts[chart.id] = chart;
- return chart;
- }
- function releaseChart(chart) {
- chart.chart.canvas.parentNode.remove();
- delete charts[chart.id];
- delete chart;
- }
- function releaseAllCharts(scope) {
- for (var id in charts) {
- var chart = charts[id];
- releaseChart(chart);
- }
- }
- function injectCSS(css) {
- // http://stackoverflow.com/q/3922139
- var head = document.getElementsByTagName('head')[0];
- var style = document.createElement('style');
- style.setAttribute('type', 'text/css');
- if (style.styleSheet) { // IE
- style.styleSheet.cssText = css;
- } else {
- style.appendChild(document.createTextNode(css));
- }
- head.appendChild(style);
- }
- window.acquireChart = acquireChart;
- window.releaseChart = releaseChart;
- window.releaseAllCharts = releaseAllCharts;
- // some style initialization to limit differences between browsers across different plateforms.
- injectCSS(
- '.chartjs-wrapper, .chartjs-wrapper canvas {' +
- 'border: 0;' +
- 'margin: 0;' +
- 'padding: 0;' +
- '}' +
- '.chartjs-wrapper {' +
- 'position: absolute' +
- '}');
- })();
|