Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 59 additions & 0 deletions KiaTests/MockVehicleDataTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -356,4 +356,63 @@ final class MockVehicleDataTests: XCTestCase {
_ = try? decoder.decode(VehicleState.self, from: jsonData)
}
}

// MARK: - Date Parsing Coverage for Recent MQTT/Status Changes

func testTimeIntervalDateFormatterDecodesMillisecondsTimestampString() throws {
struct TimestampPayload: Codable {
@DateValue<TimeIntervalDateFormatter> var ts: Date
}

let json = #"{"ts":"1753344063251"}"#
let payload = try JSONDecoder().decode(TimestampPayload.self, from: Data(json.utf8))

XCTAssertEqual(payload.ts.timeIntervalSince1970, 1_753_344_063.251, accuracy: 0.0001)
}

func testMergedDateFormatterDecodesCompactTimestampString() throws {
struct MergedPayload: Codable {
@DateValue<MergedDateFormatter> var latestUpdateTime: Date
}

let json = #"{"latestUpdateTime":"20250901202513"}"#
let payload = try JSONDecoder().decode(MergedPayload.self, from: Data(json.utf8))

var components = DateComponents()
components.year = 2025
components.month = 9
components.day = 1
components.hour = 20
components.minute = 25
components.second = 13
components.timeZone = TimeZone(secondsFromGMT: 0)
let expected = Calendar(identifier: .gregorian).date(from: components)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Calendar(identifier: .gregorian).date(from:) returns an optional Date; consider unwrapping the result so the test fails loudly if the components can’t be converted and the subsequent equality check is against a non-optional value.

Severity: medium

Fix This in Augment

🤖 Was this useful? React with 👍 or 👎, or 🚀 if it prevented an incident/outage.

Copy link

Copilot AI Mar 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

expected is a Date? from Calendar.date(from:); if it were ever nil, the assertion failure would be less clear. Consider unwrapping with XCTUnwrap (or assert not-nil) before comparing to payload.latestUpdateTime so failures point to calendar construction vs decoding.

Suggested change
let expected = Calendar(identifier: .gregorian).date(from: components)
let expected = try XCTUnwrap(Calendar(identifier: .gregorian).date(from: components))

Copilot uses AI. Check for mistakes.

XCTAssertEqual(payload.latestUpdateTime, expected)
}

func testVehicleMQTTStatusResponseDecodesLatestUpdateTimeAndState() throws {
let vehicleJSON = MockVehicleData.createVehicleStateJSON(
batteryLevel: 61,
isCharging: false,
drivingReady: true,
scenario: "mqtt_decode"
)
let mqttJSON = """
{
"latestUpdateTime": "20250901202513",
"state": {
"Vehicle": \(vehicleJSON)
}
}
"""

let response = try JSONDecoder().decode(
VehicleMQTTStatusResponse.self,
from: Data(mqttJSON.utf8)
)

Copy link

Copilot AI Mar 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

testVehicleMQTTStatusResponseDecodesLatestUpdateTimeAndState doesn’t currently assert anything about latestUpdateTime/lastUpdateTime, so it won’t catch regressions in the CodingKeys mapping or MergedDateFormatter parsing. Add an assertion that response.lastUpdateTime matches the expected UTC date represented by "20250901202513" (or rename the test if time decoding is intentionally out of scope).

Suggested change
var components = DateComponents()
components.year = 2025
components.month = 9
components.day = 1
components.hour = 20
components.minute = 25
components.second = 13
components.timeZone = TimeZone(secondsFromGMT: 0)
let expected = Calendar(identifier: .gregorian).date(from: components)
XCTAssertEqual(response.lastUpdateTime, expected)

Copilot uses AI. Check for mistakes.
XCTAssertEqual(response.state.vehicle.green.batteryManagement.batteryRemain.ratio, 61)
XCTAssertTrue(response.state.vehicle.drivingReady)
}
}
Loading