diff --git a/web/gui/src/main/webapp/app/fw/svg/map.js b/web/gui/src/main/webapp/app/fw/svg/map.js index 0b3088d2eb..c736149df8 100644 --- a/web/gui/src/main/webapp/app/fw/svg/map.js +++ b/web/gui/src/main/webapp/app/fw/svg/map.js @@ -19,17 +19,81 @@ @author Simon Hunt */ + +/* + The Map Service caches GeoJSON maps, which can be loaded into the map + layer of the Topology View. + + A GeoMap object can be fetched by ID. IDs that start with an asterisk + identify maps bundled with the GUI. IDs that do not start with an + asterisk are assumed to be URLs to externally provided data (exact + format to be decided). + + e.g. var geomap = MapService.fetchGeoMap('*continental-us'); + + The GeoMap object encapsulates topology data (features), and the + D3 projection object. + + Note that, since the GeoMap instance is cached / shared, it should + contain no state. + */ + (function () { 'use strict'; - var $log; + // injected references + var $log, fs; + + // internal state + var maps = d3.map(), + msgMs = 'MapService.', + bundledUrlPrefix = 'data/map/'; + + function getUrl(id) { + if (id[0] === '*') { + return bundledUrlPrefix + id.slice(1) + '.json'; + } + return id + '.json'; + } angular.module('onosSvg') - .factory('MapService', ['$log', function (_$log_) { + .factory('MapService', ['$log', 'FnService', + + function (_$log_, _fs_) { $log = _$log_; + fs = _fs_; + + function clearCache() { + maps = d3.map(); + } + + function fetchGeoMap(id) { + if (!fs.isS(id)) { + return null; + } + + var geomap = maps.get(id); + + if (!geomap) { + // need to fetch the data and build the object... + geomap = { + id: id, + url: getUrl(id), + wasCached: false + }; + // TODO: use $http service to load map data asynchronously + + maps.set(id, geomap); + } else { + geomap.wasCached = true; + } + + return geomap; + } return { - tbd: function () {} + clearCache: clearCache, + fetchGeoMap: fetchGeoMap }; }]); diff --git a/web/gui/src/main/webapp/app/fw/svg/svg.js b/web/gui/src/main/webapp/app/fw/svg/svg.js index 9f8351b06c..ba400bd01a 100644 --- a/web/gui/src/main/webapp/app/fw/svg/svg.js +++ b/web/gui/src/main/webapp/app/fw/svg/svg.js @@ -22,6 +22,6 @@ (function () { 'use strict'; - angular.module('onosSvg', []); + angular.module('onosSvg', ['onosUtil']); }()); diff --git a/web/gui/src/main/webapp/tests/app/fw/svg/map-spec.js b/web/gui/src/main/webapp/tests/app/fw/svg/map-spec.js index 2822bb9ae1..159f36b1dd 100644 --- a/web/gui/src/main/webapp/tests/app/fw/svg/map-spec.js +++ b/web/gui/src/main/webapp/tests/app/fw/svg/map-spec.js @@ -20,17 +20,80 @@ @author Simon Hunt */ describe('factory: fw/svg/map.js', function() { - var ms; + var $log, fs, ms, d3Elem, geomap; - beforeEach(module('onosSvg')); + var urlPrefix = 'data/map/'; - beforeEach(inject(function (MapService) { + beforeEach(module('onosUtil', 'onosSvg')); + + beforeEach(inject(function (_$log_, FnService, MapService) { + $log = _$log_; + fs = FnService; ms = MapService; + ms.clearCache(); + // TODO: d3Elem = d3.select('body').append('...').attr('id', 'myFoo'); })); + afterEach(function () { + // TODO d3.select('#myFoo').remove(); + }); + it('should define MapService', function () { expect(ms).toBeDefined(); }); - // TODO: unit tests for map functions + it('should define api functions', function () { + expect(fs.areFunctions(ms, [ + 'clearCache', 'fetchGeoMap' + ])).toBeTruthy(); + }); + + it('should return null when no parameters given', function () { + geomap = ms.fetchGeoMap(); + expect(geomap).toBeNull(); + }); + + it('should augment the id of a bundled map', function () { + var id = '*foo'; + geomap = ms.fetchGeoMap(id); + expect(geomap).toBeDefined(); + expect(geomap.id).toBe(id); + expect(geomap.url).toBe('data/map/foo.json'); + }); + + it('should treat an external id as the url itself', function () { + var id = 'some/path/to/foo'; + geomap = ms.fetchGeoMap(id); + expect(geomap).toBeDefined(); + expect(geomap.id).toBe(id); + expect(geomap.url).toBe(id + '.json'); + }); + + it('should cache the returned objects', function () { + var id = 'foo'; + geomap = ms.fetchGeoMap(id); + expect(geomap).toBeDefined(); + expect(geomap.wasCached).toBeFalsy(); + expect(geomap.tagged).toBeUndefined(); + + geomap.tagged = 'I woz here'; + + geomap = ms.fetchGeoMap(id); + expect(geomap).toBeDefined(); + expect(geomap.wasCached).toBeTruthy(); + expect(geomap.tagged).toEqual('I woz here'); + }); + + it('should clear the cache when asked', function () { + var id = 'foo'; + geomap = ms.fetchGeoMap(id); + expect(geomap.wasCached).toBeFalsy(); + + geomap = ms.fetchGeoMap(id); + expect(geomap.wasCached).toBeTruthy(); + + ms.clearCache(); + geomap = ms.fetchGeoMap(id); + expect(geomap.wasCached).toBeFalsy(); + }); });