Merge pull request #8903 from tschaub/rendering-tests
Additional render tests
@@ -79,6 +79,7 @@
|
||||
"proj4": "2.5.0",
|
||||
"puppeteer": "^1.10.0",
|
||||
"rollup": "0.67.0",
|
||||
"serve-static": "^1.13.2",
|
||||
"sinon": "^6.0.0",
|
||||
"typescript": "^3.1.0-dev.20180905",
|
||||
"uglifyjs-webpack-plugin": "^2.0.1",
|
||||
|
||||
BIN
rendering/cases/icon-symbol/expected.png
Normal file
|
After Width: | Height: | Size: 44 KiB |
22
rendering/cases/icon-symbol/index.html
Normal file
@@ -0,0 +1,22 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<style>
|
||||
html, body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
#map {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="map"></div>
|
||||
<script src="main.js"></script>
|
||||
</body>
|
||||
</script>
|
||||
</html>
|
||||
44
rendering/cases/icon-symbol/main.js
Normal file
@@ -0,0 +1,44 @@
|
||||
import Map from '../../../src/ol/Map.js';
|
||||
import View from '../../../src/ol/View.js';
|
||||
import {Vector as VectorLayer, Tile as TileLayer} from '../../../src/ol/layer.js';
|
||||
import {Vector as VectorSource, OSM} from '../../../src/ol/source.js';
|
||||
import Point from '../../../src/ol/geom/Point.js';
|
||||
import Feature from '../../../src/ol/Feature.js';
|
||||
import {fromLonLat} from '../../../src/ol/proj.js';
|
||||
import {Style, Icon} from '../../../src/ol/style.js';
|
||||
|
||||
const center = fromLonLat([8.6, 50.1]);
|
||||
|
||||
new Map({
|
||||
layers: [
|
||||
new TileLayer({
|
||||
source: new OSM()
|
||||
}),
|
||||
new VectorLayer({
|
||||
style: function() {
|
||||
return new Style({
|
||||
image: new Icon({
|
||||
src: '/data/icon.png',
|
||||
anchor: [0.5, 46],
|
||||
anchorXUnits: 'fraction',
|
||||
anchorYUnits: 'pixels'
|
||||
})
|
||||
});
|
||||
},
|
||||
source: new VectorSource({
|
||||
features: [
|
||||
new Feature(
|
||||
new Point(center)
|
||||
)
|
||||
]
|
||||
})
|
||||
})
|
||||
],
|
||||
target: 'map',
|
||||
view: new View({
|
||||
center: center,
|
||||
zoom: 3
|
||||
})
|
||||
});
|
||||
|
||||
render();
|
||||
BIN
rendering/cases/rotated-view/expected.png
Normal file
|
After Width: | Height: | Size: 13 KiB |
22
rendering/cases/rotated-view/index.html
Normal file
@@ -0,0 +1,22 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<style>
|
||||
html, body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
#map {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="map"></div>
|
||||
<script src="main.js"></script>
|
||||
</body>
|
||||
</script>
|
||||
</html>
|
||||
34
rendering/cases/rotated-view/main.js
Normal file
@@ -0,0 +1,34 @@
|
||||
import Map from '../../../src/ol/Map.js';
|
||||
import View from '../../../src/ol/View.js';
|
||||
import {Vector as VectorLayer, Tile as TileLayer} from '../../../src/ol/layer.js';
|
||||
import {Vector as VectorSource, OSM} from '../../../src/ol/source.js';
|
||||
import Point from '../../../src/ol/geom/Point.js';
|
||||
import Feature from '../../../src/ol/Feature.js';
|
||||
import {fromLonLat} from '../../../src/ol/proj.js';
|
||||
|
||||
const center = fromLonLat([-111, 45.7]);
|
||||
|
||||
new Map({
|
||||
layers: [
|
||||
new TileLayer({
|
||||
source: new OSM()
|
||||
}),
|
||||
new VectorLayer({
|
||||
source: new VectorSource({
|
||||
features: [
|
||||
new Feature(
|
||||
new Point(center)
|
||||
)
|
||||
]
|
||||
})
|
||||
})
|
||||
],
|
||||
target: 'map',
|
||||
view: new View({
|
||||
center: center,
|
||||
zoom: 4,
|
||||
rotation: Math.PI / 4
|
||||
})
|
||||
});
|
||||
|
||||
render();
|
||||
BIN
rendering/data/icon.png
Normal file
|
After Width: | Height: | Size: 2.5 KiB |
@@ -2,7 +2,7 @@
|
||||
const puppeteer = require('puppeteer');
|
||||
const webpack = require('webpack');
|
||||
const config = require('./webpack.config');
|
||||
const middleware = require('webpack-dev-middleware');
|
||||
const webpackMiddleware = require('webpack-dev-middleware');
|
||||
const http = require('http');
|
||||
const path = require('path');
|
||||
const png = require('pngjs');
|
||||
@@ -12,6 +12,7 @@ const pixelmatch = require('pixelmatch');
|
||||
const yargs = require('yargs');
|
||||
const log = require('loglevelnext');
|
||||
const globby = require('globby');
|
||||
const serveStatic = require('serve-static');
|
||||
|
||||
const compiler = webpack(Object.assign({mode: 'development'}, config));
|
||||
|
||||
@@ -19,14 +20,10 @@ function getHref(entry) {
|
||||
return path.dirname(entry).slice(1) + '/';
|
||||
}
|
||||
|
||||
const staticHandler = serveStatic(__dirname);
|
||||
|
||||
function notFound(req, res) {
|
||||
return () => {
|
||||
if (req.url === '/favicon.ico') {
|
||||
res.writeHead(204);
|
||||
res.end();
|
||||
return;
|
||||
}
|
||||
|
||||
const items = [];
|
||||
for (const key in config.entry) {
|
||||
const href = getHref(config.entry[key]);
|
||||
@@ -42,7 +39,7 @@ function notFound(req, res) {
|
||||
}
|
||||
|
||||
function serve(options) {
|
||||
const handler = middleware(compiler, {
|
||||
const webpackHandler = webpackMiddleware(compiler, {
|
||||
lazy: true,
|
||||
logger: options.log,
|
||||
stats: 'minimal'
|
||||
@@ -50,7 +47,18 @@ function serve(options) {
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
const server = http.createServer((req, res) => {
|
||||
handler(req, res, notFound(req, res));
|
||||
if (req.url === '/favicon.ico') {
|
||||
res.writeHead(204);
|
||||
res.end();
|
||||
return;
|
||||
}
|
||||
|
||||
if (path.extname(req.url) === '.js') {
|
||||
webpackHandler(req, res, notFound(req, res));
|
||||
return;
|
||||
}
|
||||
|
||||
staticHandler(req, res, notFound(req, res));
|
||||
});
|
||||
|
||||
server.listen(options.port, options.host, err => {
|
||||
@@ -141,8 +149,10 @@ async function renderPage(page, entry, options) {
|
||||
resolve();
|
||||
};
|
||||
});
|
||||
options.log.debug('navigating', entry);
|
||||
await page.goto(`http://${options.host}:${options.port}${getHref(entry)}`, {waitUntil: 'networkidle0'});
|
||||
await renderCalled;
|
||||
options.log.debug('screenshot', entry);
|
||||
await page.screenshot({path: getActualScreenshotPath(entry)});
|
||||
}
|
||||
|
||||
@@ -168,7 +178,7 @@ async function renderEach(page, entries, options) {
|
||||
}
|
||||
const error = await assertScreenshotsMatch(entry);
|
||||
if (error) {
|
||||
process.stderr.write(`${error.message}\n`);
|
||||
options.log.error(error);
|
||||
fail = true;
|
||||
continue;
|
||||
}
|
||||
@@ -181,7 +191,7 @@ async function renderEach(page, entries, options) {
|
||||
async function render(entries, options) {
|
||||
const browser = await puppeteer.launch({
|
||||
args: options.puppeteerArgs,
|
||||
headless: !process.env.CI
|
||||
headless: options.headless
|
||||
});
|
||||
|
||||
let fail = false;
|
||||
@@ -232,14 +242,14 @@ async function getOutdated(entries, options) {
|
||||
for (const entry of entries) {
|
||||
const passPath = getPassFilePath(entry);
|
||||
const passTime = await getLatest(passPath);
|
||||
options.log.debug(entry, 'pass time', passTime);
|
||||
options.log.debug('pass time', entry, passTime);
|
||||
if (passTime < libTime) {
|
||||
outdated.push(entry);
|
||||
continue;
|
||||
}
|
||||
|
||||
const caseTime = await getLatest(path.join(__dirname, path.dirname(entry), '**', '*'));
|
||||
options.log.debug(entry, 'case time', caseTime);
|
||||
options.log.debug('case time', entry, caseTime);
|
||||
if (passTime < caseTime) {
|
||||
outdated.push(entry);
|
||||
continue;
|
||||
@@ -254,7 +264,7 @@ async function main(entries, options) {
|
||||
if (!options.force) {
|
||||
entries = await getOutdated(entries, options);
|
||||
}
|
||||
if (entries.length === 0) {
|
||||
if (!options.interactive && entries.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -304,8 +314,13 @@ if (require.main === module) {
|
||||
choices: ['trace', 'debug', 'info', 'warn', 'error', 'silent'],
|
||||
default: 'error'
|
||||
}).
|
||||
option('headless', {
|
||||
describe: 'Launch Puppeteer in headless mode',
|
||||
type: 'boolean',
|
||||
default: process.env.CI ? false : true
|
||||
}).
|
||||
option('puppeteer-args', {
|
||||
describe: 'Args of for puppeteer.launch()',
|
||||
describe: 'Additional args for Puppeteer',
|
||||
type: 'array',
|
||||
default: process.env.CI ? ['--no-sandbox', '--disable-setuid-sandbox'] : []
|
||||
}).
|
||||
@@ -313,9 +328,6 @@ if (require.main === module) {
|
||||
|
||||
const entries = Object.keys(config.entry).map(key => config.entry[key]);
|
||||
|
||||
if (options.interactive) {
|
||||
options.force = true;
|
||||
}
|
||||
options.log = log.create({name: 'rendering', level: options.logLevel});
|
||||
|
||||
main(entries, options).catch(err => {
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
const CopyPlugin = require('copy-webpack-plugin');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
@@ -15,22 +14,5 @@ module.exports = {
|
||||
context: __dirname,
|
||||
target: 'web',
|
||||
entry: entry,
|
||||
module: {
|
||||
rules: [{
|
||||
use: {
|
||||
loader: 'buble-loader'
|
||||
},
|
||||
test: /\.js$/,
|
||||
include: [
|
||||
path.join(__dirname, '..', 'src')
|
||||
]
|
||||
}]
|
||||
},
|
||||
plugins: [
|
||||
new CopyPlugin([
|
||||
{from: '../src/ol/ol.css', to: 'css'},
|
||||
{from: 'cases/**/*.html'}
|
||||
])
|
||||
],
|
||||
devtool: 'source-map'
|
||||
};
|
||||
|
||||
|
Before Width: | Height: | Size: 615 B |
|
Before Width: | Height: | Size: 639 B |
|
Before Width: | Height: | Size: 4.0 KiB |
@@ -127,14 +127,6 @@ describe('ol.rendering.layer.Tile', function() {
|
||||
});
|
||||
});
|
||||
|
||||
it('tests the canvas renderer', function(done) {
|
||||
createMap('canvas');
|
||||
waitForTiles([source1, source2], {}, function() {
|
||||
expectResemble(map, 'rendering/ol/layer/expected/2-layers-canvas.png',
|
||||
IMAGE_TOLERANCE, done);
|
||||
});
|
||||
});
|
||||
|
||||
where('WebGL').it('tests the WebGL renderer', function(done) {
|
||||
assertWebGL();
|
||||
createMap('webgl');
|
||||
|
||||
@@ -98,14 +98,6 @@ describe('ol.rendering.Map', function() {
|
||||
|
||||
describe('#rotate()', function() {
|
||||
|
||||
it('tests the canvas renderer', function(done) {
|
||||
createMap('canvas');
|
||||
map.getView().setRotation(90);
|
||||
map.getView().setCenter([10, 10]);
|
||||
expectResemble(
|
||||
map, 'rendering/ol/expected/rotate-canvas.png', 2.8, done);
|
||||
});
|
||||
|
||||
where('WebGL').it('tests the WebGL renderer', function(done) {
|
||||
assertWebGL();
|
||||
createMap('webgl');
|
||||
@@ -118,14 +110,6 @@ describe('ol.rendering.Map', function() {
|
||||
|
||||
describe('#zoom()', function() {
|
||||
|
||||
it('tests the canvas renderer', function(done) {
|
||||
createMap('canvas');
|
||||
map.getView().setCenter([10, 10]);
|
||||
map.getView().setResolution(2);
|
||||
expectResemble(
|
||||
map, 'rendering/ol/expected/zoom-canvas.png', IMAGE_TOLERANCE, done);
|
||||
});
|
||||
|
||||
where('WebGL').it('tests the WebGL renderer', function(done) {
|
||||
assertWebGL();
|
||||
createMap('webgl');
|
||||
|
||||
|
Before Width: | Height: | Size: 1.2 KiB |
@@ -66,14 +66,6 @@ describe('ol.rendering.style.Icon', function() {
|
||||
img.src = src;
|
||||
}
|
||||
|
||||
it('tests the canvas renderer', function(done) {
|
||||
createMap('canvas');
|
||||
createFeatures('rendering/ol/data/icon.png', imgInfo, function() {
|
||||
expectResemble(map, 'rendering/ol/style/expected/icon-canvas.png',
|
||||
IMAGE_TOLERANCE, done);
|
||||
});
|
||||
});
|
||||
|
||||
it('scales svg correctly in the canvas renderer', function(done) {
|
||||
createMap('canvas', 512, 512);
|
||||
createFeatures('rendering/ol/data/me0.svg', {
|
||||
|
||||