// // APIService+GetItemsTests.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 APIServiceGetItemsTests: XCTestCase { // MARK: Properties private let dateFormatter = DateFormatter.isoZulu private let sessionConfiguration = { let configuration = URLSessionConfiguration.default configuration.protocolClasses = [MockURLProtocol.self] return configuration }() private let itemId = UUID().uuidString private let url = URL(string: "http://163.172.147.216:8080/items/")! private var service: APIService! private var data: Data! private var result: [Item]! // MARK: Setup override func setUp() async throws { service = .init(configuration: sessionConfiguration) } override func tearDown() async throws { service = nil } // MARK: Test cases func test_withExistingId_andRightCredentials_whenDataArrayPopulated() async throws { // GIVEN data = "[{\"id\":\"a077432ceb69b4f2dcbd4932d3ec63c3a4f14784\",\"parentId\":\"4b8e41fd4a6a89712f15bbf102421b9338cfab11\",\"name\":\"Tokyo\",\"isDir\":true,\"modificationDate\":\"2022-11-25T17:33:57.095027128Z\"},{\"id\":\"f5d351f7e532cae7c7be28488564b567ffeb425a\",\"parentId\":\"4b8e41fd4a6a89712f15bbf102421b9338cfab11\",\"name\":\"Meme.jpg\",\"isDir\":false,\"size\":43144,\"contentType\":\"image/jpeg\",\"modificationDate\":\"2022-12-01T15:24:12.29816675Z\"}]\n".data(using: .utf8) MockURLProtocol.mockData[url.appendingPathComponent(itemId)] = MockURLResponse( status: .ok, headers: [.Header.Keys.contentType: .Header.Values.contentTypeJSON], data: data ) // WHEN result = try await service.getItems( id: itemId, credentials: .init( username: "username", password: "password" ) ) // THEN XCTAssertEqual(result, [ .init( idParent: "4b8e41fd4a6a89712f15bbf102421b9338cfab11", id: "a077432ceb69b4f2dcbd4932d3ec63c3a4f14784", name: "Tokyo", isDirectory: true, lastModifiedAt: dateFormatter.date(from: "2022-11-25T17:33:57.095027128Z")!, size: nil, contentType: nil ), .init( idParent: "4b8e41fd4a6a89712f15bbf102421b9338cfab11", id: "f5d351f7e532cae7c7be28488564b567ffeb425a", name: "Meme.jpg", isDirectory: false, lastModifiedAt: dateFormatter.date(from: "2022-12-01T15:24:12.29816675Z")!, size: 43144, contentType: "image/jpeg" ), ]) } func test_withExistingId_andRightCredentials_whenDataArrayEmpty() async throws { // GIVEN data = "[]".data(using: .utf8) MockURLProtocol.mockData[url.appendingPathComponent(itemId)] = MockURLResponse( status: .ok, headers: [.Header.Keys.contentType: .Header.Values.contentTypeJSON], data: data ) // WHEN result = try await service.getItems( id: itemId, credentials: .init( username: "username", password: "password" ) ) // THEN XCTAssertEqual(result, []) } func test_withExistingId_andWrongCredentials() async throws { // GIVEN MockURLProtocol.mockData[url.appendingPathComponent(itemId)] = MockURLResponse( status: .unauthorized, headers: [:], data: nil ) // WHEN & THEN do { _ = try await service.getItems( id: itemId, credentials: .init( username: "usrname", password: "passwrd" ) ) } catch APIClientError.authenticationFailed { XCTAssertTrue(true) } catch { XCTAssertTrue(false) } } func test_withNonExistingId_andRightCredentials() async throws { // GIVEN MockURLProtocol.mockData[url.appendingPathComponent("xxx")] = MockURLResponse( status: .notFound, headers: [:], data: nil ) // WHEN & THEN do { _ = try await service.getItems( id: "xxx", credentials: .init( username: "usrname", password: "passwrd" ) ) } catch APIClientError.itemDoesNotExist { XCTAssertTrue(true) } catch { XCTAssertTrue(false) } } func test_withEmptyId_andRightCredentials() async throws { // GIVEN MockURLProtocol.mockData[url.appendingPathComponent("")] = MockURLResponse( status: .notFound, headers: [:], data: nil ) // WHEN & THEN do { _ = try await service.getItems( id: "", credentials: .init( username: "usrname", password: "passwrd" ) ) } catch APIClientError.itemDoesNotExist { XCTAssertTrue(true) } catch { XCTAssertTrue(false) } } }