diff --git a/package-lock.json b/package-lock.json
index 5457f9851..1671b7b3d 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -51,6 +51,7 @@
"@types/d3": "^7.4.3",
"@types/happen": "^0.3.0",
"@types/lodash-es": "^4.17.12",
+ "@types/node": "^22.13.4",
"@types/sinon": "^17.0.3",
"@types/sinon-chai": "^4.0.0",
"autoprefixer": "^10.4.20",
@@ -1958,6 +1959,15 @@
"@types/lodash": "*"
}
},
+ "node_modules/@types/node": {
+ "version": "22.13.4",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.4.tgz",
+ "integrity": "sha512-ywP2X0DYtX3y08eFVx5fNIw7/uIv8hYUKgXoK8oayJlLnKcRfEYCxWMVE1XagUdVtCJlZT1AU4LXEABW+L1Peg==",
+ "devOptional": true,
+ "dependencies": {
+ "undici-types": "~6.20.0"
+ }
+ },
"node_modules/@types/pako": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/@types/pako/-/pako-1.0.7.tgz",
@@ -23639,6 +23649,12 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/undici-types": {
+ "version": "6.20.0",
+ "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz",
+ "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==",
+ "devOptional": true
+ },
"node_modules/update-browserslist-db": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.1.tgz",
diff --git a/package.json b/package.json
index 064ab4b2a..f7c6e2659 100644
--- a/package.json
+++ b/package.json
@@ -86,6 +86,7 @@
"@types/d3": "^7.4.3",
"@types/happen": "^0.3.0",
"@types/lodash-es": "^4.17.12",
+ "@types/node": "^22.13.4",
"@types/sinon": "^17.0.3",
"@types/sinon-chai": "^4.0.0",
"autoprefixer": "^10.4.20",
diff --git a/test/spec/behavior/hash.js b/test/spec/behavior/hash.js
index 226a11161..2f0456aec 100644
--- a/test/spec/behavior/hash.js
+++ b/test/spec/behavior/hash.js
@@ -1,3 +1,5 @@
+import { setTimeout } from 'node:timers/promises';
+
describe('iD.behaviorHash', function () {
var hash, context;
@@ -30,16 +32,14 @@ describe('iD.behaviorHash', function () {
expect(context.map().zoom()).to.equal(20.0);
});
- it('centerZooms map at requested coordinates on hash change', function (done) {
+ it('centerZooms map at requested coordinates on hash change', async () => {
hash();
- d3.select(window).on('hashchange', function () {
- expect(context.map().center()[0]).to.be.closeTo(-77.02405, 0.1);
- expect(context.map().center()[1]).to.be.closeTo(38.87952, 0.1);
- expect(context.map().zoom()).to.equal(20.0);
- d3.select(window).on('hashchange', null);
- done();
- });
window.location.hash = '#background=none&map=20.00/38.87952/-77.02405';
+ await new Promise(cb => { d3.select(window).on('hashchange', cb); });
+ expect(context.map().center()[0]).to.be.closeTo(-77.02405, 0.1);
+ expect(context.map().center()[1]).to.be.closeTo(38.87952, 0.1);
+ expect(context.map().zoom()).to.equal(20.0);
+ d3.select(window).on('hashchange', null);
});
it('sets hadLocation if map-location is in local storage', function () {
@@ -68,16 +68,14 @@ describe('iD.behaviorHash', function () {
iD.prefs('map-location', null);
});
- it('stores the current zoom and coordinates in window.location.hash on map move events', function (done) {
+ it('stores the current zoom and coordinates in window.location.hash on map move events', async () => {
hash();
context.map().center([-77.0, 38.9]);
context.map().zoom(2.0);
- window.setTimeout(function() {
- // 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);
+ await setTimeout(600);
+ // 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');
});
it('accepts default changeset comment as hash parameter', function () {
diff --git a/test/spec/behavior/select.js b/test/spec/behavior/select.js
index 606d25229..d082e7dfb 100644
--- a/test/spec/behavior/select.js
+++ b/test/spec/behavior/select.js
@@ -1,3 +1,5 @@
+import { setTimeout } from 'node:timers/promises';
+
describe('iD.behaviorSelect', function() {
var a, b, context, behavior, container;
@@ -55,62 +57,50 @@ describe('iD.behaviorSelect', function() {
expect(context.mode().id).to.eql('browse');
});
- it('click on entity selects the entity', function(done) {
+ it('click on entity selects the entity', async () => {
var el = context.surface().selectAll('.' + a.id).node();
simulateClick(el, {});
- window.setTimeout(function() {
- expect(context.selectedIDs()).to.eql([a.id]);
- done();
- }, 50);
+ await setTimeout(50);
+ expect(context.selectedIDs()).to.eql([a.id]);
});
- it('click on empty space clears the selection', function(done) {
+ it('click on empty space clears the selection', async () => {
context.enter(iD.modeSelect(context, [a.id]));
var el = context.surface().node();
simulateClick(el, {});
- window.setTimeout(function() {
- expect(context.mode().id).to.eql('browse');
- done();
- }, 50);
+ await setTimeout(50);
+ expect(context.mode().id).to.eql('browse');
});
- it('shift-click on unselected entity adds it to the selection', function(done) {
+ it('shift-click on unselected entity adds it to the selection', async () => {
context.enter(iD.modeSelect(context, [a.id]));
var el = context.surface().selectAll('.' + b.id).node();
simulateClick(el, { shiftKey: true });
- window.setTimeout(function() {
- expect(context.selectedIDs()).to.eql([a.id, b.id]);
- done();
- }, 50);
+ await setTimeout(50);
+ expect(context.selectedIDs()).to.eql([a.id, b.id]);
});
- it('shift-click on selected entity removes it from the selection', function(done) {
+ it('shift-click on selected entity removes it from the selection', async () => {
context.enter(iD.modeSelect(context, [a.id, b.id]));
var el = context.surface().selectAll('.' + b.id).node();
simulateClick(el, { shiftKey: true });
- window.setTimeout(function() {
- expect(context.selectedIDs()).to.eql([a.id]);
- done();
- }, 50);
+ await setTimeout(50);
+ expect(context.selectedIDs()).to.eql([a.id]);
});
- it('shift-click on last selected entity clears the selection', function(done) {
+ it('shift-click on last selected entity clears the selection', async () => {
context.enter(iD.modeSelect(context, [a.id]));
var el = context.surface().selectAll('.' + a.id).node();
simulateClick(el, { shiftKey: true });
- window.setTimeout(function() {
- expect(context.mode().id).to.eql('browse');
- done();
- }, 50);
+ await setTimeout(50);
+ expect(context.mode().id).to.eql('browse');
});
- it('shift-click on empty space leaves the selection unchanged', function(done) {
+ it('shift-click on empty space leaves the selection unchanged', async () => {
context.enter(iD.modeSelect(context, [a.id]));
var el = context.surface().node();
simulateClick(el, { shiftKey: true });
- window.setTimeout(function() {
- expect(context.selectedIDs()).to.eql([a.id]);
- done();
- }, 50);
+ await setTimeout(50);
+ expect(context.selectedIDs()).to.eql([a.id]);
});
});
diff --git a/test/spec/core/LocationManager.js b/test/spec/core/LocationManager.js
index 955ba8169..6c29f834a 100644
--- a/test/spec/core/LocationManager.js
+++ b/test/spec/core/LocationManager.js
@@ -38,56 +38,35 @@ describe('LocationManager', () => {
describe('#mergeLocationSets', () => {
- it('returns a promise rejected if not passed an array', done => {
+ it('returns a promise rejected if not passed an array', async () => {
const prom = locationManager.mergeLocationSets({});
- prom
- .then(() => {
- done(new Error('This was supposed to fail, but somehow succeeded.'));
- })
- .catch(err => {
- expect(/^nothing to do/.test(err)).to.be.true;
- done();
- });
-
- window.setTimeout(() => {}, 20); // async - to let the promise settle in phantomjs
+ await expect(prom).rejects.toThrow(/^nothing to do/);
});
- it('resolves locationSets, assigning locationSetID', done => {
+ it('resolves locationSets, assigning locationSetID', async () => {
const data = [
{ id: 'world', locationSet: { include: ['001'] } },
{ id: 'usa', locationSet: { include: ['usa'] } }
];
const prom = locationManager.mergeLocationSets(data);
- prom
- .then(data => {
- expect(data).to.be.a('array');
- expect(data[0].locationSetID).to.eql('+[Q2]');
- expect(data[1].locationSetID).to.eql('+[Q30]');
- done();
- })
- .catch(err => done(err));
-
- window.setTimeout(() => {}, 20); // async - to let the promise settle in phantomjs
+ await prom;
+ expect(data).to.be.a('array');
+ expect(data[0].locationSetID).to.eql('+[Q2]');
+ expect(data[1].locationSetID).to.eql('+[Q30]');
});
- it('resolves locationSets, falls back to world locationSetID on errror', done => {
+ it('resolves locationSets, falls back to world locationSetID on errror', async () => {
const data = [
{ id: 'bogus1', locationSet: { foo: 'bar' } },
{ id: 'bogus2', locationSet: { include: ['fake.geojson'] } }
];
const prom = locationManager.mergeLocationSets(data);
- prom
- .then(data => {
- expect(data).to.be.a('array');
- expect(data[0].locationSetID).to.eql('+[Q2]');
- expect(data[1].locationSetID).to.eql('+[Q2]');
- done();
- })
- .catch(err => done(err));
-
- window.setTimeout(() => {}, 20); // async - to let the promise settle in phantomjs
+ await prom;
+ expect(data).to.be.a('array');
+ expect(data[0].locationSetID).to.eql('+[Q2]');
+ expect(data[1].locationSetID).to.eql('+[Q2]');
});
});
@@ -127,26 +106,20 @@ describe('LocationManager', () => {
expect(result3).to.be.an('object').that.has.all.keys('+[Q2]');
});
- it('returns valid locationSets at a given lon,lat', done => {
+ it('returns valid locationSets at a given lon,lat', async () => {
// setup, load colorado.geojson and resolve some locationSets
locationManager.mergeCustomGeoJSON(fc);
- locationManager.mergeLocationSets([
+ await locationManager.mergeLocationSets([
{ id: 'OSM-World', locationSet: { include: ['001'] } },
{ id: 'OSM-USA', locationSet: { include: ['us'] } },
{ id: 'OSM-Colorado', locationSet: { include: ['colorado.geojson'] } }
- ])
- .then(() => {
- const result1 = locationManager.locationSetsAt([-108.557, 39.065]); // Grand Junction
- expect(result1).to.be.an('object').that.has.all.keys('+[Q2]', '+[Q30]', '+[colorado.geojson]');
- const result2 = locationManager.locationSetsAt([-74.481, 40.797]); // Morristown
- expect(result2).to.be.an('object').that.has.all.keys('+[Q2]', '+[Q30]');
- const result3 = locationManager.locationSetsAt([13.575, 41.207,]); // Gaeta
- expect(result3).to.be.an('object').that.has.all.keys('+[Q2]');
- done();
- })
- .catch(err => done(err));
-
- window.setTimeout(() => {}, 20); // async - to let the promise settle in phantomjs
+ ]);
+ const result1 = locationManager.locationSetsAt([-108.557, 39.065]); // Grand Junction
+ expect(result1).to.be.an('object').that.has.all.keys('+[Q2]', '+[Q30]', '+[colorado.geojson]');
+ const result2 = locationManager.locationSetsAt([-74.481, 40.797]); // Morristown
+ expect(result2).to.be.an('object').that.has.all.keys('+[Q2]', '+[Q30]');
+ const result3 = locationManager.locationSetsAt([13.575, 41.207,]); // Gaeta
+ expect(result3).to.be.an('object').that.has.all.keys('+[Q2]');
});
});
diff --git a/test/spec/core/file_fetcher.js b/test/spec/core/file_fetcher.js
index a209b5403..2b77b9cff 100644
--- a/test/spec/core/file_fetcher.js
+++ b/test/spec/core/file_fetcher.js
@@ -13,50 +13,31 @@ describe('iD.coreFileFetcher', function() {
});
describe('#get', function() {
- it('returns a promise resolved if we already have the data', function(done) {
+ it('returns a promise resolved if we already have the data', async () => {
var data = iD.coreFileFetcher();
data.cache().test = { hello: 'world' };
var prom = data.get('test');
expect(prom).to.be.a('promise');
- prom
- .then(function(data) {
- expect(data).to.be.a('object');
- expect(data.hello).to.eql('world');
- done();
- })
- .catch(function(err) {
- done(err);
- });
+ data = await prom;
+ expect(data).to.be.a('object');
+ expect(data.hello).to.eql('world');
});
- it('returns a promise rejected if we can not get the data', function(done) {
+ it('returns a promise rejected if we can not get the data', async () => {
var data = iD.coreFileFetcher().assetPath('../dist/');
var prom = data.get('wat');
- prom
- .then(function(data) {
- done(new Error('We were not supposed to get data but did: ' + data));
- })
- .catch(function(err) {
- expect(/^Unknown data file/.test(err)).to.be.true;
- done();
- });
+ await expect(prom).rejects.toThrow(/^Unknown data file/);
});
- it('returns a promise to fetch data if we do not already have the data', function(done) {
+ it('returns a promise to fetch data if we do not already have the data', async () => {
var files = { 'intro_graph': 'data/intro_graph.min.json' };
var data = iD.coreFileFetcher().assetPath('../dist/').fileMap(files);
var prom = data.get('intro_graph');
expect(prom).to.be.a('promise');
- prom
- .then(function(data) {
- expect(data).to.be.a('object');
- expect(data.n2061.tags.name).to.eql('Three Rivers City Hall');
- done();
- })
- .catch(function(err) {
- done(err);
- });
+ data = await prom;
+ expect(data).to.be.a('object');
+ expect(data.n2061.tags.name).to.eql('Three Rivers City Hall');
});
});
diff --git a/test/spec/core/history.js b/test/spec/core/history.js
index d9313a454..4e8d73e4e 100644
--- a/test/spec/core/history.js
+++ b/test/spec/core/history.js
@@ -1,3 +1,5 @@
+import { setTimeout } from 'node:timers/promises';
+
describe('iD.coreHistory', function () {
var context, history, spy;
var actionNoop = function(g) { return g; };
@@ -68,15 +70,13 @@ describe('iD.coreHistory', function () {
expect(history.undoAnnotation()).to.equal('annotation');
});
- it('performs transitionable actions in a transition', function (done) {
+ it('performs transitionable actions in a transition', async () => {
var action1 = function() { return iD.coreGraph(); };
action1.transitionable = true;
history.on('change', spy);
history.perform(action1);
- window.setTimeout(function() {
- expect(spy.callCount).to.be.above(2);
- done();
- }, 300);
+ await setTimeout(300);
+ expect(spy.callCount).to.be.above(2);
});
});
diff --git a/test/spec/core/validator.js b/test/spec/core/validator.js
index ce10bd80b..b86261b09 100644
--- a/test/spec/core/validator.js
+++ b/test/spec/core/validator.js
@@ -24,7 +24,7 @@ describe('iD.coreValidator', function() {
expect(issues).to.have.lengthOf(0);
});
- it('validate returns a promise, fulfilled when the validation has completed', function(done) {
+ it('validate returns a promise, fulfilled when the validation has completed', async () => {
createInvalidWay();
var validator = new iD.coreValidator(context);
validator.init();
@@ -32,22 +32,16 @@ describe('iD.coreValidator', function() {
expect(issues).to.have.lengthOf(0);
var prom = validator.validate();
- prom
- .then(function() {
- issues = validator.getIssues();
- expect(issues).to.have.lengthOf(1);
- var issue = issues[0];
- expect(issue.type).to.eql('missing_tag');
- expect(issue.entityIds).to.have.lengthOf(1);
- expect(issue.entityIds[0]).to.eql('w-1');
- done();
- })
- .catch(function(err) {
- done(err);
- });
+ await prom;
+ issues = validator.getIssues();
+ expect(issues).to.have.lengthOf(1);
+ var issue = issues[0];
+ expect(issue.type).to.eql('missing_tag');
+ expect(issue.entityIds).to.have.lengthOf(1);
+ expect(issue.entityIds[0]).to.eql('w-1');
});
- it('removes validation issue when highway is no longer disconnected', function(done) {
+ it('removes validation issue when highway is no longer disconnected', async () => {
// Add a way which is disconnected from the rest of the map
var n1 = iD.osmNode({ id: 'n-1', loc: [4, 4] });
var n2 = iD.osmNode({ id: 'n-2', loc: [4, 5] });
@@ -59,32 +53,25 @@ describe('iD.coreValidator', function() {
);
var validator = new iD.coreValidator(context);
validator.init();
- validator.validate().then(function() {
- // Should produce disconnected way error
- let issues = validator.getIssues();
- expect(issues).to.have.lengthOf(1);
+ await validator.validate();
+ // Should produce disconnected way error
+ let issues = validator.getIssues();
+ expect(issues).to.have.lengthOf(1);
- // Add new node with entrance node to simulate connection with rest of map
- var n3 = iD.osmNode({ id: 'n-3', loc: [4, 6], tags: { 'entrance': 'yes' } });
- var w2 = iD.osmWay({ id: 'w-2', nodes: ['n-2', 'n-3'], tags: { 'highway': 'unclassified' } });
- context.perform(
- iD.actionAddEntity(n3),
- iD.actionAddEntity(w2)
- );
- validator.validate().then(function() {
- // Should be no errors
- issues = validator.getIssues();
- expect(issues).to.have.lengthOf(0);
- done();
- }).catch(function(err) {
- done(err);
- });
- }).catch(function(err) {
- done(err);
- });
+ // Add new node with entrance node to simulate connection with rest of map
+ var n3 = iD.osmNode({ id: 'n-3', loc: [4, 6], tags: { 'entrance': 'yes' } });
+ var w2 = iD.osmWay({ id: 'w-2', nodes: ['n-2', 'n-3'], tags: { 'highway': 'unclassified' } });
+ context.perform(
+ iD.actionAddEntity(n3),
+ iD.actionAddEntity(w2)
+ );
+ await validator.validate();
+ // Should be no errors
+ issues = validator.getIssues();
+ expect(issues).to.have.lengthOf(0);
});
- it('add validation issue when highway becomes disconnected', function(done) {
+ it('add validation issue when highway becomes disconnected', async () => {
// Add a way which is connected to another way with an entrance node to simulate connection with rest of map
var n1 = iD.osmNode({ id: 'n-1', loc: [4, 4] });
var n2 = iD.osmNode({ id: 'n-2', loc: [4, 5] });
@@ -100,27 +87,19 @@ describe('iD.coreValidator', function() {
);
var validator = new iD.coreValidator(context);
validator.init();
- validator.validate().then(function() {
- // Should be no errors
- let issues = validator.getIssues();
- expect(issues).to.have.lengthOf(0);
+ await validator.validate();
+ // Should be no errors
+ let issues = validator.getIssues();
+ expect(issues).to.have.lengthOf(0);
- // delete second way -> first way becomes disconnected form the rest of the network
- context.perform(
- iD.actionDeleteWay(w2.id)
- );
+ // delete second way -> first way becomes disconnected form the rest of the network
+ context.perform(
+ iD.actionDeleteWay(w2.id)
+ );
- validator.validate().then(function() {
- // Should produce disconnected way error
- issues = validator.getIssues();
- expect(issues).to.have.lengthOf(1);
- done();
- }).catch(function(err) {
- done(err);
- });
- }).catch(function(err) {
- done(err);
- });
+ await validator.validate();
+ // Should produce disconnected way error
+ issues = validator.getIssues();
+ expect(issues).to.have.lengthOf(1);
});
-
});
diff --git a/test/spec/presets/index.js b/test/spec/presets/index.js
index 9c3c39efe..0214c2fa2 100644
--- a/test/spec/presets/index.js
+++ b/test/spec/presets/index.js
@@ -48,55 +48,47 @@ describe('iD.presetIndex', function () {
park: { tags: { leisure: 'park' }, geometry: ['point', 'area'] }
};
- it('returns a collection containing presets matching a geometry and tags', function (done) {
+ it('returns a collection containing presets matching a geometry and tags', async () => {
iD.fileFetcher.cache().preset_presets = testPresets;
var presets = iD.presetIndex();
- presets.ensureLoaded().then(function() {
- var way = iD.osmWay({ tags: { highway: 'residential' } });
- var graph = iD.coreGraph([way]);
- expect(presets.match(way, graph).id).to.eql('residential');
- done();
- });
+ await presets.ensureLoaded();
+ var way = iD.osmWay({ tags: { highway: 'residential' } });
+ var graph = iD.coreGraph([way]);
+ expect(presets.match(way, graph).id).to.eql('residential');
});
- it('returns the appropriate fallback preset when no tags match', function (done) {
+ it('returns the appropriate fallback preset when no tags match', async () => {
iD.fileFetcher.cache().preset_presets = testPresets;
var presets = iD.presetIndex();
var point = iD.osmNode();
var line = iD.osmWay({ tags: { foo: 'bar' } });
var graph = iD.coreGraph([point, line]);
- presets.ensureLoaded().then(function() {
- expect(presets.match(point, graph).id).to.eql('point');
- expect(presets.match(line, graph).id).to.eql('line');
- done();
- });
+ await presets.ensureLoaded();
+ expect(presets.match(point, graph).id).to.eql('point');
+ expect(presets.match(line, graph).id).to.eql('line');
});
- it('matches vertices on a line as points', function (done) {
+ it('matches vertices on a line as points', async () => {
iD.fileFetcher.cache().preset_presets = testPresets;
var presets = iD.presetIndex();
var point = iD.osmNode({ tags: { leisure: 'park' } });
var line = iD.osmWay({ nodes: [point.id], tags: { 'highway': 'residential' } });
var graph = iD.coreGraph([point, line]);
- presets.ensureLoaded().then(function() {
- expect(presets.match(point, graph).id).to.eql('point');
- done();
- });
+ await presets.ensureLoaded();
+ expect(presets.match(point, graph).id).to.eql('point');
});
- it('matches vertices on an addr:interpolation line as points', function (done) {
+ it('matches vertices on an addr:interpolation line as points', async () => {
iD.fileFetcher.cache().preset_presets = testPresets;
var presets = iD.presetIndex();
var point = iD.osmNode({ tags: { leisure: 'park' } });
var line = iD.osmWay({ nodes: [point.id], tags: { 'addr:interpolation': 'even' } });
var graph = iD.coreGraph([point, line]);
- presets.ensureLoaded().then(function() {
- expect(presets.match(point, graph).id).to.eql('park');
- done();
- });
+ await presets.ensureLoaded();
+ expect(presets.match(point, graph).id).to.eql('park');
});
});
@@ -112,68 +104,55 @@ describe('iD.presetIndex', function () {
'natural/wood': { tags: { 'natural': 'wood' }, geometry: ['point', 'area'] }
};
- it('includes keys for presets with area geometry', function (done) {
+ it('includes keys for presets with area geometry', async () => {
iD.fileFetcher.cache().preset_presets = testPresets;
var presets = iD.presetIndex();
- presets.ensureLoaded().then(function() {
- expect(presets.areaKeys()).to.include.keys('natural');
- done();
- });
+ await presets.ensureLoaded();
+ expect(presets.areaKeys()).to.include.keys('natural');
});
- it('discards key-values for presets with a line geometry', function (done) {
+ it('discards key-values for presets with a line geometry', async () => {
iD.fileFetcher.cache().preset_presets = testPresets;
var presets = iD.presetIndex();
- presets.ensureLoaded().then(function() {
- expect(presets.areaKeys().natural).to.include.keys('tree_row');
- expect(presets.areaKeys().natural.tree_row).to.be.true;
- done();
- });
+ await presets.ensureLoaded();
+ expect(presets.areaKeys().natural).to.include.keys('tree_row');
+ expect(presets.areaKeys().natural.tree_row).to.be.true;
+
});
- it('discards key-values for presets with both area and line geometry', function (done) {
+ it('discards key-values for presets with both area and line geometry', async () => {
iD.fileFetcher.cache().preset_presets = testPresets;
var presets = iD.presetIndex();
- presets.ensureLoaded().then(function() {
- expect(presets.areaKeys().leisure).to.include.keys('track');
- done();
- });
+ await presets.ensureLoaded();
+ expect(presets.areaKeys().leisure).to.include.keys('track');
});
- it('does not discard key-values for presets with neither area nor line geometry', function (done) {
+ it('does not discard key-values for presets with neither area nor line geometry', async () => {
iD.fileFetcher.cache().preset_presets = testPresets;
var presets = iD.presetIndex();
- presets.ensureLoaded().then(function() {
- expect(presets.areaKeys().natural).not.to.include.keys('peak');
- done();
- });
+ await presets.ensureLoaded();
+ expect(presets.areaKeys().natural).not.to.include.keys('peak');
});
- it('does not discard generic \'*\' key-values', function (done) {
+ it('does not discard generic \'*\' key-values', async () => {
iD.fileFetcher.cache().preset_presets = testPresets;
var presets = iD.presetIndex();
- presets.ensureLoaded().then(function() {
- expect(presets.areaKeys().natural).not.to.include.keys('natural');
- done();
- });
+ await presets.ensureLoaded();
+ expect(presets.areaKeys().natural).not.to.include.keys('natural');
});
- it('ignores keys like \'highway\' that are assumed to be lines', function (done) {
+ it('ignores keys like \'highway\' that are assumed to be lines', async () => {
iD.fileFetcher.cache().preset_presets = testPresets;
var presets = iD.presetIndex();
- presets.ensureLoaded().then(function() {
- expect(presets.areaKeys()).not.to.include.keys('highway');
- done();
- });
+ await presets.ensureLoaded();
+ expect(presets.areaKeys()).not.to.include.keys('highway');
});
- it('ignores suggestion presets', function (done) {
+ it('ignores suggestion presets', async () => {
iD.fileFetcher.cache().preset_presets = testPresets;
var presets = iD.presetIndex();
- presets.ensureLoaded().then(function() {
- expect(presets.areaKeys()).not.to.include.keys('amenity');
- done();
- });
+ await presets.ensureLoaded();
+ expect(presets.areaKeys()).not.to.include.keys('amenity');
});
});
@@ -185,94 +164,83 @@ describe('iD.presetIndex', function () {
bench: { tags: { amenity: 'bench' }, geometry: ['point', 'line'] }
};
- it('addablePresetIDs is initially null', function (done) {
+ it('addablePresetIDs is initially null', async () => {
iD.fileFetcher.cache().preset_presets = testPresets;
var presets = iD.presetIndex();
- presets.ensureLoaded().then(function() {
- expect(presets.addablePresetIDs()).to.be.null;
- done();
- });
+ await presets.ensureLoaded();
+ expect(presets.addablePresetIDs()).to.be.null;
});
- it('can set and get addablePresetIDs', function (done) {
+ it('can set and get addablePresetIDs', async () => {
iD.fileFetcher.cache().preset_presets = testPresets;
var presets = iD.presetIndex();
- presets.ensureLoaded().then(function() {
+ await presets.ensureLoaded();
- expect(presets.item('residential').addable()).to.be.true;
- expect(presets.item('park').addable()).to.be.true;
+ expect(presets.item('residential').addable()).to.be.true;
+ expect(presets.item('park').addable()).to.be.true;
- var ids = new Set(['residential']); // can only add preset with this ID
- presets.addablePresetIDs(ids);
+ var ids = new Set(['residential']); // can only add preset with this ID
+ presets.addablePresetIDs(ids);
- expect(presets.item('residential').addable()).to.be.true;
- expect(presets.item('park').addable()).to.be.false;
- expect(presets.addablePresetIDs()).to.eql(ids);
+ expect(presets.item('residential').addable()).to.be.true;
+ expect(presets.item('park').addable()).to.be.false;
+ expect(presets.addablePresetIDs()).to.eql(ids);
- presets.addablePresetIDs(null);
- expect(presets.item('residential').addable()).to.be.true;
- expect(presets.item('park').addable()).to.be.true;
-
- done();
- });
+ presets.addablePresetIDs(null);
+ expect(presets.item('residential').addable()).to.be.true;
+ expect(presets.item('park').addable()).to.be.true;
});
- it('ignores invalid IDs in addablePresetIDs', function (done) {
+ it('ignores invalid IDs in addablePresetIDs', async () => {
iD.fileFetcher.cache().preset_presets = testPresets;
var presets = iD.presetIndex();
- presets.ensureLoaded().then(function() {
+ await presets.ensureLoaded();
- expect(presets.item(null)).to.eql(undefined);
- expect(presets.item(undefined)).to.eql(undefined);
- expect(presets.item('')).to.eql(undefined);
- expect(presets.item('garbage')).to.eql(undefined);
- expect(presets.item('residential').addable()).to.be.true;
- expect(presets.item('park').addable()).to.be.true;
+ expect(presets.item(null)).to.eql(undefined);
+ expect(presets.item(undefined)).to.eql(undefined);
+ expect(presets.item('')).to.eql(undefined);
+ expect(presets.item('garbage')).to.eql(undefined);
+ expect(presets.item('residential').addable()).to.be.true;
+ expect(presets.item('park').addable()).to.be.true;
- var ids = new Set([null, undefined, '', 'garbage', 'residential']); // can only add preset with these IDs
- presets.addablePresetIDs(ids);
+ var ids = new Set([null, undefined, '', 'garbage', 'residential']); // can only add preset with these IDs
+ presets.addablePresetIDs(ids);
- expect(presets.item(null)).to.eql(undefined);
- expect(presets.item(undefined)).to.eql(undefined);
- expect(presets.item('')).to.eql(undefined);
- expect(presets.item('garbage')).to.eql(undefined);
- expect(presets.item('residential').addable()).to.be.true;
- expect(presets.item('park').addable()).to.be.false;
- expect(presets.addablePresetIDs()).to.eql(ids);
+ expect(presets.item(null)).to.eql(undefined);
+ expect(presets.item(undefined)).to.eql(undefined);
+ expect(presets.item('')).to.eql(undefined);
+ expect(presets.item('garbage')).to.eql(undefined);
+ expect(presets.item('residential').addable()).to.be.true;
+ expect(presets.item('park').addable()).to.be.false;
+ expect(presets.addablePresetIDs()).to.eql(ids);
- presets.addablePresetIDs(null);
- expect(presets.item(null)).to.eql(undefined);
- expect(presets.item(undefined)).to.eql(undefined);
- expect(presets.item('')).to.eql(undefined);
- expect(presets.item('garbage')).to.eql(undefined);
- expect(presets.item('residential').addable()).to.be.true;
- expect(presets.item('park').addable()).to.be.true;
-
- done();
- });
+ presets.addablePresetIDs(null);
+ expect(presets.item(null)).to.eql(undefined);
+ expect(presets.item(undefined)).to.eql(undefined);
+ expect(presets.item('')).to.eql(undefined);
+ expect(presets.item('garbage')).to.eql(undefined);
+ expect(presets.item('residential').addable()).to.be.true;
+ expect(presets.item('park').addable()).to.be.true;
});
- it('addablePresetIDs are default presets', function (done) {
+ it('addablePresetIDs are default presets', async () => {
iD.fileFetcher.cache().preset_presets = testPresets;
var presets = iD.presetIndex();
- presets.ensureLoaded().then(function() {
- var ids = new Set(['bench', 'residential']); // can only add presets with these IDs
- presets.addablePresetIDs(ids);
+ await presets.ensureLoaded();
+ var ids = new Set(['bench', 'residential']); // can only add presets with these IDs
+ presets.addablePresetIDs(ids);
- var areaDefaults = presets.defaults('area', 10).collection;
- expect(areaDefaults.length).to.eql(0);
+ var areaDefaults = presets.defaults('area', 10).collection;
+ expect(areaDefaults.length).to.eql(0);
- var pointDefaults = presets.defaults('point', 10).collection;
- expect(pointDefaults.length).to.eql(1);
- expect(pointDefaults[0].id).to.eql('bench');
+ var pointDefaults = presets.defaults('point', 10).collection;
+ expect(pointDefaults.length).to.eql(1);
+ expect(pointDefaults[0].id).to.eql('bench');
- var lineDefaults = presets.defaults('line', 10).collection;
- expect(lineDefaults.length).to.eql(2);
- expect(lineDefaults[0].id).to.eql('bench');
- expect(lineDefaults[1].id).to.eql('residential');
-
- done();
- });
+ var lineDefaults = presets.defaults('line', 10).collection;
+ expect(lineDefaults.length).to.eql(2);
+ expect(lineDefaults[0].id).to.eql('bench');
+ expect(lineDefaults[1].id).to.eql('residential');
});
});
@@ -347,40 +315,34 @@ describe('iD.presetIndex', function () {
}
};
- it('prefers building to multipolygon', function (done) {
+ it('prefers building to multipolygon', async () => {
iD.fileFetcher.cache().preset_presets = testPresets;
var presets = iD.presetIndex();
var relation = iD.osmRelation({ tags: { type: 'multipolygon', building: 'yes' } });
var graph = iD.coreGraph([relation]);
- presets.ensureLoaded().then(function() {
- var match = presets.match(relation, graph);
- expect(match.id).to.eql('building');
- done();
- });
+ await presets.ensureLoaded();
+ var match = presets.match(relation, graph);
+ expect(match.id).to.eql('building');
});
- it('prefers building to address', function (done) {
+ it('prefers building to address', async () => {
iD.fileFetcher.cache().preset_presets = testPresets;
var presets = iD.presetIndex();
var way = iD.osmWay({ tags: { area: 'yes', building: 'yes', 'addr:housenumber': '1234' } });
var graph = iD.coreGraph([way]);
- presets.ensureLoaded().then(function() {
- var match = presets.match(way, graph);
- expect(match.id).to.eql('building');
- done();
- });
+ await presets.ensureLoaded();
+ var match = presets.match(way, graph);
+ expect(match.id).to.eql('building');
});
- it('prefers pedestrian to area', function (done) {
+ it('prefers pedestrian to area', async () => {
iD.fileFetcher.cache().preset_presets = testPresets;
var presets = iD.presetIndex();
var way = iD.osmWay({ tags: { area: 'yes', highway: 'pedestrian' } });
var graph = iD.coreGraph([way]);
- presets.ensureLoaded().then(function() {
- var match = presets.match(way, graph);
- expect(match.id).to.eql('highway/pedestrian_area');
- done();
- });
+ await presets.ensureLoaded();
+ var match = presets.match(way, graph);
+ expect(match.id).to.eql('highway/pedestrian_area');
});
});
diff --git a/test/spec/renderer/map.js b/test/spec/renderer/map.js
index 4aa234a1c..09af253e8 100644
--- a/test/spec/renderer/map.js
+++ b/test/spec/renderer/map.js
@@ -1,3 +1,4 @@
+import { setTimeout } from 'node:timers/promises';
import css from '../../../css/55_cursors.css?raw';
describe('iD.Map', function() {
@@ -45,26 +46,22 @@ describe('iD.Map', function() {
});
describe('#zoomIn', function() {
- it('increments zoom', function(done) {
+ it('increments zoom', async () => {
expect(map.zoom(4)).to.equal(map);
map.zoomIn();
- window.setTimeout(function() {
- d3.timerFlush();
- expect(map.zoom()).to.be.closeTo(5, 1e-6);
- done();
- }, 275);
+ await setTimeout(275);
+ d3.timerFlush();
+ expect(map.zoom()).to.be.closeTo(5, 1e-6);
});
});
describe('#zoomOut', function() {
- it('decrements zoom', function(done) {
+ it('decrements zoom', async () => {
expect(map.zoom(4)).to.equal(map);
map.zoomOut();
- window.setTimeout(function() {
- d3.timerFlush();
- expect(map.zoom()).to.be.closeTo(3, 1e-6);
- done();
- }, 275);
+ await setTimeout(275);
+ d3.timerFlush();
+ expect(map.zoom()).to.be.closeTo(3, 1e-6);
});
});
@@ -102,15 +99,13 @@ describe('iD.Map', function() {
});
describe('#centerEase', function() {
- it('sets center', function(done) {
+ it('sets center', async () => {
expect(map.center([10, 10])).to.equal(map);
expect(map.centerEase([20, 20], 250)).to.equal(map);
- window.setTimeout(function() {
- d3.timerFlush();
- expect(map.center()[0]).to.be.closeTo(20, 1e-6);
- expect(map.center()[1]).to.be.closeTo(20, 1e-6);
- done();
- }, 275);
+ await setTimeout(275);
+ d3.timerFlush();
+ expect(map.center()[0]).to.be.closeTo(20, 1e-6);
+ expect(map.center()[1]).to.be.closeTo(20, 1e-6);
});
});
diff --git a/test/spec/services/kartaview.js b/test/spec/services/kartaview.js
index c0eb5ce41..346914fbf 100644
--- a/test/spec/services/kartaview.js
+++ b/test/spec/services/kartaview.js
@@ -1,3 +1,5 @@
+import { setTimeout } from 'node:timers/promises';
+
describe('iD.serviceKartaview', function() {
var dimensions = [64, 64];
var context, kartaview;
@@ -52,7 +54,7 @@ describe('iD.serviceKartaview', function() {
});
describe('#loadImages', function() {
- it('fires loadedImages when images are loaded', function(done) {
+ it('fires loadedImages when images are loaded', async () => {
var data = {
status: { apiCode: '600', httpCode: 200, httpMessage: 'Success' },
currentPageItems:[{
@@ -101,15 +103,13 @@ describe('iD.serviceKartaview', function() {
headers: { 'Content-Type': 'application/json' }
});
- kartaview.on('loadedImages', function() {
- expect(fetchMock.calls().length).to.eql(1); // 1 nearby-photos
- done();
- });
-
kartaview.loadImages(context.projection);
+
+ await new Promise(cb => { kartaview.on('loadedImages', cb); });
+ expect(fetchMock.calls().length).to.eql(1); // 1 nearby-photos
});
- it('does not load images around null island', function (done) {
+ it('does not load images around null island', async () => {
var data = {
status: { apiCode: '600', httpCode: 200, httpMessage: 'Success' },
currentPageItems:[{
@@ -164,14 +164,12 @@ describe('iD.serviceKartaview', function() {
kartaview.on('loadedImages', spy);
kartaview.loadImages(context.projection);
- window.setTimeout(function() {
- expect(spy).to.have.been.not.called;
- expect(fetchMock.calls().length).to.eql(0); // no tile requests of any kind
- done();
- }, 200);
+ await setTimeout(200);
+ expect(spy).to.have.been.not.called;
+ expect(fetchMock.calls().length).to.eql(0); // no tile requests of any kind
});
- it('loads multiple pages of image results', function(done) {
+ it('loads multiple pages of image results', async () => {
var features = [];
for (var i = 0; i < 1000; i++) {
var key = String(i);
@@ -202,12 +200,10 @@ describe('iD.serviceKartaview', function() {
headers: { 'Content-Type': 'application/json' }
});
- kartaview.on('loadedImages', function() {
- expect(fetchMock.calls().length).to.eql(2); // 2 nearby-photos
- done();
- });
-
kartaview.loadImages(context.projection);
+
+ await new Promise(cb => { kartaview.on('loadedImages', cb); });
+ expect(fetchMock.calls().length).to.eql(2); // 2 nearby-photos
});
});
diff --git a/test/spec/services/nominatim.js b/test/spec/services/nominatim.js
index 47a552180..3dbf5f7d1 100644
--- a/test/spec/services/nominatim.js
+++ b/test/spec/services/nominatim.js
@@ -1,3 +1,5 @@
+import { setTimeout } from 'node:timers/promises';
+
describe('iD.serviceNominatim', function() {
var nominatim;
@@ -25,7 +27,7 @@ describe('iD.serviceNominatim', function() {
}
describe('#countryCode', function() {
- it('calls the given callback with the results of the country code query', function(done) {
+ it('calls the given callback with the results of the country code query', async () => {
var callback = sinon.spy();
fetchMock.mock(new RegExp('https://nominatim.openstreetmap.org/reverse'), {
body: '{"address":{"country_code":"at"}}',
@@ -35,18 +37,16 @@ describe('iD.serviceNominatim', function() {
nominatim.countryCode([16, 48], callback);
- window.setTimeout(function() {
- expect(parseQueryString(fetchMock.calls()[0][0])).to.eql(
- {zoom: '13', format: 'json', addressdetails: '1', lat: '48', lon: '16'}
- );
- expect(callback).to.have.been.calledWithExactly(null, 'at');
- done();
- }, 50);
+ await setTimeout(50);
+ expect(parseQueryString(fetchMock.calls()[0][0])).to.eql(
+ {zoom: '13', format: 'json', addressdetails: '1', lat: '48', lon: '16'}
+ );
+ expect(callback).to.have.been.calledWithExactly(null, 'at');
});
});
describe('#reverse', function() {
- it('should not cache distant result', function(done) {
+ it('should not cache distant result', async () => {
var callback = sinon.spy();
fetchMock.mock(new RegExp('https://nominatim.openstreetmap.org/reverse'), {
body: '{"address":{"country_code":"at"}}',
@@ -56,36 +56,33 @@ describe('iD.serviceNominatim', function() {
nominatim.reverse([16, 48], callback);
- window.setTimeout(function() {
- expect(parseQueryString(fetchMock.calls()[0][0])).to.eql(
- {zoom: '13', format: 'json', addressdetails: '1', lat: '48', lon: '16'}
- );
- expect(callback).to.have.been.calledWithExactly(null, {address: {country_code:'at'}});
+ await setTimeout(50);
+ expect(parseQueryString(fetchMock.calls()[0][0])).to.eql(
+ {zoom: '13', format: 'json', addressdetails: '1', lat: '48', lon: '16'}
+ );
+ expect(callback).to.have.been.calledWithExactly(null, {address: {country_code:'at'}});
- fetchMock.reset();
- fetchMock.mock(new RegExp('https://nominatim.openstreetmap.org/reverse'), {
- body: '{"address":{"country_code":"cz"}}',
- status: 200,
- headers: { 'Content-Type': 'application/json' }
- });
+ fetchMock.reset();
+ fetchMock.mock(new RegExp('https://nominatim.openstreetmap.org/reverse'), {
+ body: '{"address":{"country_code":"cz"}}',
+ status: 200,
+ headers: { 'Content-Type': 'application/json' }
+ });
- callback = sinon.spy();
- nominatim.reverse([17, 49], callback);
+ callback = sinon.spy();
+ nominatim.reverse([17, 49], callback);
- window.setTimeout(function() {
- expect(parseQueryString(fetchMock.calls()[0][0])).to.eql(
- {zoom: '13', format: 'json', addressdetails: '1', lat: '49', lon: '17'}
- );
- expect(fetchMock.calls()[0][1].headers).to.eql({
- 'Accept-Language': 'en'
- });
- expect(callback).to.have.been.calledWithExactly(null, {address: {country_code:'cz'}});
- done();
- }, 50);
- }, 50);
+ await setTimeout(50);
+ expect(parseQueryString(fetchMock.calls()[0][0])).to.eql(
+ {zoom: '13', format: 'json', addressdetails: '1', lat: '49', lon: '17'}
+ );
+ expect(fetchMock.calls()[0][1].headers).to.eql({
+ 'Accept-Language': 'en'
+ });
+ expect(callback).to.have.been.calledWithExactly(null, {address: {country_code:'cz'}});
});
- it('should cache nearby result', function(done) {
+ it('should cache nearby result', async () => {
var callback = sinon.spy();
fetchMock.mock(new RegExp('https://nominatim.openstreetmap.org/reverse'), {
body: '{"address":{"country_code":"at"}}',
@@ -95,25 +92,22 @@ describe('iD.serviceNominatim', function() {
nominatim.reverse([16, 48], callback);
- window.setTimeout(function() {
- expect(parseQueryString(fetchMock.calls()[0][0])).to.eql(
- {zoom: '13', format: 'json', addressdetails: '1', lat: '48', lon: '16'}
- );
- expect(callback).to.have.been.calledWithExactly(null, {address: {country_code:'at'}});
+ await setTimeout(50);
+ expect(parseQueryString(fetchMock.calls()[0][0])).to.eql(
+ {zoom: '13', format: 'json', addressdetails: '1', lat: '48', lon: '16'}
+ );
+ expect(callback).to.have.been.calledWithExactly(null, {address: {country_code:'at'}});
- fetchMock.resetHistory();
+ fetchMock.resetHistory();
- callback = sinon.spy();
- nominatim.reverse([16.000001, 48.000001], callback);
+ callback = sinon.spy();
+ nominatim.reverse([16.000001, 48.000001], callback);
- window.setTimeout(function() {
- expect(callback).to.have.been.calledWithExactly(null, {address: {country_code:'at'}});
- done();
- }, 50);
- }, 50);
+ await setTimeout(50);
+ expect(callback).to.have.been.calledWithExactly(null, {address: {country_code:'at'}});
});
- it('calls the given callback with an error', function(done) {
+ it('calls the given callback with an error', async () => {
var callback = sinon.spy();
fetchMock.mock(new RegExp('https://nominatim.openstreetmap.org/reverse'), {
body: '{"error":"Unable to geocode"}',
@@ -124,19 +118,17 @@ describe('iD.serviceNominatim', function() {
nominatim.reverse([1000, 1000], callback);
- window.setTimeout(function() {
- expect(parseQueryString(fetchMock.calls()[0][0])).to.eql(
- {zoom: '13', format: 'json', addressdetails: '1', lat: '1000', lon: '1000'}
- );
- expect(callback).to.have.been.calledWithExactly('Unable to geocode');
- done();
- }, 50);
+ await setTimeout(50);
+ expect(parseQueryString(fetchMock.calls()[0][0])).to.eql(
+ {zoom: '13', format: 'json', addressdetails: '1', lat: '1000', lon: '1000'}
+ );
+ expect(callback).to.have.been.calledWithExactly('Unable to geocode');
});
});
describe('#search', function() {
- it('calls the given callback with the results of the search query', function(done) {
+ it('calls the given callback with the results of the search query', async () => {
var callback = sinon.spy();
fetchMock.mock(new RegExp('https://nominatim.openstreetmap.org/search'), {
body: '[{"place_id":"158484588","osm_type":"relation","osm_id":"188022","boundingbox":["39.867005","40.1379593","-75.2802976","-74.9558313"],"lat":"39.9523993","lon":"-75.1635898","display_name":"Philadelphia, Philadelphia County, Pennsylvania, United States of America","class":"place","type":"city","importance":0.83238050437778}]',
@@ -146,18 +138,16 @@ describe('iD.serviceNominatim', function() {
nominatim.search('philadelphia', callback);
- window.setTimeout(function() {
- expect(parseQueryString(fetchMock.calls()[0][0])).to.eql({
- q: 'philadelphia',
- format: 'json',
- limit: '10'
- });
- expect(fetchMock.calls()[0][1].headers).to.eql({
- 'Accept-Language': 'en'
- });
- expect(callback).to.have.been.calledOnce;
- done();
- }, 50);
+ await setTimeout(50);
+ expect(parseQueryString(fetchMock.calls()[0][0])).to.eql({
+ q: 'philadelphia',
+ format: 'json',
+ limit: '10'
+ });
+ expect(fetchMock.calls()[0][1].headers).to.eql({
+ 'Accept-Language': 'en'
+ });
+ expect(callback).to.have.been.calledOnce;
});
});
diff --git a/test/spec/services/osm.js b/test/spec/services/osm.js
index fcc9d2227..260d7e7fb 100644
--- a/test/spec/services/osm.js
+++ b/test/spec/services/osm.js
@@ -1,3 +1,6 @@
+import { setTimeout } from 'node:timers/promises';
+import { promisify } from 'node:util';
+
describe('iD.serviceOsm', function () {
var context, connection, spy;
var serverXHR;
@@ -149,21 +152,18 @@ describe('iD.serviceOsm', function () {
' ]' +
'}';
- it('returns an object', function(done) {
+ it('returns an object', async () => {
fetchMock.mock('https://www.openstreetmap.org' + path, {
body: response,
status: 200,
headers: { 'Content-Type': 'application/json' }
});
- connection.loadFromAPI(path, function (err, payload) {
- expect(err).to.not.be.ok;
- expect(typeof payload).to.eql('object');
- done();
- });
+ const payload = await promisify(connection.loadFromAPI).call(connection, path);
+ expect(typeof payload).to.eql('object');
});
- it('retries an authenticated call unauthenticated if 401 Unauthorized', function (done) {
+ it('retries an authenticated call unauthenticated if 401 Unauthorized', async () => {
fetchMock.mock('https://www.openstreetmap.org' + path, {
body: response,
status: 200,
@@ -174,19 +174,15 @@ describe('iD.serviceOsm', function () {
login();
- connection.loadFromAPI(path, function (err, xml) {
- expect(err).to.be.not.ok;
- expect(typeof xml).to.eql('object');
- expect(connection.authenticated()).to.be.not.ok;
- expect(fetchMock.called()).to.be.true;
-
- done();
- });
-
+ const xml = promisify(connection.loadFromAPI).call(connection, path);
serverXHR.respond();
+
+ expect(typeof await xml).to.eql('object');
+ expect(connection.authenticated()).to.be.not.ok;
+ expect(fetchMock.called()).to.be.true;
});
- it('retries an authenticated call unauthenticated if 401 Unauthorized', function (done) {
+ it('retries an authenticated call unauthenticated if 401 Unauthorized', async () => {
fetchMock.mock('https://www.openstreetmap.org' + path, {
body: response,
status: 200,
@@ -196,19 +192,16 @@ describe('iD.serviceOsm', function () {
[401, { 'Content-Type': 'text/plain' }, 'Unauthorized']);
login();
- connection.loadFromAPI(path, function (err, xml) {
- expect(err).to.be.not.ok;
- expect(typeof xml).to.eql('object');
- expect(connection.authenticated()).to.be.not.ok;
- expect(fetchMock.called()).to.be.true;
-
- done();
- });
+ const xml = promisify(connection.loadFromAPI).call(connection, path);
serverXHR.respond();
+
+ expect(typeof await xml).to.eql('object');
+ expect(connection.authenticated()).to.be.not.ok;
+ expect(fetchMock.called()).to.be.true;
});
- it('retries an authenticated call unauthenticated if 403 Forbidden', function (done) {
+ it('retries an authenticated call unauthenticated if 403 Forbidden', async () => {
fetchMock.mock('https://www.openstreetmap.org' + path, {
body: response,
status: 200,
@@ -218,20 +211,16 @@ describe('iD.serviceOsm', function () {
[403, { 'Content-Type': 'text/plain' }, 'Forbidden']);
login();
- connection.loadFromAPI(path, function (err, xml) {
- expect(err).to.be.not.ok;
- expect(typeof xml).to.eql('object');
- expect(connection.authenticated()).to.be.not.ok;
- expect(fetchMock.called()).to.be.true;
-
- done();
- });
-
+ const xml = promisify(connection.loadFromAPI).call(connection, path);
serverXHR.respond();
+
+ expect(typeof await xml).to.eql('object');
+ expect(connection.authenticated()).to.be.not.ok;
+ expect(fetchMock.called()).to.be.true;
});
- it('dispatches change event if 509 Bandwidth Limit Exceeded', function (done) {
+ it('dispatches change event if 509 Bandwidth Limit Exceeded', async () => {
fetchMock.mock('https://www.openstreetmap.org' + path, {
body: 'Bandwidth Limit Exceeded',
status: 509,
@@ -240,14 +229,14 @@ describe('iD.serviceOsm', function () {
logout();
connection.on('change', spy);
- connection.loadFromAPI(path, function (err) {
- expect(err).to.have.property('status', 509);
- expect(spy).to.have.been.calledOnce;
- done();
- });
+ const promise = promisify(connection.loadFromAPI).call(connection, path);
+
+ await expect(promise).rejects.toThrow(expect.objectContaining({ status: 509 }));
+
+ expect(spy).to.have.been.calledOnce;
});
- it('dispatches change event if 429 Too Many Requests', function (done) {
+ it('dispatches change event if 429 Too Many Requests', async () => {
fetchMock.mock('https://www.openstreetmap.org' + path, {
body: '429 Too Many Requests',
status: 429,
@@ -256,14 +245,13 @@ describe('iD.serviceOsm', function () {
logout();
connection.on('change', spy);
- connection.loadFromAPI(path, function (err) {
- expect(err).to.have.property('status', 429);
- expect(spy).to.have.been.calledOnce;
- done();
- });
+ const promise = promisify(connection.loadFromAPI).call(connection, path);
+
+ await expect(promise).rejects.toThrow(expect.objectContaining({ status: 429 }));
+ expect(spy).to.have.been.calledOnce;
});
- it('uses apiUrl', function(done) {
+ it('uses apiUrl', async () => {
fetchMock.mock('https://api.openstreetmap.org' + path, {
body: response,
status: 200,
@@ -275,12 +263,10 @@ describe('iD.serviceOsm', function () {
apiUrl: 'https://api.openstreetmap.org'
});
- connection.loadFromAPI(path, function (err) {
- expect(err).to.not.be.ok;
- expect(fetchMock.calls().length).to.eql(1);
- expect(fetchMock.calls()[0][0]).to.eql('https://api.openstreetmap.org' + path);
- done();
- });
+ await promisify(connection.loadFromAPI).call(connection, path);
+
+ expect(fetchMock.calls().length).to.eql(1);
+ expect(fetchMock.calls()[0][0]).to.eql('https://api.openstreetmap.org' + path);
});
});
@@ -303,7 +289,7 @@ describe('iD.serviceOsm', function () {
.clipExtent([[0,0], dimensions]);
});
- it('calls callback when data tiles are loaded', function(done) {
+ it('calls callback when data tiles are loaded', async () => {
fetchMock.mock(/map.json\?bbox/, {
body: tileResponse,
status: 200,
@@ -313,13 +299,11 @@ describe('iD.serviceOsm', function () {
var spy = sinon.spy();
connection.loadTiles(context.projection, spy);
- window.setTimeout(function() {
- expect(spy).to.have.been.calledOnce;
- done();
- }, 500);
+ await setTimeout(500);
+ expect(spy).to.have.been.calledOnce;
});
- it('#isDataLoaded', function(done) {
+ it('#isDataLoaded', async () => {
fetchMock.mock(/map.json\?bbox/, {
body: tileResponse,
status: 200,
@@ -338,11 +322,9 @@ describe('iD.serviceOsm', function () {
connection.loadTiles(context.projection);
- window.setTimeout(function() {
- expect(fetchMock.called()).to.be.true;
- expect(connection.isDataLoaded([-74.0444216, 40.6694299])).to.be.true;
- done();
- }, 500);
+ await setTimeout(500);
+ expect(fetchMock.called()).to.be.true;
+ expect(connection.isDataLoaded([-74.0444216, 40.6694299])).to.be.true;
});
});
@@ -364,7 +346,7 @@ describe('iD.serviceOsm', function () {
' ]' +
'}';
- it('loads a node', function(done) {
+ it('loads a node', async () => {
fetchMock.mock('https://www.openstreetmap.org/api/0.6/node/1.json', {
body: nodeResponse,
status: 200,
@@ -372,14 +354,13 @@ describe('iD.serviceOsm', function () {
});
var id = 'n1';
- connection.loadEntity(id, function(err, result) {
- var entity = result.data.find(function(e) { return e.id === id; });
- expect(entity).to.be.an.instanceOf(iD.osmNode);
- done();
- });
+ const result = await promisify(connection.loadEntity).call(connection, id);
+
+ var entity = result.data.find(function(e) { return e.id === id; });
+ expect(entity).to.be.an.instanceOf(iD.osmNode);
});
- it('loads a way', function(done) {
+ it('loads a way', async () => {
fetchMock.mock('https://www.openstreetmap.org/api/0.6/way/1/full.json', {
body: wayResponse,
status: 200,
@@ -387,14 +368,13 @@ describe('iD.serviceOsm', function () {
});
var id = 'w1';
- connection.loadEntity(id, function(err, result) {
- var entity = result.data.find(function(e) { return e.id === id; });
- expect(entity).to.be.an.instanceOf(iD.osmWay);
- done();
- });
+ const result = await promisify(connection.loadEntity).call(connection, id);
+
+ var entity = result.data.find(function(e) { return e.id === id; });
+ expect(entity).to.be.an.instanceOf(iD.osmWay);
});
- it('does not ignore repeat requests', function(done) {
+ it('does not ignore repeat requests', async () => {
fetchMock.mock('https://www.openstreetmap.org/api/0.6/node/1.json', {
body: wayResponse,
status: 200,
@@ -402,16 +382,13 @@ describe('iD.serviceOsm', function () {
});
var id = 'n1';
- connection.loadEntity(id, function(err1, result1) {
- var entity1 = result1.data.find(function(e1) { return e1.id === id; });
- expect(entity1).to.be.an.instanceOf(iD.osmNode);
+ const result1 = await promisify(connection.loadEntity).call(connection, id);
+ var entity1 = result1.data.find(function(e1) { return e1.id === id; });
+ expect(entity1).to.be.an.instanceOf(iD.osmNode);
- connection.loadEntity(id, function(err2, result2) {
- var entity2 = result2.data.find(function(e2) { return e2.id === id; });
- expect(entity2).to.be.an.instanceOf(iD.osmNode);
- done();
- });
- });
+ const result2 = await promisify(connection.loadEntity).call(connection, id);
+ var entity2 = result2.data.find(function(e2) { return e2.id === id; });
+ expect(entity2).to.be.an.instanceOf(iD.osmNode);
});
});
@@ -433,7 +410,7 @@ describe('iD.serviceOsm', function () {
' ]' +
'}';
- it('loads a node', function(done) {
+ it('loads a node', async () => {
fetchMock.mock('https://www.openstreetmap.org/api/0.6/node/1/1.json', {
body: nodeResponse,
status: 200,
@@ -441,14 +418,13 @@ describe('iD.serviceOsm', function () {
});
var id = 'n1';
- connection.loadEntityVersion(id, 1, function(err, result) {
- var entity = result.data.find(function(e) { return e.id === id; });
- expect(entity).to.be.an.instanceOf(iD.osmNode);
- done();
- });
+ const result = await promisify(connection.loadEntityVersion).call(connection, id, 1);
+
+ var entity = result.data.find(function(e) { return e.id === id; });
+ expect(entity).to.be.an.instanceOf(iD.osmNode);
});
- it('loads a way', function(done) {
+ it('loads a way', async () => {
fetchMock.mock('https://www.openstreetmap.org/api/0.6/way/1/1.json', {
body: wayResponse,
status: 200,
@@ -456,14 +432,13 @@ describe('iD.serviceOsm', function () {
});
var id = 'w1';
- connection.loadEntityVersion(id, 1, function(err, result) {
- var entity = result.data.find(function(e) { return e.id === id; });
- expect(entity).to.be.an.instanceOf(iD.osmWay);
- done();
- });
+ const result = await promisify(connection.loadEntityVersion).call(connection, id, 1);
+
+ var entity = result.data.find(function(e) { return e.id === id; });
+ expect(entity).to.be.an.instanceOf(iD.osmWay);
});
- it('does not ignore repeat requests', function(done) {
+ it('does not ignore repeat requests', async () => {
fetchMock.mock('https://www.openstreetmap.org/api/0.6/node/1/1.json', {
body: nodeResponse,
status: 200,
@@ -471,16 +446,15 @@ describe('iD.serviceOsm', function () {
});
var id = 'n1';
- connection.loadEntityVersion(id, 1, function(err1, result1) {
- var entity1 = result1.data.find(function(e1) { return e1.id === id; });
- expect(entity1).to.be.an.instanceOf(iD.osmNode);
+ const result1 = await promisify(connection.loadEntityVersion).call(connection, id, 1);
- connection.loadEntityVersion(id, 1, function(err2, result2) {
- var entity2 = result2.data.find(function(e2) { return e2.id === id; });
- expect(entity2).to.be.an.instanceOf(iD.osmNode);
- done();
- });
- });
+ var entity1 = result1.data.find(function(e1) { return e1.id === id; });
+ expect(entity1).to.be.an.instanceOf(iD.osmNode);
+
+ const result2 = await promisify(connection.loadEntityVersion).call(connection, id, 1);
+
+ var entity2 = result2.data.find(function(e2) { return e2.id === id; });
+ expect(entity2).to.be.an.instanceOf(iD.osmNode);
});
});
@@ -507,7 +481,7 @@ describe('iD.serviceOsm', function () {
});
- it('loads user changesets', function(done) {
+ it('loads user changesets', async () => {
var changesetsXML = '' +
'' +
'' +
@@ -517,23 +491,23 @@ describe('iD.serviceOsm', function () {
'';
login();
- connection.userChangesets(function(err, changesets) {
- expect(changesets).to.deep.equal([{
- tags: {
- comment: 'Caprice Court has been extended',
- created_by: 'iD 2.0.0'
- }
- }]);
- connection.logout();
- done();
- });
serverXHR.respondWith('GET', 'https://www.openstreetmap.org/api/0.6/changesets\\?user=1',
[200, { 'Content-Type': 'text/xml' }, changesetsXML]);
serverXHR.respond();
+
+ const changesets = await promisify(connection.userChangesets).call(connection);
+
+ expect(changesets).to.deep.equal([{
+ tags: {
+ comment: 'Caprice Court has been extended',
+ created_by: 'iD 2.0.0'
+ }
+ }]);
+ connection.logout();
});
- it('excludes changesets without comment tag', function(done) {
+ it('excludes changesets without comment tag', async () => {
var changesetsXML = '' +
'' +
'' +
@@ -546,23 +520,23 @@ describe('iD.serviceOsm', function () {
'';
login();
- connection.userChangesets(function(err, changesets) {
- expect(changesets).to.deep.equal([{
- tags: {
- comment: 'Caprice Court has been extended',
- created_by: 'iD 2.0.0'
- }
- }]);
- connection.logout();
- done();
- });
serverXHR.respondWith('GET', 'https://www.openstreetmap.org/api/0.6/changesets\\?user=1',
[200, { 'Content-Type': 'text/xml' }, changesetsXML]);
serverXHR.respond();
+
+ const changesets = await promisify(connection.userChangesets).call(connection);
+
+ expect(changesets).to.deep.equal([{
+ tags: {
+ comment: 'Caprice Court has been extended',
+ created_by: 'iD 2.0.0'
+ }
+ }]);
+ connection.logout();
});
- it('excludes changesets with empty comment', function(done) {
+ it('excludes changesets with empty comment', async () => {
var changesetsXML = '' +
'' +
'' +
@@ -576,20 +550,20 @@ describe('iD.serviceOsm', function () {
'';
login();
- connection.userChangesets(function(err, changesets) {
- expect(changesets).to.deep.equal([{
- tags: {
- comment: 'Caprice Court has been extended',
- created_by: 'iD 2.0.0'
- }
- }]);
- connection.logout();
- done();
- });
serverXHR.respondWith('GET', 'https://www.openstreetmap.org/api/0.6/changesets\\?user=1',
[200, { 'Content-Type': 'text/xml' }, changesetsXML]);
serverXHR.respond();
+
+ const changesets = await promisify(connection.userChangesets)();
+
+ expect(changesets).to.deep.equal([{
+ tags: {
+ comment: 'Caprice Court has been extended',
+ created_by: 'iD 2.0.0'
+ }
+ }]);
+ connection.logout();
});
});
@@ -668,7 +642,7 @@ describe('iD.serviceOsm', function () {
.clipExtent([[0,0], dimensions]);
});
- it('fires loadedNotes when notes are loaded', function(done) {
+ it('fires loadedNotes when notes are loaded', async () => {
fetchMock.mock(/notes\?/, {
body: notesXML,
status: 200,
@@ -678,10 +652,8 @@ describe('iD.serviceOsm', function () {
connection.on('loadedNotes', spy);
connection.loadNotes(context.projection, {});
- window.setTimeout(function() {
- expect(spy).to.have.been.calledOnce;
- done();
- }, 500);
+ await setTimeout(500);
+ expect(spy).to.have.been.calledOnce;
});
});
@@ -785,7 +757,7 @@ describe('iD.serviceOsm', function () {
`;
describe('#status', function() {
- it('gets API status', function(done) {
+ it('gets API status', async () => {
fetchMock.mock('https://www.openstreetmap.org/api/capabilities', {
body: capabilitiesXML,
status: 200,
@@ -794,15 +766,13 @@ describe('iD.serviceOsm', function () {
overwriteRoutes: true
});
- connection.status(function (err, val) {
- expect(val).to.eql('online');
- done();
- });
+ const val = await promisify(connection.status).call(connection);
+ expect(val).to.eql('online');
});
});
describe('#imageryBlocklists', function() {
- it('updates imagery blocklists', function(done) {
+ it('updates imagery blocklists', async () => {
fetchMock.mock('https://www.openstreetmap.org/api/capabilities', {
body: capabilitiesXML,
status: 200,
@@ -811,11 +781,9 @@ describe('iD.serviceOsm', function () {
overwriteRoutes: true
});
- connection.status(function() {
- var blocklists = connection.imageryBlocklists();
- expect(blocklists).to.deep.equal([new RegExp('\.foo\.com'), new RegExp('\.bar\.org')]);
- done();
- });
+ await promisify(connection.status).call(connection);
+ var blocklists = connection.imageryBlocklists();
+ expect(blocklists).to.deep.equal([new RegExp('\.foo\.com'), new RegExp('\.bar\.org')]);
});
});
diff --git a/test/spec/services/osm_wikibase.js b/test/spec/services/osm_wikibase.js
index ce736f477..52d94bc1a 100644
--- a/test/spec/services/osm_wikibase.js
+++ b/test/spec/services/osm_wikibase.js
@@ -1,3 +1,5 @@
+import { setTimeout } from 'node:timers/promises';
+
describe('iD.serviceOsmWikibase', function () {
var wikibase;
@@ -262,7 +264,7 @@ describe('iD.serviceOsmWikibase', function () {
};
describe('#getEntity', function () {
- it('calls the given callback with the results of the getEntity data item query', function (done) {
+ it('calls the given callback with the results of the getEntity data item query', async () => {
var callback = sinon.spy();
fetchMock.mock(/action=wbgetentities/, {
body: JSON.stringify({
@@ -279,24 +281,22 @@ describe('iD.serviceOsmWikibase', function () {
wikibase.getEntity({ key: 'amenity', value: 'parking', langCodes: ['fr'] }, callback);
- window.setTimeout(function () {
- expect(parseQueryString(fetchMock.calls()[0][0])).to.eql(
- {
- action: 'wbgetentities',
- sites: 'wiki',
- titles: 'Locale:fr|Key:amenity|Tag:amenity=parking',
- languages: 'fr',
- languagefallback: '1',
- origin: '*',
- format: 'json',
- }
- );
- expect(callback).to.have.been.calledWith(null, {
- key: keyData(),
- tag: tagData()
- });
- done();
- }, 50);
+ await setTimeout(50);
+ expect(parseQueryString(fetchMock.calls()[0][0])).to.eql(
+ {
+ action: 'wbgetentities',
+ sites: 'wiki',
+ titles: 'Locale:fr|Key:amenity|Tag:amenity=parking',
+ languages: 'fr',
+ languagefallback: '1',
+ origin: '*',
+ format: 'json',
+ }
+ );
+ expect(callback).to.have.been.calledWith(null, {
+ key: keyData(),
+ tag: tagData()
+ });
});
});
diff --git a/test/spec/services/streetside.js b/test/spec/services/streetside.js
index 3caea8c71..c7596bb32 100644
--- a/test/spec/services/streetside.js
+++ b/test/spec/services/streetside.js
@@ -1,3 +1,5 @@
+import { setTimeout } from 'node:timers/promises';
+
describe('iD.serviceStreetside', function() {
var dimensions = [64, 64];
var context, streetside;
@@ -47,7 +49,7 @@ describe('iD.serviceStreetside', function() {
});
describe('#loadBubbles', function() {
- it('fires loadedImages when bubbles are loaded', function(done) {
+ it('fires loadedImages when bubbles are loaded', async () => {
// adjust projection so that only one tile is fetched
// (JSONP hack will return the same data for every fetch)
context.projection
@@ -71,13 +73,11 @@ describe('iD.serviceStreetside', function() {
streetside.loadBubbles(context.projection, 0); // 0 = don't fetch margin tiles
- window.setTimeout(function() {
- expect(spy).to.have.been.calledOnce;
- done();
- }, 200);
+ await setTimeout(200);
+ expect(spy).to.have.been.calledOnce;
});
- it('does not load bubbles around null island', function(done) {
+ it('does not load bubbles around null island', async () => {
context.projection
.scale(iD.geoZoomToScale(18))
.translate([0, 0])
@@ -99,10 +99,8 @@ describe('iD.serviceStreetside', function() {
streetside.loadBubbles(context.projection, 0); // 0 = don't fetch margin tiles
- window.setTimeout(function() {
- expect(spy).to.have.been.not.called;
- done();
- }, 200);
+ await setTimeout(200);
+ expect(spy).to.have.been.not.called;
});
});
diff --git a/test/spec/services/taginfo.js b/test/spec/services/taginfo.js
index cdb35deac..558632bfc 100644
--- a/test/spec/services/taginfo.js
+++ b/test/spec/services/taginfo.js
@@ -1,3 +1,5 @@
+import { setTimeout } from 'node:timers/promises';
+
describe('iD.serviceTaginfo', function() {
var taginfo;
@@ -33,7 +35,7 @@ describe('iD.serviceTaginfo', function() {
}
describe('#keys', function() {
- it('calls the given callback with the results of the keys query', function(done) {
+ it('calls the given callback with the results of the keys query', async () => {
fetchMock.mock(/\/keys\/all/, {
body: '{"data":[{"count_all":5190337,"key":"amenity","count_all_fraction":1.0}]}',
status: 200,
@@ -43,18 +45,16 @@ describe('iD.serviceTaginfo', function() {
var callback = sinon.spy();
taginfo.keys({ query: 'amen' }, callback);
- window.setTimeout(function() {
- expect(parseQueryString(fetchMock.calls()[0][0])).to.eql(
- {query: 'amen', page: '1', rp: '10', sortname: 'count_all', sortorder: 'desc', lang: 'en'}
- );
- expect(callback).to.have.been.calledWith(
- null, [{'title':'amenity', 'value':'amenity'}]
- );
- done();
- }, 50);
+ await setTimeout(50);
+ expect(parseQueryString(fetchMock.calls()[0][0])).to.eql(
+ {query: 'amen', page: '1', rp: '10', sortname: 'count_all', sortorder: 'desc', lang: 'en'}
+ );
+ expect(callback).to.have.been.calledWith(
+ null, [{'title':'amenity', 'value':'amenity'}]
+ );
});
- it('includes popular keys', function(done) {
+ it('includes popular keys', async () => {
fetchMock.mock(/\/keys\/all/, {
body: '{"data":[{"count_all":5190337,"count_nodes":500000,"key":"amenity","count_all_fraction":1.0, "count_nodes_fraction":1.0},'
+ '{"count_all":1,"key":"amenityother","count_all_fraction":0.0, "count_nodes":100}]}',
@@ -65,15 +65,13 @@ describe('iD.serviceTaginfo', function() {
var callback = sinon.spy();
taginfo.keys({ query: 'amen' }, callback);
- window.setTimeout(function() {
- expect(callback).to.have.been.calledWith(
- null, [{'title':'amenity', 'value':'amenity'}]
- );
- done();
- }, 50);
+ await setTimeout(50);
+ expect(callback).to.have.been.calledWith(
+ null, [{'title':'amenity', 'value':'amenity'}]
+ );
});
- it('includes popular keys with an entity type filter', function(done) {
+ it('includes popular keys with an entity type filter', async () => {
fetchMock.mock(/\/keys\/all/, {
body: '{"data":[{"count_all":5190337,"count_nodes":500000,"key":"amenity","count_all_fraction":1.0, "count_nodes_fraction":1.0},'
+ '{"count_all":1,"key":"amenityother","count_all_fraction":0.0, "count_nodes":100}]}',
@@ -84,15 +82,13 @@ describe('iD.serviceTaginfo', function() {
var callback = sinon.spy();
taginfo.keys({ query: 'amen', filter: 'nodes' }, callback);
- window.setTimeout(function() {
- expect(callback).to.have.been.calledWith(
- null, [{'title':'amenity', 'value':'amenity'}]
- );
- done();
- }, 50);
+ await setTimeout(50);
+ expect(callback).to.have.been.calledWith(
+ null, [{'title':'amenity', 'value':'amenity'}]
+ );
});
- it('includes unpopular keys with a wiki page', function(done) {
+ it('includes unpopular keys with a wiki page', async () => {
fetchMock.mock(/\/keys\/all/, {
body: '{"data":[{"count_all":5190337,"key":"amenity","count_all_fraction":1.0, "count_nodes_fraction":1.0},'
+ '{"count_all":1,"key":"amenityother","count_all_fraction":0.0, "count_nodes_fraction":0.0, "in_wiki": true}]}',
@@ -103,16 +99,14 @@ describe('iD.serviceTaginfo', function() {
var callback = sinon.spy();
taginfo.keys({ query: 'amen' }, callback);
- window.setTimeout(function() {
- expect(callback).to.have.been.calledWith(null, [
- {'title':'amenity', 'value':'amenity'},
- {'title':'amenityother', 'value':'amenityother'}
- ]);
- done();
- }, 50);
+ await setTimeout(50);
+ expect(callback).to.have.been.calledWith(null, [
+ {'title':'amenity', 'value':'amenity'},
+ {'title':'amenityother', 'value':'amenityother'}
+ ]);
});
- it('sorts keys with \':\' below keys without \':\'', function(done) {
+ it('sorts keys with \':\' below keys without \':\'', async () => {
fetchMock.mock(/\/keys\/all/, {
body: '{"data":[{"key":"ref:bag","count_all":9790586,"count_all_fraction":0.0028},' +
'{"key":"ref","count_all":7933528,"count_all_fraction":0.0023}]}',
@@ -123,17 +117,15 @@ describe('iD.serviceTaginfo', function() {
var callback = sinon.spy();
taginfo.keys({ query: 'ref' }, callback);
- window.setTimeout(function() {
- expect(callback).to.have.been.calledWith(
- null, [{'title':'ref', 'value':'ref'},{'title':'ref:bag', 'value':'ref:bag'}]
- );
- done();
- }, 50);
+ await setTimeout(50);
+ expect(callback).to.have.been.calledWith(
+ null, [{'title':'ref', 'value':'ref'},{'title':'ref:bag', 'value':'ref:bag'}]
+ );
});
});
describe('#multikeys', function() {
- it('calls the given callback with the results of the multikeys query', function(done) {
+ it('calls the given callback with the results of the multikeys query', async () => {
fetchMock.mock(/\/keys\/all/, {
body: '{"data":[{"count_all":69593,"key":"recycling:glass","count_all_fraction":0.0}]}',
status: 200,
@@ -143,18 +135,16 @@ describe('iD.serviceTaginfo', function() {
var callback = sinon.spy();
taginfo.multikeys({ query: 'recycling:' }, callback);
- window.setTimeout(function() {
- expect(parseQueryString(fetchMock.calls()[0][0])).to.eql(
- {query: 'recycling:', page: '1', rp: '25', sortname: 'count_all', sortorder: 'desc', lang: 'en'}
- );
- expect(callback).to.have.been.calledWith(
- null, [{'title':'recycling:glass', 'value':'recycling:glass'}]
- );
- done();
- }, 50);
+ await setTimeout(50);
+ expect(parseQueryString(fetchMock.calls()[0][0])).to.eql(
+ {query: 'recycling:', page: '1', rp: '25', sortname: 'count_all', sortorder: 'desc', lang: 'en'}
+ );
+ expect(callback).to.have.been.calledWith(
+ null, [{'title':'recycling:glass', 'value':'recycling:glass'}]
+ );
});
- it('excludes multikeys with extra colons', function(done) {
+ it('excludes multikeys with extra colons', async () => {
fetchMock.mock(/\/keys\/all/, {
body: '{"data":[{"count_all":4426,"key":"service:bicycle:retail","count_all_fraction":0.0},' +
'{"count_all":22,"key":"service:bicycle:retail:ebikes","count_all_fraction":0.0}]}',
@@ -165,15 +155,13 @@ describe('iD.serviceTaginfo', function() {
var callback = sinon.spy();
taginfo.multikeys({ query: 'service:bicycle:' }, callback);
- window.setTimeout(function() {
- expect(callback).to.have.been.calledWith(
- null, [{'title':'service:bicycle:retail', 'value':'service:bicycle:retail'}]
- );
- done();
- }, 50);
+ await setTimeout(50);
+ expect(callback).to.have.been.calledWith(
+ null, [{'title':'service:bicycle:retail', 'value':'service:bicycle:retail'}]
+ );
});
- it('excludes multikeys with wrong prefix', function(done) {
+ it('excludes multikeys with wrong prefix', async () => {
fetchMock.mock(/\/keys\/all/, {
body: '{"data":[{"count_all":4426,"key":"service:bicycle:retail","count_all_fraction":0.0},' +
'{"count_all":22,"key":"disused:service:bicycle","count_all_fraction":0.0}]}',
@@ -184,17 +172,15 @@ describe('iD.serviceTaginfo', function() {
var callback = sinon.spy();
taginfo.multikeys({ query: 'service:bicycle:' }, callback);
- window.setTimeout(function() {
- expect(callback).to.have.been.calledWith(
- null, [{'title':'service:bicycle:retail', 'value':'service:bicycle:retail'}]
- );
- done();
- }, 50);
+ await setTimeout(50);
+ expect(callback).to.have.been.calledWith(
+ null, [{'title':'service:bicycle:retail', 'value':'service:bicycle:retail'}]
+ );
});
});
describe('#values', function() {
- it('calls the given callback with the results of the values query', function(done) {
+ it('calls the given callback with the results of the values query', async () => {
fetchMock.mock(/\/key\/values/, {
body: '{"data":[{"value":"parking","description":"A place for parking cars", "count":1000}]}',
status: 200,
@@ -204,18 +190,16 @@ describe('iD.serviceTaginfo', function() {
var callback = sinon.spy();
taginfo.values({ key: 'amenity', query: 'par' }, callback);
- window.setTimeout(function() {
- expect(parseQueryString(fetchMock.calls()[0][0])).to.eql(
- {key: 'amenity', query: 'par', page: '1', rp: '25', sortname: 'count_all', sortorder: 'desc', lang: 'en'}
- );
- expect(callback).to.have.been.calledWith(
- null, [{'value':'parking','title':'A place for parking cars'}]
- );
- done();
- }, 50);
+ await setTimeout(50);
+ expect(parseQueryString(fetchMock.calls()[0][0])).to.eql(
+ {key: 'amenity', query: 'par', page: '1', rp: '25', sortname: 'count_all', sortorder: 'desc', lang: 'en'}
+ );
+ expect(callback).to.have.been.calledWith(
+ null, [{'value':'parking','title':'A place for parking cars'}]
+ );
});
- it('includes popular values', function(done) {
+ it('includes popular values', async () => {
fetchMock.mock(/\/key\/values/, {
body: '{"data":[{"value":"parking","description":"A place for parking cars", "count":1000},' +
'{"value":"party","description":"A place for partying", "count":1}]}',
@@ -226,15 +210,13 @@ describe('iD.serviceTaginfo', function() {
var callback = sinon.spy();
taginfo.values({ key: 'amenity', query: 'par' }, callback);
- window.setTimeout(function() {
- expect(callback).to.have.been.calledWith(
- null, [{'value':'parking','title':'A place for parking cars'}]
- );
- done();
- }, 50);
+ await setTimeout(50);
+ expect(callback).to.have.been.calledWith(
+ null, [{'value':'parking','title':'A place for parking cars'}]
+ );
});
- it('does not get values for extremely unpopular keys', function(done) {
+ it('does not get values for extremely unpopular keys', async () => {
fetchMock.mock(/\/key\/values/, {
body: '{"data":[{"value":"Rue Pasteur","description":"", "count":3},' +
'{"value":"Via Trieste","description":"", "count":1}]}',
@@ -245,13 +227,11 @@ describe('iD.serviceTaginfo', function() {
var callback = sinon.spy();
taginfo.values({ key: 'name', query: 'ste' }, callback);
- window.setTimeout(function() {
- expect(callback).to.have.been.calledWith(null, []);
- done();
- }, 50);
+ await setTimeout(50);
+ expect(callback).to.have.been.calledWith(null, []);
});
- it('includes unpopular values with a wiki page', function(done) {
+ it('includes unpopular values with a wiki page', async () => {
fetchMock.mock(/\/key\/values/, {
body: '{"data":[{"value":"party","description":"A place for partying", "count":1, "in_wiki": true}]}',
status: 200,
@@ -261,15 +241,13 @@ describe('iD.serviceTaginfo', function() {
var callback = sinon.spy();
taginfo.values({ key: 'amenity', query: 'par' }, callback);
- window.setTimeout(function() {
- expect(callback).to.have.been.calledWith(
- null, [{'value':'party','title':'A place for partying'}]
- );
- done();
- }, 50);
+ await setTimeout(50);
+ expect(callback).to.have.been.calledWith(
+ null, [{'value':'party','title':'A place for partying'}]
+ );
});
- it('excludes values with capital letters and some punctuation', function(done) {
+ it('excludes values with capital letters and some punctuation', async () => {
fetchMock.mock(/\/key\/values/, {
body: '{"data":[{"value":"parking","description":"A place for parking cars", "count":2000},'
+ '{"value":"PArking","description":"A common misspelling", "count":200},'
@@ -283,15 +261,13 @@ describe('iD.serviceTaginfo', function() {
var callback = sinon.spy();
taginfo.values({ key: 'amenity', query: 'par' }, callback);
- window.setTimeout(function() {
- expect(callback).to.have.been.calledWith(
- null, [{'value':'parking','title':'A place for parking cars'}]
- );
- done();
- }, 50);
+ await setTimeout(50);
+ expect(callback).to.have.been.calledWith(
+ null, [{'value':'parking','title':'A place for parking cars'}]
+ );
});
- it('includes network values with capital letters and some punctuation', function(done) {
+ it('includes network values with capital letters and some punctuation', async () => {
fetchMock.mock(/\/key\/values/, {
body: '{"data":[{"value":"US:TX:FM","description":"Farm to Market Roads in the U.S. state of Texas.", "count":34000},'
+ '{"value":"US:KY","description":"Primary and secondary state highways in the U.S. state of Kentucky.", "count":31000},'
@@ -305,19 +281,17 @@ describe('iD.serviceTaginfo', function() {
var callback = sinon.spy();
taginfo.values({ key: 'network', query: 'us' }, callback);
- window.setTimeout(function() {
- expect(callback).to.have.been.calledWith(null, [
- {'value':'US:TX:FM','title':'Farm to Market Roads in the U.S. state of Texas.'},
- {'value':'US:KY','title':'Primary and secondary state highways in the U.S. state of Kentucky.'},
- {'value':'US:US','title':'U.S. routes in the United States.'},
- {'value':'US:I','title':'Interstate highways in the United States.'},
- {'value':'US:MD','title':'State highways in the U.S. state of Maryland.'}
- ]);
- done();
- }, 50);
+ await setTimeout(50);
+ expect(callback).to.have.been.calledWith(null, [
+ {'value':'US:TX:FM','title':'Farm to Market Roads in the U.S. state of Texas.'},
+ {'value':'US:KY','title':'Primary and secondary state highways in the U.S. state of Kentucky.'},
+ {'value':'US:US','title':'U.S. routes in the United States.'},
+ {'value':'US:I','title':'Interstate highways in the United States.'},
+ {'value':'US:MD','title':'State highways in the U.S. state of Maryland.'}
+ ]);
});
- it('includes biological genus values with capital letters', function(done) {
+ it('includes biological genus values with capital letters', async () => {
fetchMock.mock(/\/key\/values/, {
body: '{"data":[{"value":"Quercus","description":"Oak", "count": 1000}]}',
status: 200,
@@ -327,15 +301,13 @@ describe('iD.serviceTaginfo', function() {
var callback = sinon.spy();
taginfo.values({ key: 'genus', query: 'qu' }, callback);
- window.setTimeout(function() {
- expect(callback).to.have.been.calledWith(
- null, [{'value':'Quercus','title':'Oak'}]
- );
- done();
- }, 50);
+ await setTimeout(50);
+ expect(callback).to.have.been.calledWith(
+ null, [{'value':'Quercus','title':'Oak'}]
+ );
});
- it('includes biological taxon values with capital letters', function(done) {
+ it('includes biological taxon values with capital letters', async () => {
fetchMock.mock(/\/key\/values/, {
body: '{"data":[{"value":"Quercus robur","description":"Oak", "count": 1000}]}',
status: 200,
@@ -345,15 +317,13 @@ describe('iD.serviceTaginfo', function() {
var callback = sinon.spy();
taginfo.values({ key: 'taxon', query: 'qu' }, callback);
- window.setTimeout(function() {
- expect(callback).to.have.been.calledWith(
- null, [{'value':'Quercus robur','title':'Oak'}]
- );
- done();
- }, 50);
+ await setTimeout(50);
+ expect(callback).to.have.been.calledWith(
+ null, [{'value':'Quercus robur','title':'Oak'}]
+ );
});
- it('includes biological species values with capital letters', function(done) {
+ it('includes biological species values with capital letters', async () => {
fetchMock.mock(/\/key\/values/, {
body: '{"data":[{"value":"Quercus robur","description":"Oak", "count": 1000}]}',
status: 200,
@@ -363,17 +333,15 @@ describe('iD.serviceTaginfo', function() {
var callback = sinon.spy();
taginfo.values({ key: 'species', query: 'qu' }, callback);
- window.setTimeout(function() {
- expect(callback).to.have.been.calledWith(
- null, [{'value':'Quercus robur','title':'Oak'}]
- );
- done();
- }, 50);
+ await setTimeout(50);
+ expect(callback).to.have.been.calledWith(
+ null, [{'value':'Quercus robur','title':'Oak'}]
+ );
});
});
describe('#roles', function() {
- it('calls the given callback with the results of the roles query', function(done) {
+ it('calls the given callback with the results of the roles query', async () => {
fetchMock.mock(/\/relation\/roles/, {
body: '{"data":[{"role":"stop","count_relation_members_fraction":0.1757},' +
'{"role":"south","count_relation_members_fraction":0.0035}]}',
@@ -384,21 +352,19 @@ describe('iD.serviceTaginfo', function() {
var callback = sinon.spy();
taginfo.roles({ rtype: 'route', query: 's', geometry: 'relation' }, callback);
- window.setTimeout(function() {
- expect(parseQueryString(fetchMock.calls()[0][0])).to.eql(
- {rtype: 'route', query: 's', page: '1', rp: '25', sortname: 'count_relation_members', sortorder: 'desc', lang: 'en'}
- );
- expect(callback).to.have.been.calledWith(null, [
- {'value': 'stop', 'title': 'stop'},
- {'value': 'south', 'title': 'south'}
- ]);
- done();
- }, 50);
+ await setTimeout(50);
+ expect(parseQueryString(fetchMock.calls()[0][0])).to.eql(
+ {rtype: 'route', query: 's', page: '1', rp: '25', sortname: 'count_relation_members', sortorder: 'desc', lang: 'en'}
+ );
+ expect(callback).to.have.been.calledWith(null, [
+ {'value': 'stop', 'title': 'stop'},
+ {'value': 'south', 'title': 'south'}
+ ]);
});
});
describe('#docs', function() {
- it('calls the given callback with the results of the docs query', function(done) {
+ it('calls the given callback with the results of the docs query', async () => {
fetchMock.mock(/\/tag\/wiki_page/, {
body: '{"data":[{"on_way":false,"lang":"en","on_area":true,"image":"File:Car park2.jpg"}]}',
status: 200,
@@ -408,15 +374,13 @@ describe('iD.serviceTaginfo', function() {
var callback = sinon.spy();
taginfo.docs({ key: 'amenity', value: 'parking' }, callback);
- window.setTimeout(function() {
- expect(parseQueryString(fetchMock.calls()[0][0])).to.eql(
- {key: 'amenity', value: 'parking'}
- );
- expect(callback).to.have.been.calledWith(
- null, [{'on_way':false,'lang':'en','on_area':true,'image':'File:Car park2.jpg'}]
- );
- done();
- }, 50);
+ await setTimeout(50);
+ expect(parseQueryString(fetchMock.calls()[0][0])).to.eql(
+ {key: 'amenity', value: 'parking'}
+ );
+ expect(callback).to.have.been.calledWith(
+ null, [{'on_way':false,'lang':'en','on_area':true,'image':'File:Car park2.jpg'}]
+ );
});
});
diff --git a/test/spec/services/vegbilder.js b/test/spec/services/vegbilder.js
index d340aeb64..2225b6566 100644
--- a/test/spec/services/vegbilder.js
+++ b/test/spec/services/vegbilder.js
@@ -1,3 +1,5 @@
+import { setTimeout } from 'node:timers/promises';
+
describe('iD.serviceVegbilder', function() {
const dimensions = [64, 64];
const testImages = [{
@@ -248,7 +250,7 @@ describe('iD.serviceVegbilder', function() {
vegbilder.on('loadedImages', spy);
vegbilder.loadImages(context, 0);
- await new Promise((resolve) => { window.setTimeout(resolve, 200); });
+ await setTimeout(200);
expect(spy).to.have.been.not.called;
expect(fetchMock.calls().length).to.eql(0);
diff --git a/test/spec/svg/data.js b/test/spec/svg/data.js
index 02a1e71d5..bd990d6a4 100644
--- a/test/spec/svg/data.js
+++ b/test/spec/svg/data.js
@@ -1,3 +1,5 @@
+import { setTimeout } from 'node:timers/promises';
+
describe('iD.svgData', function () {
var context;
var surface;
@@ -114,72 +116,66 @@ describe('iD.svgData', function () {
});
describe('#fileList', function() {
- it('handles gpx files', function (done) {
+ it('handles gpx files', async () => {
var files = [ makeFile(gpx, 'test.gpx', 'application/gpx+xml') ];
var render = iD.svgData(projection, context, dispatch);
var spy = sinon.spy();
dispatch.on('change', spy);
render.fileList(files);
- window.setTimeout(function() {
- expect(spy).to.have.been.calledOnce;
- surface.call(render);
- var path;
- path = surface.selectAll('path.shadow');
- expect(path.nodes().length).to.eql(1);
- expect(path.attr('d')).to.match(/^M.*z$/);
- path = surface.selectAll('path.stroke');
- expect(path.nodes().length).to.eql(1);
- expect(path.attr('d')).to.match(/^M.*z$/);
- done();
- }, 200);
+ await setTimeout(200);
+ expect(spy).to.have.been.calledOnce;
+ surface.call(render);
+ var path;
+ path = surface.selectAll('path.shadow');
+ expect(path.nodes().length).to.eql(1);
+ expect(path.attr('d')).to.match(/^M.*z$/);
+ path = surface.selectAll('path.stroke');
+ expect(path.nodes().length).to.eql(1);
+ expect(path.attr('d')).to.match(/^M.*z$/);
});
- it('handles kml files', function (done) {
+ it('handles kml files', async () => {
var files = [ makeFile(kml, 'test.kml', 'application/vnd.google-earth.kml+xml') ];
var render = iD.svgData(projection, context, dispatch);
var spy = sinon.spy();
dispatch.on('change', spy);
render.fileList(files);
- window.setTimeout(function() {
- expect(spy).to.have.been.calledOnce;
- surface.call(render);
- var path;
- path = surface.selectAll('path.shadow');
- expect(path.nodes().length).to.eql(1);
- expect(path.attr('d')).to.match(/^M.*z$/);
- path = surface.selectAll('path.stroke');
- expect(path.nodes().length).to.eql(1);
- expect(path.attr('d')).to.match(/^M.*z$/);
- done();
- }, 200);
+ await setTimeout(200);
+ expect(spy).to.have.been.calledOnce;
+ surface.call(render);
+ var path;
+ path = surface.selectAll('path.shadow');
+ expect(path.nodes().length).to.eql(1);
+ expect(path.attr('d')).to.match(/^M.*z$/);
+ path = surface.selectAll('path.stroke');
+ expect(path.nodes().length).to.eql(1);
+ expect(path.attr('d')).to.match(/^M.*z$/);
});
- it('handles geojson files', function (done) {
+ it('handles geojson files', async () => {
var files = [ makeFile(geojson, 'test.geojson', 'application/vnd.geo+json') ];
var render = iD.svgData(projection, context, dispatch);
var spy = sinon.spy();
dispatch.on('change', spy);
render.fileList(files);
- window.setTimeout(function() {
- expect(spy).to.have.been.calledOnce;
- surface.call(render);
- var path;
- path = surface.selectAll('path.shadow');
- expect(path.nodes().length).to.eql(1);
- expect(path.attr('d')).to.match(/^M.*z$/);
- path = surface.selectAll('path.stroke');
- expect(path.nodes().length).to.eql(1);
- expect(path.attr('d')).to.match(/^M.*z$/);
- expect(render.geojson().features[0].properties.osm_id).to.be.a('string');
- expect(render.geojson().features[0].properties.flag).to.be.a('string');
- expect(render.geojson().features[0].properties.list).to.be.a('string');
- expect(render.geojson().features[0].properties.null).to.be.a('string');
- expect(render.geojson().features[0].properties.object).to.be.a('string');
- done();
- }, 200);
+ await setTimeout(200);
+ expect(spy).to.have.been.calledOnce;
+ surface.call(render);
+ var path;
+ path = surface.selectAll('path.shadow');
+ expect(path.nodes().length).to.eql(1);
+ expect(path.attr('d')).to.match(/^M.*z$/);
+ path = surface.selectAll('path.stroke');
+ expect(path.nodes().length).to.eql(1);
+ expect(path.attr('d')).to.match(/^M.*z$/);
+ expect(render.geojson().features[0].properties.osm_id).to.be.a('string');
+ expect(render.geojson().features[0].properties.flag).to.be.a('string');
+ expect(render.geojson().features[0].properties.list).to.be.a('string');
+ expect(render.geojson().features[0].properties.null).to.be.a('string');
+ expect(render.geojson().features[0].properties.object).to.be.a('string');
});
});
diff --git a/test/spec/ui/combobox.js b/test/spec/ui/combobox.js
index 4123710f6..8dffc8209 100644
--- a/test/spec/ui/combobox.js
+++ b/test/spec/ui/combobox.js
@@ -231,28 +231,24 @@ describe('uiCombobox', function() {
expect(input.property('value')).to.equal('foobar');
});
- it('emits accepted event with selected datum on ⇥', function(done) {
- combobox.on('accept', function(d) {
- expect(d).to.eql({title: 'bar', value: 'bar'});
- combobox.on('accept', null);
- done();
- });
+ it('emits accepted event with selected datum on ⇥', async () => {
+ const d = new Promise(cb => { combobox.on('accept', cb); });
input.call(combobox.data(data));
focusTypeahead(input);
simulateKeypress('b');
simulateKeypress('⇥');
+ expect(await d).to.eql({title: 'bar', value: 'bar'});
+ combobox.on('accept', null);
});
- it('emits accepted event with selected datum on ↩', function(done) {
- combobox.on('accept', function(d) {
- expect(d).to.eql({title: 'bar', value: 'bar'});
- combobox.on('accept', null);
- done();
- });
+ it('emits accepted event with selected datum on ↩', async () => {
+ const d = new Promise(cb => { combobox.on('accept', cb); });
input.call(combobox.data(data));
focusTypeahead(input);
simulateKeypress('b');
simulateKeypress('↩');
+ expect(await d).to.eql({title: 'bar', value: 'bar'});
+ combobox.on('accept', null);
});
it('emits cancel event on ⎋', function() {
diff --git a/test/spec/ui/confirm.js b/test/spec/ui/confirm.js
index db37195b3..1d3359d35 100644
--- a/test/spec/ui/confirm.js
+++ b/test/spec/ui/confirm.js
@@ -1,3 +1,5 @@
+import { setTimeout } from 'node:timers/promises';
+
describe('iD.uiConfirm', function () {
var elem;
@@ -37,55 +39,45 @@ describe('iD.uiConfirm', function () {
expect(selection.selectAll('div.content div.buttons button.action').size()).to.equal(1);
});
- it('can be dismissed by calling close function', function (done) {
+ it('can be dismissed by calling close function', async () => {
var selection = iD.uiConfirm(elem);
selection.close();
- window.setTimeout(function() {
- d3.timerFlush();
- expect(selection.node().parentNode).to.be.null;
- done();
- }, 275);
+ await setTimeout(275);
+ d3.timerFlush();
+ expect(selection.node().parentNode).to.be.null;
});
- it('can be dismissed by clicking the close button', function (done) {
+ it('can be dismissed by clicking the close button', async () => {
var selection = iD.uiConfirm(elem);
happen.click(selection.select('button.close').node());
- window.setTimeout(function() {
- d3.timerFlush();
- expect(selection.node().parentNode).to.be.null;
- done();
- }, 275);
+ await setTimeout(275);
+ d3.timerFlush();
+ expect(selection.node().parentNode).to.be.null;
});
- it('can be dismissed by pressing escape', function (done) {
+ it('can be dismissed by pressing escape', async () => {
var selection = iD.uiConfirm(elem);
happen.keydown(document, {keyCode: 27});
happen.keyup(document, {keyCode: 27});
- window.setTimeout(function() {
- d3.timerFlush();
- expect(selection.node().parentNode).to.be.null;
- done();
- }, 275);
+ await setTimeout(275);
+ d3.timerFlush();
+ expect(selection.node().parentNode).to.be.null;
});
- it('can be dismissed by pressing backspace', function (done) {
+ it('can be dismissed by pressing backspace', async () => {
var selection = iD.uiConfirm(elem);
happen.keydown(document, {keyCode: 8});
happen.keyup(document, {keyCode: 8});
- window.setTimeout(function() {
- d3.timerFlush();
- expect(selection.node().parentNode).to.be.null;
- done();
- }, 275);
+ await setTimeout(275);
+ d3.timerFlush();
+ expect(selection.node().parentNode).to.be.null;
});
- it('can be dismissed by clicking the ok button', function (done) {
+ it('can be dismissed by clicking the ok button', async () => {
var selection = iD.uiConfirm(elem).okButton();
happen.click(selection.select('div.content div.buttons button.action').node());
- window.setTimeout(function() {
- d3.timerFlush();
- expect(selection.node().parentNode).to.be.null;
- done();
- }, 275);
+ await setTimeout(275);
+ d3.timerFlush();
+ expect(selection.node().parentNode).to.be.null;
});
});
diff --git a/test/spec/ui/fields/localized.js b/test/spec/ui/fields/localized.js
index 24788513f..bde9b6b9c 100644
--- a/test/spec/ui/fields/localized.js
+++ b/test/spec/ui/fields/localized.js
@@ -1,3 +1,5 @@
+import { setTimeout } from 'node:timers/promises';
+
describe('iD.uiFieldLocalized', function() {
var context, selection, field;
@@ -22,158 +24,138 @@ describe('iD.uiFieldLocalized', function() {
});
- it('adds a blank set of fields when the + button is clicked', function(done) {
+ it('adds a blank set of fields when the + button is clicked', async () => {
var localized = iD.uiFieldLocalized(field, context);
- window.setTimeout(function() { // async, so data will be available
- selection.call(localized);
- happen.click(selection.selectAll('.localized-add').node());
- expect(selection.selectAll('.localized-lang').nodes().length).to.equal(1);
- expect(selection.selectAll('.localized-value').nodes().length).to.equal(1);
- done();
- }, 20);
+ await setTimeout(20);
+ selection.call(localized);
+ happen.click(selection.selectAll('.localized-add').node());
+ expect(selection.selectAll('.localized-lang').nodes().length).to.equal(1);
+ expect(selection.selectAll('.localized-value').nodes().length).to.equal(1);
});
- it('doesn\'t create a tag when the value is empty', function(done) {
+ it('doesn\'t create a tag when the value is empty', async () => {
var localized = iD.uiFieldLocalized(field, context);
- window.setTimeout(function() { // async, so data will be available
- selection.call(localized);
- happen.click(selection.selectAll('.localized-add').node());
+ await setTimeout(20);
+ selection.call(localized);
+ happen.click(selection.selectAll('.localized-add').node());
- localized.on('change', function(tags) {
- expect(tags).to.eql({});
- });
+ localized.on('change', function(tags) {
+ expect(tags).to.eql({});
+ });
- iD.utilGetSetValue(selection.selectAll('.localized-lang'), 'Deutsch');
- happen.once(selection.selectAll('.localized-lang').node(), {type: 'change'});
- happen.once(selection.selectAll('.localized-lang').node(), {type: 'blur'});
- done();
- }, 20);
+ iD.utilGetSetValue(selection.selectAll('.localized-lang'), 'Deutsch');
+ happen.once(selection.selectAll('.localized-lang').node(), {type: 'change'});
+ happen.once(selection.selectAll('.localized-lang').node(), {type: 'blur'});
});
- it('doesn\'t create a tag when the name is empty', function(done) {
+ it('doesn\'t create a tag when the name is empty', async () => {
var localized = iD.uiFieldLocalized(field, context);
- window.setTimeout(function() { // async, so data will be available
- selection.call(localized);
- happen.click(selection.selectAll('.localized-add').node());
+ await setTimeout(20);
+ selection.call(localized);
+ happen.click(selection.selectAll('.localized-add').node());
- localized.on('change', function(tags) {
- expect(tags).to.eql({});
- });
+ localized.on('change', function(tags) {
+ expect(tags).to.eql({});
+ });
- iD.utilGetSetValue(selection.selectAll('.localized-value'), 'Value');
- happen.once(selection.selectAll('.localized-value').node(), {type: 'change'});
- happen.once(selection.selectAll('.localized-value').node(), {type: 'blur'});
- done();
- }, 20);
+ iD.utilGetSetValue(selection.selectAll('.localized-value'), 'Value');
+ happen.once(selection.selectAll('.localized-value').node(), {type: 'change'});
+ happen.once(selection.selectAll('.localized-value').node(), {type: 'blur'});
});
- it('creates a tag after setting language then value', function(done) {
+ it('creates a tag after setting language then value', async () => {
var localized = iD.uiFieldLocalized(field, context);
- window.setTimeout(function() { // async, so data will be available
- selection.call(localized);
- happen.click(selection.selectAll('.localized-add').node());
+ await setTimeout(20);
+ selection.call(localized);
+ happen.click(selection.selectAll('.localized-add').node());
- iD.utilGetSetValue(selection.selectAll('.localized-lang'), 'Deutsch');
- happen.once(selection.selectAll('.localized-lang').node(), {type: 'change'});
+ iD.utilGetSetValue(selection.selectAll('.localized-lang'), 'Deutsch');
+ happen.once(selection.selectAll('.localized-lang').node(), {type: 'change'});
- localized.on('change', function(tags) {
- expect(tags).to.eql({'name:de': 'Value'});
- });
+ localized.on('change', function(tags) {
+ expect(tags).to.eql({'name:de': 'Value'});
+ });
- iD.utilGetSetValue(selection.selectAll('.localized-value'), 'Value');
- happen.once(selection.selectAll('.localized-value').node(), {type: 'change'});
- done();
- }, 20);
+ iD.utilGetSetValue(selection.selectAll('.localized-value'), 'Value');
+ happen.once(selection.selectAll('.localized-value').node(), {type: 'change'});
});
- it('creates a tag after setting value then language', function(done) {
+ it('creates a tag after setting value then language', async () => {
var localized = iD.uiFieldLocalized(field, context);
- window.setTimeout(function() { // async, so data will be available
- selection.call(localized);
- happen.click(selection.selectAll('.localized-add').node());
+ await setTimeout(20);
+ selection.call(localized);
+ happen.click(selection.selectAll('.localized-add').node());
- iD.utilGetSetValue(selection.selectAll('.localized-value'), 'Value');
- happen.once(selection.selectAll('.localized-value').node(), {type: 'change'});
+ iD.utilGetSetValue(selection.selectAll('.localized-value'), 'Value');
+ happen.once(selection.selectAll('.localized-value').node(), {type: 'change'});
- localized.on('change', function(tags) {
- expect(tags).to.eql({'name:de': 'Value'});
- });
+ localized.on('change', function(tags) {
+ expect(tags).to.eql({'name:de': 'Value'});
+ });
- iD.utilGetSetValue(selection.selectAll('.localized-lang'), 'Deutsch');
- happen.once(selection.selectAll('.localized-lang').node(), {type: 'change'});
- done();
- }, 20);
+ iD.utilGetSetValue(selection.selectAll('.localized-lang'), 'Deutsch');
+ happen.once(selection.selectAll('.localized-lang').node(), {type: 'change'});
});
- it('changes an existing language', function(done) {
+ it('changes an existing language', async () => {
var localized = iD.uiFieldLocalized(field, context);
- window.setTimeout(function() { // async, so data will be available
- selection.call(localized);
- localized.tags({'name:de': 'Value'});
+ await setTimeout(20);
+ selection.call(localized);
+ localized.tags({'name:de': 'Value'});
- localized.on('change', function(tags) {
- expect(tags).to.eql({
- 'name:de': undefined,
- 'name:en': 'Value'});
- });
+ localized.on('change', function(tags) {
+ expect(tags).to.eql({
+ 'name:de': undefined,
+ 'name:en': 'Value'});
+ });
- iD.utilGetSetValue(selection.selectAll('.localized-lang'), 'English');
- happen.once(selection.selectAll('.localized-lang').node(), {type: 'change'});
- done();
- }, 20);
+ iD.utilGetSetValue(selection.selectAll('.localized-lang'), 'English');
+ happen.once(selection.selectAll('.localized-lang').node(), {type: 'change'});
});
- it('ignores similar keys like `old_name`', function(done) {
+ it('ignores similar keys like `old_name`', async () => {
var localized = iD.uiFieldLocalized(field, context);
- window.setTimeout(function() { // async, so data will be available
- selection.call(localized);
- localized.tags({'old_name:de': 'Value'});
+ await setTimeout(20);
+ selection.call(localized);
+ localized.tags({'old_name:de': 'Value'});
- expect(selection.selectAll('.localized-lang').empty()).to.be.ok;
- expect(selection.selectAll('.localized-value').empty()).to.be.ok;
- done();
- }, 20);
+ expect(selection.selectAll('.localized-lang').empty()).to.be.ok;
+ expect(selection.selectAll('.localized-value').empty()).to.be.ok;
});
- it('removes the tag when the language is emptied', function(done) {
+ it('removes the tag when the language is emptied', async () => {
var localized = iD.uiFieldLocalized(field, context);
- window.setTimeout(function() { // async, so data will be available
- selection.call(localized);
- localized.tags({'name:de': 'Value'});
+ await setTimeout(20);
+ selection.call(localized);
+ localized.tags({'name:de': 'Value'});
- localized.on('change', function(tags) {
- expect(tags).to.eql({'name:de': undefined});
- });
+ localized.on('change', function(tags) {
+ expect(tags).to.eql({'name:de': undefined});
+ });
- iD.utilGetSetValue(selection.selectAll('.localized-lang'), '');
- happen.once(selection.selectAll('.localized-lang').node(), {type: 'change'});
- done();
- }, 20);
+ iD.utilGetSetValue(selection.selectAll('.localized-lang'), '');
+ happen.once(selection.selectAll('.localized-lang').node(), {type: 'change'});
});
- it('removes the tag when the value is emptied', function(done) {
+ it('removes the tag when the value is emptied', async () => {
var localized = iD.uiFieldLocalized(field, context);
- window.setTimeout(function() { // async, so data will be available
- selection.call(localized);
- localized.tags({'name:de': 'Value'});
+ await setTimeout(20);
+ selection.call(localized);
+ localized.tags({'name:de': 'Value'});
- localized.on('change', function(tags) {
- expect(tags).to.eql({'name:de': undefined});
- });
+ localized.on('change', function(tags) {
+ expect(tags).to.eql({'name:de': undefined});
+ });
- iD.utilGetSetValue(selection.selectAll('.localized-value'), '');
- happen.once(selection.selectAll('.localized-value').node(), {type: 'change'});
- done();
- }, 20);
+ iD.utilGetSetValue(selection.selectAll('.localized-value'), '');
+ happen.once(selection.selectAll('.localized-value').node(), {type: 'change'});
});
- it('has a lang attribute on an existing multilingual name field', function(done) {
- var localized = iD.uiFieldLocalized(field, context);
- localized.tags({'name:de': 'Value'});
- window.setTimeout(function() {
+ it('has a lang attribute on an existing multilingual name field', async () => {
+ var localized = iD.uiFieldLocalized(field, context);
+ localized.tags({'name:de': 'Value'});
+ await setTimeout(20);
selection.call(localized);
expect(selection.selectAll('.localized-value').attr('lang')).to.eql('de');
- done();
- }, 20);
});
});
diff --git a/test/spec/ui/fields/wikipedia.js b/test/spec/ui/fields/wikipedia.js
index c5790fa1a..5c8399abb 100644
--- a/test/spec/ui/fields/wikipedia.js
+++ b/test/spec/ui/fields/wikipedia.js
@@ -1,3 +1,5 @@
+import { setTimeout } from 'node:timers/promises';
+
describe('iD.uiFieldWikipedia', function() {
var entity, context, selection, field;
@@ -60,119 +62,104 @@ describe('iD.uiFieldWikipedia', function() {
}
}
- it('recognizes lang:title format', function(done) {
+ it('recognizes lang:title format', async () => {
var wikipedia = iD.uiFieldWikipedia(field, context);
- window.setTimeout(function() { // async, so data will be available
- selection.call(wikipedia);
- wikipedia.tags({wikipedia: 'en:Title'});
+ await setTimeout(20);
+ selection.call(wikipedia);
+ wikipedia.tags({wikipedia: 'en:Title'});
- expect(iD.utilGetSetValue(selection.selectAll('.wiki-lang'))).to.equal('English');
- expect(iD.utilGetSetValue(selection.selectAll('.wiki-title'))).to.equal('Title');
- done();
- }, 20);
+ expect(iD.utilGetSetValue(selection.selectAll('.wiki-lang'))).to.equal('English');
+ expect(iD.utilGetSetValue(selection.selectAll('.wiki-title'))).to.equal('Title');
});
- it('sets language, value', function(done) {
+ it('sets language, value', async () => {
var wikipedia = iD.uiFieldWikipedia(field, context).entityIDs([entity.id]);
- window.setTimeout(function() { // async, so data will be available
- wikipedia.on('change', changeTags);
- selection.call(wikipedia);
+ await setTimeout(20);
+ wikipedia.on('change', changeTags);
+ selection.call(wikipedia);
- var spy = sinon.spy();
- wikipedia.on('change.spy', spy);
+ var spy = sinon.spy();
+ wikipedia.on('change.spy', spy);
- iD.utilGetSetValue(selection.selectAll('.wiki-lang'), 'Deutsch');
- happen.once(selection.selectAll('.wiki-lang').node(), { type: 'change' });
- happen.once(selection.selectAll('.wiki-lang').node(), { type: 'blur' });
+ iD.utilGetSetValue(selection.selectAll('.wiki-lang'), 'Deutsch');
+ happen.once(selection.selectAll('.wiki-lang').node(), { type: 'change' });
+ happen.once(selection.selectAll('.wiki-lang').node(), { type: 'blur' });
- iD.utilGetSetValue(selection.selectAll('.wiki-title'), 'Title');
- happen.once(selection.selectAll('.wiki-title').node(), { type: 'change' });
- happen.once(selection.selectAll('.wiki-title').node(), { type: 'blur' });
+ iD.utilGetSetValue(selection.selectAll('.wiki-title'), 'Title');
+ happen.once(selection.selectAll('.wiki-title').node(), { type: 'change' });
+ happen.once(selection.selectAll('.wiki-title').node(), { type: 'blur' });
- expect(spy.callCount).to.equal(4);
- expect(spy.getCall(0)).to.have.been.calledWith({ wikipedia: undefined}); // lang on change
- expect(spy.getCall(1)).to.have.been.calledWith({ wikipedia: undefined}); // lang on blur
- expect(spy.getCall(2)).to.have.been.calledWith({ wikipedia: 'de:Title' }); // title on change
- expect(spy.getCall(3)).to.have.been.calledWith({ wikipedia: 'de:Title' }); // title on blur
- done();
- }, 20);
+ expect(spy.callCount).to.equal(4);
+ expect(spy.getCall(0)).to.have.been.calledWith({ wikipedia: undefined}); // lang on change
+ expect(spy.getCall(1)).to.have.been.calledWith({ wikipedia: undefined}); // lang on blur
+ expect(spy.getCall(2)).to.have.been.calledWith({ wikipedia: 'de:Title' }); // title on change
+ expect(spy.getCall(3)).to.have.been.calledWith({ wikipedia: 'de:Title' }); // title on blur
});
- it('recognizes pasted URLs', function(done) {
+ it('recognizes pasted URLs', async () => {
var wikipedia = iD.uiFieldWikipedia(field, context).entityIDs([entity.id]);
- window.setTimeout(function() { // async, so data will be available
- wikipedia.on('change', changeTags);
- selection.call(wikipedia);
+ await setTimeout(20);
+ wikipedia.on('change', changeTags);
+ selection.call(wikipedia);
- iD.utilGetSetValue(selection.selectAll('.wiki-title'), 'http://de.wikipedia.org/wiki/Title');
- happen.once(selection.selectAll('.wiki-title').node(), { type: 'change' });
+ iD.utilGetSetValue(selection.selectAll('.wiki-title'), 'http://de.wikipedia.org/wiki/Title');
+ happen.once(selection.selectAll('.wiki-title').node(), { type: 'change' });
- expect(iD.utilGetSetValue(selection.selectAll('.wiki-lang'))).to.equal('Deutsch');
- expect(iD.utilGetSetValue(selection.selectAll('.wiki-title'))).to.equal('Title');
- done();
- }, 20);
+ expect(iD.utilGetSetValue(selection.selectAll('.wiki-lang'))).to.equal('Deutsch');
+ expect(iD.utilGetSetValue(selection.selectAll('.wiki-title'))).to.equal('Title');
});
describe('encodePath', function() {
- it('returns an encoded URI component that contains the title with spaces replaced by underscores', function(done) {
+ it('returns an encoded URI component that contains the title with spaces replaced by underscores', () => {
var wikipedia = iD.uiFieldWikipedia(field, context).entityIDs([entity.id]);
expect(wikipedia.encodePath('? (film)', undefined)).to.equal('%3F_(film)');
- done();
});
- it('returns an encoded URI component that includes an anchor fragment', function(done) {
+ it('returns an encoded URI component that includes an anchor fragment', () => {
var wikipedia = iD.uiFieldWikipedia(field, context).entityIDs([entity.id]);
// this can be tested manually by entering '? (film)#Themes and style in the search box before focusing out'
expect(wikipedia.encodePath('? (film)', 'Themes and style')).to.equal('%3F_(film)#Themes_and_style');
- done();
});
});
describe('encodeURIAnchorFragment', function() {
- it('returns an encoded URI anchor fragment', function(done) {
+ it('returns an encoded URI anchor fragment', () => {
var wikipedia = iD.uiFieldWikipedia(field, context).entityIDs([entity.id]);
// this can be similarly tested by entering 'Section#Arts, entertainment and media' in the search box before focusing out'
expect(wikipedia.encodeURIAnchorFragment('Theme?')).to.equal('#Theme%3F');
- done();
});
- it('replaces all whitespace characters with underscore', function(done) {
+ it('replaces all whitespace characters with underscore', () => {
var wikipedia = iD.uiFieldWikipedia(field, context).entityIDs([entity.id]);
expect(wikipedia.encodeURIAnchorFragment('Themes And Styles')).to.equal('#Themes_And_Styles');
- done();
});
- it('encodes % characters, does not replace them with a dot', function(done) {
+ it('encodes % characters, does not replace them with a dot', () => {
var wikipedia = iD.uiFieldWikipedia(field, context).entityIDs([entity.id]);
expect(wikipedia.encodeURIAnchorFragment('Is%this_100% correct')).to.equal('#Is%25this_100%25_correct');
- done();
});
- it('encodes characters that are URI encoded characters', function (done) {
+ it('encodes characters that are URI encoded characters', () => {
var wikipedia = iD.uiFieldWikipedia(field, context).entityIDs([entity.id]);
expect(wikipedia.encodeURIAnchorFragment('Section %20%25')).to.equal('#Section_%2520%2525');
- done();
});
});
// note - currently skipping the tests that use `options` to delay responses
- it('preserves existing language', function(done) {
+ it('preserves existing language', async () => {
var wikipedia1 = iD.uiFieldWikipedia(field, context);
- window.setTimeout(function() { // async, so data will be available
- selection.call(wikipedia1);
- iD.utilGetSetValue(selection.selectAll('.wiki-lang'), 'Deutsch');
+ await setTimeout(20);
+ selection.call(wikipedia1);
+ iD.utilGetSetValue(selection.selectAll('.wiki-lang'), 'Deutsch');
- var wikipedia2 = iD.uiFieldWikipedia(field, context);
- window.setTimeout(function() { // async, so data will be available
- selection.call(wikipedia2);
- wikipedia2.tags({});
- expect(iD.utilGetSetValue(selection.selectAll('.wiki-lang'))).to.equal('Deutsch');
- done();
- }, 20);
- }, 20);
+ var wikipedia2 = iD.uiFieldWikipedia(field, context);
+ await setTimeout(20);
+ selection.call(wikipedia2);
+ wikipedia2.tags({});
+ expect(iD.utilGetSetValue(selection.selectAll('.wiki-lang'))).to.equal('Deutsch');
});
- it.skip('does not set delayed wikidata tag if graph has changed', function(done) {
+ it.skip('does not set delayed wikidata tag if graph has changed', async () => {
var wikipedia = iD.uiFieldWikipedia(field, context).entityIDs([entity.id]);
wikipedia.on('change', changeTags);
selection.call(wikipedia);
@@ -227,16 +214,13 @@ describe('iD.uiFieldWikipedia', function() {
// t90: at t30 + 60ms (delay), wikidata SHOULD be set because graph is unchanged.
// t100: check that wikidata has changed
- window.setTimeout(function() {
- expect(context.entity(entity.id).tags.wikidata).to.equal('Q216353');
-
- expect(spy.callCount).to.equal(4);
- expect(spy.getCall(0)).to.have.been.calledWith({ wikipedia: 'de:Skip' }); // 'Skip' on change
- expect(spy.getCall(1)).to.have.been.calledWith({ wikipedia: 'de:Skip' }); // 'Skip' on blur
- expect(spy.getCall(2)).to.have.been.calledWith({ wikipedia: 'de:Title' }); // 'Title' on change +10ms
- expect(spy.getCall(3)).to.have.been.calledWith({ wikipedia: 'de:Title' }); // 'Title' on blur +10ms
- done();
- }, 100);
+ await setTimeout(100);
+ expect(context.entity(entity.id).tags.wikidata).to.equal('Q216353');
+ expect(spy.callCount).to.equal(4);
+ expect(spy.getCall(0)).to.have.been.calledWith({ wikipedia: 'de:Skip' }); // 'Skip' on change
+ expect(spy.getCall(1)).to.have.been.calledWith({ wikipedia: 'de:Skip' }); // 'Skip' on blur
+ expect(spy.getCall(2)).to.have.been.calledWith({ wikipedia: 'de:Title' }); // 'Title' on change +10ms
+ expect(spy.getCall(3)).to.have.been.calledWith({ wikipedia: 'de:Title' }); // 'Title' on blur +10ms
});
});
diff --git a/test/spec/ui/flash.js b/test/spec/ui/flash.js
index 3a929f834..40dd8f5fe 100644
--- a/test/spec/ui/flash.js
+++ b/test/spec/ui/flash.js
@@ -1,3 +1,5 @@
+import { setTimeout } from 'node:timers/promises';
+
describe('iD.uiFlash', function () {
var context;
@@ -24,16 +26,14 @@ describe('iD.uiFlash', function () {
expect(footerWrap.classed('footer-hide')).to.be.ok;
});
- it('flash goes away', function(done) {
+ it('flash goes away', async () => {
iD.uiFlash(context).duration(200)();
- window.setTimeout(function() {
- d3.timerFlush();
- var flashWrap = d3.selectAll('.flash-wrap');
- var footerWrap = d3.selectAll('.main-footer-wrap');
- expect(flashWrap.classed('footer-hide')).to.be.ok;
- expect(footerWrap.classed('footer-show')).to.be.ok;
- done();
- }, 225);
+ await setTimeout(225);
+ d3.timerFlush();
+ var flashWrap = d3.selectAll('.flash-wrap');
+ var footerWrap = d3.selectAll('.main-footer-wrap');
+ expect(flashWrap.classed('footer-hide')).to.be.ok;
+ expect(footerWrap.classed('footer-show')).to.be.ok;
});
});
diff --git a/test/spec/ui/modal.js b/test/spec/ui/modal.js
index e542a11c0..a92e5f8a9 100644
--- a/test/spec/ui/modal.js
+++ b/test/spec/ui/modal.js
@@ -1,3 +1,5 @@
+import { setTimeout } from 'node:timers/promises';
+
describe('iD.uiModal', function () {
var elem;
@@ -22,46 +24,38 @@ describe('iD.uiModal', function () {
expect(selection.selectAll('div.content').size()).to.equal(1);
});
- it('can be dismissed by calling close function', function (done) {
+ it('can be dismissed by calling close function', async () => {
var selection = iD.uiModal(elem);
selection.close();
- window.setTimeout(function() {
- d3.timerFlush();
- expect(selection.node().parentNode).to.be.null;
- done();
- }, 275);
+ await setTimeout(275);
+ d3.timerFlush();
+ expect(selection.node().parentNode).to.be.null;
});
- it('can be dismissed by clicking the close button', function (done) {
+ it('can be dismissed by clicking the close button', async () => {
var selection = iD.uiModal(elem);
happen.click(selection.select('button.close').node());
- window.setTimeout(function() {
- d3.timerFlush();
- expect(selection.node().parentNode).to.be.null;
- done();
- }, 275);
+ await setTimeout(275);
+ d3.timerFlush();
+ expect(selection.node().parentNode).to.be.null;
});
- it('can be dismissed by pressing escape', function (done) {
+ it('can be dismissed by pressing escape', async () => {
var selection = iD.uiModal(elem);
happen.keydown(document, {keyCode: 27});
happen.keyup(document, {keyCode: 27});
- window.setTimeout(function() {
- d3.timerFlush();
- expect(selection.node().parentNode).to.be.null;
- done();
- }, 275);
+ await setTimeout(275);
+ d3.timerFlush();
+ expect(selection.node().parentNode).to.be.null;
});
- it('can be dismissed by pressing backspace', function (done) {
+ it('can be dismissed by pressing backspace', async () => {
var selection = iD.uiModal(elem);
happen.keydown(document, {keyCode: 8});
happen.keyup(document, {keyCode: 8});
- window.setTimeout(function() {
- d3.timerFlush();
- expect(selection.node().parentNode).to.be.null;
- done();
- }, 275);
+ await setTimeout(275);
+ d3.timerFlush();
+ expect(selection.node().parentNode).to.be.null;
});
});
diff --git a/test/spec/ui/sections/raw_tag_editor.js b/test/spec/ui/sections/raw_tag_editor.js
index e34c4f575..18e94f878 100644
--- a/test/spec/ui/sections/raw_tag_editor.js
+++ b/test/spec/ui/sections/raw_tag_editor.js
@@ -1,3 +1,5 @@
+import { setTimeout } from 'node:timers/promises';
+
describe('iD.uiSectionRawTagEditor', function() {
var taglist, element, entity, context;
@@ -39,42 +41,36 @@ describe('iD.uiSectionRawTagEditor', function() {
expect(element.select('.tag-list').selectAll('input.key').property('value')).to.be.empty;
});
- it('adds tags when clicking the add button', function (done) {
+ it('adds tags when clicking the add button', async () => {
happen.click(element.selectAll('button.add-tag').node());
- setTimeout(function() {
- expect(element.select('.tag-list').selectAll('input').nodes()[2].value).to.be.empty;
- expect(element.select('.tag-list').selectAll('input').nodes()[3].value).to.be.empty;
- done();
- }, 20);
+ await setTimeout(20);
+ expect(element.select('.tag-list').selectAll('input').nodes()[2].value).to.be.empty;
+ expect(element.select('.tag-list').selectAll('input').nodes()[3].value).to.be.empty;
});
- it('removes tags when clicking the remove button', function (done) {
- taglist.on('change', function(entityIDs, tags) {
- expect(tags).to.eql({highway: undefined});
- done();
- });
+ it('removes tags when clicking the remove button', async () => {
iD.utilTriggerEvent(element.selectAll('button.remove'), 'mousedown', { button: 0 });
+ const tags = await new Promise(cb => {
+ taglist.on('change', (_, tags) => cb(tags));
+ });
+ expect(tags).to.eql({highway: undefined});
});
- it('adds tags when pressing the TAB key on last input.value', function (done) {
+ it('adds tags when pressing the TAB key on last input.value', async () => {
expect(element.selectAll('.tag-list li').nodes().length).to.eql(1);
var input = d3.select('.tag-list li:last-child input.value').nodes()[0];
happen.keydown(d3.select(input).node(), {keyCode: 9});
- setTimeout(function() {
- expect(element.selectAll('.tag-list li').nodes().length).to.eql(2);
- expect(element.select('.tag-list').selectAll('input').nodes()[2].value).to.be.empty;
- expect(element.select('.tag-list').selectAll('input').nodes()[3].value).to.be.empty;
- done();
- }, 20);
+ await setTimeout(20);
+ expect(element.selectAll('.tag-list li').nodes().length).to.eql(2);
+ expect(element.select('.tag-list').selectAll('input').nodes()[2].value).to.be.empty;
+ expect(element.select('.tag-list').selectAll('input').nodes()[3].value).to.be.empty;
});
- it('does not add a tag when pressing TAB while shift is pressed', function (done) {
+ it('does not add a tag when pressing TAB while shift is pressed', async () => {
expect(element.selectAll('.tag-list li').nodes().length).to.eql(1);
var input = d3.select('.tag-list li:last-child input.value').nodes()[0];
happen.keydown(d3.select(input).node(), {keyCode: 9, shiftKey: true});
- setTimeout(function() {
- expect(element.selectAll('.tag-list li').nodes().length).to.eql(1);
- done();
- }, 20);
+ await setTimeout(20);
+ expect(element.selectAll('.tag-list li').nodes().length).to.eql(1);
});
});
diff --git a/test/spec/validations/mutually_exclusive_tags.js b/test/spec/validations/mutually_exclusive_tags.js
index 1639ea701..515240a3f 100644
--- a/test/spec/validations/mutually_exclusive_tags.js
+++ b/test/spec/validations/mutually_exclusive_tags.js
@@ -1,3 +1,5 @@
+import { setTimeout } from 'node:timers/promises';
+
describe('iD.validations.mutually_exclusive_tags', function () {
var context;
@@ -22,71 +24,61 @@ describe('iD.validations.mutually_exclusive_tags', function () {
}
- it('has no errors on init', function(done) {
+ it('has no errors on init', async () => {
var validator = iD.validationMutuallyExclusiveTags(context);
- window.setTimeout(function() { // async, so data will be available
- var issues = validate(validator);
- expect(issues).to.have.lengthOf(0);
- done();
- }, 20);
+ await setTimeout(20);
+ var issues = validate(validator);
+ expect(issues).to.have.lengthOf(0);
});
- it('has no errors on good tags', function(done) {
+ it('has no errors on good tags', async () => {
createNode({'name': 'Trader Joe', 'not:name': 'Trader Jane'});
var validator = iD.validationMutuallyExclusiveTags(context);
- window.setTimeout(function() { // async, so data will be available
- var issues = validate(validator);
- expect(issues).to.have.lengthOf(0);
- done();
- }, 20);
+ await setTimeout(20);
+ var issues = validate(validator);
+ expect(issues).to.have.lengthOf(0);
});
- it('flags mutually exclusive tags', function(done) {
+ it('flags mutually exclusive tags', async () => {
createNode({'name': 'Trader Joe', 'noname': 'yes'});
var validator = iD.validationMutuallyExclusiveTags(context);
- window.setTimeout(function() { // async, so data will be available
- var issues = validate(validator);
- expect(issues).to.have.lengthOf(1);
- var issue = issues[0];
- expect(issue.type).to.eql('mutually_exclusive_tags');
- expect(issue.subtype).to.eql('default');
- expect(issue.severity).to.eql('warning');
- expect(issue.entityIds).to.have.lengthOf(1);
- expect(issue.entityIds[0]).to.eql('n-1');
- done();
- }, 20);
+ await setTimeout(20);
+ var issues = validate(validator);
+ expect(issues).to.have.lengthOf(1);
+ var issue = issues[0];
+ expect(issue.type).to.eql('mutually_exclusive_tags');
+ expect(issue.subtype).to.eql('default');
+ expect(issue.severity).to.eql('warning');
+ expect(issue.entityIds).to.have.lengthOf(1);
+ expect(issue.entityIds[0]).to.eql('n-1');
});
- it('flags feature with a mutually exclusive `not:name` value', function(done) {
+ it('flags feature with a mutually exclusive `not:name` value', async () => {
createNode({ shop: 'supermarket', name: 'Lous', 'not:name': 'Lous' });
var validator = iD.validationMutuallyExclusiveTags(context);
- window.setTimeout(function() { // async, so data will be available
- var issues = validate(validator);
- expect(issues).to.have.lengthOf(1);
- var issue = issues[0];
- expect(issue.type).to.eql('mutually_exclusive_tags');
- expect(issue.subtype).to.eql('same_value');
- expect(issue.severity).to.eql('warning');
- expect(issue.entityIds).to.have.lengthOf(1);
- expect(issue.entityIds[0]).to.eql('n-1');
- done();
- }, 20);
+ await setTimeout(20);
+ var issues = validate(validator);
+ expect(issues).to.have.lengthOf(1);
+ var issue = issues[0];
+ expect(issue.type).to.eql('mutually_exclusive_tags');
+ expect(issue.subtype).to.eql('same_value');
+ expect(issue.severity).to.eql('warning');
+ expect(issue.entityIds).to.have.lengthOf(1);
+ expect(issue.entityIds[0]).to.eql('n-1');
});
- it('flags feature with a mutually exclusive semicolon-separated `not:name` value', function(done) {
+ it('flags feature with a mutually exclusive semicolon-separated `not:name` value', async () => {
createNode({ shop: 'supermarket', name: 'Lous', 'not:name': 'Louis\';Lous;Louis\'s' });
var validator = iD.validationMutuallyExclusiveTags(context);
- window.setTimeout(function() { // async, so data will be available
- var issues = validate(validator);
- expect(issues).to.have.lengthOf(1);
- var issue = issues[0];
- expect(issue.type).to.eql('mutually_exclusive_tags');
- expect(issue.subtype).to.eql('same_value');
- expect(issue.severity).to.eql('warning');
- expect(issue.entityIds).to.have.lengthOf(1);
- expect(issue.entityIds[0]).to.eql('n-1');
- done();
- }, 20);
+ await setTimeout(20);
+ var issues = validate(validator);
+ expect(issues).to.have.lengthOf(1);
+ var issue = issues[0];
+ expect(issue.type).to.eql('mutually_exclusive_tags');
+ expect(issue.subtype).to.eql('same_value');
+ expect(issue.severity).to.eql('warning');
+ expect(issue.entityIds).to.have.lengthOf(1);
+ expect(issue.entityIds[0]).to.eql('n-1');
});
});
diff --git a/test/spec/validations/outdated_tags.js b/test/spec/validations/outdated_tags.js
index 0a64a11bb..1d2d04c26 100644
--- a/test/spec/validations/outdated_tags.js
+++ b/test/spec/validations/outdated_tags.js
@@ -1,3 +1,5 @@
+import { setTimeout } from 'node:timers/promises';
+
describe('iD.validations.outdated_tags', function () {
var context;
@@ -55,74 +57,62 @@ describe('iD.validations.outdated_tags', function () {
return issues;
}
- it('has no errors on init', function(done) {
+ it('has no errors on init', async () => {
var validator = iD.validationOutdatedTags(context);
- window.setTimeout(function() { // async, so data will be available
- var issues = validate(validator);
- expect(issues).to.have.lengthOf(0);
- done();
- }, 20);
+ await setTimeout(20);
+ var issues = validate(validator);
+ expect(issues).to.have.lengthOf(0);
});
- it('has no errors on good tags', function(done) {
+ it('has no errors on good tags', async () => {
createWay({'highway': 'unclassified'});
var validator = iD.validationOutdatedTags(context);
- window.setTimeout(function() { // async, so data will be available
- var issues = validate(validator);
- expect(issues).to.have.lengthOf(0);
- done();
- }, 20);
+ await setTimeout(20);
+ var issues = validate(validator);
+ expect(issues).to.have.lengthOf(0);
});
- it('flags deprecated tag with replacement', function(done) {
+ it('flags deprecated tag with replacement', async () => {
createWay({'highway': 'ford'});
var validator = iD.validationOutdatedTags(context);
- window.setTimeout(function() { // async, so data will be available
- var issues = validate(validator);
- expect(issues).to.have.lengthOf(1);
- var issue = issues[0];
- expect(issue.type).to.eql('outdated_tags');
- expect(issue.subtype).to.eql('deprecated_tags');
- expect(issue.severity).to.eql('warning');
- expect(issue.entityIds).to.have.lengthOf(1);
- expect(issue.entityIds[0]).to.eql('w-1');
- done();
- }, 20);
+ await setTimeout(20);
+ var issues = validate(validator);
+ expect(issues).to.have.lengthOf(1);
+ var issue = issues[0];
+ expect(issue.type).to.eql('outdated_tags');
+ expect(issue.subtype).to.eql('deprecated_tags');
+ expect(issue.severity).to.eql('warning');
+ expect(issue.entityIds).to.have.lengthOf(1);
+ expect(issue.entityIds[0]).to.eql('w-1');
});
- it('flags deprecated tag with no replacement', function(done) {
+ it('flags deprecated tag with no replacement', async () => {
createWay({'highway': 'no'});
var validator = iD.validationOutdatedTags(context);
- window.setTimeout(function() { // async, so data will be available
- var issues = validate(validator);
- expect(issues).to.have.lengthOf(1);
- var issue = issues[0];
- expect(issue.type).to.eql('outdated_tags');
- expect(issue.subtype).to.eql('deprecated_tags');
- expect(issue.severity).to.eql('warning');
- expect(issue.entityIds).to.have.lengthOf(1);
- expect(issue.entityIds[0]).to.eql('w-1');
- done();
- }, 20);
+ await setTimeout(20);
+ var issues = validate(validator);
+ expect(issues).to.have.lengthOf(1);
+ var issue = issues[0];
+ expect(issue.type).to.eql('outdated_tags');
+ expect(issue.subtype).to.eql('deprecated_tags');
+ expect(issue.severity).to.eql('warning');
+ expect(issue.entityIds).to.have.lengthOf(1);
+ expect(issue.entityIds[0]).to.eql('w-1');
});
- it('ignores way with no relations', function(done) {
+ it('ignores way with no relations', async () => {
createWay({});
var validator = iD.validationOutdatedTags(context);
- window.setTimeout(function() { // async, so data will be available
- var issues = validate(validator);
- expect(issues).to.have.lengthOf(0);
- done();
- }, 20);
+ await setTimeout(20);
+ var issues = validate(validator);
+ expect(issues).to.have.lengthOf(0);
});
- it('ignores multipolygon tagged on the relation', function(done) {
+ it('ignores multipolygon tagged on the relation', async () => {
createRelation({}, { type: 'multipolygon', building: 'yes' });
var validator = iD.validationOutdatedTags(context);
- window.setTimeout(function() { // async, so data will be available
- var issues = validate(validator);
- expect(issues).to.have.lengthOf(0);
- done();
- }, 20);
+ await setTimeout(20);
+ var issues = validate(validator);
+ expect(issues).to.have.lengthOf(0);
});
});
diff --git a/test/spec/validations/suspicious_name.js b/test/spec/validations/suspicious_name.js
index 6acb69390..532f5a542 100644
--- a/test/spec/validations/suspicious_name.js
+++ b/test/spec/validations/suspicious_name.js
@@ -1,3 +1,5 @@
+import { setTimeout } from 'node:timers/promises';
+
describe('iD.validations.suspicious_name', function () {
var context;
@@ -69,123 +71,103 @@ describe('iD.validations.suspicious_name', function () {
return issues;
}
- it('has no errors on init', function(done) {
+ it('has no errors on init', async () => {
var validator = iD.validationSuspiciousName(context);
- window.setTimeout(function() { // async, so data will be available
- var issues = validate(validator);
- expect(issues).to.have.lengthOf(0);
- done();
- }, 20);
+ await setTimeout(20);
+ var issues = validate(validator);
+ expect(issues).to.have.lengthOf(0);
});
- it('ignores way with no tags', function(done) {
+ it('ignores way with no tags', async () => {
createWay({});
var validator = iD.validationSuspiciousName(context);
- window.setTimeout(function() { // async, so data will be available
- var issues = validate(validator);
- expect(issues).to.have.lengthOf(0);
- done();
- }, 20);
+ await setTimeout(20);
+ var issues = validate(validator);
+ expect(issues).to.have.lengthOf(0);
});
- it('ignores feature with no name', function(done) {
+ it('ignores feature with no name', async () => {
createWay({ shop: 'supermarket' });
var validator = iD.validationSuspiciousName(context);
- window.setTimeout(function() { // async, so data will be available
- var issues = validate(validator);
- expect(issues).to.have.lengthOf(0);
- done();
- }, 20);
+ await setTimeout(20);
+ var issues = validate(validator);
+ expect(issues).to.have.lengthOf(0);
});
- it('ignores feature with a specific name', function(done) {
+ it('ignores feature with a specific name', async () => {
createWay({ shop: 'supermarket', name: 'Lou\'s' });
var validator = iD.validationSuspiciousName(context);
- window.setTimeout(function() { // async, so data will be available
- var issues = validate(validator);
- expect(issues).to.have.lengthOf(0);
- done();
- }, 20);
+ await setTimeout(20);
+ var issues = validate(validator);
+ expect(issues).to.have.lengthOf(0);
});
- it('ignores feature with a specific name that includes a generic name', function(done) {
+ it('ignores feature with a specific name that includes a generic name', async () => {
createWay({ shop: 'supermarket', name: 'Lou\'s Store' });
var validator = iD.validationSuspiciousName(context);
- window.setTimeout(function() { // async, so data will be available
- var issues = validate(validator);
- expect(issues).to.have.lengthOf(0);
- done();
- }, 20);
+ await setTimeout(20);
+ var issues = validate(validator);
+ expect(issues).to.have.lengthOf(0);
});
- it('ignores feature matching excludeNamed pattern in name-suggestion-index', function(done) {
+ it('ignores feature matching excludeNamed pattern in name-suggestion-index', async () => {
createWay({ shop: 'supermarket', name: 'famiglia cooperativa' });
var validator = iD.validationSuspiciousName(context);
- window.setTimeout(function() { // async, so data will be available
- var issues = validate(validator);
- expect(issues).to.have.lengthOf(0);
- done();
- }, 20);
+ await setTimeout(20);
+ var issues = validate(validator);
+ expect(issues).to.have.lengthOf(0);
});
- it('flags feature matching a excludeGeneric pattern in name-suggestion-index', function(done) {
+ it('flags feature matching a excludeGeneric pattern in name-suggestion-index', async () => {
createWay({ shop: 'supermarket', name: 'super mercado' });
var validator = iD.validationSuspiciousName(context);
- window.setTimeout(function() { // async, so data will be available
- var issues = validate(validator);
- expect(issues).to.have.lengthOf(1);
- var issue = issues[0];
- expect(issue.type).to.eql('suspicious_name');
- expect(issue.subtype).to.eql('generic_name');
- expect(issue.entityIds).to.have.lengthOf(1);
- expect(issue.entityIds[0]).to.eql('w-1');
- done();
- }, 20);
+ await setTimeout(20);
+ var issues = validate(validator);
+ expect(issues).to.have.lengthOf(1);
+ var issue = issues[0];
+ expect(issue.type).to.eql('suspicious_name');
+ expect(issue.subtype).to.eql('generic_name');
+ expect(issue.entityIds).to.have.lengthOf(1);
+ expect(issue.entityIds[0]).to.eql('w-1');
});
- it('flags feature matching a global exclude pattern in name-suggestion-index', function(done) {
+ it('flags feature matching a global exclude pattern in name-suggestion-index', async () => {
createWay({ shop: 'supermarket', name: 'store' });
var validator = iD.validationSuspiciousName(context);
- window.setTimeout(function() { // async, so data will be available
- var issues = validate(validator);
- expect(issues).to.have.lengthOf(1);
- var issue = issues[0];
- expect(issue.type).to.eql('suspicious_name');
- expect(issue.subtype).to.eql('generic_name');
- expect(issue.entityIds).to.have.lengthOf(1);
- expect(issue.entityIds[0]).to.eql('w-1');
- done();
- }, 20);
+ await setTimeout(20);
+ var issues = validate(validator);
+ expect(issues).to.have.lengthOf(1);
+ var issue = issues[0];
+ expect(issue.type).to.eql('suspicious_name');
+ expect(issue.subtype).to.eql('generic_name');
+ expect(issue.entityIds).to.have.lengthOf(1);
+ expect(issue.entityIds[0]).to.eql('w-1');
});
- it('flags feature with a name that is just a defining tag key', function(done) {
+ it('flags feature with a name that is just a defining tag key', async () => {
createWay({ amenity: 'drinking_water', name: 'Amenity' });
var validator = iD.validationSuspiciousName(context);
- window.setTimeout(function() { // async, so data will be available
- var issues = validate(validator);
- expect(issues).to.have.lengthOf(1);
- var issue = issues[0];
- expect(issue.type).to.eql('suspicious_name');
- expect(issue.subtype).to.eql('generic_name');
- expect(issue.entityIds).to.have.lengthOf(1);
- expect(issue.entityIds[0]).to.eql('w-1');
- done();
- }, 20);
+ await setTimeout(20);
+ var issues = validate(validator);
+ expect(issues).to.have.lengthOf(1);
+ var issue = issues[0];
+ expect(issue.type).to.eql('suspicious_name');
+ expect(issue.subtype).to.eql('generic_name');
+ expect(issue.entityIds).to.have.lengthOf(1);
+ expect(issue.entityIds[0]).to.eql('w-1');
});
- it('flags feature with a name that is just a defining tag value', function(done) {
+ it('flags feature with a name that is just a defining tag value', async () => {
createWay({ shop: 'red_bicycle_emporium', name: 'Red Bicycle Emporium' });
var validator = iD.validationSuspiciousName(context);
- window.setTimeout(function() { // async, so data will be available
- var issues = validate(validator);
- expect(issues).to.have.lengthOf(1);
- var issue = issues[0];
- expect(issue.type).to.eql('suspicious_name');
- expect(issue.subtype).to.eql('generic_name');
- expect(issue.entityIds).to.have.lengthOf(1);
- expect(issue.entityIds[0]).to.eql('w-1');
- done();
- }, 20);
+ await setTimeout(20);
+ var issues = validate(validator);
+ expect(issues).to.have.lengthOf(1);
+ var issue = issues[0];
+ expect(issue.type).to.eql('suspicious_name');
+ expect(issue.subtype).to.eql('generic_name');
+ expect(issue.entityIds).to.have.lengthOf(1);
+ expect(issue.entityIds[0]).to.eql('w-1');
});
it('flags feature with a name that matches the preset name', async () => {
diff --git a/test/spec_helpers.mts b/test/spec_helpers.mts
index f56e14037..f312c2f71 100644
--- a/test/spec_helpers.mts
+++ b/test/spec_helpers.mts
@@ -34,33 +34,6 @@ UIEvent.prototype.initUIEvent = function (...args) {
return initUIEvent.apply(this, args);
};
-// vitest has deprecated the done() callback, so we overwrite the `it` function
-const _it = it;
-Reflect.set(
- global,
- 'it',
- Object.assign(
- (msg: string, fn: (done?: (err?: any) => void) => void | Promise) => {
- _it(msg, () => {
- if (fn.length) {
- // there is a done callback -> return a promise instead
- return new Promise((resolve, reject) => fn(err => {
- if (err) {
- reject(err);
- } else {
- resolve();
- }
- }));
- } else {
- // no done callback -> normal behaviour
- return fn();
- }
- });
- },
- { todo: _it.todo, skip: _it.skip, only: _it.only, each: _it.each },
- ),
-);
-
// must be imported after global envs are defined
await import('../modules/id.js');
const iD = global.iD;