Files
maptool/test/test_overpass_pois.rb
randy ea9cd5fc40 Fix three bugs found reviewing this session's changes
- notes.js's ICON_LABELS wasn't extended for the shop_supermarket/
  shop_convenience keys icons.js added — the note icon picker showed
  the raw internal key as the title instead of a real label.
- Plugins.run mislabeled a malformed plugin.json as "plugin did not
  print valid JSON" — a message written for bad script stdout, not a
  bad manifest, since both paths shared one rescue.
- overpass_pois.rb's description_for joined raw OSM tag values with
  "\n" — an operator/opening_hours tag with an embedded newline could
  inject an extra line into the popup that gpx.js's formatDescription
  (built for p4n2gpx's own well-formed lines) would render as its own
  independent, legitimate-looking link. Tag values are stripped of
  embedded newlines before joining.
2026-09-09 18:21:47 +02:00

124 lines
4.9 KiB
Ruby

require_relative "test_helper"
require "maptool/overpass_pois"
# No real network calls — to_geojson is pure (canned Overpass response ->
# GeoJSON), and that's the part worth protecting from regressions. fetch()
# itself is a thin Net::HTTP.post_form + JSON.parse wrapper, same as
# LiveTrackClient's own fetch_html, not independently tested for the same
# reason that one isn't.
class OverpassPoisTest < Minitest::Test
def test_to_geojson_converts_matching_node_elements
response = {
"elements" => [
{ "type" => "node", "lat" => 48.1, "lon" => 17.2, "tags" => { "amenity" => "drinking_water" } },
{ "type" => "node", "lat" => 48.3, "lon" => 17.4, "tags" => { "amenity" => "toilets", "name" => "Rest area" } },
],
}
geojson = Maptool::OverpassPois.to_geojson(response)
assert_equal "FeatureCollection", geojson["type"]
assert_equal 2, geojson["features"].size
water = geojson["features"].find { |f| f["properties"]["category"] == "Drinking water" }
assert_equal [17.2, 48.1], water["geometry"]["coordinates"]
assert_equal "Drinking water", water["properties"]["name"], "falls back to the category when the node has no name tag"
assert_equal "amenity_drinking_water", water["properties"]["icon"]
assert_equal "#2e86de", water["properties"]["color"]
end
def test_to_geojson_assigns_icons_to_shop_categories
response = {
"elements" => [
{ "type" => "node", "lat" => 1, "lon" => 1, "tags" => { "shop" => "supermarket" } },
{ "type" => "node", "lat" => 2, "lon" => 2, "tags" => { "shop" => "convenience" } },
],
}
icons = Maptool::OverpassPois.to_geojson(response)["features"].map { |f| f["properties"]["icon"] }
assert_equal %w[shop_supermarket shop_convenience], icons
end
def test_to_geojson_builds_a_description_from_recognized_tags
response = {
"elements" => [
{
"type" => "node",
"lat" => 48.1,
"lon" => 17.2,
"tags" => { "amenity" => "toilets", "opening_hours" => "24/7", "operator" => "Town Council", "website" => "https://example.com" },
},
],
}
description = Maptool::OverpassPois.to_geojson(response)["features"].first["properties"]["description"]
assert_equal "Opening hours: 24/7\nOperator: Town Council\nhttps://example.com", description
end
def test_to_geojson_strips_embedded_newlines_from_tag_values
response = {
"elements" => [
{
"type" => "node",
"lat" => 48.1,
"lon" => 17.2,
"tags" => { "amenity" => "toilets", "operator" => "Acme Co\nhttps://evil.example" },
},
],
}
description = Maptool::OverpassPois.to_geojson(response)["features"].first["properties"]["description"]
assert_equal "Operator: Acme Co https://evil.example", description, "an embedded newline must not inject a second, independently-rendered line"
end
def test_to_geojson_omits_description_when_no_recognized_tags_are_present
response = { "elements" => [{ "type" => "node", "lat" => 48.1, "lon" => 17.2, "tags" => { "amenity" => "toilets" } }] }
refute Maptool::OverpassPois.to_geojson(response)["features"].first["properties"].key?("description")
end
def test_to_geojson_uses_the_node_name_when_present
response = { "elements" => [{ "type" => "node", "lat" => 48.3, "lon" => 17.4, "tags" => { "amenity" => "toilets", "name" => "Rest area" } }] }
feature = Maptool::OverpassPois.to_geojson(response)["features"].first
assert_equal "Rest area", feature["properties"]["name"]
end
def test_to_geojson_skips_ways_and_relations
response = { "elements" => [{ "type" => "way", "tags" => { "amenity" => "drinking_water" } }] }
assert_empty Maptool::OverpassPois.to_geojson(response)["features"]
end
def test_to_geojson_skips_nodes_matching_no_known_category
response = { "elements" => [{ "type" => "node", "lat" => 48.1, "lon" => 17.2, "tags" => { "amenity" => "restaurant" } }] }
assert_empty Maptool::OverpassPois.to_geojson(response)["features"]
end
def test_lpg_matches_either_fuel_stations_with_the_lpg_tag_or_gas_bottle_shops
response = {
"elements" => [
{ "type" => "node", "lat" => 1, "lon" => 1, "tags" => { "amenity" => "fuel", "fuel:lpg" => "yes" } },
{ "type" => "node", "lat" => 2, "lon" => 2, "tags" => { "shop" => "gas" } },
{ "type" => "node", "lat" => 3, "lon" => 3, "tags" => { "amenity" => "fuel" } }, # no lpg tag - not a match
],
}
categories = Maptool::OverpassPois.to_geojson(response)["features"].map { |f| f["properties"]["category"] }
assert_equal ["LPG refill", "LPG refill"], categories
end
def test_build_query_includes_the_bbox_and_every_category_filter
query = Maptool::OverpassPois.build_query([48.0, 17.0, 49.0, 18.0])
assert_includes query, "48.0,17.0,49.0,18.0"
assert_includes query, %(["amenity"="drinking_water"])
assert_includes query, %(["natural"="spring"])
end
end