require "minitest/autorun" require_relative "support/stubs" require_relative "../lib/geocode" # Tests for the pure helper methods in Geocode that do not require a DB # connection or network access. All DB/Http calls are stubbed out via # test/support/stubs.rb. class TestGeocodeCleanForGeocode < Minitest::Test def test_removes_ct_reference_with_colon input = "123 Main St (CT: 12345/678)" result = Geocode.clean_for_geocode(input) assert_equal "123 Main St", result end def test_removes_ct_reference_with_space input = "45 High St (CT 99/100)" result = Geocode.clean_for_geocode(input) assert_equal "45 High St", result end def test_collapses_whitespace result = Geocode.clean_for_geocode("12 George St") assert_equal "12 George St", result end def test_strips_leading_and_trailing_whitespace result = Geocode.clean_for_geocode(" 4 River Rd ") assert_equal "4 River Rd", result end def test_plain_address_unchanged result = Geocode.clean_for_geocode("7 Beach Rd, Hobart") assert_equal "7 Beach Rd, Hobart", result end def test_empty_string assert_equal "", Geocode.clean_for_geocode("") end end class TestGeocodeParseResult < Minitest::Test # Build a minimal Google Maps geocode result hash def result_fixture(components:, location: { "lat" => -42.8, "lng" => 147.3 }, location_type: "ROOFTOP", types: ["street_address"]) { "types" => types, "address_components" => components, "geometry" => { "location" => location, "location_type" => location_type } } end def test_full_address components = [ { "types" => ["street_number"], "long_name" => "42", "short_name" => "42" }, { "types" => ["route"], "long_name" => "Main Street", "short_name" => "Main St" }, { "types" => ["locality"], "long_name" => "Hobart", "short_name" => "Hobart" }, { "types" => ["administrative_area_level_1"], "long_name" => "Tasmania", "short_name" => "TAS" }, { "types" => ["postal_code"], "long_name" => "7000", "short_name" => "7000" } ] r = Geocode.parse_result(result_fixture(components: components)) assert_equal "42 Main Street, Hobart, TAS, 7000", r[:display] assert_equal "42 Main Street", r[:street] assert_equal "Hobart", r[:locality] assert_equal "TAS", r[:state] assert_equal "7000", r[:postcode] assert_in_delta(-42.8, r[:lat], 0.001) assert_in_delta(147.3, r[:lng], 0.001) end def test_missing_street_number components = [ { "types" => ["route"], "long_name" => "Collins Street", "short_name" => "Collins St" }, { "types" => ["locality"], "long_name" => "Launceston", "short_name" => "Launceston" }, { "types" => ["administrative_area_level_1"], "long_name" => "Tasmania", "short_name" => "TAS" }, { "types" => ["postal_code"], "long_name" => "7250", "short_name" => "7250" } ] r = Geocode.parse_result(result_fixture(components: components)) assert_equal "Collins Street", r[:street] assert_equal "Collins Street, Launceston, TAS, 7250", r[:display] end def test_postal_town_fallback_for_locality # When no "locality" component, fall back to "postal_town" components = [ { "types" => ["street_number"], "long_name" => "5", "short_name" => "5" }, { "types" => ["route"], "long_name" => "Hill Rd", "short_name" => "Hill Rd" }, { "types" => ["postal_town"], "long_name" => "Burnie", "short_name" => "Burnie" }, { "types" => ["administrative_area_level_1"], "long_name" => "Tasmania", "short_name" => "TAS" }, { "types" => ["postal_code"], "long_name" => "7320", "short_name" => "7320" } ] r = Geocode.parse_result(result_fixture(components: components)) assert_equal "Burnie", r[:locality] end def test_empty_components_returns_safe_defaults r = Geocode.parse_result(result_fixture(components: [])) assert_equal "", r[:street] assert_equal "", r[:locality] assert_equal "", r[:state] assert_equal "", r[:postcode] assert_equal "", r[:display] end end class TestGeocodePickBestResult < Minitest::Test def make_result(location_type:, types:, state: "TAS") { "types" => types, "address_components" => [ { "types" => ["administrative_area_level_1"], "short_name" => state } ], "geometry" => { "location_type" => location_type } } end def test_prefers_rooftop_over_approximate rooftop = make_result(location_type: "ROOFTOP", types: ["street_address"]) approx = make_result(location_type: "APPROXIMATE", types: ["locality"]) best = Geocode.pick_best_result([approx, rooftop]) assert_equal "ROOFTOP", best.dig("geometry", "location_type") end def test_prefers_tas_result_over_non_tas tas_result = make_result(location_type: "APPROXIMATE", types: ["street_address"], state: "TAS") vic_result = make_result(location_type: "ROOFTOP", types: ["street_address"], state: "VIC") best = Geocode.pick_best_result([vic_result, tas_result]) tas_state = best["address_components"].find { |c| c["types"].include?("administrative_area_level_1") }&.fetch("short_name") assert_equal "TAS", tas_state end def test_single_result_returned_as_is r = make_result(location_type: "ROOFTOP", types: ["street_address"]) assert_equal r, Geocode.pick_best_result([r]) end end