import Foundation import Testing @testable import CardsNative @Suite("Review-JSON-Decoding") struct ReviewDecodingTests { @Test("Review-Wire-Format decodet vollständig") func decodesReview() throws { let json = """ { "card_id": "card_1", "sub_index": 0, "user_id": "user_1", "due": "2026-05-13T10:00:00.000Z", "stability": 2.5, "difficulty": 5.0, "elapsed_days": 1.0, "scheduled_days": 3.0, "learning_steps": 0, "reps": 5, "lapses": 1, "state": "review", "last_review": "2026-05-10T10:00:00.000Z" } """.data(using: .utf8)! let decoder = JSONDecoder() decoder.dateDecodingStrategy = .iso8601withFractional let review = try decoder.decode(Review.self, from: json) #expect(review.cardId == "card_1") #expect(review.subIndex == 0) #expect(review.state == .review) #expect(review.reps == 5) #expect(review.lastReview != nil) } @Test("DueReview embedded card decodet (camelCase deckId!)") func decodesDueReview() throws { // Achtung: Server liefert hier `deckId` camelCase im embedded card, // weil das aus Drizzle direkt rauskommt, nicht durch toCardDto. let json = """ { "card_id": "c1", "sub_index": 0, "user_id": "u1", "due": "2026-05-13T10:00:00.000Z", "stability": 0, "difficulty": 0, "elapsed_days": 0, "scheduled_days": 0, "learning_steps": 0, "reps": 0, "lapses": 0, "state": "new", "last_review": null, "card": { "id": "c1", "deckId": "d1", "type": "basic", "fields": {"front": "Was ist 1+1?", "back": "2"} } } """.data(using: .utf8)! let decoder = JSONDecoder() decoder.dateDecodingStrategy = .iso8601withFractional let due = try decoder.decode(DueReview.self, from: json) #expect(due.review.cardId == "c1") #expect(due.card.deckId == "d1") #expect(due.card.type == .basic) #expect(due.card.fields["front"] == "Was ist 1+1?") } @Test("Rating-Enum-Werte sind exakt wie ts-fsrs erwartet") func ratingValues() { #expect(Rating.again.rawValue == "again") #expect(Rating.hard.rawValue == "hard") #expect(Rating.good.rawValue == "good") #expect(Rating.easy.rawValue == "easy") } }