Settings About: data source section (connection, station count, GOV.UK update time)

- Relay envelope now carries source (api|csv), stations_count, and
  data_updated (freshest price_last_updated the GOV.UK server reports,
  independent of relay sync time).
- App decodes the new envelope metadata (RelayMeta), persists it after
  each full fetch, and shows it in Settings → About → Data source:
  Connection (API/CSV), Stations count, Data updated (local-formatted).
- Older relays without the fields decode cleanly (nil meta → em-dash).
- 2 new tests for meta decode + absent-meta tolerance; 37/37 pass.
This commit is contained in:
FuelBoard Contributor
2026-08-12 16:23:41 +01:00
parent a5a95cbb03
commit fccd0c07ef
5 changed files with 162 additions and 1 deletions
@@ -62,6 +62,27 @@ final class PriceGuardTests: XCTestCase {
XCTAssertEqual(stations[0].prices[.diesel], 142.9)
}
func testRelayMetaDecoded() throws {
let json = """
{"source":"api","stations_count":8010,"data_updated":"2026-08-12T10:23:00.000Z","stations":[{"id":"s1","name":"SHELL LEEDS","brand":"Shell","address":"A1","postcode":"LS1 1AA","lat":53.8,"lng":-1.5,"prices":{"E10":137.9}}]}
"""
let meta = FuelPriceProvider.decodeRelayMeta(from: Data(json.utf8))
XCTAssertEqual(meta?.source, "api")
XCTAssertEqual(meta?.stationCount, 8010)
XCTAssertEqual(meta?.dataUpdated, "2026-08-12T10:23:00.000Z")
}
func testRelayMetaAbsentIsNil() throws {
// Older relay without envelope metadata must not fail decode nil meta.
let json = """
{"stations":[{"id":"s1","name":"SHELL LEEDS","brand":"Shell","address":"A1","postcode":"LS1 1AA","lat":53.8,"lng":-1.5,"prices":{"E10":137.9}}]}
"""
let meta = FuelPriceProvider.decodeRelayMeta(from: Data(json.utf8))
XCTAssertNil(meta?.source)
XCTAssertNil(meta?.stationCount)
XCTAssertNil(meta?.dataUpdated)
}
func testOutOfBandPricesDropped() throws {
let json = """
{"stations":[{"id":"s1","name":"GARBAGE","brand":"X","address":"A","postcode":"L","lat":0,"lng":0,"prices":{"E10":1.3,"E5":1589.0,"DIESEL":137.9}}]}