diff --git a/modules/core/context.js b/modules/core/context.js index 2d18bda67..1acc4f96b 100644 --- a/modules/core/context.js +++ b/modules/core/context.js @@ -88,7 +88,9 @@ export function coreContext() { } context.preauth = function(options) { - connection.switch(options); + if (connection) { + connection.switch(options); + } return context; }; @@ -97,7 +99,9 @@ export function coreContext() { entitiesLoaded(err, result); if (callback) callback(err, result); } - connection.loadTiles(projection, dimensions, done); + if (connection) { + connection.loadTiles(projection, dimensions, done); + } }; context.loadEntity = function(id, callback) { @@ -105,7 +109,9 @@ export function coreContext() { entitiesLoaded(err, result); if (callback) callback(err, result); } - connection.loadEntity(id, done); + if (connection) { + connection.loadEntity(id, done); + } }; context.zoomToEntity = function(id, zoomTo) { @@ -136,7 +142,9 @@ export function coreContext() { context.minEditableZoom = function(_) { if (!arguments.length) return minEditableZoom; minEditableZoom = _; - connection.tileZoom(_); + if (connection) { + connection.tileZoom(_); + } return context; }; diff --git a/modules/core/history.js b/modules/core/history.js index 7c53e55b0..7c69eaa76 100644 --- a/modules/core/history.js +++ b/modules/core/history.js @@ -454,6 +454,7 @@ export function coreHistory(context) { // When we restore a modified way, we also need to fetch any missing // childnodes that would normally have been downloaded with it.. #2142 if (loadChildNodes) { + var osm = context.connection(); var missing = _(baseEntities) .filter({ type: 'way' }) .map('nodes') @@ -462,7 +463,7 @@ export function coreHistory(context) { .reject(function(n) { return stack[0].graph.hasEntity(n); }) .value(); - if (!_.isEmpty(missing)) { + if (!_.isEmpty(missing) && osm) { loadComplete = false; context.redrawEnable(false); @@ -480,8 +481,7 @@ export function coreHistory(context) { // fetch older versions of nodes that were deleted.. _.each(visible.false, function(entity) { - context.connection() - .loadEntityVersion(entity.id, +entity.version - 1, childNodesLoaded); + osm.loadEntityVersion(entity.id, +entity.version - 1, childNodesLoaded); }); } @@ -492,7 +492,7 @@ export function coreHistory(context) { } }; - context.connection().loadMultiple(missing, childNodesLoaded); + osm.loadMultiple(missing, childNodesLoaded); } } } diff --git a/modules/modes/save.js b/modules/modes/save.js index 27a70ebca..766f66779 100644 --- a/modules/modes/save.js +++ b/modules/modes/save.js @@ -35,8 +35,8 @@ export function modeSave(context) { }; var commit = uiCommit(context) - .on('cancel', cancel) - .on('save', save); + .on('cancel', cancel) + .on('save', save); function cancel() { @@ -46,7 +46,8 @@ export function modeSave(context) { function save(changeset, tryAgain) { - var loading = uiLoading(context).message(t('save.uploading')).blocking(true), + var osm = context.connection(), + loading = uiLoading(context).message(t('save.uploading')).blocking(true), history = context.history(), origChanges = history.changes(actionDiscardTags(history.difference())), localGraph = context.graph(), @@ -57,6 +58,8 @@ export function modeSave(context) { conflicts = [], errors = []; + if (!osm) return; + if (!tryAgain) { history.perform(actionNoop()); // checkpoint } @@ -64,7 +67,7 @@ export function modeSave(context) { context.container().call(loading); if (toCheck.length) { - context.connection().loadMultiple(toLoad, loaded); + osm.loadMultiple(toLoad, loaded); } else { upload(); } @@ -119,7 +122,7 @@ export function modeSave(context) { if (loadMore.length) { toLoad.push.apply(toLoad, loadMore); - context.connection().loadMultiple(loadMore, loaded); + osm.loadMultiple(loadMore, loaded); } if (!toLoad.length) { @@ -134,7 +137,7 @@ export function modeSave(context) { return { id: id, text: text, action: function() { history.replace(action); } }; } function formatUser(d) { - return '' + d + ''; + return '' + d + ''; } function entityName(entity) { return utilDisplayName(entity) || (utilDisplayType(entity.id) + ' ' + entity.id); @@ -201,7 +204,7 @@ export function modeSave(context) { } else { var changes = history.changes(actionDiscardTags(history.difference())); if (changes.modified.length || changes.created.length || changes.deleted.length) { - context.connection().putChangeset(changeset, changes, uploadCallback); + osm.putChangeset(changeset, changes, uploadCallback); } else { // changes were insignificant or reverted by user d3.select('.inspector-wrap *').remove(); loading.close(); @@ -360,10 +363,13 @@ export function modeSave(context) { context.container().selectAll('#content') .attr('class', 'inactive'); - if (context.connection().authenticated()) { + var osm = context.connection(); + if (!osm) return; + + if (osm.authenticated()) { done(); } else { - context.connection().authenticate(function(err) { + osm.authenticate(function(err) { if (err) { cancel(); } else { diff --git a/modules/renderer/background.js b/modules/renderer/background.js index ab98e186d..5fc5286de 100644 --- a/modules/renderer/background.js +++ b/modules/renderer/background.js @@ -76,7 +76,9 @@ export function rendererBackground(context) { delete q.offset; } - window.location.replace('#' + utilQsString(q, true)); + if (!window.mocha) { + window.location.replace('#' + utilQsString(q, true)); + } var imageryUsed = [b.imageryUsed()]; @@ -124,6 +126,9 @@ export function rendererBackground(context) { if (!arguments.length) return baseLayer.source(); // test source against OSM imagery blacklists.. + var osm = context.connection(); + if (!osm) return background; + var blacklists = context.connection().imageryBlacklists(); var template = d.template(), diff --git a/modules/renderer/map.js b/modules/renderer/map.js index faadea119..8e82e12c8 100644 --- a/modules/renderer/map.js +++ b/modules/renderer/map.js @@ -73,8 +73,10 @@ export function rendererMap(context) { context .on('change.map', immediateRedraw); - context.connection() - .on('change.map', immediateRedraw); + var osm = context.connection(); + if (osm) { + osm.on('change.map', immediateRedraw); + } context.history() .on('change.map', immediateRedraw) diff --git a/modules/services/index.js b/modules/services/index.js index ea8f600c7..f893714ab 100644 --- a/modules/services/index.js +++ b/modules/services/index.js @@ -13,3 +13,12 @@ export var services = { wikidata: serviceWikidata, wikipedia: serviceWikipedia }; + +export { + serviceMapillary, + serviceNominatim, + serviceOsm, + serviceTaginfo, + serviceWikidata, + serviceWikipedia +}; diff --git a/modules/ui/account.js b/modules/ui/account.js index 13c122b47..ec8811ee2 100644 --- a/modules/ui/account.js +++ b/modules/ui/account.js @@ -4,17 +4,19 @@ import { svgIcon } from '../svg/index'; export function uiAccount(context) { - var connection = context.connection(); + var osm = context.connection(); function update(selection) { - if (!connection.authenticated()) { + if (!osm) return; + + if (!osm.authenticated()) { selection.selectAll('#userLink, #logoutLink') .classed('hide', true); return; } - connection.userDetails(function(err, details) { + osm.userDetails(function(err, details) { var userLink = selection.select('#userLink'), logoutLink = selection.select('#logoutLink'); @@ -28,7 +30,7 @@ export function uiAccount(context) { // Link userLink.append('a') - .attr('href', connection.userURL(details.display_name)) + .attr('href', osm.userURL(details.display_name)) .attr('target', '_blank'); // Add thumbnail or dont @@ -52,7 +54,7 @@ export function uiAccount(context) { .text(t('logout')) .on('click.logout', function() { d3.event.preventDefault(); - connection.logout(); + osm.logout(); }); }); } @@ -67,9 +69,9 @@ export function uiAccount(context) { .attr('id', 'userLink') .classed('hide', true); - connection - .on('change.account', function() { update(selection); }); - - update(selection); + if (osm) { + osm.on('change.account', function() { update(selection); }); + update(selection); + } }; } diff --git a/modules/ui/commit.js b/modules/ui/commit.js index 4e1512b8e..088d282e7 100644 --- a/modules/ui/commit.js +++ b/modules/ui/commit.js @@ -26,6 +26,9 @@ export function uiCommit(context) { function commit(selection) { + var osm = context.connection(); + if (!osm) return; + if (!changeset) { var detected = utilDetect(), tags = { @@ -87,7 +90,7 @@ export function uiCommit(context) { commentField.node().select(); - context.connection().userChangesets(function (err, changesets) { + osm.userChangesets(function (err, changesets) { if (err) return; var comments = changesets.map(function(changeset) { @@ -174,7 +177,7 @@ export function uiCommit(context) { .html(t('commit.upload_explanation')); - context.connection().userDetails(function(err, user) { + osm.userDetails(function(err, user) { if (err) return; var userLink = d3.select(document.createElement('div')); @@ -190,7 +193,7 @@ export function uiCommit(context) { .append('a') .attr('class','user-info') .text(user.display_name) - .attr('href', context.connection().userURL(user.display_name)) + .attr('href', osm.userURL(user.display_name)) .attr('tabindex', -1) .attr('target', '_blank'); diff --git a/modules/ui/contributors.js b/modules/ui/contributors.js index ae09a202a..2a07a5b87 100644 --- a/modules/ui/contributors.js +++ b/modules/ui/contributors.js @@ -5,13 +5,16 @@ import { svgIcon } from '../svg/index'; export function uiContributors(context) { - var debouncedUpdate = _.debounce(function() { update(); }, 1000), + var osm = context.connection(), + debouncedUpdate = _.debounce(function() { update(); }, 1000), limit = 4, hidden = false, wrap = d3.select(null); function update() { + if (!osm) return; + var users = {}, entities = context.intersects(context.map().extent()); @@ -32,7 +35,7 @@ export function uiContributors(context) { .enter() .append('a') .attr('class', 'user-link') - .attr('href', function(d) { return context.connection().userURL(d); }) + .attr('href', function(d) { return osm.userURL(d); }) .attr('target', '_blank') .attr('tabindex', -1) .text(String); @@ -44,7 +47,7 @@ export function uiContributors(context) { .attr('target', '_blank') .attr('tabindex', -1) .attr('href', function() { - return context.connection().changesetsURL(context.map().center(), context.map().zoom()); + return osm.changesetsURL(context.map().center(), context.map().zoom()); }) .text(u.length - limit + 1); @@ -71,10 +74,11 @@ export function uiContributors(context) { return function(selection) { + if (!osm) return; wrap = selection; update(); - context.connection().on('loaded.contributors', debouncedUpdate); + osm.on('loaded.contributors', debouncedUpdate); context.map().on('move.contributors', debouncedUpdate); }; } diff --git a/modules/ui/init.js b/modules/ui/init.js index c382f257a..08181d367 100644 --- a/modules/ui/init.js +++ b/modules/ui/init.js @@ -290,18 +290,19 @@ export function uiInit(context) { .call(uiShortcuts(context)); } - var authenticating = uiLoading(context) - .message(t('loading_auth')) - .blocking(true); + var osm = context.connection(), + auth = uiLoading(context).message(t('loading_auth')).blocking(true); - context.connection() - .on('authLoading.ui', function() { - context.container() - .call(authenticating); - }) - .on('authDone.ui', function() { - authenticating.close(); - }); + if (osm && auth) { + osm + .on('authLoading.ui', function() { + context.container() + .call(auth); + }) + .on('authDone.ui', function() { + auth.close(); + }); + } uiInitCounter++; diff --git a/modules/ui/intro/intro.js b/modules/ui/intro/intro.js index c87e2aa6a..bb351c452 100644 --- a/modules/ui/intro/intro.js +++ b/modules/ui/intro/intro.js @@ -55,14 +55,15 @@ export function uiIntro(context) { context.enter(modeBrowse(context)); // Save current map state - var history = context.history().toJSON(), + var osm = context.connection(), + history = context.history().toJSON(), hash = window.location.hash, center = context.map().center(), zoom = context.map().zoom(), background = context.background().baseLayerSource(), overlays = context.background().overlayLayerSources(), opacity = d3.selectAll('#map .layer-background').style('opacity'), - loadedTiles = context.connection().loadedTiles(), + loadedTiles = osm && osm.loadedTiles(), baseEntities = context.history().graph().base().entities, countryCode = services.geocoder.countryCode; @@ -70,7 +71,7 @@ export function uiIntro(context) { context.inIntro(true); // Load semi-real data used in intro - context.connection().toggle(false).reset(); + if (osm) { osm.toggle(false).reset(); } context.history().reset(); context.history().merge(d3.values(coreGraph().load(introGraph).entities)); context.history().checkpoint('initial'); @@ -109,11 +110,11 @@ export function uiIntro(context) { curtain.remove(); navwrap.remove(); d3.selectAll('#map .layer-background').style('opacity', opacity); - context.connection().toggle(true).reset().loadedTiles(loadedTiles); + if (osm) { osm.toggle(true).reset().loadedTiles(loadedTiles); } context.history().reset().merge(d3.values(baseEntities)); context.background().baseLayerSource(background); overlays.forEach(function (d) { context.background().toggleOverlayLayer(d); }); - if (history) context.history().fromJSON(history, false); + if (history) { context.history().fromJSON(history, false); } context.map().centerZoom(center, zoom); window.location.replace(hash); services.geocoder.countryCode = countryCode; diff --git a/modules/ui/panels/history.js b/modules/ui/panels/history.js index a1c604d00..0c7418490 100644 --- a/modules/ui/panels/history.js +++ b/modules/ui/panels/history.js @@ -4,7 +4,7 @@ import { svgIcon } from '../../svg'; export function uiPanelHistory(context) { - + var osm; function displayTimestamp(entity) { if (!entity.timestamp) return t('info_panels.history.unknown'); @@ -33,13 +33,15 @@ export function uiPanelHistory(context) { .append('div') .attr('class', 'links'); - links - .append('a') - .attr('class', 'user-osm-link') - .attr('href', context.connection().userURL(entity.user)) - .attr('target', '_blank') - .attr('tabindex', -1) - .text('OSM'); + if (osm) { + links + .append('a') + .attr('class', 'user-osm-link') + .attr('href', osm.userURL(entity.user)) + .attr('target', '_blank') + .attr('tabindex', -1) + .text('OSM'); + } links .append('a') @@ -68,13 +70,15 @@ export function uiPanelHistory(context) { .append('div') .attr('class', 'links'); - links - .append('a') - .attr('class', 'changeset-osm-link') - .attr('href', context.connection().changesetURL(entity.changeset)) - .attr('target', '_blank') - .attr('tabindex', -1) - .text('OSM'); + if (osm) { + links + .append('a') + .attr('class', 'changeset-osm-link') + .attr('href', osm.changesetURL(entity.changeset)) + .attr('target', '_blank') + .attr('tabindex', -1) + .text('OSM'); + } links .append('a') @@ -90,6 +94,8 @@ export function uiPanelHistory(context) { var selected = _.filter(context.selectedIDs(), function(e) { return context.hasEntity(e); }), singular = selected.length === 1 ? selected[0] : null; + osm = context.connection(); + selection.html(''); selection @@ -122,15 +128,17 @@ export function uiPanelHistory(context) { .text(t('info_panels.history.changeset') + ': ') .call(displayChangeset, entity); - selection - .append('a') - .attr('class', 'view-history-on-osm') - .attr('target', '_blank') - .attr('tabindex', -1) - .attr('href', context.connection().historyURL(entity)) - .call(svgIcon('#icon-out-link', 'inline')) - .append('span') - .text(t('info_panels.history.link_text')); + if (osm) { + selection + .append('a') + .attr('class', 'view-history-on-osm') + .attr('target', '_blank') + .attr('tabindex', -1) + .attr('href', osm.historyURL(entity)) + .call(svgIcon('#icon-out-link', 'inline')) + .append('span') + .text(t('info_panels.history.link_text')); + } } diff --git a/modules/ui/spinner.js b/modules/ui/spinner.js index 9daaf4b92..758ed2d5d 100644 --- a/modules/ui/spinner.js +++ b/modules/ui/spinner.js @@ -1,5 +1,5 @@ export function uiSpinner(context) { - var connection = context.connection(); + var osm = context.connection(); return function(selection) { @@ -8,16 +8,16 @@ export function uiSpinner(context) { .attr('src', context.imagePath('loader-black.gif')) .style('opacity', 0); - connection - .on('loading.spinner', function() { - img.transition() - .style('opacity', 1); - }); - - connection - .on('loaded.spinner', function() { - img.transition() - .style('opacity', 0); - }); + if (osm) { + osm + .on('loading.spinner', function() { + img.transition() + .style('opacity', 1); + }) + .on('loaded.spinner', function() { + img.transition() + .style('opacity', 0); + }); + } }; } diff --git a/modules/ui/status.js b/modules/ui/status.js index 05cf2bc9d..d9ba2bd0e 100644 --- a/modules/ui/status.js +++ b/modules/ui/status.js @@ -4,12 +4,14 @@ import { svgIcon } from '../svg/index'; export function uiStatus(context) { - var connection = context.connection(); + var osm = context.connection(); + return function(selection) { + if (!osm) return; function update() { - connection.status(function(err, apiStatus) { + osm.status(function(err, apiStatus) { selection.html(''); if (err) { @@ -24,7 +26,7 @@ export function uiStatus(context) { .text(t('login')) .on('click.login', function() { d3.event.preventDefault(); - connection.authenticate(); + osm.authenticate(); }); } else { // TODO: nice messages for different error types @@ -41,8 +43,7 @@ export function uiStatus(context) { }); } - connection - .on('change', function() { update(selection); }); + osm.on('change', function() { update(selection); }); window.setInterval(update, 90000); update(selection); diff --git a/modules/ui/success.js b/modules/ui/success.js index d7002520c..bf9b19541 100644 --- a/modules/ui/success.js +++ b/modules/ui/success.js @@ -43,8 +43,10 @@ export function uiSuccess(context) { .append('span') .text(t('success.help_link_text')); - var changesetURL = context.connection().changesetURL(changeset.id); + var osm = context.connection(); + if (!osm) return; + var changesetURL = osm.changesetURL(changeset.id); var viewOnOsm = body .append('a') @@ -62,9 +64,8 @@ export function uiSuccess(context) { .append('div') .text(t('success.view_on_osm')); - var message = (changeset.tags.comment || t('success.edited_osm')).substring(0, 130) + - ' ' + context.connection().changesetURL(changeset.id); + ' ' + changesetURL; var sharing = { facebook: 'https://facebook.com/sharer/sharer.php?u=' + encodeURIComponent(changesetURL), diff --git a/test/index.html b/test/index.html index ad42a95b7..cf2737c66 100644 --- a/test/index.html +++ b/test/index.html @@ -6,7 +6,7 @@ -
+ diff --git a/test/spec/behavior/hash.js b/test/spec/behavior/hash.js index fda5c8da3..2c4d4f04f 100644 --- a/test/spec/behavior/hash.js +++ b/test/spec/behavior/hash.js @@ -5,8 +5,6 @@ describe('iD.behaviorHash', function () { beforeEach(function () { context = iD.Context(); - context.connection().loadTiles = function () {}; // Neuter connection - var container = d3.select(document.createElement('div')); context.container(container); container.call(context.map()); @@ -15,6 +13,7 @@ describe('iD.behaviorHash', function () { afterEach(function () { hash.off(); + location.hash = ''; }); it('sets hadHash if location.hash is present', function () { diff --git a/test/spec/services/mapillary.js b/test/spec/services/mapillary.js index 0bf7b7f39..dd184db05 100644 --- a/test/spec/services/mapillary.js +++ b/test/spec/services/mapillary.js @@ -6,6 +6,14 @@ describe('iD.serviceMapillary', function() { context, server, mapillary, orig; + before(function() { + iD.services.mapillary = iD.serviceMapillary; + }); + + after(function() { + delete iD.services.mapillary; + }); + beforeEach(function() { context = iD.Context().assetPath('../dist/'); context.projection diff --git a/test/spec/services/nominatim.js b/test/spec/services/nominatim.js index 37e5a60ee..fb984039b 100644 --- a/test/spec/services/nominatim.js +++ b/test/spec/services/nominatim.js @@ -1,6 +1,15 @@ describe('iD.serviceNominatim', function() { var server, nominatim; + + before(function() { + iD.services.geocoder = iD.serviceNominatim; + }); + + after(function() { + delete iD.services.geocoder; + }); + beforeEach(function() { server = sinon.fakeServer.create(); nominatim = iD.services.geocoder; diff --git a/test/spec/services/osm.js b/test/spec/services/osm.js index 259a0cc7d..f23c1d635 100644 --- a/test/spec/services/osm.js +++ b/test/spec/services/osm.js @@ -1,5 +1,5 @@ describe('iD.serviceOsm', function () { - var context, connection, spy; + var context, connection, server, spy; function login() { if (!connection) return; @@ -17,7 +17,16 @@ describe('iD.serviceOsm', function () { connection.logout(); } + before(function() { + iD.services.osm = iD.serviceOsm; + }); + + after(function() { + delete iD.services.osm; + }); + beforeEach(function () { + server = sinon.fakeServer.create(); context = iD.Context(); connection = context.connection(); connection.switch({ urlroot: 'http://www.openstreetmap.org' }); @@ -25,6 +34,10 @@ describe('iD.serviceOsm', function () { spy = sinon.spy(); }); + afterEach(function() { + server.restore(); + }); + it('is instantiated', function () { expect(connection).to.be.ok; @@ -109,8 +122,7 @@ describe('iD.serviceOsm', function () { }); describe('#loadFromAPI', function () { - var server, - path = '/api/0.6/map?bbox=-74.542,40.655,-74.541,40.656', + var path = '/api/0.6/map?bbox=-74.542,40.655,-74.541,40.656', response = '' + '