Add GeoSpatial backends for geocoding

Signed-off-by: Thomas Citharel <tcit@tcit.fr>

Geospatial Backend

Signed-off-by: Thomas Citharel <tcit@tcit.fr>
This commit is contained in:
Thomas Citharel
2019-03-12 11:52:28 +01:00
parent f7284740e3
commit 98b7618338
29 changed files with 1301 additions and 1 deletions

View File

@@ -0,0 +1,59 @@
defmodule Mobilizon.Service.Geospatial.AddokTest do
use Mobilizon.DataCase, async: false
alias Mobilizon.Service.Geospatial.Addok
alias Mobilizon.Addresses.Address
import Mock
use ExVCR.Mock, adapter: ExVCR.Adapter.Hackney
@endpoint Application.get_env(:mobilizon, Mobilizon.Service.Geospatial.Addok)
|> get_in([:endpoint])
@fake_endpoint "https://domain.tld"
describe "search address" do
test "produces a valid search address" do
with_mock HTTPoison, get: fn _url -> "{}" end do
Addok.search("10 Rue Jangot")
assert_called(HTTPoison.get("#{@endpoint}/search/?q=10%20Rue%20Jangot&limit=10"))
end
end
test "produces a valid search address with options" do
with_mock HTTPoison, get: fn _url -> "{}" end do
Addok.search("10 Rue Jangot",
endpoint: @fake_endpoint,
limit: 5,
coords: %{lat: 49, lon: 12}
)
assert_called(
HTTPoison.get("#{@fake_endpoint}/search/?q=10%20Rue%20Jangot&limit=5&lat=49&lon=12")
)
end
end
test "returns a valid address from search" do
use_cassette "geospatial/addok/search" do
assert %Address{
addressLocality: "Lyon",
description: "10 Rue Jangot",
postalCode: "69007",
streetAddress: "10 Rue Jangot",
geom: %Geo.Point{coordinates: {4.842569, 45.751718}, properties: %{}, srid: 4326}
} == Addok.search("10 rue Jangot") |> hd
end
end
test "returns a valid address from reverse geocode" do
use_cassette "geospatial/addok/geocode" do
assert %Address{
addressLocality: "Lyon",
description: "10 Rue Jangot",
postalCode: "69007",
streetAddress: "10 Rue Jangot",
geom: %Geo.Point{coordinates: {4.842569, 45.751718}, properties: %{}, srid: 4326}
} == Addok.geocode(4.842569, 45.751718) |> hd
end
end
end
end

View File

@@ -0,0 +1,8 @@
defmodule Mobilizon.Service.GeospatialTest do
use Mobilizon.DataCase
alias Mobilizon.Service.Geospatial
describe "get service" do
assert Geospatial.service() === Elixir.Mobilizon.Service.Geospatial.Mock
end
end

View File

