diff --git a/modules/ui/fields/localized.js b/modules/ui/fields/localized.js index 316794942..96c410e51 100644 --- a/modules/ui/fields/localized.js +++ b/modules/ui/fields/localized.js @@ -22,6 +22,10 @@ export function uiFieldLocalized(field, context) { var _countryCode; var _tags; + + // A concern here in switching to async data means that _languagesArray will not + // be available the first time through, so things like the fetchers and + // the language() function will not work immediately. context.data().get('languages') .then(loadLanguagesArray) .catch(function() { /* ignore */ }); diff --git a/test/spec/spec_helpers.js b/test/spec/spec_helpers.js index c5a782bc4..e11291ac3 100644 --- a/test/spec/spec_helpers.js +++ b/test/spec/spec_helpers.js @@ -23,7 +23,7 @@ iD.data.presets = { // creating `coreContext` creates validators and some of the validators try loading these iD.data.deprecated = []; iD.data.nsi_brands = []; -iD.data.nsi_filters = []; +iD.data.nsi_filters = { discardNames: [] }; mocha.setup({ diff --git a/test/spec/ui/fields/localized.js b/test/spec/ui/fields/localized.js index b2f07a90b..10127c818 100644 --- a/test/spec/ui/fields/localized.js +++ b/test/spec/ui/fields/localized.js @@ -22,121 +22,148 @@ describe('iD.uiFieldLocalized', function() { }); - it('adds a blank set of fields when the + button is clicked', function() { + it('adds a blank set of fields when the + button is clicked', function(done) { var localized = iD.uiFieldLocalized(field, context); - 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); + 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); }); - it('doesn\'t create a tag when the value is empty', function() { + it('doesn\'t create a tag when the value is empty', function(done) { var localized = iD.uiFieldLocalized(field, context); - selection.call(localized); - happen.click(selection.selectAll('.localized-add').node()); + window.setTimeout(function() { // async, so data will be available + 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'}); + 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); }); - it('doesn\'t create a tag when the name is empty', function() { + it('doesn\'t create a tag when the name is empty', function(done) { var localized = iD.uiFieldLocalized(field, context); - selection.call(localized); - happen.click(selection.selectAll('.localized-add').node()); + window.setTimeout(function() { // async, so data will be available + 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'}); + 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); }); - it('creates a tag after setting language then value', function() { + it('creates a tag after setting language then value', function(done) { var localized = iD.uiFieldLocalized(field, context); - selection.call(localized); - happen.click(selection.selectAll('.localized-add').node()); + window.setTimeout(function() { // async, so data will be available + 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'}); + iD.utilGetSetValue(selection.selectAll('.localized-value'), 'Value'); + happen.once(selection.selectAll('.localized-value').node(), {type: 'change'}); + done(); + }, 20); }); - it('creates a tag after setting value then language', function() { + it('creates a tag after setting value then language', function(done) { var localized = iD.uiFieldLocalized(field, context); - selection.call(localized); - happen.click(selection.selectAll('.localized-add').node()); + window.setTimeout(function() { // async, so data will be available + 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'}); + iD.utilGetSetValue(selection.selectAll('.localized-lang'), 'Deutsch'); + happen.once(selection.selectAll('.localized-lang').node(), {type: 'change'}); + done(); + }, 20); }); - it('changes an existing language', function() { + it('changes an existing language', function(done) { var localized = iD.uiFieldLocalized(field, context); - selection.call(localized); - localized.tags({'name:de': 'Value'}); + window.setTimeout(function() { // async, so data will be available + 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'}); + iD.utilGetSetValue(selection.selectAll('.localized-lang'), 'English'); + happen.once(selection.selectAll('.localized-lang').node(), {type: 'change'}); + done(); + }, 20); }); - it('ignores similar keys like `old_name`', function() { + it('ignores similar keys like `old_name`', function(done) { var localized = iD.uiFieldLocalized(field, context); - selection.call(localized); - localized.tags({'old_name:de': 'Value'}); + window.setTimeout(function() { // async, so data will be available + 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; + expect(selection.selectAll('.localized-lang').empty()).to.be.ok; + expect(selection.selectAll('.localized-value').empty()).to.be.ok; + done(); + }, 20); }); - it('removes the tag when the language is emptied', function() { + it('removes the tag when the language is emptied', function(done) { var localized = iD.uiFieldLocalized(field, context); - selection.call(localized); - localized.tags({'name:de': 'Value'}); + window.setTimeout(function() { // async, so data will be available + 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'}); + iD.utilGetSetValue(selection.selectAll('.localized-lang'), ''); + happen.once(selection.selectAll('.localized-lang').node(), {type: 'change'}); + done(); + }, 20); }); - it('removes the tag when the value is emptied', function() { + it('removes the tag when the value is emptied', function(done) { var localized = iD.uiFieldLocalized(field, context); - selection.call(localized); - localized.tags({'name:de': 'Value'}); + window.setTimeout(function() { // async, so data will be available + 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'}); + iD.utilGetSetValue(selection.selectAll('.localized-value'), ''); + happen.once(selection.selectAll('.localized-value').node(), {type: 'change'}); + done(); + }, 20); }); }); diff --git a/test/spec/validations/suspicious_name.js b/test/spec/validations/suspicious_name.js index 1a51983d1..eb490ca7f 100644 --- a/test/spec/validations/suspicious_name.js +++ b/test/spec/validations/suspicious_name.js @@ -1,6 +1,14 @@ describe('iD.validations.suspicious_name', function () { var context; + before(function() { + iD.data.nsi_filters = { discardNames: ['^stores?$'] }; + }); + + after(function() { + iD.data.nsi_filters = { discardNames: [] }; + }); + beforeEach(function() { context = iD.coreContext().init(); }); @@ -30,94 +38,138 @@ describe('iD.validations.suspicious_name', function () { return issues; } - it('has no errors on init', function() { - var issues = validate(); - expect(issues).to.have.lengthOf(0); + it('has no errors on init', function(done) { + var validator = iD.validationSuspiciousName(context); + window.setTimeout(function() { // async, so data will be available + var issues = validate(); + expect(issues).to.have.lengthOf(0); + done(); + }, 20); }); - it('ignores way with no tags', function() { + it('ignores way with no tags', function(done) { createWay({}); - var issues = validate(); - expect(issues).to.have.lengthOf(0); + var validator = iD.validationSuspiciousName(context); + window.setTimeout(function() { // async, so data will be available + var issues = validate(); + expect(issues).to.have.lengthOf(0); + done(); + }, 20); }); - it('ignores feature with no name', function() { + it('ignores feature with no name', function(done) { createWay({ shop: 'supermarket' }); - var issues = validate(); - expect(issues).to.have.lengthOf(0); + var validator = iD.validationSuspiciousName(context); + window.setTimeout(function() { // async, so data will be available + var issues = validate(); + expect(issues).to.have.lengthOf(0); + done(); + }, 20); }); - it('ignores feature with a specific name', function() { + it('ignores feature with a specific name', function(done) { createWay({ shop: 'supermarket', name: 'Lou\'s' }); - var issues = validate(); - expect(issues).to.have.lengthOf(0); + var validator = iD.validationSuspiciousName(context); + window.setTimeout(function() { // async, so data will be available + var issues = validate(); + expect(issues).to.have.lengthOf(0); + done(); + }, 20); }); - it('ignores feature with a specific name that includes a generic name', function() { + it('ignores feature with a specific name that includes a generic name', function(done) { createWay({ shop: 'supermarket', name: 'Lou\'s Store' }); - var issues = validate(); - expect(issues).to.have.lengthOf(0); + var validator = iD.validationSuspiciousName(context); + window.setTimeout(function() { // async, so data will be available + var issues = validate(); + expect(issues).to.have.lengthOf(0); + done(); + }, 20); }); - it('flags feature with a known generic name', function() { + it('flags feature with a known generic name', function(done) { createWay({ shop: 'supermarket', name: 'Store' }); - var issues = validate(); - 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'); + var validator = iD.validationSuspiciousName(context); + window.setTimeout(function() { // async, so data will be available + var issues = validate(); + 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); }); - it('flags feature with a name that is just a defining tag key', function() { + it('flags feature with a name that is just a defining tag key', function(done) { createWay({ amenity: 'drinking_water', name: 'Amenity' }); - var issues = validate(); - 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'); + var validator = iD.validationSuspiciousName(context); + window.setTimeout(function() { // async, so data will be available + var issues = validate(); + 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); }); - it('flags feature with a name that is just a defining tag value', function() { + it('flags feature with a name that is just a defining tag value', function(done) { createWay({ shop: 'red_bicycle_emporium', name: 'Red Bicycle Emporium' }); - var issues = validate(); - 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'); + var validator = iD.validationSuspiciousName(context); + window.setTimeout(function() { // async, so data will be available + var issues = validate(); + 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); }); - it('ignores feature with a non-matching `not:name` tag', function() { + it('ignores feature with a non-matching `not:name` tag', function(done) { createWay({ shop: 'supermarket', name: 'Lou\'s', 'not:name': 'Lous' }); - var issues = validate(); - expect(issues).to.have.lengthOf(0); + var validator = iD.validationSuspiciousName(context); + window.setTimeout(function() { // async, so data will be available + var issues = validate(); + expect(issues).to.have.lengthOf(0); + done(); + }, 20); }); - it('flags feature with a matching `not:name` tag', function() { + it('flags feature with a matching `not:name` tag', function(done) { createWay({ shop: 'supermarket', name: 'Lous', 'not:name': 'Lous' }); - var issues = validate(); - expect(issues).to.have.lengthOf(1); - var issue = issues[0]; - expect(issue.type).to.eql('suspicious_name'); - expect(issue.subtype).to.eql('not_name'); - expect(issue.entityIds).to.have.lengthOf(1); - expect(issue.entityIds[0]).to.eql('w-1'); + var validator = iD.validationSuspiciousName(context); + window.setTimeout(function() { // async, so data will be available + var issues = validate(); + expect(issues).to.have.lengthOf(1); + var issue = issues[0]; + expect(issue.type).to.eql('suspicious_name'); + expect(issue.subtype).to.eql('not_name'); + expect(issue.entityIds).to.have.lengthOf(1); + expect(issue.entityIds[0]).to.eql('w-1'); + done(); + }, 20); }); - it('flags feature with a matching a semicolon-separated `not:name` tag', function() { + it('flags feature with a matching a semicolon-separated `not:name` tag', function(done) { createWay({ shop: 'supermarket', name: 'Lous', 'not:name': 'Louis\';Lous;Louis\'s' }); - var issues = validate(); - expect(issues).to.have.lengthOf(1); - var issue = issues[0]; - expect(issue.type).to.eql('suspicious_name'); - expect(issue.subtype).to.eql('not_name'); - expect(issue.entityIds).to.have.lengthOf(1); - expect(issue.entityIds[0]).to.eql('w-1'); + window.setTimeout(function() { // async, so data will be available + var validator = iD.validationSuspiciousName(context); + var issues = validate(); + expect(issues).to.have.lengthOf(1); + var issue = issues[0]; + expect(issue.type).to.eql('suspicious_name'); + expect(issue.subtype).to.eql('not_name'); + expect(issue.entityIds).to.have.lengthOf(1); + expect(issue.entityIds[0]).to.eql('w-1'); + done(); + }, 20); }); });