diff options
Diffstat (limited to 'misc/openlayers/tests/Layer/Grid.html')
-rw-r--r-- | misc/openlayers/tests/Layer/Grid.html | 1593 |
1 files changed, 1593 insertions, 0 deletions
diff --git a/misc/openlayers/tests/Layer/Grid.html b/misc/openlayers/tests/Layer/Grid.html new file mode 100644 index 0000000..495a9ab --- /dev/null +++ b/misc/openlayers/tests/Layer/Grid.html @@ -0,0 +1,1593 @@ +<html> +<head> + <script src="../OLLoader.js"></script> + <script type="text/javascript"> + + var isMozilla = (navigator.userAgent.indexOf("compatible") == -1); + var layer; + + var name = 'Test Layer'; + var url = "http://vmap0.tiles.osgeo.org/wms/vmap0"; + var params = {layers: 'basic', format: 'image/png'}; + + /** + * NOTE TO READER: + * + * Some of the tests on the Grid class actually use the WMS class. + * This is because WMS is a subclass of Grid and it implements the + * core functions which are necessary to test the tile-generation + * mechanism. + * + */ + + + function test_constructor (t) { + t.plan( 7 ); + + layer = new OpenLayers.Layer.Grid(name, url, params, null); + t.ok( layer instanceof OpenLayers.Layer.Grid, "returns OpenLayers.Layer.Grid object" ); + t.eq( layer.buffer, 0, "buffer default is 0"); + t.eq( layer.ratio, 1.5, "ratio default is 1.5"); + t.eq( layer.numLoadingTiles, 0, "numLoadingTiles starts at 0"); + t.ok( layer.tileClass === OpenLayers.Tile.Image, "tileClass default is OpenLayers.Tile.Image"); + t.eq( layer.className, 'olLayerGrid', "className default is olLayerGrid"); + + var obj = {}; + var func = function() {}; + layer.events.register('tileloaded', obj, func); + + t.ok( layer.events.listeners['tileloaded'].length == 1, "one listener for tileloaded after register"); + } + + function test_constructor_singleTile(t) { + t.plan(2); + layer = new OpenLayers.Layer.Grid(name, url, params, {singleTile: true}); + t.eq( layer.className, 'olLayerGridSingleTile', "className default is olLayerGridSingleTile"); + t.eq( layer.removeBackBufferDelay, 0, "removeBackBufferDelay default is 0"); + } + + function test_setMap(t) { + t.plan(1); + var map = new OpenLayers.Map('map', {tileManager: null}); + layer = new OpenLayers.Layer.Grid(name, url, params, null); + map.addLayer(layer); + t.ok(OpenLayers.Element.hasClass(layer.div, "olLayerGrid"), + "olLayerGrid class assigned to layer div"); + map.destroy(); + } + + function test_setMap_singleTile(t) { + t.plan(1); + var map = new OpenLayers.Map('map'); + layer = new OpenLayers.Layer.Grid(name, url, params, {singleTile: true}); + map.addLayer(layer); + t.ok(OpenLayers.Element.hasClass(layer.div, "olLayerGridSingleTile"), + "olLayerGridSingleTile class assigned to layer div"); + map.destroy(); + } + + function test_Layer_Grid_inittiles (t) { + t.plan( 2 ); + var map = new OpenLayers.Map('map'); + layer = new OpenLayers.Layer.WMS(name, url, params, {buffer:2}); + map.addLayer(layer); + map.setCenter(new OpenLayers.LonLat(0,0),5); + t.eq( layer.grid.length, 8, "Grid rows is correct." ); + t.eq( layer.grid[0].length, 7, "Grid cols is correct." ); + + } + + function test_Layer_Grid_tileClass(t) { + t.plan(2); + + var myTileClass = OpenLayers.Class(OpenLayers.Tile, {}); + var map = new OpenLayers.Map('map'); + layer = new OpenLayers.Layer.WMS(name, url, params, { + tileClass: myTileClass + }); + map.addLayer(layer); + + t.ok(layer.tileClass === myTileClass, "tileClass is set"); + var instance = layer.addTile(new OpenLayers.Bounds(-10, 10, 50, 100), + new OpenLayers.Pixel(10, 12)); + + t.ok(instance instanceof myTileClass, "addTile returns type is correct"); + + map.destroy(); + } + + function test_Layer_Grid_clearTiles (t) { + t.plan(4); + + var map = new OpenLayers.Map('map'); + layer = new OpenLayers.Layer.WMS(name, url, params); + map.addLayer(layer); + + map.setCenter(new OpenLayers.LonLat(0,0)); + + var numTiles = layer.grid.length * layer.grid[0].length; + + //our count of how many times tile.destroy() is called + tilesDeleted = 0; + + //this will get set to false if we try to destroy a tile that has + // not been unhookedv + allTilesUnhooked = true; + + OpenLayers.Tile.Image.prototype._destroy = + OpenLayers.Tile.Image.prototype.destroy; + + OpenLayers.Tile.Image.prototype.destroy = function() { + if (!this.unhooked) { + allTilesUnhooked = false; + } + tilesDeleted++; + } + + layer.removeTileMonitoringHooks = function(tile) { + tile.unhooked = true; + } + + layer.clearGrid(); + + t.ok( layer.grid != null, "layer.grid does not get nullified" ); + t.eq(tilesDeleted, numTiles, "all tiles destroy()ed properly"); + t.ok(allTilesUnhooked, "all tiles unhooked before being destroyed"); + t.eq(layer.gridResolution, null, "gridResolution set to null"); + + OpenLayers.Tile.Image.prototype.destroy = + OpenLayers.Tile.Image.prototype._destroy; + + } + + + function test_Layer_Grid_getTilesBounds(t) { + t.plan(4); + + layer = new OpenLayers.Layer.WMS(name, url, params); + + + //normal grid + var bl = { bounds: new OpenLayers.Bounds(1,2,2,3)}; + var tr = { bounds: new OpenLayers.Bounds(2,3,3,4)}; + layer.grid = [ [6, tr], + [bl, 7]]; + + var bounds = layer.getTilesBounds(); + var testBounds = new OpenLayers.Bounds(1,2,3,4); + + t.ok( bounds.equals(testBounds), "getTilesBounds() returns correct bounds"); + + //no tiles + layer.grid = []; + bounds = layer.getTilesBounds(); + + t.ok(bounds == null, "getTilesBounds() on a tile-less grid returns null"); + + + //singleTile + var singleTile = { bounds: new OpenLayers.Bounds(1,2,3,4)}; + layer.grid = [ [ singleTile ] ]; + bounds = layer.getTilesBounds(); + + t.ok( bounds.equals(testBounds), "getTilesBounds() returns correct bounds"); + + //world wrapped around the dateline + var bl = { bounds: new OpenLayers.Bounds(0,-90,180,90)}; + var tr = { bounds: new OpenLayers.Bounds(-180,-90,0,90)}; + layer.grid = [[bl, tr]]; + + var bounds = layer.getTilesBounds(); + var testBounds = new OpenLayers.Bounds(0,-90,360,90); + + t.ok( bounds.equals(testBounds), "getTilesBounds() returns correct bounds"); + + } + + function test_Layer_Grid_getResolution(t) { + t.plan( 1 ); + + var map = new OpenLayers.Map('map'); + layer = new OpenLayers.Layer.WMS(name, url, params); + map.addLayer(layer); + + map.zoom = 5; + + t.eq( layer.getResolution(), 0.0439453125, "getResolution() returns correct value"); + } + + function test_Layer_Grid_getZoomForExtent(t) { + t.plan( 2 ); + var bounds, zoom; + + var map = new OpenLayers.Map('map'); + layer = new OpenLayers.Layer.WMS(name, url, params); + map.addLayer(layer); + + bounds = new OpenLayers.Bounds(10,10,12,12); + zoom = layer.getZoomForExtent(bounds); + + t.eq( zoom, 8, "getZoomForExtent() returns correct value"); + + bounds = new OpenLayers.Bounds(10,10,100,100); + zoom = layer.getZoomForExtent(bounds); + + t.eq( zoom, 2, "getZoomForExtent() returns correct value"); + } + + function test_moveGriddedTiles(t) { + t.plan(1); + var map = new OpenLayers.Map('map'); + layer = new OpenLayers.Layer.WMS(name, url, params, {buffer: 2}); + map.addLayer(layer); + map.setCenter([0, 0], 5); + var count = 0; + layer.shiftColumn = function(prepend) { + ++count; + OpenLayers.Layer.WMS.prototype.shiftColumn.apply(this, arguments); + } + map.moveTo([15, 0]); + t.delay_call(.5, function() { + t.eq(count, 1, "column shifted once"); + }); + } + + function test_Layer_Grid_moveTo(t) { + + t.plan(13); + + var map = new OpenLayers.Map('map'); + layer = new OpenLayers.Layer.WMS(name, url, params); + layer.destroy = function() {}; //we're going to do funky things with the grid + layer.applyBackBuffer = function() {}; // backbuffering isn't under test here + map.addLayer(layer); + map.setCenter([-10, 0], 5); + + var log = []; + + //make sure null bounds doesnt cause script error. + // no test necessary, just action + map.getExtent = function() { return null; } + layer.singleTile = false; + layer.moveTo(); //checks to make sure null bounds doesnt break us + + + //observing globals + layer.initSingleTile = function(bounds) { + g_WhichFunc = "InitSingle"; + g_Bounds = bounds; + }; + layer.initGriddedTiles = function(bounds) { + g_WhichFunc = "InitGridded"; + g_Bounds = bounds; + }; + layer.moveGriddedTiles = function() { + g_WhichFunc = "MoveGridded"; + g_Bounds = layer.map.getExtent(); + }; + var clearTestBounds = function() { + g_WhichFunc = null; + g_Bounds = null; + }; + + //default map extent (tested every time below) + b = new OpenLayers.Bounds(0,0,100,100); + map.getExtent = function() { + return b; + }; + var tilesBounds = null; + layer.getTilesBounds = function() { + return tilesBounds; + } + + +//FORCE + + //empty grid + layer.grid = []; + //grid + clearTestBounds(); + layer.singleTile = false; + layer.moveTo() + t.ok(g_Bounds.equals(b), "if grid is empty, initGridded called"); + + //singletile + clearTestBounds(); + layer.singleTile = true; + layer.moveTo() + t.ok(g_Bounds.equals(b), "if grid is empty, initSingleTile called"); + + //zoomChanged + zoomChanged = true; + layer.grid = [ [ {} ] ]; + + //grid + clearTestBounds(); + layer.singleTile = false; + layer.moveTo(null, zoomChanged); + t.ok(g_Bounds.equals(b), "if layer has grid but zoomChanged is called, initGridded called"); + + //singletile + clearTestBounds(); + layer.singleTile = true; + layer.moveTo(null, zoomChanged); + t.ok(g_Bounds.equals(b), "if layer has grid but zoomChanged is called, initSingleTile called"); + + +//NO FORCE + zoomChanged = false; + layer.grid = [ [ {} ] ]; + + //single tile + layer.singleTile = true; + + //DRAGGING + var dragging = true; + + //in bounds + clearTestBounds(); + tilesBounds = new OpenLayers.Bounds(-10,-10,110,110); + layer.moveTo(null, zoomChanged, dragging); + t.ok(g_Bounds == null, "if dragging and tile in bounds, no init()"); + + //out bounds + clearTestBounds(); + tilesBounds = new OpenLayers.Bounds(10,10,120,120); + layer.moveTo(null, zoomChanged, dragging); + t.ok(g_Bounds == null, "if dragging and tile out of bounds, no init()"); + + //NOT DRAGGING + dragging = false; + + //in bounds + clearTestBounds(); + tilesBounds = new OpenLayers.Bounds(-10,-10,110,110); + layer.moveTo(null, zoomChanged, dragging); + t.ok(g_Bounds == null, "if dragging and tile in bounds, no init()"); + + //out bounds + clearTestBounds(); + tilesBounds = new OpenLayers.Bounds(10,10,120,120); + layer.moveTo(null, zoomChanged, dragging); + t.ok(g_WhichFunc == "InitSingle", "if not dragging and tile out of bounds, we call initSingleTile()"); + t.ok(g_Bounds.equals(b), "if not dragging and tile out of bounds, we call initSingleTile() with correct bounds"); + + + //gridded + layer.grid = [ [ {position: new OpenLayers.Pixel(0,0)} ] ]; + layer.singleTile = false; + + //regular move + clearTestBounds(); + tilesBounds = new OpenLayers.Bounds(10,10,120,120); + g_WhichFunc = null; + layer.moveTo(null, zoomChanged); + t.eq(g_WhichFunc, "MoveGridded", "if tiles not drastically out of bounds, we call moveGriddedTile()"); + t.ok(g_Bounds.equals(b), "if tiles not drastically out of bounds, we call moveGriddedTile() with correct bounds"); + + // drastic pan + clearTestBounds(); + tilesBounds = new OpenLayers.Bounds(-150,-150,-120,-120); + layer.moveTo(null, zoomChanged); + t.ok(g_WhichFunc == "InitGridded", "if tiles drastically out of bounds, we call initGriddedTile()"); + t.ok(g_Bounds.equals(b), "if tiles drastically out of bounds, we call initGriddedTile() with correct bounds"); + } + + /** THIS WOULD BE WHERE THE TESTS WOULD GO FOR + * + * -insertColumn + * -insertRow + * + + function 08_Layer_Grid_insertColumn(t) { + } + + function 09_Layer_Grid_insertRow(t) { + } + + * + */ + + function test_Layer_Grid_clone(t) { + t.plan(7); + + var options = {tileSize: new OpenLayers.Size(500,50)}; + var map = new OpenLayers.Map('map', options); + layer = new OpenLayers.Layer.Grid(name, url, params); + map.addLayer(layer); + + layer.grid = [ [6, 7], + [8, 9]]; + + // if we clone when tiles are still loading, this should not influence the clone + layer.numLoadingTiles = 1; + var clone = layer.clone(); + t.eq( clone.numLoadingTiles, 0, "numLoadingTiles should be reset"); + t.ok( clone.grid != layer.grid, "clone does not copy grid"); + t.ok( clone.grid.length == 0, "clone creates a new array instead"); + + t.eq(clone.backBuffer, null, "no backbuffer from original"); + + t.ok( clone.tileSize.equals(layer.tileSize), "tileSize correctly cloned"); + + layer.tileSize.w += 40; + + t.eq( clone.tileSize.w, 500, "changing layer.tileSize does not change clone.tileSize -- a fresh copy was made, not just copied reference"); + + t.eq( clone.alpha, layer.alpha, "alpha copied correctly"); + + layer.grid = null; + } + + function test_Layer_Grid_setTileSize(t) { + t.plan(1); + + OpenLayers.Layer.HTTPRequest.prototype._setTileSize = + OpenLayers.Layer.HTTPRequest.prototype.setTileSize; + + OpenLayers.Layer.HTTPRequest.prototype.setTileSize = function(size) { + g_Size = size; + }; + + + layer = new OpenLayers.Layer.Grid(name, url, params, { + singleTile: true + }); + mapSize = new OpenLayers.Size(100,1000); + layer.map = { + getSize: function() { return mapSize; } + } + + g_Size = null; + layer.setTileSize(); + + var idealSize = new OpenLayers.Size(150,1500); + t.ok( g_Size && g_Size.equals(idealSize), "correctly calculated tile size passed to superclass setTileSize() function"); + + OpenLayers.Layer.HTTPRequest.prototype.setTileSize = + OpenLayers.Layer.HTTPRequest.prototype._setTileSize; + } + + function test_Layer_Grid_initSingleTile(t) { + t.plan( 11 ); + + layer = new OpenLayers.Layer.Grid(name, url, params, { + singleTile: true, + ratio: 2 + }); + + var bounds = new OpenLayers.Bounds(-10,10,50,100); + + var desiredTileBounds = new OpenLayers.Bounds(-40,-35,80,145); + var desiredUL = new OpenLayers.LonLat(-40,145); + + translatedPX = {}; + layer.map = { + getLayerPxFromLonLat: function(ul) { + t.ok(ul.lon === desiredUL.lon && ul.lat === desiredUL.lat, "correct ul passed to translation"); + return translatedPX; + }, + getResolution: function() { + } + } + + var newTile = { + draw: function() { + t.ok(true, "newly created tile has been drawn"); + } + }; + layer.addTile = function(tileBounds, px) { + t.ok(tileBounds.equals(desiredTileBounds), "correct tile bounds passed to addTile to create new tile"); + t.ok(px == translatedPX, "correct tile px passed to addTile to create new tile"); + return newTile; + }; + layer.addTileMonitoringHooks = function(tile) { + t.ok(tile == newTile, "adding monitoring hooks to the newly added tile"); + }; + layer.removeExcessTiles = function(x,y) { + t.ok(x == 1 && y == 1, "removeExcessTiles called") + }; + + + layer.grid = []; + layer.initSingleTile(bounds); + + t.ok(layer.grid[0][0] == newTile, "grid's 0,0 is set to the newly created tile"); + + var tile = { + moveTo: function(tileBounds, px) { + t.ok(tileBounds.equals(desiredTileBounds), "correct tile bounds passed to tile.moveTo()"); + t.ok(px == translatedPX, "correct tile px passed to tile.moveTo()"); + } + }; + layer.grid = [[ tile ]]; + layer.initSingleTile(bounds); + + } + + function test_Layer_Grid_addTileMonitoringHooks(t) { + t.plan(18); + + layer = new OpenLayers.Layer.Grid(); + layer.events = { + 'triggerEvent': function(str, evt) { + g_events.push([str, evt]); + } + } + + var tile = { + events: { + register: function(name, obj, func) { + g_registered[name] = [obj, func]; + }, + on: function(obj) { + for (var o in obj) { + if (obj.hasOwnProperty(o)) { + tile.events.register(o, obj.scope, obj[o]); + } + } + } + }, + imgDiv: {className: ''} + } + + g_registered = {}; + g_events = []; + + layer.addTileMonitoringHooks(tile); + + //loadstart + t.ok(tile.onLoadStart != null, "onLoadStart function created and added to tile"); + entry = g_registered["loadstart"]; + t.ok( entry && entry[0] == layer && entry[1] == tile.onLoadStart, "loadstart correctly registered"); + + layer.numLoadingTiles = 0; + g_events = []; + tile.onLoadStart.apply(layer); + + t.eq(g_events[0][0], "loadstart", "loadstart event triggered when numLoadingTiles is 0"); + t.eq(layer.numLoadingTiles, 1, "numLoadingTiles incremented"); + t.eq(g_events[1][0], "tileloadstart", "tileloadstart event triggered"); + + g_events = []; + tile.onLoadStart.apply(layer); + t.eq(g_events.length, 1, "tileloadstart, but not loadstart triggered when numLoadingTiles is not 0"); + t.eq(layer.numLoadingTiles, 2, "numLoadingTiles incremented"); + + + //loadend + t.ok(tile.onLoadEnd != null, "onLoadEnd function created and added to tile"); + entry = g_registered["loadend"]; + t.ok( entry && entry[0] == layer && entry[1] == tile.onLoadEnd, "loadend correctly registered"); + + g_events = []; + tile.onLoadError.apply(layer); + t.eq(g_events[0][0], "tileerror", "tileerror triggered"); + t.ok(g_events[0][1].tile === tile, "tile passed as tile property to event object"); + + layer.numLoadingTiles = 2; + g_events = []; + tile.onLoadEnd.apply(layer, [{}]); + t.eq(g_events[0][0], "tileloaded", "tileloaded triggered when numLoadingTiles is > 0"); + t.ok(g_events[0][1].tile === tile, "tile passed as tile property to event object"); + t.eq(g_events.length, 1, "loadend event not triggered when numLoadingTiles is > 0"); + t.eq(layer.numLoadingTiles, 1, "numLoadingTiles decremented"); + + + g_events = []; + layer.grid = [[{}]]; // to prevent error in updateBackBuffer + tile.onLoadEnd.apply(layer, [{}]); + t.eq(g_events[0][0], "tileloaded", "tileloaded triggered when numLoadingTiles is 0"); + t.eq(g_events[1][0], "loadend", "loadend event triggered when numLoadingTiles is 0"); + t.eq(layer.numLoadingTiles, 0, "numLoadingTiles decremented"); + } + + function test_Layer_Grid_removeTileMonitoringHooks(t) { + t.plan(2); + + layer = new OpenLayers.Layer.Grid(); + + var tile = { + onLoadStart: {}, + onLoadEnd: {}, + unload: function() {}, + events: { + unregister: function(name, obj, func) { + g_unregistered[name] = [obj, func]; + }, + un: OpenLayers.Events.prototype.un + } + } + + g_unregistered = {}; + + layer.removeTileMonitoringHooks(tile); + + entry = g_unregistered["loadstart"]; + t.ok( entry && entry[0] == layer && entry[1] == tile.onLoadStart, "loadstart correctly unregistered"); + + entry = g_unregistered["loadend"]; + t.ok( entry && entry[0] == layer && entry[1] == tile.onLoadEnd, "loadend correctly unregistered"); + } + + function test_Layer_Grid_tileSizeIsInteger(t) { + t.plan(1); + + var map = new OpenLayers.Map('map'); + var layer = new OpenLayers.Layer.Grid(name, url, params, { + singleTile: true, + ratio: 1.5 + }); + map.addLayers([layer]); + + width = layer.tileSize.w; + height = layer.tileSize.h; + t.ok(width == parseInt(width) && height == parseInt(height), "calculated tileSize width/height are integer values"); + } + function test_Layer_Grid_getTileBounds(t) { + t.plan(2); + var map = new OpenLayers.Map("map2", {zoomMethod: null}); + var url = "http://octo.metacarta.com/cgi-bin/mapserv"; + layer = new OpenLayers.Layer.WMS(name, url, params); + + var newParams = { layers: 'sooper', + chickpeas: 'image/png'}; + + map.addLayer(layer); + map.zoomToMaxExtent(); + map.zoomIn(); + var bounds = layer.getTileBounds(new OpenLayers.Pixel(200,200)); + t.eq(bounds.toBBOX(), "-180,-90,0,90", "get tile bounds returns correct bounds"); + map.pan(200,0, {animate:false}); + var bounds = layer.getTileBounds(new OpenLayers.Pixel(200,200)); + t.eq(bounds.toBBOX(), "0,-90,180,90", "get tile bounds returns correct bounds after pan"); + } + + function test_Layer_Grid_moveTo_buffer_calculation (t) { + t.plan(6); + + var map = new OpenLayers.Map( 'map3' ); // odd map size + var layer0 = new OpenLayers.Layer.WMS( "0 buffer: OpenLayers WMS", + "http://labs.metacarta.com/wms/vmap0", + {layers: 'basic'}, {'buffer':0} ); + map.addLayer(layer0); + + var layer1 = new OpenLayers.Layer.WMS( "1 buffer: OpenLayers WMS", + "http://labs.metacarta.com/wms/vmap0", + {layers: 'basic'}, {'buffer':1} ); + map.addLayer(layer1); + + var layer2 = new OpenLayers.Layer.WMS( "2 buffer: OpenLayers WMS", + "http://labs.metacarta.com/wms/vmap0", + {layers: 'basic'}, {'buffer':2} ); + map.addLayer(layer2); + + map.setCenter(new OpenLayers.LonLat(0, 0), 4); + t.eq( layer0.grid.length, 3, "Grid rows with buffer:0" ); + map.setBaseLayer(layer1); + t.eq( layer1.grid.length, 5, "Grid rows with buffer:1" ); + map.setBaseLayer(layer2); + t.eq( layer2.grid.length, 7, "Grid rows with buffer:2" ); + + // zooming in on Greenland exercises the bug from pre-r4313 + map.setCenter(new OpenLayers.LonLat(0, 90), 4); + t.eq( layer0.grid.length, 3, "Grid rows with buffer:0" ); + map.setBaseLayer(layer1); + t.eq( layer1.grid.length, 5, "Grid rows with buffer:1" ); + map.setBaseLayer(layer2); + t.eq( layer2.grid.length, 7, "Grid rows with buffer:2" ); + } + + function test_Layer_Grid_destroy (t) { + + t.plan( 9 ); + + var map = new OpenLayers.Map('map', {tileManager: null}); + layer = new OpenLayers.Layer.Grid(name, url, params); + map.addLayer(layer); + layer.destroy(); + t.eq( layer.grid, null, "layer.grid is null after destroy" ); + t.eq( layer.tileSize, null, "layer.tileSize is null after destroy" ); + + + //test with tile creation + layer = new OpenLayers.Layer.WMS(name, url, params); + map.addLayer(layer); + + map.setCenter(new OpenLayers.LonLat(0,0), 10); + map.setCenter(new OpenLayers.LonLat(1,1)); + + //grab a reference to one of the tiles + var tile = layer.grid[1][1]; + t.eq( tile.imgDiv.className, "olTileImage", "Tile has an image" ); + + var removeBackBufferCalled = false; + layer.removeBackBuffer = function() { + removeBackBufferCalled = true; + }; + + layer.destroy(); + t.eq( tile.imgDiv, null, "Tile destroyed" ); + t.eq( layer.timerId, null, "Tile loading timeout cleared"); + t.ok( layer.grid == null, "tiles appropriately destroyed") + t.ok( removeBackBufferCalled, "destroy calls removeBackBuffer"); + + // destroy after remove from map + layer = new OpenLayers.Layer.WMS(name, url, params); + map.addLayer(layer); + map.setCenter(new OpenLayers.LonLat(0,0), 10); + map.removeLayer(layer); + layer.destroy(); + t.eq( layer.grid, null, "layer.grid is null after destroy" ); + t.eq( layer.tileSize, null, "layer.tileSize is null after destroy" ); + } + + function test_setOpacity(t) { + t.plan(5); + + var map = new OpenLayers.Map('map'); + var layer = new OpenLayers.Layer.WMS('', '', {}, { + isBaseLayer: true, + opacity: '0.6' + }); + map.addLayer(layer); + // setCenter adds tiles to the layer's grid + map.setCenter(new OpenLayers.LonLat(0, 0), 5); + + var tile = layer.grid[0][0], tileImg = tile.imgDiv; + + tile.onImageLoad(); // simulate an image load event + t.eq(layer.opacity, '0.6', 'layer opacity value is correct'); + t.eq(parseFloat(tileImg.style.opacity), 0.6, 'tile opacity is correct'); + + layer.setOpacity('0.2'); + t.eq(layer.opacity, '0.2', 'layer opacity value is correct'); + t.eq(parseFloat(tileImg.style.opacity), 0.2, 'tile opacity is correct'); + + tile = layer.addTile(new OpenLayers.Bounds(1, 2, 3, 4), + new OpenLayers.Pixel(5, 6)); + tile.draw(); // add tile to the grid + tile.onImageLoad(); // simulate an image load event + t.eq(parseFloat(tile.imgDiv.style.opacity), 0.2, "tile opacity is correc"); + + map.destroy(); + } + + function test_getServerResolution(t) { + + t.plan(4); + + var layer = new OpenLayers.Layer.Grid('', '', {}, {}); + var res; + + res = layer.getServerResolution(1); + t.eq(res, 1, '[1] getServerResolution return value is correct'); + + layer.serverResolutions = [2, 1]; + res = layer.getServerResolution(1); + t.eq(res, 1, '[2] getServerResolution return value is correct'); + + layer.serverResolutions = [2]; + res = layer.getServerResolution(1); + t.eq(res, 2, '[3] getServerResolution return value is correct'); + + var exc; + layer.serverResolutions = [0.5]; + res = layer.getServerResolution(1); + t.eq(res, 0.5, '[4] getServerResolution return value is correct'); + } + + function test_getServerZoom(t) { + + t.plan(5); + + var resolution, zoom; + var map = new OpenLayers.Map('map', { + resolutions: [8, 4, 2, 1, 0.5], + getResolution: function() { + return resolution; + } + }); + var layer = new OpenLayers.Layer.WMS('', '', {}, {isBaseLayer: true}); + map.addLayer(layer); + + resolution = 8; + zoom = layer.getServerZoom(); + t.eq(zoom, 0, '[1] getServerZoom return value is correct'); + + resolution = 4; + zoom = layer.getServerZoom(); + t.eq(zoom, 1, '[2] getServerZoom return value is correct'); + + layer.serverResolutions = [2, 1]; + resolution = 1; + zoom = layer.getServerZoom(); + t.eq(zoom, 1, '[3] getServerZoom return value is correct'); + + layer.serverResolutions = [2]; + resolution = 0.5; + zoom = layer.getServerZoom(); + t.eq(zoom, 0, '[4] getServerZoom return value is correct'); + + var exc; + layer.serverResolutions = [0.5]; + resolution = 1; + zoom = layer.getServerZoom(); + t.eq(zoom, 0, '[4] getServerZoom return value is correct'); + + map.destroy(); + } + + function test_moveTo_scale(t) { + + t.plan(11); + + var map = new OpenLayers.Map('map', { + resolutions: [32, 16, 8, 4, 2, 1], + zoomMethod: null + }); + var layer = new OpenLayers.Layer.WMS('', '', {}, { + isBaseLayer: true, + serverResolutions: [32, 16, 8] + }); + map.addLayer(layer); + + // initial resolution is 8 + map.setCenter(new OpenLayers.LonLat(0, 0), 2); + + // test initial conditions + t.eq(parseInt(layer.div.lastChild.style.width) / layer.tileSize.w, 1, 'layer div scale is 1'); + + // change from resolution 8 to 4 + map.zoomTo(3); + t.eq(parseInt(layer.div.lastChild.style.width) / layer.tileSize.w, 2, '[8->4] layer div scale is 2'); + + // change from resolution 8 to 2 + map.zoomTo(2); map.zoomTo(4); + t.eq(parseInt(layer.div.lastChild.style.width) / layer.tileSize.w, 4, '[8->2] layer div scale is 4'); + + // change from resolution 8 to 1 + map.zoomTo(2); map.zoomTo(5); + t.eq(parseInt(layer.div.lastChild.style.width) / layer.tileSize.w, 8, '[8->1] layer div scale is 8'); + + // change from resolution 4 to 2 + map.zoomTo(3); map.zoomTo(4); + t.eq(parseInt(layer.div.lastChild.style.width) / layer.tileSize.w, 4, '[4->2] layer div scale is 4'); + + // change from resolution 4 to 1 + map.zoomTo(3); map.zoomTo(5); + t.eq(parseInt(layer.div.lastChild.style.width) / layer.tileSize.w, 8, '[4->1] layer div scale is 8'); + + // change from resolution 2 to 1 + map.zoomTo(4); map.zoomTo(5); + t.eq(parseInt(layer.div.lastChild.style.width) / layer.tileSize.w, 8, '[2->1] layer div scale is 8'); + + // change from resolution 1 to 2 + map.zoomTo(5); map.zoomTo(4); + t.eq(parseInt(layer.div.lastChild.style.width) / layer.tileSize.w, 4, '[1->2] layer div scale is 4'); + + // change from resolution 1 to 4 + map.zoomTo(5); map.zoomTo(3); + t.eq(parseInt(layer.div.lastChild.style.width) / layer.tileSize.w, 2, '[1->4] layer div scale is 2'); + + // change from resolution 1 to 8 + map.zoomTo(5); map.zoomTo(2); + t.eq(parseInt(layer.div.lastChild.style.width) / layer.tileSize.w, 1, '[1->8] layer div scale is 1'); + + // change from resolution 1 to 16 + map.zoomTo(5); map.zoomTo(1); + t.eq(parseInt(layer.div.lastChild.style.width) / layer.tileSize.w, 1, '[1->16] layer div scale is 1'); + + map.destroy(); + } + + function test_moveTo_backbuffer_singletile(t) { + t.plan(4); + + var map = new OpenLayers.Map('map', { + resolutions: [1, 0.5, 0.025], + zoomMethod: null + }); + var resolution; + var layer = new OpenLayers.Layer.WMS('', '', {}, { + singleTile: true, + isBaseLayer: true, + transitionEffect: 'resize', + applyBackBuffer: function(res) { + resolution = res; + } + }); + map.addLayer(layer); + + // initial resolution is 0.025 + resolution = undefined; + map.setCenter(new OpenLayers.LonLat(0, 0), 2); + t.eq(resolution, 0.025, + 'applyBackBuffer not called on first moveTo'); + + // move to (-90, 45) + resolution = undefined; + map.setCenter(new OpenLayers.LonLat(-90, 45)); + t.eq(resolution, 0.025, + 'applyBackBuffer called when map is moved'); + + // change to resolution 1 + resolution = undefined; + map.zoomTo(0); + t.eq(resolution, 1, + 'applyBackBuffer called when map is zoomed out'); + + // change to resolution 0.5 + resolution = undefined; + map.zoomTo(1); + t.eq(resolution, 0.5, + 'applyBackBuffer called when map is zoomed out'); + + map.destroy(); + } + + function test_moveTo_backbuffer(t) { + t.plan(4); + + var map = new OpenLayers.Map('map', { + resolutions: [1, 0.5, 0.025], + zoomMethod: null + }); + var resolution; + var layer = new OpenLayers.Layer.WMS('', '', {}, { + isBaseLayer: true, + transitionEffect: 'resize', + applyBackBuffer: function(res) { + resolution = res; + } + }); + map.addLayer(layer); + + // initial resolution is 0.025 + resolution = undefined; + map.setCenter(new OpenLayers.LonLat(0, 0), 2); + t.eq(resolution, 0.025, + 'applyBackBuffer not called on first moveTo'); + + // move to (-90, 45) + resolution = undefined; + map.setCenter(new OpenLayers.LonLat(-90, 45)); + t.eq(resolution, undefined, + 'applyBackBuffer not called when map is moved'); + + // change to resolution 1 + resolution = undefined; + map.zoomTo(0); + t.eq(resolution, 1, + 'applyBackBuffer called when map is zoomed out'); + + // change to resolution 0.5 + map.zoomTo(1); + t.eq(resolution, 0.5, + 'applyBackBuffer called when map is zoomed out'); + + map.destroy(); + } + + function test_applyBackBuffer(t) { + t.plan(12); + + var map = new OpenLayers.Map('map2'); + var layer = new OpenLayers.Layer.WMS('', '', {}, { + isBaseLayer: true + }); + map.addLayer(layer); + map.zoomToMaxExtent(); + + var backBuffer; + + // test #1 + layer.createBackBuffer = function() { + return; + }; + layer.applyBackBuffer(2); + t.eq(layer.backBuffer, undefined, + 'back buffer not created if createBackBuffer returns undefined'); + + // test #2 + layer.createBackBuffer = function() { + backBuffer = document.createElement('div'); + return backBuffer; + }; + layer.gridResolution = 32; + layer.backBufferResolution = 2; + layer.grid[0][0].bounds = new OpenLayers.Bounds(0, 1, 1, 0); + layer.applyBackBuffer(2); + t.ok(layer.backBuffer === backBuffer, + 'back buffer set in layer'); + t.ok(map.layerContainerDiv.firstChild === backBuffer, + 'back buffer inserted as first child'); + t.eq(layer.backBuffer.style.left, '250px', + 'back buffer has correct left'); + t.eq(layer.backBuffer.style.top, '275px', + 'back buffer has correct top'); + + // test #3 + layer.createBackBuffer = function() { + backBuffer = document.createElement('div'); + return backBuffer; + }; + layer.gridResolution = 32; + layer.backBufferResolution = 2; + layer.grid[0][0].bounds = new OpenLayers.Bounds(0, 1, 1, 0); + map.layerContainerOriginPx.x = 20; + map.layerContainerOriginPx.y = -20; + layer.applyBackBuffer(2); + t.ok(layer.backBuffer === backBuffer, + 'back buffer set in layer'); + t.ok(map.layerContainerDiv.firstChild === backBuffer, + 'back buffer inserted as first child'); + t.eq(layer.backBuffer.style.left, '230px', + 'back buffer has correct left'); + t.eq(layer.backBuffer.style.top, '295px', + 'back buffer has correct top'); + + // test #4 + // and a back buffer in the layer and do as if back buffer removal + // has been scheduled, and test that applyBackBuffer removes the + // back buffer and clears the timer + layer.createBackBuffer = function() { + return; + }; + backBuffer = document.createElement('div'); + map.layerContainerDiv.insertBefore(backBuffer, map.baseLayer.div); + layer.backBuffer = backBuffer; + layer.backBufferTimerId = 'fake'; + layer.applyBackBuffer(2); + t.ok(backBuffer !== map.layerContainerDiv.firstChild, + 'back buffer is not first child of layer container div'); + t.eq(layer.backBuffer, null, + 'back buffer not set in layer'); + t.eq(layer.backBufferTimerId, null, + 'back buffer timer cleared'); + map.destroy(); + } + + function test_createBackBuffer(t) { + t.plan(9); + + var map = new OpenLayers.Map('map'); + var layer = new OpenLayers.Layer.WMS('', '', {}, { + isBaseLayer: true + }); + map.addLayer(layer); + map.zoomToMaxExtent(); + + var createBackBuffer = OpenLayers.Tile.Image.prototype.createBackBuffer; + + var backBuffer; + + OpenLayers.Tile.Image.prototype.createBackBuffer = function() { + return; + }; + backBuffer = layer.createBackBuffer(); + t.ok(backBuffer != undefined, + 'createBackBuffer returns a back buffer'); + t.eq(backBuffer.childNodes.length, 0, + 'returned back buffer has no child nodes'); + + OpenLayers.Tile.Image.prototype.createBackBuffer = function() { + return document.createElement('div'); + }; + + layer.transitionEffect = 'map-resize'; + backBuffer = layer.createBackBuffer(); + t.ok(backBuffer.style.zIndex == 99, 'z-index of backbuffer correct for "map-resize".'); + layer.removeBackBuffer(); + + layer.transitionEffect = 'resize'; + backBuffer = layer.createBackBuffer(); + t.ok(backBuffer.style.zIndex == layer.getZIndex() - 1, 'z-index of backbuffer correct for "resize",'); + + layer.backBufferResolution = 1; + layer.gridResolution = 1; + layer.backBuffer = backBuffer; + layer.div.appendChild(backBuffer); + layer.backBufferLonLat = {lon: 0, lat: 0}; + layer.applyBackBuffer(1); + t.ok(backBuffer != undefined, + 'createBackBuffer returns a back buffer'); + t.eq(backBuffer.childNodes[0].style.left, '0px', + 'first tile has correct left'); + t.eq(backBuffer.childNodes[0].style.top, '0px', + 'first tile has correct top'); + t.eq(backBuffer.childNodes[1].style.left, '256px', + 'second tile has correct left'); + t.eq(backBuffer.childNodes[1].style.top, '0px', + 'second tile has correct top'); + + map.destroy(); + OpenLayers.Tile.Image.prototype.createBackBuffer = createBackBuffer; + } + + function test_removeBackBuffer(t) { + t.plan(3); + + var map = new OpenLayers.Map('map'); + var layer = new OpenLayers.Layer.WMS('', '', {}, {isBaseLayer: true}); + map.addLayer(layer); + + // add a fake back buffer + var backBuffer = document.createElement('div'); + layer.backBuffer = backBuffer; + layer.div.appendChild(backBuffer); + layer.backBufferResolution = 32; + + layer.removeBackBuffer(); + t.eq(layer.backBuffer, null, 'backBuffer set to null in layer'); + t.eq(layer.backBufferResolution, null, + 'backBufferResolution set to null in layer'); + t.ok(backBuffer.parentNode !== layer.div, + 'back buffer removed from layer'); + + map.destroy(); + } + + function test_backbuffer_replace(t) { + t.plan(6); + var map = new OpenLayers.Map('map', {tileManager: null}); + var layer = new OpenLayers.Layer.WMS('', '../../img/blank.gif'); + map.addLayer(layer); + map.zoomToMaxExtent(); + + layer.grid[1][1].onImageLoad(); + layer.mergeNewParams({foo: 'bar'}); + var tile = layer.grid[1][1]; + t.ok(OpenLayers.Element.hasClass(tile.imgDiv, 'olTileReplacing'), 'tile is marked for being replaced'); + t.ok(document.getElementById(tile.id + '_bb'), 'backbuffer created for tile'); + // simulate a css declaration where '.olTileReplacing' sets display + // to none. + tile.imgDiv.style.display = 'none'; + tile.onImageLoad(); + t.ok(!OpenLayers.Element.hasClass(tile.imgDiv, 'olTileReplacing'), 'tile replaced, no longer marked'); + t.ok(!document.getElementById(tile.id + '_bb'), 'backbuffer removed for tile'); + + layer.mergeNewParams({foo: 'baz'}); + tile = layer.grid[1][1]; + // simulate a css declaration where '.olTileReplacing' does not set + // display to none. + tile.imgDiv.style.display = 'block'; + tile.onImageLoad(); + t.ok(!OpenLayers.Element.hasClass(tile.imgDiv, 'olTileReplacing'), 'tile replaced, no longer marked'); + t.ok(document.getElementById(tile.id + '_bb'), 'backbuffer not removed for visible tile'); + } + + function test_backbuffer_replace_singleTile(t) { + t.plan(1); + var map = new OpenLayers.Map('map'); + var layer = new OpenLayers.Layer.WMS('', '../../img/blank.gif', null, { + singleTile: true, + transitionEffect: 'resize' + }); + map.addLayer(layer); + map.zoomToMaxExtent(); + + t.delay_call(1, function() { + map.zoomIn(); + var tile = layer.grid[0][0]; + t.ok(!OpenLayers.Element.hasClass(tile.imgDiv, 'olTileReplacing'), 'tile is not marked for being replaced for singleTile layers'); + }); + } + + function test_singleTile_move_and_zoom(t) { + + // + // In single tile mode with no transition effect, we insert a non-scaled + // backbuffer when the layer is moved. But if a zoom occurs right after + // a move, i.e. before the new image is received, we need to remove the + // backbuffer, or an ill-positioned image will be visible during the + // zoom transition. + // + + t.plan(4); + + var map = new OpenLayers.Map('map', {zoomMethod: null}); + var layer = new OpenLayers.Layer.WMS('', '', {}, { + isBaseLayer: true, + transitionEffect: null, + singleTile: true, + ratio: 1.1 + }); + map.addLayer(layer); + map.setCenter(new OpenLayers.LonLat(0, 0), 0); + + // move + map.setCenter(new OpenLayers.LonLat(50, 50)); + t.ok(layer.backBuffer && layer.backBuffer.parentNode === layer.div, + 'backbuffer inserted after map move'); + t.eq(layer.backBuffer.style.left, '-25px'); + t.eq(layer.backBuffer.style.top, '-28px'); + // zoom + map.zoomTo(1); + t.eq(layer.backBuffer, null, + 'back buffer removed when zooming'); + + map.destroy(); + } + + function test_backbuffer_scaled_layer(t) { + t.plan(12); + + // + // set up + // + + var map = new OpenLayers.Map('map', { + resolutions: [32, 16, 8, 4, 2, 1], + zoomMethod: null, + tileManager: null + }); + var layer = new OpenLayers.Layer.WMS( + "WMS", + window.location.href + "#", + null, + {transitionEffect: "resize"} + ); + + layer.serverResolutions = [32, 16, 8]; + + map.addLayer(layer); + map.setCenter(new OpenLayers.LonLat(0, 0), 2); + + var origCreateBackBuffer = OpenLayers.Tile.Image.prototype.createBackBuffer; + OpenLayers.Tile.Image.prototype.createBackBuffer = function() { + return document.createElement('div'); + }; + + // we want to control when the back buffer is removed + var removeBackBuffer = OpenLayers.Function.bind( + layer.removeBackBuffer, layer); + layer.removeBackBuffer = function() {}; + + // + // test + // + + // change resolution from 8 to 4 + map.zoomTo(3); + t.eq(parseInt(layer.backBuffer.firstChild.style.width) / parseInt(layer.div.lastChild.style.width), 1, + '[8->4] back buffer not scaled'); + removeBackBuffer(); + + // change resolution from 8 to 2 + map.zoomTo(2); removeBackBuffer(); map.zoomTo(4); + t.eq(parseInt(layer.backBuffer.firstChild.style.width) / parseInt(layer.div.lastChild.style.width), 1, + '[8->2] back buffer not scaled'); + removeBackBuffer(); + + // change resolution from 16 to 4 + map.zoomTo(1); removeBackBuffer(); map.zoomTo(3); + t.eq(parseInt(layer.backBuffer.firstChild.style.width) / parseInt(layer.div.lastChild.style.width), 2, + '[16->4] back buffer width is as expected'); + t.eq(parseInt(layer.backBuffer.firstChild.style.height) / parseInt(layer.div.lastChild.style.height), 2, + '[16->4] back buffer height is as expected'); + removeBackBuffer(); + + // change resolution from 32 to 1 + map.zoomTo(0); removeBackBuffer(); map.zoomTo(5); + t.eq(parseInt(layer.backBuffer.firstChild.style.width) / parseInt(layer.div.lastChild.style.width), 4, + '[32->1] back buffer width is as expected'); + t.eq(parseInt(layer.backBuffer.firstChild.style.height) / parseInt(layer.div.lastChild.style.height), 4, + '[32->1] back buffer height is as expected'); + removeBackBuffer(); + + // change resolution from 4 to 2 + map.zoomTo(3); removeBackBuffer(); map.zoomTo(4); + t.eq(parseInt(layer.backBuffer.firstChild.style.width) / parseInt(layer.div.lastChild.style.width), 1, + '[4->2] back buffer not scaled'); + removeBackBuffer(); + + // change resolution from 4 to 1 + map.zoomTo(3); removeBackBuffer(); map.zoomTo(5); + t.eq(parseInt(layer.backBuffer.firstChild.style.width) / parseInt(layer.div.lastChild.style.width), 1, + '[4->1] back buffer not scaled'); + removeBackBuffer(); + + // change resolution from 1 to 4 + map.zoomTo(5); removeBackBuffer(); map.zoomTo(3); + t.eq(parseInt(layer.backBuffer.firstChild.style.width) / parseInt(layer.div.lastChild.style.width), 1, + '[1->4] back buffer not scaled'); + removeBackBuffer(); + + // change resolution from 4 to 8 + map.zoomTo(3); removeBackBuffer(); map.zoomTo(2); + t.eq(parseInt(layer.backBuffer.firstChild.style.width) / parseInt(layer.div.lastChild.style.width), 1, + '[4->8] back buffer not scaled'); + removeBackBuffer(); + + // change resolution from 4 to 16 + map.zoomTo(3); removeBackBuffer(); map.zoomTo(1); + t.eq(parseInt(layer.backBuffer.firstChild.style.width) / parseInt(layer.div.lastChild.style.width), 0.5, + '[4->16] back buffer width is as expected'); + t.eq(parseInt(layer.backBuffer.firstChild.style.height) / parseInt(layer.div.lastChild.style.height), 0.5, + '[4->16] back buffer height is as expected'); + removeBackBuffer(); + + // + // tear down + // + + map.destroy(); + OpenLayers.Tile.Image.prototype.createBackBuffer = origCreateBackBuffer + } + + + function test_delayed_back_buffer_removal(t) { + // + // Test that the delaying of the back buffer removal behaves + // as expected. + // + + t.plan(5); + + // set up + + var map = new OpenLayers.Map('map', { + resolutions: [32, 16, 8, 4, 2, 1], + zoomMethod: null + }); + var layer = new OpenLayers.Layer.WMS('', '', {}, { + isBaseLayer: true, + transitionEffect: 'resize' + }); + map.addLayer(layer); + map.setCenter(new OpenLayers.LonLat(0, 0), 0); + + map.zoomTo(1); + + t.ok(layer.backBuffer === map.layerContainerDiv.firstChild, + '[a] back buffer is first child of layer container div'); + + // Mark one tile loaded and add an element to the backbuffer, to see if + // backbuffer removal gets scheduled. + layer.backBuffer.appendChild(document.createElement('img')); + layer.grid[1][1].onImageLoad(); + + t.ok(layer.backBufferTimerId !== null, + '[a] back buffer scheduled for removal'); + + var backBuffer = layer.backBuffer; + + map.zoomTo(2); + + t.ok(layer.backBuffer !== backBuffer, + '[b] a new back buffer was created'); + t.ok(layer.backBuffer === map.layerContainerDiv.firstChild, + '[b] back buffer is first child of layer container div'); + t.ok(layer.backBufferTimerId === null, + '[b] back buffer no longer scheduled for removal'); + + // tear down + + map.destroy(); + } + + function test_getGridData(t) { + t.plan(12); + + var layer = new OpenLayers.Layer.Grid(null, null, null, { + isBaseLayer: true, getURL: function() { + return "/bogus/path/to/tile"; + } + }); + var map = new OpenLayers.Map({ + div: "map", + layers: [layer], + controls: [], + center: [0, 0], + zoom: 1 + }); + + // get tile data for [0, 0] + var data = layer.getTileData({lon: 0, lat: 0}); + t.ok(data && data.tile, "[0, 0]: got tile data"); + t.eq(data.i, 0, "[0, 0]: i"); + t.eq(data.j, 128, "[0, 0]: j"); + t.ok( + data.tile.bounds.equals({left: 0, bottom: -90, right: 180, top: 90}), + "[0, 0]: tile bounds " + data.tile.bounds.toString() + ); + + // get tile data for [-110, 45] + data = layer.getTileData({lon: -110, lat: 45}); + t.ok(data && data.tile, "[-110, 45]: got tile data"); + t.eq(data.i, 99, "[-110, 45]: i"); + t.eq(data.j, 64, "[-110, 45]: j"); + t.ok( + data.tile.bounds.equals({left: -180, bottom: -90, right: 0, top: 90}), + "[-110, 45]: tile bounds " + data.tile.bounds.toString() + ); + + // get tile data for [0, 300] (north of grid) + data = layer.getTileData({lon: 0, lat: 300}) + t.eq(data, null, "[0, 300]: north of grid"); + + // get tile data for [400, 0] (east of grid) + data = layer.getTileData({lon: 400, lat: 0}) + t.eq(data, null, "[400, 0]: east of grid"); + + // get tile data for [0, -500] (south of grid) + data = layer.getTileData({lon: 0, lat: -500}) + t.eq(data, null, "[0, -500]: south of grid"); + + // get tile data for [-200, 0] (west of grid) + data = layer.getTileData({lon: -200, lat: 0}) + t.eq(data, null, "[-200, 0]: west of grid"); + + map.destroy(); + + } + + function test_getGridData_wrapped(t) { + t.plan(18); + + var layer = new OpenLayers.Layer.Grid(null, null, null, { + isBaseLayer: true, getURL: function() { + return "/bogus/path/to/tile"; + }, + wrapDateLine: true + }); + var map = new OpenLayers.Map({ + div: "map", + layers: [layer], + controls: [], + center: [-50, 0], + zoom: 1 + }); + + // get tile data for [0, 0] + var data = layer.getTileData({lon: 0, lat: 0}); + t.ok(data && data.tile, "[0, 0]: got tile data"); + t.eq(data.i, 0, "[0, 0]: i"); + t.eq(data.j, 128, "[0, 0]: j"); + t.ok( + data.tile.bounds.equals({left: 0, bottom: -90, right: 180, top: 90}), + "[0, 0]: tile bounds " + data.tile.bounds.toString() + ); + + // get tile data for [-110, 45] + data = layer.getTileData({lon: -110, lat: 45}); + t.ok(data && data.tile, "[-110, 45]: got tile data"); + t.eq(data.i, 99, "[-110, 45]: i"); + t.eq(data.j, 64, "[-110, 45]: j"); + t.ok( + data.tile.bounds.equals({left: -180, bottom: -90, right: 0, top: 90}), + "[-110, 45]: tile bounds " + data.tile.bounds.toString() + ); + + // get tile data for [0, 300] (north of grid) + data = layer.getTileData({lon: 0, lat: 300}) + t.eq(data, null, "[0, 300]: north of grid"); + + // get tile data for [400, 0] (equivalent to [40, 0] and visible on map) + data = layer.getTileData({lon: 400, lat: 0}) + t.ok(data && data.tile, "[400, 0]: got tile data"); + t.eq(data.i, 56, "[400, 0]: i"); + t.eq(data.j, 128, "[400, 0]: j"); + t.ok( + data.tile.bounds.equals({left: 0, bottom: -90, right: 180, top: 90}), + "[400, 0]: tile bounds " + data.tile.bounds.toString() + ); + + // get tile data for [0, -500] (south of grid) + data = layer.getTileData({lon: 0, lat: -500}) + t.eq(data, null, "[0, -500]: south of grid"); + + // get tile data for [-200, 0] (equivalent to [160, 0] and wrapped to west side map) + data = layer.getTileData({lon: -200, lat: 0}) + t.ok(data && data.tile, "[-200, 0]: got tile data"); + t.eq(data.i, 227, "[-200, 0]: i"); + t.eq(data.j, 128, "[-200, 0]: j"); + t.ok( + data.tile.bounds.equals({left: 0, bottom: -90, right: 180, top: 90}), + "[-200, 0]: tile bounds " + data.tile.bounds.toString() + ); + + map.destroy(); + + } + + function test_removeExcessTiles(t) { + t.plan(15); + + /* + * Set up + */ + + var map = new OpenLayers.Map('map'); + var layer = new OpenLayers.Layer.Grid('name', '/url', + {}, {isBaseLayer: true}); + map.addLayer(layer); + + function newTile(id) { + var t = new OpenLayers.Tile(layer, + new OpenLayers.Pixel(1, 1), + new OpenLayers.Bounds(1, 1, 1, 1)); + t._id = id; + return t; + } + + layer.grid = [ + [newTile(1), newTile(2), newTile(3)], + [newTile(4), newTile(5)], + [newTile(6), newTile(7), newTile(8)] + ]; + + // create a clone to be able to test whether + // tiles have been destroyed or not + var grid = [ + layer.grid[0].slice(), + layer.grid[1].slice(), + layer.grid[2].slice() + ]; + + /* + * Test + */ + + layer.removeExcessTiles(2, 2); + + t.eq(layer.grid.length, 2, 'grid has two rows'); + t.eq(layer.grid[0].length, 2, 'row #1 has two columns'); + t.eq(layer.grid[0][0]._id, 1, 'row #1 col #1 includes expected tile'); + t.eq(layer.grid[0][1]._id, 2, 'row #1 col #2 includes expected tile'); + t.eq(layer.grid[1].length, 2, 'row #2 has two columns'); + t.eq(layer.grid[1][0]._id, 4, 'row #2 col #1 includes expected tile'); + t.eq(layer.grid[1][1]._id, 5, 'row #2 col #2 includes expected tile'); + + t.ok(grid[0][0].events != null, 'tile 0,0 not destroyed'); + t.ok(grid[0][1].events != null, 'tile 0,1 not destroyed'); + t.ok(grid[0][2].events == null, 'tile 0,2 destroyed'); + t.ok(grid[1][0].events != null, 'tile 1,0 not destroyed'); + t.ok(grid[1][1].events != null, 'tile 1,1 not destroyed'); + t.ok(grid[2][0].events == null, 'tile 2,0 destroyed'); + t.ok(grid[2][1].events == null, 'tile 2,1 destroyed'); + t.ok(grid[2][2].events == null, 'tile 2,2 destroyed'); + + /* + * Tear down + */ + + map.destroy(); + } + + function test_addOptions(t) { + t.plan(15); + var map = new OpenLayers.Map('map'); + layer = new OpenLayers.Layer.WMS(name, url, params, {buffer:2}); + map.addLayer(layer); + t.eq(layer.tileSize, map.getTileSize(), "layer's tile size is equal to the map's tile size"); + t.ok(layer.removeBackBufferDelay !== 0, "removeBackBufferDelay should not be 0 since we are not singleTile"); + t.eq(layer.className, "olLayerGrid", "className correct for gridded mode"); + map.setCenter(new OpenLayers.LonLat(0,0),5); + t.eq(layer.grid.length, 8, "Grid rows is correct."); + t.eq(layer.grid[0].length, 7, "Grid cols is correct."); + t.eq(layer.singleTile, false, "singleTile is false by default"); + layer.addOptions({singleTile: true}); + t.eq(layer.removeBackBufferDelay, 0, "removeBackBufferDelay set to 0 since singleTile is true"); + t.eq(layer.singleTile, true, "singleTile set to true"); + t.eq(layer.className, "olLayerGridSingleTile", "className correct for singleTile mode"); + t.eq(layer.grid.length, 1, "Grid rows is correct."); + t.eq(layer.grid[0].length, 1, "Grid cols is correct."); + t.eq(layer.tileSize, new OpenLayers.Size(748, 823), "tile size changed"); + layer.addOptions({singleTile: false}); + t.eq(layer.grid.length, 8, "Grid rows is correct."); + t.eq(layer.grid[0].length, 7, "Grid cols is correct."); + t.eq(layer.tileSize, map.getTileSize(), "layer's tile size is equal to the map's tile size"); + map.destroy(); + } + + </script> +</head> +<body> +<div id="map" style="width:499px;height:549px;display:none"></div> +<div id="map2" style="width:500px;height:550px;display:none"></div> +<div id="map3" style="width:594px;height:464px;display:none"></div> +<div id="map4" style="width:768px;height:512px;display:none"></div> +</body> +</html> |