@@ -0,0 +1,80 @@
defmodule Mobilizon.Service.Geospatial.GoogleMapsTest do
use Mobilizon.DataCase, async: false
alias Mobilizon.Service.Geospatial.GoogleMaps
alias Mobilizon.Addresses.Address
import Mock
use ExVCR.Mock, adapter: ExVCR.Adapter.Hackney
describe "search address" do
test "without API Key triggers an error" do
assert_raise ArgumentError, "API Key required to use Google Maps", fn ->
GoogleMaps.search("10 Rue Jangot")
end
end
test "produces a valid search address with options" do
with_mock HTTPoison,
get: fn _url ->
{:ok,
%HTTPoison.Response{status_code: 200, body: "{\"status\": \"OK\", \"results\": []}"}}
end do
GoogleMaps.search("10 Rue Jangot",
limit: 5,
lang: "fr",
api_key: "toto"
)
assert_called(
HTTPoison.get(
"https://maps.googleapis.com/maps/api/geocode/json?limit=5&key=toto&language=fr&address=10%20Rue%20Jangot"
)
)
end
end
test "triggers an error with an invalid API Key" do
assert_raise ArgumentError, "The provided API key is invalid.", fn ->
GoogleMaps.search("10 rue Jangot", api_key: "secret_key")
end
end
test "returns a valid address from search" do
use_cassette "geospatial/google_maps/search" do
assert %Address{
addressLocality: "Lyon",
description: "10 Rue Jangot, 69007 Lyon, France",
addressRegion: "Auvergne-Rhône-Alpes",
addressCountry: "France",
postalCode: "69007",
streetAddress: "10 Rue Jangot",
geom: %Geo.Point{
coordinates: {4.8424032, 45.75164940000001},
properties: %{},
srid: 4326
}
} == GoogleMaps.search("10 rue Jangot", api_key: "toto") |> hd
end
end
test "returns a valid address from reverse geocode" do
use_cassette "geospatial/google_maps/geocode" do
assert %Address{
addressLocality: "Lyon",
description: "10 Rue Jangot, 69007 Lyon, France",
addressRegion: "Auvergne-Rhône-Alpes",
addressCountry: "France",
postalCode: "69007",
streetAddress: "10 Rue Jangot",
geom: %Geo.Point{
coordinates: {4.8424967, 45.751725},
properties: %{},
srid: 4326
}
} ==
GoogleMaps.geocode(4.842569, 45.751718, api_key: "toto")
|> hd
end
end
end
end

View File

@@ -0,0 +1,85 @@
defmodule Mobilizon.Service.Geospatial.MapQuestTest do
use Mobilizon.DataCase, async: false
alias Mobilizon.Service.Geospatial.MapQuest
alias Mobilizon.Addresses.Address
import Mock
use ExVCR.Mock, adapter: ExVCR.Adapter.Hackney
describe "search address" do
test "without API Key triggers an error" do
assert_raise ArgumentError, "API Key required to use MapQuest", fn ->
MapQuest.search("10 Rue Jangot")
end
end
test "produces a valid search address with options" do
with_mock HTTPoison,
get: fn _url ->
{:ok,
%HTTPoison.Response{
status_code: 200,
body: "{\"info\": {\"statuscode\": 0}, \"results\": []}"
}}
end do
MapQuest.search("10 Rue Jangot",
limit: 5,
lang: "fr",
api_key: "toto"
)
assert_called(
HTTPoison.get(
"https://open.mapquestapi.com/geocoding/v1/address?key=toto&location=10%20Rue%20Jangot&maxResults=5"
)
)
end
end
test "triggers an error with an invalid API Key" do
assert_raise ArgumentError, "The AppKey submitted with this request is invalid.", fn ->
MapQuest.search("10 rue Jangot", api_key: "secret_key")
end
end
test "returns a valid address from search" do
use_cassette "geospatial/map_quest/search" do
assert %Address{
addressLocality: "Lyon",
description: "10 Rue Jangot",
addressRegion: "Auvergne-Rhône-Alpes",
addressCountry: "FR",
postalCode: "69007",
streetAddress: "10 Rue Jangot",
geom: %Geo.Point{
coordinates: {4.842566, 45.751714},
properties: %{},
srid: 4326
}
} ==
MapQuest.search("10 rue Jangot", api_key: "secret_key")
|> hd
end
end
test "returns a valid address from reverse geocode" do
use_cassette "geospatial/map_quest/geocode" do
assert %Address{
addressLocality: "Lyon",
description: "10 Rue Jangot",
addressRegion: "Auvergne-Rhône-Alpes",
addressCountry: "FR",
postalCode: "69007",
streetAddress: "10 Rue Jangot",
geom: %Geo.Point{
coordinates: {4.842569, 45.751718},
properties: %{},
srid: 4326
}
} ==
MapQuest.geocode(4.842569, 45.751718, api_key: "secret_key")
|> hd
end
end
end
end

View File

