From 27b206df36522718c100d8eb9253df67dc80388a Mon Sep 17 00:00:00 2001 From: Adam Young Date: Wed, 15 May 2024 19:51:08 +0100 Subject: [PATCH] TECH DEBT: Add tests for error scenarios in services (#177) * AuthenticationService and CertificationsService error tests * CompanyService error tests * ConfigurationService error tests * DiscoverService, GenreService and MovieService error tests * PersonService error tests * SearchService error tests * TrendingService error tests * TVEpisodesService error tests * TVSeasonService error tests * TVSeriesService and WatchProviderService error tests * Break up MovieServiceTests and TVSeriesTests * Tidy up * Fix Linux builds * Fix Linux builds * Fix Linux builds --- .../ConfigurationProviding.swift | 39 +++ .../Services/Account/AccountService.swift | 2 +- .../Services/Account/FavouriteSort.swift | 16 - .../Services/Account/WatchlistSort.swift | 16 - .../AuthenticationService.swift | 2 +- .../URLBuilders/AuthenticateURLBuilder.swift | 16 +- .../Certifications/CertificationService.swift | 2 +- .../Services/Company/CompanyService.swift | 2 +- .../Configuration/ConfigurationService.swift | 2 +- .../Discover/DiscoverMovieFilter.swift | 44 +++ .../Services/Discover/DiscoverService.swift | 8 +- .../Requests/DiscoverMoviesRequest.swift | 14 +- .../Domain/Services/Genres/GenreService.swift | 2 +- .../Domain/Services/Movies/MovieService.swift | 2 +- .../Services/People/PersonService.swift | 2 +- .../Services/Search/SearchService.swift | 2 +- .../TVEpisodes/TVEpisodeService.swift | 2 +- .../Services/TVSeasons/TVSeasonService.swift | 2 +- .../Services/TVSeries/TVSeriesService.swift | 2 +- .../Services/Trending/TrendingService.swift | 2 +- .../WatchProviders/WatchProviderService.swift | 2 +- Sources/TMDb/Extensions/URL+QueryItem.swift | 136 -------- Sources/TMDb/TMDbConfiguration.swift | 2 +- Sources/TMDb/TMDbFactory.swift | 4 +- .../APIRequestQueryItemNameTests.swift | 85 +++++ .../Services/Account/FavouriteSortTests.swift | 18 - .../Services/Account/WatchlistSortTests.swift | 18 - .../AuthenticationServiceTests.swift | 38 +- .../AuthenticateURLBuilderTests.swift | 9 +- .../CertificationServiceTests.swift | 30 ++ .../Company/CompanyServiceTests.swift | 17 + .../ConfigurationServiceTests.swift | 60 ++++ .../Discover/DiscoverServiceTests.swift | 41 ++- .../Requests/DiscoverMoviesRequestTests.swift | 14 +- .../Services/Genres/GenreServiceTests.swift | 30 ++ .../Movies/MovieServiceCreditsTests.swift | 81 +++++ .../Movies/MovieServiceDetailsTests.swift | 81 +++++ ...sts.swift => MovieServiceListsTests.swift} | 239 +++++-------- .../Movies/MovieServiceMediaTests.swift | 124 +++++++ .../Movies/MovieServiceOthersTests.swift | 98 ++++++ .../Movies/MovieServiceReviewsTests.swift | 82 +++++ .../Services/People/PersonServiceTests.swift | 111 ++++++ .../Services/Search/SearchServiceTests.swift | 64 ++++ .../TVEpisodes/TVEpisodeServiceTests.swift | 66 ++++ .../TVSeasons/TVSeasonServiceTests.swift | 85 +++++ .../TVSeriesServiceCreditsTests.swift | 122 +++++++ .../TVSeriesServiceDetailsTests.swift | 81 +++++ .../TVSeries/TVSeriesServiceListsTests.swift | 163 +++++++++ .../TVSeries/TVSeriesServiceMediaTests.swift | 124 +++++++ .../TVSeries/TVSeriesServiceOthersTests.swift | 97 ++++++ .../TVSeriesServiceReviewsTests.swift | 81 +++++ .../TVSeries/TVSeriesServiceTests.swift | 293 ---------------- .../Trending/TrendingServiceTests.swift | 48 +++ .../WatchProviderServiceTests.swift | 45 +++ .../Extensions/URL+QueryItemTests.swift | 329 ------------------ 55 files changed, 2073 insertions(+), 1024 deletions(-) create mode 100644 Sources/TMDb/Domain/ConfigurationProvider/ConfigurationProviding.swift create mode 100644 Sources/TMDb/Domain/Services/Discover/DiscoverMovieFilter.swift delete mode 100644 Sources/TMDb/Extensions/URL+QueryItem.swift create mode 100644 Tests/TMDbTests/Domain/APIClient/APIRequestQueryItemNameTests.swift create mode 100644 Tests/TMDbTests/Domain/Services/Movies/MovieServiceCreditsTests.swift create mode 100644 Tests/TMDbTests/Domain/Services/Movies/MovieServiceDetailsTests.swift rename Tests/TMDbTests/Domain/Services/Movies/{MovieServiceTests.swift => MovieServiceListsTests.swift} (53%) create mode 100644 Tests/TMDbTests/Domain/Services/Movies/MovieServiceMediaTests.swift create mode 100644 Tests/TMDbTests/Domain/Services/Movies/MovieServiceOthersTests.swift create mode 100644 Tests/TMDbTests/Domain/Services/Movies/MovieServiceReviewsTests.swift create mode 100644 Tests/TMDbTests/Domain/Services/TVSeries/TVSeriesServiceCreditsTests.swift create mode 100644 Tests/TMDbTests/Domain/Services/TVSeries/TVSeriesServiceDetailsTests.swift create mode 100644 Tests/TMDbTests/Domain/Services/TVSeries/TVSeriesServiceListsTests.swift create mode 100644 Tests/TMDbTests/Domain/Services/TVSeries/TVSeriesServiceMediaTests.swift create mode 100644 Tests/TMDbTests/Domain/Services/TVSeries/TVSeriesServiceOthersTests.swift create mode 100644 Tests/TMDbTests/Domain/Services/TVSeries/TVSeriesServiceReviewsTests.swift delete mode 100644 Tests/TMDbTests/Domain/Services/TVSeries/TVSeriesServiceTests.swift delete mode 100644 Tests/TMDbTests/Extensions/URL+QueryItemTests.swift diff --git a/Sources/TMDb/Domain/ConfigurationProvider/ConfigurationProviding.swift b/Sources/TMDb/Domain/ConfigurationProvider/ConfigurationProviding.swift new file mode 100644 index 00000000..02c02e6c --- /dev/null +++ b/Sources/TMDb/Domain/ConfigurationProvider/ConfigurationProviding.swift @@ -0,0 +1,39 @@ +// +// ConfigurationProviding.swift +// TMDb +// +// Copyright © 2024 Adam Young. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an AS IS BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +import Foundation + +/// +/// An interface to provide configuration for service. +/// +/// Create an API key at [https://www.themoviedb.org/documentation/api](https://www.themoviedb.org/documentation/api). +/// +public protocol ConfigurationProviding { + + /// + /// TMDb API key. + /// + var apiKey: String { get } + + /// + /// The HTTP client adapter for making HTTP requests. + /// + var httpClient: any HTTPClient { get } + +} diff --git a/Sources/TMDb/Domain/Services/Account/AccountService.swift b/Sources/TMDb/Domain/Services/Account/AccountService.swift index fdaab8d0..295422f2 100644 --- a/Sources/TMDb/Domain/Services/Account/AccountService.swift +++ b/Sources/TMDb/Domain/Services/Account/AccountService.swift @@ -34,7 +34,7 @@ public final class AccountService { /// /// - Parameter configuration: A TMDb configuration object. /// - public convenience init(configuration: TMDbConfiguration) { + public convenience init(configuration: some ConfigurationProviding) { self.init( apiClient: TMDbFactory.apiClient(configuration: configuration) ) diff --git a/Sources/TMDb/Domain/Services/Account/FavouriteSort.swift b/Sources/TMDb/Domain/Services/Account/FavouriteSort.swift index 5a504ee7..1197c974 100644 --- a/Sources/TMDb/Domain/Services/Account/FavouriteSort.swift +++ b/Sources/TMDb/Domain/Services/Account/FavouriteSort.swift @@ -52,19 +52,3 @@ extension FavouriteSort { } } - -extension URL { - - private enum QueryItemName { - static let sortBy = "sort_by" - } - - func appendingSortBy(_ sortBy: FavouriteSort?) -> Self { - guard let sortBy else { - return self - } - - return appendingQueryItem(name: QueryItemName.sortBy, value: sortBy) - } - -} diff --git a/Sources/TMDb/Domain/Services/Account/WatchlistSort.swift b/Sources/TMDb/Domain/Services/Account/WatchlistSort.swift index 83caf8bd..f14e2f54 100644 --- a/Sources/TMDb/Domain/Services/Account/WatchlistSort.swift +++ b/Sources/TMDb/Domain/Services/Account/WatchlistSort.swift @@ -52,19 +52,3 @@ extension WatchlistSort { } } - -extension URL { - - private enum QueryItemName { - static let sortBy = "sort_by" - } - - func appendingSortBy(_ sortBy: WatchlistSort?) -> Self { - guard let sortBy else { - return self - } - - return appendingQueryItem(name: QueryItemName.sortBy, value: sortBy) - } - -} diff --git a/Sources/TMDb/Domain/Services/Authentication/AuthenticationService.swift b/Sources/TMDb/Domain/Services/Authentication/AuthenticationService.swift index cc2a992f..ad5518a7 100644 --- a/Sources/TMDb/Domain/Services/Authentication/AuthenticationService.swift +++ b/Sources/TMDb/Domain/Services/Authentication/AuthenticationService.swift @@ -36,7 +36,7 @@ public final class AuthenticationService { /// /// - Parameter configuration: A TMDb configuration object. /// - public convenience init(configuration: TMDbConfiguration) { + public convenience init(configuration: some ConfigurationProviding) { self.init( apiClient: TMDbFactory.authAPIClient(configuration: configuration), authenticateURLBuilder: TMDbFactory.authenticateURLBuilder() diff --git a/Sources/TMDb/Domain/Services/Authentication/URLBuilders/AuthenticateURLBuilder.swift b/Sources/TMDb/Domain/Services/Authentication/URLBuilders/AuthenticateURLBuilder.swift index 72f153d2..2b0523b5 100644 --- a/Sources/TMDb/Domain/Services/Authentication/URLBuilders/AuthenticateURLBuilder.swift +++ b/Sources/TMDb/Domain/Services/Authentication/URLBuilders/AuthenticateURLBuilder.swift @@ -32,15 +32,25 @@ final class AuthenticateURLBuilder: AuthenticateURLBuilding { } func authenticateURL(with requestToken: String, redirectURL: URL?) -> URL { - var url = baseURL + let url = baseURL .appendingPathComponent("authenticate") .appendingPathComponent(requestToken) + guard var urlComponents = URLComponents(url: url, resolvingAgainstBaseURL: false) else { + return url + } + + var queryItems = urlComponents.queryItems ?? [] if let redirectURL { - url = url.appendingQueryItem(name: "redirect_to", value: redirectURL.absoluteString) + let queryItem = URLQueryItem(name: "redirect_to", value: redirectURL.absoluteString) + queryItems.append(queryItem) + } + + if !queryItems.isEmpty { + urlComponents.queryItems = queryItems } - return url + return urlComponents.url ?? url } } diff --git a/Sources/TMDb/Domain/Services/Certifications/CertificationService.swift b/Sources/TMDb/Domain/Services/Certifications/CertificationService.swift index d2842473..2ccdb1a0 100644 --- a/Sources/TMDb/Domain/Services/Certifications/CertificationService.swift +++ b/Sources/TMDb/Domain/Services/Certifications/CertificationService.swift @@ -32,7 +32,7 @@ public final class CertificationService { /// /// - Parameter configuration: A TMDb configuration object. /// - public convenience init(configuration: TMDbConfiguration) { + public convenience init(configuration: some ConfigurationProviding) { self.init( apiClient: TMDbFactory.apiClient(configuration: configuration) ) diff --git a/Sources/TMDb/Domain/Services/Company/CompanyService.swift b/Sources/TMDb/Domain/Services/Company/CompanyService.swift index 0ff6eb61..aa964ec8 100644 --- a/Sources/TMDb/Domain/Services/Company/CompanyService.swift +++ b/Sources/TMDb/Domain/Services/Company/CompanyService.swift @@ -32,7 +32,7 @@ public final class CompanyService { /// /// - Parameter configuration: A TMDb configuration object. /// - public convenience init(configuration: TMDbConfiguration) { + public convenience init(configuration: some ConfigurationProviding) { self.init( apiClient: TMDbFactory.apiClient(configuration: configuration) ) diff --git a/Sources/TMDb/Domain/Services/Configuration/ConfigurationService.swift b/Sources/TMDb/Domain/Services/Configuration/ConfigurationService.swift index a1557b22..aa3c1e74 100644 --- a/Sources/TMDb/Domain/Services/Configuration/ConfigurationService.swift +++ b/Sources/TMDb/Domain/Services/Configuration/ConfigurationService.swift @@ -32,7 +32,7 @@ public final class ConfigurationService { /// /// - Parameter configuration: A TMDb configuration object. /// - public convenience init(configuration: TMDbConfiguration) { + public convenience init(configuration: some ConfigurationProviding) { self.init( apiClient: TMDbFactory.apiClient(configuration: configuration) ) diff --git a/Sources/TMDb/Domain/Services/Discover/DiscoverMovieFilter.swift b/Sources/TMDb/Domain/Services/Discover/DiscoverMovieFilter.swift new file mode 100644 index 00000000..c3f019a0 --- /dev/null +++ b/Sources/TMDb/Domain/Services/Discover/DiscoverMovieFilter.swift @@ -0,0 +1,44 @@ +// +// DiscoverMovieFilter.swift +// TMDb +// +// Copyright © 2024 Adam Young. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an AS IS BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +import Foundation + +/// +/// A filter for discovering movies. +/// +public struct DiscoverMovieFilter { + + /// + /// A list of Person identifiers which to return only movies they have + /// appeared in. + /// + public let people: [Person.ID]? + + /// + /// Creates a discover movies filter. + /// + /// - Parameters: + /// - people: A list of Person identifiers which to return only + /// movies they have appeared in. + /// + public init(people: [Person.ID]? = nil) { + self.people = people + } + +} diff --git a/Sources/TMDb/Domain/Services/Discover/DiscoverService.swift b/Sources/TMDb/Domain/Services/Discover/DiscoverService.swift index babd3aa6..8e194826 100644 --- a/Sources/TMDb/Domain/Services/Discover/DiscoverService.swift +++ b/Sources/TMDb/Domain/Services/Discover/DiscoverService.swift @@ -32,7 +32,7 @@ public final class DiscoverService { /// /// - Parameter configuration: A TMDb configuration object. /// - public convenience init(configuration: TMDbConfiguration) { + public convenience init(configuration: some ConfigurationProviding) { self.init( apiClient: TMDbFactory.apiClient(configuration: configuration) ) @@ -50,8 +50,8 @@ public final class DiscoverService { /// - Precondition: `page` can be between `1` and `1000`. /// /// - Parameters: + /// - filter: Movie filter. /// - sortedBy: How results should be sorted. - /// - people: A list of Person identifiers which to return only movies they have appeared in. /// - page: The page of results to return. /// - language: ISO 639-1 language code to display results in. Defaults to `en`. /// @@ -60,14 +60,14 @@ public final class DiscoverService { /// - Returns: Matching movies as a pageable list. /// public func movies( + filter: DiscoverMovieFilter? = nil, sortedBy: MovieSort? = nil, - withPeople people: [Person.ID]? = nil, page: Int? = nil, language: String? = nil ) async throws -> MoviePageableList { let request = DiscoverMoviesRequest( + people: filter?.people, sortedBy: sortedBy, - people: people, page: page, language: language ) diff --git a/Sources/TMDb/Domain/Services/Discover/Requests/DiscoverMoviesRequest.swift b/Sources/TMDb/Domain/Services/Discover/Requests/DiscoverMoviesRequest.swift index a1ddecf1..db893ba9 100644 --- a/Sources/TMDb/Domain/Services/Discover/Requests/DiscoverMoviesRequest.swift +++ b/Sources/TMDb/Domain/Services/Discover/Requests/DiscoverMoviesRequest.swift @@ -22,15 +22,15 @@ import Foundation final class DiscoverMoviesRequest: DecodableAPIRequest { init( - sortedBy: MovieSort? = nil, people: [Person.ID]? = nil, + sortedBy: MovieSort? = nil, page: Int? = nil, language: String? = nil ) { let path = "/discover/movie" let queryItems = APIRequestQueryItems( - sortedBy: sortedBy, people: people, + sortedBy: sortedBy, page: page, language: language ) @@ -43,21 +43,21 @@ final class DiscoverMoviesRequest: DecodableAPIRequest { private extension APIRequestQueryItems { init( - sortedBy: MovieSort?, people: [Person.ID]?, + sortedBy: MovieSort?, page: Int?, language: String? ) { self.init() - if let sortedBy { - self[.sortBy] = sortedBy - } - if let people { self[.withPeople] = Self.peopleQueryItemValue(for: people) } + if let sortedBy { + self[.sortBy] = sortedBy + } + if let page { self[.page] = page } diff --git a/Sources/TMDb/Domain/Services/Genres/GenreService.swift b/Sources/TMDb/Domain/Services/Genres/GenreService.swift index 1170d7a6..057eca75 100644 --- a/Sources/TMDb/Domain/Services/Genres/GenreService.swift +++ b/Sources/TMDb/Domain/Services/Genres/GenreService.swift @@ -32,7 +32,7 @@ public final class GenreService { /// /// - Parameter configuration: A TMDb configuration object. /// - public convenience init(configuration: TMDbConfiguration) { + public convenience init(configuration: some ConfigurationProviding) { self.init( apiClient: TMDbFactory.apiClient(configuration: configuration) ) diff --git a/Sources/TMDb/Domain/Services/Movies/MovieService.swift b/Sources/TMDb/Domain/Services/Movies/MovieService.swift index f8861a1e..c6a0f009 100644 --- a/Sources/TMDb/Domain/Services/Movies/MovieService.swift +++ b/Sources/TMDb/Domain/Services/Movies/MovieService.swift @@ -34,7 +34,7 @@ public final class MovieService { /// /// - Parameter configuration: A TMDb configuration object. /// - public convenience init(configuration: TMDbConfiguration) { + public convenience init(configuration: some ConfigurationProviding) { self.init( apiClient: TMDbFactory.apiClient(configuration: configuration) ) diff --git a/Sources/TMDb/Domain/Services/People/PersonService.swift b/Sources/TMDb/Domain/Services/People/PersonService.swift index 9c3d5c43..03c4b1ca 100644 --- a/Sources/TMDb/Domain/Services/People/PersonService.swift +++ b/Sources/TMDb/Domain/Services/People/PersonService.swift @@ -34,7 +34,7 @@ public final class PersonService { /// /// - Parameter configuration: A TMDb configuration object. /// - public convenience init(configuration: TMDbConfiguration) { + public convenience init(configuration: some ConfigurationProviding) { self.init( apiClient: TMDbFactory.apiClient(configuration: configuration) ) diff --git a/Sources/TMDb/Domain/Services/Search/SearchService.swift b/Sources/TMDb/Domain/Services/Search/SearchService.swift index cec7b7f2..3badde2f 100644 --- a/Sources/TMDb/Domain/Services/Search/SearchService.swift +++ b/Sources/TMDb/Domain/Services/Search/SearchService.swift @@ -32,7 +32,7 @@ public final class SearchService { /// /// - Parameter configuration: A TMDb configuration object. /// - public convenience init(configuration: TMDbConfiguration) { + public convenience init(configuration: some ConfigurationProviding) { self.init( apiClient: TMDbFactory.apiClient(configuration: configuration) ) diff --git a/Sources/TMDb/Domain/Services/TVEpisodes/TVEpisodeService.swift b/Sources/TMDb/Domain/Services/TVEpisodes/TVEpisodeService.swift index c2a9f373..effcb3d3 100644 --- a/Sources/TMDb/Domain/Services/TVEpisodes/TVEpisodeService.swift +++ b/Sources/TMDb/Domain/Services/TVEpisodes/TVEpisodeService.swift @@ -32,7 +32,7 @@ public final class TVEpisodeService { /// /// - Parameter configuration: A TMDb configuration object. /// - public convenience init(configuration: TMDbConfiguration) { + public convenience init(configuration: some ConfigurationProviding) { self.init( apiClient: TMDbFactory.apiClient(configuration: configuration) ) diff --git a/Sources/TMDb/Domain/Services/TVSeasons/TVSeasonService.swift b/Sources/TMDb/Domain/Services/TVSeasons/TVSeasonService.swift index b4803c8a..f874a5a3 100644 --- a/Sources/TMDb/Domain/Services/TVSeasons/TVSeasonService.swift +++ b/Sources/TMDb/Domain/Services/TVSeasons/TVSeasonService.swift @@ -32,7 +32,7 @@ public final class TVSeasonService { /// /// - Parameter configuration: A TMDb configuration object. /// - public convenience init(configuration: TMDbConfiguration) { + public convenience init(configuration: some ConfigurationProviding) { self.init( apiClient: TMDbFactory.apiClient(configuration: configuration) ) diff --git a/Sources/TMDb/Domain/Services/TVSeries/TVSeriesService.swift b/Sources/TMDb/Domain/Services/TVSeries/TVSeriesService.swift index 3c56d099..b3dd97cc 100644 --- a/Sources/TMDb/Domain/Services/TVSeries/TVSeriesService.swift +++ b/Sources/TMDb/Domain/Services/TVSeries/TVSeriesService.swift @@ -32,7 +32,7 @@ public final class TVSeriesService { /// /// - Parameter configuration: A TMDb configuration object. /// - public convenience init(configuration: TMDbConfiguration) { + public convenience init(configuration: some ConfigurationProviding) { self.init( apiClient: TMDbFactory.apiClient(configuration: configuration) ) diff --git a/Sources/TMDb/Domain/Services/Trending/TrendingService.swift b/Sources/TMDb/Domain/Services/Trending/TrendingService.swift index 438be470..f2799f2a 100644 --- a/Sources/TMDb/Domain/Services/Trending/TrendingService.swift +++ b/Sources/TMDb/Domain/Services/Trending/TrendingService.swift @@ -32,7 +32,7 @@ public final class TrendingService { /// /// - Parameter configuration: A TMDb configuration object. /// - public convenience init(configuration: TMDbConfiguration) { + public convenience init(configuration: some ConfigurationProviding) { self.init( apiClient: TMDbFactory.apiClient(configuration: configuration) ) diff --git a/Sources/TMDb/Domain/Services/WatchProviders/WatchProviderService.swift b/Sources/TMDb/Domain/Services/WatchProviders/WatchProviderService.swift index 6a96a736..35127a77 100644 --- a/Sources/TMDb/Domain/Services/WatchProviders/WatchProviderService.swift +++ b/Sources/TMDb/Domain/Services/WatchProviders/WatchProviderService.swift @@ -32,7 +32,7 @@ public final class WatchProviderService { /// /// - Parameter configuration: A TMDb configuration object. /// - public convenience init(configuration: TMDbConfiguration) { + public convenience init(configuration: some ConfigurationProviding) { self.init( apiClient: TMDbFactory.apiClient(configuration: configuration) ) diff --git a/Sources/TMDb/Extensions/URL+QueryItem.swift b/Sources/TMDb/Extensions/URL+QueryItem.swift deleted file mode 100644 index d61701bc..00000000 --- a/Sources/TMDb/Extensions/URL+QueryItem.swift +++ /dev/null @@ -1,136 +0,0 @@ -// -// URL+QueryItem.swift -// TMDb -// -// Copyright © 2024 Adam Young. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an AS IS BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// - -import Foundation - -extension URL { - - func appendingPathComponent(_ value: Int) -> Self { - appendingPathComponent(String(value)) - } - - func appendingQueryItem(name: String, value: some CustomStringConvertible) -> Self { - var urlComponents = URLComponents(url: self, resolvingAgainstBaseURL: false)! - var queryItems = urlComponents.queryItems ?? [] - queryItems.append(URLQueryItem(name: name, value: value.description)) - urlComponents.queryItems = queryItems - return urlComponents.url! - } - - func apendingQueryItems(_ queryItems: [String: (any CustomStringConvertible)?]) -> Self { - queryItems.reduce(self) { - guard let queryItemValue = $1.1 else { - return $0 - } - - return $0.appendingQueryItem(name: $1.key, value: queryItemValue) - } - } - -} - -extension URL { - - private enum QueryItemName { - static let apiKey = "api_key" - static let language = "language" - static let imageLanguage = "include_image_language" - static let videoLanguage = "include_video_language" - static let page = "page" - static let year = "year" - static let firstAirDateYear = "first_air_date_year" - static let withPeople = "with_people" - } - - func appendingAPIKey(_ apiKey: String) -> Self { - appendingQueryItem(name: QueryItemName.apiKey, value: apiKey) - } - - func appendingLanguage(_ languageCode: String?) -> Self { - guard let languageCode else { - return self - } - - return appendingQueryItem(name: QueryItemName.language, value: languageCode) - } - - func appendingImageLanguage(_ languageCode: String?) -> Self { - guard let languageCode else { - return self - } - - let value = [languageCode, "null"] - .map(\.description) - .joined(separator: ",") - - return appendingQueryItem(name: QueryItemName.imageLanguage, value: value) - } - - func appendingVideoLanguage(_ languageCode: String?) -> Self { - guard let languageCode else { - return self - } - - let value = [languageCode, "null"] - .map(\.description) - .joined(separator: ",") - - return appendingQueryItem(name: QueryItemName.videoLanguage, value: value) - } - - func appendingPage(_ page: Int?) -> Self { - guard var page else { - return self - } - - page = max(page, 1) - page = min(page, 1000) - - return appendingQueryItem(name: QueryItemName.page, value: page) - } - - func appendingYear(_ year: Int?) -> Self { - guard let year else { - return self - } - - return appendingQueryItem(name: QueryItemName.year, value: year) - } - - func appendingFirstAirDateYear(_ year: Int?) -> Self { - guard let year else { - return self - } - - return appendingQueryItem(name: QueryItemName.firstAirDateYear, value: year) - } - - func appendingWithPeople(_ peopleIDs: [Person.ID]?) -> Self { - guard let peopleIDs else { - return self - } - - let value = peopleIDs - .map(\.description) - .joined(separator: ",") - - return appendingQueryItem(name: QueryItemName.withPeople, value: value) - } - -} diff --git a/Sources/TMDb/TMDbConfiguration.swift b/Sources/TMDb/TMDbConfiguration.swift index 4040751d..fe079b4d 100644 --- a/Sources/TMDb/TMDbConfiguration.swift +++ b/Sources/TMDb/TMDbConfiguration.swift @@ -24,7 +24,7 @@ import Foundation /// /// Create an API key at [https://www.themoviedb.org/documentation/api](https://www.themoviedb.org/documentation/api). /// -public final class TMDbConfiguration: Sendable { +public final class TMDbConfiguration: ConfigurationProviding, Sendable { /// /// TMDb API key. diff --git a/Sources/TMDb/TMDbFactory.swift b/Sources/TMDb/TMDbFactory.swift index 464490cd..495a3d3e 100644 --- a/Sources/TMDb/TMDbFactory.swift +++ b/Sources/TMDb/TMDbFactory.swift @@ -35,7 +35,7 @@ final class TMDbFactory { extension TMDbFactory { - static func apiClient(configuration: TMDbConfiguration) -> some APIClient { + static func apiClient(configuration: some ConfigurationProviding) -> some APIClient { TMDbAPIClient( apiKey: configuration.apiKey, baseURL: tmdbAPIBaseURL, @@ -44,7 +44,7 @@ extension TMDbFactory { ) } - static func authAPIClient(configuration: TMDbConfiguration) -> some APIClient { + static func authAPIClient(configuration: some ConfigurationProviding) -> some APIClient { TMDbAPIClient( apiKey: configuration.apiKey, baseURL: .tmdbAPIBaseURL, diff --git a/Tests/TMDbTests/Domain/APIClient/APIRequestQueryItemNameTests.swift b/Tests/TMDbTests/Domain/APIClient/APIRequestQueryItemNameTests.swift new file mode 100644 index 00000000..8c7cae6f --- /dev/null +++ b/Tests/TMDbTests/Domain/APIClient/APIRequestQueryItemNameTests.swift @@ -0,0 +1,85 @@ +// +// APIRequestQueryItemNameTests.swift +// TMDb +// +// Copyright © 2024 Adam Young. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an AS IS BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +@testable import TMDb +import XCTest + +final class APIRequestQueryItemNameTests: XCTestCase { + + func testPageName() { + XCTAssertEqual(APIRequestQueryItem.Name.page, "page") + } + + func testSortByName() { + XCTAssertEqual(APIRequestQueryItem.Name.sortBy, "sort_by") + } + + func testWithPeopleName() { + XCTAssertEqual(APIRequestQueryItem.Name.withPeople, "with_people") + } + + func testWatchRegionName() { + XCTAssertEqual(APIRequestQueryItem.Name.watchRegion, "watch_region") + } + + func testIncludeImageLanguageName() { + XCTAssertEqual(APIRequestQueryItem.Name.includeImageLanguage, "include_image_language") + } + + func testIncludeVideoLanguageName() { + XCTAssertEqual(APIRequestQueryItem.Name.includeVideoLanguage, "include_video_language") + } + + func testIncludeAdultName() { + XCTAssertEqual(APIRequestQueryItem.Name.includeAdult, "include_adult") + } + + func testQueryName() { + XCTAssertEqual(APIRequestQueryItem.Name.query, "query") + } + + func testYearName() { + XCTAssertEqual(APIRequestQueryItem.Name.year, "year") + } + + func testPrimaryReleaseYearName() { + XCTAssertEqual(APIRequestQueryItem.Name.primaryReleaseYear, "primary_release_year") + } + + func testFirstAirDateYearName() { + XCTAssertEqual(APIRequestQueryItem.Name.firstAirDateYear, "first_air_date_year") + } + + func testSessionIDName() { + XCTAssertEqual(APIRequestQueryItem.Name.sessionID, "session_id") + } + + func testLanguageName() { + XCTAssertEqual(APIRequestQueryItem.Name.language, "language") + } + + func testRegionName() { + XCTAssertEqual(APIRequestQueryItem.Name.region, "region") + } + + func testAPIKeyName() { + XCTAssertEqual(APIRequestQueryItem.Name.apiKey, "api_key") + } + +} diff --git a/Tests/TMDbTests/Domain/Services/Account/FavouriteSortTests.swift b/Tests/TMDbTests/Domain/Services/Account/FavouriteSortTests.swift index c90039d9..7638e5fb 100644 --- a/Tests/TMDbTests/Domain/Services/Account/FavouriteSortTests.swift +++ b/Tests/TMDbTests/Domain/Services/Account/FavouriteSortTests.swift @@ -34,22 +34,4 @@ final class FavouriteSortTests: XCTestCase { XCTAssertEqual(FavouriteSort.createdAt(descending: true).description, "created_at.desc") } - func testURLAppendingSortByWhenNilReturnsOriginalURL() throws { - let sort: FavouriteSort? = nil - let expectedURL = try XCTUnwrap(URL(string: "/some/path")) - - let url = URL(string: "/some/path")?.appendingSortBy(sort) - - XCTAssertEqual(url, expectedURL) - } - - func testURLAppendingSortByReturnsURL() throws { - let sort: FavouriteSort? = .createdAt() - let expectedURL = try XCTUnwrap(URL(string: "/some/path?sort_by=created_at.asc")) - - let url = URL(string: "/some/path")?.appendingSortBy(sort) - - XCTAssertEqual(url, expectedURL) - } - } diff --git a/Tests/TMDbTests/Domain/Services/Account/WatchlistSortTests.swift b/Tests/TMDbTests/Domain/Services/Account/WatchlistSortTests.swift index 9a181a6d..087acfc3 100644 --- a/Tests/TMDbTests/Domain/Services/Account/WatchlistSortTests.swift +++ b/Tests/TMDbTests/Domain/Services/Account/WatchlistSortTests.swift @@ -34,22 +34,4 @@ final class WatchlistSortTests: XCTestCase { XCTAssertEqual(WatchlistSort.createdAt(descending: true).description, "created_at.desc") } - func testURLAppendingSortByWhenNilReturnsOriginalURL() throws { - let sort: WatchlistSort? = nil - let expectedURL = try XCTUnwrap(URL(string: "/some/path")) - - let url = URL(string: "/some/path")?.appendingSortBy(sort) - - XCTAssertEqual(url, expectedURL) - } - - func testURLAppendingSortByReturnsURL() throws { - let sort: WatchlistSort? = .createdAt() - let expectedURL = try XCTUnwrap(URL(string: "/some/path?sort_by=created_at.asc")) - - let url = URL(string: "/some/path")?.appendingSortBy(sort) - - XCTAssertEqual(url, expectedURL) - } - } diff --git a/Tests/TMDbTests/Domain/Services/Authentication/AuthenticationServiceTests.swift b/Tests/TMDbTests/Domain/Services/Authentication/AuthenticationServiceTests.swift index dcb2e772..93e115f2 100644 --- a/Tests/TMDbTests/Domain/Services/Authentication/AuthenticationServiceTests.swift +++ b/Tests/TMDbTests/Domain/Services/Authentication/AuthenticationServiceTests.swift @@ -132,11 +132,28 @@ final class AuthenticationServiceTests: XCTestCase { } func testCreateSessionWithTokenWhenErrorsThrowsError() async throws { + let token = Token(success: true, requestToken: "abc123", expiresAt: Date(timeIntervalSince1970: 1_705_956_596)) apiClient.addResponse(.failure(.unknown)) var error: Error? do { - _ = try await service.requestToken() + _ = try await service.createSession(withToken: token) + } catch let err { + error = err + } + + let tmdbAPIError = try XCTUnwrap(error as? TMDbError) + + XCTAssertEqual(tmdbAPIError, .unknown) + } + + func testCreateSessionWithTokenWhenRequestTokenErrorsThrowsError() async throws { + let token = Token(success: true, requestToken: "abc123", expiresAt: Date(timeIntervalSince1970: 1_705_956_596)) + apiClient.addResponse(.failure(.unknown)) + + var error: Error? + do { + _ = try await service.createSession(withToken: token) } catch let err { error = err } @@ -177,6 +194,25 @@ final class AuthenticationServiceTests: XCTestCase { XCTAssertEqual(createSessionRequest, expectedCreateSessionRequest) } + func testCreateSessionWithCredentialWhenValidateTokenErrorsThrowsError() async throws { + let credential = Credential(username: "test", password: "pass123") + let token = Token.mock() + + apiClient.addResponse(.success(token)) + apiClient.addResponse(.failure(.unknown)) + + var error: Error? + do { + _ = try await service.createSession(withCredential: credential) + } catch let err { + error = err + } + + let tmdbAPIError = try XCTUnwrap(error as? TMDbError) + + XCTAssertEqual(tmdbAPIError, .unknown) + } + func testDeleteSessionWhenSuccessfulReturnsTrue() async throws { let response = SuccessResult(success: true) let session = Session.mock() diff --git a/Tests/TMDbTests/Domain/Services/Authentication/URLBuilders/AuthenticateURLBuilderTests.swift b/Tests/TMDbTests/Domain/Services/Authentication/URLBuilders/AuthenticateURLBuilderTests.swift index 1f88657e..0bd10fff 100644 --- a/Tests/TMDbTests/Domain/Services/Authentication/URLBuilders/AuthenticateURLBuilderTests.swift +++ b/Tests/TMDbTests/Domain/Services/Authentication/URLBuilders/AuthenticateURLBuilderTests.swift @@ -51,10 +51,11 @@ final class AuthenticateURLBuilderTests: XCTestCase { func testAuthenticateURLWithRedirectURLReturnsURL() throws { let requestToken = "qwertyuiop" let redirectURL = try XCTUnwrap(URL(string: "https://my.domain.com/auth/callback")) - let expectedURL = baseURL - .appendingPathComponent("authenticate") - .appendingPathComponent(requestToken) - .appendingQueryItem(name: "redirect_to", value: redirectURL.absoluteString) + let expectedURL = try XCTUnwrap( + URL( + string: "https://some.domain.com/authenticate/\(requestToken)?redirect_to=\(redirectURL.absoluteString)" + ) + ) let url = builder.authenticateURL(with: requestToken, redirectURL: redirectURL) diff --git a/Tests/TMDbTests/Domain/Services/Certifications/CertificationServiceTests.swift b/Tests/TMDbTests/Domain/Services/Certifications/CertificationServiceTests.swift index 0d1cda44..4246d256 100644 --- a/Tests/TMDbTests/Domain/Services/Certifications/CertificationServiceTests.swift +++ b/Tests/TMDbTests/Domain/Services/Certifications/CertificationServiceTests.swift @@ -50,6 +50,21 @@ final class CertificationServiceTests: XCTestCase { XCTAssertEqual(apiClient.lastRequest as? MovieCertificationsRequest, expectedRequest) } + func testMovieCertificationsWhenErrosThrowError() async throws { + apiClient.addResponse(.failure(.unknown)) + + var error: Error? + do { + _ = try await service.movieCertifications() + } catch let err { + error = err + } + + let tmdbAPIError = try XCTUnwrap(error as? TMDbError) + + XCTAssertEqual(tmdbAPIError, .unknown) + } + func testTVSeriesCertificationsReturnsTVSeriesCertifications() async throws { let certifications = Certifications.gbAndUS let expectedResult = certifications.certifications @@ -63,4 +78,19 @@ final class CertificationServiceTests: XCTestCase { XCTAssertEqual(apiClient.lastRequest as? TVSeriesCertificationsRequest, expectedRequest) } + func testTVSeriesCertificationsWhenErrorsThrowsError() async throws { + apiClient.addResponse(.failure(.unknown)) + + var error: Error? + do { + _ = try await service.tvSeriesCertifications() + } catch let err { + error = err + } + + let tmdbAPIError = try XCTUnwrap(error as? TMDbError) + + XCTAssertEqual(tmdbAPIError, .unknown) + } + } diff --git a/Tests/TMDbTests/Domain/Services/Company/CompanyServiceTests.swift b/Tests/TMDbTests/Domain/Services/Company/CompanyServiceTests.swift index 982aeb8d..e9fb3dd2 100644 --- a/Tests/TMDbTests/Domain/Services/Company/CompanyServiceTests.swift +++ b/Tests/TMDbTests/Domain/Services/Company/CompanyServiceTests.swift @@ -50,4 +50,21 @@ final class CompanyServiceTests: XCTestCase { XCTAssertEqual(apiClient.lastRequest as? CompanyDetailsRequest, expectedRequest) } + func testDetailsWhenErrorsThrowsError() async throws { + let companyID = 1 + + apiClient.addResponse(.failure(.unknown)) + + var error: Error? + do { + _ = try await service.details(forCompany: companyID) + } catch let err { + error = err + } + + let tmdbAPIError = try XCTUnwrap(error as? TMDbError) + + XCTAssertEqual(tmdbAPIError, .unknown) + } + } diff --git a/Tests/TMDbTests/Domain/Services/Configuration/ConfigurationServiceTests.swift b/Tests/TMDbTests/Domain/Services/Configuration/ConfigurationServiceTests.swift index 05ff4224..e3420a3a 100644 --- a/Tests/TMDbTests/Domain/Services/Configuration/ConfigurationServiceTests.swift +++ b/Tests/TMDbTests/Domain/Services/Configuration/ConfigurationServiceTests.swift @@ -48,6 +48,21 @@ final class ConfigurationServiceTests: XCTestCase { XCTAssertEqual(apiClient.lastRequest as? APIConfigurationRequest, expectedRequest) } + func testAPIConfigurationWhenErrorsThrowsError() async throws { + apiClient.addResponse(.failure(.unknown)) + + var error: Error? + do { + _ = try await service.apiConfiguration() + } catch let err { + error = err + } + + let tmdbAPIError = try XCTUnwrap(error as? TMDbError) + + XCTAssertEqual(tmdbAPIError, .unknown) + } + func testCountriesReturnsCountries() async throws { let expectedResult = [Country].mocks apiClient.addResponse(.success(expectedResult)) @@ -71,6 +86,21 @@ final class ConfigurationServiceTests: XCTestCase { XCTAssertEqual(apiClient.lastRequest as? CountriesConfigurationRequest, expectedRequest) } + func testCountriesWhenErrorsThrowsError() async throws { + apiClient.addResponse(.failure(.unknown)) + + var error: Error? + do { + _ = try await service.countries() + } catch let err { + error = err + } + + let tmdbAPIError = try XCTUnwrap(error as? TMDbError) + + XCTAssertEqual(tmdbAPIError, .unknown) + } + func testJobsByDepartmentReturnsDepartments() async throws { let expectedResult = [Department].mocks apiClient.addResponse(.success(expectedResult)) @@ -82,6 +112,21 @@ final class ConfigurationServiceTests: XCTestCase { XCTAssertEqual(apiClient.lastRequest as? JobsConfigurationRequest, expectedRequest) } + func testJobsByDepartmentWhenErrorsThrows() async throws { + apiClient.addResponse(.failure(.unknown)) + + var error: Error? + do { + _ = try await service.jobsByDepartment() + } catch let err { + error = err + } + + let tmdbAPIError = try XCTUnwrap(error as? TMDbError) + + XCTAssertEqual(tmdbAPIError, .unknown) + } + func testLanguagesReturnsLanguages() async throws { let expectedResult = [Language].mocks apiClient.addResponse(.success(expectedResult)) @@ -93,4 +138,19 @@ final class ConfigurationServiceTests: XCTestCase { XCTAssertEqual(apiClient.lastRequest as? LanguaguesConfigurationRequest, expectedRequest) } + func testLanguagesWhenErrorsThrowsError() async throws { + apiClient.addResponse(.failure(.unknown)) + + var error: Error? + do { + _ = try await service.languages() + } catch let err { + error = err + } + + let tmdbAPIError = try XCTUnwrap(error as? TMDbError) + + XCTAssertEqual(tmdbAPIError, .unknown) + } + } diff --git a/Tests/TMDbTests/Domain/Services/Discover/DiscoverServiceTests.swift b/Tests/TMDbTests/Domain/Services/Discover/DiscoverServiceTests.swift index f61adcba..59ebbc9f 100644 --- a/Tests/TMDbTests/Domain/Services/Discover/DiscoverServiceTests.swift +++ b/Tests/TMDbTests/Domain/Services/Discover/DiscoverServiceTests.swift @@ -40,7 +40,7 @@ final class DiscoverServiceTests: XCTestCase { func testMoviesReturnsMovies() async throws { let expectedResult = MoviePageableList.mock() apiClient.addResponse(.success(expectedResult)) - let expectedRequest = DiscoverMoviesRequest(sortedBy: nil, people: nil, page: nil, language: nil) + let expectedRequest = DiscoverMoviesRequest(people: nil, sortedBy: nil, page: nil, language: nil) let result = try await service.movies() @@ -48,21 +48,37 @@ final class DiscoverServiceTests: XCTestCase { XCTAssertEqual(apiClient.lastRequest as? DiscoverMoviesRequest, expectedRequest) } - func testMoviesWithSortByAndWithPeopleAndPageAndLanguageReturnsMovies() async throws { - let sortBy = MovieSort.originalTitle(descending: false) + func testMoviesWithFilterAndSortByAndPageAndLanguageReturnsMovies() async throws { let people = [4, 5, 6, 7, 8] + let sortBy = MovieSort.originalTitle(descending: false) let expectedResult = MoviePageableList.mock() let page = expectedResult.page let language = "en" apiClient.addResponse(.success(expectedResult)) - let expectedRequest = DiscoverMoviesRequest(sortedBy: sortBy, people: people, page: page, language: language) + let expectedRequest = DiscoverMoviesRequest(people: people, sortedBy: sortBy, page: page, language: language) - let result = try await service.movies(sortedBy: sortBy, withPeople: people, page: page, language: language) + let filter = DiscoverMovieFilter(people: people) + let result = try await service.movies(filter: filter, sortedBy: sortBy, page: page, language: language) XCTAssertEqual(result, expectedResult) XCTAssertEqual(apiClient.lastRequest as? DiscoverMoviesRequest, expectedRequest) } + func testMoviesWhenErrorsThrowsError() async throws { + apiClient.addResponse(.failure(.unknown)) + + var error: Error? + do { + _ = try await service.movies() + } catch let err { + error = err + } + + let tmdbAPIError = try XCTUnwrap(error as? TMDbError) + + XCTAssertEqual(tmdbAPIError, .unknown) + } + func testTVSeriesReturnsTVSeries() async throws { let expectedResult = TVSeriesPageableList.mock() apiClient.addResponse(.success(expectedResult)) @@ -88,4 +104,19 @@ final class DiscoverServiceTests: XCTestCase { XCTAssertEqual(apiClient.lastRequest as? DiscoverTVSeriesRequest, expectedRequest) } + func testTVSeriesWhenErrorsThrowsError() async throws { + apiClient.addResponse(.failure(.unknown)) + + var error: Error? + do { + _ = try await service.tvSeries() + } catch let err { + error = err + } + + let tmdbAPIError = try XCTUnwrap(error as? TMDbError) + + XCTAssertEqual(tmdbAPIError, .unknown) + } + } diff --git a/Tests/TMDbTests/Domain/Services/Discover/Requests/DiscoverMoviesRequestTests.swift b/Tests/TMDbTests/Domain/Services/Discover/Requests/DiscoverMoviesRequestTests.swift index a03cccbd..79e3bb15 100644 --- a/Tests/TMDbTests/Domain/Services/Discover/Requests/DiscoverMoviesRequestTests.swift +++ b/Tests/TMDbTests/Domain/Services/Discover/Requests/DiscoverMoviesRequestTests.swift @@ -34,18 +34,18 @@ final class DiscoverMoviesRequestTests: XCTestCase { XCTAssertTrue(request.queryItems.isEmpty) } - func testQueryItemsWithSortedBy() { - let request = DiscoverMoviesRequest(sortedBy: .originalTitle(descending: false)) - - XCTAssertEqual(request.queryItems, ["sort_by": "original_title.asc"]) - } - func testQueryItemsWithPeople() { let request = DiscoverMoviesRequest(people: [1, 2, 3]) XCTAssertEqual(request.queryItems, ["with_people": "1,2,3"]) } + func testQueryItemsWithSortedBy() { + let request = DiscoverMoviesRequest(sortedBy: .originalTitle(descending: false)) + + XCTAssertEqual(request.queryItems, ["sort_by": "original_title.asc"]) + } + func testQueryItemsWithPage() { let request = DiscoverMoviesRequest(page: 1) @@ -60,8 +60,8 @@ final class DiscoverMoviesRequestTests: XCTestCase { func testQueryItemsWithSortedByAndPeopleAndPageAndLanguage() { let request = DiscoverMoviesRequest( - sortedBy: .originalTitle(descending: false), people: [1, 2, 3], + sortedBy: .originalTitle(descending: false), page: 2, language: "en" ) diff --git a/Tests/TMDbTests/Domain/Services/Genres/GenreServiceTests.swift b/Tests/TMDbTests/Domain/Services/Genres/GenreServiceTests.swift index 57f3de2b..27d7c714 100644 --- a/Tests/TMDbTests/Domain/Services/Genres/GenreServiceTests.swift +++ b/Tests/TMDbTests/Domain/Services/Genres/GenreServiceTests.swift @@ -62,6 +62,21 @@ final class GenreServiceTests: XCTestCase { XCTAssertEqual(apiClient.lastRequest as? MovieGenresRequest, expectedRequest) } + func testMovieGenresWhenErrorsThrowsError() async throws { + apiClient.addResponse(.failure(.unknown)) + + var error: Error? + do { + _ = try await service.movieGenres() + } catch let err { + error = err + } + + let tmdbAPIError = try XCTUnwrap(error as? TMDbError) + + XCTAssertEqual(tmdbAPIError, .unknown) + } + func testTVSeriesGenresReturnsGenres() async throws { let genreList = GenreList.mock() let expectedResult = genreList.genres @@ -87,4 +102,19 @@ final class GenreServiceTests: XCTestCase { XCTAssertEqual(apiClient.lastRequest as? TVSeriesGenresRequest, expectedRequest) } + func testTVSeriesGenresWhenErrorsThrowsError() async throws { + apiClient.addResponse(.failure(.unknown)) + + var error: Error? + do { + _ = try await service.tvSeriesGenres() + } catch let err { + error = err + } + + let tmdbAPIError = try XCTUnwrap(error as? TMDbError) + + XCTAssertEqual(tmdbAPIError, .unknown) + } + } diff --git a/Tests/TMDbTests/Domain/Services/Movies/MovieServiceCreditsTests.swift b/Tests/TMDbTests/Domain/Services/Movies/MovieServiceCreditsTests.swift new file mode 100644 index 00000000..7690df6c --- /dev/null +++ b/Tests/TMDbTests/Domain/Services/Movies/MovieServiceCreditsTests.swift @@ -0,0 +1,81 @@ +// +// MovieServiceCreditsTests.swift +// TMDb +// +// Copyright © 2024 Adam Young. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an AS IS BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +@testable import TMDb +import XCTest + +final class MovieServiceCreditsTests: XCTestCase { + + var service: MovieService! + var apiClient: MockAPIClient! + + override func setUp() { + super.setUp() + apiClient = MockAPIClient() + service = MovieService(apiClient: apiClient) + } + + override func tearDown() { + apiClient = nil + service = nil + super.tearDown() + } + + func testCreditsReturnsCredits() async throws { + let expectedResult = ShowCredits.mock() + let movieID = expectedResult.id + apiClient.addResponse(.success(expectedResult)) + let expectedRequest = MovieCreditsRequest(id: movieID, language: nil) + + let result = try await service.credits(forMovie: movieID) + + XCTAssertEqual(result, expectedResult) + XCTAssertEqual(apiClient.lastRequest as? MovieCreditsRequest, expectedRequest) + } + + func testCreditsWithLanguageReturnsCredits() async throws { + let expectedResult = ShowCredits.mock() + let movieID = expectedResult.id + let language = "en" + apiClient.addResponse(.success(expectedResult)) + let expectedRequest = MovieCreditsRequest(id: movieID, language: language) + + let result = try await service.credits(forMovie: movieID, language: language) + + XCTAssertEqual(result, expectedResult) + XCTAssertEqual(apiClient.lastRequest as? MovieCreditsRequest, expectedRequest) + } + + func testCreditsWhenErrorsThrowsError() async throws { + let movieID = 1 + apiClient.addResponse(.failure(.unknown)) + + var error: Error? + do { + _ = try await service.credits(forMovie: movieID) + } catch let err { + error = err + } + + let tmdbAPIError = try XCTUnwrap(error as? TMDbError) + + XCTAssertEqual(tmdbAPIError, .unknown) + } + +} diff --git a/Tests/TMDbTests/Domain/Services/Movies/MovieServiceDetailsTests.swift b/Tests/TMDbTests/Domain/Services/Movies/MovieServiceDetailsTests.swift new file mode 100644 index 00000000..711de13d --- /dev/null +++ b/Tests/TMDbTests/Domain/Services/Movies/MovieServiceDetailsTests.swift @@ -0,0 +1,81 @@ +// +// MovieServiceDetailsTests.swift +// TMDb +// +// Copyright © 2024 Adam Young. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an AS IS BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +@testable import TMDb +import XCTest + +final class MovieServiceDetailsTests: XCTestCase { + + var service: MovieService! + var apiClient: MockAPIClient! + + override func setUp() { + super.setUp() + apiClient = MockAPIClient() + service = MovieService(apiClient: apiClient) + } + + override func tearDown() { + apiClient = nil + service = nil + super.tearDown() + } + + func testDetailsReturnsMovie() async throws { + let expectedResult = Movie.thorLoveAndThunder + let movieID = expectedResult.id + apiClient.addResponse(.success(expectedResult)) + let expectedRequest = MovieRequest(id: movieID, language: nil) + + let result = try await service.details(forMovie: movieID) + + XCTAssertEqual(result, expectedResult) + XCTAssertEqual(apiClient.lastRequest as? MovieRequest, expectedRequest) + } + + func testDetailsWithLanguageReturnsMovie() async throws { + let expectedResult = Movie.thorLoveAndThunder + let movieID = expectedResult.id + let language = "en" + apiClient.addResponse(.success(expectedResult)) + let expectedRequest = MovieRequest(id: movieID, language: language) + + let result = try await service.details(forMovie: movieID, language: language) + + XCTAssertEqual(result, expectedResult) + XCTAssertEqual(apiClient.lastRequest as? MovieRequest, expectedRequest) + } + + func testDetailsWhenErrorsThrowsError() async throws { + let movieID = 1 + apiClient.addResponse(.failure(.unknown)) + + var error: Error? + do { + _ = try await service.details(forMovie: movieID) + } catch let err { + error = err + } + + let tmdbAPIError = try XCTUnwrap(error as? TMDbError) + + XCTAssertEqual(tmdbAPIError, .unknown) + } + +} diff --git a/Tests/TMDbTests/Domain/Services/Movies/MovieServiceTests.swift b/Tests/TMDbTests/Domain/Services/Movies/MovieServiceListsTests.swift similarity index 53% rename from Tests/TMDbTests/Domain/Services/Movies/MovieServiceTests.swift rename to Tests/TMDbTests/Domain/Services/Movies/MovieServiceListsTests.swift index 1b45212b..e10d2634 100644 --- a/Tests/TMDbTests/Domain/Services/Movies/MovieServiceTests.swift +++ b/Tests/TMDbTests/Domain/Services/Movies/MovieServiceListsTests.swift @@ -1,5 +1,5 @@ // -// MovieServiceTests.swift +// MovieServiceListsTests.swift // TMDb // // Copyright © 2024 Adam Young. @@ -20,7 +20,7 @@ @testable import TMDb import XCTest -final class MovieServiceTests: XCTestCase { +final class MovieServiceListsTests: XCTestCase { var service: MovieService! var apiClient: MockAPIClient! @@ -37,134 +37,6 @@ final class MovieServiceTests: XCTestCase { super.tearDown() } - func testDetailsReturnsMovie() async throws { - let expectedResult = Movie.thorLoveAndThunder - let movieID = expectedResult.id - apiClient.addResponse(.success(expectedResult)) - let expectedRequest = MovieRequest(id: movieID, language: nil) - - let result = try await service.details(forMovie: movieID) - - XCTAssertEqual(result, expectedResult) - XCTAssertEqual(apiClient.lastRequest as? MovieRequest, expectedRequest) - } - - func testDetailsWithLanguageReturnsMovie() async throws { - let expectedResult = Movie.thorLoveAndThunder - let movieID = expectedResult.id - let language = "en" - apiClient.addResponse(.success(expectedResult)) - let expectedRequest = MovieRequest(id: movieID, language: language) - - let result = try await service.details(forMovie: movieID, language: language) - - XCTAssertEqual(result, expectedResult) - XCTAssertEqual(apiClient.lastRequest as? MovieRequest, expectedRequest) - } - - func testCreditsReturnsCredits() async throws { - let expectedResult = ShowCredits.mock() - let movieID = expectedResult.id - apiClient.addResponse(.success(expectedResult)) - let expectedRequest = MovieCreditsRequest(id: movieID, language: nil) - - let result = try await service.credits(forMovie: movieID) - - XCTAssertEqual(result, expectedResult) - XCTAssertEqual(apiClient.lastRequest as? MovieCreditsRequest, expectedRequest) - } - - func testCreditsWithLanguageReturnsCredits() async throws { - let expectedResult = ShowCredits.mock() - let movieID = expectedResult.id - let language = "en" - apiClient.addResponse(.success(expectedResult)) - let expectedRequest = MovieCreditsRequest(id: movieID, language: language) - - let result = try await service.credits(forMovie: movieID, language: language) - - XCTAssertEqual(result, expectedResult) - XCTAssertEqual(apiClient.lastRequest as? MovieCreditsRequest, expectedRequest) - } - - func testReviewsReturnsReviews() async throws { - let movieID = Int.randomID - let expectedResult = ReviewPageableList.mock() - apiClient.addResponse(.success(expectedResult)) - let expectedRequest = MovieReviewsRequest(id: movieID, page: nil, language: nil) - - let result = try await service.reviews(forMovie: movieID) - - XCTAssertEqual(result, expectedResult) - XCTAssertEqual(apiClient.lastRequest as? MovieReviewsRequest, expectedRequest) - } - - func testReviewsWithPageAndLanguageReturnsReviews() async throws { - let movieID = Int.randomID - let expectedResult = ReviewPageableList.mock() - let page = expectedResult.page - let language = "en" - apiClient.addResponse(.success(expectedResult)) - let expectedRequest = MovieReviewsRequest(id: movieID, page: page, language: language) - - let result = try await service.reviews(forMovie: movieID, page: page, language: language) - - XCTAssertEqual(result, expectedResult) - XCTAssertEqual(apiClient.lastRequest as? MovieReviewsRequest, expectedRequest) - } - - func testImagesReturnsImageCollection() async throws { - let expectedResult = ImageCollection.mock() - let movieID = expectedResult.id - apiClient.addResponse(.success(expectedResult)) - let expectedRequest = MovieImagesRequest(id: movieID, languages: nil) - - let result = try await service.images(forMovie: movieID) - - XCTAssertEqual(result, expectedResult) - XCTAssertEqual(apiClient.lastRequest as? MovieImagesRequest, expectedRequest) - } - - func testImagesWithFilterReturnsImageCollection() async throws { - let expectedResult = ImageCollection.mock() - let movieID = expectedResult.id - let languages = ["en-GB", "fr"] - apiClient.addResponse(.success(expectedResult)) - let expectedRequest = MovieImagesRequest(id: movieID, languages: languages) - - let filter = MovieImageFilter(languages: languages) - let result = try await service.images(forMovie: movieID, filter: filter) - - XCTAssertEqual(result, expectedResult) - XCTAssertEqual(apiClient.lastRequest as? MovieImagesRequest, expectedRequest) - } - - func testVideosReturnsVideoCollection() async throws { - let expectedResult = VideoCollection.mock() - let movieID = expectedResult.id - apiClient.addResponse(.success(expectedResult)) - let expectedRequest = MovieVideosRequest(id: movieID, languages: nil) - - let result = try await service.videos(forMovie: movieID) - - XCTAssertEqual(result, expectedResult) - XCTAssertEqual(apiClient.lastRequest as? MovieVideosRequest, expectedRequest) - } - - func testVideosWithFilterReturnsVideoCollection() async throws { - let expectedResult = VideoCollection.mock() - let movieID = expectedResult.id - let languages = ["en", "fr"] - apiClient.addResponse(.success(expectedResult)) - let expectedRequest = MovieVideosRequest(id: movieID, languages: languages) - - let filter = MovieVideoFilter(languages: languages) - let result = try await service.videos(forMovie: movieID, filter: filter) - - XCTAssertEqual(result, expectedResult) - XCTAssertEqual(apiClient.lastRequest as? MovieVideosRequest, expectedRequest) - } - func testRecommendationsReturnsMovies() async throws { let movieID = 1 let expectedResult = MoviePageableList.mock() @@ -191,6 +63,22 @@ final class MovieServiceTests: XCTestCase { XCTAssertEqual(apiClient.lastRequest as? MovieRecommendationsRequest, expectedRequest) } + func testRecommendationsWhenErrorsThrowsError() async throws { + let movieID = 1 + apiClient.addResponse(.failure(.unknown)) + + var error: Error? + do { + _ = try await service.recommendations(forMovie: movieID) + } catch let err { + error = err + } + + let tmdbAPIError = try XCTUnwrap(error as? TMDbError) + + XCTAssertEqual(tmdbAPIError, .unknown) + } + func testSimilarReturnsMovies() async throws { let movieID = 1 let expectedResult = MoviePageableList.mock() @@ -217,6 +105,22 @@ final class MovieServiceTests: XCTestCase { XCTAssertEqual(apiClient.lastRequest as? SimilarMoviesRequest, expectedRequest) } + func testSimilarWhenErrorsThrowsError() async throws { + let movieID = 1 + apiClient.addResponse(.failure(.unknown)) + + var error: Error? + do { + _ = try await service.similar(toMovie: movieID) + } catch let err { + error = err + } + + let tmdbAPIError = try XCTUnwrap(error as? TMDbError) + + XCTAssertEqual(tmdbAPIError, .unknown) + } + func testNowPlayingReturnsMovies() async throws { let expectedResult = MoviePageableList.mock() apiClient.addResponse(.success(expectedResult)) @@ -242,6 +146,21 @@ final class MovieServiceTests: XCTestCase { XCTAssertEqual(apiClient.lastRequest as? MoviesNowPlayingRequest, expectedRequest) } + func testNowPlayingWHenErrorsThrowsError() async throws { + apiClient.addResponse(.failure(.unknown)) + + var error: Error? + do { + _ = try await service.nowPlaying() + } catch let err { + error = err + } + + let tmdbAPIError = try XCTUnwrap(error as? TMDbError) + + XCTAssertEqual(tmdbAPIError, .unknown) + } + func testPopularReturnsMovies() async throws { let expectedResult = MoviePageableList.mock() apiClient.addResponse(.success(expectedResult)) @@ -267,6 +186,21 @@ final class MovieServiceTests: XCTestCase { XCTAssertEqual(apiClient.lastRequest as? PopularMoviesRequest, expectedRequest) } + func testPopularWhenErrorsThrowsError() async throws { + apiClient.addResponse(.failure(.unknown)) + + var error: Error? + do { + _ = try await service.popular() + } catch let err { + error = err + } + + let tmdbAPIError = try XCTUnwrap(error as? TMDbError) + + XCTAssertEqual(tmdbAPIError, .unknown) + } + func testTopRatedReturnsMovies() async throws { let expectedResult = MoviePageableList.mock() apiClient.addResponse(.success(expectedResult)) @@ -292,6 +226,21 @@ final class MovieServiceTests: XCTestCase { XCTAssertEqual(apiClient.lastRequest as? TopRatedMoviesRequest, expectedRequest) } + func testTopRatedWhenErrorsThrowsError() async throws { + apiClient.addResponse(.failure(.unknown)) + + var error: Error? + do { + _ = try await service.topRated() + } catch let err { + error = err + } + + let tmdbAPIError = try XCTUnwrap(error as? TMDbError) + + XCTAssertEqual(tmdbAPIError, .unknown) + } + func testUpcomingReturnsMovies() async throws { let expectedResult = MoviePageableList.mock() apiClient.addResponse(.success(expectedResult)) @@ -317,29 +266,19 @@ final class MovieServiceTests: XCTestCase { XCTAssertEqual(apiClient.lastRequest as? UpcomingMoviesRequest, expectedRequest) } - func testWatchProvidersReturnsWatchProviders() async throws { - let expectedResult = ShowWatchProviderResult.mock() - let movieID = 1 - let country = "GB" - apiClient.addResponse(.success(expectedResult)) - let expectedRequest = MovieWatchProvidersRequest(id: movieID) - - let result = try await service.watchProviders(forMovie: movieID, country: country) - - XCTAssertEqual(result, expectedResult.results[country]) - XCTAssertEqual(apiClient.lastRequest as? MovieWatchProvidersRequest, expectedRequest) - } + func testUpcomingWhenErrorsThrowsError() async throws { + apiClient.addResponse(.failure(.unknown)) - func testExternalLinksReturnsExternalLinks() async throws { - let expectedResult = MovieExternalLinksCollection.barbie - let movieID = 346_698 - apiClient.addResponse(.success(expectedResult)) - let expectedRequest = MovieExternalLinksRequest(id: movieID) + var error: Error? + do { + _ = try await service.upcoming() + } catch let err { + error = err + } - let result = try await service.externalLinks(forMovie: movieID) + let tmdbAPIError = try XCTUnwrap(error as? TMDbError) - XCTAssertEqual(result, expectedResult) - XCTAssertEqual(apiClient.lastRequest as? MovieExternalLinksRequest, expectedRequest) + XCTAssertEqual(tmdbAPIError, .unknown) } } diff --git a/Tests/TMDbTests/Domain/Services/Movies/MovieServiceMediaTests.swift b/Tests/TMDbTests/Domain/Services/Movies/MovieServiceMediaTests.swift new file mode 100644 index 00000000..33e99fd3 --- /dev/null +++ b/Tests/TMDbTests/Domain/Services/Movies/MovieServiceMediaTests.swift @@ -0,0 +1,124 @@ +// +// MovieServiceMediaTests.swift +// TMDb +// +// Copyright © 2024 Adam Young. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an AS IS BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +@testable import TMDb +import XCTest + +final class MovieServiceMediaTests: XCTestCase { + + var service: MovieService! + var apiClient: MockAPIClient! + + override func setUp() { + super.setUp() + apiClient = MockAPIClient() + service = MovieService(apiClient: apiClient) + } + + override func tearDown() { + apiClient = nil + service = nil + super.tearDown() + } + + func testImagesReturnsImageCollection() async throws { + let expectedResult = ImageCollection.mock() + let movieID = expectedResult.id + apiClient.addResponse(.success(expectedResult)) + let expectedRequest = MovieImagesRequest(id: movieID, languages: nil) + + let result = try await service.images(forMovie: movieID) + + XCTAssertEqual(result, expectedResult) + XCTAssertEqual(apiClient.lastRequest as? MovieImagesRequest, expectedRequest) + } + + func testImagesWithFilterReturnsImageCollection() async throws { + let expectedResult = ImageCollection.mock() + let movieID = expectedResult.id + let languages = ["en-GB", "fr"] + apiClient.addResponse(.success(expectedResult)) + let expectedRequest = MovieImagesRequest(id: movieID, languages: languages) + + let filter = MovieImageFilter(languages: languages) + let result = try await service.images(forMovie: movieID, filter: filter) + + XCTAssertEqual(result, expectedResult) + XCTAssertEqual(apiClient.lastRequest as? MovieImagesRequest, expectedRequest) + } + + func testImagesWhenErrorsThrowsError() async throws { + let movieID = 1 + apiClient.addResponse(.failure(.unknown)) + + var error: Error? + do { + _ = try await service.images(forMovie: movieID) + } catch let err { + error = err + } + + let tmdbAPIError = try XCTUnwrap(error as? TMDbError) + + XCTAssertEqual(tmdbAPIError, .unknown) + } + + func testVideosReturnsVideoCollection() async throws { + let expectedResult = VideoCollection.mock() + let movieID = expectedResult.id + apiClient.addResponse(.success(expectedResult)) + let expectedRequest = MovieVideosRequest(id: movieID, languages: nil) + + let result = try await service.videos(forMovie: movieID) + + XCTAssertEqual(result, expectedResult) + XCTAssertEqual(apiClient.lastRequest as? MovieVideosRequest, expectedRequest) + } + + func testVideosWithFilterReturnsVideoCollection() async throws { + let expectedResult = VideoCollection.mock() + let movieID = expectedResult.id + let languages = ["en", "fr"] + apiClient.addResponse(.success(expectedResult)) + let expectedRequest = MovieVideosRequest(id: movieID, languages: languages) + + let filter = MovieVideoFilter(languages: languages) + let result = try await service.videos(forMovie: movieID, filter: filter) + + XCTAssertEqual(result, expectedResult) + XCTAssertEqual(apiClient.lastRequest as? MovieVideosRequest, expectedRequest) + } + + func testVideosWhenErrorsThrowsError() async throws { + let movieID = 1 + apiClient.addResponse(.failure(.unknown)) + + var error: Error? + do { + _ = try await service.videos(forMovie: movieID) + } catch let err { + error = err + } + + let tmdbAPIError = try XCTUnwrap(error as? TMDbError) + + XCTAssertEqual(tmdbAPIError, .unknown) + } + +} diff --git a/Tests/TMDbTests/Domain/Services/Movies/MovieServiceOthersTests.swift b/Tests/TMDbTests/Domain/Services/Movies/MovieServiceOthersTests.swift new file mode 100644 index 00000000..de00492a --- /dev/null +++ b/Tests/TMDbTests/Domain/Services/Movies/MovieServiceOthersTests.swift @@ -0,0 +1,98 @@ +// +// MovieServiceOthersTests.swift +// TMDb +// +// Copyright © 2024 Adam Young. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an AS IS BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +@testable import TMDb +import XCTest + +final class MovieServiceOthersTests: XCTestCase { + + var service: MovieService! + var apiClient: MockAPIClient! + + override func setUp() { + super.setUp() + apiClient = MockAPIClient() + service = MovieService(apiClient: apiClient) + } + + override func tearDown() { + apiClient = nil + service = nil + super.tearDown() + } + + func testWatchProvidersReturnsWatchProviders() async throws { + let expectedResult = ShowWatchProviderResult.mock() + let movieID = 1 + let country = "GB" + apiClient.addResponse(.success(expectedResult)) + let expectedRequest = MovieWatchProvidersRequest(id: movieID) + + let result = try await service.watchProviders(forMovie: movieID, country: country) + + XCTAssertEqual(result, expectedResult.results[country]) + XCTAssertEqual(apiClient.lastRequest as? MovieWatchProvidersRequest, expectedRequest) + } + + func testWatchProvidersWhenErrorsThrowsError() async throws { + let movieID = 1 + let country = "GB" + apiClient.addResponse(.failure(.unknown)) + + var error: Error? + do { + _ = try await service.watchProviders(forMovie: movieID, country: country) + } catch let err { + error = err + } + + let tmdbAPIError = try XCTUnwrap(error as? TMDbError) + + XCTAssertEqual(tmdbAPIError, .unknown) + } + + func testExternalLinksReturnsExternalLinks() async throws { + let expectedResult = MovieExternalLinksCollection.barbie + let movieID = 346_698 + apiClient.addResponse(.success(expectedResult)) + let expectedRequest = MovieExternalLinksRequest(id: movieID) + + let result = try await service.externalLinks(forMovie: movieID) + + XCTAssertEqual(result, expectedResult) + XCTAssertEqual(apiClient.lastRequest as? MovieExternalLinksRequest, expectedRequest) + } + + func testExternalLinksWhenErrorsThrowsError() async throws { + let movieID = 346_698 + apiClient.addResponse(.failure(.unknown)) + + var error: Error? + do { + _ = try await service.externalLinks(forMovie: movieID) + } catch let err { + error = err + } + + let tmdbAPIError = try XCTUnwrap(error as? TMDbError) + + XCTAssertEqual(tmdbAPIError, .unknown) + } + +} diff --git a/Tests/TMDbTests/Domain/Services/Movies/MovieServiceReviewsTests.swift b/Tests/TMDbTests/Domain/Services/Movies/MovieServiceReviewsTests.swift new file mode 100644 index 00000000..e44c296d --- /dev/null +++ b/Tests/TMDbTests/Domain/Services/Movies/MovieServiceReviewsTests.swift @@ -0,0 +1,82 @@ +// +// MovieServiceReviewsTests.swift +// TMDb +// +// Copyright © 2024 Adam Young. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an AS IS BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +@testable import TMDb +import XCTest + +final class MovieServiceReviewsTests: XCTestCase { + + var service: MovieService! + var apiClient: MockAPIClient! + + override func setUp() { + super.setUp() + apiClient = MockAPIClient() + service = MovieService(apiClient: apiClient) + } + + override func tearDown() { + apiClient = nil + service = nil + super.tearDown() + } + + func testReviewsReturnsReviews() async throws { + let movieID = Int.randomID + let expectedResult = ReviewPageableList.mock() + apiClient.addResponse(.success(expectedResult)) + let expectedRequest = MovieReviewsRequest(id: movieID, page: nil, language: nil) + + let result = try await service.reviews(forMovie: movieID) + + XCTAssertEqual(result, expectedResult) + XCTAssertEqual(apiClient.lastRequest as? MovieReviewsRequest, expectedRequest) + } + + func testReviewsWithPageAndLanguageReturnsReviews() async throws { + let movieID = Int.randomID + let expectedResult = ReviewPageableList.mock() + let page = expectedResult.page + let language = "en" + apiClient.addResponse(.success(expectedResult)) + let expectedRequest = MovieReviewsRequest(id: movieID, page: page, language: language) + + let result = try await service.reviews(forMovie: movieID, page: page, language: language) + + XCTAssertEqual(result, expectedResult) + XCTAssertEqual(apiClient.lastRequest as? MovieReviewsRequest, expectedRequest) + } + + func testReviewsWhenErrorsThrowsError() async throws { + let movieID = 1 + apiClient.addResponse(.failure(.unknown)) + + var error: Error? + do { + _ = try await service.reviews(forMovie: movieID) + } catch let err { + error = err + } + + let tmdbAPIError = try XCTUnwrap(error as? TMDbError) + + XCTAssertEqual(tmdbAPIError, .unknown) + } + +} diff --git a/Tests/TMDbTests/Domain/Services/People/PersonServiceTests.swift b/Tests/TMDbTests/Domain/Services/People/PersonServiceTests.swift index 7e748f28..c6142c96 100644 --- a/Tests/TMDbTests/Domain/Services/People/PersonServiceTests.swift +++ b/Tests/TMDbTests/Domain/Services/People/PersonServiceTests.swift @@ -62,6 +62,22 @@ final class PersonServiceTests: XCTestCase { XCTAssertEqual(apiClient.lastRequest as? PersonRequest, expectedRequest) } + func testDetailsWhenErrorsThrowsError() async throws { + let personID = 1 + apiClient.addResponse(.failure(.unknown)) + + var error: Error? + do { + _ = try await service.details(forPerson: personID) + } catch let err { + error = err + } + + let tmdbAPIError = try XCTUnwrap(error as? TMDbError) + + XCTAssertEqual(tmdbAPIError, .unknown) + } + func testCombinedCreditsReturnsCombinedCredits() async throws { let mock = PersonCombinedCredits.mock() let expectedResult = PersonCombinedCredits(id: mock.id, cast: mock.cast, crew: mock.crew) @@ -89,6 +105,22 @@ final class PersonServiceTests: XCTestCase { XCTAssertEqual(apiClient.lastRequest as? PersonCombinedCreditsRequest, expectedRequest) } + func testCombinedCreditsWhenErrorsThrowsError() async throws { + let personID = 1 + apiClient.addResponse(.failure(.unknown)) + + var error: Error? + do { + _ = try await service.combinedCredits(forPerson: personID) + } catch let err { + error = err + } + + let tmdbAPIError = try XCTUnwrap(error as? TMDbError) + + XCTAssertEqual(tmdbAPIError, .unknown) + } + func testMovieCreditsReturnsMovieCredits() async throws { let mock = PersonMovieCredits.mock() let expectedResult = PersonMovieCredits(id: mock.id, cast: mock.cast, crew: mock.crew) @@ -116,6 +148,22 @@ final class PersonServiceTests: XCTestCase { XCTAssertEqual(apiClient.lastRequest as? PersonMovieCreditsRequest, expectedRequest) } + func testMovieCreditsWhenErrorsThrowsError() async throws { + let personID = 1 + apiClient.addResponse(.failure(.unknown)) + + var error: Error? + do { + _ = try await service.movieCredits(forPerson: personID) + } catch let err { + error = err + } + + let tmdbAPIError = try XCTUnwrap(error as? TMDbError) + + XCTAssertEqual(tmdbAPIError, .unknown) + } + func testTVSeriesCreditsReturnsTVSeriesCredits() async throws { let mock = PersonTVSeriesCredits.mock() let expectedResult = PersonTVSeriesCredits(id: mock.id, cast: mock.cast, crew: mock.crew) @@ -143,6 +191,22 @@ final class PersonServiceTests: XCTestCase { XCTAssertEqual(apiClient.lastRequest as? PersonTVSeriesCreditsRequest, expectedRequest) } + func testTVSeriesCreditsWhenErrorsThrowsError() async throws { + let personID = 1 + apiClient.addResponse(.failure(.unknown)) + + var error: Error? + do { + _ = try await service.tvSeriesCredits(forPerson: personID) + } catch let err { + error = err + } + + let tmdbAPIError = try XCTUnwrap(error as? TMDbError) + + XCTAssertEqual(tmdbAPIError, .unknown) + } + func testImagesReturnsImageCollection() async throws { let expectedResult = PersonImageCollection.mock() let personID = expectedResult.id @@ -155,6 +219,22 @@ final class PersonServiceTests: XCTestCase { XCTAssertEqual(apiClient.lastRequest as? PersonImagesRequest, expectedRequest) } + func testImagesWhenErrorsThrowsError() async throws { + let personID = 1 + apiClient.addResponse(.failure(.unknown)) + + var error: Error? + do { + _ = try await service.images(forPerson: personID) + } catch let err { + error = err + } + + let tmdbAPIError = try XCTUnwrap(error as? TMDbError) + + XCTAssertEqual(tmdbAPIError, .unknown) + } + func testPopularReturnsPeople() async throws { let expectedResult = PersonPageableList.mock() apiClient.addResponse(.success(expectedResult)) @@ -179,6 +259,21 @@ final class PersonServiceTests: XCTestCase { XCTAssertEqual(apiClient.lastRequest as? PopularPeopleRequest, expectedRequest) } + func testPopularWhenErrorsThrowsError() async throws { + apiClient.addResponse(.failure(.unknown)) + + var error: Error? + do { + _ = try await service.popular() + } catch let err { + error = err + } + + let tmdbAPIError = try XCTUnwrap(error as? TMDbError) + + XCTAssertEqual(tmdbAPIError, .unknown) + } + func testExternalLinksReturnsExternalLinks() async throws { let expectedResult = PersonExternalLinksCollection.sydneySweeney let personID = 115_440 @@ -191,4 +286,20 @@ final class PersonServiceTests: XCTestCase { XCTAssertEqual(apiClient.lastRequest as? PersonExternalLinksRequest, expectedRequest) } + func testExternalLinksWhenErrorsThrowsError() async throws { + let personID = 115_440 + apiClient.addResponse(.failure(.unknown)) + + var error: Error? + do { + _ = try await service.externalLinks(forPerson: personID) + } catch let err { + error = err + } + + let tmdbAPIError = try XCTUnwrap(error as? TMDbError) + + XCTAssertEqual(tmdbAPIError, .unknown) + } + } diff --git a/Tests/TMDbTests/Domain/Services/Search/SearchServiceTests.swift b/Tests/TMDbTests/Domain/Services/Search/SearchServiceTests.swift index 1ceb80b1..f517d8e6 100644 --- a/Tests/TMDbTests/Domain/Services/Search/SearchServiceTests.swift +++ b/Tests/TMDbTests/Domain/Services/Search/SearchServiceTests.swift @@ -70,6 +70,22 @@ final class SearchServiceTests: XCTestCase { XCTAssertEqual(apiClient.lastRequest as? MultiSearchRequest, expectedRequest) } + func testSearchAllWhenErrorsThrowsError() async throws { + let query = String.randomString + apiClient.addResponse(.failure(.unknown)) + + var error: Error? + do { + _ = try await service.searchAll(query: query) + } catch let err { + error = err + } + + let tmdbAPIError = try XCTUnwrap(error as? TMDbError) + + XCTAssertEqual(tmdbAPIError, .unknown) + } + func testSearchMoviesReturnsMovies() async throws { let query = String.randomString let expectedResult = MoviePageableList.mock() @@ -117,6 +133,22 @@ final class SearchServiceTests: XCTestCase { XCTAssertEqual(apiClient.lastRequest as? MovieSearchRequest, expectedRequest) } + func testSearchMoviesWhenErrorsThrowsError() async throws { + let query = String.randomString + apiClient.addResponse(.failure(.unknown)) + + var error: Error? + do { + _ = try await service.searchMovies(query: query) + } catch let err { + error = err + } + + let tmdbAPIError = try XCTUnwrap(error as? TMDbError) + + XCTAssertEqual(tmdbAPIError, .unknown) + } + func testSearchTVSeriesReturnsTVSeries() async throws { let query = String.randomString let expectedResult = TVSeriesPageableList.mock() @@ -161,6 +193,22 @@ final class SearchServiceTests: XCTestCase { XCTAssertEqual(apiClient.lastRequest as? TVSeriesSearchRequest, expectedRequest) } + func testSearchTVSeriesWhenErrorsThrowsError() async throws { + let query = String.randomString + apiClient.addResponse(.failure(.unknown)) + + var error: Error? + do { + _ = try await service.searchTVSeries(query: query) + } catch let err { + error = err + } + + let tmdbAPIError = try XCTUnwrap(error as? TMDbError) + + XCTAssertEqual(tmdbAPIError, .unknown) + } + func testSearchPeopleReturnsPeople() async throws { let query = String.randomString let expectedResult = PersonPageableList.mock() @@ -194,4 +242,20 @@ final class SearchServiceTests: XCTestCase { XCTAssertEqual(apiClient.lastRequest as? PersonSearchRequest, expectedRequest) } + func testSearchPeopleWhenErrorsThrowsError() async throws { + let query = String.randomString + apiClient.addResponse(.failure(.unknown)) + + var error: Error? + do { + _ = try await service.searchPeople(query: query) + } catch let err { + error = err + } + + let tmdbAPIError = try XCTUnwrap(error as? TMDbError) + + XCTAssertEqual(tmdbAPIError, .unknown) + } + } diff --git a/Tests/TMDbTests/Domain/Services/TVEpisodes/TVEpisodeServiceTests.swift b/Tests/TMDbTests/Domain/Services/TVEpisodes/TVEpisodeServiceTests.swift index 6699573e..1c306525 100644 --- a/Tests/TMDbTests/Domain/Services/TVEpisodes/TVEpisodeServiceTests.swift +++ b/Tests/TMDbTests/Domain/Services/TVEpisodes/TVEpisodeServiceTests.swift @@ -85,6 +85,28 @@ final class TVEpisodeServiceTests: XCTestCase { XCTAssertEqual(apiClient.lastRequest as? TVEpisodeRequest, expectedRequest) } + func testDetailsWhenErrorsThrowsError() async throws { + let tvSeriesID = 1 + let seasonNumber = 2 + let episodeNumber = 3 + apiClient.addResponse(.failure(.unknown)) + + var error: Error? + do { + _ = try await service.details( + forEpisode: episodeNumber, + inSeason: seasonNumber, + inTVSeries: tvSeriesID + ) + } catch let err { + error = err + } + + let tmdbAPIError = try XCTUnwrap(error as? TMDbError) + + XCTAssertEqual(tmdbAPIError, .unknown) + } + func testImagesReturnsImages() async throws { let episodeNumber = Int.randomID let seasonNumber = Int.randomID @@ -134,6 +156,28 @@ final class TVEpisodeServiceTests: XCTestCase { XCTAssertEqual(apiClient.lastRequest as? TVEpisodeImagesRequest, expectedRequest) } + func testImagesWhenErrorsThrowsError() async throws { + let tvSeriesID = 1 + let seasonNumber = 2 + let episodeNumber = 3 + apiClient.addResponse(.failure(.unknown)) + + var error: Error? + do { + _ = try await service.images( + forEpisode: episodeNumber, + inSeason: seasonNumber, + inTVSeries: tvSeriesID + ) + } catch let err { + error = err + } + + let tmdbAPIError = try XCTUnwrap(error as? TMDbError) + + XCTAssertEqual(tmdbAPIError, .unknown) + } + func testVideosReturnsVideos() async throws { let episodeNumber = Int.randomID let seasonNumber = Int.randomID @@ -183,4 +227,26 @@ final class TVEpisodeServiceTests: XCTestCase { XCTAssertEqual(apiClient.lastRequest as? TVEpisodeVideosRequest, expectedRequest) } + func testVideosWhenErrorsThrowsError() async throws { + let tvSeriesID = 1 + let seasonNumber = 2 + let episodeNumber = 3 + apiClient.addResponse(.failure(.unknown)) + + var error: Error? + do { + _ = try await service.videos( + forEpisode: episodeNumber, + inSeason: seasonNumber, + inTVSeries: tvSeriesID + ) + } catch let err { + error = err + } + + let tmdbAPIError = try XCTUnwrap(error as? TMDbError) + + XCTAssertEqual(tmdbAPIError, .unknown) + } + } diff --git a/Tests/TMDbTests/Domain/Services/TVSeasons/TVSeasonServiceTests.swift b/Tests/TMDbTests/Domain/Services/TVSeasons/TVSeasonServiceTests.swift index 703f4537..e546a650 100644 --- a/Tests/TMDbTests/Domain/Services/TVSeasons/TVSeasonServiceTests.swift +++ b/Tests/TMDbTests/Domain/Services/TVSeasons/TVSeasonServiceTests.swift @@ -72,6 +72,23 @@ final class TVSeasonServiceTests: XCTestCase { XCTAssertEqual(apiClient.lastRequest as? TVSeasonRequest, expectedRequest) } + func testDetailsWhenErrorsThrowsError() async throws { + let tvSeriesID = 1 + let seasonNumber = 2 + apiClient.addResponse(.failure(.unknown)) + + var error: Error? + do { + _ = try await service.details(forSeason: seasonNumber, inTVSeries: tvSeriesID) + } catch let err { + error = err + } + + let tmdbAPIError = try XCTUnwrap(error as? TMDbError) + + XCTAssertEqual(tmdbAPIError, .unknown) + } + func testAggregateCreditsReturnsTVSeasonCredits() async throws { let tvSeriesID = Int.randomID let expectedResult = TVSeasonAggregateCredits(id: 1, cast: [], crew: []) @@ -111,6 +128,40 @@ final class TVSeasonServiceTests: XCTestCase { XCTAssertEqual(apiClient.lastRequest as? TVSeasonAggregateCreditsRequest, expectedRequest) } + func testAggregateCreditsWhenErrorsThrowsError() async throws { + let tvSeriesID = 1 + let seasonNumber = 2 + apiClient.addResponse(.failure(.unknown)) + + var error: Error? + do { + _ = try await service.aggregateCredits(forSeason: seasonNumber, inTVSeries: tvSeriesID) + } catch let err { + error = err + } + + let tmdbAPIError = try XCTUnwrap(error as? TMDbError) + + XCTAssertEqual(tmdbAPIError, .unknown) + } + + func testImagesReturnsImages() async throws { + let seasonNumber = Int.randomID + let tvSeriesID = Int.randomID + let expectedResult = TVSeasonImageCollection.mock() + apiClient.addResponse(.success(expectedResult)) + let expectedRequest = TVSeasonImagesRequest( + seasonNumber: seasonNumber, + tvSeriesID: tvSeriesID, + languages: nil + ) + + let result = try await service.images(forSeason: seasonNumber, inTVSeries: tvSeriesID) + + XCTAssertEqual(result, expectedResult) + XCTAssertEqual(apiClient.lastRequest as? TVSeasonImagesRequest, expectedRequest) + } + func testImagesWithFilterReturnsImages() async throws { let seasonNumber = Int.randomID let tvSeriesID = Int.randomID @@ -130,6 +181,23 @@ final class TVSeasonServiceTests: XCTestCase { XCTAssertEqual(apiClient.lastRequest as? TVSeasonImagesRequest, expectedRequest) } + func testImagesWhenErrorsThrowsError() async throws { + let tvSeriesID = 1 + let seasonNumber = 2 + apiClient.addResponse(.failure(.unknown)) + + var error: Error? + do { + _ = try await service.images(forSeason: seasonNumber, inTVSeries: tvSeriesID) + } catch let err { + error = err + } + + let tmdbAPIError = try XCTUnwrap(error as? TMDbError) + + XCTAssertEqual(tmdbAPIError, .unknown) + } + func testVideosReturnsVideos() async throws { let seasonNumber = Int.randomID let tvSeriesID = Int.randomID @@ -166,4 +234,21 @@ final class TVSeasonServiceTests: XCTestCase { XCTAssertEqual(apiClient.lastRequest as? TVSeasonVideosRequest, expectedRequest) } + func testVideosWhenErrorsThrowsError() async throws { + let tvSeriesID = 1 + let seasonNumber = 2 + apiClient.addResponse(.failure(.unknown)) + + var error: Error? + do { + _ = try await service.videos(forSeason: seasonNumber, inTVSeries: tvSeriesID) + } catch let err { + error = err + } + + let tmdbAPIError = try XCTUnwrap(error as? TMDbError) + + XCTAssertEqual(tmdbAPIError, .unknown) + } + } diff --git a/Tests/TMDbTests/Domain/Services/TVSeries/TVSeriesServiceCreditsTests.swift b/Tests/TMDbTests/Domain/Services/TVSeries/TVSeriesServiceCreditsTests.swift new file mode 100644 index 00000000..062528ca --- /dev/null +++ b/Tests/TMDbTests/Domain/Services/TVSeries/TVSeriesServiceCreditsTests.swift @@ -0,0 +1,122 @@ +// +// TVSeriesServiceCreditsTests.swift +// TMDb +// +// Copyright © 2024 Adam Young. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an AS IS BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +@testable import TMDb +import XCTest + +final class TVSeriesServiceCreditsTests: XCTestCase { + + var service: TVSeriesService! + var apiClient: MockAPIClient! + + override func setUp() { + super.setUp() + apiClient = MockAPIClient() + service = TVSeriesService(apiClient: apiClient) + } + + override func tearDown() { + apiClient = nil + service = nil + super.tearDown() + } + + func testCreditsReturnsShowsCredits() async throws { + let expectedResult = ShowCredits.mock() + let tvSeriesID = expectedResult.id + apiClient.addResponse(.success(expectedResult)) + let expectedRequest = TVSeriesCreditsRequest(id: tvSeriesID, language: nil) + + let result = try await service.credits(forTVSeries: tvSeriesID) + + XCTAssertEqual(result, expectedResult) + XCTAssertEqual(apiClient.lastRequest as? TVSeriesCreditsRequest, expectedRequest) + } + + func testCreditsWithLanguageReturnsShowsCredits() async throws { + let expectedResult = ShowCredits.mock() + let tvSeriesID = expectedResult.id + let language = "en" + apiClient.addResponse(.success(expectedResult)) + let expectedRequest = TVSeriesCreditsRequest(id: tvSeriesID, language: language) + + let result = try await service.credits(forTVSeries: tvSeriesID, language: language) + + XCTAssertEqual(result, expectedResult) + XCTAssertEqual(apiClient.lastRequest as? TVSeriesCreditsRequest, expectedRequest) + } + + func testCreditsWhenErrorsThrowsError() async throws { + let tvSeriesID = 1 + apiClient.addResponse(.failure(.unknown)) + + var error: Error? + do { + _ = try await service.credits(forTVSeries: tvSeriesID) + } catch let err { + error = err + } + + let tmdbAPIError = try XCTUnwrap(error as? TMDbError) + + XCTAssertEqual(tmdbAPIError, .unknown) + } + + func testAggregateCreditsReturnsShowsCredits() async throws { + let expectedResult = TVSeriesAggregateCredits(id: 1, cast: [], crew: []) + let tvSeriesID = expectedResult.id + apiClient.addResponse(.success(expectedResult)) + let expectedRequest = TVSeriesAggregateCreditsRequest(id: tvSeriesID, language: nil) + + let result = try await service.aggregateCredits(forTVSeries: tvSeriesID) + + XCTAssertEqual(result, expectedResult) + XCTAssertEqual(apiClient.lastRequest as? TVSeriesAggregateCreditsRequest, expectedRequest) + } + + func testAggregateCreditsWithLanguageReturnsShowsCredits() async throws { + let expectedResult = TVSeriesAggregateCredits(id: 1, cast: [], crew: []) + let tvSeriesID = expectedResult.id + let language = "en" + apiClient.addResponse(.success(expectedResult)) + let expectedRequest = TVSeriesAggregateCreditsRequest(id: tvSeriesID, language: language) + + let result = try await service.aggregateCredits(forTVSeries: tvSeriesID, language: language) + + XCTAssertEqual(result, expectedResult) + XCTAssertEqual(apiClient.lastRequest as? TVSeriesAggregateCreditsRequest, expectedRequest) + } + + func testAggregateCreditsWhenErrorsThrowsError() async throws { + let tvSeriesID = 1 + apiClient.addResponse(.failure(.unknown)) + + var error: Error? + do { + _ = try await service.aggregateCredits(forTVSeries: tvSeriesID) + } catch let err { + error = err + } + + let tmdbAPIError = try XCTUnwrap(error as? TMDbError) + + XCTAssertEqual(tmdbAPIError, .unknown) + } + +} diff --git a/Tests/TMDbTests/Domain/Services/TVSeries/TVSeriesServiceDetailsTests.swift b/Tests/TMDbTests/Domain/Services/TVSeries/TVSeriesServiceDetailsTests.swift new file mode 100644 index 00000000..9eac977f --- /dev/null +++ b/Tests/TMDbTests/Domain/Services/TVSeries/TVSeriesServiceDetailsTests.swift @@ -0,0 +1,81 @@ +// +// TVSeriesServiceDetailsTests.swift +// TMDb +// +// Copyright © 2024 Adam Young. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an AS IS BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +@testable import TMDb +import XCTest + +final class TVSeriesServiceTests: XCTestCase { + + var service: TVSeriesService! + var apiClient: MockAPIClient! + + override func setUp() { + super.setUp() + apiClient = MockAPIClient() + service = TVSeriesService(apiClient: apiClient) + } + + override func tearDown() { + apiClient = nil + service = nil + super.tearDown() + } + + func testDetailsReturnsTVSeries() async throws { + let expectedResult = TVSeries.theSandman + let tvSeriesID = expectedResult.id + apiClient.addResponse(.success(expectedResult)) + let expectedRequest = TVSeriesRequest(id: tvSeriesID, language: nil) + + let result = try await service.details(forTVSeries: tvSeriesID) + + XCTAssertEqual(result, expectedResult) + XCTAssertEqual(apiClient.lastRequest as? TVSeriesRequest, expectedRequest) + } + + func testDetailsWithLanguageReturnsTVSeries() async throws { + let expectedResult = TVSeries.theSandman + let tvSeriesID = expectedResult.id + let language = "en" + apiClient.addResponse(.success(expectedResult)) + let expectedRequest = TVSeriesRequest(id: tvSeriesID, language: language) + + let result = try await service.details(forTVSeries: tvSeriesID, language: language) + + XCTAssertEqual(result, expectedResult) + XCTAssertEqual(apiClient.lastRequest as? TVSeriesRequest, expectedRequest) + } + + func testDetailsWhenErrorsThrowsError() async throws { + let tvSeriesID = 1 + apiClient.addResponse(.failure(.unknown)) + + var error: Error? + do { + _ = try await service.details(forTVSeries: tvSeriesID) + } catch let err { + error = err + } + + let tmdbAPIError = try XCTUnwrap(error as? TMDbError) + + XCTAssertEqual(tmdbAPIError, .unknown) + } + +} diff --git a/Tests/TMDbTests/Domain/Services/TVSeries/TVSeriesServiceListsTests.swift b/Tests/TMDbTests/Domain/Services/TVSeries/TVSeriesServiceListsTests.swift new file mode 100644 index 00000000..ded8367c --- /dev/null +++ b/Tests/TMDbTests/Domain/Services/TVSeries/TVSeriesServiceListsTests.swift @@ -0,0 +1,163 @@ +// +// TVSeriesServiceListsTests.swift +// TMDb +// +// Copyright © 2024 Adam Young. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an AS IS BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +@testable import TMDb +import XCTest + +final class TVSeriesServiceListsTests: XCTestCase { + + var service: TVSeriesService! + var apiClient: MockAPIClient! + + override func setUp() { + super.setUp() + apiClient = MockAPIClient() + service = TVSeriesService(apiClient: apiClient) + } + + override func tearDown() { + apiClient = nil + service = nil + super.tearDown() + } + + func testRecommendationsReturnsTVSeries() async throws { + let tvSeriesID = Int.randomID + let expectedResult = TVSeriesPageableList.mock() + apiClient.addResponse(.success(expectedResult)) + let expectedRequest = TVSeriesRecommendationsRequest(id: tvSeriesID, page: nil, language: nil) + + let result = try await service.recommendations(forTVSeries: tvSeriesID) + + XCTAssertEqual(result, expectedResult) + XCTAssertEqual(apiClient.lastRequest as? TVSeriesRecommendationsRequest, expectedRequest) + } + + func testRecommendationsWithPageAndLanguageReturnsTVSeries() async throws { + let tvSeriesID = Int.randomID + let page = 2 + let language = "en" + let expectedResult = TVSeriesPageableList.mock() + apiClient.addResponse(.success(expectedResult)) + let expectedRequest = TVSeriesRecommendationsRequest(id: tvSeriesID, page: page, language: language) + + let result = try await service.recommendations(forTVSeries: tvSeriesID, page: page, language: language) + + XCTAssertEqual(result, expectedResult) + XCTAssertEqual(apiClient.lastRequest as? TVSeriesRecommendationsRequest, expectedRequest) + } + + func testRecommendationsWhenErrorsThrowsError() async throws { + let tvSeriesID = 1 + apiClient.addResponse(.failure(.unknown)) + + var error: Error? + do { + _ = try await service.recommendations(forTVSeries: tvSeriesID) + } catch let err { + error = err + } + + let tmdbAPIError = try XCTUnwrap(error as? TMDbError) + + XCTAssertEqual(tmdbAPIError, .unknown) + } + + func testSimilarReturnsTVSeries() async throws { + let tvSeriesID = Int.randomID + let expectedResult = TVSeriesPageableList.mock() + apiClient.addResponse(.success(expectedResult)) + let expectedRequest = SimilarTVSeriesRequest(id: tvSeriesID, page: nil, language: nil) + + let result = try await service.similar(toTVSeries: tvSeriesID) + + XCTAssertEqual(result, expectedResult) + XCTAssertEqual(apiClient.lastRequest as? SimilarTVSeriesRequest, expectedRequest) + } + + func testSimilarWithPageAndLanguageReturnsTVSeries() async throws { + let tvSeriesID = Int.randomID + let page = 2 + let language = "en" + let expectedResult = TVSeriesPageableList.mock() + apiClient.addResponse(.success(expectedResult)) + let expectedRequest = SimilarTVSeriesRequest(id: tvSeriesID, page: page, language: language) + + let result = try await service.similar(toTVSeries: tvSeriesID, page: page, language: language) + + XCTAssertEqual(result, expectedResult) + XCTAssertEqual(apiClient.lastRequest as? SimilarTVSeriesRequest, expectedRequest) + } + + func testSimilarWhenErrorsThrowsError() async throws { + let tvSeriesID = 1 + apiClient.addResponse(.failure(.unknown)) + + var error: Error? + do { + _ = try await service.similar(toTVSeries: tvSeriesID) + } catch let err { + error = err + } + + let tmdbAPIError = try XCTUnwrap(error as? TMDbError) + + XCTAssertEqual(tmdbAPIError, .unknown) + } + + func testPopularReturnsTVSeries() async throws { + let expectedResult = TVSeriesPageableList.mock() + apiClient.addResponse(.success(expectedResult)) + let expectedRequest = PopularTVSeriesRequest(page: nil, language: nil) + + let result = try await service.popular() + + XCTAssertEqual(result, expectedResult) + XCTAssertEqual(apiClient.lastRequest as? PopularTVSeriesRequest, expectedRequest) + } + + func testPopularWithPageAndLanguageReturnsTVSeries() async throws { + let page = 2 + let language = "en" + let expectedResult = TVSeriesPageableList.mock() + apiClient.addResponse(.success(expectedResult)) + let expectedRequest = PopularTVSeriesRequest(page: page, language: language) + + let result = try await service.popular(page: page, language: language) + + XCTAssertEqual(result, expectedResult) + XCTAssertEqual(apiClient.lastRequest as? PopularTVSeriesRequest, expectedRequest) + } + + func testPopularWhenErrorsThrowsError() async throws { + apiClient.addResponse(.failure(.unknown)) + + var error: Error? + do { + _ = try await service.popular() + } catch let err { + error = err + } + + let tmdbAPIError = try XCTUnwrap(error as? TMDbError) + + XCTAssertEqual(tmdbAPIError, .unknown) + } + +} diff --git a/Tests/TMDbTests/Domain/Services/TVSeries/TVSeriesServiceMediaTests.swift b/Tests/TMDbTests/Domain/Services/TVSeries/TVSeriesServiceMediaTests.swift new file mode 100644 index 00000000..a43d4fef --- /dev/null +++ b/Tests/TMDbTests/Domain/Services/TVSeries/TVSeriesServiceMediaTests.swift @@ -0,0 +1,124 @@ +// +// TVSeriesServiceMediaTests.swift +// TMDb +// +// Copyright © 2024 Adam Young. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an AS IS BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +@testable import TMDb +import XCTest + +final class TVSeriesServiceMediaTests: XCTestCase { + + var service: TVSeriesService! + var apiClient: MockAPIClient! + + override func setUp() { + super.setUp() + apiClient = MockAPIClient() + service = TVSeriesService(apiClient: apiClient) + } + + override func tearDown() { + apiClient = nil + service = nil + super.tearDown() + } + + func testImagesReturnsImages() async throws { + let tvSeriesID = Int.randomID + let expectedResult = ImageCollection.mock() + apiClient.addResponse(.success(expectedResult)) + let expectedRequest = TVSeriesImagesRequest(id: tvSeriesID, languages: nil) + + let result = try await service.images(forTVSeries: tvSeriesID) + + XCTAssertEqual(result, expectedResult) + XCTAssertEqual(apiClient.lastRequest as? TVSeriesImagesRequest, expectedRequest) + } + + func testImagesWithFilterReturnsImages() async throws { + let tvSeriesID = Int.randomID + let languages = ["en-GB", "fr"] + let expectedResult = ImageCollection.mock() + apiClient.addResponse(.success(expectedResult)) + let expectedRequest = TVSeriesImagesRequest(id: tvSeriesID, languages: languages) + + let filter = TVSeriesImageFilter(languages: languages) + let result = try await service.images(forTVSeries: tvSeriesID, filter: filter) + + XCTAssertEqual(result, expectedResult) + XCTAssertEqual(apiClient.lastRequest as? TVSeriesImagesRequest, expectedRequest) + } + + func testImagesWhenErrorsThrowsError() async throws { + let tvSeriesID = 1 + apiClient.addResponse(.failure(.unknown)) + + var error: Error? + do { + _ = try await service.images(forTVSeries: tvSeriesID) + } catch let err { + error = err + } + + let tmdbAPIError = try XCTUnwrap(error as? TMDbError) + + XCTAssertEqual(tmdbAPIError, .unknown) + } + + func testVideosReturnsVideos() async throws { + let expectedResult = VideoCollection.mock() + let tvSeriesID = expectedResult.id + apiClient.addResponse(.success(expectedResult)) + let expectedRequest = TVSeriesVideosRequest(id: tvSeriesID, languages: nil) + + let result = try await service.videos(forTVSeries: tvSeriesID) + + XCTAssertEqual(result, expectedResult) + XCTAssertEqual(apiClient.lastRequest as? TVSeriesVideosRequest, expectedRequest) + } + + func testVideosWithFilterReturnsVideos() async throws { + let expectedResult = VideoCollection.mock() + let tvSeriesID = expectedResult.id + let languages = ["en", "fr"] + apiClient.addResponse(.success(expectedResult)) + let expectedRequest = TVSeriesVideosRequest(id: tvSeriesID, languages: languages) + + let filter = TVSeriesVideoFilter(languages: languages) + let result = try await service.videos(forTVSeries: tvSeriesID, filter: filter) + + XCTAssertEqual(result, expectedResult) + XCTAssertEqual(apiClient.lastRequest as? TVSeriesVideosRequest, expectedRequest) + } + + func testVideosWhenErrorsThrowsError() async throws { + let tvSeriesID = 1 + apiClient.addResponse(.failure(.unknown)) + + var error: Error? + do { + _ = try await service.videos(forTVSeries: tvSeriesID) + } catch let err { + error = err + } + + let tmdbAPIError = try XCTUnwrap(error as? TMDbError) + + XCTAssertEqual(tmdbAPIError, .unknown) + } + +} diff --git a/Tests/TMDbTests/Domain/Services/TVSeries/TVSeriesServiceOthersTests.swift b/Tests/TMDbTests/Domain/Services/TVSeries/TVSeriesServiceOthersTests.swift new file mode 100644 index 00000000..ef715863 --- /dev/null +++ b/Tests/TMDbTests/Domain/Services/TVSeries/TVSeriesServiceOthersTests.swift @@ -0,0 +1,97 @@ +// +// TVSeriesServiceOthersTests.swift +// TMDb +// +// Copyright © 2024 Adam Young. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an AS IS BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +@testable import TMDb +import XCTest + +final class TVSeriesServiceOthersTests: XCTestCase { + + var service: TVSeriesService! + var apiClient: MockAPIClient! + + override func setUp() { + super.setUp() + apiClient = MockAPIClient() + service = TVSeriesService(apiClient: apiClient) + } + + override func tearDown() { + apiClient = nil + service = nil + super.tearDown() + } + + func testWatchProvidersReturnsWatchProviders() async throws { + let expectedResult = ShowWatchProviderResult.mock() + let tvSeriesID = 1 + let country = "GB" + apiClient.addResponse(.success(expectedResult)) + let expectedRequest = TVSeriesWatchProvidersRequest(id: tvSeriesID) + + let result = try await service.watchProviders(forTVSeries: tvSeriesID, country: country) + + XCTAssertEqual(result, expectedResult.results[country]) + XCTAssertEqual(apiClient.lastRequest as? TVSeriesWatchProvidersRequest, expectedRequest) + } + + func testWatchProvidersWhenErrorsThrowsError() async throws { + let tvSeriesID = 1 + apiClient.addResponse(.failure(.unknown)) + + var error: Error? + do { + _ = try await service.watchProviders(forTVSeries: tvSeriesID) + } catch let err { + error = err + } + + let tmdbAPIError = try XCTUnwrap(error as? TMDbError) + + XCTAssertEqual(tmdbAPIError, .unknown) + } + + func testExternalLinksReturnsExternalLinks() async throws { + let expectedResult = TVSeriesExternalLinksCollection.lockeAndKey + let tvSeriesID = 86423 + apiClient.addResponse(.success(expectedResult)) + let expectedRequest = TVSeriesExternalLinksRequest(id: tvSeriesID) + + let result = try await service.externalLinks(forTVSeries: tvSeriesID) + + XCTAssertEqual(result, expectedResult) + XCTAssertEqual(apiClient.lastRequest as? TVSeriesExternalLinksRequest, expectedRequest) + } + + func testExternalLinksWhenErrorsThrowsError() async throws { + let tvSeriesID = 1 + apiClient.addResponse(.failure(.unknown)) + + var error: Error? + do { + _ = try await service.externalLinks(forTVSeries: tvSeriesID) + } catch let err { + error = err + } + + let tmdbAPIError = try XCTUnwrap(error as? TMDbError) + + XCTAssertEqual(tmdbAPIError, .unknown) + } + +} diff --git a/Tests/TMDbTests/Domain/Services/TVSeries/TVSeriesServiceReviewsTests.swift b/Tests/TMDbTests/Domain/Services/TVSeries/TVSeriesServiceReviewsTests.swift new file mode 100644 index 00000000..6cbf510e --- /dev/null +++ b/Tests/TMDbTests/Domain/Services/TVSeries/TVSeriesServiceReviewsTests.swift @@ -0,0 +1,81 @@ +// +// TVSeriesServiceReviewsTests.swift +// TMDb +// +// Copyright © 2024 Adam Young. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an AS IS BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +@testable import TMDb +import XCTest + +final class TVSeriesServiceReviewsTests: XCTestCase { + + var service: TVSeriesService! + var apiClient: MockAPIClient! + + override func setUp() { + super.setUp() + apiClient = MockAPIClient() + service = TVSeriesService(apiClient: apiClient) + } + + override func tearDown() { + apiClient = nil + service = nil + super.tearDown() + } + + func testReviewsReturnsReviews() async throws { + let tvSeriesID = Int.randomID + let expectedResult = ReviewPageableList.mock() + apiClient.addResponse(.success(expectedResult)) + let expectedRequest = TVSeriesReviewsRequest(id: tvSeriesID, page: nil, language: nil) + + let result = try await service.reviews(forTVSeries: tvSeriesID) + + XCTAssertEqual(result, expectedResult) + XCTAssertEqual(apiClient.lastRequest as? TVSeriesReviewsRequest, expectedRequest) + } + + func testReviewsWithLanguageReturnsReviews() async throws { + let tvSeriesID = Int.randomID + let language = "en" + let expectedResult = ReviewPageableList.mock() + apiClient.addResponse(.success(expectedResult)) + let expectedRequest = TVSeriesReviewsRequest(id: tvSeriesID, page: nil, language: language) + + let result = try await service.reviews(forTVSeries: tvSeriesID, language: language) + + XCTAssertEqual(result, expectedResult) + XCTAssertEqual(apiClient.lastRequest as? TVSeriesReviewsRequest, expectedRequest) + } + + func testReviewsWhenErrorsThrowsError() async throws { + let tvSeriesID = 1 + apiClient.addResponse(.failure(.unknown)) + + var error: Error? + do { + _ = try await service.reviews(forTVSeries: tvSeriesID) + } catch let err { + error = err + } + + let tmdbAPIError = try XCTUnwrap(error as? TMDbError) + + XCTAssertEqual(tmdbAPIError, .unknown) + } + +} diff --git a/Tests/TMDbTests/Domain/Services/TVSeries/TVSeriesServiceTests.swift b/Tests/TMDbTests/Domain/Services/TVSeries/TVSeriesServiceTests.swift deleted file mode 100644 index 00c36f20..00000000 --- a/Tests/TMDbTests/Domain/Services/TVSeries/TVSeriesServiceTests.swift +++ /dev/null @@ -1,293 +0,0 @@ -// -// TVSeriesServiceTests.swift -// TMDb -// -// Copyright © 2024 Adam Young. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an AS IS BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// - -@testable import TMDb -import XCTest - -final class TVSeriesServiceTests: XCTestCase { - - var service: TVSeriesService! - var apiClient: MockAPIClient! - - override func setUp() { - super.setUp() - apiClient = MockAPIClient() - service = TVSeriesService(apiClient: apiClient) - } - - override func tearDown() { - apiClient = nil - service = nil - super.tearDown() - } - - func testDetailsReturnsTVSeries() async throws { - let expectedResult = TVSeries.theSandman - let tvSeriesID = expectedResult.id - apiClient.addResponse(.success(expectedResult)) - let expectedRequest = TVSeriesRequest(id: tvSeriesID, language: nil) - - let result = try await service.details(forTVSeries: tvSeriesID) - - XCTAssertEqual(result, expectedResult) - XCTAssertEqual(apiClient.lastRequest as? TVSeriesRequest, expectedRequest) - } - - func testDetailsWithLanguageReturnsTVSeries() async throws { - let expectedResult = TVSeries.theSandman - let tvSeriesID = expectedResult.id - let language = "en" - apiClient.addResponse(.success(expectedResult)) - let expectedRequest = TVSeriesRequest(id: tvSeriesID, language: language) - - let result = try await service.details(forTVSeries: tvSeriesID, language: language) - - XCTAssertEqual(result, expectedResult) - XCTAssertEqual(apiClient.lastRequest as? TVSeriesRequest, expectedRequest) - } - - func testCreditsReturnsShowsCredits() async throws { - let expectedResult = ShowCredits.mock() - let tvSeriesID = expectedResult.id - apiClient.addResponse(.success(expectedResult)) - let expectedRequest = TVSeriesCreditsRequest(id: tvSeriesID, language: nil) - - let result = try await service.credits(forTVSeries: tvSeriesID) - - XCTAssertEqual(result, expectedResult) - XCTAssertEqual(apiClient.lastRequest as? TVSeriesCreditsRequest, expectedRequest) - } - - func testCreditsWithLanguageReturnsShowsCredits() async throws { - let expectedResult = ShowCredits.mock() - let tvSeriesID = expectedResult.id - let language = "en" - apiClient.addResponse(.success(expectedResult)) - let expectedRequest = TVSeriesCreditsRequest(id: tvSeriesID, language: language) - - let result = try await service.credits(forTVSeries: tvSeriesID, language: language) - - XCTAssertEqual(result, expectedResult) - XCTAssertEqual(apiClient.lastRequest as? TVSeriesCreditsRequest, expectedRequest) - } - - func testAggregateCreditsReturnsShowsCredits() async throws { - let expectedResult = TVSeriesAggregateCredits(id: 1, cast: [], crew: []) - let tvSeriesID = expectedResult.id - apiClient.addResponse(.success(expectedResult)) - let expectedRequest = TVSeriesAggregateCreditsRequest(id: tvSeriesID, language: nil) - - let result = try await service.aggregateCredits(forTVSeries: tvSeriesID) - - XCTAssertEqual(result, expectedResult) - XCTAssertEqual(apiClient.lastRequest as? TVSeriesAggregateCreditsRequest, expectedRequest) - } - - func testAggregateCreditsWithLanguageReturnsShowsCredits() async throws { - let expectedResult = TVSeriesAggregateCredits(id: 1, cast: [], crew: []) - let tvSeriesID = expectedResult.id - let language = "en" - apiClient.addResponse(.success(expectedResult)) - let expectedRequest = TVSeriesAggregateCreditsRequest(id: tvSeriesID, language: language) - - let result = try await service.aggregateCredits(forTVSeries: tvSeriesID, language: language) - - XCTAssertEqual(result, expectedResult) - XCTAssertEqual(apiClient.lastRequest as? TVSeriesAggregateCreditsRequest, expectedRequest) - } - - func testReviewsReturnsReviews() async throws { - let tvSeriesID = Int.randomID - let expectedResult = ReviewPageableList.mock() - apiClient.addResponse(.success(expectedResult)) - let expectedRequest = TVSeriesReviewsRequest(id: tvSeriesID, page: nil, language: nil) - - let result = try await service.reviews(forTVSeries: tvSeriesID) - - XCTAssertEqual(result, expectedResult) - XCTAssertEqual(apiClient.lastRequest as? TVSeriesReviewsRequest, expectedRequest) - } - - func testReviewsWithLanguageReturnsReviews() async throws { - let tvSeriesID = Int.randomID - let language = "en" - let expectedResult = ReviewPageableList.mock() - apiClient.addResponse(.success(expectedResult)) - let expectedRequest = TVSeriesReviewsRequest(id: tvSeriesID, page: nil, language: language) - - let result = try await service.reviews(forTVSeries: tvSeriesID, language: language) - - XCTAssertEqual(result, expectedResult) - XCTAssertEqual(apiClient.lastRequest as? TVSeriesReviewsRequest, expectedRequest) - } - - func testImagesReturnsImages() async throws { - let tvSeriesID = Int.randomID - let expectedResult = ImageCollection.mock() - apiClient.addResponse(.success(expectedResult)) - let expectedRequest = TVSeriesImagesRequest(id: tvSeriesID, languages: nil) - - let result = try await service.images(forTVSeries: tvSeriesID) - - XCTAssertEqual(result, expectedResult) - XCTAssertEqual(apiClient.lastRequest as? TVSeriesImagesRequest, expectedRequest) - } - - func testImagesWithFilterReturnsImages() async throws { - let tvSeriesID = Int.randomID - let languages = ["en-GB", "fr"] - let expectedResult = ImageCollection.mock() - apiClient.addResponse(.success(expectedResult)) - let expectedRequest = TVSeriesImagesRequest(id: tvSeriesID, languages: languages) - - let filter = TVSeriesImageFilter(languages: languages) - let result = try await service.images(forTVSeries: tvSeriesID, filter: filter) - - XCTAssertEqual(result, expectedResult) - XCTAssertEqual(apiClient.lastRequest as? TVSeriesImagesRequest, expectedRequest) - } - - func testVideosReturnsVideos() async throws { - let expectedResult = VideoCollection.mock() - let tvSeriesID = expectedResult.id - apiClient.addResponse(.success(expectedResult)) - let expectedRequest = TVSeriesVideosRequest(id: tvSeriesID, languages: nil) - - let result = try await service.videos(forTVSeries: tvSeriesID) - - XCTAssertEqual(result, expectedResult) - XCTAssertEqual(apiClient.lastRequest as? TVSeriesVideosRequest, expectedRequest) - } - - func testVideosWithFilterReturnsVideos() async throws { - let expectedResult = VideoCollection.mock() - let tvSeriesID = expectedResult.id - let languages = ["en", "fr"] - apiClient.addResponse(.success(expectedResult)) - let expectedRequest = TVSeriesVideosRequest(id: tvSeriesID, languages: languages) - - let filter = TVSeriesVideoFilter(languages: languages) - let result = try await service.videos(forTVSeries: tvSeriesID, filter: filter) - - XCTAssertEqual(result, expectedResult) - XCTAssertEqual(apiClient.lastRequest as? TVSeriesVideosRequest, expectedRequest) - } - - func testRecommendationsReturnsTVSeries() async throws { - let tvSeriesID = Int.randomID - let expectedResult = TVSeriesPageableList.mock() - apiClient.addResponse(.success(expectedResult)) - let expectedRequest = TVSeriesRecommendationsRequest(id: tvSeriesID, page: nil, language: nil) - - let result = try await service.recommendations(forTVSeries: tvSeriesID) - - XCTAssertEqual(result, expectedResult) - XCTAssertEqual(apiClient.lastRequest as? TVSeriesRecommendationsRequest, expectedRequest) - } - - func testRecommendationsWithPageAndLanguageReturnsTVSeries() async throws { - let tvSeriesID = Int.randomID - let page = 2 - let language = "en" - let expectedResult = TVSeriesPageableList.mock() - apiClient.addResponse(.success(expectedResult)) - let expectedRequest = TVSeriesRecommendationsRequest(id: tvSeriesID, page: page, language: language) - - let result = try await service.recommendations(forTVSeries: tvSeriesID, page: page, language: language) - - XCTAssertEqual(result, expectedResult) - XCTAssertEqual(apiClient.lastRequest as? TVSeriesRecommendationsRequest, expectedRequest) - } - - func testSimilarReturnsTVSeries() async throws { - let tvSeriesID = Int.randomID - let expectedResult = TVSeriesPageableList.mock() - apiClient.addResponse(.success(expectedResult)) - let expectedRequest = SimilarTVSeriesRequest(id: tvSeriesID, page: nil, language: nil) - - let result = try await service.similar(toTVSeries: tvSeriesID) - - XCTAssertEqual(result, expectedResult) - XCTAssertEqual(apiClient.lastRequest as? SimilarTVSeriesRequest, expectedRequest) - } - - func testSimilarWithPageAndLanguageReturnsTVSeries() async throws { - let tvSeriesID = Int.randomID - let page = 2 - let language = "en" - let expectedResult = TVSeriesPageableList.mock() - apiClient.addResponse(.success(expectedResult)) - let expectedRequest = SimilarTVSeriesRequest(id: tvSeriesID, page: page, language: language) - - let result = try await service.similar(toTVSeries: tvSeriesID, page: page, language: language) - - XCTAssertEqual(result, expectedResult) - XCTAssertEqual(apiClient.lastRequest as? SimilarTVSeriesRequest, expectedRequest) - } - - func testPopularReturnsTVSeries() async throws { - let expectedResult = TVSeriesPageableList.mock() - apiClient.addResponse(.success(expectedResult)) - let expectedRequest = PopularTVSeriesRequest(page: nil, language: nil) - - let result = try await service.popular() - - XCTAssertEqual(result, expectedResult) - XCTAssertEqual(apiClient.lastRequest as? PopularTVSeriesRequest, expectedRequest) - } - - func testPopularWithPageAndLanguageReturnsTVSeries() async throws { - let page = 2 - let language = "en" - let expectedResult = TVSeriesPageableList.mock() - apiClient.addResponse(.success(expectedResult)) - let expectedRequest = PopularTVSeriesRequest(page: page, language: language) - - let result = try await service.popular(page: page, language: language) - - XCTAssertEqual(result, expectedResult) - XCTAssertEqual(apiClient.lastRequest as? PopularTVSeriesRequest, expectedRequest) - } - - func testWatchReturnsWatchProviders() async throws { - let expectedResult = ShowWatchProviderResult.mock() - let tvSeriesID = 1 - let country = "GB" - apiClient.addResponse(.success(expectedResult)) - let expectedRequest = TVSeriesWatchProvidersRequest(id: tvSeriesID) - - let result = try await service.watchProviders(forTVSeries: tvSeriesID, country: country) - - XCTAssertEqual(result, expectedResult.results[country]) - XCTAssertEqual(apiClient.lastRequest as? TVSeriesWatchProvidersRequest, expectedRequest) - } - - func testExternalLinksReturnsExternalLinks() async throws { - let expectedResult = TVSeriesExternalLinksCollection.lockeAndKey - let tvSeriesID = 86423 - apiClient.addResponse(.success(expectedResult)) - let expectedRequest = TVSeriesExternalLinksRequest(id: tvSeriesID) - - let result = try await service.externalLinks(forTVSeries: tvSeriesID) - - XCTAssertEqual(result, expectedResult) - XCTAssertEqual(apiClient.lastRequest as? TVSeriesExternalLinksRequest, expectedRequest) - } - -} diff --git a/Tests/TMDbTests/Domain/Services/Trending/TrendingServiceTests.swift b/Tests/TMDbTests/Domain/Services/Trending/TrendingServiceTests.swift index 3dfb86a8..99139727 100644 --- a/Tests/TMDbTests/Domain/Services/Trending/TrendingServiceTests.swift +++ b/Tests/TMDbTests/Domain/Services/Trending/TrendingServiceTests.swift @@ -63,6 +63,22 @@ final class TrendingServiceTests: XCTestCase { XCTAssertEqual(apiClient.lastRequest as? TrendingMoviesRequest, expectedRequest) } + func testMoviesWhenErrorsThrowsError() async throws { + let timeWindow = TrendingTimeWindowFilterType.day + apiClient.addResponse(.failure(.unknown)) + + var error: Error? + do { + _ = try await service.movies(inTimeWindow: timeWindow) + } catch let err { + error = err + } + + let tmdbAPIError = try XCTUnwrap(error as? TMDbError) + + XCTAssertEqual(tmdbAPIError, .unknown) + } + func testTVSeriesReturnsTVSeries() async throws { let timeWindow = TrendingTimeWindowFilterType.day let expectedResult = TVSeriesPageableList.mock() @@ -89,6 +105,22 @@ final class TrendingServiceTests: XCTestCase { XCTAssertEqual(apiClient.lastRequest as? TrendingTVSeriesRequest, expectedRequest) } + func testTVSeriesWhenErrorsThrowsError() async throws { + let timeWindow = TrendingTimeWindowFilterType.day + apiClient.addResponse(.failure(.unknown)) + + var error: Error? + do { + _ = try await service.tvSeries(inTimeWindow: timeWindow) + } catch let err { + error = err + } + + let tmdbAPIError = try XCTUnwrap(error as? TMDbError) + + XCTAssertEqual(tmdbAPIError, .unknown) + } + func testPeopleReturnsPeople() async throws { let timeWindow = TrendingTimeWindowFilterType.day let expectedResult = PersonPageableList.mock() @@ -115,4 +147,20 @@ final class TrendingServiceTests: XCTestCase { XCTAssertEqual(apiClient.lastRequest as? TrendingPeopleRequest, expectedRequest) } + func testPeopleWhenErrorsThrowsError() async throws { + let timeWindow = TrendingTimeWindowFilterType.day + apiClient.addResponse(.failure(.unknown)) + + var error: Error? + do { + _ = try await service.people(inTimeWindow: timeWindow) + } catch let err { + error = err + } + + let tmdbAPIError = try XCTUnwrap(error as? TMDbError) + + XCTAssertEqual(tmdbAPIError, .unknown) + } + } diff --git a/Tests/TMDbTests/Domain/Services/WatchProviders/WatchProviderServiceTests.swift b/Tests/TMDbTests/Domain/Services/WatchProviders/WatchProviderServiceTests.swift index b9bd62d9..a79d5ddb 100644 --- a/Tests/TMDbTests/Domain/Services/WatchProviders/WatchProviderServiceTests.swift +++ b/Tests/TMDbTests/Domain/Services/WatchProviders/WatchProviderServiceTests.swift @@ -62,6 +62,21 @@ final class WatchProviderServiceTests: XCTestCase { XCTAssertEqual(apiClient.lastRequest as? WatchProviderRegionsRequest, expectedRequest) } + func testCountriesWhenErrorsThrowsError() async throws { + apiClient.addResponse(.failure(.unknown)) + + var error: Error? + do { + _ = try await service.countries() + } catch let err { + error = err + } + + let tmdbAPIError = try XCTUnwrap(error as? TMDbError) + + XCTAssertEqual(tmdbAPIError, .unknown) + } + func testMovieWatchProvidersReturnsWatchProviders() async throws { let watchProviderResult = WatchProviderResult.mock let expectedResult = watchProviderResult.results @@ -89,6 +104,21 @@ final class WatchProviderServiceTests: XCTestCase { XCTAssertEqual(apiClient.lastRequest as? WatchProvidersForMoviesRequest, expectedRequest) } + func testMovieWatchProvidersWhenErrorsThrowsError() async throws { + apiClient.addResponse(.failure(.unknown)) + + var error: Error? + do { + _ = try await service.movieWatchProviders() + } catch let err { + error = err + } + + let tmdbAPIError = try XCTUnwrap(error as? TMDbError) + + XCTAssertEqual(tmdbAPIError, .unknown) + } + func testTVSeriesWatchProvidersReturnsWatchProviders() async throws { let watchProviderResult = WatchProviderResult.mock let expectedResult = watchProviderResult.results @@ -116,4 +146,19 @@ final class WatchProviderServiceTests: XCTestCase { XCTAssertEqual(apiClient.lastRequest as? WatchProvidersForTVSeriesRequest, expectedRequest) } + func testTVSeriesWatchProvidersWhenErrorsThrowsError() async throws { + apiClient.addResponse(.failure(.unknown)) + + var error: Error? + do { + _ = try await service.tvSeriesWatchProviders() + } catch let err { + error = err + } + + let tmdbAPIError = try XCTUnwrap(error as? TMDbError) + + XCTAssertEqual(tmdbAPIError, .unknown) + } + } diff --git a/Tests/TMDbTests/Extensions/URL+QueryItemTests.swift b/Tests/TMDbTests/Extensions/URL+QueryItemTests.swift deleted file mode 100644 index d4c59e55..00000000 --- a/Tests/TMDbTests/Extensions/URL+QueryItemTests.swift +++ /dev/null @@ -1,329 +0,0 @@ -// -// URL+QueryItemTests.swift -// TMDb -// -// Copyright © 2024 Adam Young. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an AS IS BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// - -@testable import TMDb -import XCTest - -final class URLQueryItemTests: XCTestCase { - - func testAppendingIntPathComponentReturnsURL() throws { - let expectedResult = try XCTUnwrap(URL(string: "/some/path/2")) - - let result = try XCTUnwrap(URL(string: "/some/path")).appendingPathComponent(2) - - XCTAssertEqual(result, expectedResult) - } - - func testAppendingQueryItemWhenNoQueryItemsReturnsURL() throws { - let expectedResult = try XCTUnwrap(URL(string: "/some/path?a=b")) - - let result = try XCTUnwrap(URL(string: "/some/path")).appendingQueryItem(name: "a", value: "b") - - XCTAssertEqual(result, expectedResult) - } - - func testAppendingQueryItemWhenContainsQueryItemsReturnsURL() throws { - let expectedResult = try XCTUnwrap(URL(string: "/some/path?a=b&c=d")) - - let result = try XCTUnwrap(URL(string: "/some/path?a=b")).appendingQueryItem(name: "c", value: "d") - - XCTAssertEqual(result, expectedResult) - } - - func testAppendingAPIKeyWhenNoQueryItemsReturnsURL() throws { - let expectedResult = try XCTUnwrap(URL(string: "/some/path?api_key=123456")) - - let result = try XCTUnwrap(URL(string: "/some/path")).appendingAPIKey("123456") - - XCTAssertEqual(result, expectedResult) - } - - func testAppendingAPIKeyWhenContainsQueryItemsReturnsURL() throws { - let expectedResult = try XCTUnwrap(URL(string: "/some/path?a=b&api_key=123456")) - - let result = try XCTUnwrap(URL(string: "/some/path?a=b")).appendingAPIKey("123456") - - XCTAssertEqual(result, expectedResult) - } - - func testAppendingLanguageWithLocaleReturnsURL() throws { - let languageCode = "en" - let expectedResult = try XCTUnwrap(URL(string: "/some/path?language=\(languageCode)")) - - let result = try XCTUnwrap(URL(string: "/some/path")).appendingLanguage(languageCode) - - XCTAssertEqual(result, expectedResult) - } - - func testAppendingLanguageWithLocaleWithoutLanguageCodeReturnsURL() throws { - let expectedResult = try XCTUnwrap(URL(string: "/some/path")) - - let result = try XCTUnwrap(URL(string: "/some/path")).appendingLanguage(nil) - - XCTAssertEqual(result, expectedResult) - } - - func testAppendingLanguageWithLocaleWithoutRegionCodeReturnsURL() throws { - let languageCode = "en" - let expectedResult = try XCTUnwrap(URL(string: "/some/path?language=\(languageCode)")) - - let result = try XCTUnwrap(URL(string: "/some/path")).appendingLanguage(languageCode) - - XCTAssertEqual(result, expectedResult) - } - - func testAppendingImageLanguageWithLocaleReturnsURL() throws { - let languageCode = "en" - let expectedResult = try XCTUnwrap(URL(string: "/some/path?include_image_language=\(languageCode),null")) - - let result = try XCTUnwrap(URL(string: "/some/path")).appendingImageLanguage(languageCode) - - XCTAssertEqual(result, expectedResult) - } - - func testAppendingImageLanguageWithLocaleWithoutLanguageCodeReturnsURL() throws { - let expectedResult = try XCTUnwrap(URL(string: "/some/path")) - - let result = try XCTUnwrap(URL(string: "/some/path")).appendingImageLanguage(nil) - - XCTAssertEqual(result, expectedResult) - } - - func testAppendingImageLanguageWithLocaleWithoutRegionCodeReturnsURL() throws { - let languageCode = "en" - let expectedResult = try XCTUnwrap(URL(string: "/some/path?include_image_language=\(languageCode),null")) - - let result = try XCTUnwrap(URL(string: "/some/path")).appendingImageLanguage(languageCode) - - XCTAssertEqual(result, expectedResult) - } - - func testAppendingImageLanguageWithLocaleWhenContainsQueryItemsReturnsURL() throws { - let languageCode = "en" - let expectedResult = try XCTUnwrap(URL(string: "/some/path?a=b&include_image_language=\(languageCode),null")) - - let result = try XCTUnwrap(URL(string: "/some/path?a=b")).appendingImageLanguage(languageCode) - - XCTAssertEqual(result, expectedResult) - } - - func testAppendingVideoLanguageWithLocaleReturnsURL() throws { - let languageCode = "en" - let expectedResult = try XCTUnwrap(URL(string: "/some/path?include_video_language=en,null")) - - let result = try XCTUnwrap(URL(string: "/some/path")).appendingVideoLanguage(languageCode) - - XCTAssertEqual(result, expectedResult) - } - - func testAppendingVideoLanguageWithLocaleWithoutLanguageCodeReturnsURL() throws { - let expectedResult = try XCTUnwrap(URL(string: "/some/path")) - - let result = try XCTUnwrap(URL(string: "/some/path")).appendingVideoLanguage(nil) - - XCTAssertEqual(result, expectedResult) - } - - func testAppendingVideoLanguageWithLocaleWithoutRegionCodeReturnsURL() throws { - let languageCode = "en" - let expectedResult = try XCTUnwrap(URL(string: "/some/path?include_video_language=en,null")) - - let result = try XCTUnwrap(URL(string: "/some/path")).appendingVideoLanguage(languageCode) - - XCTAssertEqual(result, expectedResult) - } - - func testAppendingVideoLanguageWithLocaleWhenContainsQueryItemsReturnsURL() throws { - let languageCode = "en" - let expectedResult = try XCTUnwrap(URL(string: "/some/path?a=b&include_video_language=en,null")) - - let result = try XCTUnwrap(URL(string: "/some/path?a=b")).appendingVideoLanguage(languageCode) - - XCTAssertEqual(result, expectedResult) - } - - func testAppendingPageWhenNoQueryItemsAndPageIsNilReturnsURL() throws { - let expectedResult = try XCTUnwrap(URL(string: "/some/path")) - - let result = try XCTUnwrap(URL(string: "/some/path")).appendingPage(nil) - - XCTAssertEqual(result, expectedResult) - } - - func testAppendingPageWhenContainsQueryItemAndPageIsNilReturnsURL() throws { - let expectedResult = try XCTUnwrap(URL(string: "/some/path?a=b")) - - let result = try XCTUnwrap(URL(string: "/some/path?a=b")).appendingPage(nil) - - XCTAssertEqual(result, expectedResult) - } - - func testAppendingPageWhenNoQueryItemsAndPageIsLessThan1ReturnsURL() throws { - let expectedResult = try XCTUnwrap(URL(string: "/some/path?page=1")) - - let result = try XCTUnwrap(URL(string: "/some/path")).appendingPage(0) - - XCTAssertEqual(result, expectedResult) - } - - func testAppendingPageWhenContainsQueryItemAndPageIsLessThan1ReturnsURL() throws { - let expectedResult = try XCTUnwrap(URL(string: "/some/path?a=b&page=1")) - - let result = try XCTUnwrap(URL(string: "/some/path?a=b")).appendingPage(0) - - XCTAssertEqual(result, expectedResult) - } - - func testAppendingPageWhenNoQueryItemsAndPageIsBetween1and1000ReturnsURL() throws { - let expectedResult = try XCTUnwrap(URL(string: "/some/path?page=500")) - - let result = try XCTUnwrap(URL(string: "/some/path")).appendingPage(500) - - XCTAssertEqual(result, expectedResult) - } - - func testAppendingPageWhenContainsQueryItemAndPageIsBetween1and1000ReturnsURL() throws { - let expectedResult = try XCTUnwrap(URL(string: "/some/path?a=b&page=500")) - - let result = try XCTUnwrap(URL(string: "/some/path?a=b")).appendingPage(500) - - XCTAssertEqual(result, expectedResult) - } - - func testAppendingPageWhenNoQueryItemsAndPageIsGreaterThan1000ReturnsURL() throws { - let expectedResult = try XCTUnwrap(URL(string: "/some/path?page=1000")) - - let result = try XCTUnwrap(URL(string: "/some/path")).appendingPage(1001) - - XCTAssertEqual(result, expectedResult) - } - - func testAppendingPageWhenContainsQueryItemAndPageIsGreaterThan1000ReturnsURL() throws { - let expectedResult = try XCTUnwrap(URL(string: "/some/path?a=b&page=1000")) - - let result = try XCTUnwrap(URL(string: "/some/path?a=b")).appendingPage(1001) - - XCTAssertEqual(result, expectedResult) - } - - func testAppendingYearWhenNoQueryItemsAndYearIsNilReturnsURL() throws { - let expectedResult = try XCTUnwrap(URL(string: "/some/path")) - - let result = try XCTUnwrap(URL(string: "/some/path")).appendingYear(nil) - - XCTAssertEqual(result, expectedResult) - } - - func testAppendingYearWhenContainsQueryItemAndYearIsNilReturnsURL() throws { - let expectedResult = try XCTUnwrap(URL(string: "/some/path?a=b")) - - let result = try XCTUnwrap(URL(string: "/some/path?a=b")).appendingYear(nil) - - XCTAssertEqual(result, expectedResult) - } - - func testAppendingYearWhenNoQueryItemsAndYearIsNotNilReturnsURL() throws { - let expectedResult = try XCTUnwrap(URL(string: "/some/path?year=2020")) - - let result = try XCTUnwrap(URL(string: "/some/path")).appendingYear(2020) - - XCTAssertEqual(result, expectedResult) - } - - func testAppendingYearWhenContainsQueryItemAndYearIsNotNilReturnsURL() throws { - let expectedResult = try XCTUnwrap(URL(string: "/some/path?a=b&year=2020")) - - let result = try XCTUnwrap(URL(string: "/some/path?a=b")).appendingYear(2020) - - XCTAssertEqual(result, expectedResult) - } - - func testAppendingFirstAirDateYearWhenNoQueryItemsAndYearIsNilReturnsURL() throws { - let expectedResult = try XCTUnwrap(URL(string: "/some/path")) - - let result = try XCTUnwrap(URL(string: "/some/path")).appendingFirstAirDateYear(nil) - - XCTAssertEqual(result, expectedResult) - } - - func testAppendingFirstAirDateYearWhenContainsQueryItemAndYearIsNilReturnsURL() throws { - let expectedResult = try XCTUnwrap(URL(string: "/some/path?a=b")) - - let result = try XCTUnwrap(URL(string: "/some/path?a=b")).appendingFirstAirDateYear(nil) - - XCTAssertEqual(result, expectedResult) - } - - func testAppendingFirstAirDateYearWhenNoQueryItemsAndYearIsNotNilReturnsURL() throws { - let expectedResult = try XCTUnwrap(URL(string: "/some/path?first_air_date_year=2020")) - - let result = try XCTUnwrap(URL(string: "/some/path")).appendingFirstAirDateYear(2020) - - XCTAssertEqual(result, expectedResult) - } - - func testAppendingFirstAirDateYearWhenContainsQueryItemAndYearIsNotNilReturnsURL() throws { - let expectedResult = try XCTUnwrap(URL(string: "/some/path?a=b&first_air_date_year=2020")) - - let result = try XCTUnwrap(URL(string: "/some/path?a=b")).appendingFirstAirDateYear(2020) - - XCTAssertEqual(result, expectedResult) - } - - func testAppendingWithPeopleWhenNoQueryItemsAndWithPeopleIsNilReturnsURL() throws { - let expectedResult = try XCTUnwrap(URL(string: "/some/path")) - - let result = try XCTUnwrap(URL(string: "/some/path")).appendingWithPeople(nil) - - XCTAssertEqual(result, expectedResult) - } - - func testAppendingWithPeopleWhenContainsQueryItemAndWithPeopleIsNilReturnsURL() throws { - let expectedResult = try XCTUnwrap(URL(string: "/some/path?a=b")) - - let result = try XCTUnwrap(URL(string: "/some/path?a=b")).appendingWithPeople(nil) - - XCTAssertEqual(result, expectedResult) - } - - func testAppendingWithPeopleWhenNoQueryItemsAndWithPeopleHasOneElementReturnsURL() throws { - let expectedResult = try XCTUnwrap(URL(string: "/some/path?with_people=1")) - - let result = try XCTUnwrap(URL(string: "/some/path")).appendingWithPeople([1]) - - XCTAssertEqual(result, expectedResult) - } - - func testAppendingWithPeopleWhenContainsQueryItemAndWithPeopleHasOneElementReturnsURL() throws { - let expectedResult = try XCTUnwrap(URL(string: "/some/path?a=b&with_people=1")) - - let result = try XCTUnwrap(URL(string: "/some/path?a=b")).appendingWithPeople([1]) - - XCTAssertEqual(result, expectedResult) - } - - func testAppendingWithPeopleWhenContainsQueryItemAndWithPeopleHasTwoElementsReturnsURL() throws { - let expectedResult = try XCTUnwrap(URL(string: "/some/path?a=b&with_people=1,2")) - - let result = try XCTUnwrap(URL(string: "/some/path?a=b")).appendingWithPeople([1, 2]) - - XCTAssertEqual(result, expectedResult) - } - -}