]> dev.renevier.net Git - syp.git/blob - openlayers/tests/Format/GeoJSON.html
initial commit
[syp.git] / openlayers / tests / Format / GeoJSON.html
1 <html> 
2 <head> 
3     <script src="../../lib/OpenLayers.js"></script> 
4     <script type="text/javascript">
5
6     var poly_content = '{"type": "FeatureCollection", "features": [{"geometry": {"type": "Polygon", "coordinates": [[[-131.484375, -5.9765625], [-112.5, -58.0078125], [-32.34375, -50.2734375], [-114.609375, 52.3828125], [-167.34375, -35.5078125], [-146.953125, -57.3046875], [-139.921875, -34.1015625], [-131.484375, -5.9765625]]]}, "type": "Feature", "id": 562, "properties": {"strokeColor": "red", "title": "Feature 2", "author": "Your Name Here"}}]}'; 
7     var null_geom_feature = '{"type":"Feature","id":573,"properties":{"strokeColor":"blue","title":"Feature 5","author":"Your Name Here"},"geometry":null}';
8     var point_feature = '{"geometry": {"type": "Point", "coordinates": [94.21875, 72.94921875]}, "type": "Feature", "id": 573, "properties": {"strokeColor": "blue", "title": "Feature 5", "author": "Your Name Here"}}';
9     var line_feature = '{"type": "FeatureCollection", "features": [{"geometry": {"type": "LineString", "coordinates": [[-27.0703125, 59.4140625], [-77.6953125, 20.7421875], [30.5859375, -36.2109375], [67.1484375, 34.8046875]]}, "type": "Feature", "id": 559, "properties": {"strokeColor": "red", "title": "Feature 1", "author": "Your Name Here"}}]}';
10     var multiple_features = '{"type": "FeatureCollection", "features": [{"geometry": {"type": "Point", "coordinates": [-91.0546875, 43.9453125]}, "type": "Feature", "id": 577, "properties": {"strokeColor": "red", "title": "Feature 2", "image": "foo.gif", "author": "Your Name Here"}}, {"geometry": {"type": "LineString", "coordinates": [[91.40625, -1.40625], [116.015625, -42.890625], [153.28125, -28.125], [108.984375, 11.25], [75.234375, 8.4375], [76.640625, 9.140625], [67.5, -36.5625], [67.5, -35.859375]]}, "type": "Feature", "id": 576, "properties": {"strokeColor": "red", "title": "Feature 1", "author": "Your Name Here"}}, {"geometry": {"type": "Point", "coordinates": [139.5703125, 57.48046875]}, "type": "Feature", "id": 575, "properties": {"strokeColor": "blue", "title": "Feature 7", "author": "Your Name Here"}}, {"geometry": {"type": "Point", "coordinates": [107.2265625, 82.44140625]}, "type": "Feature", "id": 574, "properties": {"strokeColor": "blue", "title": "Feature 6", "author": "Your Name Here"}}, {"geometry": {"type": "Point", "coordinates": [94.21875, 72.94921875]}, "type": "Feature", "id": 573, "properties": {"strokeColor": "blue", "title": "Feature 5", "author": "Your Name Here"}}, {"geometry": {"type": "Point", "coordinates": [116.3671875, 61.69921875]}, "type": "Feature", "id": 572, "properties": {"strokeColor": "blue", "title": "Feature 4", "author": "Your Name Here"}}, {"geometry": {"type": "Point", "coordinates": [145.8984375, 73.65234375]}, "type": "Feature", "id": 571, "properties": {"strokeColor": "blue", "title": "Feature 3", "author": "Your Name Here"}}, {"geometry": {"type": "Polygon", "coordinates": [[[32.34375, 52.20703125], [87.1875, 70.13671875], [122.6953125, 37.44140625], [75.234375, 42.36328125], [40.078125, 42.36328125], [28.828125, 48.33984375], [18.6328125, 56.77734375], [23.203125, 65.56640625], [32.34375, 52.20703125]]]}, "type": "Feature", "id": 570, "properties": {"strokeColor": "blue", "title": "Feature 2", "author": "Your Name Here"}}, {"geometry": {"type": "Point", "coordinates": [62.578125, -53.4375]}, "type": "Feature", "id": 569, "properties": {"strokeColor": "red", "title": "Feature 3", "author": "Your Name Here"}}, {"geometry": {"type": "Point", "coordinates": [121.640625, 16.875]}, "type": "Feature", "id": 568, "properties": {"strokeColor": "red", "title": "Feature 6", "author": "Your Name Here"}}, {"geometry": {"type": "Point", "coordinates": [135.703125, 8.4375]}, "type": "Feature", "id": 567, "properties": {"strokeColor": "red", "title": "Feature 4", "author": "Your Name Here"}}, {"geometry": {"type": "Point", "coordinates": [137.109375, 48.515625]}, "type": "Feature", "id": 566, "properties": {"strokeColor": "red", "title": "Feature 274", "author": "Your Name Here"}}, {"geometry": {"type": "Point", "coordinates": [0, 5]}, "type": "Feature", "id": 565, "properties": {}}, {"geometry": {"type": "Point", "coordinates": [0, 5]}, "type": "Feature", "id": 564, "properties": {}}, {"geometry": {"type": "Point", "coordinates": [0, 5]}, "type": "Feature", "id": 563, "properties": {}}, {"geometry": {"type": "Polygon", "coordinates": [[[-131.484375, -5.9765625], [-112.5, -58.0078125], [-32.34375, -50.2734375], [-114.609375, 52.3828125], [-167.34375, -35.5078125], [-146.953125, -57.3046875], [-139.921875, -34.1015625], [-131.484375, -5.9765625]]]}, "type": "Feature", "id": 562, "properties": {"strokeColor": "red", "title": "Feature 2", "author": "Your Name Here"}}, {"geometry": {"type": "Point", "coordinates": [48.8671875, -15.8203125]}, "type": "Feature", "id": 560, "properties": {"strokeColor": "red", "title": "Feature 2", "author": "Your Name Here"}}, {"geometry": {"type": "LineString", "coordinates": [[-27.0703125, 59.4140625], [-77.6953125, 20.7421875], [30.5859375, -36.2109375], [67.1484375, 34.8046875]]}, "type": "Feature", "id": 559, "properties": {"strokeColor": "red", "title": "Feature 1", "author": "Your Name Here"}}, {"geometry": {"type": "Point", "coordinates": [12.65625, 16.5234375]}, "type": "Feature", "id": 558, "properties": {"styleUrl": "#allstyle", "title": "Feature 1", "strokeColor": "red", "author": "Your Name Here"}}]}';
11     var parser = new OpenLayers.Format.GeoJSON();
12     var data;
13
14     function test_Format_GeoJSON_constructor(t) { 
15         t.plan(4); 
16          
17         var options = {'foo': 'bar'}; 
18         var format = new OpenLayers.Format.GeoJSON(options); 
19         t.ok(format instanceof OpenLayers.Format.GeoJSON, 
20              "new OpenLayers.Format.GeoJSON returns object" ); 
21         t.eq(format.foo, "bar", "constructor sets options correctly"); 
22         t.eq(typeof format.read, "function", "format has a read function"); 
23         t.eq(typeof format.write, "function", "format has a write function"); 
24     }
25
26     function test_Format_GeoJSON_null_geom(t) {
27         t.plan(2);
28         var f = new OpenLayers.Format.GeoJSON();
29         var fs = f.read(null_geom_feature);
30         t.ok(fs[0].geometry == null, "Reading feature with null geom works okay");
31         t.eq(f.write(fs[0]), null_geom_feature, "round trip null okay"); 
32
33     }   
34     function test_Format_GeoJSON_valid_type(t) { 
35         t.plan(14);
36
37         OpenLayers.Console.error = function(error) { window.global_error = error;};
38         var types = ["Point", "MultiPoint", "LineString", "MultiLineString", "Polygon", "MultiPolygon", "Box", "GeometryCollection"];
39         for (var i = 0; i < types.length; i++) {
40             t.ok(parser.isValidType({'type':types[i]}, "Geometry"), "Geometry with type " + types[i] + " is valid");
41         }
42         t.ok(!parser.isValidType({'type':"foo"}, "Geometry"), "Geometry with type foo is not valid");
43         t.eq(global_error, "Unsupported geometry type: foo", "error message set correctly for 'foo' geom.");
44         t.ok(parser.isValidType({}, "FeatureCollection"), "Feature collection type is always valid"); 
45         t.ok(parser.isValidType({'type':"GeometryCollection"}, "GeometryCollection"), "Geometry Collection type is valid"); 
46         t.ok(!parser.isValidType({'type':"GeometryCollection2"}, "GeometryCollection"), "Geometry Collection 2 type is invalid"); 
47         t.eq(global_error, "Cannot convert types from GeometryCollection2 to GeometryCollection", "error message set correctly for bad geometrycollection type");
48     }
49
50     function test_Format_GeoJSON_point(t) { 
51         t.plan(3);
52
53         data = parser.read(point_feature);
54         t.eq(data[0].fid, 573, "Fid is correct on point feature"); 
55         t.eq(data[0].geometry.x, 94.21875, 'Reading point feature gives correct x');
56         data = parser.read(point_feature, "Feature");
57         t.eq(data.fid, 573, 'Reading point feature with type gives feature instead of array of features ');
58     }
59
60     function test_Format_GeoJSON_line(t) { 
61         t.plan(5);
62
63         data = parser.read(line_feature);
64         t.eq(data[0].fid, 559, "Fid is correct on line feature"); 
65         t.eq(data[0].geometry.components.length, 4, 'Reading line feature gives correct length');
66         t.eq(data[0].geometry.CLASS_NAME, 'OpenLayers.Geometry.LineString', 'Reading line feature gives correct class');
67         t.eq(data[0].geometry.components[0].x, -27.0703125, 'Reading line feature gives correct x');
68         t.eq(data[0].geometry.components[0].y, 59.4140625, 'Reading line feature gives correct y');
69     }
70
71     function test_Format_GeoJSON_poly(t) { 
72         t.plan(2);
73
74         data = parser.read(poly_content);
75         t.eq(data[0].fid, 562, "poly id is correct");
76         t.eq(data[0].geometry.components[0].components.length, 8, 
77                 'Reading polygon first ring  on feature from featurecollection gives correct length');
78     }
79
80     function test_Format_GeoJSON_multipoint(t) { 
81         t.plan(5);
82
83         var multipoint = {
84            "type": "MultiPoint",
85            "coordinates": [
86                [100.0, 0.0], [101.0, 1.0]
87            ]
88         };
89         data = parser.read(multipoint, "Geometry");
90         t.eq(data.components.length, 2, 
91             "Right number of components");
92         t.eq(data.components[0].CLASS_NAME, "OpenLayers.Geometry.Point", "First component is point");    
93         t.eq(data.components[1].CLASS_NAME, "OpenLayers.Geometry.Point", "Second component is point");    
94         t.eq(data.components[1].x, 101, "x of second component is right");    
95         t.eq(data.components[1].y, 1, "y of second component is right");    
96     }
97
98     function test_Format_GeoJSON_multiline(t) {
99         t.plan(3);
100
101         var multiline = {
102            "type": "MultiLineString",
103            "coordinates": [
104                [ [100.0, 0.0], [101.0, 1.0] ],
105                [ [102.0, 2.0], [103.0, 3.0] ]
106            ]
107         };
108         data = parser.read(multiline, "Geometry");
109         t.eq(data.CLASS_NAME, "OpenLayers.Geometry.MultiLineString", "Correct class retrieved");
110         t.eq(data.components[0].components[0].CLASS_NAME, "OpenLayers.Geometry.Point", "correct type of components");
111         t.eq(data.components[0].CLASS_NAME, "OpenLayers.Geometry.LineString", "correct type of components");
112     }
113
114     function test_Format_GeoJSON_multipol(t) {
115         t.plan(2);
116
117         var multipol = {
118             "type": "MultiPolygon",
119             "coordinates": [
120                 [
121                     [ [102.0, 2.0], [103.0, 2.0], [103.0, 3.0], [102.0, 3.0], [102.0, 2.0] ]
122                 ],
123                 [
124                     [ [100.0, 0.0], [101.0, 0.0], [101.0, 1.0], [100.0, 1.0], [100.0, 0.0] ],
125                     [ [100.2, 0.2], [100.8, 0.2], [100.8, 0.8], [100.2, 0.8], [100.2, 0.2] ]
126                 ]
127             ]
128         };
129         OpenLayers.Console.error = function(error) { window.global_error = error; };
130         data = parser.read(multipol, "Geometry");
131         t.eq(data.CLASS_NAME, "OpenLayers.Geometry.MultiPolygon", "Correct class retrieved");
132         t.eq(data.components[1].components[0].components[0].CLASS_NAME, "OpenLayers.Geometry.Point", "correct type of components");
133     }
134
135     function test_Format_GeoJSON_box(t) {
136         t.plan(6);
137
138         var box = {
139             "type": "Box",
140             "coordinates": [[100.0, 0.0], [101.0, 1.0]]
141         };
142         var poly = parser.read(box, "Geometry");
143         t.eq(poly.CLASS_NAME, "OpenLayers.Geometry.Polygon", "Box creates polygon"); 
144         t.eq(poly.components[0].components[1].x, 101, "x of lower right is correct");
145         t.eq(poly.components[0].components[1].y, 0, "y of lower right is correct");
146         t.eq(poly.components[0].components[3].x, 100, "x of upper left is correct");
147         t.eq(poly.components[0].components[3].y, 1, "y of upper left is correct");
148         box = parser.write(poly );
149         t.ok(box.search("Polygon") != -1 , "Serializes back to polygon");
150     }
151
152     // This test is from the geom_collection example on geojson spec.
153     function test_Format_GeoJSON_collection(t) {
154        t.plan(12);
155
156        var geomcol = {
157            "type": "GeometryCollection",
158            "geometries": [
159                {
160                    "type": "Point",
161                    "coordinates": [100.0, 0.0]
162                },
163                {
164                    "type": "LineString",
165                    "coordinates": [
166                        [101.0, 0.0], [102.0, 1.0]
167                    ]
168                }
169            ]
170         };
171         data = parser.read(geomcol, "Geometry");
172         t.eq(data.CLASS_NAME, "OpenLayers.Geometry.Collection",
173              "GeometryCollection deserialized into geometry.collection");  
174         t.eq(data.components[0].CLASS_NAME, "OpenLayers.Geometry.Point",
175              "First geom is correct type");  
176         t.eq(data.components[0].x, 100,
177              "First geom in geom collection has correct x");  
178         t.eq(data.components[0].y, 0,
179              "First geom in geom collection has correct x");  
180         
181         t.eq(data.components[1].CLASS_NAME, "OpenLayers.Geometry.LineString",
182              "Second geom in geom collection is point linestring");  
183         t.eq(data.components[1].components.length, 2,
184              "linestring is correct length");
185         t.eq(data.components[1].components[1].x, 102,
186              "linestring is correct x end");
187         t.eq(data.components[1].components[1].y, 1,
188              "linestring is correct y end");
189
190         data = parser.read(geomcol, "FeatureCollection");
191         t.eq(data[0].CLASS_NAME, "OpenLayers.Feature.Vector",
192              "GeometryCollection can be read in as a feature collection");
193         t.eq(data[0].geometry.CLASS_NAME, "OpenLayers.Geometry.Collection",
194              "feature contains the correct geometry type");
195         var feature = {
196            "type": "Feature",
197            "geometry": {
198               "type": "GeometryCollection",
199               "geometries": [
200                   {
201                     "type": "Point",
202                     "coordinates": [100.0, 0.0]
203                   },
204                   {
205                     "type": "LineString",
206                     "coordinates": [
207                         [101.0, 0.0], [102.0, 1.0]
208                     ]
209                   }
210               ]
211            },
212            "properties": {
213                "prop0": "value0",
214                "prop1": "value1"
215            }
216         };
217         data = parser.read(feature, "Feature");
218         t.eq(data.geometry.CLASS_NAME, "OpenLayers.Geometry.Collection", "Geometry of feature is a collection");
219         var l = new OpenLayers.Layer.Vector();
220         l.addFeatures(data);
221         t.ok(true, "adding a feature with geomcollection to layer doesn't cause error."); 
222     }
223
224     function test_Format_GeoJSON_multipleFeatures(t) {
225         t.plan(2);
226
227         var feats = parser.read(multiple_features);
228         t.eq(feats.length, 19, "parsing a feature collection returns the correct number of features.");
229         var types = {'Point':0, 'LineString':0, 'Polygon':0};
230         for(var i = 0; i < feats.length; i++) {
231             var type = feats[i].geometry.CLASS_NAME.replace("OpenLayers.Geometry.", "");
232             types[type]++;
233         }
234         t.eq(types, {'Point':15, 'Polygon': 2, 'LineString':2}, "Correct number of each type"); 
235     }
236
237     function test_Format_GeoJSON_writeWithCRS(t) {
238         t.plan(2);
239         var feature = new OpenLayers.Feature.Vector(new OpenLayers.Geometry.Point(1,2));
240         feature.fid = 0;
241         var output = '{"type":"Feature","id":0,"properties":{},"geometry":{"type":"Point","coordinates":[1,2]},"crs":{"type":"OGC","properties":{"urn":"urn:ogc:def:crs:OGC:1.3:CRS84"}}}';
242         var layer = new OpenLayers.Layer.Vector();
243         layer.projection = "EPSG:4326";
244         feature.layer = layer;
245         var parser = new OpenLayers.Format.GeoJSON();
246         var test_out = parser.write(feature);
247         t.eq(test_out, output, "Output is equal for vector with layer in EPSG:4326 ");
248         feature.layer.projection = "EPSG:2805";
249         output = '{"type":"Feature","id":0,"properties":{},"geometry":{"type":"Point","coordinates":[1,2]},"crs":{"type":"EPSG","properties":{"code":2805}}}';
250         test_out = parser.write(feature);
251         t.eq(test_out, output, "Output is equal for vector with point");
252     }    
253         
254     function test_Format_GeoJSON_write(t) {
255         t.plan(10);
256
257         var line_object = {
258             "type": "FeatureCollection", 
259             "features": [
260                 {
261                     "geometry": {
262                         "type": "LineString", 
263                         "coordinates": [
264                             [-27.0703125, 59.4140625], 
265                             [-77.6953125, 20.7421875], 
266                             [30.5859375, -36.2109375], 
267                             [67.1484375, 34.8046875]
268                         ]
269                     },
270                     "type": "Feature", 
271                     "id": 559, 
272                     "properties": {
273                         "strokeColor": "red", 
274                         "title": "Feature 1", 
275                         "author": "Your Name Here"
276                     }
277                 }
278             ]
279         };
280         data = parser.read(line_object);
281         out = parser.write(data);
282         serialized = '{"type":"FeatureCollection","features":[{"type":"Feature","id":559,"properties":{"strokeColor":"red","title":"Feature 1","author":"Your Name Here"},"geometry":{"type":"LineString","coordinates":[[-27.0703125,59.4140625],[-77.6953125,20.7421875],[30.5859375,-36.2109375],[67.1484375,34.8046875]]}}]}';
283         t.eq(out, serialized, "input and output on line collections are the same");
284         
285         var serialize_tests = [
286             [
287                 new OpenLayers.Feature.Vector(new OpenLayers.Geometry.Point(1,2)),
288                 '{"type":"Feature","id":0,"properties":{},"geometry":{"type":"Point","coordinates":[1,2]}}'
289             ],
290             [
291                 new OpenLayers.Geometry.Point(1,2), 
292                 '{"type":"Point","coordinates":[1,2]}'
293             ], 
294             [
295                 new OpenLayers.Geometry.MultiPoint([
296                     new OpenLayers.Geometry.Point(1,2)
297                 ]),
298                 '{"type":"MultiPoint","coordinates":[[1,2]]}'
299             ],
300             [
301                 new OpenLayers.Geometry.LineString([
302                     new OpenLayers.Geometry.Point(1,2), 
303                     new OpenLayers.Geometry.Point(3,4)
304                 ]),
305                 '{"type":"LineString","coordinates":[[1,2],[3,4]]}'
306             ], 
307             [
308                 new OpenLayers.Geometry.Polygon([
309                     new OpenLayers.Geometry.LinearRing([
310                         new OpenLayers.Geometry.Point(1,2), 
311                         new OpenLayers.Geometry.Point(3,4), 
312                         new OpenLayers.Geometry.Point(5,6)
313                     ])
314                 ]), 
315                 '{"type":"Polygon","coordinates":[[[1,2],[3,4],[5,6],[1,2]]]}'
316             ],
317             [
318                 new OpenLayers.Geometry.Collection([
319                     new OpenLayers.Geometry.Polygon([
320                         new OpenLayers.Geometry.LinearRing([
321                             new OpenLayers.Geometry.Point(1,2), 
322                             new OpenLayers.Geometry.Point(3,4), 
323                             new OpenLayers.Geometry.Point(5,6)
324                         ])
325                     ]), 
326                     new OpenLayers.Geometry.LineString([
327                         new OpenLayers.Geometry.Point(1,2), 
328                         new OpenLayers.Geometry.Point(3,4)
329                     ]),
330                     new OpenLayers.Geometry.Point(1,2)
331                 ]),
332                 '{"type":"GeometryCollection","geometries":[{"type":"Polygon","coordinates":[[[1,2],[3,4],[5,6],[1,2]]]},{"type":"LineString","coordinates":[[1,2],[3,4]]},{"type":"Point","coordinates":[1,2]}]}'
333             ]
334         ];
335         serialize_tests[0][0].fid = 0;
336         multiline = new OpenLayers.Geometry.MultiLineString([serialize_tests[3][0], serialize_tests[3][0]]);
337         serialize_tests.push([multiline, '{"type":"MultiLineString","coordinates":[[[1,2],[3,4]],[[1,2],[3,4]]]}']);
338         multipolygon = new OpenLayers.Geometry.MultiPolygon([serialize_tests[4][0],  serialize_tests[4][0]]);
339         serialize_tests.push([multipolygon, '{"type":"MultiPolygon","coordinates":[[[[1,2],[3,4],[5,6],[1,2]]],[[[1,2],[3,4],[5,6],[1,2]]]]}']);
340         serialize_tests.push([ [ serialize_tests[0][0] ], '{"type":"FeatureCollection","features":[{"type":"Feature","id":0,"properties":{},"geometry":{"type":"Point","coordinates":[1,2]}}]}' ]);
341         for (var i = 0; i < serialize_tests.length; i++) {
342             var input = serialize_tests[i][0];
343             var output = serialize_tests[i][1];
344             test_out = parser.write(input);
345             t.eq(test_out, output, "Serializing " + input.toString() + " saved correctly.");
346         }
347     }
348
349     function test_Format_GeoJSON_read_object(t) {
350         t.plan(1);
351
352         var line_object = {
353             "type": "FeatureCollection", 
354             "features": [
355                 {
356                     "geometry": {
357                         "type": "LineString", 
358                         "coordinates": [
359                             [-27.0703125, 59.4140625], 
360                             [-77.6953125, 20.7421875], 
361                             [30.5859375, -36.2109375], 
362                             [67.1484375, 34.8046875]
363                         ]
364                     }, 
365                     "type": "Feature", 
366                     "id": 559, 
367                     "properties": {
368                         "strokeColor": "red", 
369                         "title": "Feature 1", 
370                         "author": "Your Name Here"
371                     }
372                 }
373             ]
374         };
375         data = parser.read(line_object);
376         t.eq(data[0].fid, 559, "Can read data from an object correctly.");
377     }
378
379     function test_Format_GeoJSON_read_attributes(t) {
380         t.plan(3);
381
382         var parser = new OpenLayers.Format.GeoJSON();
383         data = parser.read(line_feature);
384         t.eq(data[0].attributes['strokeColor'], 'red', 'read strokeColor attribute properly'); 
385         t.eq(data[0].attributes['title'], 'Feature 1', 'read title attribute properly'); 
386         t.eq(data[0].attributes['author'], 'Your Name Here', 'read author attribute properly'); 
387     }
388
389     function test_read_bbox(t) {
390         t.plan(8);
391
392         var f;
393         parser = new OpenLayers.Format.GeoJSON();
394
395         // 4 tests
396         f = '{"geometry": {"type": "Point", "coordinates": [94.21875, 72.94921875], "bbox": [94.21875, 72.94921875, 94.21875, 72.94921875]}, "type": "Feature", "id": 573, "properties": {}, "bbox": [95.0, 73.0]}';
397         data = parser.read(f);
398         t.eq(data[0].bounds.left, 94.21875, "read left bound is correct");
399         t.eq(data[0].bounds.bottom, 72.94921875, "read bottom left bound is correct");
400         t.eq(data[0].bounds.right, 94.21875, "read right bound is correct");
401         t.eq(data[0].bounds.top, 72.94921875, "read top left bound is correct");
402
403         // 4 tests
404         f = '{"geometry": {"type": "Point", "coordinates": [94.21875, 72.94921875]}, "type": "Feature", "id": 573, "properties": {}, "bbox": [95.0, 73.0, 96.0, 74.0]}';
405         data = parser.read(f);
406         t.eq(data[0].bounds.left, 95.0, "read left bound is correct");
407         t.eq(data[0].bounds.bottom, 73.0, "read bottom left bound is correct");
408         t.eq(data[0].bounds.right, 96.0, "read right bound is correct");
409         t.eq(data[0].bounds.top, 74.0, "read top left bound is correct");
410     }
411
412     </script> 
413 </head> 
414 <body> 
415 </body> 
416 </html>