summaryrefslogtreecommitdiff
path: root/player-android/test/screens/podcast_episodes_screen_test.dart
diff options
context:
space:
mode:
Diffstat (limited to 'player-android/test/screens/podcast_episodes_screen_test.dart')
-rw-r--r--player-android/test/screens/podcast_episodes_screen_test.dart39
1 files changed, 39 insertions, 0 deletions
diff --git a/player-android/test/screens/podcast_episodes_screen_test.dart b/player-android/test/screens/podcast_episodes_screen_test.dart
index dcf289f..a027cc1 100644
--- a/player-android/test/screens/podcast_episodes_screen_test.dart
+++ b/player-android/test/screens/podcast_episodes_screen_test.dart
@@ -90,6 +90,11 @@ class _FakeApiClient extends PlayerApiClient {
/// Records every call to [downloadEpisode] — useful for download tests.
int downloadEpisodeCallCount = 0;
+ /// When non-null, [downloadEpisode] returns this completer's future instead
+ /// of resolving immediately. This lets a test hold the first call
+ /// in-flight so a second tap can be verified to be suppressed by the guard.
+ Completer<Media>? downloadCompleter;
+
@override
Future<List<PodcastEpisode>> listEpisodes(
int podcastSetId, {
@@ -111,6 +116,8 @@ class _FakeApiClient extends PlayerApiClient {
Future<Media> downloadEpisode(int episodeId) async {
downloadEpisodeCallCount++;
if (downloadError != null) throw downloadError!;
+ // If a completer is provided, the caller controls when the future resolves.
+ if (downloadCompleter != null) return downloadCompleter!.future;
return downloadResult!;
}
}
@@ -883,6 +890,38 @@ void main() {
expect(find.byType(SnackBar), findsOneWidget);
expect(find.textContaining('Could not reach'), findsOneWidget);
});
+
+ testWidgets(
+ 'double-tap download button only fires one API call',
+ (tester) async {
+ // Hold the first download in-flight so the button is still showing when
+ // the second tap happens — this is the window the guard must close.
+ final fakeClient = _FakeApiClient()
+ ..episodesResult = [_kEpisode1]
+ ..downloadCompleter = Completer<Media>();
+
+ await _pumpScreen(tester, fakeClient);
+ await tester.pumpAndSettle();
+
+ final downloadButton =
+ find.byKey(const Key('episode_download_button_1'));
+ expect(downloadButton, findsOneWidget);
+
+ // First tap: starts the download; future not yet resolved.
+ await tester.tap(downloadButton);
+ await tester.pump();
+
+ // Second tap: should be suppressed by the _pendingDownloads guard.
+ await tester.tap(downloadButton);
+ await tester.pump();
+
+ // Resolve the in-flight download to allow pumpAndSettle to complete.
+ fakeClient.downloadCompleter!.complete(_kDownloadedMedia);
+ await tester.pumpAndSettle();
+
+ // Despite two taps, the API must have been called exactly once.
+ expect(fakeClient.downloadEpisodeCallCount, equals(1));
+ });
});
// --------------------------------------------------------------------------