fix: region map tap selecting wrong region due to accessibility button overlay

Accessibility buttons split the map into equal-width thirds, intercepting
taps before the coordinate-based logic. Tapping the visual West region
could hit the Central button. Adding .allowsHitTesting(false) lets taps
pass through to MapReader's coordinate detection; VoiceOver still works.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Trey t
2026-02-13 09:12:00 -06:00
parent 9736773475
commit 67965cbac6
2 changed files with 121 additions and 2 deletions

View File

@@ -56,13 +56,15 @@ struct RegionMapSelector: View {
.mapStyle(.standard(elevation: .flat, pointsOfInterest: .excludingAll))
.onTapGesture { location in
if let coordinate = proxy.convert(location, from: .local) {
let tappedRegion = regionForCoordinate(coordinate)
let tappedRegion = Self.regionForCoordinate(coordinate)
onToggle(tappedRegion)
}
}
}
// Invisible button overlays for UI testing accessibility
// allowsHitTesting(false) lets taps pass through to the map's
// coordinate-based region detection; VoiceOver still reads these.
HStack(spacing: 0) {
Button { onToggle(.west) } label: { Color.clear }
.accessibilityIdentifier("wizard.regions.west")
@@ -98,6 +100,7 @@ struct RegionMapSelector: View {
.accessibilityAddTraits(selectedRegions.contains(.east) ? .isSelected : [])
.frame(maxWidth: .infinity)
}
.allowsHitTesting(false)
}
.frame(height: 160)
.clipShape(RoundedRectangle(cornerRadius: Theme.CornerRadius.medium))
@@ -128,7 +131,9 @@ struct RegionMapSelector: View {
/// West: States west of ~-102° (WA, OR, CA, NV, ID, UT, AZ, MT, WY, CO, NM)
/// Central: States between ~-102° and ~-89° (ND, SD, NE, KS, OK, TX, MN, IA, MO, AR, LA, WI, IL)
/// East: States east of ~-89°
private func regionForCoordinate(_ coordinate: CLLocationCoordinate2D) -> Region {
/// Maps a tap coordinate to a region based on the visual polygon boundaries.
/// Thresholds match the drawn polygon edges (not Region.classify which uses stadium locations).
static func regionForCoordinate(_ coordinate: CLLocationCoordinate2D) -> Region {
let longitude = coordinate.longitude
if longitude < -102 {
return .west

View File

@@ -0,0 +1,114 @@
//
// RegionMapSelectorTests.swift
// SportsTimeTests
//
// Regression tests for map tap region coordinate detection.
// Bug: invisible accessibility buttons intercepted taps before the
// coordinate-based logic, causing offset selection (tapping West
// selected Central). Fix: .allowsHitTesting(false) on button overlay.
//
import CoreLocation
import Testing
@testable import SportsTime
@Suite("RegionMapSelector — regionForCoordinate")
struct RegionMapSelectorTests {
// MARK: - West Region (longitude < -102)
@Test("West: Los Angeles (-118.24)")
func west_losAngeles() {
let coord = CLLocationCoordinate2D(latitude: 34.05, longitude: -118.24)
#expect(RegionMapSelector.regionForCoordinate(coord) == .west)
}
@Test("West: Seattle (-122.33)")
func west_seattle() {
let coord = CLLocationCoordinate2D(latitude: 47.61, longitude: -122.33)
#expect(RegionMapSelector.regionForCoordinate(coord) == .west)
}
@Test("West: Phoenix (-112.07)")
func west_phoenix() {
let coord = CLLocationCoordinate2D(latitude: 33.45, longitude: -112.07)
#expect(RegionMapSelector.regionForCoordinate(coord) == .west)
}
@Test("West: just inside boundary (-102.01)")
func west_boundary() {
let coord = CLLocationCoordinate2D(latitude: 39.0, longitude: -102.01)
#expect(RegionMapSelector.regionForCoordinate(coord) == .west)
}
// MARK: - Central Region (-102 to -89)
@Test("Central: Kansas City (-94.58)")
func central_kansasCity() {
let coord = CLLocationCoordinate2D(latitude: 39.10, longitude: -94.58)
#expect(RegionMapSelector.regionForCoordinate(coord) == .central)
}
@Test("Central: Dallas (-96.80)")
func central_dallas() {
let coord = CLLocationCoordinate2D(latitude: 32.78, longitude: -96.80)
#expect(RegionMapSelector.regionForCoordinate(coord) == .central)
}
@Test("Central: Chicago (-87.62)")
func central_chicago() {
let coord = CLLocationCoordinate2D(latitude: 41.88, longitude: -89.0)
#expect(RegionMapSelector.regionForCoordinate(coord) == .central)
}
@Test("Central: exactly at west boundary (-102)")
func central_westBoundary() {
let coord = CLLocationCoordinate2D(latitude: 39.0, longitude: -102.0)
#expect(RegionMapSelector.regionForCoordinate(coord) == .central)
}
@Test("Central: exactly at east boundary (-89)")
func central_eastBoundary() {
let coord = CLLocationCoordinate2D(latitude: 39.0, longitude: -89.0)
#expect(RegionMapSelector.regionForCoordinate(coord) == .central)
}
// MARK: - East Region (longitude > -89)
@Test("East: New York (-73.99)")
func east_newYork() {
let coord = CLLocationCoordinate2D(latitude: 40.71, longitude: -73.99)
#expect(RegionMapSelector.regionForCoordinate(coord) == .east)
}
@Test("East: Miami (-80.19)")
func east_miami() {
let coord = CLLocationCoordinate2D(latitude: 25.76, longitude: -80.19)
#expect(RegionMapSelector.regionForCoordinate(coord) == .east)
}
@Test("East: Atlanta (-84.39)")
func east_atlanta() {
let coord = CLLocationCoordinate2D(latitude: 33.75, longitude: -84.39)
#expect(RegionMapSelector.regionForCoordinate(coord) == .east)
}
@Test("East: just outside boundary (-88.99)")
func east_boundary() {
let coord = CLLocationCoordinate2D(latitude: 39.0, longitude: -88.99)
#expect(RegionMapSelector.regionForCoordinate(coord) == .east)
}
// MARK: - Regression: original bug scenario
@Test("Regression: tapping visual West region should not select Central")
func regression_westTapNotCentral() {
// User reported tapping the West overlay (around -108 longitude)
// was selecting Central due to accessibility button overlay intercepting.
// With .allowsHitTesting(false), the coordinate logic is now used.
let westernTap = CLLocationCoordinate2D(latitude: 40.0, longitude: -108.0)
let result = RegionMapSelector.regionForCoordinate(westernTap)
#expect(result == .west, "Tapping at -108° longitude must select West, not Central")
#expect(result != .central)
}
}