diff --git a/package.json b/package.json index fb38b62e8f..82eab66faf 100644 --- a/package.json +++ b/package.json @@ -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", diff --git a/rendering/cases/icon-symbol/expected.png b/rendering/cases/icon-symbol/expected.png new file mode 100644 index 0000000000..5629baa58f Binary files /dev/null and b/rendering/cases/icon-symbol/expected.png differ diff --git a/rendering/cases/icon-symbol/index.html b/rendering/cases/icon-symbol/index.html new file mode 100644 index 0000000000..96cfb5a582 --- /dev/null +++ b/rendering/cases/icon-symbol/index.html @@ -0,0 +1,22 @@ + + + + + + +
+ + + + diff --git a/rendering/cases/icon-symbol/main.js b/rendering/cases/icon-symbol/main.js new file mode 100644 index 0000000000..44866172b2 --- /dev/null +++ b/rendering/cases/icon-symbol/main.js @@ -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(); diff --git a/rendering/cases/rotated-view/expected.png b/rendering/cases/rotated-view/expected.png new file mode 100644 index 0000000000..de3ae98a23 Binary files /dev/null and b/rendering/cases/rotated-view/expected.png differ diff --git a/rendering/cases/rotated-view/index.html b/rendering/cases/rotated-view/index.html new file mode 100644 index 0000000000..96cfb5a582 --- /dev/null +++ b/rendering/cases/rotated-view/index.html @@ -0,0 +1,22 @@ + + + + + + +
+ + + + diff --git a/rendering/cases/rotated-view/main.js b/rendering/cases/rotated-view/main.js new file mode 100644 index 0000000000..4e75c0ef42 --- /dev/null +++ b/rendering/cases/rotated-view/main.js @@ -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(); diff --git a/rendering/data/icon.png b/rendering/data/icon.png new file mode 100644 index 0000000000..ed886623d5 Binary files /dev/null and b/rendering/data/icon.png differ diff --git a/rendering/test.js b/rendering/test.js index 4d2c915f43..13af9f4eba 100755 --- a/rendering/test.js +++ b/rendering/test.js @@ -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 => { diff --git a/rendering/webpack.config.js b/rendering/webpack.config.js index 2541c394f5..ff7a27f222 100644 --- a/rendering/webpack.config.js +++ b/rendering/webpack.config.js @@ -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' }; diff --git a/test/rendering/ol/expected/rotate-canvas.png b/test/rendering/ol/expected/rotate-canvas.png deleted file mode 100644 index e614cf3c08..0000000000 Binary files a/test/rendering/ol/expected/rotate-canvas.png and /dev/null differ diff --git a/test/rendering/ol/expected/zoom-canvas.png b/test/rendering/ol/expected/zoom-canvas.png deleted file mode 100644 index ab3b0abde3..0000000000 Binary files a/test/rendering/ol/expected/zoom-canvas.png and /dev/null differ diff --git a/test/rendering/ol/layer/expected/2-layers-canvas.png b/test/rendering/ol/layer/expected/2-layers-canvas.png deleted file mode 100644 index ad069af45c..0000000000 Binary files a/test/rendering/ol/layer/expected/2-layers-canvas.png and /dev/null differ diff --git a/test/rendering/ol/layer/tile.test.js b/test/rendering/ol/layer/tile.test.js index fcb01b3694..d5a800434c 100644 --- a/test/rendering/ol/layer/tile.test.js +++ b/test/rendering/ol/layer/tile.test.js @@ -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'); diff --git a/test/rendering/ol/map.test.js b/test/rendering/ol/map.test.js index 9e84ee11e9..fed97af903 100644 --- a/test/rendering/ol/map.test.js +++ b/test/rendering/ol/map.test.js @@ -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'); diff --git a/test/rendering/ol/style/expected/icon-canvas.png b/test/rendering/ol/style/expected/icon-canvas.png deleted file mode 100644 index b15cc13994..0000000000 Binary files a/test/rendering/ol/style/expected/icon-canvas.png and /dev/null differ diff --git a/test/rendering/ol/style/icon.test.js b/test/rendering/ol/style/icon.test.js index 07013b69d8..a901d436b9 100644 --- a/test/rendering/ol/style/icon.test.js +++ b/test/rendering/ol/style/icon.test.js @@ -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', {