// // GetReviewsAPIEndpointTests.swift // ReviewsiTunesTest // // Created by Javier Cicchelli on 17/03/2024. // Copyright © 2024 Röck+Cöde VoF. All rights reserved. // import ReviewsFeedKit import ReviewsFoundationKit import XCTest @testable import ReviewsiTunesKit final class GetReviewsAPIEndpointTests: XCTestCase { // MARK: Properties private var input: GetReviewsAPIEndpoint.Input! private var sut: GetReviewsAPIEndpoint! // MARK: Setup override func setUp() async throws { sut = .init( host: .iTunes, decoder: .default, session: .init(configuration: .mock) ) } // MARK: Functions tests func testCallAsFunction_whenResponseOK_withOneReview() async throws { // GIVEN let reviews: [Review] = .one input = .init( appID: "1234567890", countryCode: "abc" ) MockURLProtocol.response = .init( statusCode: 200, object: Feed(entries: reviews) ) // WHEN let output = try await sut(input) // THEN XCTAssertFalse(output.reviews.isEmpty) XCTAssertEqual(output.reviews.count, reviews.count) XCTAssertEqual(output.reviews, reviews) } func testCallAsFunction_whenResponseOK_withManyReviews() async throws { // GIVEN let reviews: [Review] = .many input = .init( appID: "1234567890", countryCode: "abc" ) MockURLProtocol.response = .init( statusCode: 200, object: Feed(entries: reviews) ) // WHEN let output = try await sut(input) // THEN XCTAssertFalse(output.reviews.isEmpty) XCTAssertEqual(output.reviews.count, reviews.count) XCTAssertEqual(output.reviews, reviews) } func testCallAsFunction_whenResponseOK_withEmptyReviews() async throws { // GIVEN let reviews: [Review] = .empty input = .init( appID: "1234567890", countryCode: "abc" ) MockURLProtocol.response = .init( statusCode: 200, object: Feed(entries: reviews) ) // WHEN let output = try await sut(input) // THEN XCTAssertTrue(output.reviews.isEmpty) XCTAssertEqual(output.reviews.count, reviews.count) XCTAssertEqual(output.reviews, reviews) } func testCallAsFunction_whenResponseNotOK() async throws { // GIVEN let statusCode = 404 input = .init( appID: "1234567890", countryCode: "abc" ) MockURLProtocol.response = .init(statusCode: statusCode) // WHEN // THEN do { try await sut(input) } catch EndpointError.requestFailed(statusCode: statusCode) { XCTAssertTrue(true) } catch { XCTAssertTrue(false) } } func testMakePath_withFilledInput() throws { // GIVEN input = .init( appID: "1234567890", countryCode: "abc" ) // WHEN let path = try sut.makePath(with: input) // THEN XCTAssertEqual(path, "/\(input.countryCode)/rss/customerreviews/id=\(input.appID)/sortby=mostrecent/json") } func testMakePath_withPartiallyFilledInput() throws { // GIVEN input = .init( appID: .empty, countryCode: "abc" ) // WHEN // THEN XCTAssertThrowsError(try sut.makePath(with: input)) { error in XCTAssertEqual(error as? EndpointError, .inputParametersEmpty) } } func testMakePath_withEmptyInput() throws { // GIVEN input = .init( appID: .empty, countryCode: .empty ) // WHEN // THEN XCTAssertThrowsError(try sut.makePath(with: input)) { error in XCTAssertEqual(error as? EndpointError, .inputParametersEmpty) } } } // MARK: - Array+Constants private extension Array where Element == Review { // MARK: Constants static let empty: [Review] = [] static let many: [Review] = [ .init( id: 1, author: "Some author name #1 goes here...", title: "Some title #1 goes here...", content: "Some content #1 goes here...", rating: 1, version: "Some version #1 goes here...", updated: .init() ), .init( id: 2, author: "Some author name #2 goes here...", title: "Some title #2 goes here...", content: "Some content #2 goes here...", rating: 5, version: "Some version #2 goes here...", updated: .init() ), .init( id: 3, author: "Some author name #3 goes here...", title: "Some title #3 goes here...", content: "Some content #3 goes here...", rating: 3, version: "Some version #3 goes here...", updated: .init() ) ] static let one: [Review] = [ .init( id: 1, author: "Some author name goes here...", title: "Some title goes here...", content: "Some content goes here...", rating: 3, version: "Some version goes here...", updated: .init() ) ] }