@@ -0,0 +1,68 @@
defmodule Mobilizon.Service.Geospatial.NominatimTest do
use Mobilizon.DataCase, async: false
alias Mobilizon.Service.Geospatial.Nominatim
alias Mobilizon.Addresses.Address
import Mock
use ExVCR.Mock, adapter: ExVCR.Adapter.Hackney
describe "search address" do
test "produces a valid search address with options" do
with_mock HTTPoison,
get: fn _url ->
{:ok, %HTTPoison.Response{status_code: 200, body: "[]"}}
end do
Nominatim.search("10 Rue Jangot",
limit: 5,
lang: "fr"
)
assert_called(
HTTPoison.get(
"https://nominatim.openstreetmap.org/search?format=jsonv2&q=10%20Rue%20Jangot&limit=5&accept-language=fr&addressdetails=1"
)
)
end
end
test "returns a valid address from search" do
use_cassette "geospatial/nominatim/search" do
assert %Address{
addressLocality: "Lyon",
description:
"10, Rue Jangot, La Guillotière, Lyon 7e Arrondissement, Lyon, Métropole de Lyon, Departemental constituency of Rhône, Auvergne-Rhône-Alpes, Metropolitan France, 69007, France",
addressRegion: "Auvergne-Rhône-Alpes",
addressCountry: "France",
postalCode: "69007",
streetAddress: "10 Rue Jangot",
geom: %Geo.Point{
coordinates: {4.8425657, 45.7517141},
properties: %{},
srid: 4326
}
} == Nominatim.search("10 rue Jangot") |> hd
end
end
test "returns a valid address from reverse geocode" do
use_cassette "geospatial/nominatim/geocode" do
assert %Address{
addressLocality: "Lyon",
description:
"10, Rue Jangot, La Guillotière, Lyon 7e Arrondissement, Lyon, Métropole de Lyon, Circonscription départementale du Rhône, Auvergne-Rhône-Alpes, France métropolitaine, 69007, France",
addressRegion: "Auvergne-Rhône-Alpes",
addressCountry: "France",
postalCode: "69007",
streetAddress: "10 Rue Jangot",
geom: %Geo.Point{
coordinates: {4.8425657, 45.7517141},
properties: %{},
srid: 4326
}
} ==
Nominatim.geocode(4.842569, 45.751718)
|> hd
end
end
end
end

View File

@@ -0,0 +1,65 @@
defmodule Mobilizon.Service.Geospatial.PhotonTest do
use Mobilizon.DataCase, async: false
alias Mobilizon.Service.Geospatial.Photon
alias Mobilizon.Addresses.Address
import Mock
use ExVCR.Mock, adapter: ExVCR.Adapter.Hackney
describe "search address" do
test "produces a valid search address with options" do
with_mock HTTPoison,
get: fn _url ->
{:ok, %HTTPoison.Response{status_code: 200, body: "{\"features\": []"}}
end do
Photon.search("10 Rue Jangot",
limit: 5,
lang: "fr"
)
assert_called(
HTTPoison.get("https://photon.komoot.de/api/?q=10%20Rue%20Jangot&lang=fr&limit=5")
)
end
end
test "returns a valid address from search" do
use_cassette "geospatial/photon/search" do
assert %Address{
addressLocality: "Lyon",
description: "10 Rue Jangot",
addressRegion: "Auvergne-Rhône-Alpes",
addressCountry: "France",
postalCode: "69007",
streetAddress: "10 Rue Jangot",
geom: %Geo.Point{
coordinates: {4.8425657, 45.7517141},
properties: %{},
srid: 4326
}
} == Photon.search("10 rue Jangot") |> hd
end
end
# Photon returns something quite wrong, so no need to test this right now.
# test "returns a valid address from reverse geocode" do
# use_cassette "geospatial/photon/geocode" do
# assert %Address{
# addressLocality: "Lyon",
# description: "",
# addressRegion: "Auvergne-Rhône-Alpes",
# addressCountry: "France",
# postalCode: "69007",
# streetAddress: "10 Rue Jangot",
# geom: %Geo.Point{
# coordinates: {4.8425657, 45.7517141},
# properties: %{},
# srid: 4326
# }
# } ==
# Photon.geocode(4.8425657, 45.7517141)
# |> hd
# end
# end
end
end