Files
maptool/test/test_hiking_trails.rb
T
randy c6e4a455b6
CI / check (push) Successful in 21s
CI / deploy (push) Successful in 11s
Split offline hiking trails per country, add a picker instead of one big file
data/hiking_trails.geojson is now data/hiking_trails/<CODE>.geojson —
one file per country instead of a merge, generated per-source
(PmtilesBuilder.extract_hiking_trails), cached the same way
geofabrik_cache is (skipped once a country's own extract is already
newer than its source .osm.pbf, so growing the selection by one
country only re-extracts that one). GET /api/hiking-trails now lists
available country codes instead of a single file's status.

The Overlays panel's "Hiking trails" item becomes an expandable
per-country checklist once any offline extract exists (same shape as
Radar's own expand), replacing the plain on/off checkbox — nobody
covering a dozen countries' worth of offline map data needs all of
their hiking trails loaded and parsed at once, so each ticked country
fetches its own GeoJSON independently instead.

HikingTrails.extract_merged (server-side multi-country merge, no
longer needed now that the client picks per country) removed again.
Verified the new extract_hiking_trails + caching skip live on brick
against a real cached country PBF.
2026-09-13 11:17:05 +02:00

126 lines
4.4 KiB
Ruby

require_relative "test_helper"
require "maptool/hiking_trails"
# No real osmium calls — extract() is a thin subprocess-plus-parse wrapper
# (same "not independently tested" reasoning OverpassPois.fetch gets), but
# parse_opl is pure text in, GeoJSON out, and that's the part actually worth
# protecting: the OPL escaping rules and the way-id -> relation-member
# stitching are easy to get subtly wrong and osmium isn't installed in every
# environment this test suite runs in.
class HikingTrailsTest < Minitest::Test
def test_parse_opl_builds_a_multilinestring_from_member_way_geometry
opl = <<~OPL
w1 Thighway=path Nn10x20.087y49.179,n11x20.088y49.18
w2 Thighway=path Nn11x20.088y49.18,n12x20.089y49.181
r1 Troute=hiking,type=route,name=Rysy Mw1@,w2@
OPL
features = Maptool::HikingTrails.parse_opl(opl)["features"]
assert_equal 1, features.size
feature = features.first
assert_equal "MultiLineString", feature["geometry"]["type"]
assert_equal [[[20.087, 49.179], [20.088, 49.18]], [[20.088, 49.18], [20.089, 49.181]]], feature["geometry"]["coordinates"]
assert_equal "Rysy", feature["properties"]["name"]
end
def test_parse_opl_skips_relations_that_are_not_route_hiking
opl = <<~OPL
w1 Thighway=path Nn10x20.087y49.179,n11x20.088y49.18
r1 Ttype=multipolygon Mw1@outer
OPL
assert_empty Maptool::HikingTrails.parse_opl(opl)["features"]
end
def test_parse_opl_falls_back_to_description_when_there_is_no_name
opl = <<~OPL
w1 Thighway=path Nn10x20.087y49.179,n11x20.088y49.18
r1 Troute=hiking,type=route,description=Rázc.%20%pri%20%Žabom%20%potoku%20%-%20%Rysy Mw1@
OPL
feature = Maptool::HikingTrails.parse_opl(opl)["features"].first
assert_equal "Rázc. pri Žabom potoku - Rysy", feature["properties"]["name"]
end
def test_parse_opl_unescapes_commas_and_equals_in_tag_values
opl = <<~OPL
w1 Thighway=path Nn10x20.087y49.179,n11x20.088y49.18
r1 Troute=hiking,type=route,name=Salt%2c%%20%Pepper%3d%Co Mw1@
OPL
feature = Maptool::HikingTrails.parse_opl(opl)["features"].first
assert_equal "Salt, Pepper=Co", feature["properties"]["name"]
end
def test_parse_opl_carries_over_colour_network_operator_ref
opl = <<~OPL
w1 Thighway=path Nn10x20.087y49.179,n11x20.088y49.18
r1 Troute=hiking,type=route,name=Trail,colour=red,network=rwn,operator=KST,ref=0933 Mw1@
OPL
properties = Maptool::HikingTrails.parse_opl(opl)["features"].first["properties"]
assert_equal "red", properties["colour"]
assert_equal "rwn", properties["network"]
assert_equal "KST", properties["operator"]
assert_equal "0933", properties["ref"]
end
def test_parse_opl_computes_distance_from_member_way_geometry
# Roughly 111.2m per 0.001 degree of latitude at the equator.
opl = <<~OPL
w1 Thighway=path Nn10x0.0y0.0,n11x0.0y0.001
r1 Troute=hiking,type=route,name=Trail Mw1@
OPL
distance = Maptool::HikingTrails.parse_opl(opl)["features"].first["properties"]["distance_meters"]
assert_in_delta 111.2, distance, 1.0
end
def test_parse_opl_drops_a_relation_whose_member_ways_are_all_missing
opl = <<~OPL
r1 Troute=hiking,type=route,name=Ghost Mw999@
OPL
assert_empty Maptool::HikingTrails.parse_opl(opl)["features"]
end
def test_parse_opl_carries_the_osm_relation_id_for_cross_country_dedup
opl = <<~OPL
w1 Thighway=path Nn10x20.087y49.179,n11x20.088y49.18
r1246205 Troute=hiking,type=route,name=Trail Mw1@
OPL
feature = Maptool::HikingTrails.parse_opl(opl)["features"].first
assert_equal 1246205, feature["properties"]["id"]
end
def test_parse_opl_rounds_coordinates_to_5_decimal_places
opl = <<~OPL
w1 Thighway=path Nn10x20.0876543210y49.1791234567,n11x20.0880000001y49.1800000009
r1 Troute=hiking,type=route,name=Trail Mw1@
OPL
coords = Maptool::HikingTrails.parse_opl(opl)["features"].first["geometry"]["coordinates"]
assert_equal [[[20.08765, 49.17912], [20.088, 49.18]]], coords
end
def test_parse_opl_ignores_a_dangling_member_reference_but_keeps_the_rest
opl = <<~OPL
w1 Thighway=path Nn10x20.087y49.179,n11x20.088y49.18
r1 Troute=hiking,type=route,name=Trail Mw1@,w999@
OPL
features = Maptool::HikingTrails.parse_opl(opl)["features"]
assert_equal 1, features.size
assert_equal 1, features.first["geometry"]["coordinates"].size
end
end