diff --git a/app/assets/config/manifest.js b/app/assets/config/manifest.js
index c4cf761a4..3bc6e3f23 100644
--- a/app/assets/config/manifest.js
+++ b/app/assets/config/manifest.js
@@ -14,3 +14,4 @@
//= link print.css
//= link pdf_fonts.css
//= link_tree ../../../vendor/assets/images
+//= link_tree ../../../node_modules/leaflet/dist/images
diff --git a/app/assets/javascripts/map.js b/app/assets/javascripts/map.js
index 3793e2858..cb5b9835f 100644
--- a/app/assets/javascripts/map.js
+++ b/app/assets/javascripts/map.js
@@ -220,17 +220,22 @@
}
},
addGeozone: function(geozone, map) {
- var polygon = L.polygon(geozone.outline_points, {
- color: geozone.color,
- fillOpacity: 0.3,
- className: "map-polygon"
+ var geojsonData = JSON.parse(geozone.outline_points);
+
+ var geoJsonLayer = L.geoJSON(geojsonData, {
+ style: {
+ color: geozone.color,
+ fillOpacity: 0.3,
+ className: "map-polygon"
+ },
+ onEachFeature: function(feature, layer) {
+ if (geozone.headings) {
+ layer.bindPopup(geozone.headings.join("
"));
+ }
+ }
});
- if (geozone.headings !== undefined) {
- polygon.bindPopup(geozone.headings.join("
"));
- }
-
- polygon.addTo(map);
+ geoJsonLayer.addTo(map);
},
getPopupContent: function(data) {
return "" + data.title + "";
diff --git a/app/models/concerns/geojson_format_validator.rb b/app/models/concerns/geojson_format_validator.rb
index e2a88f0e8..1614cc794 100644
--- a/app/models/concerns/geojson_format_validator.rb
+++ b/app/models/concerns/geojson_format_validator.rb
@@ -3,8 +3,13 @@ class GeojsonFormatValidator < ActiveModel::EachValidator
if value.present?
geojson = parse_json(value)
- unless geojson?(geojson)
+ unless valid_geojson?(geojson)
record.errors.add(attribute, :invalid)
+ return
+ end
+
+ unless valid_coordinates?(geojson)
+ record.errors.add(attribute, :invalid_coordinates)
end
end
end
@@ -12,12 +17,91 @@ class GeojsonFormatValidator < ActiveModel::EachValidator
private
def parse_json(geojson_data)
- JSON.parse(geojson_data) rescue nil
+ JSON.parse(geojson_data)
+ rescue JSON::ParserError
+ nil
end
- def geojson?(geojson)
+ def valid_geojson?(geojson)
return false unless geojson.is_a?(Hash)
- geojson.dig("geometry", "coordinates").is_a?(Array)
+ if geojson["type"] == "FeatureCollection"
+ valid_feature_collection?(geojson)
+ elsif geojson["type"] == "Feature"
+ valid_feature?(geojson)
+ else
+ valid_geometry?(geojson)
+ end
+ end
+
+ def valid_feature_collection?(geojson)
+ return false unless geojson["features"].is_a?(Array)
+
+ geojson["features"].all? { |feature| valid_feature?(feature) }
+ end
+
+ def valid_feature?(feature)
+ feature["type"] == "Feature" && valid_geometry?(feature["geometry"])
+ end
+
+ def valid_geometry?(geometry)
+ geometry.is_a?(Hash) && valid_geometry_types.include?(geometry["type"])
+ end
+
+ def valid_geometry_types
+ [
+ "Point", "LineString", "Polygon", "MultiPoint", "MultiLineString", "MultiPolygon",
+ "GeometryCollection"
+ ]
+ end
+
+ def valid_coordinates?(geojson)
+ if geojson["type"] == "FeatureCollection"
+ geojson["features"].all? { |feature| valid_coordinates?(feature) }
+ elsif geojson["type"] == "Feature"
+ valid_geometry_coordinates?(geojson["geometry"])
+ else
+ valid_geometry_coordinates?(geojson)
+ end
+ end
+
+ def valid_geometry_coordinates?(geometry)
+ if geometry["type"] == "GeometryCollection"
+ geometries = geometry["geometries"]
+
+ return geometries.is_a?(Array) && geometries.all? { |geom| valid_geometry_coordinates?(geom) }
+ end
+
+ coordinates = geometry["coordinates"]
+
+ return false unless coordinates.is_a?(Array)
+
+ case geometry["type"]
+ when "Point"
+ valid_wgs84_coordinates?(coordinates)
+ when "LineString", "MultiPoint"
+ coordinates.all? { |coordinates| valid_wgs84_coordinates?(coordinates) }
+ when "Polygon", "MultiLineString"
+ valid_polygon_coordinates?(coordinates)
+ when "MultiPolygon"
+ coordinates.all? do |polygon_coordinates|
+ valid_polygon_coordinates?(polygon_coordinates)
+ end
+ else
+ false
+ end
+ end
+
+ def valid_wgs84_coordinates?(coordinates)
+ return false unless coordinates.is_a?(Array) && coordinates.size == 2
+
+ longitude, latitude = coordinates
+ (-180.0..180.0).include?(longitude) && (-90.0..90.0).include?(latitude)
+ end
+
+ def valid_polygon_coordinates?(polygon_coordinates)
+ polygon_coordinates.all? do |ring|
+ ring.all? { |coordinates| valid_wgs84_coordinates?(coordinates) }
+ end
end
end
diff --git a/app/models/geozone.rb b/app/models/geozone.rb
index d3fc484d5..7c72cdded 100644
--- a/app/models/geozone.rb
+++ b/app/models/geozone.rb
@@ -21,26 +21,40 @@ class Geozone < ApplicationRecord
end
def outline_points
- normalized_coordinates.map { |longlat| [longlat.last, longlat.first] }
+ normalized_geojson&.to_json
end
private
- def normalized_coordinates
+ def normalized_geojson
if geojson.present?
- if geojson.match(/"coordinates"\s*:\s*\[\s*\[\s*\[\s*\[/)
- coordinates.reduce([], :concat).reduce([], :concat)
- elsif geojson.match(/"coordinates"\s*:\s*\[\s*\[\s*\[/)
- coordinates.reduce([], :concat)
+ parsed_geojson = JSON.parse(geojson)
+
+ if parsed_geojson["type"] == "FeatureCollection"
+ parsed_geojson
+ elsif parsed_geojson["type"] == "Feature"
+ wrap_in_feature_collection(parsed_geojson)
+ elsif parsed_geojson["geometry"]
+ wrap_in_feature_collection(wrap_in_feature(parsed_geojson["geometry"]))
+ elsif parsed_geojson["type"] && parsed_geojson["coordinates"]
+ wrap_in_feature_collection(wrap_in_feature(parsed_geojson))
else
- coordinates
+ raise ArgumentError, "Invalid GeoJSON fragment"
end
- else
- []
end
end
- def coordinates
- JSON.parse(geojson)["geometry"]["coordinates"]
+ def wrap_in_feature(geometry)
+ {
+ type: "Feature",
+ geometry: geometry
+ }
+ end
+
+ def wrap_in_feature_collection(feature)
+ {
+ type: "FeatureCollection",
+ features: [feature]
+ }
end
end
diff --git a/config/application.rb b/config/application.rb
index 593c41866..ed72b992a 100644
--- a/config/application.rb
+++ b/config/application.rb
@@ -125,6 +125,7 @@ module Consul
config.assets.paths << Rails.root.join("app", "assets", "fonts")
config.assets.paths << Rails.root.join("vendor", "assets", "fonts")
config.assets.paths << Rails.root.join("node_modules", "jquery-ui", "themes", "base")
+ config.assets.paths << Rails.root.join("node_modules", "leaflet", "dist")
config.assets.paths << Rails.root.join("node_modules")
config.active_job.queue_adapter = :delayed_job
diff --git a/config/locales/en/activerecord.yml b/config/locales/en/activerecord.yml
index 43397129f..068a4dde0 100644
--- a/config/locales/en/activerecord.yml
+++ b/config/locales/en/activerecord.yml
@@ -551,7 +551,8 @@ en:
geozone:
attributes:
geojson:
- invalid: "The GeoJSON provided does not follow the correct format. It must follow the \"Polygon\" or \"MultiPolygon\" type format."
+ invalid: "The GeoJSON provided does not follow the correct format. It must follow the RFC 7946 standard format"
+ invalid_coordinates: "The GeoJSON provided contains invalid coordinates; the coordinates must be in the required \"Longitude, Latitude\" format and follow the RFC 7946 standard format"
image:
attributes:
attachment:
diff --git a/config/locales/es/activerecord.yml b/config/locales/es/activerecord.yml
index 4aa224ae7..9bab05b5a 100644
--- a/config/locales/es/activerecord.yml
+++ b/config/locales/es/activerecord.yml
@@ -551,7 +551,8 @@ es:
geozone:
attributes:
geojson:
- invalid: "Los datos GeoJSON proporcionados no tienen el formato correcto. Deben tener un tipo del formato \"Polygon\" o \"MultiPolygon\"."
+ invalid: "Los datos GeoJSON proporcionados no tienen el formato correcto. Deben seguir el formato estándar RFC 7946"
+ invalid_coordinates: "Los datos GeoJSON proporcionados contienen coordenadas inválidas; las coordenadas deben utilizar el formato \"Longitud, Latitud\" y seguir el formato estándar RFC 7946"
image:
attributes:
attachment:
diff --git a/spec/factories/administration.rb b/spec/factories/administration.rb
index 1855b1069..b02cfcb20 100644
--- a/spec/factories/administration.rb
+++ b/spec/factories/administration.rb
@@ -20,7 +20,15 @@ FactoryBot.define do
trait :with_geojson do
geojson do
- '{ "geometry": { "type": "Polygon", "coordinates": [[0.117,51.513],[0.118,51.512],[0.119,51.514]] } }'
+ <<~JSON
+ {
+ "type": "Feature",
+ "geometry": {
+ "type": "Polygon",
+ "coordinates": [[[0.117, 51.513], [0.118, 51.512], [0.119, 51.514]]]
+ }
+ }
+ JSON
end
end
end
diff --git a/spec/models/geojson_format_validator_spec.rb b/spec/models/geojson_format_validator_spec.rb
new file mode 100644
index 000000000..1a3ebbf54
--- /dev/null
+++ b/spec/models/geojson_format_validator_spec.rb
@@ -0,0 +1,329 @@
+require "rails_helper"
+
+describe GeojsonFormatValidator do
+ before do
+ dummy_model = Class.new do
+ include ActiveModel::Model
+ attr_accessor :geojson
+ validates :geojson, geojson_format: true
+ end
+
+ stub_const("DummyModel", dummy_model)
+ end
+
+ let(:record) { DummyModel.new }
+
+ it "is not valid with an empty hash" do
+ record.geojson = "{}"
+
+ expect(record).not_to be_valid
+ end
+
+ it "is not valid with arbitrary keys" do
+ record.geojson = '{ "invalid": "yes" }'
+
+ expect(record).not_to be_valid
+ end
+
+ it "is not valid without a type" do
+ record.geojson = '{ "coordinates": [1.23, 4.56] }'
+
+ expect(record).not_to be_valid
+ end
+
+ it "is not valid without a type but a geometry" do
+ record.geojson = '{ "geometry": { "type": "Point", "coordinates": [1.23, 4.56] } }'
+
+ expect(record).not_to be_valid
+ end
+
+ context "Point geometry" do
+ it "is not valid without coordinates" do
+ record.geojson = '{ "type": "Point" }'
+
+ expect(record).not_to be_valid
+ end
+
+ it "is not valid with only one the longitude" do
+ record.geojson = '{ "type": "Point", "coordinates": 1.23 }'
+
+ expect(record).not_to be_valid
+ end
+
+ it "is not valid with non-numerical coordinates" do
+ record.geojson = '{ "type": "Point", "coordinates": ["1.23", "4.56"] }'
+
+ expect(record).not_to be_valid
+ end
+
+ it "is not valid with 3-dimensional coordinates" do
+ record.geojson = '{ "type": "Point", "coordinates": [1.23, 4.56, 7.89] }'
+
+ expect(record).not_to be_valid
+ end
+
+ it "is not valid with multiple coordinates" do
+ record.geojson = '{ "type": "Point", "coordinates": [[1.23, 4.56], [7.89, 10.11]] }'
+
+ expect(record).not_to be_valid
+ end
+
+ it "is not valid with a longitude above 180" do
+ record.geojson = '{ "type": "Point", "coordinates": [180.01, 4.56] }'
+
+ expect(record).not_to be_valid
+ end
+
+ it "is not valid with a longitude below -180" do
+ record.geojson = '{ "type": "Point", "coordinates": [-180.01, 4.56] }'
+
+ expect(record).not_to be_valid
+ end
+
+ it "is not valid with a latitude above 90" do
+ record.geojson = '{ "type": "Point", "coordinates": [1.23, 90.01] }'
+
+ expect(record).not_to be_valid
+ end
+
+ it "is not valid with a latitude below -90" do
+ record.geojson = '{ "type": "Point", "coordinates": [1.23, -90.01] }'
+
+ expect(record).not_to be_valid
+ end
+
+ it "is valid with coordinates in the valid range" do
+ record.geojson = '{ "type": "Point", "coordinates": [1.23, 4.56] }'
+
+ expect(record).to be_valid
+ end
+
+ it "is valid with coordinates at the positive end of the range" do
+ record.geojson = '{ "type": "Point", "coordinates": [180.0, 90.0] }'
+
+ expect(record).to be_valid
+ end
+
+ it "is valid with coordinates at the negative end of the range" do
+ record.geojson = '{ "type": "Point", "coordinates": [-180.0, -90.0] }'
+
+ expect(record).to be_valid
+ end
+ end
+
+ context "LineString or MultiPoint geometry" do
+ it "is not valid with a one-dimensional array of coordinates" do
+ record.geojson = '{ "type": "LineString", "coordinates": [1.23, 4.56] }'
+
+ expect(record).not_to be_valid
+
+ record.geojson = '{ "type": "MultiPoint", "coordinates": [1.23, 4.56] }'
+
+ expect(record).not_to be_valid
+ end
+
+ it "is valid with a two-dimensional array including only one point" do
+ record.geojson = '{ "type": "LineString", "coordinates": [[1.23, 4.56]] }'
+
+ expect(record).to be_valid
+
+ record.geojson = '{ "type": "MultiPoint", "coordinates": [[1.23, 4.56]] }'
+
+ expect(record).to be_valid
+ end
+
+ it "is not valid when some coordinates are invalid" do
+ record.geojson = '{ "type": "LineString", "coordinates": [[1.23, 4.56], [180.01, 4.56]] }'
+
+ expect(record).not_to be_valid
+
+ record.geojson = '{ "type": "MultiPoint", "coordinates": [[1.23, 4.56], [180.01, 4.56]] }'
+
+ expect(record).not_to be_valid
+ end
+
+ it "is valid when all the coordinates are valid" do
+ record.geojson = '{ "type": "LineString", "coordinates": [[1.23, 4.56], [7.89, 4.56]] }'
+
+ expect(record).to be_valid
+
+ record.geojson = '{ "type": "MultiPoint", "coordinates": [[1.23, 4.56], [7.89, 4.56]] }'
+
+ expect(record).to be_valid
+ end
+ end
+
+ context "GeometryCollection" do
+ it "is not valid if it doesn't contain geometries" do
+ record.geojson = '{ "type": "GeometryCollection" }'
+
+ expect(record).not_to be_valid
+ end
+
+ it "is not valid if geometries is not an array" do
+ record.geojson = <<~JSON
+ {
+ "type": "GeometryCollection",
+ "geometries": { "type": "Point", "coordinates": [1.23, 4.56] }
+ }
+ JSON
+
+ expect(record).not_to be_valid
+ end
+
+ it "is valid if the array of geometries is empty" do
+ record.geojson = '{ "type": "GeometryCollection", "geometries": [] }'
+
+ expect(record).to be_valid
+ end
+
+ it "is valid if all geometries are valid" do
+ record.geojson = <<~JSON
+ {
+ "type": "GeometryCollection",
+ "geometries": [
+ {
+ "type": "Point",
+ "coordinates": [100.0, 0.0]
+ },
+ {
+ "type": "LineString",
+ "coordinates": [
+ [101.0, 0.0],
+ [102.0, 1.0]
+ ]
+ }
+ ]
+ }
+ JSON
+
+ expect(record).to be_valid
+ end
+
+ it "is not valid if some geometries are invalid" do
+ record.geojson = <<~JSON
+ {
+ "type": "GeometryCollection",
+ "geometries": [
+ {
+ "type": "Point",
+ "coordinates": [100.0, 0.0]
+ },
+ {
+ "type": "LineString",
+ "coordinates": [101.0, 0.0]
+ }
+ ]
+ }
+ JSON
+
+ expect(record).not_to be_valid
+ end
+ end
+
+ context "Feature" do
+ it "is valid with a valid geometry" do
+ record.geojson = <<~JSON
+ {
+ "type": "Feature",
+ "geometry": {
+ "type": "Point",
+ "coordinates": [1.23, 4.56]
+ }
+ }
+ JSON
+
+ expect(record).to be_valid
+ end
+
+ it "is not valid with a valid geometry" do
+ record.geojson = <<~JSON
+ {
+ "type": "Feature",
+ "geometry": {
+ "type": "Point",
+ "coordinates": [1.23]
+ }
+ }
+ JSON
+
+ expect(record).not_to be_valid
+ end
+ end
+
+ context "FeatureCollection" do
+ it "is not valid without features" do
+ record.geojson = '{ "type": "FeatureCollection" }'
+ end
+
+ it "is not valid if features is not an array" do
+ record.geojson = <<~JSON
+ {
+ "type": "FeatureCollection",
+ "features": {
+ "type": "Feature",
+ "geometry": {
+ "type": "Point",
+ "coordinates": [1.23, 4.56]
+ }
+ }
+ }
+ JSON
+ end
+
+ it "is valid if the array of features is empty" do
+ record.geojson = '{ "type": "FeatureCollection", "features": [] }'
+
+ expect(record).to be_valid
+ end
+
+ it "is valid if all features are valid" do
+ record.geojson = <<~JSON
+ {
+ "type": "FeatureCollection",
+ "features": [
+ {
+ "type": "Feature",
+ "geometry": {
+ "type": "Point",
+ "coordinates": [1.23, 4.56]
+ }
+ },
+ {
+ "type": "Feature",
+ "geometry": {
+ "type": "LineString",
+ "coordinates": [[101.0, 0.0], [102.0, 1.0]]
+ }
+ }
+ ]
+ }
+ JSON
+
+ expect(record).to be_valid
+ end
+
+ it "is not valid if some features are invalid" do
+ record.geojson = <<~JSON
+ {
+ "type": "FeatureCollection",
+ "features": [
+ {
+ "type": "Feature",
+ "geometry": {
+ "type": "Point",
+ "coordinates": [1.23, 4.56]
+ }
+ },
+ {
+ "type": "LineString",
+ "coordinates": [[101.0, 0.0], [102.0, 1.0]]
+ }
+ ]
+ }
+ JSON
+
+ expect(record).not_to be_valid
+ end
+ end
+end
diff --git a/spec/models/geozone_spec.rb b/spec/models/geozone_spec.rb
index 973e61139..dcae19120 100644
--- a/spec/models/geozone_spec.rb
+++ b/spec/models/geozone_spec.rb
@@ -18,10 +18,20 @@ describe Geozone do
end
it "is not valid with invalid geojson file format" do
- geozone.geojson = '{"geo\":{"type":"Incorrect key","coordinates": [
- [40.8792937308316, -3.9259027239257],
- [40.8788966596619, -3.9249047078766],
- [40.8789131852224, -3.9247799675785]]}}'
+ geozone.geojson = <<~JSON
+ {
+ "type": "Feature",
+ "geometry": {
+ "type": "Incorrect",
+ "coordinates": [
+ [40.8792937308316, -3.9259027239257],
+ [40.8788966596619, -3.9249047078766],
+ [40.8789131852224, -3.9247799675785]
+ ]
+ }
+ }
+ JSON
+
expect(geozone).not_to be_valid
end
@@ -54,99 +64,149 @@ describe Geozone do
end
describe "#outline_points" do
- it "returns empty array when geojson is nil" do
- expect(geozone.outline_points).to eq([])
+ it "returns nil when geojson is nil" do
+ geozone.geojson = nil
+
+ expect(geozone.outline_points).to be nil
end
- it "returns coordinates array when geojson is not nil" do
- geozone = build(:geozone, geojson: '{
- "geometry": {
- "type": "Polygon",
- "coordinates": [
- [40.8792937308316, -3.9259027239257],
- [40.8788966596619, -3.9249047078766],
- [40.8789131852224, -3.9247799675785]
- ]
+ it "returns normalized feature collection when geojson is a valid FeatureCollection" do
+ geozone.geojson = <<~JSON
+ {
+ "type": "FeatureCollection",
+ "features": [{
+ "type": "Feature",
+ "geometry": {
+ "type": "Polygon",
+ "coordinates": [[
+ [-3.9259027239257, 40.8792937308316],
+ [-3.9249047078766, 40.8788966596619],
+ [-3.9247799675785, 40.8789131852224],
+ [-3.9259027239257, 40.8792937308316]
+ ]]
+ }
+ }]
}
- }')
+ JSON
- expect(geozone.outline_points).to eq(
- [[-3.9259027239257, 40.8792937308316],
- [-3.9249047078766, 40.8788966596619],
- [-3.9247799675785, 40.8789131852224]]
- )
+ expected = {
+ type: "FeatureCollection",
+ features: [{
+ type: "Feature",
+ geometry: {
+ type: "Polygon",
+ coordinates: [[
+ [-3.9259027239257, 40.8792937308316],
+ [-3.9249047078766, 40.8788966596619],
+ [-3.9247799675785, 40.8789131852224],
+ [-3.9259027239257, 40.8792937308316]
+ ]]
+ }
+ }]
+ }
+
+ expect(geozone.outline_points).to eq expected.to_json
end
- it "handles coordinates with three-dimensional arrays" do
- geozone = build(:geozone, geojson: '{
- "geometry": {
- "type": "Polygon",
- "coordinates": [[[40.8792937308316, -3.9259027239257],
- [40.8788966596619, -3.9249047078766],
- [40.8789131852224, -3.9247799675785]]]
+ it "returns normalized feature collection when geojson is a valid Feature" do
+ geozone.geojson = <<~JSON
+ {
+ "type": "Feature",
+ "geometry": {
+ "type": "Polygon",
+ "coordinates": [[
+ [-3.9259027239257, 40.8792937308316],
+ [-3.9249047078766, 40.8788966596619],
+ [-3.9247799675785, 40.8789131852224],
+ [-3.9259027239257, 40.8792937308316]
+ ]]
+ }
}
- }')
+ JSON
- expect(geozone.outline_points).to eq(
- [[-3.9259027239257, 40.8792937308316],
- [-3.9249047078766, 40.8788966596619],
- [-3.9247799675785, 40.8789131852224]]
- )
+ expected = {
+ type: "FeatureCollection",
+ features: [{
+ type: "Feature",
+ geometry: {
+ type: "Polygon",
+ coordinates: [[
+ [-3.9259027239257, 40.8792937308316],
+ [-3.9249047078766, 40.8788966596619],
+ [-3.9247799675785, 40.8789131852224],
+ [-3.9259027239257, 40.8792937308316]
+ ]]
+ }
+ }]
+ }
+
+ expect(geozone.outline_points).to eq expected.to_json
end
- it "handles coordinates with three-dimensional arrays with spaces between brackets" do
- geozone = build(:geozone, geojson: '{
- "geometry": {
+ it "returns normalized feature collection when geojson is a valid Geometry object" do
+ geozone.geojson = <<~JSON
+ {
+ "geometry": {
+ "type": "Polygon",
+ "coordinates": [[
+ [-3.9259027239257, 40.8792937308316],
+ [-3.9249047078766, 40.8788966596619],
+ [-3.9247799675785, 40.8789131852224],
+ [-3.9259027239257, 40.8792937308316]
+ ]]
+ }
+ }
+ JSON
+
+ expected = {
+ type: "FeatureCollection",
+ features: [{
+ type: "Feature",
+ geometry: {
+ type: "Polygon",
+ coordinates: [[
+ [-3.9259027239257, 40.8792937308316],
+ [-3.9249047078766, 40.8788966596619],
+ [-3.9247799675785, 40.8789131852224],
+ [-3.9259027239257, 40.8792937308316]
+ ]]
+ }
+ }]
+ }
+
+ expect(geozone.outline_points).to eq expected.to_json
+ end
+
+ it "returns normalized feature collection when geojson is a valid top-level Geometry object" do
+ geozone.geojson = <<~JSON
+ {
"type": "Polygon",
"coordinates": [[
- [40.8792937308316, -3.9259027239257],
- [40.8788966596619, -3.9249047078766],
- [40.8789131852224, -3.9247799675785]
+ [-3.9259027239257, 40.8792937308316],
+ [-3.9249047078766, 40.8788966596619],
+ [-3.9247799675785, 40.8789131852224],
+ [-3.9259027239257, 40.8792937308316]
]]
}
- }')
+ JSON
- expect(geozone.outline_points).to eq(
- [[-3.9259027239257, 40.8792937308316],
- [-3.9249047078766, 40.8788966596619],
- [-3.9247799675785, 40.8789131852224]]
- )
- end
+ expected = {
+ type: "FeatureCollection",
+ features: [{
+ type: "Feature",
+ geometry: {
+ type: "Polygon",
+ coordinates: [[
+ [-3.9259027239257, 40.8792937308316],
+ [-3.9249047078766, 40.8788966596619],
+ [-3.9247799675785, 40.8789131852224],
+ [-3.9259027239257, 40.8792937308316]
+ ]]
+ }
+ }]
+ }
- it "handles coordinates with four-dimensional arrays" do
- geozone = build(:geozone, geojson: '{
- "geometry": {
- "type": "Polygon",
- "coordinates": [[[[40.8792937308316, -3.9259027239257],
- [40.8788966596619, -3.9249047078766],
- [40.8789131852224, -3.9247799675785]]]]
- }
- }')
-
- expect(geozone.outline_points).to eq(
- [[-3.9259027239257, 40.8792937308316],
- [-3.9249047078766, 40.8788966596619],
- [-3.9247799675785, 40.8789131852224]]
- )
- end
-
- it "handles coordinates with four-dimensional arrays with spaces between brackets" do
- geozone = build(:geozone, geojson: '{
- "geometry": {
- "type": "Polygon",
- "coordinates": [[[
- [40.8792937308316, -3.9259027239257],
- [40.8788966596619, -3.9249047078766],
- [40.8789131852224, -3.9247799675785]
- ]]]
- }
- }')
-
- expect(geozone.outline_points).to eq(
- [[-3.9259027239257, 40.8792937308316],
- [-3.9249047078766, 40.8788966596619],
- [-3.9247799675785, 40.8789131852224]]
- )
+ expect(geozone.outline_points).to eq expected.to_json
end
end
end
diff --git a/spec/system/admin/geozones_spec.rb b/spec/system/admin/geozones_spec.rb
index 3ece9f6f4..2adec9b3e 100644
--- a/spec/system/admin/geozones_spec.rb
+++ b/spec/system/admin/geozones_spec.rb
@@ -110,8 +110,16 @@ describe "Admin geozones", :admin do
scenario "Show polygons when a heading is associated with a geozone" do
Setting["feature.map"] = true
+ geojson = <<~JSON
+ {
+ "type": "Feature",
+ "geometry": {
+ "type": "Polygon",
+ "coordinates": [[[-0.1, 51.5], [-0.2, 51.4], [-0.3, 51.6]]]
+ }
+ }
+ JSON
- geojson = '{ "geometry": { "type": "Polygon", "coordinates": [[-0.1,51.5],[-0.2,51.4],[-0.3,51.6]] } }'
geozone = create(:geozone, name: "Polygon me!")
budget = create(:budget)
group = create(:budget_group, budget: budget)
@@ -145,7 +153,16 @@ describe "Admin geozones", :admin do
scenario "Show polygons on geozone admin view" do
Setting["feature.map"] = true
- geojson = '{ "geometry": { "type": "Polygon", "coordinates": [[-0.1,51.5],[-0.2,51.4],[-0.3,51.6]] } }'
+ geojson = <<~JSON
+ {
+ "type": "Feature",
+ "geometry": {
+ "type": "Polygon",
+ "coordinates": [[[-0.1, 51.5], [-0.2, 51.4], [-0.3, 51.6]]]
+ }
+ }
+ JSON
+
geozone = create(:geozone, name: "Polygon me!", geojson: geojson)
visit admin_geozones_path
diff --git a/spec/system/budgets/investments_spec.rb b/spec/system/budgets/investments_spec.rb
index b18ff6e81..45930fe45 100644
--- a/spec/system/budgets/investments_spec.rb
+++ b/spec/system/budgets/investments_spec.rb
@@ -1658,18 +1658,20 @@ describe "Budget Investments" do
scenario "Shows the polygon associated to the current heading" do
triangle = <<~JSON
{
+ "type": "Feature",
"geometry": {
"type": "Polygon",
- "coordinates": [[-0.1,51.5],[-0.2,51.4],[-0.3,51.6]]
+ "coordinates": [[[-0.1, 51.5], [-0.2, 51.4], [-0.3, 51.6]]]
}
}
JSON
rectangle = <<~JSON
{
+ "type": "Feature",
"geometry": {
"type": "Polygon",
- "coordinates": [[-0.1,51.5],[-0.2,51.5],[-0.2,51.6],[-0.1,51.6]]
+ "coordinates": [[[-0.1, 51.5], [-0.2, 51.5], [-0.2, 51.6], [-0.1, 51.6]]]
}
}
JSON