// // APIClient+RequestTests.swift // APIServiceTests // // Created by Javier Cicchelli on 04/12/2022. // Copyright © 2022 Röck+Cöde. All rights reserved. // import Foundation import XCTest @testable import APIService final class APIClientRequestTests: XCTestCase { // MARK: Properties private let makeURLRequest = MakeURLRequestUseCase() private let dateFormatter = DateFormatter.iso8601 private let sessionConfiguration = { let configuration = URLSessionConfiguration.default configuration.protocolClasses = [MockURLProtocol.self] return configuration }() private var client: APIClient! private var url: URL! private var data: Data! // MARK: Setup override func setUp() async throws { client = .init(configuration: sessionConfiguration) } // MARK: Request cases func test_withSomeEndpoint_andSomeModel_whenResponseStatusOk() async throws { // GIVEN let endpoint = GetMeEndpoint( username: "username", password: "password" ) url = try makeURLRequest(endpoint: endpoint).url data = "{\"firstName\":\"Noel\",\"lastName\":\"Flantier\",\"rootItem\":{\"id\":\"4b8e41fd4a6a89712f15bbf102421b9338cfab11\",\"parentId\":\"\",\"name\":\"dossierTest\",\"isDir\":true,\"modificationDate\":\"2021-11-29T10:57:13Z\"}}\n".data(using: .utf8) MockURLProtocol.mockData[url] = MockURLResponse( status: .ok, headers: [:], data: data ) // WHEN let result = try await client.request(endpoint: endpoint, model: Me.self) // THEN XCTAssertEqual(result, Me( firstName: "Noel", lastName: "Flantier", rootItem: .init( idParent: "", id: "4b8e41fd4a6a89712f15bbf102421b9338cfab11", name: "dossierTest", isDirectory: true, lastModifiedAt: dateFormatter.date(from: "2021-11-29T10:57:13Z")!, size: nil, contentType: nil ) )) } func test_withSomeEndpoint_andSomeModel_whenResponseStatusCreated() async throws { // GIVEN let endpoint = GetMeEndpoint( username: "username", password: "password" ) url = try makeURLRequest(endpoint: endpoint).url data = "{\"firstName\":\"Noel\",\"lastName\":\"Flantier\",\"rootItem\":{\"id\":\"4b8e41fd4a6a89712f15bbf102421b9338cfab11\",\"parentId\":\"\",\"name\":\"dossierTest\",\"isDir\":true,\"modificationDate\":\"2021-11-29T10:57:13Z\"}}\n".data(using: .utf8) MockURLProtocol.mockData[url] = MockURLResponse( status: .created, headers: [:], data: data ) // WHEN let result = try await client.request(endpoint: endpoint, model: Me.self) // THEN XCTAssertEqual(result, Me( firstName: "Noel", lastName: "Flantier", rootItem: .init( idParent: "", id: "4b8e41fd4a6a89712f15bbf102421b9338cfab11", name: "dossierTest", isDirectory: true, lastModifiedAt: dateFormatter.date(from: "2021-11-29T10:57:13Z")!, size: nil, contentType: nil ) )) } func test_withSomeEndpoint_andSomeModel_whenResponseStatusNoContent() async throws { // GIVEN let endpoint = GetMeEndpoint( username: "username", password: "password" ) url = try makeURLRequest(endpoint: endpoint).url MockURLProtocol.mockData[url] = MockURLResponse( status: .noContent, headers: [:], data: nil ) // WHEN & THEN do { _ = try await client.request(endpoint: endpoint, model: Me.self) } catch APIClientError.notSupported { XCTAssertTrue(true) } catch { XCTAssertTrue(false) } } func test_withSomeEndpoint_andSomeModel_whenResponseStatusBadRequest() async throws { // GIVEN let endpoint = GetMeEndpoint( username: "username", password: "password" ) url = try makeURLRequest(endpoint: endpoint).url MockURLProtocol.mockData[url] = MockURLResponse( status: .badRequest, headers: [:], data: nil ) // WHEN & THEN do { _ = try await client.request(endpoint: endpoint, model: Me.self) } catch APIClientError.itemAlreadyExist { XCTAssertTrue(true) } catch { XCTAssertTrue(false) } } func test_withSomeEndpoint_andSomeModel_whenResponseStatusForbidden() async throws { // GIVEN let endpoint = GetMeEndpoint( username: "username", password: "password" ) url = try makeURLRequest(endpoint: endpoint).url MockURLProtocol.mockData[url] = MockURLResponse( status: .forbidden, headers: [:], data: nil ) // WHEN & THEN do { _ = try await client.request(endpoint: endpoint, model: Me.self) } catch APIClientError.authenticationFailed { XCTAssertTrue(true) } catch { XCTAssertTrue(false) } } func test_withSomeEndpoint_andSomeModel_whenResponseStatusNotFound() async throws { // GIVEN let endpoint = GetMeEndpoint( username: "username", password: "password" ) url = try makeURLRequest(endpoint: endpoint).url MockURLProtocol.mockData[url] = MockURLResponse( status: .notFound, headers: [:], data: nil ) // WHEN & THEN do { _ = try await client.request(endpoint: endpoint, model: Me.self) } catch APIClientError.itemDoesNotExist { XCTAssertTrue(true) } catch { XCTAssertTrue(false) } } func test_withSomeEndpoint_andSomeModel_whenResponseDataIncorrect() async throws { // GIVEN let endpoint = GetMeEndpoint( username: "username", password: "password" ) url = try makeURLRequest(endpoint: endpoint).url data = "{\"firstName\":\"Noel\",\"lastName\":\"Flantier\",\"rootItem\":{\"id\":\"4b8e41fd4a6a89712f15bbf102421b9338cfab11\"\"isDir\":true}}\n".data(using: .utf8) MockURLProtocol.mockData[url] = MockURLResponse( status: .ok, headers: [:], data: data ) // WHEN & THEN do { _ = try await client.request(endpoint: endpoint, model: Me.self) } catch is DecodingError { XCTAssertTrue(true) } catch { XCTAssertTrue(false) } } func test_withSomeEndpoint_whenResponseStatusOk() async throws { // GIVEN let endpoint = GetDataEndpoint( itemId: UUID().uuidString, username: "username", password: "password" ) url = try makeURLRequest(endpoint: endpoint).url data = "This is just some dummy data for testing purposes".data(using: .utf8) MockURLProtocol.mockData[url] = MockURLResponse( status: .ok, headers: [:], data: data ) // WHEN let result = try await client.request(endpoint: endpoint) // THEN XCTAssertEqual(result, data) } func test_withSomeEndpoint_whenResponseStatusCreated() async throws { // GIVEN let endpoint = GetDataEndpoint( itemId: UUID().uuidString, username: "username", password: "password" ) url = try makeURLRequest(endpoint: endpoint).url MockURLProtocol.mockData[url] = MockURLResponse( status: .created, headers: [:], data: nil ) // WHEN & THEN do { try await client.request(endpoint: endpoint) } catch APIClientError.notSupported { XCTAssertTrue(true) } catch { XCTAssertTrue(false) } } func test_withSomeEndpoint_whenResponseStatusNoContent() async throws { // GIVEN let endpoint = GetDataEndpoint( itemId: UUID().uuidString, username: "username", password: "password" ) url = try makeURLRequest(endpoint: endpoint).url data = .init() MockURLProtocol.mockData[url] = MockURLResponse( status: .noContent, headers: [:], data: nil ) // WHEN let result = try await client.request(endpoint: endpoint) // THEN XCTAssertEqual(result, data) } func test_withSomeEndpoint_whenResponseStatusBadRequest() async throws { // GIVEN let endpoint = GetDataEndpoint( itemId: UUID().uuidString, username: "username", password: "password" ) url = try makeURLRequest(endpoint: endpoint).url MockURLProtocol.mockData[url] = MockURLResponse( status: .badRequest, headers: [:], data: nil ) // WHEN & THEN do { try await client.request(endpoint: endpoint) } catch APIClientError.itemIsNotFile { XCTAssertTrue(true) } catch { XCTAssertTrue(false) } } func test_withSomeEndpoint_whenResponseStatusForbidden() async throws { // GIVEN let endpoint = GetDataEndpoint( itemId: UUID().uuidString, username: "username", password: "password" ) url = try makeURLRequest(endpoint: endpoint).url MockURLProtocol.mockData[url] = MockURLResponse( status: .forbidden, headers: [:], data: nil ) // WHEN & THEN do { try await client.request(endpoint: endpoint) } catch APIClientError.authenticationFailed { XCTAssertTrue(true) } catch { XCTAssertTrue(false) } } func test_withSomeEndpoint_whenResponseStatusNotFound() async throws { // GIVEN let endpoint = GetDataEndpoint( itemId: UUID().uuidString, username: "username", password: "password" ) url = try makeURLRequest(endpoint: endpoint).url MockURLProtocol.mockData[url] = MockURLResponse( status: .notFound, headers: [:], data: nil ) // WHEN & THEN do { try await client.request(endpoint: endpoint) } catch APIClientError.itemDoesNotExist { XCTAssertTrue(true) } catch { XCTAssertTrue(false) } } }