diff --git a/Stream-iOS/Stream-iOS.xcodeproj/project.pbxproj b/Stream-iOS/Stream-iOS.xcodeproj/project.pbxproj index dfa74ef..1ab380a 100644 --- a/Stream-iOS/Stream-iOS.xcodeproj/project.pbxproj +++ b/Stream-iOS/Stream-iOS.xcodeproj/project.pbxproj @@ -355,7 +355,7 @@ PRODUCT_NAME = "$(TARGET_NAME)"; STRING_CATALOG_GENERATE_SYMBOLS = YES; SWIFT_APPROACHABLE_CONCURRENCY = YES; - SWIFT_DEFAULT_ACTOR_ISOLATION = MainActor; + SWIFT_DEFAULT_ACTOR_ISOLATION = nonisolated; SWIFT_EMIT_LOC_STRINGS = YES; SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES; SWIFT_VERSION = 6.0; @@ -389,7 +389,7 @@ PRODUCT_NAME = "$(TARGET_NAME)"; STRING_CATALOG_GENERATE_SYMBOLS = YES; SWIFT_APPROACHABLE_CONCURRENCY = YES; - SWIFT_DEFAULT_ACTOR_ISOLATION = MainActor; + SWIFT_DEFAULT_ACTOR_ISOLATION = nonisolated; SWIFT_EMIT_LOC_STRINGS = YES; SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES; SWIFT_VERSION = 6.0; diff --git a/Stream-iOS/Stream-iOS/Core/Models/CharacterDTO.swift b/Stream-iOS/Stream-iOS/Core/Models/CharacterDTO.swift new file mode 100644 index 0000000..72d40b9 --- /dev/null +++ b/Stream-iOS/Stream-iOS/Core/Models/CharacterDTO.swift @@ -0,0 +1,27 @@ +// +// CharacterDTO.swift +// Stream-iOS +// +// Created by Ullash Podder on 14/07/2026. +// +import Foundation + +struct CharacterDTO: Decodable, Sendable, Identifiable { + let id: Int + let name: String + let status: CharacterStatus + let species: String + let gender: String + let image: URL +} + +enum CharacterStatus: String, Decodable, Sendable { + case alive = "Alive" + case dead = "Dead" + case unknown + + init(from decoder: Decoder) throws { + let raw = try decoder.singleValueContainer().decode(String.self) + self = CharacterStatus(rawValue: raw) ?? .unknown + } +} diff --git a/Stream-iOS/Stream-iOS/Core/Models/PagedResponse.swift b/Stream-iOS/Stream-iOS/Core/Models/PagedResponse.swift new file mode 100644 index 0000000..ab1917b --- /dev/null +++ b/Stream-iOS/Stream-iOS/Core/Models/PagedResponse.swift @@ -0,0 +1,20 @@ +// +// PagedResponse.swift +// Stream-iOS +// +// Created by Ullash Podder on 14/07/2026. +// + +import Foundation +struct PagedResponse: Decodable, Sendable { + let info: PageInfo + let results: [T] +} + +struct PageInfo: Decodable, Sendable { + let count: Int + let pages: Int + let next: URL? + let prev: URL? +} + diff --git a/Stream-iOS/Stream-iOSTests/CharacterDecodingTests.swift b/Stream-iOS/Stream-iOSTests/CharacterDecodingTests.swift new file mode 100644 index 0000000..e48badb --- /dev/null +++ b/Stream-iOS/Stream-iOSTests/CharacterDecodingTests.swift @@ -0,0 +1,44 @@ +// +// CharacterDecodingTests.swift +// Stream-iOS +// +// Created by Ullash Podder on 14/07/2026. +// + +import Testing +import Foundation +@testable import Stream_iOS + +struct CharacterDecodingTests { + + @Test func decodesPagedResponseFromFixture() throws { + let data = try Fixture.load("character_page1") + let response = try JSONDecoder().decode(PagedResponse.self, from: data) + + #expect(response.info.count == 826) + #expect(response.info.pages == 42) + #expect(response.results.count == 20) + #expect(response.info.next != nil) + #expect(response.info.prev == nil) + } + + @Test func decodesFirstCharacterCorrectly() throws { + let data = try Fixture.load("character_page1") + let response = try JSONDecoder().decode(PagedResponse.self, from: data) + let rick = try #require(response.results.first) + + #expect(rick.id == 1) + #expect(rick.name == "Rick Sanchez") + #expect(rick.status == .alive) + #expect(rick.species == "Human") + #expect(rick.image.absoluteString.hasSuffix("/avatar/1.jpeg")) + } + + @Test func decodesUnknownStatusAsFallback() throws { + let json = #"{"id":1,"name":"X","status":"Martian","species":"Y","gender":"Male","image":"https://a.com/1.jpeg"}"# + let dto = try JSONDecoder().decode(CharacterDTO.self, from: Data(json.utf8)) + + #expect(dto.status == .unknown) + } +} + diff --git a/Stream-iOS/Stream-iOSTests/Fixtures/Fixture.swift b/Stream-iOS/Stream-iOSTests/Fixtures/Fixture.swift new file mode 100644 index 0000000..7876b8b --- /dev/null +++ b/Stream-iOS/Stream-iOSTests/Fixtures/Fixture.swift @@ -0,0 +1,22 @@ +// +// Fixture.swift +// Stream-iOS +// +// Created by Ullash Podder on 14/07/2026. +// + +import Foundation + +enum Fixture { + enum Error: Swift.Error { case notFound(String) } + + static func load(_ name: String) throws -> Data { + let bundle = Bundle(for: BundleToken.self) + guard let url = bundle.url(forResource: name, withExtension: "json") else { + throw Error.notFound(name) + } + return try Data(contentsOf: url) + } + + private final class BundleToken {} +} diff --git a/Stream-iOS/Stream-iOS/Resources/character_page1.json b/Stream-iOS/Stream-iOSTests/Fixtures/character_page1.json similarity index 100% rename from Stream-iOS/Stream-iOS/Resources/character_page1.json rename to Stream-iOS/Stream-iOSTests/Fixtures/character_page1.json