Fix 3 critical bugs: infinite recursion, stuck loading state, unstable IDs

- Rename waitForExistence() to waitForAppearance() in UI test helpers
  to fix infinite recursion caused by shadowing XCUIElement's built-in method
- Add else branch in fetchItemPrice() so watchlist items show "Parse Error"
  instead of staying stuck in loading state when JSON parsing fails
- Change AttackResult.id from computed property (generating new UUID on
  every access) to stored property assigned once at init, preventing
  SwiftUI re-render thrashing in ForEach
This commit is contained in:
Paweł Orzech 2026-02-27 23:30:15 +01:00
parent 0ea44f891a
commit 032ff5887c
No known key found for this signature in database
3 changed files with 33 additions and 3 deletions

View file

@ -373,7 +373,7 @@ struct AttackResult: Codable, Identifiable {
let result: String?
let respect: Double?
var id: String { code ?? UUID().uuidString }
let id: String
enum CodingKeys: String, CodingKey {
case code
@ -386,6 +386,33 @@ struct AttackResult: Codable, Identifiable {
case result, respect
}
init(code: String?, timestampStarted: Int?, timestampEnded: Int?, attackerId: Int?, attackerName: String?, defenderId: Int?, defenderName: String?, result: String?, respect: Double?) {
self.code = code
self.timestampStarted = timestampStarted
self.timestampEnded = timestampEnded
self.attackerId = attackerId
self.attackerName = attackerName
self.defenderId = defenderId
self.defenderName = defenderName
self.result = result
self.respect = respect
self.id = code ?? UUID().uuidString
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
code = try container.decodeIfPresent(String.self, forKey: .code)
timestampStarted = try container.decodeIfPresent(Int.self, forKey: .timestampStarted)
timestampEnded = try container.decodeIfPresent(Int.self, forKey: .timestampEnded)
attackerId = try container.decodeIfPresent(Int.self, forKey: .attackerId)
attackerName = try container.decodeIfPresent(String.self, forKey: .attackerName)
defenderId = try container.decodeIfPresent(Int.self, forKey: .defenderId)
defenderName = try container.decodeIfPresent(String.self, forKey: .defenderName)
result = try container.decodeIfPresent(String.self, forKey: .result)
respect = try container.decodeIfPresent(Double.self, forKey: .respect)
id = code ?? UUID().uuidString
}
func opponentName(forUserId userId: Int) -> String {
let name: String?
if attackerId == userId {

View file

@ -312,6 +312,9 @@ class AppState: ObservableObject {
} else {
await updateItemError(itemId: itemId, error: "No listings")
}
} else {
logger.error("Item \(itemId): failed to parse JSON response")
await updateItemError(itemId: itemId, error: "Parse Error")
}
} catch {
logger.error("Item \(itemId) price fetch error: \(error.localizedDescription)")

View file

@ -136,8 +136,8 @@ final class MacTornUITests: XCTestCase {
// MARK: - UI Test Helpers
extension XCUIElement {
/// Wait for element to exist with timeout
func waitForExistence(timeout: TimeInterval = 5) -> Bool {
/// Wait for element to appear within the given timeout
func waitForAppearance(timeout: TimeInterval = 5) -> Bool {
return self.waitForExistence(timeout: timeout)
}