diff options
Diffstat (limited to 'misc/openlayers/tests/Control')
44 files changed, 9275 insertions, 0 deletions
diff --git a/misc/openlayers/tests/Control/ArgParser.html b/misc/openlayers/tests/Control/ArgParser.html new file mode 100644 index 0000000..34e9f5b --- /dev/null +++ b/misc/openlayers/tests/Control/ArgParser.html @@ -0,0 +1,26 @@ +<html> +<head> + <script src="../OLLoader.js"></script> + <script type="text/javascript"> + function test_getParameters(t) { + t.plan(4); + + var c = new OpenLayers.Control.ArgParser(), p; + + p = c.getParameters('http://example.com?fook=foov&bark=barv'); + t.eq(p, {fook: 'foov', bark: 'barv'}, 'a) params are correct'); + + p = c.getParameters('http://example.com#fook=foov&bark=barv'); + t.eq(p, {fook: 'foov', bark: 'barv'}, 'b) params are correct'); + + p = c.getParameters('http://example.com?a=b&b=c#fook=foov&bark=barv'); + t.eq(p, {a: 'b', b: 'c', fook: 'foov', bark: 'barv'}, + 'c) params are correct'); + + p = c.getParameters('http://example.com?a=b&b=c&fook=a&bark=b#fook=foov&bark=barv'); + t.eq(p, {a: 'b', b: 'c', fook: 'foov', bark: 'barv'}, + 'd) params are correct'); + } + </script> +</head> +</html> diff --git a/misc/openlayers/tests/Control/Attribution.html b/misc/openlayers/tests/Control/Attribution.html new file mode 100644 index 0000000..04b85cf --- /dev/null +++ b/misc/openlayers/tests/Control/Attribution.html @@ -0,0 +1,60 @@ +<html> +<head> + <script src="../OLLoader.js"></script> + <script type="text/javascript"> + var map; + function test_Control_Attribution_constructor (t) { + t.plan( 2 ); + + control = new OpenLayers.Control.Attribution(); + t.ok( control instanceof OpenLayers.Control.Attribution, "new OpenLayers.Control returns object" ); + t.eq( control.displayClass, "olControlAttribution", "displayClass is correct" ); + } + function test_Control_Attribution_setBaseLayer (t) { + t.plan(1); + map = new OpenLayers.Map("map"); + map.addControl(control); + map.addLayer(new OpenLayers.Layer("name",{'attribution':'My layer!', isBaseLayer: true})); + map.addLayer(new OpenLayers.Layer("name",{'attribution':'My layer 2!', isBaseLayer: true})); + map.setBaseLayer(map.layers[1]); + t.eq(control.div.innerHTML, 'My layer 2!', "Attribution correct with changed base layer"); + + } + function test_Control_Attribution_draw (t) { + t.plan(3); + control = new OpenLayers.Control.Attribution(); + map = new OpenLayers.Map("map"); + map.addControl(control); + map.addLayer(new OpenLayers.Layer("name",{'attribution':'My layer!'})); + t.eq(control.div.innerHTML, 'My layer!', "Attribution correct with one layer."); + map.addLayer(new OpenLayers.Layer("name", {'attribution':'My layer 2!'})); + t.eq(control.div.innerHTML, 'My layer!, My layer 2!', "Attribution correct with two layers."); + control.separator = '|'; + control.template = "Map Copyright (c) 2012 by Foo Bar; ${layers}"; + map.addLayer(new OpenLayers.Layer("name",{'attribution':'My layer 3!'})); + t.eq(control.div.innerHTML, 'Map Copyright (c) 2012 by Foo Bar; My layer!|My layer 2!|My layer 3!', "Attribution correct with three layers and diff seperator."); + + + } + + function test_Control_Attribution_no_duplicates(t) { + t.plan(2); + + map = new OpenLayers.Map("map"); + map.addLayer(new OpenLayers.Layer("Company A: 1",{'attribution':'company A'})); + map.addLayer(new OpenLayers.Layer("Company A: 2",{'attribution':'company A'})); + + control = new OpenLayers.Control.Attribution(); + map.addControl(control); + t.eq(control.div.innerHTML, 'company A', "Attribution not duplicated."); + + map.addLayer(new OpenLayers.Layer("Company B: 1",{'attribution':'company B'})); + map.addLayer(new OpenLayers.Layer("Company A: 3",{'attribution':'company A'})); + t.eq(control.div.innerHTML, 'company A, company B', "Attribution correct with four layers (3 with same attribution)."); + } + </script> +</head> +<body> + <div id="map" style="width: 1024px; height: 512px;"/> +</body> +</html> diff --git a/misc/openlayers/tests/Control/Button.html b/misc/openlayers/tests/Control/Button.html new file mode 100644 index 0000000..8d5c036 --- /dev/null +++ b/misc/openlayers/tests/Control/Button.html @@ -0,0 +1,17 @@ +<html> +<head> + <script src="../OLLoader.js"></script> + <script type="text/javascript"> + function test_Control_Button_constructor (t) { + t.plan( 2 ); + + control = new OpenLayers.Control.Button(); + t.ok( control instanceof OpenLayers.Control.Button, "new OpenLayers.Control returns object" ); + t.eq( control.displayClass, "olControlButton", "displayClass is correct" ); + } + + </script> +</head> +<body> +</body> +</html> diff --git a/misc/openlayers/tests/Control/CacheRead.html b/misc/openlayers/tests/Control/CacheRead.html new file mode 100644 index 0000000..ae0addf --- /dev/null +++ b/misc/openlayers/tests/Control/CacheRead.html @@ -0,0 +1,108 @@ +<html> +<head> + <script> + /** + * Because browsers that implement requestAnimationFrame may not execute + * animation functions while a window is not displayed (e.g. in a hidden + * iframe as in these tests), we mask the native implementations here. The + * native requestAnimationFrame functionality is tested in Util.html and + * in PanZoom.html (where a popup is opened before panning). The tests + * here will test the fallback setTimeout implementation for animation. + */ + window.requestAnimationFrame = + window.webkitRequestAnimationFrame = + window.mozRequestAnimationFrame = + window.oRequestAnimationFrame = + window.msRequestAnimationFrame = null; + </script> + <script src="../OLLoader.js"></script> + <script type="text/javascript"> + function test_addLayer_removeLayer(t) { + t.plan(6); + var control = new OpenLayers.Control.CacheRead(); + var map = new OpenLayers.Map({ + div: "map", + controls: [control], + layers: [ + new OpenLayers.Layer.WMS("One"), + new OpenLayers.Layer.WMS("Two") + ] + }); + t.ok(map.layers[0].events.listeners.tileloadstart, "tileloadstart listener registered on layer One"); + t.ok(map.layers[1].events.listeners.tileloadstart, "tileloadstart listener registered on layer Two"); + control.destroy(); + t.ok(!map.layers[1].events.listeners.tileloadstart.length, "tileloadstart listener unregistered"); + + control = new OpenLayers.Control.CacheRead({ + fetchEvent: "tileerror", + layers: [map.layers[0]] + }); + map.addControl(control); + t.ok(map.layers[0].events.listeners.tileerror, "tileerror listener registered on layer One"); + t.ok(!map.layers[1].events.listeners.tileerror, "tileerror listener not registered on layer Two"); + control.destroy(); + t.ok(!map.layers[0].events.listeners.tileerror.length, "tileerror listener unregistered"); + + map.destroy(); + } + + function test_fetch(t) { + + if (!window.localStorage) { + t.plan(1); + var scope = {active: true}; + t.eq(OpenLayers.Control.CacheRead.prototype.fetch.call(scope), undefined, "no tiles fetched when localStorage is not supported."); + return; + } + + t.plan(5); + + var data = "data:image/gif;base64,R0lGODlhAQABAIAAAP7//wAAACH5BAAAAAAALAAAAAABAAEAAAICRAEAOw=="; + window.localStorage.setItem("olCache_foo/1/1/1", data); + window.localStorage.setItem("olCache_bar/1/1/1", data); + + var layer1 = new OpenLayers.Layer.XYZ("One", "foo/${x}/${y}/${z}"); + var layer2 = new OpenLayers.Layer.XYZ("Two", "bar/${x}/${y}/${z}", {isBaseLayer: false}); + var control1 = new OpenLayers.Control.CacheRead({ + layers: [layer1] + }); + var control2 = new OpenLayers.Control.CacheRead({ + layers: [layer2], + fetchEvent: "tileerror" + }); + + var map = new OpenLayers.Map({ + div: "map", + projection: "EPSG:900913", + controls: [control1, control2], + layers: [layer1, layer2], + zoom: 1, + center: [0, 0] + }); + + OpenLayers.ProxyHost = "proxy?url="; + var tile = new OpenLayers.Tile.Image(layer1, new OpenLayers.LonLat(0, 0), new OpenLayers.Bounds(0, 0, 1, 1), "proxy?url=foo/1/1/1"); + OpenLayers.Control.CacheWrite.urlMap[tile.url] = "foo/1/1/1"; + + control1.fetch({tile: tile}); + t.eq(tile.url, data, "proxied url replaced with data uri for original url"); + delete OpenLayers.Control.CacheWrite.urlMap[tile.url]; + + t.delay_call(1, function() { + t.eq(layer1.grid[1][1].imgDiv.src, data, "[tileloadstart] tile content from cache"); + t.ok(layer1.grid[0][0].imgDiv.src !== data, "[tileloadstart] tile content from remote resource"); + t.eq(layer2.grid[1][1].imgDiv.src, data, "[tileerror] tile content from cache"); + t.ok(layer2.grid[0][0].imgDiv.src !== data, "[tileerror] tile content from remote resource"); + + window.localStorage.removeItem("olCache_foo/1/1/1"); + window.localStorage.removeItem("olCache_bar/1/1/1"); + map.destroy(); + }); + } + + </script> +</head> +<body> + <div id="map" style="width: 400px; height: 250px;"/> +</body> +</html> diff --git a/misc/openlayers/tests/Control/CacheWrite.html b/misc/openlayers/tests/Control/CacheWrite.html new file mode 100644 index 0000000..9922569 --- /dev/null +++ b/misc/openlayers/tests/Control/CacheWrite.html @@ -0,0 +1,90 @@ +<html> +<head> + <script src="../OLLoader.js"></script> + <script type="text/javascript"> + function test_addLayer_removeLayer(t) { + t.plan(6); + var control = new OpenLayers.Control.CacheWrite(); + var map = new OpenLayers.Map({ + div: "map", + controls: [control], + layers: [ + new OpenLayers.Layer.WMS("One"), + new OpenLayers.Layer.WMS("Two") + ] + }); + t.ok(map.layers[0].events.listeners.tileloaded, "tileloaded listener registered on layer One"); + t.ok(map.layers[1].events.listeners.tileloaded, "tileloaded listener registered on layer Two"); + control.destroy(); + t.ok(!map.layers[1].events.listeners.tileloaded.length, "tileloaded listener unregistered"); + + control = new OpenLayers.Control.CacheWrite({ + layers: [map.layers[0]] + }); + map.addControl(control); + t.ok(map.layers[0].events.listeners.tileloaded.length, "tileloaded listener registered on layer One"); + t.ok(!map.layers[1].events.listeners.tileloaded.length, "tileloaded listener not registered on layer Two"); + control.destroy(); + t.ok(!map.layers[0].events.listeners.tileloaded.length, "tileloaded listener unregistered"); + + map.destroy(); + } + + function test_cache_clearCache(t) { + + if (!window.localStorage) { + t.plan(2); + var scope = {active: true}; + t.eq(OpenLayers.Control.CacheWrite.prototype.cache.call(scope), undefined, "no tiles cached when localStorage is not supported."); + t.ok(!OpenLayers.Control.CacheWrite.clearCache(), "clearCache does nothing when localStorage is not supported."); + return; + } + + t.plan(4); + OpenLayers.Control.CacheWrite.clearCache(); + var length = window.localStorage.length; + + var tiles = 0; + var layer = new OpenLayers.Layer.XYZ("One", "../../img/blank.gif?${x},${y},${z}", { + eventListeners: { + tileloaded: function() { + tiles++; + } + } + }); + var control = new OpenLayers.Control.CacheWrite({autoActivate: true}); + var map = new OpenLayers.Map({ + div: "map", + projection: "EPSG:900913", + controls: [control], + layers: [layer], + zoom: 1, + center: [0, 0] + }); + t.delay_call(1, function() { + var canvasContext = layer.grid[1][1].getCanvasContext(); + t.eq(window.localStorage.length, length + (canvasContext ? tiles : 0), "cache filled with tiles"); + var url = layer.grid[1][1].url; + // content will be null for browsers that have localStorage but no canvas support + var content = canvasContext ? canvasContext.canvas.toDataURL("image/png") : null; + t.eq(window.localStorage.getItem("olCache_"+url), content, "localStorage contains correct image data"); + + layer.events.triggerEvent('tileloaded', {aborted: true, tile: layer.grid[1][1]}); + t.eq(window.localStorage.length, length + (canvasContext ? tiles-1 : 0), "tile aborted during load not cached"); + + var key = Math.random(); + window.localStorage.setItem(key, "bar"); + OpenLayers.Control.CacheWrite.clearCache(); + t.eq(window.localStorage.length, length + 1, "cache cleared, but foreign entries left in localStorage"); + window.localStorage.removeItem(key); + + map.destroy(); + }); + } + + </script> +</head> +<body> + <div id="map" style="width: 400px; height: 250px;"/> +</body> +</html> diff --git a/misc/openlayers/tests/Control/DragFeature.html b/misc/openlayers/tests/Control/DragFeature.html new file mode 100644 index 0000000..cfc3a63 --- /dev/null +++ b/misc/openlayers/tests/Control/DragFeature.html @@ -0,0 +1,383 @@ +<html> +<head> + <script src="../OLLoader.js"></script> + <script type="text/javascript"> + function test_Control_DragFeature_constructor(t) { + t.plan(3); + + var options = { + geometryTypes: "foo" + }; + var layer = "bar"; + var control = new OpenLayers.Control.DragFeature(layer, options); + t.ok(control instanceof OpenLayers.Control.DragFeature, + "new OpenLayers.Control.DragFeature returns an instance"); + t.eq(control.layer, "bar", + "constructor sets layer correctly"); + t.eq(control.handlers.feature.geometryTypes, "foo", + "constructor sets options correctly on feature handler"); + } + + function test_Control_DragFeature_destroy(t) { + t.plan(2); + var map = new OpenLayers.Map("map"); + var layer = new OpenLayers.Layer.Vector(); + map.addLayer(layer); + var control = new OpenLayers.Control.DragFeature(layer); + control.handlers.drag.destroy = function() { + t.ok(true, + "control.destroy calls destroy on drag handler"); + } + control.handlers.feature.destroy = function() { + t.ok(true, + "control.destroy calls destroy on feature handler"); + } + + control.destroy(); + + } + + function test_Control_DragFeature_activate(t) { + t.plan(2); + var map = new OpenLayers.Map("map"); + var layer = new OpenLayers.Layer.Vector(); + map.addLayer(layer); + var control = new OpenLayers.Control.DragFeature(layer); + map.addControl(control); + t.ok(!control.handlers.feature.active, + "feature handler is not active prior to activating control"); + control.activate(); + t.ok(control.handlers.feature.active, + "feature handler is active after activating control"); + } + + function test_Control_DragFeature_deactivate(t) { + t.plan(2); + var map = new OpenLayers.Map("map"); + var layer = new OpenLayers.Layer.Vector(); + map.addLayer(layer); + var control = new OpenLayers.Control.DragFeature(layer); + map.addControl(control); + + control.handlers.drag.deactivate = function() { + t.ok(true, + "control.deactivate calls deactivate on drag handler"); + } + control.handlers.feature.deactivate = function() { + t.ok(true, + "control.deactivate calls deactivate on feature handler"); + } + control.deactivate(); + } + + function test_Control_DragFeature_over(t) { + t.plan(5); + var log = []; + var map = new OpenLayers.Map("map"); + var layer = new OpenLayers.Layer.Vector(); + map.addLayer(layer); + var control = new OpenLayers.Control.DragFeature(layer, { + onEnter: function(f) { log.push({feature: f}); } + }); + map.addControl(control); + + control.activate(); + t.ok(!control.handlers.drag.active, + "drag handler is not active before over a feature"); + + // simulate a mouseover on a feature + var feature = new OpenLayers.Feature.Vector(); + feature.layer = layer; + layer.getFeatureFromEvent = function(evt) { + return feature; + } + map.events.triggerEvent("mousemove", {type: "mousemove"}); + + t.eq(control.feature.id, feature.id, + "control gets the proper feature from the feature handler"); + t.ok(control.handlers.drag.active, + "drag handler activated when over a feature"); + t.eq(log.length, 1, + "onEnter called exactly once"); + t.eq(log[0].feature.id, feature.id, + "onEnter called with expected feature"); + } + + function test_Control_DragFeature_over_touch(t) { + t.plan(7); + var log = []; + var map = new OpenLayers.Map("map"); + var layer = new OpenLayers.Layer.Vector(); + map.addLayer(layer); + var control = new OpenLayers.Control.DragFeature(layer, { + onEnter: function(f) { log.push({feature: f}); } + }); + map.addControl(control); + + control.activate(); + t.ok(!control.handlers.drag.active, + "drag handler is not active before touch on a feature"); + + // simulate a touch on a feature + var feature = new OpenLayers.Feature.Vector(); + feature.layer = layer; + layer.getFeatureFromEvent = function(evt) { + return feature; + } + map.events.triggerEvent("touchstart", {type: "touchstart", touches: ['foo']}); + + t.eq(control.feature.id, feature.id, + "control gets the proper feature from the feature handler"); + t.ok(control.handlers.drag.active, + "drag handler activated when touch on a feature"); + t.ok(control.handlers.drag.started, "drag handler has started"); + t.ok(!control.handlers.drag.stopDown, "drag handler is not stopping down"); + t.eq(log.length, 1, + "onEnter called exactly once"); + t.eq(log[0].feature.id, feature.id, + "onEnter called with expected feature"); + } + + function test_Control_DragFeature_down(t) { + t.plan(3); + var map = new OpenLayers.Map("map"); + var layer = new OpenLayers.Layer.Vector(); + map.addLayer(layer); + var control = new OpenLayers.Control.DragFeature(layer); + map.addControl(control); + + control.activate(); + + // simulate a mouseover on a feature + var feature = new OpenLayers.Feature.Vector(); + feature.layer = layer; + layer.getFeatureFromEvent = function(evt) { + return feature; + } + map.events.triggerEvent("mousemove", {type: "mousemove"}); + + // simulate a mousedown on a feature + control.onStart = function(feat, pixel) { + t.eq(feat.id, feature.id, "onStart called with the correct feature"); + t.eq(pixel, "bar", "onStart called with the correct pixel"); + } + map.events.triggerEvent("mousedown", {xy: "bar", which: 1, type: "mousemove"}); + + t.eq(control.lastPixel, "bar", + "mousedown sets the lastPixel correctly"); + } + + function test_Control_DragFeature_move(t) { + t.plan(3); + var map = new OpenLayers.Map("map"); + var layer = new OpenLayers.Layer.Vector(); + map.addLayer(layer); + var control = new OpenLayers.Control.DragFeature(layer); + map.addControl(control); + map.getResolution = function() { + return 2; + } + + control.activate(); + + // mock up a feature - for the sole purpose of testing mousemove + var uid = Math.random(); + layer.getFeatureFromEvent = function() { + var geom = new OpenLayers.Geometry.Point(Math.random(), + Math.random()); + geom.move = function(x, y) { + t.eq(x, 2, "move called with dx * res"); + t.eq(y, -4, "move called with -dy * res"); + }; + var feature = new OpenLayers.Feature.Vector(geom); + feature.layer = layer; + feature.uid = uid; + return feature; + }; + layer.drawFeature = function(feature) { + t.eq(feature.uid, uid, + "layer.drawFeature called with correct feature"); + }; + + // simulate a mouseover on a feature + map.events.triggerEvent("mousemove", {type: "mousemove"}); + + // simulate a mousedown on a feature + var down = new OpenLayers.Pixel(0, 0); + map.events.triggerEvent("mousedown", {xy: down, which: 1, type: "mousemove"}); + + // simulate a mousemove on a feature + var move = new OpenLayers.Pixel(1, 2); + map.events.triggerEvent("mousemove", {xy: move, which: 1, type: "mousemove"}); + + } + + function test_Control_DragFeature_up(t) { + t.plan(6); + var map = new OpenLayers.Map("map"); + var layer = new OpenLayers.Layer.Vector(); + map.addLayer(layer); + var control = new OpenLayers.Control.DragFeature(layer); + map.addControl(control); + + control.activate(); + + // simulate a mouseover on a feature + var feature = new OpenLayers.Feature.Vector(); + feature.layer = layer; + layer.getFeatureFromEvent = function(evt) { + return feature; + } + map.events.triggerEvent("mousemove", {type: "mousemove"}); + t.eq(control.over, true, + "mouseover on a feature sets the over property to true"); + t.ok(OpenLayers.Element.hasClass(control.map.viewPortDiv, "olControlDragFeatureOver"), + "mouseover on a feature adds class name to map container"); + t.eq(control.handlers.drag.active, true, + "mouseover on a feature activates drag handler"); + + // simulate a mouse-up on the map, with the mouse still + // over the dragged feature + control.handlers.drag.started = true; + map.events.triggerEvent("mouseup", {type: "mouseup"}); + t.eq(control.handlers.drag.active, true, + "mouseup while still over dragged feature does not deactivate drag handler"); + + // simulate a mouse-up on the map, with the mouse out of + // the dragged feature + control.handlers.drag.started = true; + control.over = false; + map.events.triggerEvent("mouseup", {type: "mouseup"}); + t.eq(control.handlers.drag.active, false, + "mouseup deactivates drag handler"); + + control.deactivate(); + t.ok(!OpenLayers.Element.hasClass(control.map.viewPortDiv, "olControlDragFeatureOver"), + "deactivate removes class name from map container"); + } + + function test_Control_DragFeature_done(t) { + t.plan(2); + var map = new OpenLayers.Map("map"); + var layer = new OpenLayers.Layer.Vector(); + map.addLayer(layer); + var control = new OpenLayers.Control.DragFeature(layer); + map.addControl(control); + + control.activate(); + + + // simulate a mouseover on a feature + var feature = new OpenLayers.Feature.Vector(); + feature.layer = layer; + layer.getFeatureFromEvent = function() { + return feature; + }; + map.events.triggerEvent("mousemove", {type: "mousemove"}); + t.eq(control.feature.id, feature.id, + "feature is set on mouse over"); + control.doneDragging(); + t.eq(control.feature.id, feature.id, + "feature sticks around after doneDragging is called."); + + } + + function test_Control_DragFeature_out(t) { + t.plan(4); + var log = []; + var map = new OpenLayers.Map("map"); + var layer = new OpenLayers.Layer.Vector(); + map.addLayer(layer); + var control = new OpenLayers.Control.DragFeature(layer, { + onLeave: function(f) { log.push({feature: f}); } + }); + map.addControl(control); + + control.activate(); + + + // simulate a mouseover on a feature + var feature = new OpenLayers.Feature.Vector(); + feature.layer = layer; + layer.getFeatureFromEvent = function() { + return feature; + }; + map.events.triggerEvent("mousemove", {type: "mousemove"}); + t.eq(control.feature.id, feature.id, + "feature is set on mouse over"); + + // simulate a mouseout on a feature + layer.getFeatureFromEvent = function() { + return null; + }; + map.events.triggerEvent("mousemove", {type: "mousemove"}); + t.ok(control.feature == null, + "feature is set to null on mouse out"); + t.eq(log.length, 1, + "onLeave called exactly once"); + t.eq(log[0].feature.id, feature.id, + "onLeave called with expected feature"); + } + + function test_Control_DragFeature_out_touch(t) { + t.plan(5); + var log = []; + var map = new OpenLayers.Map("map"); + var layer = new OpenLayers.Layer.Vector(); + map.addLayer(layer); + var control = new OpenLayers.Control.DragFeature(layer, { + onLeave: function(f) { log.push({feature: f}); } + }); + map.addControl(control); + + control.activate(); + + // simulate a touch on a feature + var feature = new OpenLayers.Feature.Vector(); + feature.layer = layer; + layer.getFeatureFromEvent = function() { + return feature; + }; + map.events.triggerEvent("touchstart", {type: "touchstart", touches: ['foo']}); + t.eq(control.feature.id, feature.id, + "feature is set on mouse over"); + + // simulate a touch outside the feature + layer.getFeatureFromEvent = function() { + return null; + }; + map.events.triggerEvent("touchstart", {type: "touchstart", touches: ['foo']}); + t.ok(control.feature == null, + "feature is set to null on mouse out"); + t.ok(control.handlers.drag.stopDown, + "drag handler is stopping down again"); + t.eq(log.length, 1, + "onLeave called exactly once"); + t.eq(log[0].feature.id, feature.id, + "onLeave called with expected feature"); + } + + function test_Control_DragFeature_click(t) { + t.plan(1); + var map = new OpenLayers.Map("map"); + var layer = new OpenLayers.Layer.Vector(); + map.addLayer(layer); + var feature = new OpenLayers.Feature.Vector(); + feature.layer = layer; + var control = new OpenLayers.Control.DragFeature(layer); + map.addControl(control); + + control.activate(); + + control.overFeature(feature); + control.handlers.feature.evt = {which: 1}; + control.clickFeature(feature); + t.eq(control.handlers.drag.started, false, "click after over does not start drag handler"); + } + + </script> +</head> +<body> + <div id="map" style="width: 400px; height: 250px;"/> +</body> +</html> diff --git a/misc/openlayers/tests/Control/DragPan.html b/misc/openlayers/tests/Control/DragPan.html new file mode 100644 index 0000000..ba5224f --- /dev/null +++ b/misc/openlayers/tests/Control/DragPan.html @@ -0,0 +1,104 @@ +<html> +<head> + <script src="../OLLoader.js"></script> + <script type="text/javascript"> + var map, control, layer; + + function init_map() { + control = new OpenLayers.Control.DragPan(); + map = new OpenLayers.Map("map", {controls:[control]}); + layer = new OpenLayers.Layer.WMS( "OpenLayers WMS", + "http://labs.metacarta.com/wms/vmap0", + {layers: 'basic'} ); + map.addLayer(layer); + map.zoomToMaxExtent(); + map.zoomIn(); + control.activate(); + return [map, control]; + } + function test_Control_DragPan_constructor (t) { + t.plan( 1 ); + + control = new OpenLayers.Control.DragPan(); + t.ok( control instanceof OpenLayers.Control.DragPan, "new OpenLayers.Control returns object" ); + } + function test_Control_DragPan_drag (t) { + t.plan(4); + var data = init_map(); + map = data[0]; control = data[1]; + res = map.baseLayer.resolutions[map.getZoom()]; + t.eq(map.center.lat, 0, "Lat is 0 before drag"); + t.eq(map.center.lon, 0, "Lon is 0 before drag"); + map.events.triggerEvent('mousedown', {'type':'mousedown', 'xy':new OpenLayers.Pixel(0,0), 'which':1}); + map.events.triggerEvent('mousemove', {'type':'mousemove', 'xy':new OpenLayers.Pixel(5,5), 'which':1}); + map.events.triggerEvent('mouseup', {'type':'mouseup', 'xy':new OpenLayers.Pixel(5,5), 'which':1}); + + t.eq(map.getCenter().lat, res * 5, "Lat is " + (res * 5) + " after drag"); + t.eq(map.getCenter().lon, res * -5, "Lon is " + (res * -5) + " after drag"); + } + function test_Control_DragPan_drag_documentDrag (t) { + t.plan(4); + control = new OpenLayers.Control.DragPan({documentDrag: true}); + map = new OpenLayers.Map("map", {controls:[control]}); + layer = new OpenLayers.Layer.WMS( "OpenLayers WMS", + "http://labs.metacarta.com/wms/vmap0", + {layers: 'basic'} ); + map.addLayer(layer); + map.zoomToMaxExtent(); + map.zoomIn(); + control.activate(); + + res = map.baseLayer.resolutions[map.getZoom()]; + t.eq(map.center.lat, 0, "Lat is 0 before drag"); + t.eq(map.center.lon, 0, "Lon is 0 before drag"); + map.events.triggerEvent('mousedown', {'type':'mousedown', 'xy':new OpenLayers.Pixel(0,0), 'which':1}); + map.events.triggerEvent('mousemove', {'type':'mousemove', 'xy':new OpenLayers.Pixel(5,5), 'which':1}); + map.events.triggerEvent('mouseup', {'type':'mouseup', 'xy':new OpenLayers.Pixel(5,5), 'which':1}); + + t.eq(map.getCenter().lat, res * 5, "Lat is " + (res * 5) + " after drag"); + t.eq(map.getCenter().lon, res * -5, "Lon is " + (res * -5) + " after drag"); + } + function test_Control_DragPan_click(t) { + t.plan(1); + var control = new OpenLayers.Control.DragPan(); + var map = new OpenLayers.Map("map", {controls:[control]}); + var layer = new OpenLayers.Layer.WMS("OpenLayers WMS", + "http://labs.metacarta.com/wms/vmap0", + {layers: 'basic'}); + map.addLayer(layer); + map.zoomToMaxExtent(); + map.zoomIn(); + control.activate(); + map.setCenter = function() { + t.ok(false, "map.setCenter should not be called here"); + }; + var xy = new OpenLayers.Pixel(0, 0); + var down = { + 'type': 'mousedown', + 'xy': xy, + 'which': 1 + }; + var move = { + 'type': 'mousemove', + 'xy': xy, + 'which': 1 + }; + var up = { + 'type': 'mouseup', + 'xy': xy, + 'which': 1 + }; + map.events.triggerEvent('mousedown', down); + map.events.triggerEvent('mousemove', move); + map.events.triggerEvent('mouseup', up); + t.ok(true, "clicking without moving the mouse does not call setCenter"); + } + + + </script> +</head> +<body> + <a id="scale" href="">DragPan</a> <br /> + <div id="map" style="width: 1024px; height: 512px;"/> +</body> +</html> diff --git a/misc/openlayers/tests/Control/DrawFeature.html b/misc/openlayers/tests/Control/DrawFeature.html new file mode 100644 index 0000000..ef0be5a --- /dev/null +++ b/misc/openlayers/tests/Control/DrawFeature.html @@ -0,0 +1,160 @@ +<html> +<head> + <script src="../OLLoader.js"></script> + <script type="text/javascript"> + + function test_initialize(t) { + t.plan(1); + var control = new OpenLayers.Control.DrawFeature("foo", function() {}); + t.ok(control instanceof OpenLayers.Control.DrawFeature, + "constructor returns an instance"); + } + + function test_multi(t) { + t.plan(4); + + var layer = new OpenLayers.Layer.Vector(); + var control; + + // multi false by default + control = new OpenLayers.Control.DrawFeature( + layer, OpenLayers.Handler.Polygon + ); + t.ok(!control.multi, "control.multi false by default"); + t.ok(!control.handler.multi, "handler.multi false by default"); + + // set on handler + control = new OpenLayers.Control.DrawFeature( + layer, OpenLayers.Handler.Polygon, {multi: true} + ); + t.ok(control.handler.multi, "handler.multi set from control options"); + + // respect handlerOptions + control = new OpenLayers.Control.DrawFeature( + layer, OpenLayers.Handler.Polygon, + {multi: true, handlerOptions: {multi: false}} + ); + t.ok(!control.handler.multi, "handlerOptions.multi respected"); + + } + + function test_rendererOptions(t) { + t.plan(2); + + var map = new OpenLayers.Map("map"); + var renderers = ["Canvas", "VML"]; + + var layer = new OpenLayers.Layer.Vector(null, { + renderers: renderers, + rendererOptions: {zIndexing: true}, + isBaseLayer: true + }); + map.addLayer(layer); + + var control = new OpenLayers.Control.DrawFeature( + layer, OpenLayers.Handler.Polygon, {autoActivate: true} + ); + map.addControl(control); + + var sketchLayer = control.handler.layer; + + t.eq(sketchLayer.renderers, renderers, "Preferred renderers"); + t.eq(sketchLayer.rendererOptions.zIndexing, true, "renderer options"); + + map.destroy(); + + } + + function test_drawFeature(t) { + t.plan(3); + var layer = new OpenLayers.Layer.Vector(); + var control = new OpenLayers.Control.DrawFeature(layer, function() {}); + var geom = {}; + + layer.addFeatures = function(features) { + t.ok(features[0].geometry == geom, "layer.addFeatures called"); + t.eq(features[0].state, OpenLayers.State.INSERT, "layer state set"); + }; + function handlefeatureadded(event) { + t.ok(event.feature.geometry == geom, "featureadded triggered"); + } + control.events.on({"featureadded": handlefeatureadded}); + control.drawFeature(geom); + control.events.un({"featureadded": handlefeatureadded}); + + } + + function test_sketch_events(t) { + t.plan(11); + var map = new OpenLayers.Map("map", { + resolutions: [1] + }); + var layer = new OpenLayers.Layer.Vector("foo", { + maxExtent: new OpenLayers.Bounds(-10, -10, 10, 10), + isBaseLayer: true + }); + var control = new OpenLayers.Control.DrawFeature( + layer, OpenLayers.Handler.Path, { + handlerOptions: {persist: true} + } + ); + map.addLayer(layer); + map.addControl(control); + map.zoomToMaxExtent(); + + var log; + layer.events.on({ + sketchstarted: function(event) { + log['sketchstarted'] = event; + }, + sketchmodified: function(event) { + log['sketchmodified'] = event; + }, + sketchcomplete: function(event) { + log['sketchcomplete'] = event; + } + }); + + // mock up draw/modify of a point + log = {}; + control.activate(); + t.eq(log, {}, "[activate] no event triggered"); + + log = {}; + map.events.triggerEvent("mousemove", {xy: new OpenLayers.Pixel(0, 0)}); + t.eq(log.sketchstarted.type, "sketchstarted", "[mousemove] sketchstarted triggered"); + t.geom_eq(log.sketchstarted.vertex, new OpenLayers.Geometry.Point(-200, 125), "[mousemove] correct vertex"); + t.eq(log.sketchmodified.type, "sketchmodified", "[mousemove] sketchmodified triggered"); + t.geom_eq(log.sketchmodified.vertex, new OpenLayers.Geometry.Point(-200, 125), "[mousemove] correct vertex"); + + map.events.triggerEvent("mousedown", {xy: new OpenLayers.Pixel(0, 0)}); + + log = {}; + map.events.triggerEvent("mouseup", {xy: new OpenLayers.Pixel(0, 0)}); + t.eq(log.sketchmodified.type, "sketchmodified", "[mouseup] sketchmodified triggered"); + t.geom_eq(log.sketchmodified.vertex, new OpenLayers.Geometry.Point(-200, 125), "[mouseup] correct vertex"); + + log = {}; + map.events.triggerEvent("mousemove", {xy: new OpenLayers.Pixel(10, 10)}); + t.eq(log.sketchmodified.type, "sketchmodified", "[mousemove] sketchmodified triggered"); + t.geom_eq(log.sketchmodified.vertex, new OpenLayers.Geometry.Point(-190, 115), "[mousemove] correct vertex"); + + log = {}; + map.events.triggerEvent("dblclick", {xy: new OpenLayers.Pixel(10, 10)}); + t.eq(log.sketchcomplete.type, "sketchcomplete", "[dblclick] sketchcomplete triggered"); + t.geom_eq(log.sketchcomplete.feature.geometry, + new OpenLayers.Geometry.LineString([ + new OpenLayers.Geometry.Point(-200, 125), + new OpenLayers.Geometry.Point(-190, 115) + ]), + "[dblclick] correct geometry"); + + map.destroy(); + } + + </script> +</head> +<body> + <div id="map" style="width: 400px; height: 250px;"/> +</body> +</html> diff --git a/misc/openlayers/tests/Control/EditingToolbar.html b/misc/openlayers/tests/Control/EditingToolbar.html new file mode 100644 index 0000000..570986d --- /dev/null +++ b/misc/openlayers/tests/Control/EditingToolbar.html @@ -0,0 +1,33 @@ +<html> +<head> + <script src="../OLLoader.js"></script> + <script type="text/javascript"> + function test_ctor_draw(t) { + t.plan(5); + var map = new OpenLayers.Map('map'); + var vLayer = new OpenLayers.Layer.Vector(); + map.addLayer(vLayer); + + var editingToolbar = new OpenLayers.Control.EditingToolbar(vLayer, { + citeCompliant: "foo" + }); + map.addControl(editingToolbar); + + t.ok(editingToolbar instanceof OpenLayers.Control.EditingToolbar, + "new OpenLayers.Control.EditingToolbar returns object" ); + t.ok(editingToolbar.controls[0] instanceof OpenLayers.Control.Navigation, + "EditingToolbar contains Control.Navigation object" ); + t.eq(editingToolbar.controls[0].active, true, + "First control is active" ); + t.eq(editingToolbar.controls.length, 4, + "EditingToolbar contains 4 Controls" ); + t.eq(editingToolbar.controls[1].handler.citeCompliant, "foo", "citeCompliant option passed to handler correctly") + + map.destroy(); + } + </script> +</head> +<body> + <div id="map" style="width: 1024px; height: 512px;"/> +</body> +</html> diff --git a/misc/openlayers/tests/Control/Geolocate.html b/misc/openlayers/tests/Control/Geolocate.html new file mode 100644 index 0000000..4e43f39 --- /dev/null +++ b/misc/openlayers/tests/Control/Geolocate.html @@ -0,0 +1,129 @@ +<html> +<head> + <script src="../OLLoader.js"></script> + <script type="text/javascript"> + var map, control, centerLL + watch = null, + geolocation= { + getCurrentPosition: function(f) { + f({ + coords: { latitude: 10, longitude: 10 } + }); + }, + watchPosition: function(f) { + watch = true; + }, + clearWatch: function() { + watch = null; + } + }; + + function test_initialize(t) { + t.plan(3); + control = new OpenLayers.Control.Geolocate({geolocationOptions: {foo: 'bar'}}); + t.ok(control instanceof OpenLayers.Control.Geolocate, + "new OpenLayers.Control returns object" ); + t.eq(control.displayClass, "olControlGeolocate", "displayClass is correct" ); + t.eq(control.geolocationOptions.foo, 'bar', + 'provided geolocation options are set in the geolocationOptions prop'); + } + function test_bind(t) { + t.plan(3); + var control = new OpenLayers.Control.Geolocate({ + geolocation: geolocation + }); + control.events.register('locationupdated', null, function() { + t.ok(true, 'locationupdated event is fired when bound'); + }); + map.addControl(control); + control.activate(); + var center = map.getCenter(); + t.eq(center.lon, 10, 'bound control sets the map lon'); + t.eq(center.lat, 10, 'bound control sets the map lat'); + control.deactivate(); + map.removeControl(control); + map.setCenter(centerLL); + } + function test_unbind(t) { + t.plan(3); + var control = new OpenLayers.Control.Geolocate({ + geolocation: geolocation, + bind: false + }); + control.events.register('locationupdated', null, function() { + t.ok(true, 'locationupdated event is fired when unbound'); + }); + map.addControl(control); + control.activate(); + var center = map.getCenter(); + t.eq(center.lon, 0, 'unbound control doesnt sets the map lon'); + t.eq(center.lat, 0, 'unbound control doesnt sets the map lat'); + control.deactivate(); + map.removeControl(control); + map.setCenter(centerLL); + } + function test_getCurrentLocation(t) { + t.plan(5); + var control = new OpenLayers.Control.Geolocate({ + geolocation: geolocation + }); + map.addControl(control); + t.eq(control.getCurrentLocation(), false, 'getCurrentLocation return false if control hasnt been activated'); + control.activate(); + map.setCenter(centerLL); + t.eq(control.getCurrentLocation(), true, 'getCurrentLocation return true if control has been activated'); + var center = map.getCenter(); + t.eq(center.lon, 10, 'bound control sets the map lon when calling getCurrentLocation'); + t.eq(center.lat, 10, 'bound control sets the map lat when calling getCurrentLocation'); + control.deactivate(); + map.removeControl(control); + map.setCenter(centerLL); + var control2 = new OpenLayers.Control.Geolocate({ + geolocation: geolocation + }); + map.addControl(control2); + t.eq(control2.getCurrentLocation(), false, 'getCurrentLocation return false if control is in watch mode'); + control2.deactivate(); + map.removeControl(control2); + map.setCenter(centerLL); + } + function test_watch(t) { + t.plan(2); + var control = new OpenLayers.Control.Geolocate({ + geolocation: geolocation, + watch: true + }); + map.addControl(control); + control.activate(); + t.eq(watch, true, 'watch option makes calls to watchPosition'); + control.deactivate(); + t.eq(watch, null, 'deactivate control calls the clearwatch'); + map.removeControl(control); + map.setCenter(centerLL); + } + function test_destroy(t) { + t.plan(1); + var control = new OpenLayers.Control.Geolocate({ + geolocation: geolocation, + watch: true + }); + control.activate(); + control.destroy(); + t.ok(control.active === false, "control deactivated before being destroyed"); + } + + function loader() { + map = new OpenLayers.Map('map'); + var layer = new OpenLayers.Layer.WMS("Test Layer", + "http://labs.metacarta.com/wms-c/Basic.py?", + {layers: "basic"}); + map.addLayer(layer); + centerLL = new OpenLayers.LonLat(0,0); + map.setCenter(centerLL, 5); + } + </script> +</head> +<body onload="loader()"> + <div id="map" style="width: 256px; height: 256px;"/> +</body> +</html> diff --git a/misc/openlayers/tests/Control/GetFeature.html b/misc/openlayers/tests/Control/GetFeature.html new file mode 100644 index 0000000..bbdd0e4 --- /dev/null +++ b/misc/openlayers/tests/Control/GetFeature.html @@ -0,0 +1,177 @@ +<html> +<head> + <script src="../OLLoader.js"></script> + <script type="text/javascript"> + function test_Control_GetFeature_constructor(t) { + t.plan(3); + var protocol = "foo"; + var control = new OpenLayers.Control.GetFeature({ + protocol: protocol + }); + t.ok(control instanceof OpenLayers.Control.GetFeature, + "new OpenLayers.Control.SelectFeature returns an instance"); + t.eq(control.protocol, "foo", + "constructor sets protocol correctly"); + + control = new OpenLayers.Control.GetFeature({ + filterType: OpenLayers.Filter.Spatial.INTERSECTS + }); + t.eq(control.filterType, OpenLayers.Filter.Spatial.INTERSECTS, + "constructor sets filterType correctly"); + + } + + function test_Control_GetFeature_select(t) { + t.plan(10); + var cssAdded; + var map = new OpenLayers.Map("map"); + var layer = new OpenLayers.Layer.WMS("foo", "wms", { + layers: "foo" + }); + map.addLayer(layer); + map.setCenter(new OpenLayers.LonLat(1,2)); + var feature1 = new OpenLayers.Feature.Vector(new OpenLayers.Geometry.Point(1,2)); + var feature2 = new OpenLayers.Feature.Vector(new OpenLayers.Geometry.Point(2,3)); + var feature3 = new OpenLayers.Feature.Vector(new OpenLayers.Geometry.Point(3,1)); + var control = new OpenLayers.Control.GetFeature({ + protocol: new OpenLayers.Protocol({ + read: function(obj) { + cssAdded = OpenLayers.Element.hasClass(map.viewPortDiv, + "olCursorWait"); + obj.callback.call(obj.scope, { + features: [feature1, feature2, feature3], + success: function() {return true;} + }); + } + }), + box: true + }); + map.addControl(control); + + var singleTest = function(evt) { + t.eq(evt.feature.id, feature1.id, "featureselected callback called with closest feature"); + } + cssAdded = false; + control.events.register("featureselected", this, singleTest); + control.selectClick({xy: new OpenLayers.Pixel(200, 125)}); + t.ok(cssAdded, + "select adds CSS class (click)"); + t.ok(!OpenLayers.Element.hasClass(map.viewPortDiv, "olCursorWait"), + "callback removes CSS class (click)"); + control.events.unregister("featureselected", this, singleTest); + + var count = 0; + var beforeFeatureSelected = function(evt) { + count++; + return count < 3; + } + var features = []; + var boxTest = function(evt) { + features.push(evt.feature); + } + var beforeFeaturesSelected = function(evt) { + t.eq(evt.features.length, 3, "3 features passed to the beforefeaturesselected handler"); + } + var featuresSelected = function(evt) { + t.eq(evt.features.length, 2, "2 features passed to the featuresselected handler"); + } + control.events.register("beforefeatureselected", this, beforeFeatureSelected); + control.events.register("featureselected", this, boxTest); + control.events.register("beforefeaturesselected", this, beforeFeaturesSelected); + control.events.register("featuresselected", this, featuresSelected); + cssAdded = false; + control.selectBox(new OpenLayers.Bounds(0,0,4,4)); + control.events.unregister("beforefeatureselected", this, beforeFeatureSelected); + control.events.unregister("featureselected", this, boxTest); + control.events.unregister("beforefeaturesselected", this, beforeFeaturesSelected); + control.events.unregister("featuresselected", this, featuresSelected); + t.eq(features.length, 2, "2 features inside box selected"); + t.eq(features[1].id, feature2.id, "featureselected callback called with multiple features"); + t.ok(cssAdded, + "select adds CSS class (box)"); + t.ok(!OpenLayers.Element.hasClass(map.viewPortDiv, "olCursorWait"), + "callback removes CSS class (box)"); + + // allow several features even for single click + control.single = false; + var multiplePointTest = function(evt) { + t.eq(evt.features.length, 3, "3 features passed to the featuresselected handler"); + } + control.events.register("featuresselected", this, multiplePointTest); + control.selectClick({xy: new OpenLayers.Pixel(200, 125)}); + control.events.unregister("featuresselected", this, multiplePointTest); + } + + function test_Control_GetFeature_hover(t) { + t.plan(9); + var cssAdded; + var abortedResponse = null; + var map = new OpenLayers.Map("map"); + var layer = new OpenLayers.Layer.WMS("foo", "wms", { + layers: "foo" + }); + map.addLayer(layer); + map.setCenter(new OpenLayers.LonLat(1,2)); + var feature1 = new OpenLayers.Feature.Vector(new OpenLayers.Geometry.Point(1,2)); + var feature2 = new OpenLayers.Feature.Vector(new OpenLayers.Geometry.Point(2,3)); + var response = new OpenLayers.Protocol.Response(); + var control = new OpenLayers.Control.GetFeature({ + protocol: new OpenLayers.Protocol({ + read: function(obj){ + cssAdded = OpenLayers.Element.hasClass(map.viewPortDiv, + "olCursorWait"); + obj.callback.call(obj.scope, { + features: [feature1, feature2], + success: function() {return true;} + }); + return response; + }, + abort: function(response) { + abortedResponse = response; + } + }), + hover: true + }); + map.addControl(control); + + var hoverFeature; + var hoverTest = function(evt) { + t.eq(evt.feature.id, hoverFeature.id, "hoverfeature callback called with closest feature"); + } + var outTest = function(evt) { + t.eq(evt.feature.id, feature1.id, "outfeature callback called with previously hovered feature"); + } + control.events.register("hoverfeature", this, hoverTest); + control.events.register("outfeature", this, outTest); + hoverFeature = feature1; + control.selectHover({xy: new OpenLayers.Pixel(200, 125)}); + t.ok(control.hoverResponse == response, + "selectHover stores the protocol response in the hoverResponse property"); + + hoverFeature = feature2; + cssAdded = false; + control.selectHover({xy: new OpenLayers.Pixel(400, 0)}); + t.ok(cssAdded, + "select adds CSS class (hover)"); + t.ok(!OpenLayers.Element.hasClass(map.viewPortDiv, "olCursorWait"), + "callback removes CSS class (hover)"); + + OpenLayers.Element.addClass(map.viewPortDiv, "olCursorWait"); + control.cancelHover(); + t.ok(abortedResponse == response, + "cancelHover calls protocol.abort() with the expected response"); + t.eq(control.hoverResponse, null, + "cancelHover sets this.hoverResponse to null"); + t.ok(!OpenLayers.Element.hasClass(map.viewPortDiv, "olCursorWait"), + "cancelHover removes CSS class"); + + control.events.unregister("hoverfeature", this, hoverTest); + control.events.unregister("outfeature", this, outTest); + } + + </script> +</head> +<body> + <div id="map" style="width: 400px; height: 250px;"/> +</body> +</html> diff --git a/misc/openlayers/tests/Control/Graticule.html b/misc/openlayers/tests/Control/Graticule.html new file mode 100644 index 0000000..4aa867f --- /dev/null +++ b/misc/openlayers/tests/Control/Graticule.html @@ -0,0 +1,66 @@ +<html> +<head> + <script src="../OLLoader.js"></script> + <script src="http://svn.osgeo.org/metacrs/proj4js/trunk/lib/proj4js-compressed.js"></script> + <script type="text/javascript"> + + function test_initialize(t) { + t.plan(2); + var options = {}; + var map = new OpenLayers.Map("map",{projection:"EPSG:4326"}); + var layer = new OpenLayers.Layer.WMS(); + map.addLayers([layer]); + + var control = new OpenLayers.Control.Graticule(options); + map.addControl(control); + map.zoomToMaxExtent(); + + t.ok(control.gratLayer instanceof OpenLayers.Layer.Vector, + "constructor sets layer correctly"); + t.ok(control.gratLayer.features.length > 0, + "graticule has features"); + control.destroy(); + } + + function test_activate(t) { + t.plan(7); + var map = new OpenLayers.Map("map",{projection:"EPSG:4326"}); + var layer = new OpenLayers.Layer.WMS(); + map.addLayers([layer]); + + var control = new OpenLayers.Control.Graticule({}); + map.addControl(control); + map.zoomToMaxExtent(); + + t.ok(control.gratLayer.visibility, "Graticule layer is visible by default"); + control.deactivate(); + t.ok(control.gratLayer.map == null, + "Graticule layer is not in map when control is deactivated"); + control.destroy(); + + var control2 = new OpenLayers.Control.Graticule({autoActivate:false}); + map.addControl(control2); + t.ok(control2.gratLayer.map == null, + "Graticule layer is not in map when autoActivate:false"); + t.ok(control2.gratLayer.features.length == 0, + "Graticule layer is empty when autoActivate:false"); + control2.activate(); + t.ok(control2.gratLayer.map != null, + "Graticule layer is on map when control is activated"); + t.ok(control2.gratLayer.features.length > 0, + "Graticule features refreshed after control is activated"); + control2.gratLayer.setVisibility(false); + + control2.destroy(); + t.ok(control2.gratLayer == null, + "Graticule layer is destroyed when control is destroyed"); + + map.destroy(); + } + + </script> +</head> +<body> + <div id="map" style="width: 400px; height: 250px;"/> +</body> +</html> diff --git a/misc/openlayers/tests/Control/KeyboardDefaults.html b/misc/openlayers/tests/Control/KeyboardDefaults.html new file mode 100644 index 0000000..e190177 --- /dev/null +++ b/misc/openlayers/tests/Control/KeyboardDefaults.html @@ -0,0 +1,173 @@ +<html> +<head> + <script src="../OLLoader.js"></script> + <script type="text/javascript"> + var map; + function test_Control_KeyboardDefaults_constructor (t) { + t.plan( 2 ); + + control = new OpenLayers.Control.KeyboardDefaults(); + t.ok( control instanceof OpenLayers.Control.KeyboardDefaults, + "new OpenLayers.Control.KeyboardDefaults returns object" ); + t.eq( control.displayClass, "olControlKeyboardDefaults", "displayClass is correct" ); + } + + function test_Control_KeyboardDefaults_destroy (t) { + t.plan(2); + + map = new OpenLayers.Map('map'); + var control = new OpenLayers.Control.KeyboardDefaults(); + map.addControl(control); + t.ok(control.handler != null, "control.handler is created"); + control.destroy(); + t.ok(control.handler == null, "control.handler is null after destroy"); + map.destroy(); + } + + function test_Control_KeyboardDefaults_addControl (t) { + t.plan( 4 ); + + map = new OpenLayers.Map('map'); + control = new OpenLayers.Control.KeyboardDefaults(); + t.ok( control instanceof OpenLayers.Control.KeyboardDefaults, + "new OpenLayers.Control.KeyboardDefaults returns object" ); + t.ok( map instanceof OpenLayers.Map, + "new OpenLayers.Map creates map" ); + map.addControl(control); + t.ok( control.map === map, "Control.map is set to the map object" ); + t.ok( OpenLayers.Util.indexOf(map.controls, control), "map.controls contains control" ); + } + + /* When interpretting + * the keycodes below (including the comments associated with them), + * consult the URL below. For instance, the Safari browser returns + * "IE keycodes", and so is supported by any keycode labeled "IE". + * + * Very informative URL: + * http://unixpapa.com/js/key.html + */ + function test_Control_KeyboardDefaults_KeyDownEvent (t) { + t.plan( 25 ); + + var evt = {which: 1}, pans = [], zoomIns = 0, zoomOuts = 0; + + map = new OpenLayers.Map('map'); + + // mock "pan", "zoomIn" and "zoomOut" + map.pan = function(dx, dy) { + pans.push({dx: dx, dy: dy}); + }; + map.zoomIn = function() { + zoomIns++; + }; + map.zoomOut = function() { + zoomOuts++; + }; + + var layer = new OpenLayers.Layer.WMS("Test Layer", + "http://octo.metacarta.com/cgi-bin/mapserv?", + {map: "/mapdata/vmap_wms.map", layers: "basic"}); + map.addLayer(layer); + + var control = new OpenLayers.Control.KeyboardDefaults({ + slideFactor: 100 + }); + map.addControl(control); + + map.setCenter(new OpenLayers.LonLat(0, 0), 4); + + // Start new test. + evt.keyCode = OpenLayers.Event.KEY_LEFT; + control.defaultKeyPress(evt); + t.eq(pans.length, 1, '[KEY_LEFT] pan called once'); + t.eq(pans[0], {dx: -100, dy: 0}, + '[KEY LEFT] pan called with expected args'); + + evt.keyCode = OpenLayers.Event.KEY_RIGHT; + control.defaultKeyPress(evt); + t.eq(pans.length, 2, '[KEY_RIGHT] pan called once'); + t.eq(pans[1], {dx: 100, dy: 0}, + '[KEY RIGHT] pan called with expected args'); + + evt.keyCode = OpenLayers.Event.KEY_UP; + control.defaultKeyPress(evt); + t.eq(pans.length, 3, '[KEY_UP] pan called once'); + t.eq(pans[2], {dx: 0, dy: -100}, + '[KEY UP] pan called with expected args'); + + evt.keyCode = OpenLayers.Event.KEY_DOWN; + control.defaultKeyPress(evt); + t.eq(pans.length, 4, '[KEY_DOWN] pan called once'); + t.eq(pans[3], {dx: 0, dy: 100}, + '[KEY DOWN] pan called with expected args'); + + evt.keyCode = 33; + control.defaultKeyPress(evt); + t.eq(pans.length, 5, '[33] pan called once'); + t.eq(pans[4], {dx: 0, dy: -384}, + '[33] pan called with expected args'); + + evt.keyCode = 34; + control.defaultKeyPress(evt); + t.eq(pans.length, 6, '[34] pan called once'); + t.eq(pans[5], {dx: 0, dy: 384}, + '[34] pan called with expected args'); + + evt.keyCode = 35; + control.defaultKeyPress(evt); + t.eq(pans.length, 7, '[35] pan called once'); + t.eq(pans[6], {dx: 768, dy: 0}, + '[35] pan called with expected args'); + + evt.keyCode = 36; + control.defaultKeyPress(evt); + t.eq(pans.length, 8, '[36] pan called once'); + t.eq(pans[7], {dx: -768, dy: 0}, + '[36] pan called with expected args'); + + evt.keyCode = 43; + control.defaultKeyPress(evt); + t.eq(zoomIns, 1, '[43] zoomIn called once'); + + evt.keyCode = 61; + control.defaultKeyPress(evt); + t.eq(zoomIns, 2, '[61] zoomIn called once'); + + evt.keyCode = 187; + control.defaultKeyPress(evt); + t.eq(zoomIns, 3, '[187] zoomIn called once'); + + evt.keyCode = 107; + control.defaultKeyPress(evt); + t.eq(zoomIns, 4, '[107] zoomIn called once'); + + evt.keyCode = 107; + control.defaultKeyPress(evt); + t.eq(zoomIns, 5, '[107] zoomIn called once'); + + evt.keyCode = 45; + control.defaultKeyPress(evt); + t.eq(zoomOuts, 1, '[45] zoomOut called once'); + + evt.keyCode = 109; + control.defaultKeyPress(evt); + t.eq(zoomOuts, 2, '[109] zoomOut called once'); + + evt.keyCode = 189; + control.defaultKeyPress(evt); + t.eq(zoomOuts, 3, '[189] zoomOut called once'); + + evt.keyCode = 95; + control.defaultKeyPress(evt); + t.eq(zoomOuts, 4, '[95] zoomOut called once'); + + map.destroy(); + } + + + </script> +</head> +<body> + <div id="map" style="width: 1024px; height: 512px;"/> +</body> +</html> diff --git a/misc/openlayers/tests/Control/LayerSwitcher.html b/misc/openlayers/tests/Control/LayerSwitcher.html new file mode 100644 index 0000000..c81a779 --- /dev/null +++ b/misc/openlayers/tests/Control/LayerSwitcher.html @@ -0,0 +1,249 @@ +<html> +<head> + <script src="../OLLoader.js"></script> + <script type="text/javascript"> + var map; + OpenLayers.Lang.setCode('en'); + + function test_Control_LayerSwitcher_constructor (t) { + t.plan( 2 ); + + control = new OpenLayers.Control.LayerSwitcher(); + t.ok( control instanceof OpenLayers.Control.LayerSwitcher, "new OpenLayers.Control.LayerSwitcher returns object" ); + t.eq( control.displayClass, "olControlLayerSwitcher", "displayClass is correct" ); + } + + function test_Control_LayerSwitcher_draw (t) { + t.plan( 2 ); + + map = new OpenLayers.Map('map'); + control = new OpenLayers.Control.LayerSwitcher(); + map.addControl(control); + + var div = control.draw(); + t.ok( control.div != null, "draw makes a div" ); + t.ok( div != null, "draw returns its div" ); + } + function test_Control_LayerSwitcher_outsideViewport (t) { + t.plan( 4 ); + + map = new OpenLayers.Map('map'); + control = new OpenLayers.Control.LayerSwitcher({'div':OpenLayers.Util.getElement('layerswitcher')}); + map.addControl(control); + t.eq(control.div.style.width, "250px", "Div is not minimized when added."); + t.ok(control.events.element && control.events.listeners.buttonclick, "[outside] Events instance attached to div and has buttonclick event"); + control = new OpenLayers.Control.LayerSwitcher(); + map.addControl(control); + t.eq(control.div.style.width, "0px", "Div is minimized when added."); + t.ok(!control.events.element && map.events.listeners.buttonclick, "[inside] Events instance not attached to div and buttonclick event registered on map"); + } + + function test_Control_LayerSwitcher_loadContents(t) { + + t.plan( 10 ); + + map = new OpenLayers.Map('map'); + var layer = new OpenLayers.Layer.WMS("WMS", + "http://octo.metacarta.com/cgi-bin/mapserv?", + {map: "/mapdata/vmap_wms.map", layers: "basic"}); + map.addLayer(layer); + + markers = new OpenLayers.Layer.Markers("markers"); + map.addLayer(markers); + + control = new OpenLayers.Control.LayerSwitcher(); + map.addControl(control); + + t.ok(control.layersDiv != null, "correctly makes layers div"); + t.ok(OpenLayers.Element.hasClass(control.layersDiv, "layersDiv"), + "layers div has class layersDiv"); + t.ok(control.baseLayersDiv != null, "correctly makes layers div"); + t.ok(OpenLayers.Element.hasClass(control.baseLayersDiv, "baseLayersDiv"), + "base layers div has class baseLayersDiv"); + t.ok(control.dataLayersDiv != null, "correctly makes layers div"); + t.ok(OpenLayers.Element.hasClass(control.dataLayersDiv, "dataLayersDiv"), + "data layers div has class dataLayersDiv"); + t.ok(control.maximizeDiv != null, "correctly makes resize div"); + t.ok(OpenLayers.Element.hasClass(control.maximizeDiv, "maximizeDiv"), + "maximize div has class maximizeDiv"); + t.ok(control.minimizeDiv != null, "correctly makes resize div"); + t.ok(OpenLayers.Element.hasClass(control.minimizeDiv, "minimizeDiv"), + "minimize div has class minmizeDiv"); + } + + + function test_Control_LayerSwitcher_redraw (t) { + + t.plan( (OpenLayers.BROWSER_NAME == "opera" ? 9 : 19 ) ); + + map = new OpenLayers.Map('map'); + var layer = new OpenLayers.Layer.WMS("WMS", + "http://octo.metacarta.com/cgi-bin/mapserv?", + {map: "/mapdata/vmap_wms.map", layers: "basic"}); + map.addLayer(layer); + + markers = new OpenLayers.Layer.Markers("markers"); + map.addLayer(markers); + + control = new OpenLayers.Control.LayerSwitcher(); + map.addControl(control); + + var wmsInput = control.div.childNodes[0].childNodes[1].childNodes[0]; + t.ok(wmsInput != null, "correctly makes an input for wms layer"); + t.eq(wmsInput.type, "radio", "wms correctly made a radio button"); + t.eq(wmsInput.name, control.id + "_baseLayers", "wms correctly named"); + t.eq(wmsInput.value, layer.name, "wms correctly valued"); + + var markersInput = control.div.childNodes[0].childNodes[3].childNodes[0]; + t.ok(markersInput != null, "correctly makes an input for markers layer"); + t.eq(markersInput.type, "checkbox", "wms correctly made a radio button"); + t.eq(markersInput.name, markers.name, "wms correctly named"); + t.eq(markersInput.value, markers.name, "wms correctly valued"); + + t.eq(false, control.checkRedraw(), "check redraw is false"); + if (OpenLayers.BROWSER_NAME != "opera") { + control = new OpenLayers.Control.LayerSwitcher(); + var myredraw = control.redraw; + control.redraw = function() { + t.ok(true, "redraw called when setting vis"); + } + map.addControl(control); + var func = OpenLayers.Function.bind(myredraw, control); + func(); + markers.setVisibility(false); + t.eq(control.checkRedraw(), true, "check redraw is true after changing layer and not letting redraw happen."); + map.removeControl(control); + + control = new OpenLayers.Control.LayerSwitcher(); + var myredraw = control.redraw; + control.redraw = function() { + t.ok(true, "redraw called when setting inRange"); + } + map.addControl(control); + var func = OpenLayers.Function.bind(myredraw, control); + func(); + markers.inRange = false; + t.eq(control.checkRedraw(), true, "check redraw is true after changing layer.inRange and not letting redraw happen."); + map.removeControl(control); + + control = new OpenLayers.Control.LayerSwitcher(); + var myredraw = control.redraw; + control.redraw = function() { + t.ok(true, "redraw called when raising base layer "); + } + + map.addControl(control); + var func = OpenLayers.Function.bind(myredraw, control); + func(); + map.raiseLayer(layer, 1); + t.eq(control.checkRedraw(), true, "check redraw is true after changing layer.inRange and not letting redraw happen."); + map.removeControl(control); + } else { + t.debug_print("FIXME: Some LayerSwitcher tests fail in Opera."); + } + + } + function test_Control_LayerSwitcher_ascending (t) { + + t.plan( 4 ); + + map = new OpenLayers.Map('map'); + var layer = new OpenLayers.Layer.WMS("WMS", + "http://octo.metacarta.com/cgi-bin/mapserv?", + {map: "/mapdata/vmap_wms.map", layers: "basic"}); + map.addLayer(layer); + + markers = new OpenLayers.Layer.Markers("markers"); + map.addLayer(markers); + + control = new OpenLayers.Control.LayerSwitcher(); + map.addControl(control); + control2 = new OpenLayers.Control.LayerSwitcher({'ascending':false}); + map.addControl(control2); + t.ok(control.div.childNodes[0].childNodes[0].innerHTML.match("Base Layer"), "Base Layers first in LayerSwitcher with ascending true"); + t.ok(control.div.childNodes[0].childNodes[2].innerHTML.match("Overlays"), "Overlays in LayerSwitcher with ascending true"); + t.ok(control2.div.childNodes[0].childNodes[2].innerHTML.match("Base Layer"), "Base Layers last in LayerSwitcher with ascending false"); + t.ok(control2.div.childNodes[0].childNodes[0].innerHTML.match("Overlays"), "Base Layers last in LayerSwitcher with ascending false"); + } + + function test_Control_LayerSwitcher_displayInLayerSwitcher (t) { + + t.plan( 2 ); + + map = new OpenLayers.Map('map'); + var layer = new OpenLayers.Layer.WMS("WMS", + "http://octo.metacarta.com/cgi-bin/mapserv?", + {map: "/mapdata/vmap_wms.map", layers: "basic"}, {'displayInLayerSwitcher': false}); + map.addLayer(layer); + + control = new OpenLayers.Control.LayerSwitcher(); + map.addControl(control); + t.eq(control.div.childNodes[0].childNodes[0].style.display, "none" , "Base layer display off when no visble base layer"); + + map = new OpenLayers.Map('map'); + var layer = new OpenLayers.Layer.WMS("WMS", + "http://octo.metacarta.com/cgi-bin/mapserv?", + {map: "/mapdata/vmap_wms.map", layers: "basic"}); + map.addLayer(layer); + + control = new OpenLayers.Control.LayerSwitcher(); + map.addControl(control); + t.eq(control.div.childNodes[0].childNodes[0].style.display, "" , "Base layer display on when visble base layer"); + } + + // See e.g. https://github.com/openlayers/openlayers/issues/866 + function test_Control_LayerSwitcher_validIds(t){ + t.plan(2); + + // setup + var layername = "Name with spaces & illegal characters * + ~ ` ' ? )", + map = new OpenLayers.Map("map", { + controls: [ + new OpenLayers.Control.LayerSwitcher() + ], + layers: [ + new OpenLayers.Layer.WMS( + layername, + "../../img/blank.gif" + ), + // add another layer with the same name, the generated id + // must be different + new OpenLayers.Layer.WMS( + layername, + "../../img/blank.gif" + ) + ] + }); + + var baselayerDiv = map.controls[0].div.childNodes[0].childNodes[1], + firstGeneratedInputId = baselayerDiv.childNodes[0].id, + secondGeneratedInputId = baselayerDiv.childNodes[1].id, + // legal ids start with a letter and are followed only by word + // characters (letters, digits, and underscores) plus the dash (-) + // This is only a subset of all allowed charcters inside of ids. + allowedIdChars = (/^[a-zA-Z]{1}[\w-]*$/g); + + // tests + // validity + t.ok( + allowedIdChars.test(firstGeneratedInputId), + "id only contains letters, digits, underscores and dashes. It " + + "starts with a letter." + ); + // uniqueness + t.ok( + firstGeneratedInputId !== secondGeneratedInputId, + "generated ids are different even for equal layernames" + ); + + // teardown + map.destroy(); + } + + </script> +</head> +<body> + <div id="map" style="width: 1024px; height: 512px;"/> + <div id="layerswitcher" style="width:250px; height:256px;" /> +</body> +</html> diff --git a/misc/openlayers/tests/Control/Measure.html b/misc/openlayers/tests/Control/Measure.html new file mode 100644 index 0000000..ee6d192 --- /dev/null +++ b/misc/openlayers/tests/Control/Measure.html @@ -0,0 +1,386 @@ +<html> +<head> + <script src="../OLLoader.js"></script> + <script type="text/javascript"> + + function test_initialize(t) { + + t.plan(1); + + var map = new OpenLayers.Map("map"); + var control = new OpenLayers.Control.Measure( + OpenLayers.Handler.Path, {persist: true} + ); + map.addControl(control); + + t.eq(control.persist, true, "passing persist to constructor sets persist on handler"); + + map.destroy(); + + } + + function test_cancel(t) { + + t.plan(4); + + var map = new OpenLayers.Map("map"); + var layer = new OpenLayers.Layer(null, { + isBaseLayer: true + }); + map.addLayer(layer); + map.zoomToMaxExtent(); + + var control = new OpenLayers.Control.Measure( + OpenLayers.Handler.Path, {persist: true} + ); + map.addControl(control); + + control.activate(); + + try { + control.cancel(); + t.ok(true, "calling cancel before drawing works"); + } catch(err) { + t.fail("calling cancel before drawing causes trouble: " + err); + } + t.eq(control.active, true, "control remains active after cancel"); + + // create a simple measurement + function trigger(type, x, y) { + map.events.triggerEvent(type, { + xy: new OpenLayers.Pixel(x, y) + }) + }; + + trigger("mousemove", 0, 0); + // keep a reference to the line being drawn + var line = control.handler.line; + trigger("mousedown", 0, 0); + trigger("mouseup", 0, 0); + trigger("mousemove", 10, 10); + trigger("mousedown", 10, 10); + trigger("mouseup", 10, 10); + trigger("dblclick", 10, 10); + + // the geometry is finalized, we first confirm that it is persisted + t.ok(line.layer === control.handler.layer, "feature persists"); + + // cancel and see that sketch is gone + control.cancel(); + t.eq(line.layer, null, "feature is gone after cancel"); + + map.destroy(); + } + + // test for <http://trac.openlayers.org/ticket/2691> + function test_partial(t) { + + t.plan(28); + + var map = new OpenLayers.Map({ + div: "map", + units: "m", + resolutions: [1], + layers: [ + new OpenLayers.Layer(null, { + isBaseLayer: true + }) + ], + center: new OpenLayers.LonLat(0, 0) + }); + + var log = []; + var control = new OpenLayers.Control.Measure( + OpenLayers.Handler.Path, {persist: true, + eventListeners: { + measurepartial: function(evt) { + log.push(evt); + }, + measure: function(evt){ + log.push(evt); + } + }, + handlerOptions: { + pixelTolerance: 0, + dblclickTolerance: 0 + } + } + ); + map.addControl(control); + control.activate(); + + + // convenience function to trigger mouse events + function trigger(type, x, y) { + map.events.triggerEvent(type, { + xy: new OpenLayers.Pixel(x, y) + }) + }; + + // delay in seconds + var delay = control.partialDelay / 1000; + + // establish first point + trigger("mousemove", 0, 0); + trigger("mousedown", 0, 0); + trigger("mouseup", 0, 0); + + + // a) move 10 pixels and click + trigger("mousemove", 0, 10); + trigger("mousedown", 0, 10); + trigger("mouseup", 0, 10); + + // confirm measurepartial is not fired before delay + t.eq(log.length, 0, "a) no event fired yet") + + t.delay_call( + // wait for delay then confirm event was logged + delay, function() { + t.eq(log.length, 1, "a) event logged") + t.eq(log[0] && log[0].type, "measurepartial", "a) event logged"); + t.eq(log[0] && log[0].measure, 10, "a) correct measure"); + + // b) move 10 pixels and click + trigger("mousemove", 0, 20); + trigger("mousedown", 0, 20); + trigger("mouseup", 0, 20); + + // confirm measurepartial is not fired before delay + t.eq(log.length, 1, "b) no event fired yet") + + }, + delay, function() { + t.eq(log.length, 2, "b) event logged"); + t.eq(log[1] && log[1].type, "measurepartial", "b) correct type"); + t.eq(log[1] && log[1].measure, 20, "b) correct measure"); + + // c) move 10 pixels and click + trigger("mousemove", 0, 30); + trigger("mousedown", 0, 30); + trigger("mouseup", 0, 30); + }, + // wait for half delay and confirm event not logged + delay / 2, function() { + // confirm measurepartial is not fired before delay + t.eq(log.length, 2, "c) no event fired yet") + }, + // wait for rest of delay and confirm event logged + delay / 2, function() { + t.eq(log.length, 3, "c) event logged"); + t.eq(log[2] && log[2].type, "measurepartial", "c) correct type"); + t.eq(log[2] && log[2].measure, 30, "c) correct measure"); + + // d) move 10 pixels and click + trigger("mousemove", 0, 40); + trigger("mousedown", 0, 40); + trigger("mouseup", 0, 40); + + // confirm measurepartial is not fired before delay + t.eq(log.length, 3, "d) no event fired yet") + + // e) double click to finish + trigger("dblclick", 0, 40); + + t.eq(log.length, 4, "e) event logged"); + t.eq(log[3] && log[3].type, "measure", "e) correct type"); + t.eq(log[3] && log[3].measure, 40, "e) correct measure"); + }, + // wait for rest of delay and confirm no measurepartial logged + delay, function() { + // confirm measurepartial is not fired after dblclick + t.eq(log.length, 4, "e) no additional event fired"); + + // change to freehand mode and confirm synchronous event dispatch + control.handler.freehand = true; + // clear log + log = []; + + // f) establish first freehand point + trigger("mousemove", 0, 0); + trigger("mousedown", 0, 0); + t.eq(log.length, 0, "f) no event fired yet") + + // g) move 10 pixels + trigger("mousemove", 10, 0); + + t.eq(log.length, 1, "g) event logged"); + t.eq(log[0] && log[0].type, "measurepartial", "g) correct type"); + t.eq(log[0] && log[0].measure, 10, "g) correct measure"); + + // h) move 10 pixels + trigger("mousemove", 20, 0); + + t.eq(log.length, 2, "h) event logged"); + t.eq(log[1] && log[1].type, "measurepartial", "h) correct type"); + t.eq(log[1] && log[1].measure, 20, "h) correct measure"); + + // i) mouse up to finish + trigger("mouseup", 20, 0); + + t.eq(log.length, 3, "i) event logged"); + t.eq(log[2] && log[2].type, "measure", "i) correct type"); + t.eq(log[2] && log[2].measure, 20, "i) correct measure"); + + // j) clean up + log = []; + map.destroy(); + }, + // wait for delay and confirm event not logged + delay, function() { + t.eq(log.length, 0, "j) no event fired after destroy"); + } + ); + + } + + function test_immediate(t) { + t.plan(32); + + var map = new OpenLayers.Map({ + div: "map", + units: "m", + resolutions: [1], + layers: [ + new OpenLayers.Layer(null, { + isBaseLayer: true + }) + ], + center: new OpenLayers.LonLat(0, 0) + }); + + var log = []; + var control = new OpenLayers.Control.Measure( + OpenLayers.Handler.Path, { + persist: true, + immediate: true, + eventListeners: { + measurepartial: function(evt) { + log.push(evt); + }, + measure: function(evt){ + log.push(evt); + } + }, + handlerOptions: { + pixelTolerance: 0, + dblclickTolerance: 0 + } + } + ); + map.addControl(control); + control.activate(); + + // convenience function to trigger mouse events + function trigger(type, x, y) { + map.events.triggerEvent(type, { + xy: new OpenLayers.Pixel(x, y) + }) + }; + + // delay in seconds + var delay = control.partialDelay / 1000; + + // a) establish first point + trigger("mousemove", 0, 0); + trigger("mousedown", 0, 0); + trigger("mouseup", 0, 0); + + // move 10 pixels + trigger("mousemove", 0, 10); + + t.eq(log.length, 1, "a) has fired an event"); + + t.delay_call( + delay, function() { + // confirm measurepartial is fired + t.eq(log.length, 1, "a) one event logged"); + t.ok(log[0] && log[0].type == "measurepartial", "a) correct type"); + // mousemove within the partialDelay fires no event, so the + // measure below is the one of the initial point + t.eq(log[0]?log[0].measure:-1 , 10, "a) correct measure"); + + // b) move 10 pixels + trigger("mousemove", 0, 20); + // c) move 10 pixels again + trigger("mousemove", 0, 30); + + // confirm measurepartial is fired 2 times + t.eq(log.length, 3, "b) event logged"); + t.eq(log[1] && log[1].type, "measurepartial", "b) correct type"); + t.eq(log[1] && log[1].measure, 20, "b) correct measure"); + t.eq(log[2] && log[2].type, "measurepartial", "c) correct type"); + t.eq(log[2] && log[2].measure, 30, "c) correct measure"); + + // d) switch immediate measurement off + control.setImmediate(false); + t.eq(control.immediate, false, "d) immediate is false"); + + // e) move 10 pixels and click + trigger("mousemove", 0, 40); + trigger("mousedown", 0, 40); + trigger("mouseup", 0, 40); + // confirm measurepartial is not fired before delay + t.eq(log.length, 3, "e) no event fired yet") + }, + // wait for delay then confirm event was logged + delay, function() { + t.eq(log.length, 4, "e) event logged") + t.ok(log[3] && log[3].type == "measurepartial", "e) correct type"); + t.ok(log[3] && log[3].measure == 40, "e) correct measure"); + + // f) switch immediate measurement on + control.setImmediate(true); + t.eq(control.immediate, true, "f) immediate is true"); + + // g) move 10 pixels + trigger("mousemove", 0, 50); + }, + delay, function() { + t.eq(log.length, 5, "g) event logged"); + t.ok(log[4] && log[4].type == "measurepartial", "g) correct type"); + t.ok(log[4] && log[4].measure == 50, "g) correct measure"); + + // h) move 10 pixels + trigger("mousemove", 0, 60); + + t.eq(log.length, 6, "h) event logged"); + t.ok(log[5] && log[5].type == "measurepartial", "h) correct type"); + t.ok(log[5] && log[5].measure == 60, "h) correct measure"); + + // i) double click to finish + trigger("mousedown", 0, 60); + t.eq(log.length, 7, "i) event logged"); + t.eq(log[6] && log[6].type, "measurepartial", "i) correct type"); + t.eq(log[6] && log[6].measure, 60, "i) correct measure"); + trigger("mouseup", 0, 60); + t.eq(log.length, 7, "i) no event fired yet"); + }, + delay, function() { + t.eq(log.length, 8, "j) event logged"); + t.eq(log[7] && log[7].type, "measurepartial", "j) correct type"); + t.eq(log[7] && log[7].measure, 60, "j) correct measure"); + + trigger("dblclick", 0, 60); + t.eq(log.length, 9, "k) event logged"); + t.eq(log[8] && log[8].type, "measure", "k) correct type"); + t.eq(log[8] && log[8].measure, 60, "k) correct measure"); + // clear log + log = []; + + // l) clean up + map.destroy(); + // wait for delay and confirm event not logged + }, + delay, function() { + t.eq(log.length, 0, "l) no event fired after destroy"); + } + ); + } + + </script> +</head> +<body> + <div id="map" style="width: 512px; height: 256px;"></div> +</body> +</html> diff --git a/misc/openlayers/tests/Control/ModifyFeature.html b/misc/openlayers/tests/Control/ModifyFeature.html new file mode 100644 index 0000000..6226733 --- /dev/null +++ b/misc/openlayers/tests/Control/ModifyFeature.html @@ -0,0 +1,828 @@ +<html> +<head> + <script src="../OLLoader.js"></script> + <script type="text/javascript"> + + function test_initialize(t) { + t.plan(3); + var layer = { + styleMap: {createSymbolizer: function(){}}, + events: { + on: function() {}, + un: function() {} + } + }; + var options = { + documentDrag: true + }; + var control = new OpenLayers.Control.ModifyFeature(layer, options); + + t.ok(control.layer == layer, + "constructor sets layer correctly"); + t.eq(control.handlers.drag.documentDrag, true, + "constructor sets options correctly on drag handler"); + t.eq(control.mode, OpenLayers.Control.ModifyFeature.RESHAPE, + "constructor initializes modification mode correctly"); + control.destroy(); + } + + function test_destroy(t) { + t.plan(1); + var map = new OpenLayers.Map("map"); + var layer = new OpenLayers.Layer.Vector(); + map.addLayer(layer); + var control = new OpenLayers.Control.ModifyFeature(layer); + control.destroy(); + t.eq(control.layer, null, "Layer reference removed on destroy."); + map.destroy(); + } + + function test_activate(t) { + t.plan(2); + var map = new OpenLayers.Map("map"); + var layer = new OpenLayers.Layer.Vector(); + map.addLayer(layer); + var control = new OpenLayers.Control.ModifyFeature(layer); + map.addControl(control); + t.ok(!control.handlers.drag.active, + "drag handler is not active prior to activating control"); + control.activate(); + t.ok(control.handlers.drag.active, + "drag handler is active after activating control"); + + map.destroy(); + } + + function test_initDeleteCodes(t) { + t.plan(3); + var layer = new OpenLayers.Layer.Vector(); + var control = new OpenLayers.Control.ModifyFeature(layer, {'deleteCodes': 46}); + t.eq(control.deleteCodes[0], 46, "Delete code properly turned into an array."); + var control = new OpenLayers.Control.ModifyFeature(layer); + t.eq(control.deleteCodes[0], 46, "Default deleteCodes include delete"); + t.eq(control.deleteCodes[1], 68, "Default deleteCodes include 'd'"); + + control.destroy(); + layer.destroy(); + } + + function test_handleKeypress(t) { + t.plan(16); + + /** + * There are two things that we want to test here + * 1) test that control.deleteCodes are respected + * 3) test that a vertex is properly deleted + * + * In the future, feature deletion may be added to the control. + */ + + var layer = new OpenLayers.Layer.Vector(); + var control = new OpenLayers.Control.ModifyFeature(layer); + var delKey = 46; + var dKey = 100; + control.deleteCodes = [delKey, dKey]; + + // test that a polygon vertex is deleted for all delete codes + var point = new OpenLayers.Feature.Vector( + new OpenLayers.Geometry.Point() + ); + var poly = new OpenLayers.Feature.Vector( + new OpenLayers.Geometry.Polygon() + ); + + // mock up vertex deletion + var origGetFeatureFromEvent = layer.getFeatureFromEvent; + layer.getFeatureFromEvent = function() { return point; }; + control.feature = poly; + // we cannot use selectFeature since the control is not part of a map + control._originalGeometry = poly.geometry.clone(); + control.vertices = [point]; + point.geometry.parent = { + removeComponent: function(geometry) { + t.eq(geometry.id, point.geometry.id, + "vertex deletion: removeComponent called on parent with proper geometry"); + } + }; + layer.events.on({ + "featuremodified": function(event) { + t.ok(event.feature.modified !== null, "modified property of feature should have been set"); + t.eq(event.feature.id, poly.id, "vertex deletion: featuremodifed triggered"); + }, + "vertexremoved": function(evt) { + layer.events.unregister("vertexremoved", this, arguments.callee); + t.eq(evt.feature.id, poly.id, "vertexremoved triggered with correct feature"); + t.eq(evt.vertex.id, point.geometry.id, "vertexremoved triggered with correct vertex"); + t.eq(evt.pixel, "foo", "vertexremoved triggered with correct pixel"); + } + }); + layer.drawFeature = function(feature) { + t.eq(feature.id, poly.id, + "vertex deletion: drawFeature called with the proper feature"); + }; + control.resetVertices = function() { + t.ok(true, "vertex deletion: resetVertices called"); + }; + control.onModification = function(feature) { + t.eq(feature.id, poly.id, + "vertex deletion: onModification called with the proper feature"); + }; + // run the above four tests twice + control.handleKeypress({keyCode:delKey, xy: "foo"}); + control.handleKeypress({keyCode:dKey}); + t.eq(control.feature.state, OpenLayers.State.UPDATE, "feature state set to update"); + + // now make sure nothing happens if the vertex is mid-drag + control.handlers.drag.dragging = true; + control.handleKeypress({keyCode:delKey}); + + // clean up + layer.getFeatureFromEvent = origGetFeatureFromEvent; + control.destroy(); + layer.destroy(); + } + + + function test_onUnSelect(t) { + t.plan(5); + var layer = new OpenLayers.Layer.Vector(); + var control = new OpenLayers.Control.ModifyFeature(layer); + var fakeFeature = {'id':'myid'}; + control.vertices = 'a'; + control.virtualVertices = 'b'; + control.features = true; + layer.events.on({"afterfeaturemodified": function(event) { + t.eq(event.feature, fakeFeature, "afterfeaturemodified triggered"); + }}); + control.onModificationEnd = function (feature) { t.eq(feature.id, fakeFeature.id, "onModificationEnd got feature.") } + layer.removeFeatures = function(verts) { + t.ok(verts == 'a', "Normal verts removed correctly"); + } + layer.destroyFeatures = function(verts) { + t.ok(verts == 'b', "Virtual verts destroyed correctly"); + } + control.unselectFeature(fakeFeature); + t.eq(control.feature, null, "feature is set to null"); + + layer.destroyFeatures = function() {}; + control.destroy(); + layer.destroy(); + } + + function test_stop_modification(t) { + t.plan(1); + var map = new OpenLayers.Map('map'); + var layer = new OpenLayers.Layer.Vector("Vectors!", {isBaseLayer: true}); + var feature = new OpenLayers.Feature.Vector( + new OpenLayers.Geometry.Point(0, 0) + ); + layer.addFeatures([feature]); + map.addLayer(layer); + map.setCenter(new OpenLayers.LonLat(0, 0)); + + + // If a feature is to be modified, control.selectFeature gets called. + // We want this test to fail if selectFeature gets called. + var modified = false; + + var control = new OpenLayers.Control.ModifyFeature(layer); + map.addControl(control); + control.activate(); + + // register a listener that will stop feature modification + layer.events.on({"beforefeaturemodified": function() {return false}}); + + // we can initiate feature modification by programmatically selecting + // a feature + control.selectFeature(feature); + + if(modified) { + t.fail("selectFeature called, prepping feature for modification"); + } else { + t.ok(true, "the beforefeaturemodified listener stopped feature modification"); + } + } + + function test_selectFeature(t) { + t.plan(12); + var map = new OpenLayers.Map('map'); + var layer = new OpenLayers.Layer.Vector("Vectors!", {isBaseLayer: true}); + map.addLayer(layer); + map.setCenter(new OpenLayers.LonLat(0, 0)); + var control = new OpenLayers.Control.ModifyFeature(layer); + control.vertices = []; + control.virtualVertices = []; + var callback = function(obj) { + t.ok(obj.feature == fakeFeature, "beforefeaturemodified triggered"); + }; + layer.events.on({"beforefeaturemodified": callback}); + control.onModificationStart = function(feature) { t.eq(feature.id, fakeFeature.id, "On Modification Start called with correct feature."); } + + // Start of testing + + control.collectVertices = function() { t.fail("Collect vertices called when geom is a point"); } + var fakeFeature = new OpenLayers.Feature.Vector(new OpenLayers.Geometry.Point(0, 0)); + + // Points don't call collectVertices + control.selectFeature(fakeFeature); + control.unselectFeature(fakeFeature); + + control.collectVertices = function() { + t.ok(true, "collectVertices called"); + this.vertices = 'a'; + this.virtualVertices = 'd'; + layer.addFeatures(this.vertices); + layer.addFeatures(this.virtualVertices); + } + + layer.addFeatures = function(features) { + t.ok(features == 'a' || features == 'd', "features passed correctly"); + } + layer.destroyFeatures = function() {}; + + fakeFeature.geometry = new OpenLayers.Geometry.Polygon([ + new OpenLayers.Geometry.LinearRing([ + new OpenLayers.Geometry.Point(0, 0), + new OpenLayers.Geometry.Point(1, 1) + ]) + ]); + + // OnSelect calls collectVertices and passes features to layer + control.selectFeature(fakeFeature); + control.unselectFeature(fakeFeature); + layer.destroyFeatures = OpenLayers.Layer.Vector.prototype.destroyFeatures; + + control.vertices = ['a']; + control.virtualVertices = [{destroy: function() {}}]; + + layer.addFeatures = function(features) {} + + layer.removeFeatures = function(features) { + t.eq(features.length, 1, "Correct feature length passed in"); + } + + // Features are removed whenever they exist + control.selectFeature(fakeFeature); + + control.destroy(); + + // layer.destroy() will call removeFeatures with an empty array, make + // removeFeatures reference an empty function to prevent the above + // test to fail + layer.removeFeatures = function(features) {}; + layer.destroy(); + } + + function test_resetVertices(t) { + t.plan(20); + var layer = new OpenLayers.Layer.Vector(); + var control = new OpenLayers.Control.ModifyFeature(layer); + var point = new OpenLayers.Geometry.Point(5,6); + var point2 = new OpenLayers.Geometry.Point(7,8); + var point3 = new OpenLayers.Geometry.Point(9,10); + + control.feature = new OpenLayers.Feature.Vector(point); + control.resetVertices(); + t.eq(control.vertices.length, 0, "Correct vertices length"); + t.eq(control.virtualVertices.length, 0, "Correct virtual vertices length."); + + var multiPoint = new OpenLayers.Geometry.MultiPoint([point, point2]); + control.feature = new OpenLayers.Feature.Vector(multiPoint); + control.resetVertices(); + t.eq(control.vertices.length, 2, "Correct vertices length with multipoint"); + t.eq(control.virtualVertices.length, 0, "Correct virtual vertices length (multipoint)."); + + var line = new OpenLayers.Geometry.LineString([point, point2]); + control.feature = new OpenLayers.Feature.Vector(line); + control.resetVertices(); + t.eq(control.vertices.length, 2, "Correct vertices length with line"); + t.eq(control.virtualVertices.length, 1, "Correct virtual vertices length (linestring)."); + + var polygon = new OpenLayers.Geometry.Polygon([new OpenLayers.Geometry.LinearRing([point, point2, point3])]); + control.feature = new OpenLayers.Feature.Vector(polygon); + control.resetVertices(); + t.eq(control.vertices.length, 3, "Correct vertices length with polygon"); + t.eq(control.virtualVertices.length, 3, "Correct virtual vertices length (polygon)."); + + control.mode = OpenLayers.Control.ModifyFeature.DRAG; + control.resetVertices(); + t.ok(control.dragHandle != null, "Drag handle is set"); + t.eq(control.vertices.length, 0, "Correct vertices length with polygon (DRAG)"); + + control.mode = OpenLayers.Control.ModifyFeature.ROTATE; + control.resetVertices(); + t.ok(control.radiusHandle != null, "Radius handle is set"); + t.eq(control.vertices.length, 0, "Correct vertices length with polygon (ROTATE)"); + + control.mode = OpenLayers.Control.ModifyFeature.RESIZE; + control.resetVertices(); + t.ok(control.radiusHandle != null, "Radius handle is set"); + t.eq(control.vertices.length, 0, "Correct vertices length with polygon (RESIZE)"); + + control.mode = OpenLayers.Control.ModifyFeature.RESHAPE; + control.resetVertices(); + t.ok(control.radiusHandle == null, "Radius handle is not set (RESHAPE)"); + t.eq(control.vertices.length, 3, "Correct vertices length with polygon (RESHAPE)"); + t.eq(control.virtualVertices.length, 3, "Correct virtual vertices length (RESHAPE)"); + + control.mode = OpenLayers.Control.ModifyFeature.RESIZE | OpenLayers.Control.ModifyFeature.RESHAPE; + control.resetVertices(); + t.ok(control.radiusHandle != null, "Radius handle is set (RESIZE|RESHAPE)"); + t.eq(control.vertices.length, 0, "No vertices when both resizing and reshaping (RESIZE|RESHAPE)"); + t.eq(control.virtualVertices.length, 0, "No virtual vertices when both resizing and reshaping (RESIZE|RESHAPE)"); + + control.destroy(); + layer.destroy(); + } + + function test_dragVertex(t) { + t.plan(8); + var map = new OpenLayers.Map("map", { + resolutions: [1] + }); + var layer = new OpenLayers.Layer.Vector("foo", { + maxExtent: new OpenLayers.Bounds(-10, -10, 10, 10), + isBaseLayer: true + }); + map.addLayer(layer); + + var control = new OpenLayers.Control.ModifyFeature(layer); + map.addControl(control); + control.activate(); + + map.zoomToMaxExtent(); + + var log = {}; + layer.events.on({ + "vertexmodified": function(event) { + log.event = event; + } + }); + + // pretend to drag a point + var feature = new OpenLayers.Feature.Vector( + new OpenLayers.Geometry.Point(0, 0) + ); + control.feature = feature; + var pixel = new OpenLayers.Pixel(-100, 100); + control.dragVertex(feature, pixel); + t.eq(log.event.type, "vertexmodified", "[drag point] vertexmodified triggered"); + t.geom_eq(log.event.vertex, feature.geometry, "[drag point] listeners receive correct vertex"); + t.eq(log.event.feature.id, feature.id, "[drag point] listeners receive correct feature"); + t.ok(log.event.pixel === pixel, "[drag point] listeners receive correct pixel"); + + // pretend to drag vertex of a linestring + var vert = new OpenLayers.Feature.Vector( + new OpenLayers.Geometry.Point(0, 0) + ); + var feature = new OpenLayers.Feature.Vector( + new OpenLayers.Geometry.LineString([ + vert.geometry, new OpenLayers.Geometry.Point(10, 0) + ]) + ); + control.feature = feature; + var pixel = new OpenLayers.Pixel(-100, 100); + control.dragVertex(vert, pixel); + t.eq(log.event.type, "vertexmodified", "[drag vertex] vertexmodified triggered"); + t.geom_eq(log.event.vertex, vert.geometry, "[drag vertex] listeners receive correct vertex"); + t.eq(log.event.feature.id, feature.id, "[drag vertex] listeners receive correct feature"); + t.ok(log.event.pixel === pixel, "[drag vertex] listeners receive correct pixel"); + + + map.destroy(); + } + function test_collectDragHandle(t) { + t.plan(4); + var map = new OpenLayers.Map("map", { + resolutions: [1] + }); + var layer = new OpenLayers.Layer.Vector("foo", { + maxExtent: new OpenLayers.Bounds(-10, -10, 10, 10), + isBaseLayer: true + }); + map.addLayer(layer); + var feature = new OpenLayers.Feature.Vector(new OpenLayers.Geometry.Point(1,1)); + layer.addFeatures([feature]); + var control = new OpenLayers.Control.ModifyFeature(layer); + map.addControl(control); + control.activate(); + control.feature = feature; + control.collectDragHandle(); + t.ok(control.dragHandle != null, "Drag handle created"); + t.ok(control.dragHandle._sketch == true, "Handle has _sketch true"); + t.ok(control.dragHandle.renderIntent == control.vertexRenderIntent,"Render intent for handle set"); + t.ok(control.layer.getFeatureById(control.dragHandle.id) != null, "Drag handle added to layer"); + } + function test_collectRadiusHandle(t) { + t.plan(4); + var map = new OpenLayers.Map("map", { + resolutions: [1] + }); + var layer = new OpenLayers.Layer.Vector("foo", { + maxExtent: new OpenLayers.Bounds(-10, -10, 10, 10), + isBaseLayer: true + }); + map.addLayer(layer); + var feature = new OpenLayers.Feature.Vector(new OpenLayers.Geometry.Point(1,1)); + layer.addFeatures([feature]); + var control = new OpenLayers.Control.ModifyFeature(layer); + map.addControl(control); + control.activate(); + control.feature = feature; + control.collectRadiusHandle(); + t.ok(control.radiusHandle != null, "Radius handle created"); + t.ok(control.radiusHandle._sketch == true, "Radius has _sketch true"); + t.ok(control.radiusHandle.renderIntent == control.vertexRenderIntent,"Render intent for handle set"); + t.ok(control.layer.getFeatureById(control.radiusHandle.id) != null, "Drag radius added to layer"); + } + function test_onDrag(t) { + t.plan(1); + t.ok(true, "onDrag not tested yet."); + } + + function test_dragComplete(t) { + t.plan(8); + var layer = new OpenLayers.Layer.Vector(); + var control = new OpenLayers.Control.ModifyFeature(layer); + + var fakeFeature = { + 'geometry': { 'id':'myGeom'}, + 'id': 'fakeFeature' + }; + layer.addFeatures = function (verts) { + t.ok(verts == 'virtual' || verts == 'normal', verts + " verts correct"); + } + layer.removeFeatures = function (verts) { + t.ok(verts == 'previous virtual' || verts == 'previous normal', verts + " verts correct"); + } + layer.events.on({"featuremodified": function(event) { + t.eq(event.feature, fakeFeature, "featuremodified triggered"); + }}); + control.onModification = function(feat) { + t.eq(feat.id, fakeFeature.id, "onModification gets correct feat"); + } + control.collectVertices = function() { + t.ok(true, "collectVertices called"); + this.vertices = 'normal'; + this.virtualVertices = 'virtual'; + layer.addFeatures(this.vertices); + layer.addFeatures(this.virtualVertices); + } + control.feature = fakeFeature; + control.vertices = 'previous normal'; + control.virtualVertices = 'previous virtual'; + control.dragComplete(); + t.eq(fakeFeature.state, OpenLayers.State.UPDATE, "feature state set to UPDATE"); + + control.destroy(); + + // layer.destroy() will call removeFeatures with an empty array, make + // removeFeatures reference an empty function to prevent the above + // test to fail + layer.removeFeatures = function(verts) {}; + layer.destroy(); + } + + function test_deactivate(t) { + t.plan(2); + var map = new OpenLayers.Map("map"); + var layer = new OpenLayers.Layer.Vector(); + map.addLayer(layer); + var control = new OpenLayers.Control.ModifyFeature(layer); + map.addControl(control); + + control.handlers.keyboard.deactivate = function() { + t.ok(true, + "control.deactivate calls deactivate on keyboard handler"); + } + control.handlers.drag.deactivate = function() { + t.ok(true, + "control.deactivate calls deactivate on drag handler"); + } + control.active = true; + control.deactivate(); + + control.handlers.keyboard.deactivate = OpenLayers.Handler.Keyboard.prototype.deactivate; + control.handlers.drag.deactivate = OpenLayers.Handler.Drag.prototype.deactivate; + map.destroy(); + } + + function test_onModificationStart(t) { + t.plan(5); + var map = new OpenLayers.Map("map"); + var layer = new OpenLayers.Layer.Vector(null, { + styleMap: new OpenLayers.StyleMap({ + "vertex": new OpenLayers.Style({foo: "bar"}) + }, {extendDefault: false}) + }); + map.addLayer(layer); + var control = new OpenLayers.Control.ModifyFeature(layer); + map.addControl(control); + control.activate(); + + // make sure onModificationStart is called on feature selection + var testFeature = new OpenLayers.Feature.Vector( + OpenLayers.Geometry.fromWKT("LINESTRING(3 4,10 50,20 25)") + ); + layer.addFeatures([testFeature]); + control.onModificationStart = function(feature) { + t.eq(feature.id, testFeature.id, + "onModificationStart called with the right feature"); + }; + control.selectFeature(testFeature); + + // make sure styles are set correctly from default style + t.eq(control.virtualStyle, OpenLayers.Util.applyDefaults({ + strokeOpacity: 0.3, + fillOpacity: 0.3 + }, OpenLayers.Feature.Vector.style["default"]), "virtual style set correctly"); + var vertex = layer.features[layer.features.length-1]; + t.eq(vertex.renderIntent, null, "vertex style set correctly - uses default style"); + control.unselectFeature(testFeature); + + // make sure styles are set correctly with vertexRenderIntent + control = new OpenLayers.Control.ModifyFeature(layer, {vertexRenderIntent: "vertex"}); + map.addControl(control); + control.activate(); + control.selectFeature(testFeature); + t.eq(control.virtualStyle, { + strokeOpacity: 0.3, + fillOpacity: 0.3, + foo: "bar" + }, "virtual style set correctly"); + var vertex = layer.features[layer.features.length-1]; + t.eq(vertex.renderIntent, "vertex", "vertex style set correctly - uses 'vertex' renderIntent"); + control.unselectFeature(testFeature); + + map.destroy(); + } + + function test_onModification(t) { + t.plan(3); + var map = new OpenLayers.Map("map"); + var layer = new OpenLayers.Layer.Vector(); + map.addLayer(layer); + var control = new OpenLayers.Control.ModifyFeature(layer); + map.addControl(control); + control.activate(); + + // make sure onModification is called on drag complete + var point = new OpenLayers.Feature.Vector( + new OpenLayers.Geometry.Point(Math.random(), Math.random()) + ); + control.feature = point; + control.onModification = function(feature) { + t.eq(feature.id, point.id, + "onModification called with the right feature on drag complete"); + }; + control.dragComplete(); + + // make sure onModification is called on vertex deletion + var poly = new OpenLayers.Feature.Vector( + new OpenLayers.Geometry.Polygon() + ); + var oldDraw = layer.drawFeature; + layer.drawFeature = function() { + return; + }; + control.feature = poly; + control.vertices = [point]; + layer.events.on({"featuremodified": function(event) { + t.eq(event.feature.id, poly.id, "featuremodified triggered"); + }}); + + control.onModification = function(feature) { + t.eq(feature.id, poly.id, + "onModification called with the right feature on vertex delete"); + }; + point.geometry.parent = poly.geometry; + origGetFeatureFromEvent = layer.getFeatureFromEvent; + layer.getFeatureFromEvent = function() { return point; }; + control.handleKeypress({keyCode:46}); + layer.drawFeature = oldDraw; + layer.getFeatureFromEvent = origGetFeatureFromEvent; + + map.destroy(); + } + + function test_onModificationEnd(t) { + t.plan(3); + var map = new OpenLayers.Map("map"); + var layer = new OpenLayers.Layer.Vector(); + map.addLayer(layer); + var control = new OpenLayers.Control.ModifyFeature(layer); + map.addControl(control); + control.activate(); + + // make sure onModificationEnd is called on unselect feature + var testFeature = new OpenLayers.Feature.Vector( + new OpenLayers.Geometry.Point(Math.random(), Math.random()) + ); + layer.events.on({"afterfeaturemodified": function(event) { + t.eq(event.feature.id, testFeature.id, "afterfeaturemodified triggered"); + t.eq(event.modified, false, "afterfeaturemodified event given proper modified property (false - feature was not modified in this case)"); + }}); + control.onModificationEnd = function(feature) { + t.eq(feature.id, testFeature.id, + "onModificationEnd called with the right feature"); + }; + control.unselectFeature(testFeature); + + map.destroy(); + } + + function test_events(t) { + t.plan(2); + var map = new OpenLayers.Map("map"); + var layer = new OpenLayers.Layer.Vector(); + map.addLayer(layer); + var control = new OpenLayers.Control.ModifyFeature(layer); + map.addControl(control); + control.activate(); + + // make sure onModificationStart is called on feature selection + var testFeature = new OpenLayers.Feature.Vector( + new OpenLayers.Geometry.Point(Math.random(), Math.random()) + ); + + // test that beforefeatureselected is triggered + function handle_beforefeatureselected(event) { + t.ok(event.feature == testFeature, "beforefeatureselected called with the correct feature"); + } + layer.events.on({ + "beforefeatureselected": handle_beforefeatureselected + }); + layer.events.triggerEvent("beforefeatureselected", { + feature: testFeature + }); + layer.events.un({ + "beforefeatureselected": handle_beforefeatureselected + }); + + // test that beforefeatureselected is triggered + function handle_featureselected(event) { + t.ok(event.feature == testFeature, "featureselected called with the correct feature"); + } + layer.events.on({ + "featureselected": handle_featureselected + }); + layer.events.triggerEvent("featureselected", { + feature: testFeature + }); + layer.events.un({ + "featureselected": handle_featureselected + }); + + map.destroy(); + } + + function test_standalone(t) { + + t.plan(17); + var map = new OpenLayers.Map("map"); + var layer = new OpenLayers.Layer.Vector(); + + var f1 = new OpenLayers.Feature.Vector( + OpenLayers.Geometry.fromWKT("LINESTRING(3 4,10 50,20 25)") + ); + var f2 = new OpenLayers.Feature.Vector( + OpenLayers.Geometry.fromWKT("POLYGON((1 1,5 1,5 5,1 5,1 1),(2 2, 3 2, 3 3, 2 3,2 2))") + ); + var f3 = new OpenLayers.Feature.Vector( + OpenLayers.Geometry.fromWKT("POINT(10 15)") + ); + var f4 = new OpenLayers.Feature.Vector( + OpenLayers.Geometry.fromWKT("POINT(15 10)") + ); + layer.addFeatures([f1, f2, f3, f4]); + + map.addLayer(layer); + var control = new OpenLayers.Control.ModifyFeature(layer, {standalone: true}); + map.addControl(control); + + var log = []; + layer.events.on({ + beforefeaturemodified: function(evt) { + layer.events.unregister("beforefeaturemodified", this, arguments.callee); + log.push(evt); + }, + featuremodified: function(evt) { + log.push(evt); + }, + afterfeaturemodified: function(evt) { + log.push(evt); + } + }); + + // activate control + control.activate(); + t.eq(control.active, true, "[activate] control activated"); + + // manually select feature for editing + control.selectFeature(f1); + t.eq(log.length, 1, "[select f1] beforefeaturemodified triggered"); + t.ok(control.feature === f1, "[select f1] control.feature set to f1"); + log = [] + + // manually unselect feature for editing + control.unselectFeature(f1); + t.eq(control.feature, null, "[unselect f1] control.feature set to null"); + t.eq(log.length, 1, "[unselect f1] event logged"); + t.eq(log[0].type, "afterfeaturemodified", "[unselect f1] afterfeaturemodified triggered"); + t.ok(log[0].feature === f1, "[unselect f1] correct feature"); + t.eq(log[0].modified, false, "[unselect f1] feature not actually modified"); + + // clear log and select new feature for editing + log = []; + control.selectFeature(f2); + t.ok(control.feature === f2, "[select f2] control.feature set to f2"); + + // deactivate control and confirm feature is unselected + control.deactivate(); + t.eq(log.length, 1, "[deactivate] event logged"); + t.eq(log[0].type, "afterfeaturemodified", "[deactivate] afterfeaturemodified triggered"); + t.ok(log[0].feature === f2, "[deactivate] correct feature"); + t.eq(log[0].modified, false, "[deactivate] feature not actually modified"); + + // select the polygon feature to make sure that we can drag vertices and + // virtual vertices + control.selectFeature(f2); + var origGetFeatureFromEvent = layer.getFeatureFromEvent; + layer.getFeatureFromEvent = function() { return control.vertices[0]; }; + control.handlers.drag.callbacks.down.call(control, new OpenLayers.Pixel(0,0)); + t.ok(control.vertex === control.vertices[0], "can drag vertex of feature f2"); + t.ok(control.feature === f2, "dragging a vertex does not change the selected feature"); + layer.getFeatureFromEvent = function() { return control.virtualVertices[0]; }; + control.handlers.drag.callbacks.down.call(control, new OpenLayers.Pixel(0,0)); + t.ok(control.vertex === control.virtualVertices[0], "can drag virtual vertex of feature f2"); + t.ok(control.feature === f2, "dragging a vertex does not change the selected feature"); + layer.getFeatureFromEvent = origGetFeatureFromEvent; + control.deactivate(); + + map.destroy(); + + } + + function test_setFeatureState(t) { + t.plan(4); + var map = new OpenLayers.Map("map"); + var layer = new OpenLayers.Layer.Vector("vector", {isBaseLayer: true}); + map.addLayer(layer); + var feature = new OpenLayers.Feature.Vector(new OpenLayers.Geometry.Point(1,2)); + layer.addFeatures([feature]); + var control = new OpenLayers.Control.ModifyFeature(layer, {standalone: true}); + map.addControl(control); + + control.selectFeature(feature); + var originalGeometry = feature.geometry; + + t.ok(control._originalGeometry, "original geometry stored for later use in setFeatureState"); + + feature.geometry = new OpenLayers.Geometry.Point(2,3); + control.modified = true; + control.setFeatureState(); + + t.eq(feature.state, OpenLayers.State.UPDATE, "feature state set to UPDATE"); + t.geom_eq(feature.modified.geometry, originalGeometry, "original geometry stored on the modified property"); + t.eq(control._originalGeometry, undefined, "original geometry deleted once it is set on the modified property"); + } + + function test_createVertices(t) { + t.plan(2); + var layer = new OpenLayers.Layer.Vector(); + var control = new OpenLayers.Control.ModifyFeature(layer, { + createVertices: false + }); + var line = new OpenLayers.Geometry.LineString([ + new OpenLayers.Geometry.Point(5, 6), + new OpenLayers.Geometry.Point(7, 8), + new OpenLayers.Geometry.Point(9, 10) + ]); + control.feature = new OpenLayers.Feature.Vector(line); + control.resetVertices(); + + t.eq(control.vertices.length, 3, "Correct vertices length with createVertices is false"); + t.eq(control.virtualVertices.length, 0, "Correct virtual vertices length with createVertices is false"); + control.destroy(); + } + + function test_moveLayerToTop_moveLayerBack(t) { + t.plan(2); + var map = new OpenLayers.Map("map"); + var layer1 = new OpenLayers.Layer.Vector(); + var layer2 = new OpenLayers.Layer.Vector(); + map.addLayers([layer1, layer2]); + var control = new OpenLayers.Control.ModifyFeature(layer1); + map.addControl(control); + control.activate(); + t.ok(layer1.div.style.zIndex > layer2.div.style.zIndex, "layer raised so events don't get swallowed"); + control.deactivate(); + t.ok(layer1.div.style.zIndex < layer2.div.style.zIndex, 'layer order restored on deactivation'); + } + + </script> +</head> +<body> + <div id="map" style="width: 400px; height: 250px;"/> +</body> +</html> diff --git a/misc/openlayers/tests/Control/MousePosition.html b/misc/openlayers/tests/Control/MousePosition.html new file mode 100644 index 0000000..0695e16 --- /dev/null +++ b/misc/openlayers/tests/Control/MousePosition.html @@ -0,0 +1,109 @@ +<html> +<head> + <script src="../OLLoader.js"></script> + <script type="text/javascript"> + var map, control; + function test_initialize (t) { + t.plan( 2 ); + + control = new OpenLayers.Control.MousePosition(); + t.ok( control instanceof OpenLayers.Control.MousePosition, "new OpenLayers.Control returns object" ); + t.eq( control.displayClass, "olControlMousePosition", "displayClass is correct" ); + } + function test_destroy(t) { + t.plan(1); + + var map = new OpenLayers.Map('map'); + var control = new OpenLayers.Control.MousePosition(); + map.addControl(control); + + var listeners = map.events.listeners.mousemove.length; + control.destroy(); + + t.eq(map.events.listeners.mousemove.length, listeners - 1, "mousemove event is unregistered"); + map.destroy(); + } + function test_addControl(t) { + t.plan(4); + + var map = new OpenLayers.Map('map'); + var control = new OpenLayers.Control.MousePosition(); + map.addControl(control); + + t.ok(control.map === map, "Control.map is set to the map object"); + t.ok(map.controls[map.controls.length - 1] === control, "map.controls contains control"); + t.eq(parseInt(control.div.style.zIndex), map.Z_INDEX_BASE['Control'] + 5, "Control div zIndexed properly" ); + t.eq(parseInt(map.viewPortDiv.lastChild.style.zIndex), map.Z_INDEX_BASE['Control'] + 5, "Viewport div contains control div"); + map.destroy(); + } + function test_redraw_noLayer_displayProjection(t) { + t.plan(4); + var control = new OpenLayers.Control.MousePosition({'emptyString':''}); + var map = new OpenLayers.Map('map'); + map.addControl(control); + var control2 = new OpenLayers.Control.MousePosition(); + map.addControl(control2); + t.eq(control2.emptyString, null, "Emptystring is null"); + t.eq(control.div.innerHTML, "", "innerHTML set correctly"); + control.redraw({'xy': new OpenLayers.Pixel(10,10)}); + control.redraw({'xy': new OpenLayers.Pixel(12,12)}); + t.eq(control.div.innerHTML, "", "innerHTML set correctly"); + var l = new OpenLayers.Layer('name', {'isBaseLayer': true}); + map.addLayer(l); + map.zoomToMaxExtent(); + control.redraw({'xy': new OpenLayers.Pixel(10,10)}); + control.redraw({'xy': new OpenLayers.Pixel(12,12)}); + t.eq(control.div.innerHTML, "-175.78125, 85.78125", "innerHTML set correctly when triggered."); + map.destroy(); + } + function test_formatOutput(t) { + t.plan(1); + var control = new OpenLayers.Control.MousePosition({ + prefix: 'prefix', + suffix: 'suffix', + separator: 'separator', + numDigits: 3 + }); + var lonlat = new OpenLayers.LonLat(0.75699, 0.37365); + var val = control.formatOutput(lonlat); + t.eq(val, 'prefix0.757separator0.374suffix', 'formatOutput correctly formats the mouse position output'); + } + function test_deactivate(t) { + t.plan(4); + var map = new OpenLayers.Map('map'); + var layer = new OpenLayers.Layer(null, {isBaseLayer: true}); + map.addLayer(layer); + map.zoomToMaxExtent(); + // Auxiliary function + function trigger(type, x, y) { + map.events.triggerEvent(type, { + xy: new OpenLayers.Pixel(x, y) + }) + }; + + var control = new OpenLayers.Control.MousePosition(); + map.addControl(control); + trigger("mousemove", 0, 0); + + trigger("mousemove", 0, 1); + t.ok(control.div.innerHTML != "", + "Shows the position after add control (with autoActivate) and move"); + control.deactivate(); + t.ok(control.div.innerHTML == "", + "Position is not displayed after deactivate and move"); + trigger("mousemove", 0, 2); + t.ok(control.div.innerHTML == "", + "Position is not displayed after move when deactivate"); + control.activate(); + trigger("mousemove", 0, 3); + t.ok(control.div.innerHTML != "", + "Shows the position after activate and move"); + + map.destroy(); + } + </script> +</head> +<body> + <div id="map" style="width: 1024px; height: 512px;"/> +</body> +</html> diff --git a/misc/openlayers/tests/Control/NavToolbar.html b/misc/openlayers/tests/Control/NavToolbar.html new file mode 100644 index 0000000..9b3bbec --- /dev/null +++ b/misc/openlayers/tests/Control/NavToolbar.html @@ -0,0 +1,45 @@ +<html> +<head> + <script src="../OLLoader.js"></script> + <script type="text/javascript"> + var map; + function test_Control_NavToolbar_constructor (t) { + t.plan( 4 ); + control = new OpenLayers.Control.NavToolbar(); + t.ok( control instanceof OpenLayers.Control.NavToolbar, "new OpenLayers.Control.NavToolbar returns object" ); + t.eq( control.displayClass, "olControlNavToolbar", "displayClass is correct" ); + t.ok( control.controls[0] instanceof OpenLayers.Control.Navigation, "NavToolbar contains Control.Navigation object" ); + t.ok( control.controls[1] instanceof OpenLayers.Control.ZoomBox, "NavToolbar contains Control.ZoomBox object" ); + } + function test_Control_NavToolbar_addControl (t) { + t.plan( 6 ); + map = new OpenLayers.Map('map'); + control = new OpenLayers.Control.NavToolbar(); + t.ok( control instanceof OpenLayers.Control.NavToolbar, "new OpenLayers.Control.NavToolbar returns object" ); + t.ok( map instanceof OpenLayers.Map, "new OpenLayers.Map creates map" ); + map.addControl(control); + t.ok( control.map === map, "Control.map is set to the map object" ); + t.ok( map.controls[4] === control, "map.controls contains control" ); + t.eq( parseInt(control.div.style.zIndex), map.Z_INDEX_BASE['Control'] + 7, "Control div zIndexed properly" ); + t.eq( parseInt(map.viewPortDiv.lastChild.style.zIndex), map.Z_INDEX_BASE['Control'] + 7, "Viewport div contains control div" ); + // t.eq( control.div.style.top, "6px", "Control div top located correctly by default"); + + } + + function test_Control_NavToolbar_defaultControl (t) { + t.plan( 1 ); + var map = new OpenLayers.Map('map'); + + var nav = new OpenLayers.Control.NavToolbar(); + map.addControl(nav); + + t.eq(nav.controls[0].active, true, "First control is active" ); + + map.destroy(); + } + </script> +</head> +<body> + <div id="map" style="width: 1024px; height: 512px;"/> +</body> +</html> diff --git a/misc/openlayers/tests/Control/Navigation.html b/misc/openlayers/tests/Control/Navigation.html new file mode 100644 index 0000000..e73ee42 --- /dev/null +++ b/misc/openlayers/tests/Control/Navigation.html @@ -0,0 +1,200 @@ +<html> +<head> + <script src="../OLLoader.js"></script> + <script type="text/javascript"> + + function test_Control_Navigation_constructor (t) { + t.plan( 3 ); + var temp = OpenLayers.Control.prototype.initialize; + OpenLayers.Control.prototype.initialize = function() { + t.ok(true, "OpenLayers.Control's constructor called"); + }; + + var control = new OpenLayers.Control.Navigation(); + t.ok( control instanceof OpenLayers.Control.Navigation, "new OpenLayers.Control returns object" ); + + t.ok( !control.handleRightClicks, "'handleRightClicks' property is disabled by default"); + + OpenLayers.Control.prototype.initialize = temp; + } + + function test_draw(t) { + t.plan(5); + var map = new OpenLayers.Map({div: 'map', controls: []}); + var control = new OpenLayers.Control.Navigation(); + map.addControl(control); + t.ok(control.handlers.click instanceof OpenLayers.Handler.Click, + "click handler set in instance"); + t.ok(control.dragPan instanceof OpenLayers.Control.DragPan, + "drag pan control set in instance"); + t.ok(control.zoomBox instanceof OpenLayers.Control.ZoomBox, + "zoom box control set in instance"); + t.ok(control.handlers.wheel instanceof OpenLayers.Handler.MouseWheel, + "mousewheel handler set in instance"); + t.ok(control.pinchZoom instanceof OpenLayers.Control.PinchZoom, + "pinch zoom control set in instance"); + map.destroy(); + } + + function test_Control_Navigation_destroy (t) { + t.plan(12); + + var temp = OpenLayers.Control.prototype.destroy; + OpenLayers.Control.prototype.destroy = function() { + t.ok(true, "OpenLayers.Control's destroy called"); + temp.call(this); + }; + + var control = { + events: { + destroy: function() { + t.ok(true, "events destroyed"); + } + }, + 'deactivate': function() { + t.ok(true, "navigation control deactivated before being destroyed"); + }, + 'dragPan': { + 'destroy': function() { + t.ok(true, "dragPan destroyed"); + } + }, + 'zoomBox': { + 'destroy': function() { + t.ok(true, "zoomBox destroyed"); + } + }, + 'pinchZoom': { + 'destroy': function() { + t.ok(true, "pinchZoom destroyed"); + } + }, + handlers: { + 'wheel': { + 'destroy': function() { + t.ok(true, "wheelHandler destroyed"); + } + }, + 'click': { + 'destroy': function() { + t.ok(true, "clickHandler destroyed"); + } + } + } + }; + + //this will also trigger one test by calling OpenLayers.Control's destroy + // and three more for the destruction of dragPan, zoomBox, and wheelHandler + OpenLayers.Control.Navigation.prototype.destroy.apply(control, []); + + t.eq(control.dragPan, null, "'dragPan' set to null"); + t.eq(control.zoomBox, null, "'zoomBox' set to null"); + t.eq(control.pinchZoom, null, "'pinchZoom' set to null"); + t.eq(control.handlers, null, "handlers set to null"); + + OpenLayers.Control.prototype.destroy = temp; + } + + function test_Control_Navigation_disableZoomBox(t) { + t.plan(2); + var nav = new OpenLayers.Control.Navigation(); + var zb = new OpenLayers.Control.ZoomBox({}); + nav.zoomBox = zb; + zb.activate(); + nav.disableZoomBox(); + t.eq(nav.zoomBoxEnabled, false, "zoom box deactivated"); + t.eq(zb.active, false, "zoom box control deactivated"); + } + + function test_Control_Navigation_enableZoomBox(t) { + t.plan(2); + var nav = new OpenLayers.Control.Navigation(); + var zb = new OpenLayers.Control.ZoomBox({}); + nav.zoomBox = zb; + nav.active = true; + nav.enableZoomBox(); + t.eq(nav.zoomBoxEnabled, true, "zoom box activated"); + t.eq(zb.active, true, "zoom box control activated"); + } + + function test_Control_Navigation_disableZoomWheel(t) { + t.plan(2); + var nav = new OpenLayers.Control.Navigation(); + var wheel = new OpenLayers.Handler.MouseWheel(nav, {}); + nav.handlers.wheel = wheel; + wheel.register = function() {}; + wheel.unregister = function() {}; + wheel.activate(); + nav.disableZoomWheel(); + t.eq(nav.zoomWheelEnabled, false, "mouse wheel deactivated"); + t.eq(wheel.active, false, "mouse wheel handler deactivated"); + } + + function test_Control_Navigation_enableZoomWheel(t) { + t.plan(2); + var nav = new OpenLayers.Control.Navigation({zoomWheelEnabled: false}); + nav.active = true; + var wheel = new OpenLayers.Handler.MouseWheel(nav, {}); + wheel.register = function() {}; + wheel.unregister = function() {}; + nav.handlers.wheel = wheel; + nav.enableZoomWheel(); + t.eq(nav.zoomWheelEnabled, true, "mouse wheel activated"); + t.eq(wheel.active, true, "mouse wheel handler activated"); + } + + function test_touches_zoom(t) { + t.plan(3); + var nav = new OpenLayers.Control.Navigation({zoomWheelEnabled: false}); + var map = new OpenLayers.Map({ + div: "map", + zoomMethod: null, + controls: [nav], + layers: [ + new OpenLayers.Layer(null, {isBaseLayer: true}) + ], + center: new OpenLayers.LonLat(0, 0), + zoom: 3 + }); + t.eq(map.getZoom(), 3, "map zoom starts at 3"); + nav.handlers.click.callback("click", [{lastTouches: ["foo", "bar"]}]); + t.eq(map.getZoom(), 2, "map zooms out with a two touch tap"); + nav.handlers.click.callback("click", [{}]); + t.eq(map.getZoom(), 2, "map doesn't do anything with click"); + + map.destroy(); + } + + function test_documentDrag(t) { + + t.plan(2); + + /** + * These tests confirm that the documentDrag property is false by + * default and is passed on to the DragPan control. Tests of panning + * while dragging outside the viewport should go in the DragPan tests. + * Tests of the document events and appropriate callbacks from the + * handler should go in the Drag handler tests. + */ + + var nav = new OpenLayers.Control.Navigation(); + t.eq(nav.documentDrag, false, "documentDrag false by default"); + // nav.destroy(); // fails if called before draw + + var map = new OpenLayers.Map({ + div: document.body, + controls: [new OpenLayers.Control.Navigation({documentDrag: true})] + }); + nav = map.controls[0]; + + t.eq(nav.dragPan.documentDrag, true, "documentDrag set on the DragPan control"); + map.destroy(); + + } + + </script> +</head> +<body> + <div id="map" style="width: 256px; height: 256px"></div> +</body> +</html> diff --git a/misc/openlayers/tests/Control/NavigationHistory.html b/misc/openlayers/tests/Control/NavigationHistory.html new file mode 100644 index 0000000..c992ff2 --- /dev/null +++ b/misc/openlayers/tests/Control/NavigationHistory.html @@ -0,0 +1,245 @@ +<html> +<head> + <script src="../OLLoader.js"></script> + <script type="text/javascript"> + + function test_initialize(t) { + t.plan(4); + control = new OpenLayers.Control.NavigationHistory(); + t.ok(control instanceof OpenLayers.Control.NavigationHistory, + "constructor returns correct instance"); + t.eq(control.displayClass, "olControlNavigationHistory", + "displayClass is correct"); + t.ok(control.next instanceof OpenLayers.Control.Button, + "constructor creates next control"); + t.ok(control.previous instanceof OpenLayers.Control.Button, + "constructor creates previous control"); + } + + function test_destroy(t) { + t.plan(2); + control = new OpenLayers.Control.NavigationHistory(); + control.next.destroy = function() { + t.ok(true, "destroy calls next.destroy"); + } + control.previous.destroy = function() { + t.ok(true, "destroy calls previous.destroy"); + } + control.destroy(); + } + + function test_previous(t) { + var numStates = 10; + + t.plan( + numStates * 3 // for lon, lat, zoom + + 3 // for confirming that previous with empty stack works + ); + + var history = new Array(numStates); + for(var i=0; i<numStates; ++i) { + history[i] = { + center: new OpenLayers.LonLat( + (i * 360 / numStates) - 180, (i * 180 / numStates) - 90 + ), + zoom: i + }; + } + + var map = new OpenLayers.Map("map"); + var layer = new OpenLayers.Layer( + "test", {isBaseLayer: true} + ); + map.addLayer(layer); + var control = new OpenLayers.Control.NavigationHistory(); + map.addControl(control); + + // set previous states + for(i=0; i<numStates; ++i) { + map.setCenter(history[i].center, history[i].zoom); + } + // test previous states + for(i=numStates-1; i>=0; --i) { + t.eq(map.getCenter().lon, history[i].center.lon, "(step " + i + ") lon correct"); + t.eq(map.getCenter().lat, history[i].center.lat, "(step " + i + ") lat correct"); + t.eq(map.getZoom(), history[i].zoom, "(step " + i + ") zoom correct"); + control.previous.trigger(); + } + // test previous with empty stack + t.eq(map.getCenter().lon, history[0].center.lon, "(step 0 again) lon correct"); + t.eq(map.getCenter().lat, history[0].center.lat, "(step 0 again) lat correct"); + t.eq(map.getZoom(), history[0].zoom, "(step 0 again) zoom correct"); + } + + function test_next(t) { + var numStates = 10; + + t.plan( + numStates * 3 // for lon, lat, zoom + + 3 // for confirming that next with empty stack works + ); + + var history = new Array(numStates); + for(var i=0; i<numStates; ++i) { + history[i] = { + center: new OpenLayers.LonLat( + (i * 360 / numStates) - 180, (i * 180 / numStates) - 90 + ), + zoom: i + }; + } + + var map = new OpenLayers.Map("map"); + var layer = new OpenLayers.Layer( + "test", {isBaseLayer: true} + ); + map.addLayer(layer); + var control = new OpenLayers.Control.NavigationHistory(); + map.addControl(control); + + // set previous states + for(i=0; i<numStates; ++i) { + map.setCenter(history[i].center, history[i].zoom); + } + // set next states + for(i=numStates-1; i>=0; --i) { + control.previous.trigger(); + } + // test next states + for(i=0; i<numStates; ++i) { + t.eq(map.getCenter().lon, history[i].center.lon, "(step " + i + ") lon correct"); + t.eq(map.getCenter().lat, history[i].center.lat, "(step " + i + ") lat correct"); + t.eq(map.getZoom(), history[i].zoom, "(step " + i + ") zoom correct"); + control.next.trigger(); + } + // test next with empty stack + t.eq(map.getCenter().lon, history[numStates-1].center.lon, "(step " + (numStates-1) + " again) lon correct"); + t.eq(map.getCenter().lat, history[numStates-1].center.lat, "(step " + (numStates-1) + " again) lat correct"); + t.eq(map.getZoom(), history[numStates-1].zoom, "(step " + (numStates-1) + " again) zoom correct"); + } + + function test_limit(t) { + var numStates = 10; + var limit = 3; + + t.plan( + numStates * 6 // for previous & next lon, lat, zoom + ); + + var history = new Array(numStates); + for(var i=0; i<numStates; ++i) { + history[i] = { + center: new OpenLayers.LonLat( + (i * 360 / numStates) - 180, (i * 180 / numStates) - 90 + ), + zoom: i + }; + } + + var map = new OpenLayers.Map("map"); + var layer = new OpenLayers.Layer( + "test", {isBaseLayer: true} + ); + map.addLayer(layer); + var control = new OpenLayers.Control.NavigationHistory({limit: limit}); + map.addControl(control); + + // set previous states + for(i=0; i<numStates; ++i) { + map.setCenter(history[i].center, history[i].zoom); + } + // test previous states (only up to limit should work) + var state; + for(i=numStates-1; i>=0; --i) { + state = Math.max(i, numStates - limit - 1); + t.eq(map.getCenter().lon, history[state].center.lon, "(previous step " + i + ") lon correct: state " + state); + t.eq(map.getCenter().lat, history[state].center.lat, "(previous step " + i + ") lat correct: state " + state); + t.eq(map.getZoom(), history[state].zoom, "(previous step " + i + ") zoom correct: state " + state); + control.previous.trigger(); + } + // test next states + for(i=0; i<numStates; ++i) { + state = Math.min(numStates - 1, numStates - limit - 1 + i); + t.eq(map.getCenter().lon, history[state].center.lon, "(next step " + i + ") lon correct: state " + state); + t.eq(map.getCenter().lat, history[state].center.lat, "(next step " + i + ") lat correct: state " + state); + t.eq(map.getZoom(), history[state].zoom, "(next step " + i + ") zoom correct: state " + state); + control.next.trigger(); + } + + } + + function test_clear(t) { + t.plan(7); + var map = new OpenLayers.Map("map", {zoomMethod: null}); + var layer = new OpenLayers.Layer( + "test", {isBaseLayer: true} + ); + map.addLayer(layer); + map.zoomToMaxExtent(); + + var control = new OpenLayers.Control.NavigationHistory(); + map.addControl(control); + + t.ok(!control.previous.active, "previous control not active"); + t.ok(!control.next.active, "next control not active"); + + map.zoomTo(4); + t.ok(control.previous.active, "previous control is active after a move"); + t.ok(!control.next.active, "next control is not active after a move"); + + control.clear(); + t.eq(control.previousStack.length + control.nextStack.length, 0, "stacks are empty after a clear"); + t.ok(!control.previous.active, "previous control not active after a clear"); + t.ok(!control.next.active, "next control not active after a clear"); + + control.destroy(); + } + + function test_reprojection(t) { + t.plan(2); + var map = new OpenLayers.Map("map"); + var layer = new OpenLayers.Layer( + "test", {isBaseLayer: true} + ); + map.addLayer(layer); + map.zoomToMaxExtent(); + + var control = new OpenLayers.Control.NavigationHistory(); + map.addControl(control); + + map.zoomTo(4); + var bounds = map.getExtent().clone(); + var expected = bounds.transform(new OpenLayers.Projection('EPSG:4326'), + new OpenLayers.Projection('EPSG:900913')); + // change the projection to EPSG:900913 + var projSettings = { + units: "m", + maxExtent: new OpenLayers.Bounds(-20037508, -20037508, 20037508, 20037508), + maxResolution: 156543.0339 + }; + map.setOptions(projSettings); + map.projection = 'EPSG:900913'; + delete projSettings.maxResolution; + projSettings.projection = new OpenLayers.Projection('EPSG:900913'); + layer.addOptions(projSettings); + layer.initResolutions(); + + map.zoomTo(7); + + // go back one in the history + control.previous.trigger(); + + t.eq(map.getExtent().left.toFixed(3), expected.left.toFixed(3), "The extent [left] is reprojected correctly"); + t.eq(map.getExtent().right.toFixed(3), expected.right.toFixed(3), "The extent [right] is reprojected correctly"); + // top and bottom cannot be checked here since in EPSG:900913 the extent is not a rectangle so they are adjusted. + + control.destroy(); + + } + + </script> +</head> +<body> + <div id="map" style="width: 100px; height: 100px;"/> +</body> +</html> diff --git a/misc/openlayers/tests/Control/OverviewMap.html b/misc/openlayers/tests/Control/OverviewMap.html new file mode 100644 index 0000000..a5a598d --- /dev/null +++ b/misc/openlayers/tests/Control/OverviewMap.html @@ -0,0 +1,266 @@ +<html> +<head> + <script src="../OLLoader.js"></script> + <script type="text/javascript"> + var map, control; + + function test_initialize(t) { + t.plan( 2 ); + + control = new OpenLayers.Control.OverviewMap(); + t.ok( control instanceof OpenLayers.Control.OverviewMap, + "new OpenLayers.Control.OverviewMap returns object" ); + t.eq( control.displayClass, + "olControlOverviewMap", "displayClass is correct" ); + } + + function test_divs_title(t) { + t.plan(2); + + control = new OpenLayers.Control.OverviewMap({ + maximizeTitle: "maximize title", + minimizeTitle: "minimize title" + }); + map = new OpenLayers.Map('map', { + layers: [new OpenLayers.Layer("layer", {isBaseLayer: true})], + controls: [control] + }); + map.zoomToMaxExtent(); + t.eq(control.maximizeDiv.title, "maximize title", "maximizeDiv.title is correct"); + t.eq(control.minimizeDiv.title, "minimize title", "minimizeDiv.title is correct"); + map.destroy(); + } + + function test_setMap(t) { + t.plan(4); + + var setMapTest = function(map) { + t.ok(true, + "Handler.setMap called for " + this.CLASS_NAME); + this.map = map; + }; + var drag_setMap = OpenLayers.Handler.Drag.prototype.setMap; + OpenLayers.Handler.Drag.prototype.setMap = setMapTest; + var click_setMap = OpenLayers.Handler.Click.prototype.setMap; + OpenLayers.Handler.Click.prototype.setMap = setMapTest; + + map = new OpenLayers.Map('map', { + layers : [new OpenLayers.Layer("layer", {isBaseLayer: true})], + controls: [] + }); + control = new OpenLayers.Control.OverviewMap(); + + map.addControl(control); + + map.zoomToMaxExtent(); + t.eq(control.handlers.drag.map.id, control.ovmap.id, + "drag.map is correct"); + t.eq(control.handlers.click.map.id, control.ovmap.id, + "click.map is correct"); + + map.destroy(); + OpenLayers.Handler.Drag.prototype.setMap = drag_setMap; + OpenLayers.Handler.Click.prototype.setMap = click_setMap; + } + + function test_destroy(t) { + t.plan(6); + + // set up + + var log_drag = [], log_click = [], control; + + map = new OpenLayers.Map('map'); + map.addLayer(new OpenLayers.Layer("layer", {isBaseLayer: true})); + + control = new OpenLayers.Control.OverviewMap(); + map.addControl(control); + + map.zoomToMaxExtent(); + + control.handlers.drag.destroy = function() { + log_drag.push({"map": !!this.map.events}); + }; + control.handlers.click.destroy = function() { + log_click.push({"map": !!this.map.events}); + }; + + // test + + control.destroy(); + t.eq(log_drag.length, 2, + "destroy() destroys drag handler twice, expected"); + if (log_drag.length == 2) { + t.eq(log_drag[0].map, true, + "destroy() destroys drag handler before ovmap is destroyed (0)"); + t.eq(log_drag[1].map, false, + "destroy() destroys drag handler after ovmap is destroyed (1)"); + } + t.eq(log_click.length, 2, + "destroy() destroys click handler twice, expected"); + if (log_click.length == 2) { + t.eq(log_click[0].map, true, + "destroy() destroys click handler before ovmap is destroyed (0)"); + t.eq(log_click[1].map, false, + "destroy() destroys click handler after ovmap is destroyed (1)"); + } + + // tear down + map.destroy(); + } + + function test_addControl (t) { + t.plan( 6 ); + map = new OpenLayers.Map('map'); + control = new OpenLayers.Control.OverviewMap(); + t.ok( control instanceof OpenLayers.Control.OverviewMap, + "new OpenLayers.Control.OverviewMap returns object" ); + t.ok( map instanceof OpenLayers.Map, + "new OpenLayers.Map creates map" ); + map.addControl(control); + t.ok( control.map === map, + "Control.map is set to the map object" ); + t.ok( map.controls[4] === control, + "map.controls contains control" ); + t.eq( parseInt(control.div.style.zIndex), map.Z_INDEX_BASE['Control'] + 5, + "Control div zIndexed properly" ); + t.eq( parseInt(map.viewPortDiv.lastChild.style.zIndex), map.Z_INDEX_BASE['Control'] + 5, + "Viewport div contains control div" ); + + map.destroy(); + } + + function test_control_events (t) { + t.plan( 10 ); + + map = new OpenLayers.Map('map', { + // when we recenter, don't waste time animating the panning + // without this, the test fails in Firefox 10.0.1 on Linux + panMethod: null, + layers: [ new OpenLayers.Layer('Test Layer', {isBaseLayer: true}) ] + }); + + control = new OpenLayers.Control.OverviewMap(); + map.addControl(control, new OpenLayers.Pixel(20,20)); + + var centerLL = new OpenLayers.LonLat(-71,42); + map.setCenter(centerLL, 11); + + t.delay_call( + 0.1, + function() { + var overviewCenter = control.ovmap.getCenter(); + var overviewZoom = control.ovmap.getZoom(); + t.eq(overviewCenter.lon, -71, + "OverviewMap center lon correct"); + t.eq(overviewCenter.lat, 42, + "OverviewMap center lat correct"); + t.eq(overviewZoom, 8, + "OverviewMap zoom correct"); + + control.mapDivClick({'xy':new OpenLayers.Pixel(5,5)}); + }, + 0.1, + function() { + var cent = map.getCenter(); + t.eq(cent.lon, -71.3515625, + "Clicking on OverviewMap has correct effect on map lon"); + t.eq(cent.lat, 42.17578125, + "Clicking on OverviewMap has correct effect on map lat"); + + control.handlers.drag = { + last: new OpenLayers.Pixel(5,5), + destroy: function() {} + }; + control.rectDrag(new OpenLayers.Pixel(15, 15)); + control.updateMapToRect(); + }, + 0.1, + function() { + var cent = map.getCenter(); + t.eq(cent.lon, -71.2734375, + "Dragging on OverviewMap has correct effect on map lon"); + t.eq(cent.lat, 42.09765625, + "Dragging on OverviewMap has correct effect on map lat"); + + map.setCenter(new OpenLayers.LonLat(0,0), 0); + var overviewCenter = control.ovmap.getCenter(); + var overviewZoom = control.ovmap.getZoom(); + t.eq(overviewCenter.lon, 0, + "OverviewMap center lon correct -- second zoom"); + t.eq(overviewCenter.lat, 0, + "OverviewMap center lat correct -- second zoom"); + t.eq(overviewZoom, 0, + "OverviewMap zoomcorrect -- second zoom"); + map.destroy(); + } + ); + } + + function test_initialize_maximized(t) { + t.plan(4); + + control = new OpenLayers.Control.OverviewMap() + map = new OpenLayers.Map('map', { + layers : [new OpenLayers.Layer("layer", {isBaseLayer: true})], + controls: [control] + }); + + t.eq(control.maximized, false, + "OverviewMap is not maximized by default"); + t.eq(control.element.style.display, 'none', + "OverviewMap.element is not visible"); + map.destroy(); + + control = new OpenLayers.Control.OverviewMap({ + maximized: true + }) + map = new OpenLayers.Map('map', { + layers : [new OpenLayers.Layer("layer", {isBaseLayer: true})], + controls: [control] + }); + t.eq(control.maximized, true, + "OverviewMap.maximized is set"); + t.eq(control.element.style.display, '', + "OverviewMap.element is visible"); + + map.destroy(); + } + + function test_custom_div(t) { + t.plan(3); + var div = document.createElement('div'); + + control = new OpenLayers.Control.OverviewMap({ + div: div + }); + + map = new OpenLayers.Map('map', { + layers : [new OpenLayers.Layer("layer", {isBaseLayer: true})], + controls: [control] + }); + + t.eq(control.maximizeDiv, null, + "OverviewMap does not create maximize div"); + t.eq(control.minimizeDiv, null, + "OverviewMap does not create minimize div"); + + var exc; + try { + control.maximizeControl(); + control.minimizeControl(); + } catch(e) { + exc = e; + } + + t.eq(exc, undefined, 'maximize and minimize do not trigger an exception'); + + map.destroy(); + } + + </script> +</head> +<body> + <div id="map" style="width: 1024px; height: 512px;"></div> +</body> +</html> diff --git a/misc/openlayers/tests/Control/Pan.html b/misc/openlayers/tests/Control/Pan.html new file mode 100644 index 0000000..0c9dfaf --- /dev/null +++ b/misc/openlayers/tests/Control/Pan.html @@ -0,0 +1,201 @@ +<!DOCTYPE html> +<html> + <head> + <script src="../OLLoader.js"></script> + <script type="text/javascript"> + +function test_Pan_constructor (t) { + t.plan( 2 ); + + // setup + var control = new OpenLayers.Control.Pan( + "Gargoyle" // the direction, here mocked up + ); + + // tests + // + t.ok( + control instanceof OpenLayers.Control.Pan, + "new OpenLayers.Control.Pan returns object" + ); + t.eq( + control.displayClass, "olControlPanGargoyle", + "displayClass is correct" + ); + + // tear down + control.destroy(); +} + +function test_Pan_type (t) { + t.plan( 1 ); + + // setup + var control = new OpenLayers.Control.Pan(); + + // tests + // + t.eq( + control.type, + OpenLayers.Control.TYPE_BUTTON, + "Pan control is of type OpenLayers.Control.TYPE_BUTTON" + ); + + // tear down + control.destroy(); +} + +function test_Pan_constants (t) { + var dirs = [ + 'North', + 'East', + 'South', + 'West' + ], + numDirs = dirs.length, + dir, uc_dir; + + t.plan(numDirs); + + for ( ; numDirs > 0; numDirs-- ) { + dir = dirs[numDirs - 1 ]; + uc_dir = dir.toUpperCase(); + + t.eq( + OpenLayers.Control.Pan[ uc_dir ], + dir, + "A constant 'OpenLayers.Control.Pan." + uc_dir + "' is defined "+ + "and has the correct value of '" + dir + "'." + ); + } +} + +function test_Pan_trigger (t) { + t.plan( 12 ); + + // set up + var controls = { + n: new OpenLayers.Control.Pan(OpenLayers.Control.Pan.NORTH), + e: new OpenLayers.Control.Pan(OpenLayers.Control.Pan.EAST), + s: new OpenLayers.Control.Pan(OpenLayers.Control.Pan.SOUTH), + w: new OpenLayers.Control.Pan(OpenLayers.Control.Pan.WEST) + }, + controlKey, control, + zoomlevel = 5, + center = new OpenLayers.LonLat(25,25), + log = { + dx: null, + dy: null + }, + map = new OpenLayers.Map("map", { + allOverlays: true, + layers: [ + new OpenLayers.Layer.Vector() + ], + center: center, + zoom: zoomlevel + }), + oldZoom; + + // overwrite native Map::pan + map.pan = function(dx, dy) { + log = { + dx: dx, + dy: dy + }; + OpenLayers.Map.prototype.pan.apply(map, arguments); + }; + + oldCenter = map.getCenter().toString(); + + for (controlKey in controls) { + if (controls.hasOwnProperty(controlKey)) { + control = controls[controlKey]; + // trigger the control; nothing should change, we aren't added yet. + control.trigger(); + + t.ok( + log.dx === null && log.dy === null, + 'Calling trigger on a non added control doesn\'t do anything.' + ); + + // reset log object + log = { + dx: null, + dy: null + }; + } + } + + // now lets add the controls, and trigger them again + for (controlKey in controls) { + if (controls.hasOwnProperty(controlKey)) { + control = controls[controlKey]; + map.addControl(control); + // trigger again, now ... + control.trigger(); + + // ... the center should change ... + t.ok( + log.dx !== null && log.dy !== null, + 'Calling trigger on an added pan control calls map.pan()... ' + ); + + // ... with sane arguments according to the passed direction. + switch (control.direction) { + case OpenLayers.Control.Pan.NORTH: + t.ok( + log.dx === 0 && log.dy < 0, + '... with sane arguments: pan north only results in ' + + 'negative delta y' + ); + break; + case OpenLayers.Control.Pan.SOUTH: + t.ok( + log.dx === 0 && log.dy > 0, + '... with sane arguments: pan south only results in ' + + 'positive delta y' + ); + break; + case OpenLayers.Control.Pan.WEST: + t.ok( + log.dx < 0 && log.dy === 0, + '... with sane arguments: pan west only results in ' + + 'negative delta x' + ); + break; + case OpenLayers.Control.Pan.EAST: + t.ok( + log.dx > 0 && log.dy === 0, + '... with sane arguments: pan east only results in ' + + 'positive delta x' + ); + break; + } + + // reset log-object + log = { + dx: null, + dy: null + }; + // always set to initial center and zoom: + map.setCenter(center, zoomlevel); + } + } + + // tear down + for (controlKey in controls) { + if (controls.hasOwnProperty(controlKey)) { + control = controls[controlKey]; + control.destroy(); + } + } + map.destroy(); +} + + </script> + </head> + <body> + <div id="map" style="width: 1000px; height: 1000px;"></div> + </body> +</html> diff --git a/misc/openlayers/tests/Control/PanPanel.html b/misc/openlayers/tests/Control/PanPanel.html new file mode 100644 index 0000000..978a051 --- /dev/null +++ b/misc/openlayers/tests/Control/PanPanel.html @@ -0,0 +1,61 @@ +<html> +<head> + <script src="../OLLoader.js"></script> + <script type="text/javascript"> + function test_constructor (t) { + t.plan(2); + + // set up + var control; + + // tests + control = new OpenLayers.Control.PanPanel({slideFactor: 200}); + t.ok(control.controls[0].slideFactor == 200 && + control.controls[1].slideFactor == 200 && + control.controls[2].slideFactor == 200 && + control.controls[3].slideFactor == 200, + "ctor sets slideFactor in all Pan controls"); + + control.destroy(); + + control = new OpenLayers.Control.PanPanel({slideRatio: .5}); + t.ok(control.controls[0].slideRatio == .5 && + control.controls[1].slideRatio == .5 && + control.controls[2].slideRatio == .5 && + control.controls[3].slideRatio == .5, + "ctor sets slideRatio in all Pan controls"); + + control.destroy(); + } + + function test_slide(t) { + t.plan(2); + var map = new OpenLayers.Map("map", { + panMethod: null, + controls: [ + new OpenLayers.Control.PanPanel(), + new OpenLayers.Control.PanPanel({slideRatio: .5}) + ], + layers: [new OpenLayers.Layer(null, {isBaseLayer: true})], + center: new OpenLayers.LonLat(0, 0), + zoom: 1 + }); + + map.controls[0].controls[0].trigger(); + map.controls[0].controls[2].trigger(); + map.pan(-50, 50); + t.eq(map.getCenter().toShortString(), "0, 0", "correct pan distance with slideFactor"); + + map.controls[1].controls[0].trigger(); + map.controls[1].controls[2].trigger(); + map.pan(-128, 64); + t.eq(map.getCenter().toShortString(), "0, 0", "correct pan distance with slideRatio"); + + map.destroy(); + } + </script> +</head> +<body> + <div id="map" style="width: 256px; height: 128px;"></div> +</body> +</html> diff --git a/misc/openlayers/tests/Control/PanZoom.html b/misc/openlayers/tests/Control/PanZoom.html new file mode 100644 index 0000000..4982fb0 --- /dev/null +++ b/misc/openlayers/tests/Control/PanZoom.html @@ -0,0 +1,244 @@ +<html> +<head> + <script src="../OLLoader.js"></script> + <script type="text/javascript"> + var map; + function test_Control_PanZoom_constructor (t) { + t.plan( 4 ); + + control = new OpenLayers.Control.PanZoom(); + t.ok( control instanceof OpenLayers.Control.PanZoom, "new OpenLayers.Control.PanZoom returns object" ); + t.eq( control.displayClass, "olControlPanZoom", "displayClass is correct" ); + control = new OpenLayers.Control.PanZoom({position: new OpenLayers.Pixel(100,100)}); + t.eq( control.position.x, 100, "PanZoom X Set correctly."); + t.eq( control.position.y, 100, "PanZoom y Set correctly."); + } + function test_Control_PanZoom_addControl (t) { + t.plan( 8 ); + map = new OpenLayers.Map('map'); + control = new OpenLayers.Control.PanZoom(); + t.ok( control instanceof OpenLayers.Control.PanZoom, "new OpenLayers.Control.PanZoom returns object" ); + t.ok( map instanceof OpenLayers.Map, "new OpenLayers.Map creates map" ); + map.addControl(control); + t.ok( control.map === map, "Control.map is set to the map object" ); + t.ok( map.controls[4] === control, "map.controls contains control" ); + t.eq( parseInt(control.div.style.zIndex), map.Z_INDEX_BASE['Control'] + 5, "Control div zIndexed properly" ); + t.eq( parseInt(map.viewPortDiv.lastChild.style.zIndex), map.Z_INDEX_BASE['Control'] + 5, "Viewport div contains control div" ); + t.eq( control.div.style.top, "4px", "Control div top located correctly by default"); + + var control2 = new OpenLayers.Control.PanZoom(); + map.addControl(control2, new OpenLayers.Pixel(100,100)); + t.eq( control2.div.style.top, "100px", "2nd control div is located correctly"); + } + + function test_Control_PanZoom_removeButtons(t) { + t.plan(2); + map = new OpenLayers.Map("map"); + control = new OpenLayers.Control.PanZoom(); + map.addControl(control); + control.removeButtons(); + t.eq(control.buttons.length, 0, "buttons array cleared correctly"); + t.eq(control.div.childNodes.length, 0, "control div is empty"); + } + + function test_Control_PanZoom_control_events (t) { + + // IE 9+ does support the standard document.createEvent, + // event.initMouseEvent, and elem.dispatchEvent calls, so it + // should be possible to simulate clicks in this browser. + // For example it looks like jQuery UI does simulate events + // using document.createElement in IE 9+. See + // https://github.com/jquery/jquery-ui/blob/master/tests/jquery.simulate.js. + // I haven't been able to make it work though. + + if ( !window.document.createEvent || + OpenLayers.BROWSER_NAME == "msie" || + OpenLayers.BROWSER_NAME == "opera" || + !t.open_window) { + + t.plan(0); + t.debug_print("FIXME: This browser does not support the PanZoom test at this time."); + } else { + t.plan(35); + t.open_window( "Control/PanZoom.html", function( wnd ) { + t.delay_call( 3, function() { + var flag; + function setFlag(evt) { + flag[evt.type] = true; + } + function resetFlags() { + flag = { + mousedown: false, + mouseup: false, + click: false, + dblclick: false + }; + } + resetFlags(); + + wnd.mapper.events.register("mousedown", mapper, setFlag); + wnd.mapper.events.register("mouseup", mapper, setFlag); + wnd.mapper.events.register("click", mapper, setFlag); + wnd.mapper.events.register("dblclick", mapper, setFlag); + + simulateClick(wnd, wnd.control.buttons[0]); + t.delay_call(2, function() { + t.ok( wnd.mapper.getCenter().lat > wnd.centerLL.lat, "1) Pan up works correctly" ); + t.ok(!flag.mousedown, "1) mousedown does not get to the map"); + t.ok(!flag.mouseup, "1) mouseup does not get to the map"); + t.ok(!flag.click, "1) click does not get to the map"); + t.ok(!flag.dblclick, "1) dblclick does not get to the map"); + resetFlags(); + + simulateClick(wnd, wnd.control.buttons[1]); + }, 2, function() { + t.ok( wnd.mapper.getCenter().lon < wnd.centerLL.lon, "2) Pan left works correctly" ); + t.ok(!flag.mousedown, "2) mousedown does not get to the map"); + t.ok(!flag.mouseup, "2) mouseup does not get to the map"); + t.ok(!flag.click, "2) click does not get to the map"); + t.ok(!flag.dblclick, "2) dblclick does not get to the map"); + resetFlags(); + + simulateClick(wnd, wnd.control.buttons[2]); + }, 2, function() { + t.ok( wnd.mapper.getCenter().lon == wnd.centerLL.lon, "3) Pan right works correctly" ); + t.ok(!flag.mousedown, "3) mousedown does not get to the map"); + t.ok(!flag.mouseup, "3) mouseup does not get to the map"); + t.ok(!flag.click, "3) click does not get to the map"); + t.ok(!flag.dblclick, "3) dblclick does not get to the map"); + resetFlags(); + + simulateClick(wnd, wnd.control.buttons[3]); + }, 2, function() { + t.ok( wnd.mapper.getCenter().lat == wnd.centerLL.lat, "4) Pan down works correctly" ); + t.ok(!flag.mousedown, "4) mousedown does not get to the map"); + t.ok(!flag.mouseup, "4) mouseup does not get to the map"); + t.ok(!flag.click, "4) click does not get to the map"); + t.ok(!flag.dblclick, "4) dblclick does not get to the map"); + resetFlags(); + + simulateClick(wnd, wnd.control.buttons[4]); + }, 2, function() { + t.eq( wnd.mapper.getZoom(), 6, "5) zoomin works correctly" ); + t.ok(!flag.mousedown, "5) mousedown does not get to the map"); + t.ok(!flag.mouseup, "5) mouseup does not get to the map"); + t.ok(!flag.click, "5) click does not get to the map"); + t.ok(!flag.dblclick, "5) dblclick does not get to the map"); + resetFlags(); + + simulateClick(wnd, wnd.control.buttons[6]); + }, 2, function() { + t.eq( wnd.mapper.getZoom(), 5, "6) zoomout works correctly" ); + t.ok(!flag.mousedown, "6) mousedown does not get to the map"); + t.ok(!flag.mouseup, "6) mouseup does not get to the map"); + t.ok(!flag.click, "6) click does not get to the map"); + t.ok(!flag.dblclick, "6) dblclick does not get to the map"); + resetFlags(); + + simulateClick(wnd, wnd.control.buttons[5]); + }, 2, function() { + t.eq( wnd.mapper.getZoom(), 2, "7) zoomworld works correctly" ); + t.ok(!flag.mousedown, "7) mousedown does not get to the map"); + t.ok(!flag.mouseup, "7) mouseup does not get to the map"); + t.ok(!flag.click, "7) click does not get to the map"); + t.ok(!flag.dblclick, "7) dblclick does not get to the map"); + resetFlags(); + }); + }); + }); + } + } + + function test_slideRatio(t) { + t.plan(4); + + var control = new OpenLayers.Control.PanZoom({ + slideRatio: .5 + }); + + var map = new OpenLayers.Map(); + + map.addControl(control); + control.draw(); + control.activate(); + + map.getSize = function() { + return { + w: 250, + h: 100 + } + }; + + var delta, dir; + var buttons = control.buttons; + map.pan = function(dx, dy){ + t.eq([dx,dy],delta,"Panning " + dir + " sets right delta with slideRatio"); + }; + + //up + var delta = [0, -50]; + var dir = "up"; + var evt = {buttonElement: buttons[0]}; + control.onButtonClick.call(control, evt); + + //left + var delta = [-125, 0]; + var dir = "left"; + evt.buttonElement = buttons[1]; + control.onButtonClick.call(control, evt); + + //right + var delta = [125, 0]; + var dir = "right"; + evt.buttonElement = buttons[2]; + control.onButtonClick.call(control, evt); + + //down + var delta = [0, 50]; + var dir = "down"; + evt.buttonElement = buttons[3]; + control.onButtonClick.call(control, evt); + + map.destroy(); + } + + function simulateClick(wnd, elem) { + var evt = wnd.document.createEvent("MouseEvents"); + evt.initMouseEvent("mousedown", true, true, wnd, 0, 0, 0, 0, 0, false, false, false, false, 0, null); + elem.dispatchEvent(evt); + + evt = wnd.document.createEvent("MouseEvents"); + evt.initMouseEvent("mouseup", true, true, wnd, 0, 0, 0, 0, 0, false, false, false, false, 0, null); + elem.dispatchEvent(evt); + + evt = wnd.document.createEvent("MouseEvents"); + evt.initMouseEvent("click", true, true, wnd, 0, 0, 0, 0, 0, false, false, false, false, 0, null); + elem.dispatchEvent(evt); + + evt = wnd.document.createEvent("MouseEvents"); + evt.initMouseEvent("dblclick", true, true, wnd, 0, 0, 0, 0, 0, false, false, false, false, 0, null); + elem.dispatchEvent(evt); + } + + function loader() { + control = new OpenLayers.Control.PanZoom(); + + mapper = new OpenLayers.Map('map', { controls: [control]}); + + + var layer = new OpenLayers.Layer.WMS("Test Layer", + "http://labs.metacarta.com/wms-c/Basic.py?", + {layers: "basic"}); + mapper.addLayer(layer); + + centerLL = new OpenLayers.LonLat(0,0); + mapper.setCenter(centerLL, 5); + } + + + </script> +</head> +<body onload="loader()"> + <div id="map" style="width: 1024px; height: 512px;"/> +</body> +</html> diff --git a/misc/openlayers/tests/Control/PanZoomBar.html b/misc/openlayers/tests/Control/PanZoomBar.html new file mode 100644 index 0000000..5ed2833 --- /dev/null +++ b/misc/openlayers/tests/Control/PanZoomBar.html @@ -0,0 +1,245 @@ +<html> +<head> + <script src="../OLLoader.js"></script> + <script type="text/javascript"> + var map; + function test_Control_PanZoomBar_constructor (t) { + t.plan( 4 ); + + control = new OpenLayers.Control.PanZoomBar({position: new OpenLayers.Pixel(100,100)}); + t.ok( control instanceof OpenLayers.Control.PanZoomBar, "new OpenLayers.Control.PanZoomBar returns object" ); + t.eq( control.displayClass, "olControlPanZoomBar", "displayClass is correct" ); + t.eq( control.position.x, 100, "PanZoom X Set correctly."); + t.eq( control.position.y, 100, "PanZoom y Set correctly."); + } + function test_Control_PanZoomBar_addControl (t) { + t.plan( 8 ); + map = new OpenLayers.Map('map', {controls:[]}); + var layer = new OpenLayers.Layer.WMS("Test Layer", + "http://octo.metacarta.com/cgi-bin/mapserv?", + {map: "/mapdata/vmap_wms.map", layers: "basic"}); + map.addLayer(layer); + control = new OpenLayers.Control.PanZoomBar(); + t.ok( control instanceof OpenLayers.Control.PanZoomBar, "new OpenLayers.Control.PanZoomBar returns object" ); + t.ok( map instanceof OpenLayers.Map, "new OpenLayers.Map creates map" ); + map.addControl(control); + t.ok( control.map === map, "Control.map is set to the map object" ); + t.ok( map.controls[0] === control, "map.controls contains control" ); + t.eq( parseInt(control.div.style.zIndex), 1001, "Control div zIndexed properly" ); + t.eq( parseInt(map.viewPortDiv.lastChild.style.zIndex), 1001, "Viewport div contains control div" ); + t.eq( control.div.style.top, "4px", "Control div top located correctly by default"); + + var control2 = new OpenLayers.Control.PanZoomBar(); + map.addControl(control2, new OpenLayers.Pixel(100,100)); + t.eq( control2.div.style.top, "100px", "2nd control div is located correctly"); + } + + function test_draw(t) { + t.plan(3); + map = new OpenLayers.Map('map', {controls:[]}); + var layer = new OpenLayers.Layer.WMS("Test Layer", + "http://octo.metacarta.com/cgi-bin/mapserv?", + {map: "/mapdata/vmap_wms.map", layers: "basic"}); + map.addLayer(layer); + map.zoomToMaxExtent(); + control = new OpenLayers.Control.PanZoomBar(); + map.addControl(control); + t.eq(control.zoombarDiv.style.height, '176px', "Bar's height is correct."); + + map.baseLayer.wrapDateLine = true; + + control.redraw(); + t.eq(control.zoombarDiv.style.height, '154px', "Bar's height is correct after minZoom restriction."); + + map.div.style.width = "512px"; + map.updateSize(); + t.eq(control.zoombarDiv.style.height, '165px', "Bar's height is correct after resize and minZoom restriction."); + + map.div.style.width = "1024px"; + map.destroy(); + } + + function test_Control_PanZoomBar_clearDiv(t) { + t.plan(2); + map = new OpenLayers.Map('map', {controls:[]}); + var layer = new OpenLayers.Layer.WMS("Test Layer", + "http://octo.metacarta.com/cgi-bin/mapserv?", + {map: "/mapdata/vmap_wms.map", layers: "basic"}); + map.addLayer(layer); + control = new OpenLayers.Control.PanZoomBar(); + map.addControl(control); + control.removeButtons(); + var div = control.div; + map.destroy(); + t.eq(div.childNodes.length, 0, "control's div cleared."); + t.eq(control.zoombarDiv, null, "zoombar div nullified.") + } + + function test_Control_PanZoomBar_onButtonClick (t) { + t.plan(2); + map = new OpenLayers.Map('map', {controls:[], zoomMethod: null}); + var layer = new OpenLayers.Layer.WMS("Test Layer", + "http://octo.metacarta.com/cgi-bin/mapserv?", + {map: "/mapdata/vmap_wms.map", layers: "basic"}); + map.addLayer(layer); + control = new OpenLayers.Control.PanZoomBar(); + map.addControl(control); + control.onButtonClick({'buttonXY': {'x': 0, 'y': 50}, buttonElement: control.zoombarDiv}); + t.eq(map.zoom, 11, "zoom is correct on standard map"); + + map.fractionalZoom = true; + control.onButtonClick({'buttonXY': {'x': 0, 'y': 49}, buttonElement: control.zoombarDiv}); + t.eq(map.zoom.toFixed(3), '10.545', "zoom is correct on fractional zoom map"); + + } + + function test_Control_PanZoomBar_forceFixedZoomLevel_onButtonClick(t){ + t.plan(1); + map = new OpenLayers.Map('map', { + controls: [], + fractionalZoom: true, + zoomMethod: null + }); + var layer = new OpenLayers.Layer.WMS("Test Layer", "http://octo.metacarta.com/cgi-bin/mapserv?", { + map: "/mapdata/vmap_wms.map", + layers: "basic" + }); + map.addLayer(layer); + control = new OpenLayers.Control.PanZoomBar({ + forceFixedZoomLevel: true + }); + map.addControl(control); + + control.onButtonClick({ + 'buttonXY': { + 'x': 0, + 'y': 49 + }, + buttonElement: control.zoombarDiv + }); + t.eq(map.zoom, 11, "forceFixedZoomLevel makes sure that after a div click only fixed zoom levels are used even if the map has fractionalZoom"); + } + + function test_Control_PanZoomBar_forceFixedZoomLevel_zoomBarUp (t) { + var numRandomDrags = 25; + // plan one static recorded test and two for every random drag + t.plan(1 + (numRandomDrags * 2)); + + + var map = new OpenLayers.Map('map', { + controls: [], + fractionalZoom: true, + zoomMethod: null + }); + var layer = new OpenLayers.Layer.WMS("Test Layer", "http://octo.metacarta.com/cgi-bin/mapserv?", { + map: "/mapdata/vmap_wms.map", + layers: "basic" + }); + map.addLayer(layer); + + // zoom to a fractional ZoomLevel initially: + map.setCenter(new OpenLayers.LonLat(0, 0), 9.545); + + control = new OpenLayers.Control.PanZoomBar({ + forceFixedZoomLevel: true + }); + map.addControl(control); + + // The y values come from manually recording real values in an example + var evt = { + 'xy': { + 'x': 0, + 'y': -10.633 + }, + which: 1 + }; + control.zoomStart = { + 'x': 0, + 'y': 5.366 + }; + control.mouseDragStart = { + 'x': 0, + 'y': -10.633 + }; + control.deltaY = control.zoomStart.y - evt.xy.y + control.zoomBarUp(evt); + t.eq(map.zoom, 11, "forceFixedZoomLevel makes sure that after dragging of the handle only fixed zoom levels are used even if the map has fractionalZoom"); + + // randomly drag the handle around + // we should never get a zoom < 0 or a non-integer zoom, regardless of + // captured random values for start and end of the drag. + for (var i = 0; i < numRandomDrags; i++) { + var randStartY = Math.random() * 10 * ((i % 2 === 0) ? -1 : 1); + var randStopY = Math.random() * 160 * ((i % 2 === 1) ? -1 : 1); + var evt = { + 'xy': { + 'x': 0, + 'y': randStopY + }, + which: 1 + }; + control.zoomStart = { + 'x': 0, + 'y': randStartY + }; + control.mouseDragStart = { + 'x': 0, + 'y': randStopY + }; + control.deltaY = control.zoomStart.y - evt.xy.y + control.zoomBarUp(evt); + + t.eq(Math.floor(map.zoom), Math.ceil(map.zoom), 'Only integer zooms after random handle drag with forceFixedZoomLevel=true and fractionalZoom=true (current zoom was ' + map.zoom + ')'); + t.ok(map.zoom >= 0, 'map.zoom is never < 0 after random handle drag with forceFixedZoomLevel=true and fractionalZoom=true'); + } + } + + function test_Control_PanZoomBar_shows (t) { + t.plan(22); + + var control, map; + + control = new OpenLayers.Control.PanZoomBar({panIcons: true, zoomWorldIcon: false}); + map = new OpenLayers.Map('map', {controls: [control]}); + t.eq(control.buttons.length, 6, "(a) pan, no world - expected number of buttons"); + t.ok(control.buttons[0].id.match("_panup$"), "(a) pan, no world - pan up"); + t.ok(control.buttons[1].id.match("_panleft$"), "(a) pan, no world - pan left"); + t.ok(control.buttons[2].id.match("_panright$"), "(a) pan, no world - pan right"); + t.ok(control.buttons[3].id.match("_pandown$"), "(a) pan, no world - pan down"); + t.ok(control.buttons[4].id.match("_zoomin$"), "(a) pan, no world - zoom in"); + t.ok(control.buttons[5].id.match("_zoomout$"), "(a) pan, no world - zoom out"); + map.destroy(); + + control = new OpenLayers.Control.PanZoomBar({panIcons: true, zoomWorldIcon: true}); + map = new OpenLayers.Map('map', {controls:[control]}); + t.eq(control.buttons.length, 7, "(b) pan, world - expected number of buttons"); + t.ok(control.buttons[0].id.match("_panup$"), "(b) pan, world - pan up"); + t.ok(control.buttons[1].id.match("_panleft$"), "(b) pan, world - pan left"); + t.ok(control.buttons[2].id.match("_zoomworld$"), "(b) pan, world - zoom world"); + t.ok(control.buttons[3].id.match("_panright$"), "(b) pan, world - pan right"); + t.ok(control.buttons[4].id.match("_pandown$"), "(b) pan, world - pan down"); + t.ok(control.buttons[5].id.match("_zoomin$"), "(b) pan, world - zoom in"); + t.ok(control.buttons[6].id.match("_zoomout$"), "(b) pan, world - zoom out"); + map.destroy(); + + control = new OpenLayers.Control.PanZoomBar({panIcons: false, zoomWorldIcon: false}); + map = new OpenLayers.Map('map', {controls:[control]}); + t.eq(control.buttons.length, 2, "(c) no pan, no world - expected number of buttons"); + t.ok(control.buttons[0].id.match("_zoomin$"), "(c) no pan, no world - zoom in"); + t.ok(control.buttons[1].id.match("_zoomout$"), "(c) no pan, no world - zoom out"); + map.destroy(); + + control = new OpenLayers.Control.PanZoomBar({panIcons: false, zoomWorldIcon: true}); + map = new OpenLayers.Map('map', {controls:[control]}); + t.eq(control.buttons.length, 3, "(d) no pan, world - expected number of buttons"); + t.ok(control.buttons[0].id.match("_zoomin$"), "(d) no pan, world - zoom in"); + t.ok(control.buttons[1].id.match("_zoomout$"), "(d) no pan, world - zoom out"); + t.ok(control.buttons[2].id.match("_zoomworld$"), "(d) no pan, world - zoom world"); + map.destroy(); + } + </script> +</head> +<body> + <div id="map" style="width: 1024px; height: 512px;"/> +</body> +</html> diff --git a/misc/openlayers/tests/Control/Panel.html b/misc/openlayers/tests/Control/Panel.html new file mode 100644 index 0000000..f02e643 --- /dev/null +++ b/misc/openlayers/tests/Control/Panel.html @@ -0,0 +1,382 @@ +<html> +<head> + <script src="../OLLoader.js"></script> + <script type="text/javascript"> + function test_Control_Panel_constructor (t) { + t.plan( 2 ); + + control = new OpenLayers.Control.Panel(); + t.ok( control instanceof OpenLayers.Control.Panel, "new OpenLayers.Control returns object" ); + t.eq( control.displayClass, "olControlPanel", "displayClass is correct" ); + } + function test_Control_Panel_constructor2 (t) { + t.plan(19); + var map = new OpenLayers.Map('map'); + var toolControl = new OpenLayers.Control.ZoomBox(); + var AnotherToolControl = OpenLayers.Class(OpenLayers.Control, { + CLASS_NAME: 'mbControl.TestTool', + type: OpenLayers.Control.TYPE_TOOL + }); + var anotherToolControl = new AnotherToolControl(); + var ToggleControl = OpenLayers.Class(OpenLayers.Control, { + CLASS_NAME: 'mbControl.TestToggle', + type: OpenLayers.Control.TYPE_TOGGLE + }); + + var toggleControl = new ToggleControl(); + var buttonControl = new OpenLayers.Control.Button({ + trigger: function () { + t.ok(true, "trigger function of button is called."); + } + }); + + var panel = new OpenLayers.Control.Panel( + {defaultControl: anotherToolControl}); + t.ok(panel instanceof OpenLayers.Control.Panel, + "new OpenLayers.Control.Panel returns object"); + panel.redraw = function(){ + panel.redrawsCount++; + OpenLayers.Control.Panel.prototype.redraw.apply(this, arguments); + }; + + // To get length of events.listeners error-free + var getListenerLength= function(events,key){ + if(!events) { + return -2; // events is destroyed + } else if(!events.listeners) { + return -1; // events is destroyed + } else if(!events.listeners[key]) { + return 0; // no listener in event + } else { + return events.listeners[key].length; + } + }; + var toolEventListenerLength = getListenerLength(toolControl.events,"activate"); + panel.addControls([toolControl, anotherToolControl, toggleControl]); + t.eq(panel.controls.length, 3, + "added three controls to the panel"); + panel.addControls([buttonControl]); + + panel.redrawsCount = 0; + map.addControl(panel); + t.eq(getListenerLength(toolControl.events,"activate"), toolEventListenerLength+1, + "toolControl additional listener for \"activate\" after adding Panel to the map."); + t.ok((panel.redrawsCount > 0), "Redraw called on add panel to map " + + panel.redrawsCount + " times."); + t.ok((panel.active),"Panel is active after add panel to map."); + + panel.redrawsCount = 0; + panel.addControls(new AnotherToolControl()); + t.ok((panel.redrawsCount > 0), + "Redraw called on add control to panel after add panel to map " + + panel.redrawsCount + " times."); + + panel.deactivate(); + panel.redrawsCount = 0; + panel.activate(); + t.ok((panel.redrawsCount > 0),"Redraw called on activate panel " + + panel.redrawsCount + " times."); + + panel.activateControl(toolControl); + t.ok(toolControl.active && !anotherToolControl.active && !toggleControl.active && !buttonControl.active, + "activated one tool control, the other one is inactive and the toggle & button controls also."); + + panel.activateControl(toggleControl); + t.eq(toggleControl.panel_div.className,"mbControlTestToggleItemActive olButton", + "className of icon div for toggle control is active."); + t.ok(toolControl.active && !anotherToolControl.active && toggleControl.active, + "activated the toggle control, which has no influence on the tool & togggle controls."); + panel.activateControl(buttonControl); + t.ok(toolControl.active && !anotherToolControl.active && toggleControl.active, + "activateContol calling for button, which has no influence on the tool & togggle controls."); + t.ok(!buttonControl.active, + "activateContol calling for button, button remains inactive."); + buttonControl.activate(); + t.ok(buttonControl.active && toolControl.active && !anotherToolControl.active && toggleControl.active, + "activated the button control, which has no influence on the tool & togggle controls."); + + panel.activateControl(anotherToolControl); + t.eq(anotherToolControl.panel_div.className,"mbControlTestToolItemActive olButton", + "className of icon div for anotherToolControl is active."); + t.eq(toolControl.panel_div.className,"olControlZoomBoxItemInactive olButton", + "className of icon div for toolControl is inactive."); + t.ok(!toolControl.active && anotherToolControl.active && toggleControl.active, + "activated the other tool control, the first one is inactive and the toggle control still active."); + t.ok(buttonControl.active, + "activated the other tool control, the button control still active."); + + panel.destroy(); + t.eq(getListenerLength(toolControl.events,"activate"), toolEventListenerLength, + "toolControl additional listeners removed after destroy Panel."); + map.destroy(); + } + function test_Control_Panel_titles (t) { + t.plan(2); + var panel = new OpenLayers.Control.Panel(); + var toolControl = new OpenLayers.Control.ZoomBox({ + title:"Zoom box: Selecting it you can zoom on an area by clicking and dragging." + }); + panel.addControls([toolControl]); + t.eq(panel.controls.length, 1, "added a control to the panel"); + t.eq(panel.controls[0].title, toolControl.panel_div.title, "the title is correctly set"); + } + + function test_Control_Panel_getBy(t) { + + var panel = { + getBy: OpenLayers.Control.Panel.prototype.getBy, + getControlsBy: OpenLayers.Control.Panel.prototype.getControlsBy, + controls: [ + {foo: "foo", id: Math.random()}, + {foo: "bar", id: Math.random()}, + {foo: "foobar", id: Math.random()}, + {foo: "foo bar", id: Math.random()}, + {foo: "foo", id: Math.random()} + ] + }; + + var cases = [ + { + got: panel.getControlsBy("foo", "foo"), + expected: [panel.controls[0], panel.controls[4]], + message: "(string literal) got two controls matching foo" + }, { + got: panel.getControlsBy("foo", "bar"), + expected: [panel.controls[1]], + message: "(string literal) got one control matching foo" + }, { + got: panel.getControlsBy("foo", "barfoo"), + expected: [], + message: "(string literal) got empty array for no foo match" + }, { + got: panel.getControlsBy("foo", /foo/), + expected: [panel.controls[0], panel.controls[2], panel.controls[3], panel.controls[4]], + message: "(regexp literal) got three controls containing string" + }, { + got: panel.getControlsBy("foo", /foo$/), + expected: [panel.controls[0], panel.controls[4]], + message: "(regexp literal) got three controls ending with string" + }, { + got: panel.getControlsBy("foo", /\s/), + expected: [panel.controls[3]], + message: "(regexp literal) got control containing space" + }, { + got: panel.getControlsBy("foo", new RegExp("BAR", "i")), + expected: [panel.controls[1], panel.controls[2], panel.controls[3]], + message: "(regexp object) got layers ignoring case" + }, { + got: panel.getControlsBy("foo", {test: function(str) {return str.length > 3;}}), + expected: [panel.controls[2], panel.controls[3]], + message: "(custom object) got controls with foo length greater than 3" + } + ]; + t.plan(cases.length); + for(var i=0; i<cases.length; ++i) { + t.eq(cases[i].got, cases[i].expected, cases[i].message); + } + + + } + + function test_Control_Panel_saveState (t) { + t.plan(11); + var map = new OpenLayers.Map('map'); + + var defaultControl = new OpenLayers.Control(); + var panel = new OpenLayers.Control.Panel({ + defaultControl: defaultControl + }); + panel.addControls([new OpenLayers.Control(), defaultControl]); + map.addControl(panel); + t.eq(defaultControl.active, true, + "After panel activation default control is active."); + t.ok(panel.defaultControl, + "defaultControl not nullified after initial panel activation"); + // activate the 1st control + panel.activateControl(panel.controls[0]); + panel.deactivate(); + t.ok(!panel.controls[0].active && !panel.controls[1].active, + "No controls are active after panel deactivation."); + panel.activate(); + t.eq(panel.controls[0].active, false, + "After panel reactivation first control is inactive."); + t.eq(panel.controls[1].active, true, + "After panel reactivation default control is active again."); + panel.destroy(); + + defaultControl = new OpenLayers.Control(); + panel = new OpenLayers.Control.Panel({ + saveState: true, + defaultControl: defaultControl + }); + panel.addControls([new OpenLayers.Control(), defaultControl]); + map.addControl(panel); + t.eq(defaultControl.active, true, + "After panel activation default control is active."); + t.eq(panel.defaultControl, null, + "defaultControl nullified after initial panel activation"); + // activate the 1st control, which will deactivate the 2nd + panel.activateControl(panel.controls[0]); + t.eq(panel.controls[1].active, false, + "2nd control deactivated with activation of 1st"); + panel.deactivate(); + t.ok(!panel.controls[0].active && !panel.controls[1].active, + "No controls are active after panel deactivation."); + panel.activate(); + t.eq(panel.controls[0].active, true, + "After panel reactivation first control is active."); + t.eq(panel.controls[1].active, false, + "After panel reactivation second control is inactive."); + panel.destroy(); + map.destroy(); + } + + function test_Control_Panel_autoActivate (t) { + t.plan(1); + var map = new OpenLayers.Map('map'); + var controlNoDeactive = new OpenLayers.Control({autoActivate:true}); + var chkDeactivate = function () { + t.ok(false, "Tool control autoActivate:true was deactivated unnecessarily"); + }; + controlNoDeactive.events.on({deactivate: chkDeactivate}); + var panel = new OpenLayers.Control.Panel(); + + map.addControl(panel); + panel.addControls([controlNoDeactive]); + controlNoDeactive.events.un({deactivate: chkDeactivate}); + t.ok(!controlNoDeactive.active, "Tool control autoActivate:true is not active"); + + } + + function test_Control_Panel_deactivate (t) { + t.plan(2); + var map = new OpenLayers.Map('map'); + var control = new OpenLayers.Control(); + var panel = new OpenLayers.Control.Panel(); + map.addControl(panel); + panel.addControls([control]); + t.ok(panel.div.innerHTML != "", "Panel displayed after activate"); + + panel.deactivate(); + t.ok(panel.div.innerHTML == "", + "Panel is not displayed after deactivate without any active control"); + + map.destroy(); + } + + function test_allowDepress (t) { + t.plan(2); + var map = new OpenLayers.Map('map'); + + var panel = new OpenLayers.Control.Panel(); + panel.addControls([new OpenLayers.Control(),new OpenLayers.Control()]); + map.addControl(panel); + + var control1 = panel.controls[1] + + panel.activateControl(control1); + + panel.allowDepress = false; + panel.activateControl(control1); + t.eq(control1.active, true, + "control1 remains active after calling again activateControl when allowDepress = false"); + panel.allowDepress = true; + panel.activateControl(control1); + t.eq(control1.active, false, + "control1 is inactive after calling again activateControl when allowDepress = true"); + + // panel.deactivate(); + map.destroy(); + } + + function test_iconOn_iconOff(t) { + t.plan(2); + + var map = new OpenLayers.Map('map'); + + var panel = new OpenLayers.Control.Panel(); + var ctrl = new OpenLayers.Control({displayClass: 'ctrl'}); + panel.addControls([ctrl]); + + map.addControl(panel); + + // add arbitrary classes to the panel div - we want to test + // than iconOn and iconOff do their jobs even when the panel + // div has application-specific classes. + + ctrl.panel_div.className = + 'ctrlItemInactive fooItemActive fooItemInactive'; + + panel.iconOn.call(ctrl); + t.eq(ctrl.panel_div.className, + 'ctrlItemActive fooItemActive fooItemInactive', + 'iconOn behaves as expected'); + + ctrl.panel_div.className = + 'ctrlItemActive fooItemActive fooItemInactive'; + + panel.iconOff.call(ctrl); + t.eq(ctrl.panel_div.className, + 'ctrlItemInactive fooItemActive fooItemInactive', + 'iconOff behaves as expected'); + + map.destroy(); + } + + function test_buttonclick(t) { + t.plan(4); + var map = new OpenLayers.Map('map'); + var panel1 = new OpenLayers.Control.Panel(); + var div = document.createElement("div"); + var panel2 = new OpenLayers.Control.Panel({div: div}); + map.addControls([panel1, panel2]); + + t.ok(map.events.listeners.buttonclick, "buttonclick event registered on map's Events instance for panel inside map"); + t.ok(!panel1.events.element, "Panel inside map has no element on its Events instance"); + t.ok(panel2.events.listeners.buttonclick, "buttonclick event registered on panel's Events instance if outside map") + t.ok(panel2.events.element === div, "Panel outside map has the panel's div as element on its Events instance"); + + } + + function test_iconOniconOff (t) { + t.plan(6); + var map = new OpenLayers.Map("map"), + navControl = new OpenLayers.Control.Navigation({autoActivate: true}), + zbControl = new OpenLayers.Control.ZoomBox(), + panel = new OpenLayers.Control.Panel({defaultControl: navControl}), + navActiveClass, navInactiveClass, zbActiveClass, zbInactiveClass; + + panel.addControls([navControl, zbControl]); + map.addControl(panel); + + navControl.panel_div.className += " foo"; + zbControl.panel_div.className = "bar " + zbControl.panel_div.className; + + t.eq(navControl.panel_div.className, "olControlNavigationItemActive olButton foo", + "defaultControl className is set to [displayClass]Active on panel instantiation"); + t.eq(zbControl.panel_div.className, "bar olControlZoomBoxItemInactive olButton", + "non-defaultControl className is set to [displayClass]Inactive on panel instantiation"); + + panel.activateControl(zbControl); + + t.eq(zbControl.panel_div.className, "bar olControlZoomBoxItemActive olButton", + "active control class name with preceding secondary class name is set to [displayClass]Active"); + t.eq(navControl.panel_div.className, "olControlNavigationItemInactive olButton foo", + "inactive control class name with trailing secondary class name is set to [displayClass]Inactive"); + + panel.activateControl(navControl); + + t.eq(navControl.panel_div.className, "olControlNavigationItemActive olButton foo", + "active control class name with trailing secondary class name is set to [displayClass]Active"); + t.eq(zbControl.panel_div.className, "bar olControlZoomBoxItemInactive olButton", + "inactive control class name with preceding secondary class name is set to [displayClass]Inactive"); + + map.destroy(); + } + + </script> +</head> +<body> + <div id="map" style="width: 1024px; height: 512px;"/> +</body> +</html> diff --git a/misc/openlayers/tests/Control/Permalink.html b/misc/openlayers/tests/Control/Permalink.html new file mode 100644 index 0000000..0b729da --- /dev/null +++ b/misc/openlayers/tests/Control/Permalink.html @@ -0,0 +1,453 @@ +<html> +<head> + <script src="../OLLoader.js"></script> + <script type="text/javascript"> + var map; + function test_Control_Permalink_constructor (t) { + t.plan(42); + + control = new OpenLayers.Control.Permalink(); + t.ok(control instanceof OpenLayers.Control.Permalink, "new OpenLayers.Control returns object"); + t.eq(control.displayClass, "olControlPermalink", "displayClass is correct"); + t.eq(control.base, document.location.href, "base is correct"); + t.ok(!control.anchor, "anchor is correct"); + control.destroy(); + + control = new OpenLayers.Control.Permalink('permalink', 'test.html'); + t.ok(control instanceof OpenLayers.Control.Permalink, "new OpenLayers.Control returns object"); + t.eq(control.displayClass, "olControlPermalink", "displayClass is correct"); + t.eq(control.base, 'test.html', "base is correct"); + t.ok(OpenLayers.Util.isElement(control.element), "element is a dom object"); + t.ok(!control.anchor, "anchor is correct"); + control.destroy(); + + control = new OpenLayers.Control.Permalink('permalink'); + t.ok(control instanceof OpenLayers.Control.Permalink, "new OpenLayers.Control returns object"); + t.eq(control.displayClass, "olControlPermalink", "displayClass is correct"); + t.eq(control.base, document.location.href, "base is correct"); + t.ok(OpenLayers.Util.isElement(control.element), "element is a dom object"); + t.ok(!control.anchor, "anchor is correct"); + control.destroy(); + + control = new OpenLayers.Control.Permalink(OpenLayers.Util.getElement('permalink')); + t.ok(control instanceof OpenLayers.Control.Permalink, "new OpenLayers.Control returns object"); + t.eq(control.displayClass, "olControlPermalink", "displayClass is correct"); + t.eq(control.base, document.location.href, "base is correct"); + t.ok(OpenLayers.Util.isElement(control.element), "element is a dom object"); + t.ok(!control.anchor, "anchor is correct"); + control.destroy(); + + control = new OpenLayers.Control.Permalink({anchor: true}); + t.ok(control instanceof OpenLayers.Control.Permalink, "new OpenLayers.Control returns object"); + t.eq(control.displayClass, "olControlPermalink", "displayClass is correct"); + t.eq(control.base, document.location.href, "base is correct"); + t.ok(control.element == null, "element is null"); + t.ok(control.anchor, "anchor is correct"); + control.destroy(); + + control = new OpenLayers.Control.Permalink({anchor: false}); + t.ok(control instanceof OpenLayers.Control.Permalink, "new OpenLayers.Control returns object"); + t.eq(control.displayClass, "olControlPermalink", "displayClass is correct"); + t.eq(control.base, document.location.href, "base is correct"); + t.ok(!control.anchor, "anchor is correct"); + control.destroy(); + + control = new OpenLayers.Control.Permalink({}); + t.ok(control instanceof OpenLayers.Control.Permalink, "new OpenLayers.Control returns object"); + t.eq(control.displayClass, "olControlPermalink", "displayClass is correct"); + t.eq(control.base, document.location.href, "base is correct"); + t.ok(!control.anchor, "anchor is correct"); + control.destroy(); + + control = new OpenLayers.Control.Permalink({element: 'permalink', base: 'test.html'}); + t.ok(control instanceof OpenLayers.Control.Permalink, "new OpenLayers.Control returns object"); + t.eq(control.displayClass, "olControlPermalink", "displayClass is correct"); + t.eq(control.base, 'test.html', "base is correct"); + t.ok(OpenLayers.Util.isElement(control.element), "element is a dom object"); + t.ok(!control.anchor, "anchor is correct"); + control.destroy(); + + control = new OpenLayers.Control.Permalink({element: 'permalink', base: 'test.html', anchor: true}); + t.ok(control instanceof OpenLayers.Control.Permalink, "new OpenLayers.Control returns object"); + t.eq(control.displayClass, "olControlPermalink", "displayClass is correct"); + t.eq(control.base, 'test.html', "base is correct"); + t.ok(OpenLayers.Util.isElement(control.element), "element is a dom object"); + t.ok(control.anchor, "anchor is correct"); + control.destroy(); + } + function test_Control_Permalink_uncentered (t) { + t.plan( 1 ); + + control = new OpenLayers.Control.Permalink('permalink'); + map = new OpenLayers.Map('map'); + map.addControl(control); + map.events.triggerEvent("changelayer", {}); + t.ok(true, "permalink didn't bomb out."); + map.destroy(); + } + function test_Control_Permalink_initwithelem (t) { + t.plan( 1 ); + + control = new OpenLayers.Control.Permalink(OpenLayers.Util.getElement('permalink')); + t.ok(true, "If the above line doesn't throw an error, we're safe."); + control.destroy(); + } + function test_Control_Permalink_updateLinks (t) { + t.plan( 3 ); + + control = new OpenLayers.Control.Permalink('permalink'); + t.ok( control instanceof OpenLayers.Control.Permalink, "new OpenLayers.Control returns object" ); + map = new OpenLayers.Map('map'); + layer = new OpenLayers.Layer.WMS('Test Layer', "http://octo.metacarta.com/cgi-bin/mapserv", {map: '/mapdata/vmap_wms.map', layers: 'basic', format: 'image/jpeg'}); + map.addLayer(layer); + layer = new OpenLayers.Layer.WMS('Test Layer', "http://octo.metacarta.com/cgi-bin/mapserv", {map: '/mapdata/vmap_wms.map', layers: 'basic', format: 'image/jpeg'}, {'isBaseLayer': false}); + map.addLayer(layer); + layer.setVisibility(true); + if (!map.getCenter()) map.zoomToMaxExtent(); + map.addControl(control); + map.pan(5, 0, {animate:false}); + t.ok(OpenLayers.Util.isEquivalentUrl(OpenLayers.Util.getElement('permalink').href, location+"?zoom=2&lat=0&lon=1.75781&layers=BT"), 'pan sets permalink'); + + map.layers[1].setVisibility(false); + + t.ok(OpenLayers.Util.isEquivalentUrl(OpenLayers.Util.getElement('permalink').href, location+"?zoom=2&lat=0&lon=1.75781&layers=BF"), 'setVisibility sets permalink'); + map.destroy(); + } + function test_Control_Permalink_updateLinksBase (t) { + t.plan( 2 ); + + control = new OpenLayers.Control.Permalink('permalink', "./edit.html" ); + t.ok( control instanceof OpenLayers.Control.Permalink, "new OpenLayers.Control returns object" ); + map = new OpenLayers.Map('map'); + layer = new OpenLayers.Layer.WMS('Test Layer', "http://octo.metacarta.com/cgi-bin/mapserv", {map: '/mapdata/vmap_wms.map', layers: 'basic', format: 'image/jpeg'}); + map.addLayer(layer); + if (!map.getCenter()) map.zoomToMaxExtent(); + map.addControl(control); + map.pan(5, 0, {animate:false}); + OpenLayers.Util.getElement('edit_permalink').href = './edit.html?zoom=2&lat=0&lon=1.75781&layers=B'; + t.eq(OpenLayers.Util.getElement('permalink').href, OpenLayers.Util.getElement('edit_permalink').href, "Panning sets permalink with base"); + map.destroy(); + } + function test_Control_Permalink_noElement (t) { + t.plan( 2 ); + control = new OpenLayers.Control.Permalink( ); + t.ok( control instanceof OpenLayers.Control.Permalink, "new OpenLayers.Control returns object" ); + map = new OpenLayers.Map('map'); + map.addControl(control); + t.eq(map.controls[4].div.firstChild.nodeName, "A", "Permalink control creates div with 'a' inside." ); + map.destroy(); + } + function test_Control_Permalink_base_with_query (t) { + t.plan( 3 ); + + control = new OpenLayers.Control.Permalink('permalink', "./edit.html?foo=bar" ); + map = new OpenLayers.Map('map'); + layer = new OpenLayers.Layer.WMS('Test Layer', "http://example.com" ); + map.addLayer(layer); + if (!map.getCenter()) map.zoomToMaxExtent(); + map.addControl(control); + map.pan(5, 0, {animate:false}); + OpenLayers.Util.getElement('edit_permalink').href = './edit.html?foo=bar&zoom=2&lat=0&lon=1.75781&layers=B'; + t.eq(OpenLayers.Util.getElement('permalink').href, OpenLayers.Util.getElement('edit_permalink').href, "Panning sets permalink with base and querystring"); + + control = new OpenLayers.Control.Permalink('permalink', "./edit.html?foo=bar&" ); + map.addControl(control); + map.pan(0, 0, {animate:false}); + t.eq(OpenLayers.Util.getElement('permalink').href, OpenLayers.Util.getElement('edit_permalink').href, "Panning sets permalink with base and querystring ending with '&'"); + + control = new OpenLayers.Control.Permalink('permalink', "./edit.html?" ); + OpenLayers.Util.getElement('edit_permalink').href = './edit.html?zoom=2&lat=0&lon=1.75781&layers=B'; + map.addControl(control); + map.pan(5, 0, {animate:false}); + map.pan(-5, 0, {animate:false}); + t.eq(OpenLayers.Util.getElement('permalink').href, OpenLayers.Util.getElement('edit_permalink').href, "Panning sets permalink with base and querystring ending with '?'"); + map.destroy(); + } + + function test_Control_Permalink_base_with_anchor (t) { + t.plan( 4 ); + control = new OpenLayers.Control.Permalink('permalink', "./edit.html#foo" ); + map = new OpenLayers.Map('map'); + layer = new OpenLayers.Layer.WMS('Test Layer', "http://example.com" ); + map.addLayer(layer); + if (!map.getCenter()) map.zoomToMaxExtent(); + map.addControl(control); + map.pan(5, 0, {animate:false}); + OpenLayers.Util.getElement('edit_permalink').href = './edit.html?zoom=2&lat=0&lon=1.75781&layers=B#foo'; + t.eq(OpenLayers.Util.getElement('permalink').href, OpenLayers.Util.getElement('edit_permalink').href, "Panning sets permalink with base and anchor"); + + control = new OpenLayers.Control.Permalink('permalink', "./edit.html#" ); + map.addControl(control); + map.pan(0, 0, {animate:false}); + OpenLayers.Util.getElement('edit_permalink').href = './edit.html?zoom=2&lat=0&lon=1.75781&layers=B#'; + t.eq(OpenLayers.Util.getElement('permalink').href, OpenLayers.Util.getElement('edit_permalink').href, "Panning sets permalink with base and an empty anchor"); + + control = new OpenLayers.Control.Permalink('permalink', "./edit.html?foo=bar#test" ); + OpenLayers.Util.getElement('edit_permalink').href = './edit.html?foo=bar&zoom=2&lat=0&lon=1.75781&layers=B#test'; + map.addControl(control); + map.pan(5, 0, {animate:false}); + map.pan(-5, 0, {animate:false}); + t.eq(OpenLayers.Util.getElement('permalink').href, OpenLayers.Util.getElement('edit_permalink').href, "Panning sets permalink with base, querystring and an anchor"); + + control = new OpenLayers.Control.Permalink('permalink', "./edit.html#foo", {anchor : true} ); + map.addControl(control); + map.pan(0, 0, {animate:false}); + OpenLayers.Util.getElement('edit_permalink').href = './edit.html#zoom=2&lat=0&lon=1.75781&layers=B'; + t.eq(OpenLayers.Util.getElement('permalink').href, OpenLayers.Util.getElement('edit_permalink').href, "Panning sets permalink with base and an empty anchor"); + } + + function test_Control_Permalink_nonRepeating (t) { + t.plan( 2 ); + + control = new OpenLayers.Control.Permalink('permalink', "./edit.html?zoom=3" ); + t.ok( control instanceof OpenLayers.Control.Permalink, "new OpenLayers.Control returns object" ); + map = new OpenLayers.Map('map'); + layer = new OpenLayers.Layer.WMS('Test Layer', "http://octo.metacarta.com/cgi-bin/mapserv", {map: '/mapdata/vmap_wms.map', layers: 'basic', format: 'image/jpeg'}); + map.addLayer(layer); + if (!map.getCenter()) map.zoomToMaxExtent(); + map.addControl(control); + map.pan(5, 0, {animate:false}); + OpenLayers.Util.getElement('edit_permalink').href = './edit.html?zoom=2&lat=0&lon=1.75781&layers=B'; + t.eq(OpenLayers.Util.getElement('permalink').href, OpenLayers.Util.getElement('edit_permalink').href, "Panning sets permalink with existing zoom in base"); + map.destroy(); + } + + function test_Control_Permalink_customized(t) { + t.plan(2); + + var argParserClass = OpenLayers.Class(OpenLayers.Control.ArgParser, { + CLASS_NAME: "CustomArgParser" + }); + + control = new OpenLayers.Control.Permalink(null, "./edit.html", { + argParserClass: argParserClass, + createParams: function(center, zoom, layers) { + var params = OpenLayers.Control.Permalink.prototype.createParams.apply(control, arguments); + params.customParam = "foo"; + return params; + } + }); + map = new OpenLayers.Map('map'); + layer = new OpenLayers.Layer.WMS('Test Layer', "http://octo.metacarta.com/cgi-bin/mapserv", {map: '/mapdata/vmap_wms.map', layers: 'basic', format: 'image/jpeg'}); + map.addLayer(layer); + if (!map.getCenter()) map.zoomToMaxExtent(); + map.addControl(control); + map.pan(5, 0, {animate:false}); + + t.eq(this.map.controls[this.map.controls.length-1].CLASS_NAME, "CustomArgParser", "Custom ArgParser added correctly."); + t.eq(control.div.firstChild.getAttribute("href"), "./edit.html?zoom=2&lat=0&lon=1.75781&layers=B&customParam=foo", "Custom parameter encoded correctly."); + map.destroy(); + } + + function test_Control_Permalink_createParams(t) { + t.plan(18); + + var baseLayer = { 'isBaseLayer': true }; + + var m = { + 'getCenter': function() { return null; } + }; + + var pl = { + 'map': m, + 'base': {} + }; + + old_getParameters = OpenLayers.Util.getParameters; + OpenLayers.Util.getParameters = function(base) { + t.ok(base == pl.base, "correct base sent in to Util.getParameters()"); + return g_Params; + }; + + //null center, null map.getCenter() + g_Params = {}; + m.baseLayer = baseLayer; + var returnParams = OpenLayers.Control.Permalink.prototype.createParams.apply(pl, []); + t.ok(returnParams == g_Params, "correct params returned on null center"); + + //valid center, zoom, layers + g_Params = { 'test': {} }; + var center = { 'lon': 1.2345678901, 'lat': 9.8765432109 }; + var zoom = {}; + var layers = [ + { 'isBaseLayer': true }, + baseLayer, + { 'isBaseLayer': false, 'getVisibility': function() { return true; } }, + { 'isBaseLayer': false, 'getVisibility': function() { return false; } } + ]; + var returnParams = OpenLayers.Control.Permalink.prototype.createParams.apply(pl, [center, zoom, layers]); + + t.ok(returnParams.test == g_Params.test, "correct params returned from Util.getParameters() when valid center, zoom, layers"); + t.ok(returnParams.zoom == zoom, "params.zoom set correctly when valid center, zoom, layers"); + t.eq(returnParams.lon, 1.23457, "lon set and rounded correctly when valid center, zoom, layers"); + t.eq(returnParams.lat, 9.87654, "lat set and rounded correctly when valid center, zoom, layers"); + t.eq(returnParams.layers, "0BTF", "layers processed correctly when valid center, zoom, layers") + + + //null center, zoom, layers, with displayProjection + g_Params = { 'test': {} }; + g_Projection = {}; + m = { + 'baseLayer': baseLayer, + 'getProjectionObject': function() { return g_Projection; }, + 'center': { 'lon': {}, 'lat': {} }, + 'getCenter': function() { return this.center; }, + 'zoom': {}, + 'getZoom': function() { return this.zoom; }, + 'layers': [ + { 'isBaseLayer': false, 'getVisibility': function() { return true; } }, + baseLayer, + { 'isBaseLayer': false, 'getVisibility': function() { return false; } }, + { 'isBaseLayer': true } + ], + 'getLayers': function() { return this.layers; } + }; + pl = { + 'base': {}, + 'map': m, + 'displayProjection': {} + }; + + old_transform = OpenLayers.Projection.transform; + OpenLayers.Projection.transform = function(point, projObj, dispProj) { + t.ok(point.x = m.center.lon, "correct x value passed into transform"); + t.ok(point.y = m.center.lat, "correct x value passed into transform"); + t.ok(projObj == g_Projection, "correct projection object from map passed into transform"); + t.ok(dispProj == pl.displayProjection, "correct displayProjection from control passed into transform"); + + return { 'x': 9.8765432109, 'y': 1.2345678901 }; + }; + + center = zoom = layers = null; + + var returnParams = OpenLayers.Control.Permalink.prototype.createParams.apply(pl, [center, zoom, layers]); + t.ok(returnParams.test == g_Params.test, "correct params returned from Util.getParameters() when null center, zoom, layers, with displayProjection"); + t.ok(returnParams.zoom == m.zoom, "params.zoom set correctly when null center, zoom, layers, with displayProjection"); + t.eq(returnParams.lon, 9.87654, "lon set, transformed, and rounded correctly when null center, zoom, layers, with displayProjection"); + t.eq(returnParams.lat, 1.23457, "lat set, transformed, and rounded correctly when null center, zoom, layers, with displayProjection"); + t.eq(returnParams.layers, "TBF0", "layers processed correctly when null center, zoom, layers, with displayProjection"); + + OpenLayers.Util.getParameters = old_getParameters; + OpenLayers.Projection.transform = old_transform; + } + function test_Control_Permalink_Anchor (t) { + t.plan(3); + + control = new OpenLayers.Control.Permalink({anchor: true}); + t.ok( control instanceof OpenLayers.Control.Permalink, "new OpenLayers.Control returns object" ); + map = new OpenLayers.Map('map'); + layer = new OpenLayers.Layer.WMS('Test Layer', "http://octo.metacarta.com/cgi-bin/mapserv", {map: '/mapdata/vmap_wms.map', layers: 'basic', format: 'image/jpeg'}); + map.addLayer(layer); + layer = new OpenLayers.Layer.WMS('Test Layer', "http://octo.metacarta.com/cgi-bin/mapserv", {map: '/mapdata/vmap_wms.map', layers: 'basic', format: 'image/jpeg'}, {'isBaseLayer': false}); + map.addLayer(layer); + layer.setVisibility(true); + if (!map.getCenter()) map.zoomToMaxExtent(); + map.addControl(control); + map.pan(5, 0, {animate:false}); + t.ok(OpenLayers.Util.isEquivalentUrl(OpenLayers.Util.getParameterString(control.createParams()), "zoom=2&lat=0&lon=1.75781&layers=BT"), 'pan sets permalink'); + + map.layers[1].setVisibility(false); + t.ok(OpenLayers.Util.isEquivalentUrl(OpenLayers.Util.getParameterString(control.createParams()), "zoom=2&lat=0&lon=1.75781&layers=BF"), 'setVisibility sets permalink'); + map.destroy(); + } + + function test_Control_Permalink_AnchorBaseElement (t) { + t.plan(3); + + control = new OpenLayers.Control.Permalink('permalink', document.location.href, {anchor: true}); + t.ok( control instanceof OpenLayers.Control.Permalink, "new OpenLayers.Control returns object" ); + map = new OpenLayers.Map('map'); + layer = new OpenLayers.Layer.WMS('Test Layer', "http://octo.metacarta.com/cgi-bin/mapserv", {map: '/mapdata/vmap_wms.map', layers: 'basic', format: 'image/jpeg'}); + map.addLayer(layer); + layer = new OpenLayers.Layer.WMS('Test Layer', "http://octo.metacarta.com/cgi-bin/mapserv", {map: '/mapdata/vmap_wms.map', layers: 'basic', format: 'image/jpeg'}, {'isBaseLayer': false}); + map.addLayer(layer); + layer.setVisibility(true); + if (!map.getCenter()) map.zoomToMaxExtent(); + map.addControl(control); + map.pan(5, 0, {animate:false}); + t.ok(OpenLayers.Util.isEquivalentUrl(OpenLayers.Util.getElement('permalink').href, location+"#zoom=2&lat=0&lon=1.75781&layers=BT"), 'pan sets permalink'); + + map.layers[1].setVisibility(false); + t.ok(OpenLayers.Util.isEquivalentUrl(OpenLayers.Util.getElement('permalink').href, location+"#zoom=2&lat=0&lon=1.75781&layers=BF"), 'setVisibility sets permalink'); + map.destroy(); + } + + function test_center_from_map(t) { + t.plan(7); + + var previous = window.location.hash; + window.location.hash = ""; + + var err; + try { + var map = new OpenLayers.Map({ + layers: [new OpenLayers.Layer(null, {isBaseLayer: true})], + controls: [ + new OpenLayers.Control.Permalink({anchor: true}) + ], + center: [1, 2], + zoom: 3 + }); + } catch (e) { + err = e; + } + if (err) { + t.fail("Map construction failure: " + err.message); + } else { + t.ok(true, "Map construction works"); + } + + // confirm that map center is correctly set + var center = map.getCenter(); + t.eq(center.lon, 1, "map x"); + t.eq(center.lat, 2, "map y") + t.eq(map.getZoom(), 3, "map z"); + + // confirm that location from map options has been added to url + var params = OpenLayers.Util.getParameters(window.location.hash.replace("#", "?")); + t.eq(params.lon, "1", "url x"); + t.eq(params.lat, "2", "url y"); + t.eq(params.zoom, "3", "url z"); + + map.destroy(); + window.location.hash = previous; + } + + function test_center_from_url(t) { + t.plan(6); + + // In cases where the location is specified in the URL and given in + // the map options, we respect the location in the URL. + var previous = window.location.hash; + window.location.hash = "#zoom=6&lat=5&lon=4&layers=B" + + var map = new OpenLayers.Map({ + layers: [new OpenLayers.Layer(null, {isBaseLayer: true})], + controls: [new OpenLayers.Control.Permalink({anchor: true})], + center: [0, 0], + zoom: 0 + }); + + // confirm that map center is correctly set + var center = map.getCenter(); + t.eq(center.lon, 4, "map x"); + t.eq(center.lat, 5, "map y") + t.eq(map.getZoom(), 6, "map z"); + + var params = OpenLayers.Util.getParameters(window.location.hash.replace("#", "?")); + t.eq(params.lon, "4", "x set"); + t.eq(params.lat, "5", "y set"); + t.eq(params.zoom, "6", "z set"); + + map.destroy(); + window.location.hash = previous; + } + + </script> +</head> +<body> + <a id="permalink" href="">Permalink</a> <br /> + <a id="edit_permalink" href="">Edit</a> <br /> + <div id="map" style="width: 1024px; height: 512px;"/> +</body> +</html> diff --git a/misc/openlayers/tests/Control/PinchZoom.html b/misc/openlayers/tests/Control/PinchZoom.html new file mode 100644 index 0000000..22db6a5 --- /dev/null +++ b/misc/openlayers/tests/Control/PinchZoom.html @@ -0,0 +1,134 @@ +<html> +<head> + <script src="../OLLoader.js"></script> + <script type="text/javascript"> + + function test_constructor(t) { + t.plan(2); + var control = new OpenLayers.Control.PinchZoom(); + t.ok(control instanceof OpenLayers.Control.PinchZoom, "got an instance"); + t.ok(control.handler instanceof OpenLayers.Handler.Pinch, "control has pinch handler"); + control.destroy(); + } + + function test_destroy(t) { + t.plan(1); + var control = new OpenLayers.Control.PinchZoom(); + control.destroy(); + t.ok(!control.handler, "handler destroyed"); + } + + function test_activate(t) { + t.plan(3); + var control = new OpenLayers.Control.PinchZoom(); + t.ok(!control.active, "control not activated after construction"); + + var map = new OpenLayers.Map({ + div: "map", + controls: [control] + }); + t.ok(control.active, "control activated after being added to the map"); + + control.deactivate(); + t.ok(!control.active, "control deactivated"); + + map.destroy(); + } + + function test_pinchMove(t) { + + var control = new OpenLayers.Control.PinchZoom(); + + var map = new OpenLayers.Map({ + div: "map", + controls: [control] + }); + + var log = []; + map.applyTransform = function(x, y, scale) { + log.push([x, y, scale]); + } + + map.layerContainerOriginPx = { + x: -50, y: -50 + }; + + control.pinchOrigin = { + x: 100, y: 50 + }; + + var cases = [ + {x: 100, y: 60, scale: 1, transform: [-50, -40, 1]}, + {x: 150, y: 60, scale: 1, transform: [0, -40, 1]}, + {x: 150, y: 60, scale: 2, transform: [-150, -140, 2]}, + {x: 50, y: 20, scale: 2.5, transform: [-325, -230, 2.5]}, + {x: 150, y: 60, scale: 2, transform: [-150, -140, 2]}, + {x: 50, y: 20, scale: 0.25, transform: [13, -5, 0.25]} + ]; + + var len = cases.length; + t.plan(len*2); + + var c; + for (var i=0; i<len; ++i) { + c = cases[i]; + control.pinchMove({xy: {x: c.x, y: c.y}}, {scale: c.scale}); + t.eq(log.length, i+1, i + " called once"); + t.eq(log[i], c.transform, i + " correct transform"); + } + + } + + function test_pinchMove_preservecenter(t) { + + var control = new OpenLayers.Control.PinchZoom({ + preserveCenter: true + }); + + var map = new OpenLayers.Map({ + div: "map", + controls: [control], + layers: [new OpenLayers.Layer('fake', {isBaseLayer: true})] + }); + map.zoomToMaxExtent(); + + var centerPx = map.getPixelFromLonLat(map.getCenter()); + + control.pinchStart = function(evt, pinchData) { + t.eq(map.layerContainerOriginPx, {x: 0, y: 0}, "center preserved"); + t.eq(map.getPixelFromLonLat(map.getCenter()), centerPx, "center preserved"); + } + + control.pinchStart(null); + + var log = []; + map.applyTransform = function(x, y, scale) { + log.push([x, y, scale]); + } + control.pinchOrigin = map.getPixelFromLonLat(map.getCenter()); + + var cases = [ + {scale: 1, transform: [0, 0, 1]}, + {scale: 2, transform: [-128, -128, 2]}, + {scale: 2.5, transform: [-192, -192, 2.5]}, + {scale: 0.25, transform: [96, 96, 0.25]} + ]; + + var len = cases.length; + t.plan(2 + len*2); + + var c; + for (var i=0; i<len; ++i) { + c = cases[i]; + control.pinchMove(null, {scale: c.scale}); + t.eq(log.length, i+1, i + " called once"); + t.eq(log[i], c.transform, i + " correct transform"); + } + } + + </script> +</head> +<body> + <div id="map" style="width: 256px; height: 256px;"></div> +</body> +</html> diff --git a/misc/openlayers/tests/Control/SLDSelect.html b/misc/openlayers/tests/Control/SLDSelect.html new file mode 100644 index 0000000..03b871c --- /dev/null +++ b/misc/openlayers/tests/Control/SLDSelect.html @@ -0,0 +1,239 @@ +<html> +<head> + <script src="../OLLoader.js"></script> + <script type="text/javascript"> + + function test_initialize(t) { + t.plan(11); + var control = new OpenLayers.Control.SLDSelect(OpenLayers.Handler.Click); + t.eq(control.handler instanceof OpenLayers.Handler.Click, true, "Click handler created"); + t.ok(control.handler.callbacks["click"] === control.select, "Click callback correctly set"); + control.destroy(); + control = new OpenLayers.Control.SLDSelect(OpenLayers.Handler.RegularPolygon, {handlerOptions: {irregular: true}}); + t.eq(control.handler instanceof OpenLayers.Handler.RegularPolygon, true, "RegularPolygon handler created"); + t.eq(control.handler.irregular, true, "RegularPolygon handler is irregular"); + t.eq(control.handler.persist, false, "RegularPolygon handler is not persistant"); + t.ok(control.handler.callbacks["done"] === control.select, "Done callback correctly set"); + control.destroy(); + control = new OpenLayers.Control.SLDSelect(OpenLayers.Handler.Polygon); + t.eq(control.handler instanceof OpenLayers.Handler.Polygon, true, "Polygon handler created"); + t.ok(control.handler.callbacks["done"] === control.select, "Done callback correctly set"); + control.destroy(); + control = new OpenLayers.Control.SLDSelect(OpenLayers.Handler.Path); + t.eq(control.handler instanceof OpenLayers.Handler.Path, true, "Path handler created"); + t.ok(control.handler.callbacks["done"] === control.select, "Done callback correctly set"); + control.destroy(); + var layer = new OpenLayers.Layer.WMS('Foo', 'http://foo', {LAYERS: 'A'}); + control = new OpenLayers.Control.SLDSelect(OpenLayers.Handler.RegularPolygon, {layers: [layer]}); + t.eq(control.layers.length, 1, "Layers property correctly set"); + control.destroy(); + layer.destroy(); + } + + function test_select(t) { + t.plan(9); + var parser = new OpenLayers.Format.WFSDescribeFeatureType(); + var map = new OpenLayers.Map('map'); + var layer = new OpenLayers.Layer.WMS('Foo', 'http://foo', {LAYERS: 'AAA64'}); + map.addLayer(layer); + + var text = + '<?xml version="1.0" encoding="ISO-8859-1" ?>' + + '<schema' + + ' targetNamespace="http://mapserver.gis.umn.edu/mapserver" ' + + ' xmlns:rws="http://mapserver.gis.umn.edu/mapserver" ' + + ' xmlns:ogc="http://www.opengis.net/ogc"' + + ' xmlns:xsd="http://www.w3.org/2001/XMLSchema"' + + ' xmlns="http://www.w3.org/2001/XMLSchema"' + + ' xmlns:gml="http://www.opengis.net/gml"' + + ' elementFormDefault="qualified" version="0.1" >' + + ' <import namespace="http://www.opengis.net/gml"' + + ' schemaLocation="http://schemas.opengis.net/gml/2.1.2/feature.xsd" />' + + ' <element name="AAA64" ' + + ' type="rws:AAA64Type" ' + + ' substitutionGroup="gml:_Feature" />' + + ' <complexType name="AAA64Type">' + + ' <complexContent>' + + ' <extension base="gml:AbstractFeatureType">' + + ' <sequence>' + + ' <element name="geometry" type="gml:MultiLineStringPropertyType" minOccurs="0" maxOccurs="1"/>' + + ' <element name="OBJECTID" type="string"/>' + + ' </sequence>' + + ' </extension>' + + ' </complexContent>' + + ' </complexType>' + + '</schema>'; + + OpenLayers.Control.SLDSelect.prototype.wfsCache[layer.id] = parser.read(text); + var control = new OpenLayers.Control.SLDSelect(OpenLayers.Handler.RegularPolygon, + {layers: [layer], clearOnDeactivate: true, handlerOptions: {irregular: true} }); + + var testEvent = function(evt) { + t.eq(evt.filters.length, 1, "Event has a filters array set"); + t.eq(evt.filters[0] instanceof OpenLayers.Filter.Spatial, true, "Spatial filter has been created"); + }; + + control.events.register("selected", this, testEvent); + map.addControl(control); + var geometry = OpenLayers.Geometry.Polygon.createRegularPolygon( + new OpenLayers.Geometry.Point(0, 0), 5, 4); + control.select(geometry); + control.events.unregister("selected", this, testEvent); + t.eq(map.layers.length, 2, "Selection layer has been created and added to the map"); + t.eq(map.layers[1] instanceof OpenLayers.Layer.WMS, true, "A WMS layer has been created as the selection layer"); + t.eq(map.layers[1].tileOptions.maxGetUrlLength, 2048, "Selection layer will automatically switch to HTTP Post if content gets longer than 2048"); + var expected_sld = '<sld:StyledLayerDescriptor xmlns:sld="http://www.opengis.net/sld" version="1.0.0" xsi:schemaLocation="http://www.opengis.net/sld http://schemas.opengis.net/sld/1.0.0/StyledLayerDescriptor.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ogc="http://www.opengis.net/ogc" xmlns:gml="http://www.opengis.net/gml"><sld:NamedLayer><sld:Name>AAA64</sld:Name><sld:UserStyle><sld:Name>default</sld:Name><sld:FeatureTypeStyle><sld:Rule><ogc:Filter xmlns:ogc="http://www.opengis.net/ogc"><ogc:BBOX><ogc:PropertyName>geometry</ogc:PropertyName><gml:Box xmlns:gml="http://www.opengis.net/gml" srsName="EPSG:4326"><gml:coordinates decimal="." cs="," ts=" ">-3.5355339059327,-3.5355339059327 3.5355339059327,3.5355339059327</gml:coordinates></gml:Box></ogc:BBOX></ogc:Filter><sld:LineSymbolizer><sld:Stroke><sld:CssParameter name="stroke">#FF0000</sld:CssParameter><sld:CssParameter name="stroke-width">2</sld:CssParameter></sld:Stroke></sld:LineSymbolizer></sld:Rule></sld:FeatureTypeStyle></sld:UserStyle></sld:NamedLayer></sld:StyledLayerDescriptor>'; + + t.xml_eq(map.layers[1].params.SLD_BODY, expected_sld, "SLD generated correctly"); + + var geometry = OpenLayers.Geometry.Polygon.createRegularPolygon( + new OpenLayers.Geometry.Point(0, 0), 7, 4); + control.select(geometry); + t.eq(map.layers.length, 2, "Selection layer is reused when new selection is performed"); + + map.layers[0].setVisibility(false); + t.eq(map.layers[1].getVisibility(), false, "Visibility of selection layer is synchronized with source layer"); + // activate would issue a SLD WMS DescribeLayer request and we are bypassing this here + control.active = true; + control.deactivate(); + t.eq(map.layers.length, 1, "Selection layer is removed on deactive if clearOnDeactivate is set to true"); + map.destroy(); + } + + function test_filterModificationOnSelected(t) { + t.plan(1); + var parser = new OpenLayers.Format.WFSDescribeFeatureType(); + var map = new OpenLayers.Map('map'); + var layer = new OpenLayers.Layer.WMS('Foo', 'http://foo', {LAYERS: 'AAA64'}); + map.addLayer(layer); + + var text = + '<?xml version="1.0" encoding="ISO-8859-1" ?>' + + '<schema' + + ' targetNamespace="http://mapserver.gis.umn.edu/mapserver" ' + + ' xmlns:rws="http://mapserver.gis.umn.edu/mapserver" ' + + ' xmlns:ogc="http://www.opengis.net/ogc"' + + ' xmlns:xsd="http://www.w3.org/2001/XMLSchema"' + + ' xmlns="http://www.w3.org/2001/XMLSchema"' + + ' xmlns:gml="http://www.opengis.net/gml"' + + ' elementFormDefault="qualified" version="0.1" >' + + ' <import namespace="http://www.opengis.net/gml"' + + ' schemaLocation="http://schemas.opengis.net/gml/2.1.2/feature.xsd" />' + + ' <element name="AAA64" ' + + ' type="rws:AAA64Type" ' + + ' substitutionGroup="gml:_Feature" />' + + ' <complexType name="AAA64Type">' + + ' <complexContent>' + + ' <extension base="gml:AbstractFeatureType">' + + ' <sequence>' + + ' <element name="geometry" type="gml:MultiLineStringPropertyType" minOccurs="0" maxOccurs="1"/>' + + ' <element name="OBJECTID" type="string"/>' + + ' </sequence>' + + ' </extension>' + + ' </complexContent>' + + ' </complexType>' + + '</schema>'; + + OpenLayers.Control.SLDSelect.prototype.wfsCache[layer.id] = parser.read(text); + var control = new OpenLayers.Control.SLDSelect(OpenLayers.Handler.RegularPolygon, + {layers: [layer], clearOnDeactivate: true, handlerOptions: {irregular: true} }); + + var testEvent = function(evt) { + // manipulate filter + var bbox = OpenLayers.Bounds.fromString('1,2,3,4'); + evt.filters[0].value = bbox; + }; + control.events.register("selected", this, testEvent); + map.addControl(control); + var geometry = OpenLayers.Geometry.Polygon.createRegularPolygon( + new OpenLayers.Geometry.Point(0, 0), 5, 4); + control.select(geometry); + control.events.unregister("selected", this, testEvent); + + var expected_sld = '<sld:StyledLayerDescriptor xmlns:sld="http://www.opengis.net/sld" version="1.0.0" xsi:schemaLocation="http://www.opengis.net/sld http://schemas.opengis.net/sld/1.0.0/StyledLayerDescriptor.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ogc="http://www.opengis.net/ogc" xmlns:gml="http://www.opengis.net/gml"><sld:NamedLayer><sld:Name>AAA64</sld:Name><sld:UserStyle><sld:Name>default</sld:Name><sld:FeatureTypeStyle><sld:Rule><ogc:Filter xmlns:ogc="http://www.opengis.net/ogc"><ogc:BBOX><ogc:PropertyName>geometry</ogc:PropertyName><gml:Box xmlns:gml="http://www.opengis.net/gml" srsName="EPSG:4326"><gml:coordinates decimal="." cs="," ts=" ">1,2 3,4</gml:coordinates></gml:Box></ogc:BBOX></ogc:Filter><sld:LineSymbolizer><sld:Stroke><sld:CssParameter name="stroke">#FF0000</sld:CssParameter><sld:CssParameter name="stroke-width">2</sld:CssParameter></sld:Stroke></sld:LineSymbolizer></sld:Rule></sld:FeatureTypeStyle></sld:UserStyle></sld:NamedLayer></sld:StyledLayerDescriptor>'; + + t.xml_eq(map.layers[1].params.SLD_BODY, expected_sld, "Filter / SLD manipulated in select-callback correctly"); + + } + + function test_multiselect(t) { + t.plan(2); + + var parser = new OpenLayers.Format.WFSDescribeFeatureType(); + var map = new OpenLayers.Map('map'); + var layer = new OpenLayers.Layer.WMS('Multi', 'http://foo', {LAYERS: 'KGNAT.VKUNSTWERK,KGNAT.LKUNSTWERK,KGNAT.PKUNSTWERK'}); + map.addLayer(layer); + + var text = + '<?xml version="1.0" encoding="ISO-8859-1" ?>' + + '<schema' + + ' targetNamespace="http://mapserver.gis.umn.edu/mapserver" ' + + ' xmlns:rws="http://mapserver.gis.umn.edu/mapserver" ' + + ' xmlns:ogc="http://www.opengis.net/ogc"' + + ' xmlns:xsd="http://www.w3.org/2001/XMLSchema"' + + ' xmlns="http://www.w3.org/2001/XMLSchema"' + + ' xmlns:gml="http://www.opengis.net/gml"' + + ' elementFormDefault="qualified" version="0.1" >' + + ' <import namespace="http://www.opengis.net/gml"' + + ' schemaLocation="http://schemas.opengis.net/gml/2.1.2/feature.xsd" />' + + ' <element name="KGNAT.VKUNSTWERK" ' + + ' type="rws:KGNAT.VKUNSTWERKType" ' + + ' substitutionGroup="gml:_Feature" />' + + ' <complexType name="KGNAT.VKUNSTWERKType">' + + ' <complexContent>' + + ' <extension base="gml:AbstractFeatureType">' + + ' <sequence>' + + ' <element name="geometry" type="gml:MultiPolygonPropertyType" minOccurs="0" maxOccurs="1"/>' + + ' </sequence>' + + ' </extension>' + + ' </complexContent>' + + ' </complexType>' + + ' <element name="KGNAT.LKUNSTWERK" ' + + ' type="rws:KGNAT.LKUNSTWERKType" ' + + ' substitutionGroup="gml:_Feature" />' + + ' <complexType name="KGNAT.LKUNSTWERKType">' + + ' <complexContent>' + + ' <extension base="gml:AbstractFeatureType">' + + ' <sequence>' + + ' <element name="geometry" type="gml:MultiLineStringPropertyType" minOccurs="0" maxOccurs="1"/>' + + ' </sequence>' + + ' </extension>' + + ' </complexContent>' + + ' </complexType>' + + ' <element name="KGNAT.PKUNSTWERK" ' + + ' type="rws:KGNAT.PKUNSTWERKType" ' + + ' substitutionGroup="gml:_Feature" />' + + ' <complexType name="KGNAT.PKUNSTWERKType">' + + ' <complexContent>' + + ' <extension base="gml:AbstractFeatureType">' + + ' <sequence>' + + ' <element name="geometry" type="gml:MultiPointPropertyType" minOccurs="0" maxOccurs="1"/>' + + ' </sequence>' + + ' </extension>' + + ' </complexContent>' + + ' </complexType>' + + '</schema>'; + + OpenLayers.Control.SLDSelect.prototype.wfsCache[layer.id] = parser.read(text); + var control = new OpenLayers.Control.SLDSelect(OpenLayers.Handler.RegularPolygon, {handlerOptions: {irregular: true}, layers: [layer]}); + var testEvent = function(evt) { + t.eq(evt.filters.length, 3, "Event has a filters array set with length tree"); + }; + control.events.register("selected", this, testEvent); + + map.addControl(control); + var geometry = OpenLayers.Geometry.Polygon.createRegularPolygon( + new OpenLayers.Geometry.Point(0, 0), 5, 4); + control.select(geometry); + var expected_sld = '<sld:StyledLayerDescriptor xmlns:sld="http://www.opengis.net/sld" version="1.0.0" xsi:schemaLocation="http://www.opengis.net/sld http://schemas.opengis.net/sld/1.0.0/StyledLayerDescriptor.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ogc="http://www.opengis.net/ogc" xmlns:gml="http://www.opengis.net/gml"><sld:NamedLayer><sld:Name>KGNAT.VKUNSTWERK</sld:Name><sld:UserStyle><sld:Name>default</sld:Name><sld:FeatureTypeStyle><sld:Rule><ogc:Filter xmlns:ogc="http://www.opengis.net/ogc"><ogc:BBOX><ogc:PropertyName>geometry</ogc:PropertyName><gml:Box xmlns:gml="http://www.opengis.net/gml" srsName="EPSG:4326"><gml:coordinates decimal="." cs="," ts=" ">-3.5355339059327,-3.5355339059327 3.5355339059327,3.5355339059327</gml:coordinates></gml:Box></ogc:BBOX></ogc:Filter><sld:PolygonSymbolizer><sld:Fill><sld:CssParameter name="fill">#FF0000</sld:CssParameter></sld:Fill></sld:PolygonSymbolizer></sld:Rule></sld:FeatureTypeStyle></sld:UserStyle></sld:NamedLayer><sld:NamedLayer><sld:Name>KGNAT.LKUNSTWERK</sld:Name><sld:UserStyle><sld:Name>default</sld:Name><sld:FeatureTypeStyle><sld:Rule><ogc:Filter xmlns:ogc="http://www.opengis.net/ogc"><ogc:BBOX><ogc:PropertyName>geometry</ogc:PropertyName><gml:Box xmlns:gml="http://www.opengis.net/gml" srsName="EPSG:4326"><gml:coordinates decimal="." cs="," ts=" ">-3.5355339059327,-3.5355339059327 3.5355339059327,3.5355339059327</gml:coordinates></gml:Box></ogc:BBOX></ogc:Filter><sld:LineSymbolizer><sld:Stroke><sld:CssParameter name="stroke">#FF0000</sld:CssParameter><sld:CssParameter name="stroke-width">2</sld:CssParameter></sld:Stroke></sld:LineSymbolizer></sld:Rule></sld:FeatureTypeStyle></sld:UserStyle></sld:NamedLayer><sld:NamedLayer><sld:Name>KGNAT.PKUNSTWERK</sld:Name><sld:UserStyle><sld:Name>default</sld:Name><sld:FeatureTypeStyle><sld:Rule><ogc:Filter xmlns:ogc="http://www.opengis.net/ogc"><ogc:BBOX><ogc:PropertyName>geometry</ogc:PropertyName><gml:Box xmlns:gml="http://www.opengis.net/gml" srsName="EPSG:4326"><gml:coordinates decimal="." cs="," ts=" ">-3.5355339059327,-3.5355339059327 3.5355339059327,3.5355339059327</gml:coordinates></gml:Box></ogc:BBOX></ogc:Filter><sld:PointSymbolizer><sld:Graphic><sld:Mark><sld:WellKnownName>square</sld:WellKnownName><sld:Fill><sld:CssParameter name="fill">#FF0000</sld:CssParameter></sld:Fill><sld:Stroke/></sld:Mark><sld:Size>10</sld:Size></sld:Graphic></sld:PointSymbolizer></sld:Rule></sld:FeatureTypeStyle></sld:UserStyle></sld:NamedLayer></sld:StyledLayerDescriptor>'; + + t.xml_eq(map.layers[1].params.SLD_BODY, expected_sld, "SLD generated correctly"); + map.destroy(); + } + + </script> +</head> +<body> + <div id="map" style="width: 100px; height: 100px;"></div> +</body> +</html> diff --git a/misc/openlayers/tests/Control/Scale.html b/misc/openlayers/tests/Control/Scale.html new file mode 100644 index 0000000..1d43b25 --- /dev/null +++ b/misc/openlayers/tests/Control/Scale.html @@ -0,0 +1,54 @@ +<html> +<head> + <script src="../OLLoader.js"></script> + <script type="text/javascript"> + OpenLayers.Lang.setCode('en'); + var map; + function test_Control_Scale_constructor (t) { + t.plan( 2 ); + + control = new OpenLayers.Control.Scale(); + t.ok( control instanceof OpenLayers.Control.Scale, "new OpenLayers.Control returns object" ); + t.eq( control.displayClass, "olControlScale", "displayClass is correct" ); + } + function test_Control_Scale_initwithelem (t) { + t.plan( 1 ); + + control = new OpenLayers.Control.Scale(OpenLayers.Util.getElement('scale')); + t.ok(true, "If this happens, then we passed. (FF throws an error above otherwise)"); + } + function test_Control_Scale_updateScale (t) { + t.plan( 4 ); + + control = new OpenLayers.Control.Scale('scale'); + t.ok( control instanceof OpenLayers.Control.Scale, "new OpenLayers.Control returns object" ); + map = new OpenLayers.Map('map', {zoomMethod: null}); + layer = new OpenLayers.Layer.WMS('Test Layer', "http://octo.metacarta.com/cgi-bin/mapserv", {map: '/mapdata/vmap_wms.map', layers: 'basic', format: 'image/jpeg'}); + map.addLayer(layer); + map.zoomTo(0); + map.addControl(control); + t.eq(OpenLayers.Util.getElement('scale').innerHTML, "Scale = 1 : 443M", "Scale set by default." ); + map.zoomIn(); + t.eq(OpenLayers.Util.getElement('scale').innerHTML, "Scale = 1 : 221M", "Zooming in changes scale" ); + map.baseLayer.resolutions = [OpenLayers.Util.getResolutionFromScale(110)]; + map.zoomTo(0); + t.eq(OpenLayers.Util.getElement('scale').innerHTML, "Scale = 1 : 110", "Scale of 100 isn't rounded" ); + } + function test_Control_Scale_internalScale (t) { + t.plan(2); + control = new OpenLayers.Control.Scale(); + t.ok( control instanceof OpenLayers.Control.Scale, "new OpenLayers.Control returns object" ); + map = new OpenLayers.Map('map', {zoomMethod: null}); + layer = new OpenLayers.Layer.WMS('Test Layer', "http://octo.metacarta.com/cgi-bin/mapserv", {map: '/mapdata/vmap_wms.map', layers: 'basic', format: 'image/jpeg'}); + map.addLayer(layer); + map.zoomTo(0); + map.addControl(control); + t.eq(control.div.firstChild.innerHTML, "Scale = 1 : 443M", "Internal scale displayed properly."); + } + </script> +</head> +<body> + <a id="scale" href="">Scale</a> <br /> + <div id="map" style="width: 1024px; height: 512px;"/> +</body> +</html> diff --git a/misc/openlayers/tests/Control/ScaleLine.html b/misc/openlayers/tests/Control/ScaleLine.html new file mode 100644 index 0000000..e863fd9 --- /dev/null +++ b/misc/openlayers/tests/Control/ScaleLine.html @@ -0,0 +1,187 @@ +<html> +<head> + <script type="text/javascript">var oldAlert = window.alert, gMess; window.alert = function(message) {gMess = message; return true;};</script> + <!-- this gmaps key generated for http://openlayers.org/dev/ --> + <script src='http://maps.google.com/maps?file=api&v=2&key=ABQIAAAA9XNhd8q0UdwNC7YSO4YZghSPUCi5aRYVveCcVYxzezM4iaj_gxQ9t-UajFL70jfcpquH5l1IJ-Zyyw'></script> + <script src="../OLLoader.js"></script> + <script type="text/javascript"> + var validkey = (window.location.protocol == "file:") || + (window.location.host == "localhost") || + (window.location.host == "openlayers.org"); + + function test_initialize(t) { + t.plan(2); + var control = new OpenLayers.Control.ScaleLine(); + t.ok(control instanceof OpenLayers.Control.ScaleLine, "new OpenLayers.Control returns object" ); + t.eq(control.displayClass, "olControlScaleLine", "displayClass is correct" ); + control.destroy(); + } + + function test_initwithelem(t) { + t.plan(1); + var control = new OpenLayers.Control.ScaleLine({"div":OpenLayers.Util.getElement('ScaleLine')}); + t.ok(true, "If this happens, then we passed. (FF throws an error above otherwise)"); + control.destroy(); + } + + function test_calcDegrees(t) { + t.plan(5); + var control = new OpenLayers.Control.ScaleLine(); + t.ok(control instanceof OpenLayers.Control.ScaleLine, "new OpenLayers.Control returns object" ); + var map = new OpenLayers.Map('map'); + var layer = new OpenLayers.Layer.WMS('Test Layer', "http://octo.metacarta.com/cgi-bin/mapserv", {map: '/mapdata/vmap_wms.map', layers: 'basic', format: 'image/jpeg'}); + map.addLayer(layer); + map.zoomTo(0); + map.addControl(control); + t.eq(control.div.firstChild.style.visibility, "visible", "top scale is present."); + t.eq(control.div.lastChild.style.visibility, "visible", "bottom scale is present."); + t.eq(control.div.firstChild.innerHTML, "10000 km", "top scale has correct text."); + t.eq(control.div.lastChild.innerHTML, "5000 mi", "bottom scale has correct text."); + map.destroy(); + } + + function test_calcsOther (t) { + t.plan(5); + var control = new OpenLayers.Control.ScaleLine(); + t.ok(control instanceof OpenLayers.Control.ScaleLine, "new OpenLayers.Control returns object" ); + var map = new OpenLayers.Map('map'); + map.units = "mi"; + var layer = new OpenLayers.Layer.WMS('Test Layer', "http://octo.metacarta.com/cgi-bin/mapserv", {map: '/mapdata/vmap_wms.map', layers: 'basic', format: 'image/jpeg'}); + map.addLayer(layer); + map.zoomTo(0); + map.addControl(control); + t.eq(control.div.firstChild.style.visibility, "visible", "top scale is present."); + t.eq(control.div.lastChild.style.visibility, "visible", "bottom scale is present."); + t.eq(control.div.firstChild.innerHTML, "100 km", "top scale has correct text."); + t.eq(control.div.lastChild.innerHTML, "100 mi", "bottom scale has correct text."); + map.destroy(); + } + + function test_calcMeters (t) { + t.plan(5); + // this example is taken from the projected-map.html OpenLayers example + var lat = 900863; + var lon = 235829; + var zoom = 6; + var map = new OpenLayers.Map( 'map' ); + var basemap = new OpenLayers.Layer.WMS( "Boston", + "http://boston.freemap.in/cgi-bin/mapserv?", + { + map: '/www/freemap.in/boston/map/gmaps.map', + layers: 'border,water,roads,rapid_transit,buildings', + format: 'png', + transparent: 'off' + }, + + { + maxExtent: new OpenLayers.Bounds(33861, 717605, 330846, 1019656), + maxResolution: 296985/1024, + projection:"EPSG:2805", // Used in WMS/WFS requests. + units: "m" // Only neccesary for working with scales. + } ); + + map.addLayer(basemap); + map.setCenter(new OpenLayers.LonLat(lon, lat), zoom); + map.addControl(new OpenLayers.Control.LayerSwitcher()); + var control = new OpenLayers.Control.ScaleLine(); + t.ok( control instanceof OpenLayers.Control.ScaleLine, "new OpenLayers.Control returns object" ); + map.addControl(control); + t.eq(control.div.firstChild.style.visibility, "visible", "top scale is present."); + t.eq(control.div.lastChild.style.visibility, "visible", "bottom scale is present."); + t.eq(control.div.firstChild.innerHTML, "200 m", "top scale has correct text."); + t.eq(control.div.lastChild.innerHTML, "1000 ft", "bottom scale has correct text."); + map.destroy(); + } + + function test_useArguments (t) { + t.plan(5); + var control = new OpenLayers.Control.ScaleLine({topOutUnits: 'dd'} ); + t.ok( control instanceof OpenLayers.Control.ScaleLine, "new OpenLayers.Control returns object" ); + var map = new OpenLayers.Map('map'); + var layer = new OpenLayers.Layer.WMS('Test Layer', "http://octo.metacarta.com/cgi-bin/mapserv", {map: '/mapdata/vmap_wms.map', layers: 'basic', format: 'image/jpeg'}); + map.addLayer(layer); + map.zoomTo(0); + map.addControl(control); + t.eq(control.div.firstChild.style.visibility, "visible", "top scale is present."); + t.eq(control.div.lastChild.style.visibility, "visible", "bottom scale is present."); + t.eq(control.div.firstChild.innerHTML, "100 dd", "top scale has correct text."); + t.eq(control.div.lastChild.innerHTML, "5000 mi", "bottom scale has correct text."); + map.destroy(); + } + + function test_respectZoom (t) { + if(validkey) { + t.plan( 4 ); + } else { + t.plan( 3 ); + } + // ok, switch the units we use for zoomed in values. This will test that we're both + // correctly respecting all specified parameters and that we're switching to the + // "in" units when zoomed in + var control = new OpenLayers.Control.ScaleLine({topOutUnits : "mi", bottomOutUnits: "km", topInUnits: 'ft', bottomInUnits: 'm'}); + t.ok( control instanceof OpenLayers.Control.ScaleLine, "new OpenLayers.Control returns object" ); + var map = new OpenLayers.Map('map'); + var layer = new OpenLayers.Layer.WMS('Test Layer', "http://octo.metacarta.com/cgi-bin/mapserv", {map: '/mapdata/vmap_wms.map', layers: 'basic', format: 'image/jpeg'}); + map.addLayer(layer); + map.zoomTo(0); + map.addControl(control); + var widthIsOk = true; + for (var i=0; i<map.numZoomLevels && widthIsOk; i++) { + map.zoomTo(i); + var w1 = parseInt(control.eTop.style.width); + var w2 = parseInt(control.eBottom.style.width); + widthIsOk = w1 <= control.maxWidth && w2 <= control.maxWidth; + } + t.ok(widthIsOk, "respects maxWidth at all zoom levels in dd"); + + widthIsOk = true; + control.maxWidth = 200; + for (var i=0; i<map.numZoomLevels && widthIsOk; i++) { + map.zoomTo(i); + var w1 = parseInt(control.eTop.style.width); + var w2 = parseInt(control.eBottom.style.width); + widthIsOk = w1 <= control.maxWidth && w2 <= control.maxWidth; + } + t.ok(widthIsOk, "respects modified maxWidth at all zoom levels in dd"); + + if (validkey) { + var map = new OpenLayers.Map('map'); + var layer = new OpenLayers.Layer.Google('Goog Layer'); + var control = new OpenLayers.Control.ScaleLine({topOutUnits : "mi", bottomOutUnits: "km", topInUnits: 'ft', bottomInUnits: 'm'}); + map.addLayer(layer); + map.zoomTo(0); + map.addControl(control); + var widthIsOk = true; + for (var i=0; i<map.numZoomLevels && widthIsOk; i++) { + map.zoomTo(i); + var w1 = parseInt(control.eTop.style.width); + var w2 = parseInt(control.eBottom.style.width); + widthIsOk = w1 <= control.maxWidth && w2 <= control.maxWidth; + } + t.ok(widthIsOk, "respects maxWidth at all zoom levels in m"); + } else { + t.debug_print("Google tests can't be run from " + + window.location.host); + } + + map.destroy(); + } + function test_ie_oneunit(t) { + t.plan(2); + var control = new OpenLayers.Control.ScaleLine({bottomOutUnits:'',bottomInUnits:'',maxWidth:150}); + t.ok(control instanceof OpenLayers.Control.ScaleLine, "new OpenLayers.Control returns object" ); + var map = new OpenLayers.Map('map'); + var layer = new OpenLayers.Layer.WMS('Test Layer', "bogus", {}); + map.addLayer(layer); + map.zoomTo(0); + map.addControl(control); + t.ok(true, "invisible bottom scale doesn't cause scaleline failure (IE only)"); + map.destroy(); + } + </script> +</head> +<body> + <a id="ScaleLine" href="">ScaleLine</a> <br/> + <div id="map" style="width: 1024px; height: 512px;"/> +</body> +</html> diff --git a/misc/openlayers/tests/Control/SelectFeature.html b/misc/openlayers/tests/Control/SelectFeature.html new file mode 100644 index 0000000..6e522e7 --- /dev/null +++ b/misc/openlayers/tests/Control/SelectFeature.html @@ -0,0 +1,632 @@ +<html> +<head> + <script src="../OLLoader.js"></script> + <script type="text/javascript"> + function test_Control_SelectFeature_constructor(t) { + t.plan(5); + var options = { +// geometryTypes: "foo" + }; + var layer = "bar"; + var control = new OpenLayers.Control.SelectFeature([layer], options); + t.ok(control instanceof OpenLayers.Control.SelectFeature, + "new OpenLayers.Control.SelectFeature returns an instance"); + t.eq(control.layers[0], "bar", + "constructor with array of layers sets layer correctly"); +// t.eq(control.handlers.feature.geometryTypes, "foo", +// "constructor sets options correctly on feature handler"); + t.ok(control.layer instanceof OpenLayers.Layer.Vector.RootContainer, "control has a root container layer if constructor was called with an array of layers"); + + control = new OpenLayers.Control.SelectFeature(layer, options); + t.eq(control.layers, null, "this.layers is null if constructor called with a single layer"); + t.eq(control.layer, layer, "this.layer holds the layer that was passed with the constructor if called with a single layer") + } + + function test_Control_SelectFeature_destroy(t) { + t.plan(2); + var map = new OpenLayers.Map("map"); + var layer = new OpenLayers.Layer.Vector(); + map.addLayer(layer); + var control = new OpenLayers.Control.SelectFeature(layer, {box: true}); + control.handlers.feature.deactivate = function() { + t.ok(true, + "control.deactivate calls deactivate on feature handler"); + } + control.handlers.box.deactivate = function() { + t.ok(true, + "control.deactivate calls deactivate on box handler"); + } +// should nullify the layer property here + control.destroy(); + + } + + function test_Control_SelectFeature_select(t) { + t.plan(4); + var map = new OpenLayers.Map("map"); + var layer1 = new OpenLayers.Layer.Vector(); + var layer2 = new OpenLayers.Layer.Vector(); + map.addLayers([layer1, layer2]); + var control = new OpenLayers.Control.SelectFeature([layer1, layer2]); + var feature1 = new OpenLayers.Feature.Vector(new OpenLayers.Geometry.Point(0,1)); + var feature2 = new OpenLayers.Feature.Vector(new OpenLayers.Geometry.Point(1,0)); + layer1.addFeatures(feature1); + layer2.addFeatures(feature2); + var drawFeature = function(feature, style) { + feature.layer.styleMap.createSymbolizer(feature, style); + } + layer1.drawFeature = drawFeature; + layer2.drawFeature = drawFeature; + control.select(feature1); + t.eq(feature1.renderIntent, "select", "render intent is set to select"); + control.select(feature2); + t.eq(feature2.renderIntent, "select", "render intent is set to select"); + control.unselect(feature1); + t.eq(feature1.renderIntent, "default", "render intent is set back to default"); + control.unselect(feature2); + t.eq(feature2.renderIntent, "default", "render intent is set back to default"); + } + + function test_Control_SelectFeature_clickFeature(t) { + t.plan(6); + // mock up layer + var layer = { + selectedFeatures: [], + drawFeature: function() {}, + events: { + triggerEvent: function() {} + } + }; + // mock up active control + var control = new OpenLayers.Control.SelectFeature(layer); + control.handlers.feature = { + evt: {} + }; + // mock up features + var features = new Array(4); + for(var i=0; i<features.length; ++i) { + features[i] = { + id: Math.random(), + tested: 0, + style: "", + layer: layer + }; + } + + // test that onSelect gets called properly + control.onSelect = function(feature) { + feature.tested += 1; + t.eq(feature.id, features[feature.index].id, + "onSelect called with proper feature (" + feature.index + ")"); + t.eq(feature.tested, feature.test, + "onSelect called only once for feature (" + feature.index + ")"); + t.ok(this == control, "onSelect called in the scope of the control if control.scope is not provided"); + } + + // test that onUnselect gets called properly + control.onUnselect = function(feature) { + feature.tested += 1; + t.eq(feature.id, features[feature.index].id, + "onUnselect called with proper feature (" + feature.index + ")"); + t.eq(feature.tested, feature.test, + "onUnselect called only once for feature (" + feature.index + ")"); + t.ok(this == control, "onUnselect called in the scope of the control if control.scope is not provided"); + } + + // mock up first click on first feature (runs 3 tests from onSelect) + var feature = features[0]; + feature.index = 0; + feature.test = 1; + control.clickFeature(feature); + + // mock up second click on first feature (runs no tests - already selected) + control.toggle = false; + control.clickFeature(feature); + + // mock up second click on first feature (runs 3 tests from onUnselect) + control.toggle = true; + feature.test = 2; + control.clickFeature(feature); + + + } + + function test_box(t) { + t.plan(5); + var map = new OpenLayers.Map("map"); + var layer = new OpenLayers.Layer.Vector(); + map.addLayer(layer); + map.setBaseLayer(layer); + map.setCenter(new OpenLayers.LonLat(1,1)); + var control = new OpenLayers.Control.SelectFeature(layer, {'multiple': true, box: true }); + var feature = new OpenLayers.Feature.Vector(new OpenLayers.Geometry.Point(0,0)); + var feature2 = new OpenLayers.Feature.Vector(new OpenLayers.Geometry.Point(1,1)); + var feature3 = new OpenLayers.Feature.Vector(new OpenLayers.Geometry.Point(-2,-2)); + var feature4 = new OpenLayers.Feature.Vector(new OpenLayers.Geometry.LineString([ + new OpenLayers.Geometry.Point(0, 0), new OpenLayers.Geometry.Point(1, 1) + ])); + layer.addFeatures([feature, feature2, feature3, feature4]); + control.setMap(map); + map.getLonLatFromPixel = function(arg) { + return new OpenLayers.LonLat(arg.x, arg.y); + } + control.selectBox(new OpenLayers.Bounds(-1, -1, 2, 2)); + t.eq(layer.selectedFeatures.length, 3, "box around all features selects 3 features"); + + control.selectBox(new OpenLayers.Bounds(-3, -3, -1, -1)); + t.eq(layer.selectedFeatures.length, 4, "box around other features doesn't turn off already selected features."); + + control.multipleSelect = function() { + return false; + }; + control.selectBox(new OpenLayers.Bounds(-3, -3, -1, -1)); + t.eq(layer.selectedFeatures.length, 1, "box around other features correctly turns off already selected features."); + + control.geometryTypes = null; + control.selectBox(new OpenLayers.Bounds(-100, -100, 100, 100)); + t.eq(layer.selectedFeatures.length, layer.features.length, "all features selected with no geometryTypes filter"); + + control.geometryTypes = ["OpenLayers.Geometry.Point"]; + control.selectBox(new OpenLayers.Bounds(-100, -100, 100, 100)); + t.eq(layer.selectedFeatures.length, 3, "3 features selected with geometryTypes filter"); + + + } + + + function test_selectBox_events(t){ + t.plan(8); + var map = new OpenLayers.Map("map"); + var layer1 = new OpenLayers.Layer.Vector(); + map.addLayer(layer1); + map.setBaseLayer(layer1); + var layer2 = new OpenLayers.Layer.Vector(); + map.addLayer(layer2); + map.setCenter(new OpenLayers.LonLat(1,1)); + var feature = new OpenLayers.Feature.Vector(new OpenLayers.Geometry.Point(1,1)); + layer1.addFeatures([feature]); + var control = new OpenLayers.Control.SelectFeature(layer1); + control.setMap(map); + map.getLonLatFromPixel = function(arg) { + return new OpenLayers.LonLat(arg.x, arg.y); + } + control.activate(); + var firesBoxselectionstart = false; + var beforeSelectingNumberOfFeatures = -1; + var firesBoxselectionend = false; + var afterSelectingNumberOfFeatures = -1; + control.events.register("boxselectionstart",null, function(e){ + firesBoxselectionstart=true; + t.eq(e.layers.length,1,"right number of layers in event boxselectionstart"); + t.eq(layer1.id, e.layers[0].id,"correct layer in event boxselectionstart"); + beforeSelectingNumberOfFeatures = e.layers[0].selectedFeatures.length; + }); + control.events.register("boxselectionend",null, function(e){ + firesBoxselectionend=true; + t.eq(e.layers.length,1,"right number of layers in event boxselectionend"); + t.eq(layer1.id, e.layers[0].id,"correct layer in event boxselectionend"); + afterSelectingNumberOfFeatures = e.layers[0].selectedFeatures.length; + }); + var bounds = new OpenLayers.Bounds(-1, -1, 2, 2); + control.selectBox(bounds); + t.ok(firesBoxselectionstart,"selectBox fires boxselectionstart event"); + t.eq(beforeSelectingNumberOfFeatures,0,"boxselectionstart fires before selection of feature"); + t.ok(firesBoxselectionend,"selectBox fires boxselectionend event"); + t.eq(afterSelectingNumberOfFeatures,1,"boxselectionend fires after feature selected"); + } + function test_Control_SelectFeature_activate(t) { + t.plan(4); + var map = new OpenLayers.Map("map"); + var layer = new OpenLayers.Layer.Vector(); + map.addLayer(layer); + var control = new OpenLayers.Control.SelectFeature(layer, {box: true}); + map.addControl(control); + t.ok(!control.handlers.feature.active, + "feature handler is not active prior to activating control"); + t.ok(!control.handlers.box.active, + "box handler is not active prior to activating control"); + control.activate(); + t.ok(control.handlers.feature.active, + "feature handler is active after activating control"); + t.ok(control.handlers.box.active, + "box handler is active after activating control"); + } + + function test_Control_SelectFeature_deactivate(t) { + t.plan(2); + var map = new OpenLayers.Map("map"); + var layer = new OpenLayers.Layer.Vector(); + map.addLayer(layer); + var control = new OpenLayers.Control.SelectFeature(layer, {box: true}); + map.addControl(control); + + control.activate(); + control.handlers.feature.deactivate = function() { + t.ok(true, + "control.deactivate calls deactivate on feature handler"); + OpenLayers.Handler.Feature.prototype.deactivate.apply(this, arguments); + } + control.handlers.box.deactivate = function() { + t.ok(true, + "control.deactivate calls deactivate on box handler"); + } + control.deactivate(); + } + + function test_highlighyOnly(t) { + t.plan(23); + + /* + * setup + */ + + var map, layer, ctrl1, ctrl2, _feature, feature, evt, _style; + + map = new OpenLayers.Map("map"); + layer = new OpenLayers.Layer.Vector("name", {isBaseLayer: true}); + map.addLayer(layer); + + ctrl1 = new OpenLayers.Control.SelectFeature(layer, { + highlightOnly: false, + hover: false + }); + map.addControl(ctrl1); + + ctrl2 = new OpenLayers.Control.SelectFeature(layer, { + highlightOnly: true, + hover: true + }); + map.addControl(ctrl2); + + ctrl2.activate(); + ctrl1.activate(); + + feature = new OpenLayers.Feature.Vector(); + feature.layer = layer; + + // override the layer's getFeatureFromEvent func so that it always + // returns the feature referenced to by _feature + layer.getFeatureFromEvent = function(evt) { return _feature; }; + + evt = {xy: new OpenLayers.Pixel(Math.random(), Math.random())}; + + map.zoomToMaxExtent(); + + /* + * tests + */ + + // with renderIntent + + ctrl1.renderIntent = "select"; + ctrl2.renderIntent = "temporary"; + + // mouse over feature, feature is drawn with "temporary" + _feature = feature; + evt.type = "mousemove"; + map.events.triggerEvent("mousemove", evt); + t.eq(feature.renderIntent, "temporary", + "feature drawn with expected render intent after \"mouseover\""); + t.eq(feature._lastHighlighter, ctrl2.id, + "feature._lastHighlighter properly set after \"mouseover\""); + t.eq(feature._prevHighlighter, undefined, + "feature._prevHighlighter properly set after \"mouseover\""); + + // click in feature, feature is drawn with "select" + _feature = feature; + evt.type = "click"; + map.events.triggerEvent("click", evt); + t.eq(feature.renderIntent, "select", + "feature drawn with expected render intent after \"clickin\""); + t.eq(feature._lastHighlighter, ctrl1.id, + "feature._lastHighlighter properly set after \"clickin\""); + t.eq(feature._prevHighlighter, ctrl2.id, + "feature._prevHighlighter properly set after \"clickin\""); + + // mouse out of feature, feature is still drawn with "select" + _feature = null; + evt.type = "mousemove"; + map.events.triggerEvent("mousemove", evt); + t.eq(feature.renderIntent, "select", + "feature drawn with expected render intent after \"mouseout\""); + t.eq(feature._lastHighlighter, ctrl1.id, + "feature._lastHighlighter properly set after \"nouseout\""); + t.ok(feature._prevHighlighter, ctrl2.id, + "feature._prevHighlighter properly set after \"mouseout\""); + + // mouse over feature again, feature is drawn with "temporary" + _feature = feature; + evt.type = "mousemove"; + map.events.triggerEvent("mousemove", evt); + t.eq(feature.renderIntent, "temporary", + "feature drawn with expected render intent after \"mouseover\""); + t.eq(feature._lastHighlighter, ctrl2.id, + "feature._lastHighlighter properly set after \"mouseover\""); + t.eq(feature._prevHighlighter, ctrl1.id, + "feature._prevHighlighter properly set after \"mouseover\""); + + // mouve out of feature again, feature is still drawn with "select" + _feature = null; + evt.type = "mousemove"; + map.events.triggerEvent("mousemove", evt); + t.eq(feature.renderIntent, "select", + "feature drawn with expected render intent after \"mouseout\""); + t.eq(feature._lastHighlighter, ctrl1.id, + "feature._lastHighlighter properly set after \"mouseout\""); + t.eq(feature._prevHighlighter, undefined, + "feature._prevHighlighter properly set after \"mouseout\""); + + // click out of feature, feature is drawn with "default" + _feature = null; + evt.type = "click"; + map.events.triggerEvent("click", evt); + t.eq(feature.renderIntent, "default", + "feature drawn with expected render intent after \"clickout\""); + t.eq(feature._lastHighlighter, undefined, + "feature._lastHighlighter properly set after \"clickout\""); + t.eq(feature._prevHighlighter, undefined, + "feature._prevHighlighter properly set after \"clickout\""); + + // with selectStyle + + ctrl1.selectStyle = OpenLayers.Feature.Vector.style["select"]; + ctrl2.selectStyle = OpenLayers.Feature.Vector.style["temporary"]; + + layer.renderer.drawFeature = function(f, s) { + var style = OpenLayers.Feature.Vector.style[_style]; + t.eq(s, style, "renderer drawFeature called with expected style obj (" + _style + ")"); + }; + + // mouse over feature, feature is drawn with "temporary" + _feature = feature; + _style = "temporary"; + evt.type = "mousemove"; + map.events.triggerEvent("mousemove", evt); + + // click in feature, feature is drawn with "select" + _feature = feature; + _style = "select"; + evt.type = "click"; + map.events.triggerEvent("click", evt); + + // mouse out of feature, feature is still drawn with "select" and + // the renderer drawFeature method should not be called + _feature = null; + evt.type = "mousemove"; + map.events.triggerEvent("mousemove", evt); + + // mouse over feature again, feature is drawn with "temporary" + _feature = feature; + _style = "temporary"; + evt.type = "mousemove"; + map.events.triggerEvent("mousemove", evt); + + // mouve out of feature again, feature is still drawn with "select" + _feature = null; + _style = "select"; + evt.type = "mousemove"; + map.events.triggerEvent("mousemove", evt); + + // click out of feature, feature is drawn with "default" + _feature = null; + _style = "default"; + evt.type = "click"; + map.events.triggerEvent("click", evt); + } + + // test for http://trac.openlayers.org/ticket/2812 + function test_highlightOnly_toggle(t) { + t.plan(8); + + /* + * setup + */ + + var map, layer, ctrl1, ctrl2, _feature, feature, evt, _style; + + map = new OpenLayers.Map("map"); + layer = new OpenLayers.Layer.Vector("name", {isBaseLayer: true}); + map.addLayer(layer); + + ctrl1 = new OpenLayers.Control.SelectFeature(layer, { + highlightOnly: false, + hover: false, + clickout: false, + toggle: true + }); + map.addControl(ctrl1); + + ctrl2 = new OpenLayers.Control.SelectFeature(layer, { + highlightOnly: true, + hover: true + }); + map.addControl(ctrl2); + + ctrl2.activate(); + ctrl1.activate(); + + feature = new OpenLayers.Feature.Vector(); + feature.layer = layer; + + // override the layer's getFeatureFromEvent func so that it always + // returns the feature referenced to by _feature + layer.getFeatureFromEvent = function(evt) { return _feature; }; + + evt = {xy: new OpenLayers.Pixel(Math.random(), Math.random())}; + + map.zoomToMaxExtent(); + + /* + * tests + */ + + // with renderIntent + + ctrl1.renderIntent = "select"; + ctrl2.renderIntent = "temporary"; + + // mouse over feature, feature is drawn with "temporary" + _feature = feature; + evt.type = "mousemove"; + map.events.triggerEvent("mousemove", evt); + t.eq(feature.renderIntent, "temporary", + "feature drawn with expected render intent after \"mouseover\""); + + // click in feature, feature is drawn with "select" + _feature = feature; + evt.type = "click"; + map.events.triggerEvent("click", evt); + t.eq(feature.renderIntent, "select", + "feature drawn with expected render intent after \"clickin\""); + + // mouse out of feature, feature is still drawn with "select" + _feature = null; + evt.type = "mousemove"; + map.events.triggerEvent("mousemove", evt); + t.eq(feature.renderIntent, "select", + "feature drawn with expected render intent after \"mouseout\""); + + // mouse over feature again, feature is drawn with "temporary" + _feature = feature; + evt.type = "mousemove"; + map.events.triggerEvent("mousemove", evt); + t.eq(feature.renderIntent, "temporary", + "feature drawn with expected render intent after \"mouseover\""); + + // click in feature again, feature is drawn with "default" + _feature = feature; + evt.type = "click"; + map.events.triggerEvent("click", evt); + t.eq(feature.renderIntent, "default", + "feature drawn with expected render intent after \"clickin\""); + + // mouse out of feature again, feature is still drawn with "default" + _feature = null; + evt.type = "mousemove"; + map.events.triggerEvent("mousemove", evt); + t.eq(feature.renderIntent, "default", + "feature drawn with expected render intent after \"mouseout\""); + + // mouse over feature again, feature is drawn with "temporary" + _feature = feature; + evt.type = "mousemove"; + map.events.triggerEvent("mousemove", evt); + t.eq(feature.renderIntent, "temporary", + "feature drawn with expected render intent after \"mouseover\""); + + // mouse out of feature again, feature is still drawn with "default" + _feature = null; + evt.type = "mousemove"; + map.events.triggerEvent("mousemove", evt); + t.eq(feature.renderIntent, "default", + "feature drawn with expected render intent after \"mouseout\""); + } + + function test_setLayer(t) { + t.plan(5); + var map = new OpenLayers.Map("map"); + var layer1 = new OpenLayers.Layer.Vector(); + var layer2 = new OpenLayers.Layer.Vector(); + var layer3 = new OpenLayers.Layer.Vector(); + map.addLayer(layer1, layer2, layer3); + // initialize it with a single layer + var control = new OpenLayers.Control.SelectFeature(layer1); + map.addControl(control); + control.activate(); + control.setLayer([layer2, layer3]); + t.eq(control.layer instanceof OpenLayers.Layer.Vector.RootContainer, true, "Root container created correctly on setLayer with multiple layers"); + t.eq(control.active, true, "Control should be active still after using setLayer"); + t.eq((control.handlers.feature.layer === control.layer), true, "Feature handler layer set correctly"); + control.destroy(); + // initialize with an array of layers + control = new OpenLayers.Control.SelectFeature([layer1, layer2]); + t.eq((control.layers !== null), true, "Control has a layers property"); + control.setLayer(layer3); + t.eq((control.layers === null), true, "When using setLayer with a single layer, the layers property is removed if present before"); + map.destroy(); + } + + function test_setLayerWithRemoving(t) { + t.plan(2); + var map = new OpenLayers.Map("map"); + var layer1 = new OpenLayers.Layer.Vector(); + var layer2 = new OpenLayers.Layer.Vector(); + map.addLayer(layer1, layer2); + // initialize it with a single layer + var control = new OpenLayers.Control.SelectFeature(layer1); + map.addControl(control); + control.activate(); + var noError = null; + map.events.register("preremovelayer", this, function(e) { + try { + control.setLayer(layer2); + } catch (e) { + noError = e; + } + }); + layer1.destroy(); + t.eq(layer2.id, control.layer.id, "Layer is set correctly without error"); + t.eq(noError, null,"No error occured during setLayer. Error is: '"+noError+"'"); + control.destroy(); + map.destroy(); + } + + function test_destroy(t) { + t.plan(1); + var map = new OpenLayers.Map("map"); + var layer1 = new OpenLayers.Layer.Vector(); + map.addLayer(layer1); + var control = new OpenLayers.Control.SelectFeature([layer1]); + map.addControl(control); + control.activate(); + control.destroy(); + t.eq(layer1.renderer.getRenderLayerId(), layer1.id, + "Root container moved correctly when control is destroyed and layers was an array parameter"); + } + + function test_unselectAll(t) { + t.plan(2); + + var layer = new OpenLayers.Layer.Vector(); + + var control = new OpenLayers.Control.SelectFeature(layer); + + var feature1 = new OpenLayers.Feature.Vector(); + feature1.id = 1; + var feature2 = new OpenLayers.Feature.Vector(); + feature2.id = 2; + var feature3 = new OpenLayers.Feature.Vector(); + feature3.id = 3; + var feature4 = new OpenLayers.Feature.Vector(); + feature4.id = 4; + + layer.addFeatures([feature1, feature2, feature3, feature4]); + + control.select(feature1); + control.select(feature2); + control.select(feature3); + control.select(feature4); + + layer.events.on({ + featureunselected: function(e) { + // we change the selectedFeatures array while + // unselectAll is iterating over that array. + if(feature2.layer) { + layer.removeFeatures([feature2]); + } + } + }); + + control.unselectAll({except: feature3}); + t.eq(layer.selectedFeatures.length, 1, + 'unselectAll unselected all but one'); + t.eq(layer.selectedFeatures[0].id, 3, + 'the remaining selected features is the one expected'); + } + + </script> +</head> +<body> + <div id="map" style="width: 400px; height: 250px;"/> +</body> +</html> diff --git a/misc/openlayers/tests/Control/Snapping.html b/misc/openlayers/tests/Control/Snapping.html new file mode 100644 index 0000000..f065f66 --- /dev/null +++ b/misc/openlayers/tests/Control/Snapping.html @@ -0,0 +1,448 @@ +<html> +<head> + <script src="../OLLoader.js"></script> + <script type="text/javascript"> + + function test_initialize(t) { + + t.plan(5); + + // construct with a single layer + var layer = new OpenLayers.Layer.Vector(); + var control = new OpenLayers.Control.Snapping({ + layer: layer + }); + + t.ok(control.layer === layer, "[a] source layer properly set"); + t.eq(control.targets.length, 1, "[a] one target layer"); + t.ok(control.targets[0].layer === layer, "[a] target set"); + control.destroy(); + + // construct with a different target, default target config + var layer2 = new OpenLayers.Layer.Vector(); + control = new OpenLayers.Control.Snapping({ + layer: layer, + targets: [layer2] + }); + + t.eq(control.targets.length, 1, "[b] one target layer"); + t.ok(control.targets[0].layer == layer2, "[b] target set"); + control.destroy(); + } + + function test_setLayer(t) { + + t.plan(4); + + var layer = new OpenLayers.Layer.Vector(); + var control = new OpenLayers.Control.Snapping(); + control.setLayer(layer); + + t.ok(control.layer === layer, "layer properly set"); + + // confirm that the control is deactivated and reactivated when setting new layer + var log = { + activated: 0, + deactivated: 0 + }; + control.activate = function() { + log.activated++; + } + control.deactivate = function() { + log.deactivated++; + } + control.active = true; + + var layer2 = new OpenLayers.Layer.Vector(); + control.setLayer(layer2); + + t.eq(log.deactivated, 1, "control deactivated"); + t.ok(control.layer === layer2, "layer properly reset"); + t.eq(log.activated, 1, "control reactivated"); + + control.destroy(); + } + + function test_setTargets(t) { + + t.plan(4); + + var layer1 = new OpenLayers.Layer.Vector(); + var layer2 = new OpenLayers.Layer.Vector(); + var control = new OpenLayers.Control.Snapping(); + + var log = { + addTarget: [], + addTargetLayer: [] + }; + control.addTarget = function(target) { + log.addTarget.push(target); + }; + control.addTargetLayer = function(target) { + log.addTargetLayer.push(target); + }; + + control.setTargets([layer1, {layer: layer2}]); + + t.eq(log.addTargetLayer.length, 1, "setTargetLayer called once"); + t.ok(log.addTargetLayer[0] === layer1, "setTargetLayer called with layer1"); + t.eq(log.addTarget.length, 1, "setTarget called once"); + t.ok(log.addTarget[0].layer === layer2, "setTarget called with layer2"); + + control.destroy(); + } + + function test_addTarget(t) { + t.plan(5); + + var layer = new OpenLayers.Layer.Vector(); + + var control = new OpenLayers.Control.Snapping({ + defaults: { + nodeTolerance: 30, + tolerance: 40 + } + }); + + var log = {}; + control.addTarget({layer: layer}); + + t.eq(control.targets.length, 1, "single target"); + var target = control.targets[0]; + t.ok(target.layer === layer, "correct target layer"); + t.eq(target.nodeTolerance, 30, "correct nodeTolerance"); + t.eq(target.edgeTolerance, 40, "correct edgeTolerance"); + t.eq(target.vertexTolerance, 40, "correct vertexTolerance"); + + control.destroy(); + } + + function test_removeTargetLayer(t) { + + t.plan(3); + + var layer1 = new OpenLayers.Layer.Vector(); + var layer2 = new OpenLayers.Layer.Vector(); + var layer3 = new OpenLayers.Layer.Vector(); + var control = new OpenLayers.Control.Snapping({ + targets: [layer1, layer2, layer3] + }); + + control.removeTargetLayer(layer2); + + t.eq(control.targets.length, 2, "correct targets length"); + t.ok(control.targets[0].layer === layer1, "layer1 remains"); + t.ok(control.targets[1].layer === layer3, "layer3 remains"); + + control.destroy(); + + } + + function test_activate(t) { + + t.plan(4); + var layer = new OpenLayers.Layer.Vector(); + var control = new OpenLayers.Control.Snapping({ + layer: layer + }); + + control.activate(); + + t.eq(layer.events.listeners.sketchmodified.length, 1, "one sketchmodified listener"); + t.ok(layer.events.listeners.sketchmodified[0].func === control.onSketchModified, "correct sketchmodified listener"); + t.eq(layer.events.listeners.vertexmodified.length, 1, "one vertexmodified listener"); + t.ok(layer.events.listeners.vertexmodified[0].func === control.onVertexModified, "correct vertexmodified listener"); + + control.destroy(); + } + + function test_deactivate(t) { + + t.plan(2); + var layer = new OpenLayers.Layer.Vector(); + var control = new OpenLayers.Control.Snapping({ + layer: layer + }); + + control.activate(); + control.deactivate(); + + t.eq(layer.events.listeners.sketchmodified.length, 0, "no sketchmodified listeners"); + t.eq(layer.events.listeners.vertexmodified.length, 0, "no vertexmodified listeners"); + + control.destroy(); + } + + function test_resolution_limits(t) { + t.plan(7); + + var map = new OpenLayers.Map("map", { + resolutions: [1], + maxExtent: new OpenLayers.Bounds(0, 0, 100, 100) + }); + + var layer = new OpenLayers.Layer.Vector(null, { + isBaseLayer: true + }); + layer.addFeatures([ + new OpenLayers.Feature.Vector(OpenLayers.Geometry.fromWKT( + "POINT(50 50)" + )) + ]); + + map.addLayer(layer); + map.zoomToMaxExtent(); + + var control = new OpenLayers.Control.Snapping({layer: layer}); + + var result; + var loc = new OpenLayers.Geometry.Point(49, 49); + + // 1) test a target with no constraints + control.setTargets([{layer: layer}]); + result = control.testTarget(control.targets[0], loc); + t.ok(result !== null, "1) target is eligible"); + + // 2) test a target with minResolution < map.resolution + control.setTargets([{layer: layer, minResolution: 0.5}]); + result = control.testTarget(control.targets[0], loc); + t.ok(result !== null, "2) target is eligible"); + + // 3) test a target with minResolution === map.resolution + control.setTargets([{layer: layer, minResolution: 1}]); + result = control.testTarget(control.targets[0], loc); + t.ok(result !== null, "3) target is eligible"); + + // 4) test a target with minResolution > map.resolution + control.setTargets([{layer: layer, minResolution: 1.5}]); + result = control.testTarget(control.targets[0], loc); + t.ok(result === null, "4) target is not eligible"); + + // 5) test a target with maxResolution < map.resolution + control.setTargets([{layer: layer, maxResolution: 0.5}]); + result = control.testTarget(control.targets[0], loc); + t.ok(result === null, "5) target is not eligible"); + + // 6) test a target with maxResolution === map.resolution + control.setTargets([{layer: layer, maxResolution: 1}]); + result = control.testTarget(control.targets[0], loc); + t.ok(result === null, "6) target is not eligible"); + + // 7) test a target with maxResolution > map.resolution + control.setTargets([{layer: layer, maxResolution: 1.5}]); + result = control.testTarget(control.targets[0], loc); + t.ok(result !== null, "7) target is eligible"); + + map.destroy(); + + } + + function test_filter(t) { + t.plan(3); + var map = new OpenLayers.Map("map", { + resolutions: [1], + maxExtent: new OpenLayers.Bounds(0, 0, 100, 100) + }); + + var layer1 = new OpenLayers.Layer.Vector(null, { + isBaseLayer: true + }); + var f1 = new OpenLayers.Feature.Vector(OpenLayers.Geometry.fromWKT( + "LINESTRING(0 0, 10 10, 20 20, 30 30)" + ), {foo: 'bar'}); + f1.fid = "FID1"; + var f2 = new OpenLayers.Feature.Vector(OpenLayers.Geometry.fromWKT( + "LINESTRING(11 10, 20 10, 30 10)" + ), {foo: 'bar'}); + f2.fid = "FID2"; + layer1.addFeatures([f1, f2]); + map.addLayers([layer1]); + map.zoomToMaxExtent(); + + var control = new OpenLayers.Control.Snapping({ + layer: layer1, + targets: [layer1], + defaults: {tolerance: 4} + }); + control.activate(); + + var result; + var loc = new OpenLayers.Geometry.Point(1, 1); + + control.setTargets([{layer: layer1}]); + result = control.testTarget(control.targets[0], loc); + t.ok(result !== null, "target is eligible without a filter set"); + var filter = new OpenLayers.Filter.Logical({ + type: OpenLayers.Filter.Logical.NOT, + filters: [ + new OpenLayers.Filter.FeatureId({fids: ["FID1", "FID2"]}) + ] + }); + control.setTargets([{layer: layer1, filter: filter}]); + result = control.testTarget(control.targets[0], loc); + t.ok(result === null, "target is not eligible with a filter set which excludes the target's features"); + filter = new OpenLayers.Filter.Comparison({type: OpenLayers.Filter.Comparison.NOT_EQUAL_TO, value: 'bar', property: 'foo'}); + control.setTargets([{layer: layer1, filter: filter}]); + result = control.testTarget(control.targets[0], loc); + t.ok(result === null, "target is not eligible with a filter set which excludes the target's features using a comparison filter"); + } + + function test_snapping(t) { + + t.plan(46); + + var map = new OpenLayers.Map("map", { + resolutions: [1], + maxExtent: new OpenLayers.Bounds(0, 0, 100, 100) + }); + + var layer1 = new OpenLayers.Layer.Vector(null, { + isBaseLayer: true + }); + layer1.addFeatures([ + new OpenLayers.Feature.Vector(OpenLayers.Geometry.fromWKT( + "LINESTRING(0 0, 10 10, 20 20, 30 30)" + )), + new OpenLayers.Feature.Vector(OpenLayers.Geometry.fromWKT( + "LINESTRING(11 10, 20 10, 30 10)" + )) + ]); + + var layer2 = new OpenLayers.Layer.Vector(); + layer2.addFeatures([ + new OpenLayers.Feature.Vector(OpenLayers.Geometry.fromWKT( + "LINESTRING(10 10, 20 20, 30 30)" + )), + new OpenLayers.Feature.Vector(OpenLayers.Geometry.fromWKT( + "LINESTRING(21 10, 20 20, 20 30)" + )) + ]); + + map.addLayers([layer1, layer2]); + map.zoomToMaxExtent(); + + var control = new OpenLayers.Control.Snapping({ + layer: layer1, + targets: [layer1, layer2], + defaults: {tolerance: 4} + }); + control.activate(); + map.addControl(control); + + // log beforesnap, snap, and unsnap events + var events = []; + function listener(event) { + events.push(event); + } + control.events.on({ + beforesnap: listener, + snap: listener, + unsnap: listener + }); + + // create a vertex and a convenience method for mocking the drag + var vertex = new OpenLayers.Geometry.Point(-100, -100); + function drag(x, y) { + var px = map.getPixelFromLonLat(new OpenLayers.LonLat(x, y)); + layer1.events.triggerEvent("vertexmodified", { + vertex: vertex, pixel: px + }); + } + + // mock up drag far from features + drag(-100, -100); + t.eq(events.length, 0, "no snapping"); + + // mock up drag near first node of first feature + drag(0, 1); + t.eq(events.length, 2, "[a] 2 events triggered"); + t.eq(events[0].type, "beforesnap", "[a] beforesnap triggered"); + t.eq(events[0].snapType, "node", "[a] beforesnap triggered for node"); + t.ok(events[0].point === vertex, "[a] beforesnap triggered with vertex"); + t.eq(events[0].x, 0, "[a] beforesnap triggered correct x"); + t.eq(events[0].y, 0, "[a] beforesnap triggered with correct y"); + t.eq(events[1].type, "snap", "[a] snap triggered"); + t.eq(events[1].snapType, "node", "[a] snap triggered for node"); + t.ok(events[1].point === vertex, "[a] snap triggered with point"); + t.eq(events[1].distance, 1, "[a] snap triggered correct distance"); + t.ok(events[1].layer === layer1, "[a] snap triggered with correct target layer"); + t.eq(vertex.x, 0, "[a] vertex x modified"); + t.eq(vertex.y, 0, "[a] vertex y modified"); + events = []; + + // mock up drag that unsnaps + drag(-100, -50); + t.eq(events.length, 1, "[b] 1 event triggered"); + t.eq(events[0].type, "unsnap", "[b] unsnap triggered"); + t.ok(events[0].point === vertex, "[b] unsnap triggered with vertex"); + t.eq(vertex.x, -100, "[b] vertex x unsnapped"); + t.eq(vertex.y, -50, "[b] vertex y unsnapped"); + events = []; + + // drag near node of second feature in first layer to demonstrate precedence of node snapping + drag(9, 10); + t.eq(events.length, 2, "[c] 2 events triggered"); + t.eq(events[0].type, "beforesnap", "[c] beforesnap triggered first"); + t.eq(events[1].type, "snap", "[c] snap triggered second"); + t.eq(events[1].snapType, "node", "[c] snap to node"); + // unsnap & reset + drag(-100, -50); + events = []; + + // drag near node of second feature in second layer to demonstrate greedy property + // with greedy true (default) the best target from the first layer with eligible targets is used + drag(22, 10); + t.eq(events.length, 2, "[d] 2 events triggered"); + t.eq(events[1].type, "snap", "[d] snap triggered second"); + t.eq(events[1].snapType, "vertex", "[d] snap to vertex"); + t.ok(events[1].layer === layer1, "[d] snap to vertex in first layer"); + t.eq(vertex.x, 20, "[d] vertex x modified"); + t.eq(vertex.y, 10, "[d] vertex y modified"); + // unsnap & reset + drag(-100, -50); + events = []; + + // do the same drag but with greedy false - this will look for best target in all layers + control.greedy = false; + drag(22, 10); + t.eq(events.length, 2, "[d] 2 events triggered"); + t.eq(events[1].type, "snap", "[d] snap triggered second"); + t.eq(events[1].snapType, "node", "[d] snap to node"); + t.ok(events[1].layer === layer2, "[d] snap to node in second layer"); + // unsnap & reset + drag(-100, -50); + control.greedy = true; + events = []; + + // demonstrate snapping on sketchstarted + var p = new OpenLayers.Geometry.Point(0, 1); + layer1.events.triggerEvent("sketchstarted", { + vertex: p, + feature: new OpenLayers.Feature.Vector(p) + }); + t.eq(events.length, 2, "[sketchstarted] 2 events triggered"); + t.eq(events[0].type, "beforesnap", "[sketchstarted] beforesnap triggered"); + t.eq(events[0].snapType, "node", "[sketchstarted] beforesnap triggered for node"); + t.ok(events[0].point === p, "[sketchstarted] beforesnap triggered with vertex"); + t.eq(events[0].x, 0, "[sketchstarted] beforesnap triggered correct x"); + t.eq(events[0].y, 0, "[sketchstarted] beforesnap triggered with correct y"); + t.eq(events[1].type, "snap", "[sketchstarted] snap triggered"); + t.eq(events[1].snapType, "node", "[sketchstarted] snap triggered for node"); + t.ok(events[1].point === p, "[sketchstarted] snap triggered with point"); + t.eq(events[1].distance, 1, "[sketchstarted] snap triggered correct distance"); + t.ok(events[1].layer === layer1, "[sketchstarted] snap triggered with correct target layer"); + t.eq(p.x, 0, "[sketchstarted] vertex x modified"); + t.eq(p.y, 0, "[sketchstarted] vertex y modified"); + // reset + events = []; + + map.destroy(); + + } + + </script> +</head> +<body> + <div id="map" style="width: 100px; height: 100px;"></div> +</body> +</html> diff --git a/misc/openlayers/tests/Control/Split.html b/misc/openlayers/tests/Control/Split.html new file mode 100644 index 0000000..e3a6eac --- /dev/null +++ b/misc/openlayers/tests/Control/Split.html @@ -0,0 +1,319 @@ +<html> +<head> + <script src="../OLLoader.js"></script> + <script type="text/javascript"> + + function test_initialize(t) { + + t.plan(4); + + var layer = new OpenLayers.Layer.Vector(); + var control; + + // construct with nothing + control = new OpenLayers.Control.Split(); + t.ok(control instanceof OpenLayers.Control, "instanceof OpenLayers.Control"); + t.ok(control instanceof OpenLayers.Control, "instanceof OpenLayers.Control.Split") + control.destroy(); + + // construct with a single target layer + control = new OpenLayers.Control.Split({ + layer: layer + }); + t.ok(control.layer === layer, "target layer properly set"); + control.destroy(); + + // construct with same target and source + control = new OpenLayers.Control.Split({ + layer: layer, + source: layer + }); + t.ok(control.source === layer, "source layer properly set"); + control.destroy(); + } + + function test_setSource(t) { + t.plan(5); + + var layer1 = new OpenLayers.Layer.Vector("foo", { + maxExtent: new OpenLayers.Bounds(-10, -10, 10, 10), + isBaseLayer: true + }); + var layer2 = new OpenLayers.Layer.Vector("foo", { + maxExtent: new OpenLayers.Bounds(-10, -10, 10, 10), + isBaseLayer: true + }); + + var control = new OpenLayers.Control.Split({layer: layer1}); + + var map = new OpenLayers.Map("map"); + map.addLayers([layer1, layer2]); + map.zoomToMaxExtent(); + map.addControl(control); + control.activate(); + + // confirm sketch hander created + t.ok(control.handler, "sketch handler created"); + t.eq(control.handler.active, true, "sketch handler active"); + + control.setSource(layer1); + t.ok(control.source === layer1, "layer1 properly set"); + t.ok(!control.handler, "no more sketch handler"); + + // activate and switch to new source layer + control.setSource(layer2); + t.ok(control.source === layer2, "layer2 properly set"); + + map.destroy(); + + } + + function test_activate(t) { + t.plan(8); + + var layer = new OpenLayers.Layer.Vector("foo", { + maxExtent: new OpenLayers.Bounds(-10, -10, 10, 10), + isBaseLayer: true + }); + var control = new OpenLayers.Control.Split({layer: layer}); + var map = new OpenLayers.Map("map"); + map.addLayer(layer); + map.zoomToMaxExtent(); + map.addControl(control); + + // test activation with no source layer + control.activate(); + t.eq(control.active, true, "control is active"); + t.ok(control.handler instanceof OpenLayers.Handler.Path, "line sketch handler created"); + t.ok(control.handler.callbacks.done, "done callback set on sketch handler"); + t.eq(control.handler.active, true, "sketch handler is active"); + + // change the source layer - this should call activate again + control.setSource(layer); + + t.eq(control.active, true, "control is still active"); + t.ok(control.source === layer, "source layer set"); + t.ok(layer.events.listeners.sketchcomplete, "sketchcomplete listener registered"); + t.ok(layer.events.listeners.afterfeaturemodified, "afterfeaturemodified listener registered"); + + map.destroy(); + + } + + function test_deactivate(t) { + + t.plan(7); + + var layer1 = new OpenLayers.Layer.Vector("foo", { + maxExtent: new OpenLayers.Bounds(-10, -10, 10, 10), + isBaseLayer: true + }); + var layer2 = new OpenLayers.Layer.Vector("bar", { + maxExtent: new OpenLayers.Bounds(-10, -10, 10, 10), + isBaseLayer: false + }); + var control = new OpenLayers.Control.Split({layer: layer1}); + var map = new OpenLayers.Map("map"); + map.addLayer(layer1); + map.addLayer(layer2); + map.zoomToMaxExtent(); + map.addControl(control); + + // activate and check sketch handler + control.activate(); + t.ok(control.handler, "sketch handler present"); + t.eq(control.handler.active, true, "sketch handler active"); + + // deactivate and check sketch handler + control.deactivate(); + t.eq(control.handler.active, false, "sketch handler deactivated"); + + // set a source layer + control.setSource(layer2); + + // activate and check that listeners are registered + control.activate(); + t.ok(layer2.events.listeners.sketchcomplete, "sketchcomplete listener registered"); + t.ok(layer2.events.listeners.afterfeaturemodified, "afterfeaturemodified listener registered"); + + // deactivate and confirm no draw related events + control.deactivate(); + t.eq(layer2.events.listeners.sketchcomplete.length, 0, "no sketchcomplete listeners"); + t.eq(layer2.events.listeners.afterfeaturemodified.length, 0, "no afterfeaturemodified listeners"); + + map.destroy(); + } + + function test_isEligible(t) { + + t.plan(10); + + var control = new OpenLayers.Control.Split(); + var geometry = OpenLayers.Geometry.fromWKT("LINESTRING(0 1, 1 2)"); + var feature = new OpenLayers.Feature.Vector( + geometry, + {foo: "bar"} + ); + + t.eq(control.isEligible(feature), true, "plain old feature is eligible"); + + feature.state = OpenLayers.State.DELETE; + t.eq(control.isEligible(feature), false, "feature slated for deletion is not eligible"); + delete feature.state; + t.eq(control.isEligible(feature), true, "feature with no state is eligible"); + + feature.geometry = new OpenLayers.Geometry.Point(1, 1); + t.eq(control.isEligible(feature), false, "feature with point geometry is not eligible"); + feature.geometry = new OpenLayers.Geometry.MultiLineString([geometry]); + t.eq(control.isEligible(feature), true, "feature with multilinestring geometry is eligible"); + + control.feature = feature; + t.eq(control.isEligible(feature), false, "source feature is not eligible as target"); + control.feature = new OpenLayers.Feature.Vector(); + t.eq(control.isEligible(feature), true, "feature is eligible if different than source feature"); + + control.targetFilter = new OpenLayers.Filter.Comparison({ + type: OpenLayers.Filter.Comparison.NOT_EQUAL_TO, + property: "foo", + value: "bar" + }); + t.eq(control.isEligible(feature), false, "feature is not eligible unless it matches filter"); + control.targetFilter.value = "baz"; + t.eq(control.isEligible(feature), true, "feature is eligible if it matches filter"); + + delete feature.geometry; + t.eq(control.isEligible(feature), false, "feature with no geometry is not eligible"); + + control.destroy(); + + } + + function test_considerSplit(t) { + + var layer = new OpenLayers.Layer.Vector(); + + var wkt = OpenLayers.Geometry.fromWKT; + var geoms = { + abc: wkt("LINESTRING(0 0, 2 2)"), + ab: wkt("LINESTRING(0 0, 1 1)"), + bc: wkt("LINESTRING(1 1, 2 2)"), + dbe: wkt("LINESTRING(2 0, 0 2)"), + db: wkt("LINESTRING(2 0, 1 1)"), + be: wkt("LINESTRING(1 1, 0 2)") + }; + + var Feature = OpenLayers.Feature.Vector; + var feats = { + abc: new Feature(geoms.abc), + ab: new Feature(geoms.ab), + bc: new Feature(geoms.bc), + dbe: new Feature(geoms.dbe), + db: new Feature(geoms.db), + be: new Feature(geoms.be) + }; + + function feature(id, options) { + var f = OpenLayers.Util.extend(feats[id].clone(), options); + // for testing, we want to check when features are destroyed + f.destroy = function() { + f.state = "destroyed"; + } + return f; + } + var DELETE = OpenLayers.State.DELETE; + var INSERT = OpenLayers.State.INSERT; + var UPDATE = OpenLayers.State.UPDATE; + + var cases = [{ + targets: [ + feature("abc") + ], + source: feature("dbe"), + splits: [{ + original: feature("abc", {state: "destroyed"}), + features: [feature("ab", {state: INSERT}), feature("bc", {state: INSERT})] + }, { + original: feature("dbe", {state: "destroyed"}), + features: [feature("db", {state: INSERT}), feature("be", {state: INSERT})] + }] + }, { + options: {deferDelete: true}, + targets: [ + feature("abc", {state: INSERT}) + ], + source: feature("dbe"), + splits: [{ + original: feature("abc", {state: "destroyed"}), + features: [feature("ab", {state: INSERT}), feature("bc", {state: INSERT})] + }, { + original: feature("dbe", {state: DELETE}), + features: [feature("db", {state: INSERT}), feature("be", {state: INSERT})] + }] + }, { + options: {deferDelete: true}, + targets: [ + feature("abc", {state: UPDATE}) + ], + source: feature("dbe", {state: INSERT}), + splits: [{ + original: feature("abc", {state: DELETE}), + features: [feature("ab", {state: INSERT}), feature("bc", {state: INSERT})] + }, { + original: feature("dbe", {state: "destroyed"}), + features: [feature("db", {state: INSERT}), feature("be", {state: INSERT})] + }] + }]; + + var count = 0; + var c, control, options, log, event, split; + for(var i=0; i<cases.length; ++i) { + c = cases[i]; + ++count; // test number of splits + for(var j=0; j<c.splits.length; ++j) { + split = c.splits[j]; + ++count; // test original state + ++count; // test original geometry + ++count; // test number of parts + for(var k=0; k<split.features.length; ++k) { + ++count; // test part state + ++count; // test part geometry + } + } + } + t.plan(count); + + for(var i=0; i<cases.length; ++i) { + c = cases[i]; + log = {events: []}; + options = OpenLayers.Util.extend({layer: layer, source: layer}, c.options); + control = new OpenLayers.Control.Split(options); + control.events.on({ + split: function(e) { + log.events.push(e); + } + }); + layer.features = c.targets; + control.considerSplit(c.source); + t.eq(log.events.length, c.splits.length, "case " + i + ": correct number of split events"); + for(var j=0; j<log.events.length; ++j) { + event = log.events[j]; + split = c.splits[j]; + t.eq(event.original.state, split.original.state, "case " + i + " split " + j + ": correct original state"); + t.geom_eq(event.original.geometry, split.original.geometry, "case " + i + " split " + j + ": correct original geometry"); + t.eq(event.features.length, split.features.length, "case " + i + " split " + j + ": correct number of parts"); + for(var k=0; k<split.features.length; ++k) { + t.eq(event.features[k].state, split.features[k].state, "case " + i + " split " + j + " feature " + k + ": correct state"); + t.geom_eq(event.features[k].geometry, split.features[k].geometry, "case " + i + " split " + j + " feature " + k + ": correct geometry"); + } + } + control.destroy(); + } + + } + + </script> +</head> +<body> + <div id="map" style="width: 100px; height: 100px;"></div> +</body> +</html> diff --git a/misc/openlayers/tests/Control/TouchNavigation.html b/misc/openlayers/tests/Control/TouchNavigation.html new file mode 100644 index 0000000..bffc225 --- /dev/null +++ b/misc/openlayers/tests/Control/TouchNavigation.html @@ -0,0 +1,155 @@ +<html> +<head> + <script src="../OLLoader.js"></script> + <script type="text/javascript"> + + function test_Control_TouchNavigation_constructor (t) { + t.plan( 2 ); + var options = {bar: "foo"}; + var temp = OpenLayers.Control.prototype.initialize; + OpenLayers.Control.prototype.initialize = function(opt) { + t.eq(opt, options, + "constructor calls parent with the correct options"); + }; + + var control = new OpenLayers.Control.TouchNavigation(options); + t.ok(control instanceof OpenLayers.Control.TouchNavigation, + "new OpenLayers.Control returns object"); + + OpenLayers.Control.prototype.initialize = temp; + } + + function test_Control_TouchNavigation_destroy(t) { + t.plan(6); + + var control = { + events: { + destroy: function() { + t.ok(true, "events destroyed"); + } + }, + deactivate: function() { + t.ok(true, "navigation control deactivated before being destroyed"); + }, + dragPan: { + destroy: function() { + t.ok(true, "dragPan destroyed"); + } + }, + handlers: { + click: { + destroy: function() { + t.ok(true, "clickHandler destroyed"); + } + } + } + }; + + //this will also trigger one test by calling OpenLayers.Control's destroy + // and three more for the destruction of dragPan, zoomBox, and wheelHandler + OpenLayers.Control.TouchNavigation.prototype.destroy.apply(control, []); + + t.eq(control.dragPan, null, "'dragPan' set to null"); + t.eq(control.handlers, null, "handlers set to null"); + } + + function test_documentDrag(t) { + + t.plan(2); + + /** + * These tests confirm that the documentDrag property is false by + * default and is passed on to the DragPan control. Tests of panning + * while dragging outside the viewport should go in the DragPan tests. + * Tests of the document events and appropriate callbacks from the + * handler should go in the Drag handler tests. + */ + + var nav = new OpenLayers.Control.TouchNavigation(); + t.eq(nav.documentDrag, false, "documentDrag false by default"); + + var map = new OpenLayers.Map({ + div: document.body, + controls: [new OpenLayers.Control.TouchNavigation({documentDrag: true})] + }); + nav = map.controls[0]; + + t.eq(nav.dragPan.documentDrag, true, "documentDrag set on the DragPan control"); + map.destroy(); + + } + + function test_dragPanOptions(t) { + + t.plan(2); + + var nav = new OpenLayers.Control.TouchNavigation(); + t.eq(nav.dragPanOptions, null, "dragPanOptions null by default"); + + var map = new OpenLayers.Map({ + div: document.body, + controls: [ + new OpenLayers.Control.TouchNavigation({ + dragPanOptions: {foo: 'bar'} + }) + ] + }); + nav = map.controls[0]; + + t.eq(nav.dragPan.foo, 'bar', + "foo property is set on the DragPan control"); + map.destroy(); + + } + + function test_clickHandlerOptions(t) { + + t.plan(3); + + var nav = new OpenLayers.Control.TouchNavigation(); + t.eq(nav.clickHandlerOptions, null, "clickHandlerOptions null by default"); + + var map = new OpenLayers.Map({ + div: document.body, + controls: [ + new OpenLayers.Control.TouchNavigation({ + clickHandlerOptions: {foo: "bar"} + }) + ] + }); + nav = map.controls[0]; + + t.eq(nav.handlers.click.foo, "bar", "foo property is set on the click handler"); + t.eq(nav.handlers.click.pixelTolerance, 2, "pixelTolerance is 2 by default"); + map.destroy(); + + } + + function test_zoomOut(t) { + t.plan(1); + + var map = new OpenLayers.Map('map', {zoomMethod: null}); + var layer = new OpenLayers.Layer.WMS( "OpenLayers WMS", + "http://labs.metacarta.com/wms/vmap0", + {layers: 'basic'} ); + map.addLayer(layer); + map.setCenter(new OpenLayers.LonLat(0, 0), 5); + var origSetTimeout = window.setTimeout; + window.setTimeout = function(fn) { fn(); return 'id'; }; + var control = new OpenLayers.Control.TouchNavigation(); + map.addControl(control); + var handler = control.handlers.click; + handler.touchstart({xy: new OpenLayers.Pixel(1 ,1), touches: ["foo", "bar"]}); + handler.touchend({}); + t.eq(map.getZoom(), 4, "Did we zoom out?"); + // tear down + map.destroy(); + window.setTimeout = origSetTimeout; + } + + </script> +</head> +<body> + <div id="map" style="width:512px;height:256px"></div> +</body> +</html> diff --git a/misc/openlayers/tests/Control/TransformFeature.html b/misc/openlayers/tests/Control/TransformFeature.html new file mode 100644 index 0000000..3279867 --- /dev/null +++ b/misc/openlayers/tests/Control/TransformFeature.html @@ -0,0 +1,129 @@ +<html> +<head> + <script src="../OLLoader.js"></script> + <script type="text/javascript"> + + function test_initialize(t) { + t.plan(6); + var layer = "foo"; + var control = new OpenLayers.Control.TransformFeature(layer); + + t.ok(control.layer == layer, + "constructor sets layer correctly"); + t.ok(control.dragControl instanceof OpenLayers.Control.DragFeature, + "constructor sets the drag control correctly"); + t.ok(control.box instanceof OpenLayers.Feature.Vector, + "box feature created"); + t.eq(control.handles.length, 8, "8 handles created"); + t.eq(control.rotationHandles.length, 4, "4 rotation handles created") + t.eq(typeof control.rotationHandleSymbolizer, "object", + "rotationHandleSymbolizer initialized"); + control.destroy(); + } + + function test_destroy(t) { + t.plan(1); + var map = new OpenLayers.Map("map"); + var layer = new OpenLayers.Layer.Vector(); + map.addLayer(layer); + var control = new OpenLayers.Control.TransformFeature(layer); + control.dragControl.destroy = function() { + t.ok(true, + "control.destroy calls destroy on drag control"); + }; + control.destroy(); + map.destroy(); + } + + function test_activate(t) { + t.plan(3); + var map = new OpenLayers.Map("map"); + var layer = new OpenLayers.Layer.Vector(); + map.addLayer(layer); + var control = new OpenLayers.Control.TransformFeature(layer); + map.addControl(control); + + t.ok(!control.dragControl.active, + "drag control is not active prior to activating control"); + control.activate(); + t.ok(control.dragControl.active, + "drag control is active after activating control"); + t.ok(control.box.layer === layer, "box added to layer"); + + map.destroy(); + } + + function test_setFeature(t) { + t.plan(6); + var map = new OpenLayers.Map("map", {allOverlays: true}); + var layer = new OpenLayers.Layer.Vector(); + var feature = new OpenLayers.Feature.Vector( + OpenLayers.Geometry.fromWKT("POLYGON((-1 -1, 1 -1, 1 1, -1 1))")); + layer.addFeatures([feature]); + map.addLayer(layer); + map.setCenter(new OpenLayers.LonLat(0, 0), 18); + var control = new OpenLayers.Control.TransformFeature(layer); + map.addControl(control); + var log = []; + control.events.on({ + "beforesetfeature": function(e) { log.push(e); }, + "setfeature": function(e) { log.push(e); } + }); + control.setFeature(feature); + + t.eq(log[0].type, "beforesetfeature", "beforesetfeature event fired with correct event type"); + t.eq(log[1].type, "setfeature", "setfeature event fired with correct event type"); + + t.ok(control.active, "control activated on setFeature"); + t.ok(feature.geometry.getBounds().equals(control.box.geometry.getBounds()), "box positioned correctly"); + t.geom_eq(control.handles[0].geometry, control.box.geometry.components[0], "handle positioned with box"); + + var center = new OpenLayers.LonLat(1, 1); + control.box.move(center); + t.geom_eq(control.handles[0].geometry, control.box.geometry.components[0], "handle moved with box"); + } + + function test_handleMove(t) { + t.plan(16); + var map = new OpenLayers.Map("map", {allOverlays: true}); + var layer = new OpenLayers.Layer.Vector(); + var feature = new OpenLayers.Feature.Vector( + OpenLayers.Geometry.fromWKT("POLYGON((-1 -1, 1 -1, 1 1, -1 1))")); + layer.addFeatures([feature]); + map.addLayer(layer); + map.setCenter(new OpenLayers.LonLat(0, 0), 18); + var control = new OpenLayers.Control.TransformFeature(layer); + map.addControl(control); + control.setFeature(feature); + + var bottomLeft = new OpenLayers.LonLat(-2, -2); + control.handles[0].move(bottomLeft); + t.geom_eq(control.handles[0].geometry, new OpenLayers.Geometry.Point(-2, -2), "bottom left handle at -2,-2"); + t.geom_eq(control.handles[1].geometry, new OpenLayers.Geometry.Point(0, -2), "bottom handle at 0,-2"); + t.geom_eq(control.handles[2].geometry, new OpenLayers.Geometry.Point(2, -2), "bottom right handle at 2,-2"); + t.geom_eq(control.handles[3].geometry, new OpenLayers.Geometry.Point(2, 0), "right handle at 2,0"); + t.geom_eq(control.handles[4].geometry, new OpenLayers.Geometry.Point(2, 2), "top right handle at 2,2"); + t.geom_eq(control.handles[5].geometry, new OpenLayers.Geometry.Point(0, 2), "top handle at 0,2"); + t.geom_eq(control.handles[6].geometry, new OpenLayers.Geometry.Point(-2, 2), "top left handle at -2,2"); + t.geom_eq(control.handles[7].geometry, new OpenLayers.Geometry.Point(-2, 0), "left handle at -2,0"); + + control.irregular = true; + + var bottomLeft = new OpenLayers.LonLat(-3, -3); + control.handles[0].move(bottomLeft); + t.geom_eq(control.handles[0].geometry, new OpenLayers.Geometry.Point(-3, -3), "bottom left handle at -3,-3"); + t.geom_eq(control.handles[1].geometry, new OpenLayers.Geometry.Point(-0.5, -3), "bottom handle at 0,-3"); + t.geom_eq(control.handles[2].geometry, new OpenLayers.Geometry.Point(2, -3), "bottom right handle at 2,-3"); + t.geom_eq(control.handles[3].geometry, new OpenLayers.Geometry.Point(2, -0.5), "right handle at 2,0"); + t.geom_eq(control.handles[4].geometry, new OpenLayers.Geometry.Point(2, 2), "top right handle at 2,2"); + t.geom_eq(control.handles[5].geometry, new OpenLayers.Geometry.Point(-0.5, 2), "top handle at 0,2"); + t.geom_eq(control.handles[6].geometry, new OpenLayers.Geometry.Point(-3, 2), "top left handle at -3,2"); + t.geom_eq(control.handles[7].geometry, new OpenLayers.Geometry.Point(-3, -0.5), "left handle at -3,0"); + } + + </script> +</head> +<body> + <div id="map" style="width: 400px; height: 250px;"/> +</body> +</html> diff --git a/misc/openlayers/tests/Control/UTFGrid.html b/misc/openlayers/tests/Control/UTFGrid.html new file mode 100644 index 0000000..74b4b99 --- /dev/null +++ b/misc/openlayers/tests/Control/UTFGrid.html @@ -0,0 +1,120 @@ +<!DOCTYPE html> +<html> +<head> + <meta http-equiv="content-type" content="text/html; charset=UTF-8"> + <script> + /** + * Because browsers that implement requestAnimationFrame may not execute + * animation functions while a window is not displayed (e.g. in a hidden + * iframe as in these tests), we mask the native implementations here. The + * native requestAnimationFrame functionality is tested in Util.html and + * in PanZoom.html (where a popup is opened before panning). The panTo tests + * here will test the fallback setTimeout implementation for animation. + */ + window.requestAnimationFrame = + window.webkitRequestAnimationFrame = + window.mozRequestAnimationFrame = + window.oRequestAnimationFrame = + window.msRequestAnimationFrame = null; + </script> + <script src="../OLLoader.js"></script> + <script type="text/javascript"> + + var map, layer, control; + var log; + function setUp() { + layer = new OpenLayers.Layer.UTFGrid({ + url: "../data/utfgrid/world_utfgrid/${z}/${x}/${y}.json", + isBaseLayer: true, + utfgridResolution: 4 + }); + map = new OpenLayers.Map({ + div: "map", + tileManager: null, + projection: "EPSG:900913", + layers: [layer], + center: [0, 0], + zoom: 1 + }); + log = []; + control = new OpenLayers.Control.UTFGrid({ + callback: function(infoLookup, loc, pixel) { + log.push([infoLookup, loc, pixel]); + } + }); + map.addControl(control); + } + + function tearDown() { + map.destroy(); + map = null; + layer = null; + control = null; + log = []; + } + + function test_constructor(t) { + t.plan(2); + + var control = new OpenLayers.Control.UTFGrid(); + t.ok(control instanceof OpenLayers.Control.UTFGrid, "utfgrid instance"); + t.eq(control.handlerMode, "click", "control mode"); + + control.destroy(); + + } + + function test_handleEvent(t) { + setUp(); + + var cases = [{ + evt: {xy: {x: 100, y: 70}}, + lookup: { + "0": { + id: "207", + data: { + NAME: "United States", + POP2005: 299846449 + } + } + } + }, { + evt: {xy: {x: 350, y: 20}}, + lookup: { + "0": { + id: "245", + data: { + NAME: "Russia", + POP2005: 143953092 + } + } + } + }]; + + var len = cases.length; + t.plan(4*len); + + // wait for tile loading to finish + t.delay_call(0.5, function() { + var c, arg; + for (var i=0; i<len; ++i) { + c = cases[i]; + t.eq(log.length, i, i + ": log length before"); + control.handleEvent(c.evt); + t.eq(log.length, i+1, i + ": log length after"); + t.eq(log[i][0], c.lookup, i + ": callback infoLookup"); + t.eq(log[i][2], c.evt.xy, i + ": callback pixel"); + } + + tearDown(); + }); + + } + + </script> +</head> +<body> +<div id="map" style="height: 256px; width: 512px"></div> +</body> +</html> + diff --git a/misc/openlayers/tests/Control/WMSGetFeatureInfo.html b/misc/openlayers/tests/Control/WMSGetFeatureInfo.html new file mode 100644 index 0000000..b5e6d5d --- /dev/null +++ b/misc/openlayers/tests/Control/WMSGetFeatureInfo.html @@ -0,0 +1,644 @@ +<html> +<head> + <script src="../OLLoader.js"></script> + <script type="text/javascript"> + + function test_initialize(t) { + t.plan(5); + + var options = { + url: 'http://localhost/wms', + layers: ["foo"], + formatOptions: { + foo: "bar" + } + }; + var control = new OpenLayers.Control.WMSGetFeatureInfo(options); + t.ok(control instanceof OpenLayers.Control.WMSGetFeatureInfo, + "new OpenLayers.Control.WMSGetFeatureInfo returns an instance"); + t.eq(control.url, 'http://localhost/wms', + "constructor sets url correctly"); + t.eq(control.layers, ["foo"], + "constructor layers" + ); + t.ok(control.format instanceof OpenLayers.Format.WMSGetFeatureInfo, "format created"); + t.eq(control.format.foo, "bar", "format options used") + } + + function test_clickCallBack_option(t) { + t.plan(9); + + var control; + + control = new OpenLayers.Control.WMSGetFeatureInfo({ + hover: true + }); + t.ok(control.handler instanceof OpenLayers.Handler.Hover, + 'constructor creates hover handler'); + t.ok(control.handler.callbacks["move"] === control.cancelHover, + 'constructor registers proper "move" callback in handler'); + t.ok(control.handler.callbacks["pause"] === control.getInfoForHover, + 'constructor registers proper "pause" callback in handler'); + + control = new OpenLayers.Control.WMSGetFeatureInfo(); + t.ok(control.handler instanceof OpenLayers.Handler.Click, + 'constructor creates click handler'); + t.ok(control.handler.callbacks["click"] === control.getInfoForClick, + 'constructor registers proper "click" callback in handler'); + + control = new OpenLayers.Control.WMSGetFeatureInfo({ + clickCallback: "rightclick" + }); + t.ok(control.handler.callbacks["rightclick"] === control.getInfoForClick, + 'constructor registers proper "rightclick" callback in handler'); + + control = new OpenLayers.Control.WMSGetFeatureInfo({ + clickCallback: "dblclick", + handlerOptions: { + click: { + "single": false, + "double": true + } + } + }); + t.ok(control.handler.callbacks["dblclick"] === control.getInfoForClick, + 'constructor registers proper "dblclick" callback in handler'); + t.eq(control.handler["single"], false, + 'constructor sets "single" to false in handler'); + t.eq(control.handler["double"], true, + 'constructor sets "double" to true in handler'); + } + + function test_destroy(t) { + t.plan(2); + var map = new OpenLayers.Map("map"); + var click = new OpenLayers.Control.WMSGetFeatureInfo({ + url: 'http://localhost/wms', + layers: ["foo"] + }); + + var hover = new OpenLayers.Control.WMSGetFeatureInfo({ + url: 'http://localhost/wms', + layers: ["foo"], + hover: true + }); + + click.handler.deactivate = function() { + t.ok(true, + "control.deactivate calls deactivate on click handler"); + }; + hover.handler.deactivate = function() { + t.ok(true, + "control.deactivate calls deactivate on hover handler"); + }; + click.destroy(); + hover.destroy(); + } + + function test_click(t) { + t.plan(4); + var map = new OpenLayers.Map('map'); + + // mock up active control + var control = new OpenLayers.Control.WMSGetFeatureInfo(); + map.addControl(control); + control.activate(); + + control.request = function(position) { + t.eq(position.x, 50, + "x position is as expected"); + t.eq(position.y, 50, + "y position is as expected"); + }; + + control.getInfoForClick({xy: {x: 50, y: 50}}); + control.getInfoForHover({xy: {x: 50, y: 50}}); + } + + function test_getfeatureinfo_event(t) { + + t.plan(5); + + var text = + '<?xml version="1.0" encoding="UTF-8" ?>' + + '<FeatureInfoResponse>' + + ' <FIELDS OBJECTID="1188" HECTARES="1819.734" ZONENR="5854" NULZONES=" " AREA="18197340.1426" PERIMETER="19177.4073627" SHAPE="NULL" SE_ANNO_CAD_DATA="NULL" SHAPE.AREA="0" SHAPE.LEN="0"/>' + + '</FeatureInfoResponse>'; + + var map = new OpenLayers.Map('map'); + + var xy; + var url = "http://foo"; + + // mock up a control with output "object" and drillDown true + var control = new OpenLayers.Control.WMSGetFeatureInfo({ + output: "object", + drillDown: true, + request: function(position) {}, + eventListeners: { + getfeatureinfo: function(evt) { + t.ok(evt.features[0].url === url, "features is an object with a property url when output is object"); + var features = evt.features[0].features; + t.ok(features.length === 1, "features properties has a length of 1"); + t.ok(features[0] instanceof OpenLayers.Feature.Vector, "Feature array contains 1 feature"); + } + } + }); + + // mock up a control with output "features" and drillDown true + var control2 = new OpenLayers.Control.WMSGetFeatureInfo({ + autoActivate: true, + drillDown: true, + request: function(position) {}, + eventListeners: { + getfeatureinfo: function(evt) { + var features = evt.features; + t.ok(features.length === 1, "features properties has a length of 1"); + t.ok(features[0] instanceof OpenLayers.Feature.Vector, "Feature array contains 1 feature"); + } + } + }); + + map.addControls([control, control2]); + control.activate(); + + xy = {x: 50, y: 50}; + control._requestCount = control2._requestCount = 0; + control._numRequests = control2._numRequests = 1; + control.handleResponse({xy: xy}, {responseText: text}, url); + control2.handleResponse({xy: xy}, {responseText: text}, url); + map.destroy(); + } + + function test_beforegetfeatureinfo_event(t) { + t.plan(2); + var map = new OpenLayers.Map('map'); + + var xy, mode; + + // mock up active control + var control = new OpenLayers.Control.WMSGetFeatureInfo({ + request: function(position) {}, + eventListeners: { + beforegetfeatureinfo: function(evt) { + t.eq(evt.xy, xy, + "beforegetfeatureinfo listener gets " + + "expected xy (" + mode + ")"); + } + } + }); + map.addControl(control); + control.activate(); + + // 1 test + mode = "click"; + xy = {x: 50, y: 50}; + control.getInfoForClick({xy: xy}); + + // 1 test + mode = "hover"; + xy = {x: 70, y: 70}; + control.getInfoForHover({xy: xy}); + } + + function test_nogetfeatureinfo_event(t) { + t.plan(1); + var map = new OpenLayers.Map('map'); + // mock up active control + var control = new OpenLayers.Control.WMSGetFeatureInfo({ + eventListeners: { + nogetfeatureinfo: function(evt) { + t.ok((evt.type == "nogetfeatureinfo"), "nogetfeatureinfo listener gets called when there are no queryable layers"); + } + } + }); + map.addControl(control); + control.activate(); + + // 1 test + mode = "click"; + xy = {x: 50, y: 50}; + control.getInfoForClick({xy: xy}); + } + + function test_activate(t) { + t.plan(4); + var map = new OpenLayers.Map("map"); + var click = new OpenLayers.Control.WMSGetFeatureInfo({ + url: 'http://localhost/wms', + featureType: 'type', + featureNS: 'http://localhost/ns', + layers: 'ns:type' + }); + var hover = new OpenLayers.Control.WMSGetFeatureInfo({ + url: 'http://localhost/wms', + featureType: 'type', + featureNS: 'http://localhost/ns', + layers: 'ns:type', + hover: true + }); + map.addControl(click); + map.addControl(hover); + t.ok(!click.handler.active, + "click handler is not active prior to activating control"); + t.ok(!hover.handler.active, + "hover handler is not active prior to activating control"); + click.activate(); + hover.activate(); + t.ok(click.handler.active, + "click handler is active after activating control"); + t.ok(hover.handler.active, + "hover handler is active after activating control"); + } + + function test_deactivate(t) { + t.plan(2); + var map = new OpenLayers.Map("map"); + var click = new OpenLayers.Control.WMSGetFeatureInfo({ + url: 'http://localhost/wms', + featureType: 'type', + featureNS: 'http://localhost/ns', + layers: 'ns:type' + }); + var hover = new OpenLayers.Control.WMSGetFeatureInfo({ + url: 'http://localhost/wms', + featureType: 'type', + featureNS: 'http://localhost/ns', + layers: 'ns:type' + }); + map.addControl(click); + map.addControl(hover); + click.activate(); + hover.activate(); + + click.handler.deactivate = function() { + t.ok(true, + "control.deactivate calls deactivate on click handler"); + OpenLayers.Handler.Click.prototype.deactivate.apply(this, arguments); + }; + hover.handler.deactivate = function() { + t.ok(true, + "control.deactivate calls deactivate on hover handler"); + OpenLayers.Handler.Hover.prototype.deactivate.apply(this, arguments); + }; + click.deactivate(); + hover.deactivate(); + } + + // Verify that things work all right when we combine different types for the STYLES and LAYERS + // params in the WMS Layers involved + function test_mixedParams(t) { + t.plan(5); + var map = new OpenLayers.Map("map", { + getExtent: function() {return(new OpenLayers.Bounds(-180,-90,180,90));} + }); + var geographic = new OpenLayers.Projection("EPSG:4326"); + + var a = new OpenLayers.Layer.WMS("dummy","http://localhost/wms", { + layers: "a,b,c,d", + styles: "a,b,c,d" + }, {projection: geographic}); + + var b = new OpenLayers.Layer.WMS("dummy","http://localhost/wms", { + layers: ["a","b","c","d"], + styles: ["a","b","c","d"] + }, {projection: geographic}); + + var c = new OpenLayers.Layer.WMS("dummy","http://localhost/wms", { + layers: ["a","b","c","d"] + }); + + var d = new OpenLayers.Layer.WMS("dummy","http://localhost/wms", { + layers: "a,b,c,d" + }, {projection: geographic}); + + var click = new OpenLayers.Control.WMSGetFeatureInfo({ + featureType: 'type', + featureNS: 'ns', + layers: [a, b, c, d] + }, {projection: geographic}); + + map.addControl(click); + + var log = {}; + var _request = OpenLayers.Request.GET; + OpenLayers.Request.GET = function(options) { + log.options = options; + }; + click.activate(); + click.getInfoForClick({xy: {x: 50.2, y: 50.1}}); + OpenLayers.Request.GET = _request; + + t.eq( + log.options && log.options.params.X, + 50, + "X should be an integer" + ); + + t.eq( + log.options && log.options.params.Y, + 50, + "Y should be an integer" + ); + + t.eq( + log.options && log.options.url, + "http://localhost/wms", + "url from first layer used" + ); + t.eq( + log.options && log.options.params.STYLES.join(","), + ",,,,,,,,a,b,c,d,a,b,c,d", + "Styles merged correctly" + ); + + t.eq( + log.options && log.options.params.FORMAT, + "image/jpeg", + "Required 'format' parameter included" + ); + + } + + function test_urlMatches(t) { + + t.plan(5); + + var control = new OpenLayers.Control.WMSGetFeatureInfo({ + url: "http://host/wms?one=1&two=2" + }); + + t.ok(!control.urlMatches("foo"), "doesn't match garbage"); + t.ok(control.urlMatches("http://host:80/wms?two=2&one=1"), "matches equivalent url"); + + // give the control more urls to match from + control.layerUrls = ["http://a.host/wms", "http://b.host/wms"]; + + t.ok(control.urlMatches("http://host:80/wms?two=2&one=1"), "still matches equivalent url"); + t.ok(control.urlMatches("http://a.host:80/wms"), "matches equivalent of first of layerUrls"); + t.ok(control.urlMatches("http://b.host:80/wms"), "matches equivalent of second of layerUrls"); + + } + + function test_layerUrls(t) { + + t.plan(4); + var map = new OpenLayers.Map({ + div: "map", + getExtent: function() { + return new OpenLayers.Bounds(-180,-90,180,90); + } + }); + + var a = new OpenLayers.Layer.WMS( + null, "http://a.mirror/wms", {layers: "a"} + ); + var b = new OpenLayers.Layer.WMS( + null, "http://b.mirror/wms", {layers: "b"} + ); + var c = new OpenLayers.Layer.WMS( + null, ["http://c.mirror/wms", "http://d.mirror/wms"], {layers: "c"} + ); + map.addLayers([a, b, c]); + + var control = new OpenLayers.Control.WMSGetFeatureInfo({ + url: "http://host/wms", + layers: [a, b, c] + }); + map.addControl(control); + control.activate(); + + // log calls to GET + var log; + var _request = OpenLayers.Request.GET; + OpenLayers.Request.GET = function(options) { + log.options = options; + }; + + // control url doesn't match layer urls, no request issued + log = {}; + control.getInfoForClick({xy: {x: 50, y: 50}}); + t.ok(!log.options, "no url match, no request issued"); + + // give control a list of urls to match + log = {}; + control.layerUrls = ["http://a.mirror/wms", "http://b.mirror/wms"]; + control.getInfoForClick({xy: {x: 50, y: 50}}); + t.eq(log.options && log.options.url, "http://host/wms", "some match, request issued"); + t.eq(log.options && log.options.params["QUERY_LAYERS"].join(","), "b,a", "selected layers queried"); + + // show that a layer can be matched if it has a urls array itself (first needs to be matched) + log = {}; + control.layerUrls = ["http://c.mirror/wms"]; + control.getInfoForClick({xy: {x: 50, y: 50}}); + t.eq(log.options && log.options.params["QUERY_LAYERS"].join(","), "c", "layer with urls array can be queried"); + + // clean up + OpenLayers.Request.GET = _request; + map.destroy(); + + } + + function test_hover(t) { + + t.plan(2); + + var map = new OpenLayers.Map({ + div: "map", + layers: [ + new OpenLayers.Layer.WMS(null, "/dummywms", {layers: "one"}) + ], + center: new OpenLayers.LonLat(0, 0), + zoom: 1 + }); + + var control = new OpenLayers.Control.WMSGetFeatureInfo({ + hover: true + }); + map.addControl(control); + control.activate(); + + // mock up a mousemove + control.getInfoForHover({xy: new OpenLayers.Pixel(10, 10)}); + t.ok(!!control.hoverRequest, "hoverRequest set"); + + // confirm that request is canceled on next move + var called = 0; + control.hoverRequest.abort = function() { + ++called; + }; + control.handler.px = null; + control.handler.mousemove({xy: new OpenLayers.Pixel(20, 20)}); + t.eq(called, 1, "hover request aborted"); + + map.destroy(); + + } + + function test_exceptions(t) { + t.plan(1); + var map = new OpenLayers.Map("map", { + getExtent: function() {return(new OpenLayers.Bounds(-180,-90,180,90));} + } + ); + + var a = new OpenLayers.Layer.WMS("dummy","http://myhost/wms", { + layers: "x", + exceptions: "text/xml" + }); + + map.addLayer(a); + + var click = new OpenLayers.Control.WMSGetFeatureInfo({ + }); + + map.addControl(click); + + var _request = OpenLayers.Request.GET; + OpenLayers.Request.GET = function(options) { + t.eq(options.params["EXCEPTIONS"], "text/xml", "Exceptions parameter taken from the WMS layer if provided"); + }; + click.activate(); + click.getInfoForClick({xy: {x: 50, y: 50}}); + OpenLayers.Request.GET = _request; + map.destroy(); + } + + function test_drillDown(t) { + t.plan(6); + var map = new OpenLayers.Map("map", { + getExtent: function() {return(new OpenLayers.Bounds(-180,-90,180,90));} + } + ); + + var a = new OpenLayers.Layer.WMS("dummy","http://localhost/wms", { + layers: "a" + }); + + var b = new OpenLayers.Layer.WMS("dummy","http://localhost/wms", { + layers: "c" + }); + + // this service does not support application/vnd.ogc.gml for GetFeatureInfo, only text/xml + var c = new OpenLayers.Layer.WMS("dummy","http://myhost/wms", { + layers: "x", + info_format: "text/xml" + }); + + map.addLayers([a, b, c]); + + var click = new OpenLayers.Control.WMSGetFeatureInfo({ + drillDown: true, + infoFormat: "application/vnd.ogc.gml" + }); + + map.addControl(click); + + var count = 0; + var _request = OpenLayers.Request.GET; + OpenLayers.Request.GET = function(options) { + count++; + if (count == 2) { + t.eq(options.params["INFO_FORMAT"], "application/vnd.ogc.gml", "Default info format of the control is used"); + t.eq(options.params["QUERY_LAYERS"].join(","), "c,a", "Layers should be grouped by service url"); + t.eq(options.url, "http://localhost/wms", "Correct url used for second request"); + } else if (count == 1) { + t.eq(options.params["INFO_FORMAT"], "text/xml", "Overridden info format is used instead of the control's infoFormat"); + t.eq(options.url, "http://myhost/wms", "Correct url used for first request"); + } + }; + click.activate(); + click.getInfoForClick({xy: {x: 50, y: 50}}); + OpenLayers.Request.GET = _request; + t.eq(count, 2, "We expect 2 requests to go off"); + map.destroy(); + } + + function test_GetFeatureInfo_buildWMSOptions(t) { + t.plan(3); + + var map = new OpenLayers.Map("map", { + getExtent: function() {return(new OpenLayers.Bounds(-180,-90,180,90));}, + projection: "EPSG:900913" + }); + var a = new OpenLayers.Layer.WMS("dummy", "http://localhost/wms", { + layers: "a" + }, {projection: "EPSG:3857"}); + var b = new OpenLayers.Layer.WMS("dummy", "http://localhost/wms", { + layers: "b" + }); + var c = new OpenLayers.Layer.WMS("dummy", "http://localhost/wms", { + layers: "c" + }, {projection: "EPSG:4326"}); + map.addLayers([a, b, c]); + var gfi = new OpenLayers.Control.WMSGetFeatureInfo(); + map.addControl(gfi); + gfi.activate(); + + var options = gfi.buildWMSOptions("http://localhost/wms", [a], {xy: {x: 50, y: 50}}, "text/html"); + t.eq(options.params.SRS, "EPSG:3857", "layer projection used if provided and equal map projection"); + + options = gfi.buildWMSOptions("http://localhost/wms", [b], {xy: {x: 50, y: 50}}, "text/html"); + t.eq(options.params.SRS, "EPSG:900913", "map projection used if layer has no projection configured"); + + options = gfi.buildWMSOptions("http://localhost/wms", [b], {xy: {x: 50, y: 50}}, "text/html"); + t.eq(options.params.SRS, "EPSG:900913", "map projection used if layer configured with an incompatible projection"); + } + + function test_GetFeatureInfo_WMS13(t) { + t.plan(4); + var map = new OpenLayers.Map("map", { + getExtent: function() {return(new OpenLayers.Bounds(-180,-90,180,90));} + } + ); + + var a = new OpenLayers.Layer.WMS(null, "http://localhost/wms", { + layers: "a", + version: "1.3.0" + }); + map.addLayer(a); + + var click = new OpenLayers.Control.WMSGetFeatureInfo({ + }); + + map.addControl(click); + var log = {}; + var _request = OpenLayers.Request.GET; + OpenLayers.Request.GET = function(options) { + log.options = options; + }; + click.activate(); + click.getInfoForClick({xy: {x: 50.1, y: 60.2}}); + OpenLayers.Request.GET = _request; + t.eq( + log.options && log.options.params.CRS, + "EPSG:4326", + "Since it is WMS 1.3 use CRS parameter instead of SRS in the GetFeatureInfo request" + ); + + t.eq( + log.options && log.options.params.I, + 50, + "Since it is WMS 1.3 use I parameter instead of X in the GetFeatureInfo request" + ); + + t.eq( + log.options && log.options.params.J, + 60, + "Since it is WMS 1.3 use J parameter instead of Y in the GetFeatureInfo request" + ); + + t.eq( + log.options && log.options.params.BBOX, + "-90,-180,90,180", + "Since it is WMS 1.3 the BBOX should respect axis order" + ); + + } + + </script> +</head> +<body> + <div id="map" style="width: 400px; height: 250px;"/> +</body> +</html> diff --git a/misc/openlayers/tests/Control/WMTSGetFeatureInfo.html b/misc/openlayers/tests/Control/WMTSGetFeatureInfo.html new file mode 100644 index 0000000..c7be78c --- /dev/null +++ b/misc/openlayers/tests/Control/WMTSGetFeatureInfo.html @@ -0,0 +1,334 @@ +<html> +<head> + <script src="../OLLoader.js"></script> + <script type="text/javascript"> + + function test_initialize(t) { + t.plan(4); + + var options = { + url: "http://localhost/wmts", + layers: ["foo"], + formatOptions: { + foo: "bar" + } + }; + var control = new OpenLayers.Control.WMTSGetFeatureInfo(options); + t.ok(control instanceof OpenLayers.Control.WMTSGetFeatureInfo, + "new OpenLayers.Control.WMTSGetFeatureInfo returns an instance"); + t.eq(control.layers, ["foo"], + "constructor layers" + ); + t.ok(control.format instanceof OpenLayers.Format.WMSGetFeatureInfo, "format created"); + t.eq(control.format.foo, "bar", "format options used") + } + + function test_clickCallBack_option(t) { + t.plan(9); + + var control; + + control = new OpenLayers.Control.WMTSGetFeatureInfo({ + hover: true + }); + t.ok(control.handler instanceof OpenLayers.Handler.Hover, + 'constructor creates hover handler'); + t.ok(control.handler.callbacks["move"] === control.cancelHover, + 'constructor registers proper "move" callback in handler'); + t.ok(control.handler.callbacks["pause"] === control.getInfoForHover, + 'constructor registers proper "pause" callback in handler'); + + control = new OpenLayers.Control.WMTSGetFeatureInfo(); + t.ok(control.handler instanceof OpenLayers.Handler.Click, + 'constructor creates click handler'); + t.ok(control.handler.callbacks["click"] === control.getInfoForClick, + 'constructor registers proper "click" callback in handler'); + + control = new OpenLayers.Control.WMTSGetFeatureInfo({ + clickCallback: "rightclick" + }); + t.ok(control.handler.callbacks["rightclick"] === control.getInfoForClick, + 'constructor registers proper "rightclick" callback in handler'); + + control = new OpenLayers.Control.WMTSGetFeatureInfo({ + clickCallback: "dblclick", + handlerOptions: { + click: { + "single": false, + "double": true + } + } + }); + t.ok(control.handler.callbacks["dblclick"] === control.getInfoForClick, + 'constructor registers proper "dblclick" callback in handler'); + t.eq(control.handler["single"], false, + 'constructor sets "single" to false in handler'); + t.eq(control.handler["double"], true, + 'constructor sets "double" to true in handler'); + } + + function test_destroy(t) { + t.plan(2); + var map = new OpenLayers.Map("map"); + var click = new OpenLayers.Control.WMTSGetFeatureInfo({ + url: 'http://localhost/wms', + layers: ["foo"] + }); + + var hover = new OpenLayers.Control.WMTSGetFeatureInfo({ + url: 'http://localhost/wms', + layers: ["foo"], + hover: true + }); + + click.handler.deactivate = function() { + t.ok(true, + "control.deactivate calls deactivate on click handler"); + }; + hover.handler.deactivate = function() { + t.ok(true, + "control.deactivate calls deactivate on hover handler"); + }; + click.destroy(); + hover.destroy(); + } + + function test_click(t) { + t.plan(4); + var map = new OpenLayers.Map('map'); + + // mock up active control + var control = new OpenLayers.Control.WMTSGetFeatureInfo(); + map.addControl(control); + control.activate(); + + control.request = function(position) { + t.eq(position.x, 200, + "x position is as expected"); + t.eq(position.y, 125, + "y position is as expected"); + }; + + control.getInfoForClick({xy: {x: 200, y: 125}}); + control.getInfoForHover({xy: {x: 200, y: 125}}); + } + + function test_beforegetfeatureinfo_event(t) { + t.plan(2); + var map = new OpenLayers.Map({ + div: "map", + allOverlays: true, + layers: [ + new OpenLayers.Layer.WMTS({ + name: "Test WMTS 1", + url: "/testwmts/", + layer: "test1", + style: "", + matrixSet: "set-id", + isBaseLayer: false + }), + new OpenLayers.Layer.WMTS({ + name: "Test WMTS 2", + url: "/testwmts/", + layer: "test2", + style: "", + matrixSet: "set-id", + isBaseLayer: false + }) + ], + center: new OpenLayers.LonLat(0, 0), + zoom: 0 + }); + + var log = []; + + // test click + var click = new OpenLayers.Control.WMTSGetFeatureInfo({ + drillDown: true, + eventListeners: { + beforegetfeatureinfo: function(evt) { + log.push({xy: evt.xy}); + } + } + }); + map.addControl(click); + click.activate(); + click.getInfoForClick({xy: {x: 200, y: 125}}); + t.eq(log.length, 2, "click: beforegetfeatureinfo triggered twice"); + log = []; + click.deactivate(); + + // test hover + var hover = new OpenLayers.Control.WMTSGetFeatureInfo({ + hover: true, + eventListeners: { + beforegetfeatureinfo: function(evt) { + log.push({xy: evt.xy}); + } + } + }); + map.addControl(hover); + hover.activate(); + xy = {x: 70, y: 70}; + hover.getInfoForHover({xy: {x: 70, y: 70}}); + t.eq(log.length, 1, "hover: beforegetfeatureinfo triggered once"); + log = []; + hover.deactivate(); + + map.destroy(); + } + + function test_activate(t) { + t.plan(4); + var map = new OpenLayers.Map("map"); + var click = new OpenLayers.Control.WMTSGetFeatureInfo({ + url: 'http://localhost/wms', + layers: ['ns:type'] + }); + var hover = new OpenLayers.Control.WMTSGetFeatureInfo({ + url: 'http://localhost/wms', + featureType: 'type', + featureNS: 'http://localhost/ns', + layers: 'ns:type', + hover: true + }); + map.addControl(click); + map.addControl(hover); + t.ok(!click.handler.active, + "click handler is not active prior to activating control"); + t.ok(!hover.handler.active, + "hover handler is not active prior to activating control"); + click.activate(); + hover.activate(); + t.ok(click.handler.active, + "click handler is active after activating control"); + t.ok(hover.handler.active, + "hover handler is active after activating control"); + } + + function test_deactivate(t) { + t.plan(2); + var map = new OpenLayers.Map("map"); + var click = new OpenLayers.Control.WMTSGetFeatureInfo({ + url: 'http://localhost/wms', + featureType: 'type', + featureNS: 'http://localhost/ns', + layers: 'ns:type' + }); + var hover = new OpenLayers.Control.WMTSGetFeatureInfo({ + url: 'http://localhost/wms', + featureType: 'type', + featureNS: 'http://localhost/ns', + layers: 'ns:type' + }); + map.addControl(click); + map.addControl(hover); + click.activate(); + hover.activate(); + + click.handler.deactivate = function() { + t.ok(true, + "control.deactivate calls deactivate on click handler"); + OpenLayers.Handler.Click.prototype.deactivate.apply(this, arguments); + }; + hover.handler.deactivate = function() { + t.ok(true, + "control.deactivate calls deactivate on hover handler"); + OpenLayers.Handler.Hover.prototype.deactivate.apply(this, arguments); + }; + click.deactivate(); + hover.deactivate(); + } + + function test_getInfoForClick(t) { + + t.plan(13); + var map = new OpenLayers.Map({ + div: "map", + getExtent: function() { + return new OpenLayers.Bounds(-180,-90,180,90); + } + }); + + var a = new OpenLayers.Layer.WMTS({ + url: "http://a.example.com/wmts", + layer: "a", + matrixSet: "bar", + style: "default" + }); + + var b = new OpenLayers.Layer.WMTS({ + url: "http://b.example.com/wmts", + layer: "b", + matrixSet: "bar", + style: "default", + isBaseLayer: false + }); + + var c = new OpenLayers.Layer.WMTS({ + url: ["http://c1.example.com/wmts", "http://c2.example.com"], + layer: "c", + matrixSet: "bar", + style: "default", + isBaseLayer: false + }); + map.addLayers([a, b, c]); + map.zoomToMaxExtent(); + + var control = new OpenLayers.Control.WMTSGetFeatureInfo({ + layers: [a, b, c] + }); + map.addControl(control); + control.activate(); + + // log calls to GET + var log; + var _request = OpenLayers.Request.GET; + OpenLayers.Request.GET = function(options) { + log.push(options); + }; + + // query first layer (drillDown false) + log = []; + control.drillDown = false; + control.queryVisible = false; + control.getInfoForClick({xy: {x: 200, y: 125}}); + t.eq(log.length, 1, "one requests issued"); + t.eq(log[0].url, "http://c1.example.com/wmts", "{drillDown: false} correct url"); + t.eq(log[0].params["LAYER"], "c", "{drillDown: false} correct layer parameter"); + + // query all layers + log = []; + control.drillDown = true; + control.queryVisible = false; + control.getInfoForClick({xy: {x: 200, y: 125}}); + t.eq(log.length, 3, "three requests issued"); + t.eq(log[0].url, "http://c1.example.com/wmts", "[c] correct url"); + t.eq(log[0].params["LAYER"], "c", "[c] correct layer parameter"); + t.eq(log[1].url, "http://b.example.com/wmts", "[b] correct url"); + t.eq(log[1].params["LAYER"], "b", "[b] correct layer parameter"); + t.eq(log[2].url, "http://a.example.com/wmts", "[a] correct url"); + t.eq(log[2].params["LAYER"], "a", "[a] correct layer parameter"); + + // query only visible layers + log = []; + control.drillDown = true; + control.queryVisible = true; + b.setVisibility(false); + control.getInfoForClick({xy: {x: 200, y: 125}}); + t.eq(log.length, 2, "two requests issued"); + t.eq(log[0].url, "http://c1.example.com/wmts", "correct url for second visible layer"); + t.eq(log[1].url, "http://a.example.com/wmts", "correct url for first visible layer"); + + // clean up + OpenLayers.Request.GET = _request; + map.destroy(); + + } + + </script> +</head> +<body> + <div id="map" style="width: 400px; height: 250px;"/> +</body> +</html> diff --git a/misc/openlayers/tests/Control/Zoom.html b/misc/openlayers/tests/Control/Zoom.html new file mode 100644 index 0000000..cfeb082 --- /dev/null +++ b/misc/openlayers/tests/Control/Zoom.html @@ -0,0 +1,83 @@ +<!DOCTYPE html> +<html> +<head> + <script src="../OLLoader.js"></script> + <script type="text/javascript"> + + function test_constructor(t) { + t.plan(5); + + var control = new OpenLayers.Control.Zoom(); + t.ok(control instanceof OpenLayers.Control, "instance of Control"); + t.ok(control instanceof OpenLayers.Control.Zoom, "instance of Zoom"); + t.eq(control.displayClass, "olControlZoom", "displayClass"); + control.destroy(); + + control = new OpenLayers.Control.Zoom({ + zoomInText: "zoom in!", + zoomOutText: "zoom out!" + }); + t.eq(control.zoomInText, "zoom in!", "zoomInText"); + t.eq(control.zoomOutText, "zoom out!", "zoomOutText"); + control.destroy(); + } + + function test_addControl(t) { + t.plan(3); + var map = new OpenLayers.Map("map"); + var control = new OpenLayers.Control.Zoom(); + map.addControl(control); + t.ok(control.map === map, "Control.map set"); + t.ok(!!~OpenLayers.Util.indexOf(map.controls, control), "map.controls contains control"); + + control = new OpenLayers.Control.Zoom({zoomInId: "in", zoomOutId: "out"}); + map.addControl(control); + var eventsEl = document.getElementById("out").parentNode; + t.ok(control.events.element === eventsEl, "Events instance listens to custom div's parentNode"); + + map.destroy(); + } + + function test_zoomIn(t) { + t.plan(2); + + var map = new OpenLayers.Map({ + div: "map", + layers: [new OpenLayers.Layer(null, {isBaseLayer: true})], + zoomMethod: null + }); + var control = new OpenLayers.Control.Zoom(); + map.addControl(control); + map.setCenter([0, 0], 0); + + t.eq(map.getZoom(), 0, "initial center"); + map.events.triggerEvent("buttonclick", {buttonElement: control.zoomInLink}); + t.eq(map.getZoom(), 1, "after zoom in"); + map.destroy(); + } + + function test_zoomOut(t) { + t.plan(2); + + var map = new OpenLayers.Map({ + div: "map", + layers: [new OpenLayers.Layer(null, {isBaseLayer: true})], + zoomMethod: null + }); + var control = new OpenLayers.Control.Zoom(); + map.addControl(control); + map.setCenter([0, 0], 1); + + t.eq(map.getZoom(), 1, "initial center"); + map.events.triggerEvent("buttonclick", {buttonElement: control.zoomOutLink}); + t.eq(map.getZoom(), 0, "after zoom out"); + map.destroy(); + } + + </script> +</head> +<body> + <div id="map" style="width: 512px; height: 256px;"/> + <div id="in">in</div><div id="out">out</out> +</body> +</html> diff --git a/misc/openlayers/tests/Control/ZoomBox.html b/misc/openlayers/tests/Control/ZoomBox.html new file mode 100644 index 0000000..7763bcf --- /dev/null +++ b/misc/openlayers/tests/Control/ZoomBox.html @@ -0,0 +1,54 @@ +<!DOCTYPE html> +<html> +<head> + <script src="../OLLoader.js"></script> + <script type="text/javascript"> + + function test_constructor(t) { + t.plan(4); + + var control = new OpenLayers.Control.ZoomBox(); + t.ok(control instanceof OpenLayers.Control, "instance of Control"); + t.ok(control instanceof OpenLayers.Control.ZoomBox, "instance of ZoomBox"); + t.eq(control.displayClass, "olControlZoomBox", "displayClass"); + control.destroy(); + + control = new OpenLayers.Control.ZoomBox({ + zoomOnClick: false + }); + t.eq(control.zoomOnClick, false, "zoomOnClick"); + control.destroy(); + } + + function test_zoomBox(t) { + t.plan(4); + var map = new OpenLayers.Map("map", { + zoomMethod: null, + layers: [new OpenLayers.Layer("", {isBaseLayer: true})], + center: [0, 0], + zoom: 1 + }); + var control = new OpenLayers.Control.ZoomBox(); + map.addControl(control); + control.zoomBox(new OpenLayers.Pixel(50, 60)); + t.eq(map.getZoom(), 2, "zoomed on click"); + + control.zoomOnClick = false; + control.zoomBox(new OpenLayers.Pixel(-50, -60)); + t.eq(map.getZoom(), 2, "not zoomed with zoomOnClick set to false"); + + map.zoomToMaxExtent(); + // pixel bounds bottom > top + control.zoomBox(new OpenLayers.Bounds(128, 128, 256, 64)); + t.eq(map.getCenter().toShortString(), "-45, 22.5", "centered to box center"); + t.eq(map.getZoom(), 3, "zoomed to box extent"); + + map.destroy(); + } + + </script> +</head> +<body> + <div id="map" style="width: 512px; height: 256px;"/> +</body> +</html> diff --git a/misc/openlayers/tests/Control/ZoomIn.html b/misc/openlayers/tests/Control/ZoomIn.html new file mode 100644 index 0000000..844ded5 --- /dev/null +++ b/misc/openlayers/tests/Control/ZoomIn.html @@ -0,0 +1,101 @@ +<!DOCTYPE html> +<html> + <head> + <script src="../OLLoader.js"></script> + <script type="text/javascript"> + +function test_ZoomIn_constructor (t) { + t.plan( 2 ); + + // setup + var control = new OpenLayers.Control.ZoomIn(); + + // tests + // + t.ok( + control instanceof OpenLayers.Control.ZoomIn, + "new OpenLayers.Control.ZoomIn returns object" + ); + t.eq( + control.displayClass, "olControlZoomIn", + "displayClass is correct" + ); + + // tear down + control.destroy(); +} + +function test_ZoomIn_type (t) { + t.plan( 1 ); + + // setup + var control = new OpenLayers.Control.ZoomIn(); + + // tests + // + t.eq( + control.type, + OpenLayers.Control.TYPE_BUTTON, + "ZoomIn control is of type OpenLayers.Control.TYPE_BUTTON" + ); + + // tear down + control.destroy(); +} + +function test_ZoomIn_trigger (t) { + t.plan( 2 ); + + // set up + var control = new OpenLayers.Control.ZoomIn(), + zoomlevel = 5, + map = new OpenLayers.Map("map", { + allOverlays: true, + layers: [ + new OpenLayers.Layer.Vector() + ], + center: new OpenLayers.LonLat(1,1), + zoom: zoomlevel + }), + oldZoom; + + oldZoom = map.getZoom(); + + // tests + // + // trigger the control before it is being added, + // nothing should change + control.trigger(); + + t.eq( + oldZoom, + zoomlevel, + 'Calling trigger on a non added control doesn\'t do anything ' + + '(map zoom is ' + oldZoom + ').' + ); + + // now lets add the control + map.addControl(control); + + // trigger it again, now the map should have a different extent + control.trigger(); + + t.eq( + map.getZoom(), + zoomlevel + 1, + 'Calling trigger on a added control changes the map zoom ' + + '(map zoom was ' + zoomlevel + + ' and is now ' + map.getZoom() + ').' + ); + + // tear down + control.destroy(); + map.destroy(); +} + + </script> + </head> + <body> + <div id="map" style="width: 1000px; height: 1000px;"></div> + </body> +</html> diff --git a/misc/openlayers/tests/Control/ZoomOut.html b/misc/openlayers/tests/Control/ZoomOut.html new file mode 100644 index 0000000..5345c55 --- /dev/null +++ b/misc/openlayers/tests/Control/ZoomOut.html @@ -0,0 +1,100 @@ +<!DOCTYPE html> +<html> + <head> + <script src="../OLLoader.js"></script> + <script type="text/javascript"> + +function test_ZoomOut_constructor (t) { + t.plan( 2 ); + + // setup + var control = new OpenLayers.Control.ZoomOut(); + + // tests + // + t.ok( + control instanceof OpenLayers.Control.ZoomOut, + "new OpenLayers.Control.ZoomOut returns object" + ); + t.eq( + control.displayClass, "olControlZoomOut", + "displayClass is correct" + ); + + // tear down + control.destroy(); +} + +function test_ZoomOut_type(t){ + t.plan( 1 ); + + // setup + var control = new OpenLayers.Control.ZoomOut(); + + // check that the type of the control equals OpenLayers.Control.TYPE_BUTTON + t.eq( + control.type, + OpenLayers.Control.TYPE_BUTTON, + 'ZoomOut-control is of type "OpenLayers.Control.TYPE_BUTTON".' + ); + + // tear down + control.destroy(); +} + +function test_ZoomOut_trigger (t) { + t.plan( 2 ); + + // set up + var control = new OpenLayers.Control.ZoomOut(), + zoomlevel = 5, + map = new OpenLayers.Map("map", { + allOverlays: true, + layers: [ + new OpenLayers.Layer.Vector() + ], + center: new OpenLayers.LonLat(1,1), + zoom: zoomlevel + }), + oldZoom; + + oldZoom = map.getZoom(); + + // tests + // + // trigger the control before it is being added, + // nothing should change + control.trigger(); + + t.eq( + oldZoom, + zoomlevel, + 'Calling trigger on a non added control doesn\'t do anything ' + + '(map zoom is ' + oldZoom + ').' + ); + + // now lets add the control + map.addControl(control); + + // trigger it again, now the map should have a different extent + control.trigger(); + + t.eq( + map.getZoom(), + zoomlevel - 1, + 'Calling trigger on a added control changes the map zoom ' + + '(map zoom was ' + zoomlevel + + ' and is now ' + map.getZoom() + ').' + ); + + // tear down + control.destroy(); + map.destroy(); +} + + </script> + </head> + <body> + <div id="map" style="width: 1000px; height: 1000px;"></div> + </body> +</html> diff --git a/misc/openlayers/tests/Control/ZoomToMaxExtent.html b/misc/openlayers/tests/Control/ZoomToMaxExtent.html new file mode 100644 index 0000000..8ed5512 --- /dev/null +++ b/misc/openlayers/tests/Control/ZoomToMaxExtent.html @@ -0,0 +1,102 @@ +<!DOCTYPE html> +<html> + <head> + <script src="../OLLoader.js"></script> + <script type="text/javascript"> + +function test_ZoomToMaxExtent_constructor (t) { + t.plan( 2 ); + + // setup + var control = new OpenLayers.Control.ZoomToMaxExtent(); + + // tests + // + t.ok( + control instanceof OpenLayers.Control.ZoomToMaxExtent, + "new OpenLayers.Control.ZoomToMaxExtent returns object" + ); + t.eq( + control.displayClass, "olControlZoomToMaxExtent", + "displayClass is correct" + ); + + // tear down + control.destroy(); +} + +function test_ZoomToMaxExtent_type (t) { + t.plan( 1 ); + + // setup + var control = new OpenLayers.Control.ZoomToMaxExtent(); + + // check that the type of the control equals OpenLayers.Control.TYPE_BUTTON + t.eq( + control.type, + OpenLayers.Control.TYPE_BUTTON, + 'ZoomToMaxExtent-control is of type "OpenLayers.Control.TYPE_BUTTON".' + ); + + // tear down + control.destroy(); +} + +function test_ZoomToMaxExtent_trigger (t) { + t.plan( 2 ); + + // set up + var mapsMaxExtent = new OpenLayers.Bounds(0, 0, 45, 45), + mapsInitialExtent = new OpenLayers.Bounds(5, 5, 7, 7), + control = new OpenLayers.Control.ZoomToMaxExtent(), + map = new OpenLayers.Map("map", { + maxExtent: mapsMaxExtent, + allOverlays: true, + fractionalZoom: true, + layers: [ + new OpenLayers.Layer.Vector() + ] + }), + oldExtent; + + map.zoomToExtent(mapsInitialExtent); + + oldExtent = map.getExtent().toString(); + + // tests + // + // trigger the control before it is being added, + // nothing should change + control.trigger(); + t.eq( + oldExtent, + map.getExtent().toString(), + 'Calling trigger on a non added control doesn\'t do anything ' + + '(map extent is "' + oldExtent + '").' + ); + + // now lets add the control + map. addControl(control); + + // trigger it again, now the map should have a different extent + control.trigger(); + + t.eq( + map.getExtent().toString(), + mapsMaxExtent.toString(), + 'Calling trigger on a added control changes the map extent ' + + '(map extent was "' + oldExtent + '"' + + ' and is now "' + mapsMaxExtent.toString() + '").' + ); + + // tear down + control.destroy(); + map.destroy(); +} + + </script> + </head> + <body> + <div id="map" style="width: 1000px; height: 1000px;"></div> + </body> +</html> |