diff --git a/lib/src/features/albums/presentation/album_detail_screen/album_collection_edit_modal.dart b/lib/src/features/albums/presentation/album_detail_screen/album_collection_edit_modal.dart index 5b06b0fa..14d8c45a 100644 --- a/lib/src/features/albums/presentation/album_detail_screen/album_collection_edit_modal.dart +++ b/lib/src/features/albums/presentation/album_detail_screen/album_collection_edit_modal.dart @@ -12,11 +12,17 @@ class AlbumCollectionEditModal { final Album album; + static const albumCollectionStatusModal = Key('album-collection-status-modal'); + static const saveBtnKey = Key('save-btn-key'); + static const statusDropdownKey = Key('status-dropdown-key'); + static const mediaTypeDropdownKey = Key('media-type-dropdown-key'); + static const ratingBarDropdownKey = Key('rating-bar-dropdown-key'); + AlbumCollectionEditModal(this.context, this.album); Widget build() { - return SizedBox( - height: 400, + return SingleChildScrollView( + key: albumCollectionStatusModal, child: Padding( padding: const EdgeInsets.all(Sizes.p16), child: Column( @@ -35,6 +41,7 @@ class AlbumCollectionEditModal { child: Column( children: [ SimpleDropdownInput( + key: statusDropdownKey, value: value.purchaseStatus ?? 'Nothing', label: 'Status', onChanged: (value) { @@ -50,6 +57,7 @@ class AlbumCollectionEditModal { ], ), SimpleDropdownInput( + key: mediaTypeDropdownKey, value: value.mediaType ?? 'Other', label: 'Media type', onChanged: (value) { @@ -87,10 +95,11 @@ class AlbumCollectionEditModal { const Divider(), gapH16, ElevatedButton( + key: saveBtnKey, onPressed: () { ref.read(albumDetailControllerProvider(album.id).notifier) .submitUpdateStatus(); - context.pop(); + context.pop(); }, style: ElevatedButton.styleFrom( minimumSize: const Size.fromHeight(50), // NEW diff --git a/test/src/features/albums/album_robot.dart b/test/src/features/albums/album_robot.dart index 8f0e88ca..d31e2b66 100644 --- a/test/src/features/albums/album_robot.dart +++ b/test/src/features/albums/album_robot.dart @@ -1,9 +1,11 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_test/flutter_test.dart'; +import 'package:go_router/go_router.dart'; import 'package:vocadb_app/src/common_widgets/error_message_widget.dart'; import 'package:vocadb_app/src/features/albums/data/album_repository.dart'; import 'package:vocadb_app/src/features/albums/domain/album.dart'; +import 'package:vocadb_app/src/features/albums/presentation/album_detail_screen/album_collection_edit_modal.dart'; import 'package:vocadb_app/src/features/albums/presentation/album_detail_screen/album_detail_screen.dart'; import 'package:vocadb_app/src/features/albums/presentation/album_detail_screen/widgets/widgets.dart'; import 'package:vocadb_app/src/features/albums/presentation/tracks_list/tracks_list_view.dart'; @@ -30,9 +32,16 @@ class AlbumRobot { if (authRepository != null) authRepositoryProvider.overrideWithValue(authRepository), ], - child: MaterialApp( - home: AlbumDetailScreen( - album: Album(id: 1, name: 'test-album'), + child: MaterialApp.router( + routerConfig: GoRouter( + routes: [ + GoRoute( + path: '/', + builder: (context, state) => AlbumDetailScreen( + album: Album(id: 1, name: 'test-album'), + ), + ), + ], ), ), ), @@ -70,6 +79,12 @@ class AlbumRobot { (visible) ? expect(finder, findsOneWidget) : expect(finder, findsNothing); } + Future expectSaveCollectionStatusModalVisible(bool visible) async { + final finder = + find.byKey(AlbumCollectionEditModal.albumCollectionStatusModal); + (visible) ? expect(finder, findsOneWidget) : expect(finder, findsNothing); + } + Future scrollDown({double offset = -800}) async { await tester.drag(find.byType(CustomScrollView), Offset(0, offset)); await tester.pump(); @@ -100,6 +115,22 @@ class AlbumRobot { expect(finder, findsOneWidget); } + Future tapAddButton() async { + final finder = find.byKey(AlbumDetailButtonBar.addBtnKey); + expect(finder, findsOneWidget); + + await tester.tap(finder); + await tester.pump(); + } + + Future tapAlbumCollectionStatusSaveButton() async { + final finder = find.byKey(AlbumCollectionEditModal.saveBtnKey); + expect(finder, findsOneWidget); + await tester.ensureVisible(finder); + await tester.tap(finder); + await tester.pump(); + } + Future expectShareButtonVisible() async { final finder = find.byKey(AlbumDetailButtonBar.shareBtnKey); expect(finder, findsOneWidget); diff --git a/test/src/features/albums/presentation/album_detail_screen/album_detail_screen_test.dart b/test/src/features/albums/presentation/album_detail_screen/album_detail_screen_test.dart index eaa7b0b6..a365b60a 100644 --- a/test/src/features/albums/presentation/album_detail_screen/album_detail_screen_test.dart +++ b/test/src/features/albums/presentation/album_detail_screen/album_detail_screen_test.dart @@ -1,8 +1,16 @@ +import 'dart:io'; + +import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:mocktail/mocktail.dart'; import 'package:vocadb_app/src/features/albums/data/constants/fake_album_detail.dart'; import 'package:vocadb_app/src/features/albums/domain/album.dart'; +import 'package:vocadb_app/src/features/albums/domain/album_collection.dart'; +import 'package:vocadb_app/src/features/albums/domain/album_rate.dart'; +import 'package:vocadb_app/src/features/albums/presentation/album_detail_screen/album_collection_edit_modal.dart'; +import 'package:vocadb_app/src/features/albums/presentation/album_detail_screen/album_detail_screen.dart'; import 'package:vocadb_app/src/features/albums/presentation/album_detail_screen/widgets/album_basic_info.dart'; +import 'package:vocadb_app/src/features/albums/presentation/album_detail_screen/widgets/album_detail_button_bar.dart'; import 'package:vocadb_app/src/features/authentication/domain/app_user.dart'; import '../../../../mocks.dart'; @@ -157,4 +165,47 @@ void main() { verify(() => albumRepository.fetchAlbumID(any())); }); + + testWidgets('album detail screen with tap save album collection status', + (tester) async { + + final r = AlbumRobot(tester); + + when(() => albumRepository.fetchAlbumID(any())) + .thenAnswer((invocation) => Future.value(Album(id: 1))); + + when(() => albumRepository.rateAlbum(1, const AlbumRate(mediaType: 'DigitalDownload', collectionStatus: 'Owned', rating: 5))) + .thenAnswer((invocation) => Future.value(Album(id: 1))); + + when(() => authRepository.currentUser) + .thenReturn(const AppUser(id: 1, name: 'test')); + + when(() => authRepository.getAlbumCollection(1)) + .thenAnswer((invocation) => Future.value(const AlbumCollection(mediaType: 'DigitalDownload', purchaseStatus: 'Owned' ,rating: 5))); + + await r.pumpAlbumDetailScreen( + albumRepository: albumRepository, + authRepository: authRepository, + ); + + await r.expectErrorMessageWidgetNotVisible(); + + await r.expectAlbumDetailImageVisible(); + + expect(find.byKey(AlbumCollectionEditModal.albumCollectionStatusModal), findsNothing); + await tester.tap(find.byKey(AlbumDetailButtonBar.addBtnKey)); + + // If not using 2 pump, it will error Offset is out of bounds + await tester.pump(Duration(seconds: 1)); + await tester.pump(Duration(seconds: 1)); + expect(find.byKey(AlbumCollectionEditModal.albumCollectionStatusModal), findsOneWidget); + + expect(find.byKey(AlbumCollectionEditModal.saveBtnKey), findsOneWidget); + await tester.ensureVisible(find.byKey(AlbumCollectionEditModal.saveBtnKey)); + await tester.tap(find.byKey(AlbumCollectionEditModal.saveBtnKey)); + await tester.pump(Duration(seconds: 1)); + await tester.pump(Duration(seconds: 1)); + expect(find.byKey(AlbumCollectionEditModal.albumCollectionStatusModal), findsNothing); + + }); }