| final class SpotsTests: XCTestCase {
// MARK: - Borough detection
func testBorough_Manhattan() {
XCTAssertEqual(AddressHelper.borough(for: "123 W 23rd St, New York, NY 10011"), "Manhattan")
}
func testBorough_ManhattanCity() {
XCTAssertEqual(AddressHelper.borough(for: "350 5th Ave, New York City, NY 10118"), "Manhattan")
}
func testBorough_Brooklyn() {
XCTAssertEqual(AddressHelper.borough(for: "1 MetroTech Center, Brooklyn, NY 11201"), "Brooklyn")
}
func testBorough_Queens_Astoria() {
XCTAssertEqual(AddressHelper.borough(for: "31-00 47th Ave, Astoria, NY 11103"), "Queens")
}
func testBorough_Queens_LongIslandCity() {
XCTAssertEqual(AddressHelper.borough(for: "5-33 49th Ave, Long Island City, NY 11101"), "Queens")
}
func testBorough_Queens_Flushing() {
XCTAssertEqual(AddressHelper.borough(for: "136-20 Roosevelt Ave, Flushing, NY 11354"), "Queens")
}
func testBorough_Bronx() {
XCTAssertEqual(AddressHelper.borough(for: "2820 Jerome Ave, Bronx, NY 10468"), "Bronx")
}
func testBorough_TheBronx() {
XCTAssertEqual(AddressHelper.borough(for: "1 E 161st St, The Bronx, NY 10451"), "Bronx")
}
func testBorough_StatenIsland() {
XCTAssertEqual(AddressHelper.borough(for: "1000 Richmond Terrace, Staten Island, NY 10301"), "Staten Island")
}
func testBorough_NineDigitZip() {
// Regression: 9-digit zip (10025-2082) used to break the regex
XCTAssertEqual(AddressHelper.borough(for: "2880 Broadway, New York, NY 10025-2082"), "Manhattan")
}
func testBorough_StripsUnitedStates() {
// Apple Maps sometimes appends ", United States"
XCTAssertEqual(
AddressHelper.borough(for: "123 W 23rd St, New York, NY 10011, United States"),
"Manhattan"
)
}
func testBorough_StripsUSA() {
XCTAssertEqual(
AddressHelper.borough(for: "123 W 23rd St, New York, NY 10011, USA"),
"Manhattan"
)
}
func testBorough_EmptyAddress() {
XCTAssertEqual(AddressHelper.borough(for: ""), "Other")
}
func testBorough_NoMatch_ReturnsCity() {
// Non-NYC address should fall through to the city name
XCTAssertEqual(AddressHelper.borough(for: "1 Infinite Loop, Cupertino, CA 95014"), "Cupertino")
}
func testBorough_NoBoroughOrder_Deduplicated() {
XCTAssertEqual(AddressHelper.boroughOrder,
["Manhattan", "Brooklyn", "Queens", "Bronx", "Staten Island"])
}
// MARK: - Address migration
func testMigration_StripUnitedStates() {
let result = AddressHelper.migratedAddress("28 Bowery, New York, NY 10013, United States")
XCTAssertEqual(result, "28 Bowery, New York, NY 10013")
}
func testMigration_StripUSA() {
let result = AddressHelper.migratedAddress("28 Bowery, New York, NY 10013, USA")
XCTAssertEqual(result, "28 Bowery, New York, NY 10013")
}
func testMigration_ManhattanToNewYork() {
let result = AddressHelper.migratedAddress("510 W 110th St, Manhattan, NY 10025")
XCTAssertEqual(result, "510 W 110th St, New York, NY 10025")
}
func testMigration_ManhattanCaseInsensitive() {
let result = AddressHelper.migratedAddress("510 W 110th St, MANHATTAN, NY 10025")
XCTAssertEqual(result, "510 W 110th St, New York, NY 10025")
}
func testMigration_Idempotent() {
let addr = "28 Bowery, New York, NY 10013"
XCTAssertEqual(AddressHelper.migratedAddress(addr), addr)
}
func testMigration_BothTransformations() {
// Strip suffix AND fix Manhattan in the same address
let result = AddressHelper.migratedAddress("510 W 110th St, Manhattan, NY 10025, United States")
XCTAssertEqual(result, "510 W 110th St, New York, NY 10025")
}
func testMigration_EmptyAddress() {
XCTAssertEqual(AddressHelper.migratedAddress(""), "")
}
// MARK: - Search matching
func testSearch_EmptyQueryMatchesAll() {
let entry = makeEntry(name: "Babbo", cuisine: "Italian", neighborhood: "West Village")
XCTAssertTrue(AddressHelper.matches(entry: entry, query: ""))
}
func testSearch_MatchesName() {
let entry = makeEntry(name: "Le Bernardin")
XCTAssertTrue(AddressHelper.matches(entry: entry, query: "bernardin"))
}
func testSearch_MatchesCuisine() {
let entry = makeEntry(name: "Joe's", cuisine: "Pizza")
XCTAssertTrue(AddressHelper.matches(entry: entry, query: "pizza"))
}
func testSearch_MatchesNeighborhood() {
let entry = makeEntry(name: "Joe's", neighborhood: "Carroll Gardens")
XCTAssertTrue(AddressHelper.matches(entry: entry, query: "carroll"))
}
func testSearch_MatchesNotes() {
let entry = makeEntry(name: "Joe's", notes: "Great outdoor seating")
XCTAssertTrue(AddressHelper.matches(entry: entry, query: "outdoor"))
}
func testSearch_CaseInsensitive() {
let entry = makeEntry(name: "Carbone")
XCTAssertTrue(AddressHelper.matches(entry: entry, query: "CARBONE"))
}
func testSearch_NoMatch() {
let entry = makeEntry(name: "Babbo", cuisine: "Italian", neighborhood: "West Village")
XCTAssertFalse(AddressHelper.matches(entry: entry, query: "sushi"))
}
// MARK: - Entry sorting
func testSort_DefaultAlphabetical() {
let entries = [makeEntry(name: "Zuni"), makeEntry(name: "Babbo"), makeEntry(name: "Marea")]
let sorted = AddressHelper.sort(entries, by: .default)
XCTAssertEqual(sorted.map(\.playName), ["Babbo", "Marea", "Zuni"])
}
func testSort_ByCuisine() {
let entries = [
makeEntry(name: "A", cuisine: "Thai"),
makeEntry(name: "B", cuisine: "French"),
makeEntry(name: "C", cuisine: "Italian"),
]
let sorted = AddressHelper.sort(entries, by: .cuisine)
XCTAssertEqual(sorted.map(\.cuisine), ["French", "Italian", "Thai"])
}
func testSort_ByNeighborhood() {
let entries = [
makeEntry(name: "A", neighborhood: "West Village"),
makeEntry(name: "B", neighborhood: "Astoria"),
makeEntry(name: "C", neighborhood: "Tribeca"),
]
let sorted = AddressHelper.sort(entries, by: .neighborhood)
XCTAssertEqual(sorted.map(\.neighborhood), ["Astoria", "Tribeca", "West Village"])
}
func testSort_ByRatings_DescendingOrder() {
let entries = [
makeEntry(name: "A", starRating: 3),
makeEntry(name: "B", starRating: 5),
makeEntry(name: "C", starRating: 1),
]
let sorted = AddressHelper.sort(entries, by: .ratings)
XCTAssertEqual(sorted.map(\.starRating), [5, 3, 1])
}
func testSort_ByRatings_UnratedLast() {
let entries = [
makeEntry(name: "A", starRating: 0),
makeEntry(name: "B", starRating: 4),
makeEntry(name: "C", starRating: 0),
]
let sorted = AddressHelper.sort(entries, by: .ratings)
XCTAssertEqual(sorted.first?.starRating, 4)
XCTAssertEqual(sorted.last?.starRating, 0)
}
// MARK: - SpotEntry defaults
func testSpotEntry_DefaultStarRating() {
let entry = makeEntry(name: "Test")
XCTAssertEqual(entry.starRating, 0)
}
func testSpotEntry_DefaultBeenThere() {
let entry = makeEntry(name: "Test")
XCTAssertFalse(entry.beenThere)
}
func testSpotEntry_DefaultEntryMode() {
let entry = makeEntry(name: "Test")
XCTAssertEqual(entry.entryMode, .food)
}
func testSpotEntry_UniqueIDs() {
let a = makeEntry(name: "A")
let b = makeEntry(name: "B")
XCTAssertNotEqual(a.id, b.id)
}
// MARK: - Helpers
private func makeEntry(
name: String,
cuisine: String = "",
neighborhood: String = "",
notes: String = "",
starRating: Int = 0,
entryMode: EntryMode = .food
) -> SpotEntry {
SpotEntry(
playName: name,
dateTime: Date(),
cuisine: cuisine,
address: "",
phone: "",
website: "",
neighborhood: neighborhood,
hours: "",
confirmationLink: "",
remindersEnabled: false,
notes: notes,
rating: 0,
beenThere: false,
starRating: starRating,
hasCustomDate: false,
entryMode: entryMode
)
}
} | `SpotsTests` class | Defines the `SpotsTests` class. Conforms to XCTestCase. |