From d150c17a4dbeec5533b30354c38eb868ae7f0e0b Mon Sep 17 00:00:00 2001 From: Kyle Hensel Date: Mon, 20 Jan 2025 20:14:45 +1100 Subject: [PATCH] fix occasional test failures --- eslint.config.mjs | 1 + test/spec/behavior/hash.js | 4 +++- test/spec/services/nominatim.js | 3 ++- test/spec/services/osm.js | 8 ++++---- test/spec_helpers.mts | 29 +++++++++++++++++++++++++---- tsconfig.json | 2 +- 6 files changed, 36 insertions(+), 11 deletions(-) diff --git a/eslint.config.mjs b/eslint.config.mjs index 3723635483..a9772ec1ab 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -118,6 +118,7 @@ export default [ 'sinon': 'readonly', 'happen': 'readonly', 'fetchMock': 'readonly', + 'jsdom': 'readonly', 'expect': 'writable' } }, diff --git a/test/spec/behavior/hash.js b/test/spec/behavior/hash.js index 5bd3a9ae62..d2d388a292 100644 --- a/test/spec/behavior/hash.js +++ b/test/spec/behavior/hash.js @@ -73,7 +73,9 @@ describe('iD.behaviorHash', function () { context.map().center([-77.0, 38.9]); context.map().zoom(2.0); window.setTimeout(function() { - expect(window.location.hash).to.equal('#background=none&map=2.00/38.9/-77.0'); + // the hash might contain other things like `disable_features` + expect(window.location.hash).to.include('background=none'); + expect(window.location.hash).to.include('map=2.00/38.9/-77.0'); done(); }, 600); }); diff --git a/test/spec/services/nominatim.js b/test/spec/services/nominatim.js index 3fc2842141..47a552180b 100644 --- a/test/spec/services/nominatim.js +++ b/test/spec/services/nominatim.js @@ -10,9 +10,10 @@ describe('iD.serviceNominatim', function() { delete iD.services.geocoder; }); - beforeEach(function() { + beforeEach(async function() { nominatim = iD.services.geocoder; nominatim.reset(); + await iD.localizer.ensureLoaded(); }); afterEach(function() { diff --git a/test/spec/services/osm.js b/test/spec/services/osm.js index d50fc493ac..6daf3e44b8 100644 --- a/test/spec/services/osm.js +++ b/test/spec/services/osm.js @@ -137,7 +137,7 @@ describe('iD.serviceOsm', function () { }); describe('#loadFromAPI', function () { - var path = '/api/0.6/map.json?bbox=-74.542,40.655,-74.541,40.656'; + var path = '/api/0.6/map.json'; var response = '{' + ' "version":"0.6",' + @@ -528,7 +528,7 @@ describe('iD.serviceOsm', function () { done(); }); - serverXHR.respondWith('GET', 'https://www.openstreetmap.org/api/0.6/changesets?user=1', + serverXHR.respondWith('GET', 'https://www.openstreetmap.org/api/0.6/changesets\\?user=1', [200, { 'Content-Type': 'text/xml' }, changesetsXML]); serverXHR.respond(); }); @@ -557,7 +557,7 @@ describe('iD.serviceOsm', function () { done(); }); - serverXHR.respondWith('GET', 'https://www.openstreetmap.org/api/0.6/changesets?user=1', + serverXHR.respondWith('GET', 'https://www.openstreetmap.org/api/0.6/changesets\\?user=1', [200, { 'Content-Type': 'text/xml' }, changesetsXML]); serverXHR.respond(); }); @@ -587,7 +587,7 @@ describe('iD.serviceOsm', function () { done(); }); - serverXHR.respondWith('GET', 'https://www.openstreetmap.org/api/0.6/changesets?user=1', + serverXHR.respondWith('GET', 'https://www.openstreetmap.org/api/0.6/changesets\\?user=1', [200, { 'Content-Type': 'text/xml' }, changesetsXML]); serverXHR.respond(); }); diff --git a/test/spec_helpers.mts b/test/spec_helpers.mts index 1068b95098..a934ee5e4e 100644 --- a/test/spec_helpers.mts +++ b/test/spec_helpers.mts @@ -8,6 +8,8 @@ import envs from '../config/envs.mjs'; chai.use(sinonChai); +declare var global: typeof globalThis; + global.before = beforeEach; global.after = afterEach; global.fetchMock = fetchMock; @@ -19,6 +21,19 @@ for (const [key, value] of Object.entries(envs)) { Reflect.set(global, key, JSON.parse(value)); } +// the 'happen' library explicitly references `window` when creating an event, +// but we need to use jsdom's window, so we have to patch initEvent. +const { initMouseEvent } = MouseEvent.prototype; +MouseEvent.prototype.initMouseEvent = function (...args) { + args[3] = jsdom.window; + return initMouseEvent.apply(this, args); +}; +const { initUIEvent } = UIEvent.prototype; +UIEvent.prototype.initUIEvent = function (...args) { + args[3] = jsdom.window; + return initUIEvent.apply(this, args); +}; + // vitest has deprecated the done() callback, so we overwrite the `it` function const _it = it; Reflect.set( @@ -26,11 +41,17 @@ Reflect.set( 'it', Object.assign( (msg: string, fn: (done?: () => void) => void | Promise) => { - _it(msg, () => - fn.length ? () => new Promise((resolve) => fn(resolve)) : fn(), - ); + _it(msg, () => { + if (fn.length) { + // there is a done callback -> return a promise instead + return new Promise((done) => fn(done)); + } + + // no done callback -> normal behaviour + return fn(); + }); }, - { todo: _it.todo, skip: _it.skip }, + { todo: _it.todo, skip: _it.skip, only: _it.only, each: _it.each }, ), ); diff --git a/tsconfig.json b/tsconfig.json index aae0450a48..c9f72617fb 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -9,7 +9,7 @@ "target": "esnext", "module": "nodenext", "moduleResolution": "nodenext", - "types": ["vitest/globals"] + "types": ["vitest/globals", "vitest/jsdom"] }, "include": ["modules", "test"] }