Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Add unit test for FeaturedSummary sponsoredPodcasts #2290

Open
wants to merge 1 commit into
base: trunk
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,14 @@ public class DiscoverServerHandler {
}
}

public func discoverPodcastCollection(source: String) async -> PodcastCollection? {
return await withCheckedContinuation { continuation in
discoverRequest(path: source, type: PodcastCollection.self) { podcastCollection, _ in
continuation.resume(returning: podcastCollection)
}
}
}

public func discoverItem<T>(_ source: String?, type: T.Type) -> AnyPublisher<T, Error> where T: Decodable {
guard let source = source else {
return Fail(error: DiscoverServerError.badRequest).eraseToAnyPublisher()
Expand Down
24 changes: 24 additions & 0 deletions PocketCastsTests/Extensions/XCTestCase+waitForCondition.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
extension XCTestCase {
/// Waits for the provided condition to become true, executing the check block until the timeout is reached.
/// - Parameters:
/// - timeout: The maximum time to wait for the condition to become true.
/// - pollingInterval: The interval to wait between checks, in seconds.
/// - condition: A closure that returns a boolean value indicating whether the condition is met.
func waitForCondition(
timeout: TimeInterval,
pollingInterval: TimeInterval = 0.5,
condition: @escaping () -> Bool
) async {
let deadline = Date().addingTimeInterval(timeout)

while Date() < deadline {
if condition() {
return // Condition met, exit the function
}
try? await Task.sleep(nanoseconds: UInt64(pollingInterval * 1_000_000_000)) // Sleep for the polling interval
}

// If we reach here, the condition was not met in time
XCTFail("Condition was not met in time.")
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
import XCTest
@testable import podcasts
import PocketCastsServer


final class FeaturedSummaryViewControllerTests: XCTestCase {
@MainActor func testPopulateItem() async throws {
let vc = FeaturedSummaryViewController(nibName: nil, bundle: nil)

let jsonData = """
{
"id": "featured",
"title": "Featured",
"type": "podcast_list",
"summary_style": "carousel",
"expanded_style": "plain_list",
"source": "https://lists.pocketcasts.com/featured.json",
"category_id": null,
"sponsored_podcasts": [
{
"position": 0,
"source": "https://lists.pocketcasts.com/972fda60-5a69-4713-b925-bf89f69c5fda.json"
},
{
"position": 2,
"source": "https://lists.pocketcasts.com/478726f8-7b18-441b-bc0a-c49939697c38.json"
}
],
"regions": [
"au",
"at",
"be",
"br",
"ca",
"cn",
"dk",
"fi",
"fr",
"de",
"ie",
"in",
"it",
"jp",
"mx",
"nl",
"no",
"nz",
"pl",
"pt",
"ru",
"kr",
"es",
"se",
"ch",
"gb",
"us",
"za",
"sg",
"ph",
"hk",
"sa",
"tr",
"il",
"cz",
"tw",
"ua",
"global"
]
}
""".data(using: .utf8)!

let decoder = JSONDecoder()
let featuredItem = try decoder.decode(DiscoverItem.self, from: jsonData)

vc.populateFrom(item: featuredItem, region: "global", category: nil)

await self.waitForCondition(timeout: 5) {
vc.podcasts.isEmpty == false
}

for podcast in featuredItem.sponsoredPodcasts ?? [] {
let index = try XCTUnwrap(podcast.position)
let source = try XCTUnwrap(podcast.source)
let loadedPodcast = await DiscoverServerHandler.shared.discoverPodcastCollection(source: source)
XCTAssertEqual(vc.podcasts[index].uuid, loadedPodcast?.podcasts?.first?.uuid)
}

vc.populateFrom(item: featuredItem, region: "global", category: nil)

self.eventually(timeout: 5) {
vc.podcasts.isEmpty == false
}

for podcast in featuredItem.sponsoredPodcasts ?? [] {
let index = try XCTUnwrap(podcast.position)
let source = try XCTUnwrap(podcast.source)
let loadedPodcast = await DiscoverServerHandler.shared.discoverPodcastCollection(source: source)
XCTAssertEqual(vc.podcasts[index].uuid, loadedPodcast?.podcasts?.first?.uuid)
}
}
}
8 changes: 8 additions & 0 deletions podcasts.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -1663,6 +1663,7 @@
F52B4F8C2BB4A9CA00E87BE4 /* CategoriesSelectorViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F52B4F8B2BB4A9CA00E87BE4 /* CategoriesSelectorViewController.swift */; };
F52B4F8E2BB4A9ED00E87BE4 /* CategoriesSelectorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F52B4F8D2BB4A9ED00E87BE4 /* CategoriesSelectorView.swift */; };
F533F19D2C24B8CB00EDE9AA /* ShareDestination.swift in Sources */ = {isa = PBXBuildFile; fileRef = F533F19C2C24B8CB00EDE9AA /* ShareDestination.swift */; };
F5431A622CC0B5EF003C36A0 /* XCTestCase+waitForCondition.swift in Sources */ = {isa = PBXBuildFile; fileRef = F5431A612CC0B5E9003C36A0 /* XCTestCase+waitForCondition.swift */; };
F543F6A42C0804FA00FEC8B6 /* AnyPublisher+Async.swift in Sources */ = {isa = PBXBuildFile; fileRef = F543F6A32C0804FA00FEC8B6 /* AnyPublisher+Async.swift */; };
F54E72192CA722A000CD5C86 /* Array+DiscoverItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = F54E72182CA722A000CD5C86 /* Array+DiscoverItem.swift */; };
F54E721D2CA7359800CD5C86 /* DiscoverCellType.swift in Sources */ = {isa = PBXBuildFile; fileRef = F54E721C2CA7359800CD5C86 /* DiscoverCellType.swift */; };
Expand Down Expand Up @@ -1698,6 +1699,7 @@
F5BA5C9C2C80F38200BDA5B9 /* UIViewControllerContentConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = F5BA5C9B2C80F38200BDA5B9 /* UIViewControllerContentConfiguration.swift */; };
F5BA5C9E2C81254300BDA5B9 /* DiscoverCollectionViewController+DiscoverDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = F5BA5C9D2C81254300BDA5B9 /* DiscoverCollectionViewController+DiscoverDelegate.swift */; };
F5BFF9892C6B0A9100A84561 /* Optional+ThrowOnNil.swift in Sources */ = {isa = PBXBuildFile; fileRef = F5BFF9882C6B0A9100A84561 /* Optional+ThrowOnNil.swift */; };
F5C9CB7C2CBF6DD7007F6830 /* FeaturedSummaryViewControllerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F5C9CB7B2CBF6DD0007F6830 /* FeaturedSummaryViewControllerTests.swift */; };
F5CFDB622C6DA2D600DE57B2 /* AudioClipExporter.swift in Sources */ = {isa = PBXBuildFile; fileRef = F5CFDB612C6DA2D600DE57B2 /* AudioClipExporter.swift */; };
F5D3A0D92B70950100EED067 /* MockURLHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = F5D3A0D82B70950100EED067 /* MockURLHandler.swift */; };
F5DBA58A2B756A8700AED77F /* PodcastSettings+ImportUserDefaultsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F5DBA5892B756A8700AED77F /* PodcastSettings+ImportUserDefaultsTests.swift */; };
Expand Down Expand Up @@ -3585,6 +3587,7 @@
F52B4F8B2BB4A9CA00E87BE4 /* CategoriesSelectorViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CategoriesSelectorViewController.swift; sourceTree = "<group>"; };
F52B4F8D2BB4A9ED00E87BE4 /* CategoriesSelectorView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CategoriesSelectorView.swift; sourceTree = "<group>"; };
F533F19C2C24B8CB00EDE9AA /* ShareDestination.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShareDestination.swift; sourceTree = "<group>"; };
F5431A612CC0B5E9003C36A0 /* XCTestCase+waitForCondition.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "XCTestCase+waitForCondition.swift"; sourceTree = "<group>"; };
F543F6A32C0804FA00FEC8B6 /* AnyPublisher+Async.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AnyPublisher+Async.swift"; sourceTree = "<group>"; };
F54E72182CA722A000CD5C86 /* Array+DiscoverItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Array+DiscoverItem.swift"; sourceTree = "<group>"; };
F54E721C2CA7359800CD5C86 /* DiscoverCellType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DiscoverCellType.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -3617,6 +3620,7 @@
F5BA5C9B2C80F38200BDA5B9 /* UIViewControllerContentConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIViewControllerContentConfiguration.swift; sourceTree = "<group>"; };
F5BA5C9D2C81254300BDA5B9 /* DiscoverCollectionViewController+DiscoverDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "DiscoverCollectionViewController+DiscoverDelegate.swift"; sourceTree = "<group>"; };
F5BFF9882C6B0A9100A84561 /* Optional+ThrowOnNil.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Optional+ThrowOnNil.swift"; sourceTree = "<group>"; };
F5C9CB7B2CBF6DD0007F6830 /* FeaturedSummaryViewControllerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FeaturedSummaryViewControllerTests.swift; sourceTree = "<group>"; };
F5CFDB612C6DA2D600DE57B2 /* AudioClipExporter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AudioClipExporter.swift; sourceTree = "<group>"; };
F5D3A0D82B70950100EED067 /* MockURLHandler.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MockURLHandler.swift; sourceTree = "<group>"; };
F5DBA5892B756A8700AED77F /* PodcastSettings+ImportUserDefaultsTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "PodcastSettings+ImportUserDefaultsTests.swift"; sourceTree = "<group>"; };
Expand Down Expand Up @@ -4750,6 +4754,7 @@
8B484EF828D256F5001AFA97 /* Date+Ext.swift */,
8B484EFA28D25719001AFA97 /* Double+Ext.swift */,
8BA55A1228CA7425002BECC5 /* XCTestCase+eventually.swift */,
F5431A612CC0B5E9003C36A0 /* XCTestCase+waitForCondition.swift */,
321AC0292B6AFC45008D6FF2 /* XCTestCase+WaitForNotification.swift */,
F5952FC92C057C6400754BC3 /* FMDatabaseQueue+Test.swift */,
F5F69D7F2C07C867000B3C87 /* FMDatabaseQueue+Test.swift */,
Expand Down Expand Up @@ -7134,6 +7139,7 @@
C7BF5E4829083B3F00733C1E /* Discover */ = {
isa = PBXGroup;
children = (
F5C9CB7B2CBF6DD0007F6830 /* FeaturedSummaryViewControllerTests.swift */,
C7BF5E4929083B5300733C1E /* DiscoverCoordinatorTests.swift */,
);
path = Discover;
Expand Down Expand Up @@ -9212,13 +9218,15 @@
FFF024CE2B62AC9400457373 /* IAPHelperTests.swift in Sources */,
8B3295432A5336DA00BDFA11 /* WhatsNewTests.swift in Sources */,
F586959A2C04320100E0754A /* PodcastManagerTests.swift in Sources */,
F5431A622CC0B5EF003C36A0 /* XCTestCase+waitForCondition.swift in Sources */,
C781EA412A6B72AE001DBFCC /* SearchableListViewModelTests.swift in Sources */,
FF6BBCEE2C53E9D000604A01 /* TranscriptManagerTests.swift in Sources */,
F5952FCA2C057C6400754BC3 /* FMDatabaseQueue+Test.swift in Sources */,
107836262C62816900DA3FF0 /* ABTestProviderTests.swift in Sources */,
8B484EF728D23F06001AFA97 /* PlaybackTimeHelperTests.swift in Sources */,
45ECEF8627E910FB00C65030 /* ShowNotesFormatterUtilsTests.swift in Sources */,
2F63CE9528809E5B00A34B51 /* ThemeTests.swift in Sources */,
F5C9CB7C2CBF6DD7007F6830 /* FeaturedSummaryViewControllerTests.swift in Sources */,
8BA6CAFE2C404C3600FB4704 /* ComposeFilterTests.swift in Sources */,
8B317BA728906CC200A26A13 /* TestingViewController.swift in Sources */,
8BA55A1028CA6843002BECC5 /* AnalyticsPlaybackHelperTests.swift in Sources */,
Expand Down
12 changes: 7 additions & 5 deletions podcasts/FeaturedSummaryViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ class FeaturedSummaryViewController: SimpleNotificationsViewController, GridLayo
}
}

private var podcasts = [DiscoverPodcast]()
private var sponsoredPodcasts = [DiscoverPodcast]()
private(set) var podcasts = [DiscoverPodcast]()
private(set) var sponsoredPodcasts = [DiscoverPodcast]()
private var lists: [PodcastCollection] = []

private static let cellId = "FeaturedCollectionViewCell"
Expand Down Expand Up @@ -212,14 +212,16 @@ class FeaturedSummaryViewController: SimpleNotificationsViewController, GridLayo
self.podcasts = Array(podcastsToShow.prefix(self.maxFeaturedItems))

// Add sponsored podcasts
for sponsoredPodcastToAdd in sponsoredPodcastsToAdd {
for sponsoredPodcastToAdd in sponsoredPodcastsToAdd.sorted(by: { $0.key < $1.key }) {
self.podcasts.insert(sponsoredPodcastToAdd.value, safelyAt: sponsoredPodcastToAdd.key)
}
self.sponsoredPodcasts = sponsoredPodcastsToAdd.map { $0.value }

// Update and reload
self.updatePageCount()
self.featuredCollectionView.reloadData()
if isViewLoaded {
self.updatePageCount()
self.featuredCollectionView.reloadData()
}
}
}

Expand Down