Merge pull request #7138 from ahocevar/pixelmatch-pixelratio
Improvements to the new test setup
This commit is contained in:
+1
-1
@@ -75,8 +75,8 @@
|
|||||||
"mocha-phantomjs-core": "^2.1.0",
|
"mocha-phantomjs-core": "^2.1.0",
|
||||||
"mustache": "2.3.0",
|
"mustache": "2.3.0",
|
||||||
"phantomjs-prebuilt": "2.1.15",
|
"phantomjs-prebuilt": "2.1.15",
|
||||||
|
"pixelmatch": "^4.0.2",
|
||||||
"proj4": "2.4.4",
|
"proj4": "2.4.4",
|
||||||
"resemblejs": "2.2.4",
|
|
||||||
"serve-files": "1.0.1",
|
"serve-files": "1.0.1",
|
||||||
"sinon": "3.2.0",
|
"sinon": "3.2.0",
|
||||||
"slimerjs": "0.10.3"
|
"slimerjs": "0.10.3"
|
||||||
|
|||||||
+1
-1
@@ -14,7 +14,7 @@
|
|||||||
"expect": false,
|
"expect": false,
|
||||||
"expectResemble": false,
|
"expectResemble": false,
|
||||||
"proj4": false,
|
"proj4": false,
|
||||||
"resemble": false,
|
"pixelmatch": false,
|
||||||
"resembleCanvas": false,
|
"resembleCanvas": false,
|
||||||
"sinon": false,
|
"sinon": false,
|
||||||
"where": false
|
"where": false
|
||||||
|
|||||||
+1
-1
@@ -29,7 +29,7 @@ in Chrome by default).
|
|||||||
# Rendering tests
|
# Rendering tests
|
||||||
|
|
||||||
The `test/rendering` directory contains rendering tests which compare a rendered map with a
|
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
|
To run the tests in the browser, make sure the development server is running
|
||||||
(`make serve`) and open the URL
|
(`make serve`) and open the URL
|
||||||
|
|||||||
@@ -19,6 +19,9 @@ module.exports = function(karma) {
|
|||||||
},
|
},
|
||||||
files: [
|
files: [
|
||||||
{
|
{
|
||||||
|
pattern: 'module-global.js',
|
||||||
|
watched: false
|
||||||
|
}, {
|
||||||
pattern: path.resolve(__dirname, require.resolve('jquery/dist/jquery.js')),
|
pattern: path.resolve(__dirname, require.resolve('jquery/dist/jquery.js')),
|
||||||
watched: false
|
watched: false
|
||||||
}, {
|
}, {
|
||||||
@@ -31,7 +34,7 @@ module.exports = function(karma) {
|
|||||||
pattern: path.resolve(__dirname, require.resolve('proj4/dist/proj4.js')),
|
pattern: path.resolve(__dirname, require.resolve('proj4/dist/proj4.js')),
|
||||||
watched: false
|
watched: false
|
||||||
}, {
|
}, {
|
||||||
pattern: path.resolve(__dirname, require.resolve('resemblejs/resemble.js')),
|
pattern: path.resolve(__dirname, require.resolve('pixelmatch/index.js')),
|
||||||
watched: false
|
watched: false
|
||||||
}, {
|
}, {
|
||||||
pattern: path.resolve(__dirname, './test-extensions.js')
|
pattern: path.resolve(__dirname, './test-extensions.js')
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
window.module = {};
|
||||||
@@ -41,6 +41,7 @@ describe('layer clipping', function() {
|
|||||||
var map = null;
|
var map = null;
|
||||||
beforeEach(function() {
|
beforeEach(function() {
|
||||||
map = new ol.Map({
|
map = new ol.Map({
|
||||||
|
pixelRatio: 1,
|
||||||
target: createMapDiv(256, 256),
|
target: createMapDiv(256, 256),
|
||||||
view: new ol.View({
|
view: new ol.View({
|
||||||
center: [0, 0],
|
center: [0, 0],
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ describe('ol.rendering.layer.Image', function() {
|
|||||||
|
|
||||||
function createMap(renderer) {
|
function createMap(renderer) {
|
||||||
map = new ol.Map({
|
map = new ol.Map({
|
||||||
|
pixelRatio: 1,
|
||||||
target: createMapDiv(50, 50),
|
target: createMapDiv(50, 50),
|
||||||
renderer: renderer,
|
renderer: renderer,
|
||||||
view: new ol.View({
|
view: new ol.View({
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ describe('ol.rendering.layer.Vector', function() {
|
|||||||
var map;
|
var map;
|
||||||
function createMap(renderer) {
|
function createMap(renderer) {
|
||||||
map = new ol.Map({
|
map = new ol.Map({
|
||||||
|
pixelRatio: 1,
|
||||||
target: createMapDiv(80, 80),
|
target: createMapDiv(80, 80),
|
||||||
renderer: renderer,
|
renderer: renderer,
|
||||||
view: new ol.View({
|
view: new ol.View({
|
||||||
@@ -249,12 +250,12 @@ describe('ol.rendering.layer.Vector', function() {
|
|||||||
map.once('postrender', function() {
|
map.once('postrender', function() {
|
||||||
var canvas = map.getRenderer().canvas_;
|
var canvas = map.getRenderer().canvas_;
|
||||||
// take a snapshot of this `overlaps: true` image
|
// 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`
|
// now render the same with `overlaps: false`
|
||||||
layer.setSource(createSource(false));
|
layer.setSource(createSource(false));
|
||||||
// result should be similar to `overlaps: true`
|
// result should be the same as with `overlaps: true`
|
||||||
map.once('postrender', function() {
|
map.once('postrender', function(e) {
|
||||||
expectResemble(map, referenceImage, 2, done);
|
expectResemble(map, referenceImage, 1e-9, done);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -300,12 +301,12 @@ describe('ol.rendering.layer.Vector', function() {
|
|||||||
map.once('postrender', function() {
|
map.once('postrender', function() {
|
||||||
var canvas = map.getRenderer().canvas_;
|
var canvas = map.getRenderer().canvas_;
|
||||||
// take a snapshot of this `overlaps: true` image
|
// 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`
|
// now render the same with `overlaps: false`
|
||||||
layer.setSource(createSource(false));
|
layer.setSource(createSource(false));
|
||||||
// result should be exactly the same as with `overlaps: true`
|
// result should be exactly the same as with `overlaps: true`
|
||||||
map.once('postrender', function() {
|
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;
|
var map2;
|
||||||
beforeEach(function() {
|
beforeEach(function() {
|
||||||
map2 = new ol.Map({
|
map2 = new ol.Map({
|
||||||
|
pixelRatio: 1,
|
||||||
target: createMapDiv(128, 128),
|
target: createMapDiv(128, 128),
|
||||||
view: new ol.View({
|
view: new ol.View({
|
||||||
center: [0, 0],
|
center: [0, 0],
|
||||||
@@ -404,6 +406,7 @@ describe('ol.rendering.layer.Vector', function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
map3 = new ol.Map({
|
map3 = new ol.Map({
|
||||||
|
pixelRatio: 1,
|
||||||
layers: [layer],
|
layers: [layer],
|
||||||
target: createMapDiv(100, 100),
|
target: createMapDiv(100, 100),
|
||||||
view: view
|
view: view
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ describe('ol.rendering.layer.VectorTile', function() {
|
|||||||
|
|
||||||
function createMap(renderer, opt_pixelRatio) {
|
function createMap(renderer, opt_pixelRatio) {
|
||||||
map = new ol.Map({
|
map = new ol.Map({
|
||||||
pixelRatio: opt_pixelRatio,
|
pixelRatio: opt_pixelRatio || 1,
|
||||||
target: createMapDiv(50, 50),
|
target: createMapDiv(50, 50),
|
||||||
renderer: renderer,
|
renderer: renderer,
|
||||||
view: new ol.View({
|
view: new ol.View({
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ describe('ol.rendering.Map', function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
map = new ol.Map({
|
map = new ol.Map({
|
||||||
|
pixelRatio: 1,
|
||||||
target: createMapDiv(50, 50),
|
target: createMapDiv(50, 50),
|
||||||
renderer: renderer,
|
renderer: renderer,
|
||||||
layers: [vectorLayer],
|
layers: [vectorLayer],
|
||||||
|
|||||||
@@ -20,14 +20,20 @@ describe('ol.render', function() {
|
|||||||
describe('ol.render.toContext()', function() {
|
describe('ol.render.toContext()', function() {
|
||||||
|
|
||||||
it('creates a vector context from a Canvas 2d context', 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.VectorContext);
|
||||||
expect(vectorContext).to.be.a(ol.render.canvas.Immediate);
|
expect(vectorContext).to.be.a(ol.render.canvas.Immediate);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('can be used to render a point geometry', function(done) {
|
it('can be used to render a point geometry', function(done) {
|
||||||
var context = getContext();
|
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({
|
var style = new ol.style.Style({
|
||||||
image: new ol.style.Circle({
|
image: new ol.style.Circle({
|
||||||
@@ -48,7 +54,10 @@ describe('ol.render', function() {
|
|||||||
|
|
||||||
it('can be used to render a linestring geometry', function(done) {
|
it('can be used to render a linestring geometry', function(done) {
|
||||||
var context = getContext();
|
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({
|
var style = new ol.style.Style({
|
||||||
stroke: new ol.style.Stroke({
|
stroke: new ol.style.Stroke({
|
||||||
@@ -69,7 +78,10 @@ describe('ol.render', function() {
|
|||||||
|
|
||||||
it('respects lineCap for linestring', function(done) {
|
it('respects lineCap for linestring', function(done) {
|
||||||
var context = getContext();
|
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({
|
var style = new ol.style.Style({
|
||||||
stroke: new ol.style.Stroke({
|
stroke: new ol.style.Stroke({
|
||||||
@@ -91,7 +103,10 @@ describe('ol.render', function() {
|
|||||||
|
|
||||||
it('respects lineJoin for linestring', function(done) {
|
it('respects lineJoin for linestring', function(done) {
|
||||||
var context = getContext();
|
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({
|
var style = new ol.style.Style({
|
||||||
stroke: new ol.style.Stroke({
|
stroke: new ol.style.Stroke({
|
||||||
@@ -113,7 +128,10 @@ describe('ol.render', function() {
|
|||||||
|
|
||||||
it('can be used to render a polygon geometry', function(done) {
|
it('can be used to render a polygon geometry', function(done) {
|
||||||
var context = getContext();
|
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({
|
var style = new ol.style.Style({
|
||||||
stroke: new ol.style.Stroke({
|
stroke: new ol.style.Stroke({
|
||||||
@@ -139,7 +157,10 @@ describe('ol.render', function() {
|
|||||||
|
|
||||||
it('supports lineDash styles', function(done) {
|
it('supports lineDash styles', function(done) {
|
||||||
var context = getContext();
|
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({
|
var style = new ol.style.Style({
|
||||||
stroke: new ol.style.Stroke({
|
stroke: new ol.style.Stroke({
|
||||||
@@ -161,7 +182,10 @@ describe('ol.render', function() {
|
|||||||
|
|
||||||
it('supports lineDashOffset', function(done) {
|
it('supports lineDashOffset', function(done) {
|
||||||
var context = getContext();
|
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({
|
var style = new ol.style.Style({
|
||||||
stroke: new ol.style.Stroke({
|
stroke: new ol.style.Stroke({
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ describe('ol.rendering.style.Circle', function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
map = new ol.Map({
|
map = new ol.Map({
|
||||||
|
pixelRatio: 1,
|
||||||
target: createMapDiv(50, 50),
|
target: createMapDiv(50, 50),
|
||||||
renderer: renderer,
|
renderer: renderer,
|
||||||
layers: [vectorLayer],
|
layers: [vectorLayer],
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ describe('ol.rendering.style.Icon', function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
map = new ol.Map({
|
map = new ol.Map({
|
||||||
|
pixelRatio: 1,
|
||||||
target: createMapDiv(width ? width : 50, height ? height : 50),
|
target: createMapDiv(width ? width : 50, height ? height : 50),
|
||||||
renderer: renderer,
|
renderer: renderer,
|
||||||
layers: [vectorLayer],
|
layers: [vectorLayer],
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ describe('ol.rendering.style.Polygon', function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
map = new ol.Map({
|
map = new ol.Map({
|
||||||
|
pixelRatio: 1,
|
||||||
target: createMapDiv(size, size),
|
target: createMapDiv(size, size),
|
||||||
renderer: renderer,
|
renderer: renderer,
|
||||||
layers: [vectorLayer],
|
layers: [vectorLayer],
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ describe('ol.rendering.style.RegularShape', function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
map = new ol.Map({
|
map = new ol.Map({
|
||||||
|
pixelRatio: 1,
|
||||||
target: createMapDiv(50, 50),
|
target: createMapDiv(50, 50),
|
||||||
renderer: renderer,
|
renderer: renderer,
|
||||||
layers: [vectorLayer],
|
layers: [vectorLayer],
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ describe('ol.rendering.style.Text', function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
map = new ol.Map({
|
map = new ol.Map({
|
||||||
|
pixelRatio: 1,
|
||||||
target: createMapDiv(200, 200),
|
target: createMapDiv(200, 200),
|
||||||
renderer: renderer,
|
renderer: renderer,
|
||||||
layers: [vectorLayer],
|
layers: [vectorLayer],
|
||||||
|
|||||||
+41
-29
@@ -386,35 +386,47 @@ goog.require('ol.renderer.webgl.Map');
|
|||||||
};
|
};
|
||||||
|
|
||||||
function resembleCanvas(canvas, referenceImage, tolerance, done) {
|
function resembleCanvas(canvas, referenceImage, tolerance, done) {
|
||||||
if (showMap) {
|
var width = canvas.width;
|
||||||
var wrapper = document.createElement('div');
|
var height = canvas.height;
|
||||||
wrapper.style.width = canvas.width + 'px';
|
var image = new Image();
|
||||||
wrapper.style.height = canvas.height + 'px';
|
image.addEventListener('load', function() {
|
||||||
wrapper.appendChild(canvas);
|
expect(image.width).to.be(width);
|
||||||
document.body.appendChild(wrapper);
|
expect(image.height).to.be(height);
|
||||||
document.body.appendChild(document.createTextNode(referenceImage));
|
var referenceCanvas = document.createElement('CANVAS');
|
||||||
}
|
referenceCanvas.width = image.width;
|
||||||
|
referenceCanvas.height = image.height;
|
||||||
resemble(referenceImage)
|
var referenceContext = referenceCanvas.getContext('2d');
|
||||||
.compareTo(canvas.getContext('2d').getImageData(
|
referenceContext.drawImage(image, 0, 0, image.width, image.height);
|
||||||
0, 0, canvas.width, canvas.height))
|
if (showMap) {
|
||||||
.onComplete(function(data) {
|
var wrapper = document.createElement('div');
|
||||||
if (!data.isSameDimensions) {
|
wrapper.style.width = canvas.width + 'px';
|
||||||
expect().fail(
|
wrapper.style.height = canvas.height + 'px';
|
||||||
'The dimensions of the reference image and ' +
|
wrapper.appendChild(canvas);
|
||||||
'the test canvas are not the same.');
|
document.body.appendChild(wrapper);
|
||||||
}
|
document.body.appendChild(document.createTextNode(referenceImage));
|
||||||
|
}
|
||||||
if (data.misMatchPercentage > tolerance) {
|
var context = canvas.getContext('2d');
|
||||||
if (showDiff) {
|
var output = context.createImageData(canvas.width, canvas.height);
|
||||||
var diffImage = new Image();
|
var mismatchPx = pixelmatch(
|
||||||
diffImage.src = data.getImageDataUrl();
|
context.getImageData(0, 0, width, height).data,
|
||||||
document.body.appendChild(diffImage);
|
referenceContext.getImageData(0, 0, width, height).data,
|
||||||
}
|
output.data, width, height);
|
||||||
expect(data.misMatchPercentage).to.be.below(tolerance);
|
var mismatchPct = mismatchPx / (width * height) * 100;
|
||||||
}
|
if (showDiff && mismatchPct > tolerance) {
|
||||||
done();
|
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;
|
global.resembleCanvas = resembleCanvas;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user