OpenLayers OpenLayers

root/trunk/openlayers/tests/Layer/Vector.html

Revision 8349, 21.8 kB (checked in by crschmidt, 2 months ago)

Fix getDataExtent() (vector) manipulates feature: patch from vmx, tests by me,
r=me. (Closes #1822)

  • Property svn:eol-style set to native
Line 
1 <html>
2 <head>
3 <script src="../../lib/OpenLayers.js"></script>
4   <script type="text/javascript">
5
6     var name = "Vector Layer";
7    
8     function test_Layer_Vector_constructor(t) {
9         t.plan(4);
10
11         var options = {protocol: new OpenLayers.Protocol(),
12                        strategies: [new OpenLayers.Strategy(), new OpenLayers.Strategy()]}
13         var layer = new OpenLayers.Layer.Vector(name, options);
14
15         t.ok(layer instanceof OpenLayers.Layer.Vector, "new OpenLayers.Layer.Vector returns correct object" );
16         t.eq(layer.name, name, "layer name is correctly set");
17         t.ok(layer.renderer.CLASS_NAME, "layer has a renderer");
18        
19         t.ok((layer.name == layer.strategies[0].layer.name) &&
20              (layer.strategies[0].layer.name == layer.strategies[1].layer.name),
21              "setLayer was called on strategies");
22     }
23
24     function test_Layer_Vector_refresh(t) {
25         t.plan(1);
26
27         var obj = {"an": "object"};
28
29         var layer = new OpenLayers.Layer.Vector(name, {
30             eventListeners: {
31                 refresh: function(o) {
32                     t.ok(o == obj,
33                          "refresh listener called with correct arg");
34                 }
35             }
36         });
37
38         // 0 test
39         layer.inRange = false;
40         layer.visibility = false;
41         layer.refresh(obj);
42
43         // 0 test
44         layer.inRange = true;
45         layer.visibility = false;
46         layer.refresh(obj);
47
48         // 0 test
49         layer.inRange = false;
50         layer.visibility = true;
51         layer.refresh(obj);
52      
53         // 1 test
54         layer.inRange = true;
55         layer.visibility = true;
56         layer.refresh(obj);
57     }
58    
59     function test_Layer_Vector_addFeatures(t) {
60         t.plan(8);
61    
62         var layer = new OpenLayers.Layer.Vector(name);
63
64         var point = new OpenLayers.Geometry.Point(-111.04, 45.68);
65         var pointFeature = new OpenLayers.Feature.Vector(point);
66
67         layer.preFeatureInsert = function(feature) {
68             t.ok(feature == pointFeature, "OpenLayers.Layer.Vector.addFeatures calls preFeatureInsert with the right arg");
69         };
70         layer.onFeatureInsert = function(feature) {
71             t.ok(feature == pointFeature, "OpenLayers.Layer.Vector.addFeatures calls onFeatureInsert with the right arg");
72         };
73         layer.events.register('beforefeatureadded', null, function(obj) {
74             t.ok(pointFeature == obj.feature, "OpenLayers.Layer.Vector.addFeatures triggers beforefeatureadded with correct feature passed to callback");
75         });
76         layer.events.register('featureadded', null, function(obj) {
77             t.ok(pointFeature == obj.feature, "OpenLayers.Layer.Vector.addFeatures triggers featureadded with correct feature passed to callback");
78         });
79         layer.events.register('featuresadded', null, function(obj) {
80             t.ok(pointFeature == obj.features[0], "OpenLayers.Layer.Vector.addFeatures triggers featuresadded with correct features passed to callback");
81         });
82
83         layer.addFeatures([pointFeature]);
84        
85         t.eq(layer.features.length, 1, "OpenLayers.Layer.Vector.addFeatures adds something to the array");
86         t.ok(layer.features[0] == pointFeature, "OpenLayers.Layer.Vector.addFeatures returns an array of features");
87
88         layer.preFeatureInsert = function(feature) {
89             t.fail("OpenLayers.Layer.Vector.addFeatures calls preFeatureInsert while it must not");
90         };
91         layer.onFeatureInsert = function(feature) {
92             t.fail("OpenLayers.Layer.Vector.addFeatures calls onFeatureInsert while it must not");
93         };
94         layer.events.register('beforefeatureadded', null, function(obj) {
95             t.fail("OpenLayers.Layer.Vector.addFeatures triggers beforefeatureadded while it must not");
96         });
97         layer.events.register('featureadded', null, function(obj) {
98             t.fail("OpenLayers.Layer.Vector.addFeatures triggers featureadded while it must not");
99         });
100         layer.events.register('featuresadded', null, function(obj) {
101             t.fail("OpenLayers.Layer.Vector.addFeatures triggers featuresadded while it must not");
102         });
103
104         layer.addFeatures([pointFeature], {silent: true});
105
106         var extent = layer.getDataExtent();
107         t.eq(extent.toBBOX(), "-111.04,45.68,-111.04,45.68", "extent from getDataExtent is correct");
108     }
109
110     function test_Layer_Vector_getDataExtent(t) {
111         t.plan(1);
112         var layer = new OpenLayers.Layer.Vector(name);
113
114         var point = new OpenLayers.Geometry.Point(-111.04, 45.68);
115         var pointFeature = new OpenLayers.Feature.Vector(point);
116         layer.addFeatures([pointFeature]);
117         var point = new OpenLayers.Geometry.Point(-111.04, 5.68);
118         var pointFeature = new OpenLayers.Feature.Vector(point);
119         layer.addFeatures([pointFeature]);
120         var extent = layer.getDataExtent();
121         t.ok(extent.toBBOX() != layer.features[0].geometry.getBounds().toBBOX(), "extent from getDataExtent doesn't clobber first feature");
122     }
123
124     function test_Layer_Vector_removeFeatures(t) {
125         t.plan(6);
126    
127         var layer = new OpenLayers.Layer.Vector(name);
128
129         var point1 = new OpenLayers.Geometry.Point(-111.04, 45.68);
130         var pointFeature1 = new OpenLayers.Feature.Vector(layer, point1);
131         var point2 = new OpenLayers.Geometry.Point(-111.14, 45.78);
132         var pointFeature2 = new OpenLayers.Feature.Vector(layer, point2);
133      
134         layer.addFeatures([pointFeature1, pointFeature2]);
135         var features = layer.removeFeatures([pointFeature1]);
136        
137         t.ok(layer.features.length == 1, "OpenLayers.Layer.Vector.removeFeatures removes a feature from the features array");
138         layer.addFeatures([pointFeature1.clone(), pointFeature2.clone()]);
139         layer.selectedFeatures.push(layer.features[0]);
140         layer.removeFeatures(layer.features[0]);
141         t.eq(layer.selectedFeatures, [], "Remove features removes selected features");
142         var features = layer.removeFeatures(layer.features);
143        
144         t.ok(layer.features.length == 0,
145              "OpenLayers.Layer.Vector.removeFeatures(layer.features) removes all feature from the features array");
146
147         // 3 tests
148         layer.events.register('beforefeatureremoved', null, function(obj) {
149             t.ok(pointFeature1 == obj.feature,
150                  "OpenLayers.Layer.Vector.removeFeatures triggers beforefeatureremoved with correct feature passed to callback");
151         });
152         layer.events.register('featureremoved', null, function(obj) {
153             t.ok(pointFeature1 == obj.feature,
154                  "OpenLayers.Layer.Vector.removeFeatures triggers featureremoved with correct feature passed to callback");
155         });
156         layer.events.register('featuresremoved', null, function(obj) {
157             t.ok(pointFeature1 == obj.features[0],
158                  "OpenLayers.Layer.Vector.removeFeatures triggers featuresremoved with correct features passed to callback");
159         });
160         layer.addFeatures([pointFeature1]);
161         layer.removeFeatures([pointFeature1]);
162
163         // 0 test
164         layer.events.register('beforefeatureremoved', null, function(obj) {
165             t.fail("OpenLayers.Layer.Vector.removeFeatures triggers beforefeatureremoved while it must not");
166         });
167         layer.events.register('featureremoved', null, function(obj) {
168             t.fail("OpenLayers.Layer.Vector.removeFeatures triggers featureremoved while it must not");
169         });
170         layer.events.register('featuresremoved', null, function(obj) {
171             t.fail("OpenLayers.Layer.Vector.removeFeatures triggers featuresremoved while it must not");
172         });
173         layer.addFeatures([pointFeature1]);
174         layer.removeFeatures([pointFeature1], {silent: true});
175      }
176    
177     function test_Layer_Vector_drawFeature(t) {
178         t.plan(7);
179         var layer = new OpenLayers.Layer.Vector("Test Layer", {isBaseLayer: true});
180         var map = new OpenLayers.Map('map', {
181             maxExtent: new OpenLayers.Bounds(-100, -100, 100, 100)
182         });
183         map.addLayer(layer);
184         var geometry = new OpenLayers.Geometry.Point(10, 10);
185         var feature = new OpenLayers.Feature.Vector(geometry);
186        
187         var f, s;
188        
189         // Bogus layer renderer needs some methods
190         // for functional tests.
191         layer.drawn = true;
192         layer.renderer = {
193             drawFeature: function(feature, style) {
194                 f = feature;
195                 s = style;
196             },
197             root: document.createElement("div"),
198             destroy: function() { },
199             eraseFeatures: function() {},
200             setExtent: function() {}
201         };
202        
203
204         layer.drawFeature(feature);
205         t.ok(geometry.equals(f.geometry),
206              "calls layer.renderer.drawFeature() with feature.geometry");
207        
208         feature.style = {foo: "bar"};
209         layer.drawFeature(feature);
210         t.eq(feature.style, s,
211              "calls layer.renderer.drawFeature() with feature.style");
212        
213         feature.style = null;
214         layer.style = {foo: "bar"};
215         layer.drawFeature(feature);
216         t.eq(layer.style.foo, s.foo,
217              "given null feature style, uses layer style");
218
219         feature.style = {foo1: "bar1"};
220         layer.style = {foo2: "bar2"};
221         var customStyle = {foo: "bar"};
222         layer.drawFeature(feature, customStyle);
223         t.eq(customStyle.foo, s.foo,
224              "given a custom style, renders with that");
225        
226         // the real renderer's drawFeature method is tested in Renderer.html
227         layer.renderer.drawFeature = function(feature) {
228             return(feature.geometry.getBounds().intersectsBounds(map.getExtent()));
229         }
230         // reset the drawn to null as if the layer had never been rendered
231         layer.drawn = null;
232        
233         layer.drawFeature(feature);
234         t.ok(true, "Trying to draw a feature on an not drawn layer doesn't throw any error.");
235        
236         layer.addFeatures([feature]);
237        
238         map.setCenter(new OpenLayers.Bounds(0, 0, 0, 0), 6);
239         t.ok(layer.unrenderedFeatures[feature.id], "Did not render feature outside the viewport.");
240         map.panTo(new OpenLayers.LonLat(10, 10));
241         t.ok(!layer.unrenderedFeatures[feature.id], "Rendered feature inside the viewport.");
242        
243         layer.features = [];
244     }
245    
246     function test_Layer_Vector_eraseFeatures(t) {
247         t.plan(2);
248         var layer = new OpenLayers.Layer.Vector("Test Layer");
249         var map = new OpenLayers.Map('map');
250         map.addLayer(layer);
251         var geometry = new OpenLayers.Geometry.Point(10, 10);
252         var feature = new OpenLayers.Feature.Vector(geometry);
253        
254         var f;
255         layer.renderer = {
256             eraseFeatures: function(features) {
257                 f = features[0];
258             },
259             destroy: function() { }
260         };
261
262         layer.eraseFeatures([feature]);
263         t.ok(f, "calls layer.renderer.eraseFeatures");
264         t.ok(geometry.equals(f.geometry),
265              "calls layer.renderer.eraseFeatures() given an array of features");
266     }
267
268     function test_Layer_Vector_destroyFeatures (t) {
269         t.plan(5);
270         layer = new OpenLayers.Layer.Vector(name);
271         var map = new OpenLayers.Map('map');
272         map.addLayer(layer);
273         var features = [];
274         for (var i = 0; i < 5; i++) {
275             features.push(new OpenLayers.Feature.Vector(
276                           new OpenLayers.Geometry.Point(0,0)));
277         }
278         layer.addFeatures(features);
279         t.eq(layer.features.length, 5, "addFeatures adds 5 features");
280         layer.selectedFeatures.push(features[0]);
281         layer.destroyFeatures();
282         t.eq(layer.features.length, 0, "destroyFeatures triggers removal");
283         t.eq(layer.selectedFeatures, [], "Destroy features removes selected features");
284         features = [];
285         for (var i = 0; i < 5; i++) {
286             features.push(new OpenLayers.Feature.Vector(
287                           new OpenLayers.Geometry.Point(0,0)));
288         }
289         layer.addFeatures(features);
290         layer.selectedFeatures.push(features[0]);
291         layer.selectedFeatures.push(features[1]);
292         layer.destroyFeatures([features[0], features[1]]);
293         t.eq(layer.features.length, 3, "destroyFeatures removes appropriate features");
294         t.eq(layer.selectedFeatures, [], "destroyFeatures removes appropriate selected features");
295     }
296
297     function test_Layer_Vector_destroy (t) {
298         t.plan(5);   
299
300         var options = {protocol: new OpenLayers.Protocol(),
301                        strategies: [new OpenLayers.Strategy(), new OpenLayers.Strategy()]}
302         var layer = new OpenLayers.Layer.Vector(name, options);
303         var map = new OpenLayers.Map('map');
304         map.addLayer(layer);
305         layer.destroy();
306         t.eq(layer.map, null, "layer.map is null after destroy");
307         t.eq(layer.getFeatureFromEvent({'target':'map'}), null,
308             "getFeatureIdFromEvent doesn't cause an error when called on layer which has been destroyed.");
309
310         t.eq(layer.protocol, null, "layer.protocol is null after destroy");
311         t.eq(layer.strategies, null, "layer.strategies is null after destroy");
312        
313         // test that we can call layer.destroy a second time without trouble
314         try {
315             layer.destroy();
316             layer.destroy();
317             t.ok(true, "layer.destroy called twice without any issues");
318         } catch(err) {
319             t.fail("calling layer.destroy twice triggers exception: " + err + " in " + err.fileName + " line " + err.lineNumber);
320         }
321        
322     }
323
324     function test_Layer_Vector_externalGraphic(t) {
325         t.plan(11);
326         var layer = new OpenLayers.Layer.Vector("Test Layer", {isBaseLayer: true});
327         var renderer = layer.renderer;
328         var map = new OpenLayers.Map('map');
329         map.addLayers([layer]);
330
331         var geometryX = 10;
332         var geometryY = 10;
333         var geometry = new OpenLayers.Geometry.Point(geometryX, geometryY);
334         var feature = new OpenLayers.Feature.Vector(geometry);
335
336         map.zoomToMaxExtent();
337
338         var customStyle1 = new Object({
339                 externalGraphic: 'test.png',
340                 pointRadius: 10
341         });
342         var customStyle2 = new Object({
343                 externalGraphic: 'test.png',
344                 graphicWidth: 12
345         });
346         var customStyle3 = new Object({
347                 externalGraphic: 'test.png',
348                 graphicHeight: 14
349         });
350         var customStyle4 = new Object({
351                 externalGraphic: 'test.png',
352                 graphicWidth: 24,
353                 graphicHeight: 16
354         });
355         var customStyle5 = new Object({
356                 externalGraphic: 'test.png',
357                 graphicWidth: 24,
358                 graphicOpacity: 1
359         });
360         var customStyle6 = new Object({
361                 externalGraphic: 'test.png',
362                 graphicWidth: 24,
363                 graphicHeight: 16,
364                 graphicXOffset: -24,
365                 graphicYOffset: -16
366         });
367                
368         var root = renderer.root;
369         if (layer.renderer.CLASS_NAME == 'OpenLayers.Renderer.SVG') {
370                 feature.style = customStyle1;
371                 layer.drawFeature(feature);
372                 t.eq(root.firstChild.getAttributeNS(null, 'width'),
373                              (2*customStyle1.pointRadius).toString(),
374                              "given a pointRadius, width equals 2*pointRadius");
375                 t.eq(root.firstChild.getAttributeNS(null, 'height'),
376                              (2*customStyle1.pointRadius).toString(),
377                              "given a pointRadius, height equals 2*pointRadius");
378                 feature.style = customStyle2;
379                 layer.drawFeature(feature);
380                 t.eq(root.firstChild.getAttributeNS(null, 'width'),
381                              root.firstChild.getAttributeNS(null, 'height'),
382                              "given a graphicWidth, width equals height");
383                 t.eq(root.firstChild.getAttributeNS(null, 'width'),
384                              customStyle2.graphicWidth.toString(),
385                              "width is set correctly");
386                 feature.style = customStyle3;
387                 layer.drawFeature(feature);
388                 t.eq(root.firstChild.getAttributeNS(null, 'height'),
389                              root.firstChild.getAttributeNS(null, 'width'),
390                              "given a graphicHeight, height equals width");
391                 t.eq(root.firstChild.getAttributeNS(null, 'height'),
392                              customStyle3.graphicHeight.toString(),
393                              "height is set correctly");
394                 feature.style = customStyle4;
395                 layer.drawFeature(feature);
396                 t.eq(root.firstChild.getAttributeNS(null, 'height'),
397                              customStyle4.graphicHeight.toString(),
398                              "given graphicHeight and graphicWidth, both are set: height");
399                 t.eq(root.firstChild.getAttributeNS(null, 'width'),
400                              customStyle4.graphicWidth.toString(),
401                              "given graphicHeight and graphicWidth, both are set: width");
402                 feature.style = customStyle5;
403                 layer.drawFeature(feature);
404                 t.eq(root.firstChild.getAttributeNS(null, 'style'),
405                              'opacity: '+customStyle5.graphicOpacity.toString()+((OpenLayers.Util.getBrowserName() == "opera" || OpenLayers.Util.getBrowserName() == "safari") ? "" : ';'),
406                              "graphicOpacity correctly set");
407                 feature.style = customStyle6;
408                 layer.drawFeature(feature);
409                 var x = geometryX / renderer.getResolution() + renderer.left;
410                 var y = geometryY / renderer.getResolution() - renderer.top;
411                 // SVG setStyle() gets x and y using getAttributeNS(), which returns
412                 // a value with only 3 decimal digits. To mimic this we use toFixed(3) here
413                 x = x.toFixed(3);
414                 y = y.toFixed(3);
415                 // toFixed() returns a string
416                 x = parseFloat(x);
417                 y = parseFloat(y);
418                 t.eq(root.firstChild.getAttributeNS(null, 'x'),
419                         (x + customStyle6.graphicXOffset).toFixed().toString(),
420                         "graphicXOffset correctly set");
421                 t.eq(root.firstChild.getAttributeNS(null, 'y'),
422                         (-y + customStyle6.graphicYOffset).toFixed().toString(),
423                         "graphicYOffset correctly set");
424         }
425         if (layer.renderer.CLASS_NAME == 'OpenLayers.Renderer.VML') {
426                 feature.style = customStyle1;
427                 layer.drawFeature(feature);
428                 t.eq(root.firstChild.style.width,
429                              (2*customStyle1.pointRadius).toString()+'px',
430                              "given a pointRadius, width equals 2*pointRadius");
431                 t.eq(root.firstChild.style.height,
432                              (2*customStyle1.pointRadius).toString()+'px',
433                              "given a pointRadius, height equals 2*pointRadius");
434                 feature.style = customStyle2;
435                 layer.drawFeature(feature);
436                 t.eq(root.firstChild.style.width,
437                              root.firstChild.style.height,
438                              "given a graphicWidth, width equals height");
439                 t.eq(root.firstChild.style.width