// // LocationsClientTests.swift // LocationsTests // // Created by Javier Cicchelli on 10/04/2023. // Copyright © 2023 Röck+Cöde. All rights reserved. // import APICore import XCTest @testable import Locations final class LocationsClientTests: XCTestCase { // MARK: Properties private let makeURLRequest = MakeURLRequestUseCase() private let sessionConfiguration = { let configuration = URLSessionConfiguration.default configuration.protocolClasses = [MockURLProtocol.self] return configuration }() private var client: LocationsClient! private var url: URL! private var data: Data! // MARK: Setup override func setUp() async throws { client = .init(configuration: sessionConfiguration) } override func tearDown() async throws { client = nil } // MARK: Tests func test_request_withGetLocationsEndpoint_forLocations_whenResponseOK() async throws { // GIVEN let endpoint = GetLocationsEndpoint() url = try makeURLRequest(endpoint: endpoint).url data = .locations MockURLProtocol.mockData[url] = MockURLResponse( status: 200, headers: [:], data: data ) // WHEN let result = try await client.request(endpoint: endpoint, for: Locations.self) // THEN XCTAssertEqual(result, Locations(locations: [ .init( name: "Amsterdam", latitude: 52.3547498, longitude: 4.8339215 ), .init( name: "Mumbai", latitude: 19.0823998, longitude: 72.8111468 ), .init( name: "Copenhagen", latitude: 55.6713442, longitude: 12.523785 ), .init( latitude: 40.4380638, longitude: -3.7495758 ) ])) } func test_request_withGetLocationsEndpoint_forLocations_whenResponseClientError() async throws { // GIVEN let endpoint = GetLocationsEndpoint() url = try makeURLRequest(endpoint: endpoint).url data = .locations MockURLProtocol.mockData[url] = MockURLResponse( status: 404, headers: [:], data: data ) // WHEN & THEN do { _ = try await client.request(endpoint: endpoint, for: Locations.self) } catch LocationsClientError.statusErrorClient { XCTAssertTrue(true) } catch { XCTAssertTrue(false) } } func test_request_withGetLocationsEndpoint_forLocations_whenResponseServerError() async throws { // GIVEN let endpoint = GetLocationsEndpoint() url = try makeURLRequest(endpoint: endpoint).url data = .locations MockURLProtocol.mockData[url] = MockURLResponse( status: 500, headers: [:], data: data ) // WHEN & THEN do { _ = try await client.request(endpoint: endpoint, for: Locations.self) } catch LocationsClientError.statusErrorServer { XCTAssertTrue(true) } catch { XCTAssertTrue(false) } } func test_request_withGetLocationsEndpoint_forLocations_whenResponseUnexpectedError() async throws { // GIVEN let endpoint = GetLocationsEndpoint() url = try makeURLRequest(endpoint: endpoint).url data = .locations MockURLProtocol.mockData[url] = MockURLResponse( status: 302, headers: [:], data: data ) // WHEN & THEN do { _ = try await client.request(endpoint: endpoint, for: Locations.self) } catch LocationsClientError.statusErrorUnexpected { XCTAssertTrue(true) } catch { XCTAssertTrue(false) } } } // MARK: - Models private struct Locations: Decodable, Equatable { public let locations: [Location] } // MARK: - String+Constants private extension Data { static let locations = "{\"locations\":[{\"name\":\"Amsterdam\",\"lat\":52.3547498,\"long\":4.8339215},{\"name\":\"Mumbai\",\"lat\":19.0823998,\"long\":72.8111468},{\"name\":\"Copenhagen\",\"lat\":55.6713442,\"long\":12.523785},{\"lat\":40.4380638,\"long\":-3.7495758}]}".data(using: .utf8) }