From 0a7301a01ae1f26dff7702ffd730623533c490b9 Mon Sep 17 00:00:00 2001 From: Lukas Foldyna Date: Tue, 3 Mar 2026 08:26:10 +0100 Subject: [PATCH 1/2] test: cover MQTT location timestamp decode paths --- .../VehicleMQTTLocationResponseTests.swift | 70 +++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 KiaTests/VehicleMQTTLocationResponseTests.swift diff --git a/KiaTests/VehicleMQTTLocationResponseTests.swift b/KiaTests/VehicleMQTTLocationResponseTests.swift new file mode 100644 index 0000000..e2077da --- /dev/null +++ b/KiaTests/VehicleMQTTLocationResponseTests.swift @@ -0,0 +1,70 @@ +// +// VehicleMQTTLocationResponseTests.swift +// KiaTests +// +// Created by Codex on 03/03/26. +// + +import XCTest +@testable import KiaMaps + +final class VehicleMQTTLocationResponseTests: XCTestCase { + + func testDecode_ValidMergedTimestampWithNullLocation() throws { + let data = Data( + """ + { + "latestUpdateTime": "20250901142733", + "state": { + "Vehicle": { + "Location": null + } + } + } + """.utf8 + ) + + let response = try JSONDecoder().decode(VehicleMQTTLocationResponse.self, from: data) + XCTAssertNil(response.state.vehicle.location) + + var utc = Calendar(identifier: .gregorian) + utc.timeZone = TimeZone(secondsFromGMT: 0)! + let components = utc.dateComponents( + [.year, .month, .day, .hour, .minute, .second], + from: response.lastUpdateTime + ) + + XCTAssertEqual(components.year, 2025) + XCTAssertEqual(components.month, 9) + XCTAssertEqual(components.day, 1) + XCTAssertEqual(components.hour, 14) + XCTAssertEqual(components.minute, 27) + XCTAssertEqual(components.second, 33) + } + + func testDecode_InvalidMergedTimestamp_Throws() { + let data = Data( + """ + { + "latestUpdateTime": "2025-09-01T14:27:33Z", + "state": { + "Vehicle": { + "Location": null + } + } + } + """.utf8 + ) + + XCTAssertThrowsError(try JSONDecoder().decode(VehicleMQTTLocationResponse.self, from: data)) + } + + func testMergedDateFormatter_RoundTrip() { + let formatter = MergedDateFormatter() + let source = "20241231235958" + + let date = formatter.date(from: source) + XCTAssertNotNil(date) + XCTAssertEqual(formatter.string(from: date!), source) + } +} From 58ad3216dcc17fef966d81ac3c2334ddd08e79e6 Mon Sep 17 00:00:00 2001 From: Lukas Foldyna Date: Wed, 4 Mar 2026 22:41:12 +0100 Subject: [PATCH 2/2] test: harden mqtt location response timestamp tests --- .../VehicleMQTTLocationResponseTests.swift | 23 +++++++++++++++---- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/KiaTests/VehicleMQTTLocationResponseTests.swift b/KiaTests/VehicleMQTTLocationResponseTests.swift index e2077da..a84cee4 100644 --- a/KiaTests/VehicleMQTTLocationResponseTests.swift +++ b/KiaTests/VehicleMQTTLocationResponseTests.swift @@ -27,8 +27,12 @@ final class VehicleMQTTLocationResponseTests: XCTestCase { let response = try JSONDecoder().decode(VehicleMQTTLocationResponse.self, from: data) XCTAssertNil(response.state.vehicle.location) + guard let utcTimeZone = TimeZone(secondsFromGMT: 0) else { + XCTFail("Failed to create UTC timezone") + return + } var utc = Calendar(identifier: .gregorian) - utc.timeZone = TimeZone(secondsFromGMT: 0)! + utc.timeZone = utcTimeZone let components = utc.dateComponents( [.year, .month, .day, .hour, .minute, .second], from: response.lastUpdateTime @@ -56,15 +60,24 @@ final class VehicleMQTTLocationResponseTests: XCTestCase { """.utf8 ) - XCTAssertThrowsError(try JSONDecoder().decode(VehicleMQTTLocationResponse.self, from: data)) + XCTAssertThrowsError(try JSONDecoder().decode(VehicleMQTTLocationResponse.self, from: data)) { error in + guard let parsingError = error as? DateValue.ParsingError else { + XCTFail("Unexpected error type: \(type(of: error))") + return + } + + switch parsingError { + case .invalidString(let invalidValue, _): + XCTAssertEqual(invalidValue, "2025-09-01T14:27:33Z") + } + } } func testMergedDateFormatter_RoundTrip() { let formatter = MergedDateFormatter() let source = "20241231235958" - let date = formatter.date(from: source) - XCTAssertNotNil(date) - XCTAssertEqual(formatter.string(from: date!), source) + let date = try XCTUnwrap(formatter.date(from: source)) + XCTAssertEqual(formatter.string(from: date), source) } }