diff --git a/tests/e2e/test-rx-coverage-viewport-e2e.js b/tests/e2e/test-rx-coverage-viewport-e2e.js index 52baec1e..c334dc66 100644 --- a/tests/e2e/test-rx-coverage-viewport-e2e.js +++ b/tests/e2e/test-rx-coverage-viewport-e2e.js @@ -39,17 +39,28 @@ const BASE = process.env.BASE_URL || 'http://localhost:3000'; async function viewport() { return page.evaluate(() => { const m = window.__rxTestMap, c = m.getCenter(); return { lat: c.lat, lng: c.lng, zoom: m.getZoom() }; }); } + // Leaflet keeps the centre as a pixel coordinate, so a centre read back is + // only ever accurate to the pixel it landed on. One pixel spans + // 360/(256*2^zoom) degrees of longitude: 0.022° at zoom 6, 0.0014° at + // zoom 10. The budget below used to be a flat 0.001°, which at zoom 6 + // demanded 1/20 of a pixel, so any change to the map container's size + // moved the pixel centre enough to fail an assertion about the *view*. + // For latitude the Mercator scale is this figure times cos(lat), so using + // the longitude figure is the looser bound there, deliberately. + const degPerPixel = (zoom) => 360 / (256 * Math.pow(2, zoom)); + function assertViewport(actual, expected) { - // Leaflet projects centers to pixels during invalidateSize/pan, so allow - // sub-pixel coordinate rounding while still checking the intended view. - assert(Math.abs(actual.lat - expected.lat) < 0.001, JSON.stringify(actual)); - assert(Math.abs(actual.lng - expected.lng) < 0.001, JSON.stringify(actual)); + const budget = degPerPixel(expected.zoom); + const off = (axis) => axis + ' ' + actual[axis] + ' is more than one pixel (' + + budget.toFixed(5) + '°) from ' + expected[axis] + ': ' + JSON.stringify(actual); + assert(Math.abs(actual.lat - expected.lat) < budget, off('lat')); + assert(Math.abs(actual.lng - expected.lng) < budget, off('lng')); assert.equal(actual.zoom, expected.zoom); } await page.goto(BASE + '/#/rx-coverage'); await waitMap(); assertViewport(await viewport(), { lat: 12, lng: 34, zoom: 6 }); await page.evaluate(() => window.__rxTestMap.setView([22, 44], 10, { animate: false })); - await page.waitForFunction(() => Math.abs(Number(new URLSearchParams(location.hash.split('?')[1]).get('lat')) - 22) < 0.001); + await page.waitForFunction((budget) => Math.abs(Number(new URLSearchParams(location.hash.split('?')[1]).get('lat')) - 22) < budget, degPerPixel(10)); assertViewport(await page.evaluate(() => JSON.parse(localStorage.getItem('rx-coverage-view'))), { lat: 22, lng: 44, zoom: 10 }); assert.equal(await page.evaluate(() => localStorage.getItem('map-view')), null, 'coverage must not write the main map\'s saved viewport'); await page.reload(); await waitMap(); assertViewport(await viewport(), { lat: 22, lng: 44, zoom: 10 });