From b710c1f76e6f7f6e98f7f4723c71f2710657f286 Mon Sep 17 00:00:00 2001 From: Andreas Hocevar Date: Wed, 16 Aug 2017 22:37:47 -0400 Subject: [PATCH 1/2] Use pixelmatch instead of resemble.js --- package.json | 2 +- test/.eslintrc | 2 +- test/README.md | 2 +- test/karma.config.js | 5 ++- test/module-global.js | 1 + test/test-extensions.js | 70 ++++++++++++++++++++++++----------------- 6 files changed, 49 insertions(+), 33 deletions(-) create mode 100644 test/module-global.js diff --git a/package.json b/package.json index 5f48b552dd..a7f9801826 100644 --- a/package.json +++ b/package.json @@ -75,8 +75,8 @@ "mocha-phantomjs-core": "^2.1.0", "mustache": "2.3.0", "phantomjs-prebuilt": "2.1.15", + "pixelmatch": "^4.0.2", "proj4": "2.4.4", - "resemblejs": "2.2.4", "serve-files": "1.0.1", "sinon": "3.2.0", "slimerjs": "0.10.3" diff --git a/test/.eslintrc b/test/.eslintrc index 272c7b2d05..16ed203115 100644 --- a/test/.eslintrc +++ b/test/.eslintrc @@ -14,7 +14,7 @@ "expect": false, "expectResemble": false, "proj4": false, - "resemble": false, + "pixelmatch": false, "resembleCanvas": false, "sinon": false, "where": false diff --git a/test/README.md b/test/README.md index 6f63717932..5bee5991ca 100644 --- a/test/README.md +++ b/test/README.md @@ -29,7 +29,7 @@ in Chrome by default). # Rendering tests The `test/rendering` directory contains rendering tests which compare a rendered map with a -reference image using [resemble.js](http://huddle.github.io/Resemble.js/). +reference image using [pixelmatch](https://github.com/mapbox/pixelmatch). To run the tests in the browser, make sure the development server is running (`make serve`) and open the URL diff --git a/test/karma.config.js b/test/karma.config.js index 7ad0d333aa..3dd92e325a 100644 --- a/test/karma.config.js +++ b/test/karma.config.js @@ -19,6 +19,9 @@ module.exports = function(karma) { }, files: [ { + pattern: 'module-global.js', + watched: false + }, { pattern: path.resolve(__dirname, require.resolve('jquery/dist/jquery.js')), watched: false }, { @@ -31,7 +34,7 @@ module.exports = function(karma) { pattern: path.resolve(__dirname, require.resolve('proj4/dist/proj4.js')), watched: false }, { - pattern: path.resolve(__dirname, require.resolve('resemblejs/resemble.js')), + pattern: path.resolve(__dirname, require.resolve('pixelmatch/index.js')), watched: false }, { pattern: path.resolve(__dirname, './test-extensions.js') diff --git a/test/module-global.js b/test/module-global.js new file mode 100644 index 0000000000..278a7771e0 --- /dev/null +++ b/test/module-global.js @@ -0,0 +1 @@ +window.module = {}; diff --git a/test/test-extensions.js b/test/test-extensions.js index 048cf42242..a1448d3272 100644 --- a/test/test-extensions.js +++ b/test/test-extensions.js @@ -386,35 +386,47 @@ goog.require('ol.renderer.webgl.Map'); }; function resembleCanvas(canvas, referenceImage, tolerance, done) { - if (showMap) { - var wrapper = document.createElement('div'); - wrapper.style.width = canvas.width + 'px'; - wrapper.style.height = canvas.height + 'px'; - wrapper.appendChild(canvas); - document.body.appendChild(wrapper); - document.body.appendChild(document.createTextNode(referenceImage)); - } - - resemble(referenceImage) - .compareTo(canvas.getContext('2d').getImageData( - 0, 0, canvas.width, canvas.height)) - .onComplete(function(data) { - if (!data.isSameDimensions) { - expect().fail( - 'The dimensions of the reference image and ' + - 'the test canvas are not the same.'); - } - - if (data.misMatchPercentage > tolerance) { - if (showDiff) { - var diffImage = new Image(); - diffImage.src = data.getImageDataUrl(); - document.body.appendChild(diffImage); - } - expect(data.misMatchPercentage).to.be.below(tolerance); - } - done(); - }); + var width = canvas.width; + var height = canvas.height; + var image = new Image(); + image.addEventListener('load', function() { + expect(image.width).to.be(width); + expect(image.height).to.be(height); + var referenceCanvas = document.createElement('CANVAS'); + referenceCanvas.width = image.width; + referenceCanvas.height = image.height; + var referenceContext = referenceCanvas.getContext('2d'); + referenceContext.drawImage(image, 0, 0, image.width, image.height); + if (showMap) { + var wrapper = document.createElement('div'); + wrapper.style.width = canvas.width + 'px'; + wrapper.style.height = canvas.height + 'px'; + wrapper.appendChild(canvas); + document.body.appendChild(wrapper); + document.body.appendChild(document.createTextNode(referenceImage)); + } + var context = canvas.getContext('2d'); + var output = context.createImageData(canvas.width, canvas.height); + var mismatchPx = pixelmatch( + context.getImageData(0, 0, width, height).data, + referenceContext.getImageData(0, 0, width, height).data, + output.data, width, height); + var mismatchPct = mismatchPx / (width * height) * 100; + if (showDiff && mismatchPct > tolerance) { + var diffCanvas = document.createElement('canvas'); + diffCanvas.width = width; + diffCanvas.height = height; + diffCanvas.getContext('2d').putImageData(output, 0, 0); + document.body.appendChild(diffCanvas); + } + expect(mismatchPct).to.be.below(tolerance); + done(); + }); + image.addEventListener('error', function() { + expect().fail('Reference image could not be loaded'); + done(); + }); + image.src = referenceImage; } global.resembleCanvas = resembleCanvas; From 55be9b8d3c45717452d756c19faaf19c28167d4c Mon Sep 17 00:00:00 2001 From: Andreas Hocevar Date: Wed, 16 Aug 2017 22:38:33 -0400 Subject: [PATCH 2/2] Use specific pixelRatio so tests run on all devices --- test/rendering/ol/layer/clip.test.js | 1 + test/rendering/ol/layer/image.test.js | 1 + test/rendering/ol/layer/vector.test.js | 15 +++++--- test/rendering/ol/layer/vectortile.test.js | 2 +- test/rendering/ol/map.test.js | 1 + test/rendering/ol/render.test.js | 40 ++++++++++++++++---- test/rendering/ol/style/circle.test.js | 1 + test/rendering/ol/style/icon.test.js | 1 + test/rendering/ol/style/polygon.test.js | 1 + test/rendering/ol/style/regularshape.test.js | 1 + test/rendering/ol/style/text.test.js | 1 + 11 files changed, 50 insertions(+), 15 deletions(-) diff --git a/test/rendering/ol/layer/clip.test.js b/test/rendering/ol/layer/clip.test.js index bcbb48f8e8..06a16ff697 100644 --- a/test/rendering/ol/layer/clip.test.js +++ b/test/rendering/ol/layer/clip.test.js @@ -41,6 +41,7 @@ describe('layer clipping', function() { var map = null; beforeEach(function() { map = new ol.Map({ + pixelRatio: 1, target: createMapDiv(256, 256), view: new ol.View({ center: [0, 0], diff --git a/test/rendering/ol/layer/image.test.js b/test/rendering/ol/layer/image.test.js index 75d9e5e5e7..429090329f 100644 --- a/test/rendering/ol/layer/image.test.js +++ b/test/rendering/ol/layer/image.test.js @@ -15,6 +15,7 @@ describe('ol.rendering.layer.Image', function() { function createMap(renderer) { map = new ol.Map({ + pixelRatio: 1, target: createMapDiv(50, 50), renderer: renderer, view: new ol.View({ diff --git a/test/rendering/ol/layer/vector.test.js b/test/rendering/ol/layer/vector.test.js index 558bc02535..911268ec89 100644 --- a/test/rendering/ol/layer/vector.test.js +++ b/test/rendering/ol/layer/vector.test.js @@ -21,6 +21,7 @@ describe('ol.rendering.layer.Vector', function() { var map; function createMap(renderer) { map = new ol.Map({ + pixelRatio: 1, target: createMapDiv(80, 80), renderer: renderer, view: new ol.View({ @@ -249,12 +250,12 @@ describe('ol.rendering.layer.Vector', function() { map.once('postrender', function() { var canvas = map.getRenderer().canvas_; // take a snapshot of this `overlaps: true` image - var referenceImage = canvas.getContext('2d').getImageData(0, 0, canvas.width, canvas.height); + var referenceImage = canvas.toDataURL('image/png'); // now render the same with `overlaps: false` layer.setSource(createSource(false)); - // result should be similar to `overlaps: true` - map.once('postrender', function() { - expectResemble(map, referenceImage, 2, done); + // result should be the same as with `overlaps: true` + map.once('postrender', function(e) { + expectResemble(map, referenceImage, 1e-9, done); }); }); }); @@ -300,12 +301,12 @@ describe('ol.rendering.layer.Vector', function() { map.once('postrender', function() { var canvas = map.getRenderer().canvas_; // take a snapshot of this `overlaps: true` image - var referenceImage = canvas.getContext('2d').getImageData(0, 0, canvas.width, canvas.height); + var referenceImage = canvas.toDataURL('image/png'); // now render the same with `overlaps: false` layer.setSource(createSource(false)); // result should be exactly the same as with `overlaps: true` map.once('postrender', function() { - expectResemble(map, referenceImage, 0, done); + expectResemble(map, referenceImage, 1e-9, done); }); }); }); @@ -316,6 +317,7 @@ describe('ol.rendering.layer.Vector', function() { var map2; beforeEach(function() { map2 = new ol.Map({ + pixelRatio: 1, target: createMapDiv(128, 128), view: new ol.View({ center: [0, 0], @@ -404,6 +406,7 @@ describe('ol.rendering.layer.Vector', function() { }); map3 = new ol.Map({ + pixelRatio: 1, layers: [layer], target: createMapDiv(100, 100), view: view diff --git a/test/rendering/ol/layer/vectortile.test.js b/test/rendering/ol/layer/vectortile.test.js index a2b8956cca..7b1fa81b7d 100644 --- a/test/rendering/ol/layer/vectortile.test.js +++ b/test/rendering/ol/layer/vectortile.test.js @@ -15,7 +15,7 @@ describe('ol.rendering.layer.VectorTile', function() { function createMap(renderer, opt_pixelRatio) { map = new ol.Map({ - pixelRatio: opt_pixelRatio, + pixelRatio: opt_pixelRatio || 1, target: createMapDiv(50, 50), renderer: renderer, view: new ol.View({ diff --git a/test/rendering/ol/map.test.js b/test/rendering/ol/map.test.js index 755805a6c0..4ee85404e5 100644 --- a/test/rendering/ol/map.test.js +++ b/test/rendering/ol/map.test.js @@ -21,6 +21,7 @@ describe('ol.rendering.Map', function() { }); map = new ol.Map({ + pixelRatio: 1, target: createMapDiv(50, 50), renderer: renderer, layers: [vectorLayer], diff --git a/test/rendering/ol/render.test.js b/test/rendering/ol/render.test.js index 80b92578dd..6c7358b955 100644 --- a/test/rendering/ol/render.test.js +++ b/test/rendering/ol/render.test.js @@ -20,14 +20,20 @@ describe('ol.render', function() { describe('ol.render.toContext()', function() { it('creates a vector context from a Canvas 2d context', function() { - var vectorContext = ol.render.toContext(getContext(), {size: [100, 100]}); + var vectorContext = ol.render.toContext(getContext(), { + pixelRatio: 1, + size: [100, 100] + }); expect(vectorContext).to.be.a(ol.render.VectorContext); expect(vectorContext).to.be.a(ol.render.canvas.Immediate); }); it('can be used to render a point geometry', function(done) { var context = getContext(); - var vectorContext = ol.render.toContext(context, {size: [100, 100]}); + var vectorContext = ol.render.toContext(context, { + pixelRatio: 1, + size: [100, 100] + }); var style = new ol.style.Style({ image: new ol.style.Circle({ @@ -48,7 +54,10 @@ describe('ol.render', function() { it('can be used to render a linestring geometry', function(done) { var context = getContext(); - var vectorContext = ol.render.toContext(context, {size: [100, 100]}); + var vectorContext = ol.render.toContext(context, { + pixelRatio: 1, + size: [100, 100] + }); var style = new ol.style.Style({ stroke: new ol.style.Stroke({ @@ -69,7 +78,10 @@ describe('ol.render', function() { it('respects lineCap for linestring', function(done) { var context = getContext(); - var vectorContext = ol.render.toContext(context, {size: [100, 100]}); + var vectorContext = ol.render.toContext(context, { + pixelRatio: 1, + size: [100, 100] + }); var style = new ol.style.Style({ stroke: new ol.style.Stroke({ @@ -91,7 +103,10 @@ describe('ol.render', function() { it('respects lineJoin for linestring', function(done) { var context = getContext(); - var vectorContext = ol.render.toContext(context, {size: [100, 100]}); + var vectorContext = ol.render.toContext(context, { + pixelRatio: 1, + size: [100, 100] + }); var style = new ol.style.Style({ stroke: new ol.style.Stroke({ @@ -113,7 +128,10 @@ describe('ol.render', function() { it('can be used to render a polygon geometry', function(done) { var context = getContext(); - var vectorContext = ol.render.toContext(context, {size: [100, 100]}); + var vectorContext = ol.render.toContext(context, { + pixelRatio: 1, + size: [100, 100] + }); var style = new ol.style.Style({ stroke: new ol.style.Stroke({ @@ -139,7 +157,10 @@ describe('ol.render', function() { it('supports lineDash styles', function(done) { var context = getContext(); - var vectorContext = ol.render.toContext(context, {size: [100, 100]}); + var vectorContext = ol.render.toContext(context, { + pixelRatio: 1, + size: [100, 100] + }); var style = new ol.style.Style({ stroke: new ol.style.Stroke({ @@ -161,7 +182,10 @@ describe('ol.render', function() { it('supports lineDashOffset', function(done) { var context = getContext(); - var vectorContext = ol.render.toContext(context, {size: [100, 100]}); + var vectorContext = ol.render.toContext(context, { + pixelRatio: 1, + size: [100, 100] + }); var style = new ol.style.Style({ stroke: new ol.style.Stroke({ diff --git a/test/rendering/ol/style/circle.test.js b/test/rendering/ol/style/circle.test.js index 2392a07c77..f67d41327b 100644 --- a/test/rendering/ol/style/circle.test.js +++ b/test/rendering/ol/style/circle.test.js @@ -23,6 +23,7 @@ describe('ol.rendering.style.Circle', function() { }); map = new ol.Map({ + pixelRatio: 1, target: createMapDiv(50, 50), renderer: renderer, layers: [vectorLayer], diff --git a/test/rendering/ol/style/icon.test.js b/test/rendering/ol/style/icon.test.js index 9db2f15d6a..64079e5d60 100644 --- a/test/rendering/ol/style/icon.test.js +++ b/test/rendering/ol/style/icon.test.js @@ -30,6 +30,7 @@ describe('ol.rendering.style.Icon', function() { }); map = new ol.Map({ + pixelRatio: 1, target: createMapDiv(width ? width : 50, height ? height : 50), renderer: renderer, layers: [vectorLayer], diff --git a/test/rendering/ol/style/polygon.test.js b/test/rendering/ol/style/polygon.test.js index 1974077206..8d2f58ae1d 100644 --- a/test/rendering/ol/style/polygon.test.js +++ b/test/rendering/ol/style/polygon.test.js @@ -24,6 +24,7 @@ describe('ol.rendering.style.Polygon', function() { }); map = new ol.Map({ + pixelRatio: 1, target: createMapDiv(size, size), renderer: renderer, layers: [vectorLayer], diff --git a/test/rendering/ol/style/regularshape.test.js b/test/rendering/ol/style/regularshape.test.js index e0da26e6ab..b3c55f6476 100644 --- a/test/rendering/ol/style/regularshape.test.js +++ b/test/rendering/ol/style/regularshape.test.js @@ -23,6 +23,7 @@ describe('ol.rendering.style.RegularShape', function() { }); map = new ol.Map({ + pixelRatio: 1, target: createMapDiv(50, 50), renderer: renderer, layers: [vectorLayer], diff --git a/test/rendering/ol/style/text.test.js b/test/rendering/ol/style/text.test.js index ec6ea416e5..9c87b465d7 100644 --- a/test/rendering/ol/style/text.test.js +++ b/test/rendering/ol/style/text.test.js @@ -22,6 +22,7 @@ describe('ol.rendering.style.Text', function() { }); map = new ol.Map({ + pixelRatio: 1, target: createMapDiv(200, 200), renderer: renderer, layers: [vectorLayer],