Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

REFACTOR: Migrate Adapter tests to Swift Testing #195

Merged
merged 1 commit into from
Sep 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
156 changes: 70 additions & 86 deletions Tests/TMDbTests/Adapters/URLSessionHTTPClientAdapterTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,144 +17,128 @@
// limitations under the License.
//

import Foundation
import Testing
@testable import TMDb
import XCTest
#if canImport(FoundationNetworking)
import FoundationNetworking
#endif

final class URLSessionHTTPClientAdapterTests: XCTestCase {
@Suite(
.serialized,
.tags(.adapter)
)
final class URLSessionHTTPClientAdapterTests {

var httpClient: URLSessionHTTPClientAdapter!
var baseURL: URL!
var urlSession: URLSession!

override func setUpWithError() throws {
try super.setUpWithError()
baseURL = try XCTUnwrap(URL(string: "https://some.domain.com/path"))
init() throws {
self.baseURL = try #require(URL(string: "https://some.domain.com/path"))

let configuration = URLSessionConfiguration.default
configuration.protocolClasses = [MockURLProtocol.self]
urlSession = URLSession(configuration: configuration)
httpClient = URLSessionHTTPClientAdapter(urlSession: urlSession)
self.urlSession = URLSession(configuration: configuration)
self.httpClient = URLSessionHTTPClientAdapter(urlSession: urlSession)
}

override func tearDown() async throws {
deinit {
httpClient = nil
urlSession = nil
baseURL = nil
await MockURLProtocol.reset()
try await super.tearDown()
Task {
await MockURLProtocol.reset()
}
}

@Test("perform when response status code is 401 returns unauthorised error")
@MainActor
func testPerformWhenResponseStatusCodeIs401ReturnsUnauthorisedError() async throws {
func performWhenResponseStatusCodeIs401ReturnsUnauthorisedError() async throws {
MockURLProtocol.responseStatusCode = 401
let url = try XCTUnwrap(URL(string: "/error"))
let url = try #require(URL(string: "/error"))
let request = HTTPRequest(url: url)

let response: HTTPResponse
do {
response = try await httpClient.perform(request: request)
} catch {
XCTFail("Unexpected error thrown")
return
}
let response = try await httpClient.perform(request: request)

XCTAssertEqual(response.statusCode, 401)
#expect(response.statusCode == 401)
}

@Test("perform when response status code is 404 returns not found error")
@MainActor
func testPerformWhenResponseStatusCodeIs404ReturnsNotFoundError() async throws {
func performWhenResponseStatusCodeIs404ReturnsNotFoundError() async throws {
MockURLProtocol.responseStatusCode = 404
let url = try XCTUnwrap(URL(string: "/error"))
let url = try #require(URL(string: "/error"))
let request = HTTPRequest(url: url)

let response: HTTPResponse
do {
response = try await httpClient.perform(request: request)
} catch {
XCTFail("Unexpected error thrown")
return
}
let response = try await httpClient.perform(request: request)

XCTAssertEqual(response.statusCode, 404)
#expect(response.statusCode == 404)
}

@Test("perform when response status code is 404 and has status message error throws not found error with message")
@MainActor
func testPerformWhenResponseStatusCodeIs404AndHasStatusMessageErrorThrowsNotFoundErrorWithMessage() async throws {
func performWhenResponseStatusCodeIs404AndHasStatusMessageErrorThrowsNotFoundErrorWithMessage() async throws {
MockURLProtocol.responseStatusCode = 404
let expectedData = try Data(fromResource: "error-status-response", withExtension: "json")
MockURLProtocol.data = expectedData
let url = try XCTUnwrap(URL(string: "/error"))
let url = try #require(URL(string: "/error"))
let request = HTTPRequest(url: url)

let response: HTTPResponse
do {
response = try await httpClient.perform(request: request)
} catch {
XCTFail("Unexpected error thrown")
return
}
let response = try await httpClient.perform(request: request)

XCTAssertEqual(response.statusCode, 404)
XCTAssertEqual(response.data, expectedData)
#expect(response.statusCode == 404)
#expect(response.data == expectedData)
}

@Test("perform when response has valid data returns decoded object")
@MainActor
func testGetWhenResponseHasValidDataReturnsDecodedObject() async throws {
func performWhenResponseHasValidDataReturnsDecodedObject() async throws {
let expectedStatusCode = 200
let expectedData = Data("abc".utf8)
MockURLProtocol.data = expectedData
let url = try XCTUnwrap(URL(string: "/object"))
let url = try #require(URL(string: "/object"))
let request = HTTPRequest(url: url)

let response = try await httpClient.perform(request: request)

XCTAssertEqual(response.statusCode, expectedStatusCode)
XCTAssertEqual(response.data, expectedData)
#expect(response.statusCode == expectedStatusCode)
#expect(response.data == expectedData)
}

}

#if !canImport(FoundationNetworking)
extension URLSessionHTTPClientAdapterTests {

@MainActor
func testPerformURLRequestHasCorrectURL() async throws {
let path = "/object?key1=value1&key2=value2"
let expectedURL = try XCTUnwrap(URL(string: path))
let request = HTTPRequest(url: expectedURL)
@Test("perform URL request has correct URL")
@MainActor
func performURLRequestHasCorrectURL() async throws {
let path = "/object?key1=value1&key2=value2"
let expectedURL = try #require(URL(string: path))
let request = HTTPRequest(url: expectedURL)

_ = try? await httpClient.perform(request: request)
_ = try? await httpClient.perform(request: request)

let result = MockURLProtocol.lastRequest?.url
let result = MockURLProtocol.lastRequest?.url

XCTAssertEqual(result, expectedURL)
}

@MainActor
func testPerformWhenHeaderSetShouldBePresentInURLRequest() async throws {
let url = try XCTUnwrap(URL(string: "/object"))
let header1Name = "Accept"
let header1Value = "application/json"
let header2Name = "Content-Type"
let header2Value = "text/html"
let headers = [
header1Name: header1Value,
header2Name: header2Value
]
let request = HTTPRequest(url: url, headers: headers)

_ = try? await httpClient.perform(request: request)

let lastURLRequest = try XCTUnwrap(MockURLProtocol.lastRequest)
let result1 = lastURLRequest.value(forHTTPHeaderField: header1Name)
let result2 = lastURLRequest.value(forHTTPHeaderField: header2Name)

XCTAssertEqual(result1, header1Value)
XCTAssertEqual(result2, header2Value)
}
#expect(result == expectedURL)
}

@Test("perform when header set should be present in URL request")
@MainActor
func performWhenHeaderSetShouldBePresentInURLRequest() async throws {
let url = try #require(URL(string: "/object"))
let header1Name = "Accept"
let header1Value = "application/json"
let header2Name = "Content-Type"
let header2Value = "text/html"
let headers = [
header1Name: header1Value,
header2Name: header2Value
]
let request = HTTPRequest(url: url, headers: headers)

_ = try? await httpClient.perform(request: request)

let lastURLRequest = try #require(MockURLProtocol.lastRequest)
let result1 = lastURLRequest.value(forHTTPHeaderField: header1Name)
let result2 = lastURLRequest.value(forHTTPHeaderField: header2Name)

#expect(result1 == header1Value)
#expect(result2 == header2Value)
}
#endif

}
1 change: 1 addition & 0 deletions Tests/TMDbTests/TestUtils/Tags.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import Testing

extension Tag {

@Tag static var adapter: Self
@Tag static var domain: Self
@Tag static var networking: Self

Expand Down