Skip to content

Commit

Permalink
Implement a simple cache for TMDB Configuration
Browse files Browse the repository at this point in the history
pietrocaselani committed Jan 20, 2019

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
1 parent 0256aab commit 75527ec
Showing 7 changed files with 166 additions and 4 deletions.
12 changes: 10 additions & 2 deletions CouchTracker.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
@@ -531,6 +531,7 @@
82930A21216C1C8500A824F6 /* SynchronizerDataSources.swift in Sources */ = {isa = PBXBuildFile; fileRef = 69723AC6CAF4ED73AC5EA0EF /* SynchronizerDataSources.swift */; };
829A590121B2404700B67753 /* Container.swift in Sources */ = {isa = PBXBuildFile; fileRef = 829A590021B2404700B67753 /* Container.swift */; };
829A590221B2404700B67753 /* Container.swift in Sources */ = {isa = PBXBuildFile; fileRef = 829A590021B2404700B67753 /* Container.swift */; };
829CDAAC21F508E500BF1E2F /* ConfigurationCachedRepositoryTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 829CDAAB21F508E500BF1E2F /* ConfigurationCachedRepositoryTests.swift */; };
82C6477C21D72F3500175B24 /* TrendingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 82C6477B21D72F3500175B24 /* TrendingView.swift */; };
82C6477E21D72F5200175B24 /* DefaultEmptyView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 82C6477D21D72F5200175B24 /* DefaultEmptyView.swift */; };
82C6478021D7345200175B24 /* PosterAndTitleCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 82C6477F21D7345200175B24 /* PosterAndTitleCell.swift */; };
@@ -543,6 +544,7 @@
82E1DE6A21D96E2C006C8EA8 /* ShowsManagerViewState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 82E1DE6821D96E2C006C8EA8 /* ShowsManagerViewState.swift */; };
82E1DE6C21D9A530006C8EA8 /* ShowManagerViewState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 82E1DE6B21D9A530006C8EA8 /* ShowManagerViewState.swift */; };
82E1DE6D21D9A533006C8EA8 /* ShowManagerViewState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 82E1DE6B21D9A530006C8EA8 /* ShowManagerViewState.swift */; };
82EB74B021F50B830024C1E8 /* TMDBConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 82EB74AF21F50B830024C1E8 /* TMDBConfiguration.swift */; };
82F85FD821D5ACCF006A66B9 /* StringExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 82F85FD721D5ACCF006A66B9 /* StringExtensions.swift */; };
82F85FD921D5ACCF006A66B9 /* StringExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 82F85FD721D5ACCF006A66B9 /* StringExtensions.swift */; };
82F85FDB21D5AE1F006A66B9 /* UIViewControllerExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 82F85FDA21D5AE1F006A66B9 /* UIViewControllerExtensions.swift */; };
@@ -997,6 +999,7 @@
82882F5921DED8BA00B1A732 /* SearchiOSRouter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchiOSRouter.swift; sourceTree = "<group>"; };
82930A18216C1C7B00A824F6 /* DefaultWatchedShowEntityDownloader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DefaultWatchedShowEntityDownloader.swift; sourceTree = "<group>"; };
829A590021B2404700B67753 /* Container.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Container.swift; sourceTree = "<group>"; };
829CDAAB21F508E500BF1E2F /* ConfigurationCachedRepositoryTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConfigurationCachedRepositoryTests.swift; sourceTree = "<group>"; };
82C6477B21D72F3500175B24 /* TrendingView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TrendingView.swift; sourceTree = "<group>"; };
82C6477D21D72F5200175B24 /* DefaultEmptyView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DefaultEmptyView.swift; sourceTree = "<group>"; };
82C6477F21D7345200175B24 /* PosterAndTitleCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PosterAndTitleCell.swift; sourceTree = "<group>"; };
@@ -1005,6 +1008,7 @@
82E1DE6521D9657A006C8EA8 /* MoviesManagerViewState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoviesManagerViewState.swift; sourceTree = "<group>"; };
82E1DE6821D96E2C006C8EA8 /* ShowsManagerViewState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShowsManagerViewState.swift; sourceTree = "<group>"; };
82E1DE6B21D9A530006C8EA8 /* ShowManagerViewState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShowManagerViewState.swift; sourceTree = "<group>"; };
82EB74AF21F50B830024C1E8 /* TMDBConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TMDBConfiguration.swift; sourceTree = "<group>"; };
82F85FD721D5ACCF006A66B9 /* StringExtensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StringExtensions.swift; sourceTree = "<group>"; };
82F85FDA21D5AE1F006A66B9 /* UIViewControllerExtensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIViewControllerExtensions.swift; sourceTree = "<group>"; };
AF31C37B5587B21736E8BA65 /* Pods_CouchTrackerApp.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_CouchTrackerApp.framework; sourceTree = BUILT_PRODUCTS_DIR; };
@@ -1174,13 +1178,14 @@
4F0F5708203D5F4C00B86CB8 /* CouchTrackerCoreTests */ = {
isa = PBXGroup;
children = (
8209AB1421CEF4970027BBF3 /* Fixtures */,
64C384021F6C134F00FC9930 /* AppConfigurations */,
4F3A5945204EABB60061ABB7 /* AppFlow */,
4F7B09532016B53B001F6C50 /* BaseViewMock.swift */,
644EE1491F55E01E0053D631 /* Configuration */,
4F3F67D9209E66F900D3E403 /* CouchTrackerCoreTests-Bridging-Header.h */,
4F3F67D6209E665700D3E403 /* Extensions */,
8209AB1421CEF4970027BBF3 /* Fixtures */,
8209AB1621CEF59F0027BBF3 /* Fixtures.swift */,
69723117CCF8B5DEDE1B3046 /* Genre */,
6406BEEC1F4DC372004661C4 /* GenreRepositoryMock.swift */,
647B66451F5888CE00B38D2A /* Images */,
@@ -1205,7 +1210,6 @@
6454D1701F703CFD008C4E5F /* TraktLogin */,
6434CA651F752ED400EA3AD8 /* TraktLoginObservableMock.swift */,
648390C81F504E7500911BA0 /* Trending */,
8209AB1621CEF59F0027BBF3 /* Fixtures.swift */,
);
path = CouchTrackerCoreTests;
sourceTree = "<group>";
@@ -1490,6 +1494,7 @@
8209AB0A21CED6800027BBF3 /* Error+Mock.swift */,
8209AB0F21CEF39E0027BBF3 /* WatchedShowEntity+Mock.swift */,
8209AB1121CEF3F40027BBF3 /* Bundle+Testing.swift */,
82EB74AF21F50B830024C1E8 /* TMDBConfiguration.swift */,
);
path = Extensions;
sourceTree = "<group>";
@@ -1810,6 +1815,7 @@
isa = PBXGroup;
children = (
644EE1461F55DF9F0053D631 /* ConfigurationRepositoryMock.swift */,
829CDAAB21F508E500BF1E2F /* ConfigurationCachedRepositoryTests.swift */,
);
path = Configuration;
sourceTree = "<group>";
@@ -3162,6 +3168,7 @@
4F0F5944203D991A00B86CB8 /* TraktEntitiesMock.swift in Sources */,
4FC97A1F203F163300C2B924 /* ShowProgressCellDefaultPresenterTest.swift in Sources */,
4FC97A23203F683000C2B924 /* ShowEpisodeDefaultPresenterTest.swift in Sources */,
82EB74B021F50B830024C1E8 /* TMDBConfiguration.swift in Sources */,
4F0F57DB203D61B300B86CB8 /* MovieDetailsInteractorTest.swift in Sources */,
4F0F57DC203D61B300B86CB8 /* MovieDetailsMocks.swift in Sources */,
4F6102232052791D0079EDBA /* ShowManagerMocks.swift in Sources */,
@@ -3213,6 +3220,7 @@
4FC97A21203F166400C2B924 /* ShowProgressCellMocks.swift in Sources */,
4F0F5806203D61B300B86CB8 /* PosterCellInteractorTest.swift in Sources */,
4F0F5807203D61B300B86CB8 /* PosterCellPresenterTest.swift in Sources */,
829CDAAC21F508E500BF1E2F /* ConfigurationCachedRepositoryTests.swift in Sources */,
4F0F5808203D61B300B86CB8 /* PosterCellMocks.swift in Sources */,
4F0F5809203D61B300B86CB8 /* TrendingInteractorTest.swift in Sources */,
4F0F580A203D61B300B86CB8 /* TrendingMocks.swift in Sources */,
13 changes: 13 additions & 0 deletions CouchTrackerCore/Configuration/ConfigurationCachedRepository.swift
Original file line number Diff line number Diff line change
@@ -3,14 +3,27 @@ import TMDBSwift

public final class ConfigurationCachedRepository: ConfigurationRepository {
private let tmdbProvider: TMDBProvider
private var cachedConfigurations: Configuration?

public init(tmdbProvider: TMDBProvider) {
self.tmdbProvider = tmdbProvider
}

public func fetchConfiguration() -> Observable<Configuration> {
guard let configuration = cachedConfigurations else {
return fetchConfigrationsFromAPI()
}

return Observable.just(configuration)
}

private func fetchConfigrationsFromAPI() -> Observable<Configuration> {
return tmdbProvider.configuration.rx.request(.configuration)
.filterSuccessfulStatusAndRedirectCodes()
.map(Configuration.self)
.do(onSuccess: { [weak self] config in
self?.cachedConfigurations = config
})
.asObservable()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
@testable import CouchTrackerCore
import RxTest
import TMDBSwift
import XCTest

final class ConfigurationCachedRepositoryTests: XCTestCase {
func testConfigurationCachedRepository_fetchFromCache_whenCacheIsAvailable() {
// Given
let tmdb = TMDBProviderMock()
let repository = ConfigurationCachedRepository(tmdbProvider: tmdb)
let scheduler = TestSchedulers()

// When
let observer1 = scheduler.start { repository.fetchConfiguration() }
let observer2 = scheduler.start { repository.fetchConfiguration() }

// Then
let mockConfig = Configuration.mockDefaultConfiguration()
let expectedEvents1 = [Recorded.next(200, mockConfig),
Recorded.completed(200)]
let expectedEvents2 = [Recorded.next(1000, mockConfig),
Recorded.completed(1000)]

XCTAssertEqual(observer1.events, expectedEvents1)
XCTAssertEqual(observer2.events, expectedEvents2)

let mockProvider = tmdb.configuration as! MoyaProviderMock
XCTAssertEqual(mockProvider.requestInvokedCount, 1)
}
}
7 changes: 7 additions & 0 deletions CouchTrackerCoreTests/Extensions/TMDBConfiguration.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import TMDBSwift

extension Configuration {
static func mockDefaultConfiguration(decoder _: JSONDecoder = .init()) -> Configuration {
return Fixtures.TMDBConfiguration.modelFor(file: "default_configuration", ofType: Configuration.self)
}
}
6 changes: 6 additions & 0 deletions CouchTrackerCoreTests/Fixtures.swift
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
enum Fixtures: String {
case WatchedShowEntity
case TMDBConfiguration

func jsonDataFor(file named: String) -> Data {
let relativePath = "Fixtures/\(rawValue)/\(named)"
@@ -10,4 +11,9 @@ enum Fixtures: String {

return try! Data(contentsOf: URL(fileURLWithPath: path, isDirectory: false))
}

func modelFor<T: Decodable>(file named: String, ofType type: T.Type, decoder: JSONDecoder = .init()) -> T {
let data = jsonDataFor(file: named)
return try! decoder.decode(type, from: data)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
{
"images": {
"base_url": "http://image.tmdb.org/t/p/",
"secure_base_url": "https://image.tmdb.org/t/p/",
"backdrop_sizes": [
"w300",
"w780",
"w1280",
"original"
],
"logo_sizes": [
"w45",
"w92",
"w154",
"w185",
"w300",
"w500",
"original"
],
"poster_sizes": [
"w92",
"w154",
"w185",
"w342",
"w500",
"w780",
"original"
],
"profile_sizes": [
"w45",
"w185",
"h632",
"original"
],
"still_sizes": [
"w92",
"w185",
"w300",
"original"
]
},
"change_keys": [
"adult",
"air_date",
"also_known_as",
"alternative_titles",
"biography",
"birthday",
"budget",
"cast",
"certifications",
"character_names",
"created_by",
"crew",
"deathday",
"episode",
"episode_number",
"episode_run_time",
"freebase_id",
"freebase_mid",
"general",
"genres",
"guest_stars",
"homepage",
"images",
"imdb_id",
"languages",
"name",
"network",
"origin_country",
"original_name",
"original_title",
"overview",
"parts",
"place_of_birth",
"plot_keywords",
"production_code",
"production_companies",
"production_countries",
"releases",
"revenue",
"runtime",
"season",
"season_number",
"season_regular",
"spoken_languages",
"status",
"tagline",
"title",
"translations",
"tvdb_id",
"tvrage_id",
"type",
"video",
"videos"
]
}

4 changes: 2 additions & 2 deletions CouchTrackerCoreTests/Images/ImageCachedRepositoryTest.swift
Original file line number Diff line number Diff line change
@@ -14,7 +14,7 @@ final class ImageCachedRepositoryTest: XCTestCase {
super.setUp()

repository = ImageCachedRepository(tmdb: tmdbProviderMock, tvdb: tvdbProviderMock,
cofigurationRepository: configurationRepositoryMock, schedulers: scheduler)
configurationRepository: configurationRepositoryMock, schedulers: scheduler)

observer = scheduler.createObserver(ImagesEntity.self)
episodeObserver = scheduler.createObserver(URL.self)
@@ -170,7 +170,7 @@ final class ImageCachedRepositoryTest: XCTestCase {

func testImageCachedRepository_fetchEpisodeImages_fromTVDB_becauseTMDBThrowsError_withSpecificSizes() {
let repository = ImageCachedRepository(tmdb: TMDBErrorProviderMock(), tvdb: tvdbProviderMock,
cofigurationRepository: configurationRepositoryMock, schedulers: scheduler)
configurationRepository: configurationRepositoryMock, schedulers: scheduler)

let input = EpisodeImageInputMock(tmdb: 1399, tvdb: 3_254_641, season: 1, number: 1)

0 comments on commit 75527ec

Please sign in to comment.