From 118a0dcd2654cf7577a5f20247297315b9f1a158 Mon Sep 17 00:00:00 2001 From: Moritz Weber Date: Wed, 30 Aug 2023 16:27:54 -0400 Subject: [PATCH] base for unit tests --- .github/workflows/test.yml | 9 +- .gitignore | 2 +- src/lib/domain/modules/dynamic_queue.dart | 61 +- .../audio_player_repository_impl.dart | 20 +- src/pubspec.lock | 8 + src/pubspec.yaml | 1 + .../domain/modules/dynamic_queue_test.dart | 41 + .../modules/dynamic_queue_test.mocks.dart | 718 ++++++++++++++++++ 8 files changed, 816 insertions(+), 44 deletions(-) create mode 100644 src/test/domain/modules/dynamic_queue_test.dart create mode 100644 src/test/domain/modules/dynamic_queue_test.mocks.dart diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 4693527..a2847c9 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -9,6 +9,7 @@ on: branches: [ master ] pull_request: branches: [ master ] + workflow_dispatch: # A workflow run is made up of one or more jobs that can run sequentially or in parallel jobs: @@ -21,17 +22,17 @@ jobs: steps: # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it - uses: actions/checkout@v2 - - - uses: actions/setup-java@v1 + - uses: actions/setup-java@v2 with: java-version: '12.x' + distribution: 'zulu' # install sqlite3 - run: sudo apt-get install libsqlite3-dev - - uses: subosito/flutter-action@v1 + - uses: subosito/flutter-action@v2 with: - channel: 'stable' + flutter-version: '3.10.5' - run: flutter pub get - run: flutter test --coverage - name: Coveralls GitHub Action diff --git a/.gitignore b/.gitignore index 800e78d..1da9356 100644 --- a/.gitignore +++ b/.gitignore @@ -40,7 +40,7 @@ lib/generated_plugin_registrant.dart ### Custom Part ---------------------------------------------------------------- -coverage/lcov.info +src/coverage/lcov.info assets/screenshots/src signing/github.jks src/android/key.properties diff --git a/src/lib/domain/modules/dynamic_queue.dart b/src/lib/domain/modules/dynamic_queue.dart index 737eb9d..0d85419 100644 --- a/src/lib/domain/modules/dynamic_queue.dart +++ b/src/lib/domain/modules/dynamic_queue.dart @@ -30,7 +30,7 @@ class DynamicQueue implements ManagedQueueInfo { List get availableSongs => (_availableSongs..where((element) => element.isAvailable)).map((e) => e.song).toList(); - /// The queue generated so far from the _availableSongs. + /// The queue generated so far from the [_availableSongs]. List _queue = []; final BehaviorSubject> _queueSubject = BehaviorSubject.seeded([]); @@ -39,7 +39,6 @@ class DynamicQueue implements ManagedQueueInfo { final BehaviorSubject> _availableSongsSubject = BehaviorSubject.seeded([]); final BehaviorSubject _playableSubject = BehaviorSubject(); - ShuffleMode _shuffleMode = ShuffleMode.none; @override ValueStream> get availableSongsStream => _availableSongsSubject.stream; @@ -50,29 +49,30 @@ class DynamicQueue implements ManagedQueueInfo { @override ValueStream get playableStream => _playableSubject.stream; + /// Initializes the DynamicQueue with a [queue], [availableSongs] and [playable] from a previous run of the app. void init( List queue, List availableSongs, Playable playable, - ShuffleMode shuffleMode, ) { _log.d('init'); - _shuffleMode = shuffleMode; - _playableSubject.add(playable); - _log.d(availableSongs.length.toString()); _availableSongs = availableSongs; - _availableSongsSubject.add(_availableSongs); // for every item in queue, take the corresponding object from availableSongs _queue = queue - .map((qi) => availableSongs.firstWhere( - (e) => e == qi, - orElse: () { - _log.d(qi.toString()); - return qi as QueueItemModel; - }, - )) + .map( + (qi) => availableSongs.firstWhere( + (e) => e == qi, + orElse: () { + _log.d('Not found in available songs: $qi'); + return qi as QueueItemModel; + }, + ), + ) .toList(); + + _playableSubject.add(playable); + _availableSongsSubject.add(_availableSongs); _queueSubject.add(_queue); } @@ -84,7 +84,6 @@ class DynamicQueue implements ManagedQueueInfo { bool keepIndex = false, }) async { _log.d('generateQueue'); - _shuffleMode = shuffleMode; _playableSubject.add(playable); _availableSongs = List.generate( @@ -98,7 +97,7 @@ class DynamicQueue implements ManagedQueueInfo { _availableSongs, indeces: [startIndex], keepIndex: keepIndex, - blockLevel: calcBlockLevel(_shuffleMode, _playableSubject.value), + blockLevel: calcBlockLevel(shuffleMode, _playableSubject.value), ); if (filteredAvailableSongs.isEmpty) filteredAvailableSongs = _availableSongs; @@ -126,7 +125,7 @@ class DynamicQueue implements ManagedQueueInfo { } int returnIndex = -1; - switch (_shuffleMode) { + switch (shuffleMode) { case ShuffleMode.none: returnIndex = await _generateNormalQueue(filteredAvailableSongs, newStartIndex); break; @@ -216,7 +215,6 @@ class DynamicQueue implements ManagedQueueInfo { Future reshuffleQueue(ShuffleMode shuffleMode, int currentIndex) async { _log.d('reshuffleQueue'); - _shuffleMode = shuffleMode; QueueItem currentQueueItem = _queue[currentIndex]; const validSources = [QueueItemSource.original, QueueItemSource.added]; @@ -269,7 +267,7 @@ class DynamicQueue implements ManagedQueueInfo { _availableSongs, keepIndex: true, indeces: indecesToKeep, - blockLevel: calcBlockLevel(_shuffleMode, _playableSubject.value), + blockLevel: calcBlockLevel(shuffleMode, _playableSubject.value), ); int newStartIndex = -1; if (anchorIndex >= 0) { @@ -278,7 +276,7 @@ class DynamicQueue implements ManagedQueueInfo { newStartIndex = filteredAvailableSongs.indexOf(currentQueueItem); } - switch (_shuffleMode) { + switch (shuffleMode) { case ShuffleMode.none: await _generateNormalQueue(filteredAvailableSongs, newStartIndex); break; @@ -292,28 +290,29 @@ class DynamicQueue implements ManagedQueueInfo { return _queue.indexOf(currentQueueItem); } - Future> updateCurrentIndex(int currentIndex) async { - _log.d('updateCurrentIndex'); - final int songsAhead = _queue.length - currentIndex - 1; - int songsToQueue = QUEUE_AHEAD - songsAhead; + /// Reacts to updates of [currentIndex] and returns a list of newly queued songs. + Future> onCurrentIndexUpdated(int currentIndex, ShuffleMode shuffleMode) async { + _log.d('onCurrentIndexUpdated'); + final int numSongsAhead = _queue.length - currentIndex - 1; + int numSongsToQueue = QUEUE_AHEAD - numSongsAhead; - if (songsToQueue > 0) { + if (numSongsToQueue > 0) { final filteredAvailableSongs = filterAvailableSongs( _availableSongs, - blockLevel: calcBlockLevel(_shuffleMode, _playableSubject.value), + blockLevel: calcBlockLevel(shuffleMode, _playableSubject.value), ); - songsToQueue = min(songsToQueue, filteredAvailableSongs.length); + numSongsToQueue = min(numSongsToQueue, filteredAvailableSongs.length); if (filteredAvailableSongs.isNotEmpty) { List newSongs = []; - switch (_shuffleMode) { + switch (shuffleMode) { case ShuffleMode.none: - newSongs = filteredAvailableSongs.sublist(0, songsToQueue); + newSongs = filteredAvailableSongs.sublist(0, numSongsToQueue); break; case ShuffleMode.standard: - newSongs = await _shuffleQueue(filteredAvailableSongs, songsToQueue); + newSongs = await _shuffleQueue(filteredAvailableSongs, numSongsToQueue); break; case ShuffleMode.plus: - newSongs = await _shufflePlusQueue(filteredAvailableSongs, songsToQueue); + newSongs = await _shufflePlusQueue(filteredAvailableSongs, numSongsToQueue); } for (final qi in newSongs) { diff --git a/src/lib/system/repositories/audio_player_repository_impl.dart b/src/lib/system/repositories/audio_player_repository_impl.dart index dc7277e..b3dd2f2 100644 --- a/src/lib/system/repositories/audio_player_repository_impl.dart +++ b/src/lib/system/repositories/audio_player_repository_impl.dart @@ -25,12 +25,14 @@ class AudioPlayerRepositoryImpl implements AudioPlayerRepository { if (!_blockIndexUpdate) { _updateCurrentSong(queueStream.value, index); } - _dynamicQueue.updateCurrentIndex(index).then((songs) { - if (songs.isNotEmpty) { - _audioPlayerDataSource.addToQueue(songs.map((e) => e as SongModel).toList()); - _queueSubject.add(_dynamicQueue.queue); - } - }); + _dynamicQueue.onCurrentIndexUpdated(index, shuffleModeStream.value).then( + (songs) { + if (songs.isNotEmpty) { + _audioPlayerDataSource.addToQueue(songs.map((e) => e as SongModel).toList()); + _queueSubject.add(_dynamicQueue.queue); + } + }, + ); }, ); _queueSubject.listen((queue) { @@ -125,7 +127,6 @@ class AudioPlayerRepositoryImpl implements AudioPlayerRepository { queueItems, availableSongs, playable, - shuffleModeStream.value, ); _queueSubject.add(_dynamicQueue.queue); @@ -224,7 +225,10 @@ class AudioPlayerRepositoryImpl implements AudioPlayerRepository { if (_dynamicQueue.availableSongs.isEmpty) { _audioPlayerDataSource.stop(); } else { - final newSongs = await _dynamicQueue.updateCurrentIndex(newCurrentIndex); + final newSongs = await _dynamicQueue.onCurrentIndexUpdated( + newCurrentIndex, + shuffleModeStream.value, + ); if (newSongs.isNotEmpty) { await _audioPlayerDataSource.addToQueue(newSongs.map((e) => e as SongModel).toList()); _queueSubject.add(_dynamicQueue.queue); diff --git a/src/pubspec.lock b/src/pubspec.lock index 3adb772..94f97ea 100644 --- a/src/pubspec.lock +++ b/src/pubspec.lock @@ -622,6 +622,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.2.0" + mockito: + dependency: "direct dev" + description: + name: mockito + sha256: "7d5b53bcd556c1bc7ffbe4e4d5a19c3e112b7e925e9e172dd7c6ad0630812616" + url: "https://pub.dev" + source: hosted + version: "5.4.2" nested: dependency: transitive description: diff --git a/src/pubspec.yaml b/src/pubspec.yaml index 2e82db0..e35e37f 100644 --- a/src/pubspec.yaml +++ b/src/pubspec.yaml @@ -55,6 +55,7 @@ dev_dependencies: flutter_test: sdk: flutter mobx_codegen: ^2.0.1+3 # MIT + mockito: ^5.4.2 test: ^1.24.1 diff --git a/src/test/domain/modules/dynamic_queue_test.dart b/src/test/domain/modules/dynamic_queue_test.dart new file mode 100644 index 0000000..b81e536 --- /dev/null +++ b/src/test/domain/modules/dynamic_queue_test.dart @@ -0,0 +1,41 @@ +import 'package:flutter_test/flutter_test.dart'; +import 'package:mockito/annotations.dart'; +import 'package:mockito/mockito.dart'; + +import 'package:mucke/domain/entities/playable.dart'; +import 'package:mucke/domain/entities/queue_item.dart'; +import 'package:mucke/domain/entities/shuffle_mode.dart'; +import 'package:mucke/domain/modules/dynamic_queue.dart'; +import 'package:mucke/domain/repositories/music_data_repository.dart'; + + +@GenerateNiceMocks([MockSpec(), MockSpec()]) +import 'dynamic_queue_test.mocks.dart'; + +void main() { + late DynamicQueue sut; + late MockMusicDataRepository mockMusicDataRepository; + + setUp(() { + mockMusicDataRepository = MockMusicDataRepository(); + sut = DynamicQueue(mockMusicDataRepository); + }); + + group('init', () { + test( + 'should set playable', + () async { + // arrange + final tQueue = []; + final tAvailableSongs = []; + final tPlayable = MockPlayable(); + + // act + sut.init(tQueue, tAvailableSongs, tPlayable); + + // assert + expect(sut.playableStream.value, tPlayable); + }, + ); + }); +} \ No newline at end of file diff --git a/src/test/domain/modules/dynamic_queue_test.mocks.dart b/src/test/domain/modules/dynamic_queue_test.mocks.dart new file mode 100644 index 0000000..989b05e --- /dev/null +++ b/src/test/domain/modules/dynamic_queue_test.mocks.dart @@ -0,0 +1,718 @@ +// Mocks generated by Mockito 5.4.2 from annotations +// in mucke/test/domain/modules/dynamic_queue_test.dart. +// Do not manually edit this file. + +// ignore_for_file: no_leading_underscores_for_library_prefixes +import 'dart:async' as _i5; + +import 'package:mockito/mockito.dart' as _i1; +import 'package:mucke/domain/entities/album.dart' as _i8; +import 'package:mucke/domain/entities/artist.dart' as _i9; +import 'package:mucke/domain/entities/custom_list.dart' as _i11; +import 'package:mucke/domain/entities/enums.dart' as _i13; +import 'package:mucke/domain/entities/home_widgets/playlists.dart' as _i12; +import 'package:mucke/domain/entities/playable.dart' as _i14; +import 'package:mucke/domain/entities/playlist.dart' as _i6; +import 'package:mucke/domain/entities/shuffle_mode.dart' as _i10; +import 'package:mucke/domain/entities/smart_list.dart' as _i7; +import 'package:mucke/domain/entities/song.dart' as _i3; +import 'package:mucke/domain/repositories/music_data_repository.dart' as _i4; +import 'package:rxdart/rxdart.dart' as _i2; + +// ignore_for_file: type=lint +// ignore_for_file: avoid_redundant_argument_values +// ignore_for_file: avoid_setters_without_getters +// ignore_for_file: comment_references +// ignore_for_file: implementation_imports +// ignore_for_file: invalid_use_of_visible_for_testing_member +// ignore_for_file: prefer_const_constructors +// ignore_for_file: unnecessary_parenthesis +// ignore_for_file: camel_case_types +// ignore_for_file: subtype_of_sealed_class + +class _FakeValueStream_0 extends _i1.SmartFake + implements _i2.ValueStream { + _FakeValueStream_0( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeSong_1 extends _i1.SmartFake implements _i3.Song { + _FakeSong_1( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +/// A class which mocks [MusicDataRepository]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockMusicDataRepository extends _i1.Mock + implements _i4.MusicDataRepository { + @override + _i2.ValueStream get numFileStream => (super.noSuchMethod( + Invocation.getter(#numFileStream), + returnValue: _FakeValueStream_0( + this, + Invocation.getter(#numFileStream), + ), + returnValueForMissingStub: _FakeValueStream_0( + this, + Invocation.getter(#numFileStream), + ), + ) as _i2.ValueStream); + @override + _i2.ValueStream get progressStream => (super.noSuchMethod( + Invocation.getter(#progressStream), + returnValue: _FakeValueStream_0( + this, + Invocation.getter(#progressStream), + ), + returnValueForMissingStub: _FakeValueStream_0( + this, + Invocation.getter(#progressStream), + ), + ) as _i2.ValueStream); + @override + _i5.Stream> get songUpdateStream => (super.noSuchMethod( + Invocation.getter(#songUpdateStream), + returnValue: _i5.Stream>.empty(), + returnValueForMissingStub: _i5.Stream>.empty(), + ) as _i5.Stream>); + @override + _i5.Stream> get songRemovalStream => (super.noSuchMethod( + Invocation.getter(#songRemovalStream), + returnValue: _i5.Stream>.empty(), + returnValueForMissingStub: _i5.Stream>.empty(), + ) as _i5.Stream>); + @override + _i5.Stream> get songsStream => (super.noSuchMethod( + Invocation.getter(#songsStream), + returnValue: _i5.Stream>.empty(), + returnValueForMissingStub: _i5.Stream>.empty(), + ) as _i5.Stream>); + @override + _i5.Stream> get playlistsStream => (super.noSuchMethod( + Invocation.getter(#playlistsStream), + returnValue: _i5.Stream>.empty(), + returnValueForMissingStub: _i5.Stream>.empty(), + ) as _i5.Stream>); + @override + _i5.Stream> get smartListsStream => (super.noSuchMethod( + Invocation.getter(#smartListsStream), + returnValue: _i5.Stream>.empty(), + returnValueForMissingStub: _i5.Stream>.empty(), + ) as _i5.Stream>); + @override + _i5.Stream> get albumStream => (super.noSuchMethod( + Invocation.getter(#albumStream), + returnValue: _i5.Stream>.empty(), + returnValueForMissingStub: _i5.Stream>.empty(), + ) as _i5.Stream>); + @override + _i5.Stream> get artistStream => (super.noSuchMethod( + Invocation.getter(#artistStream), + returnValue: _i5.Stream>.empty(), + returnValueForMissingStub: _i5.Stream>.empty(), + ) as _i5.Stream>); + @override + _i2.ValueStream<_i8.Album?> get albumOfDayStream => (super.noSuchMethod( + Invocation.getter(#albumOfDayStream), + returnValue: _FakeValueStream_0<_i8.Album?>( + this, + Invocation.getter(#albumOfDayStream), + ), + returnValueForMissingStub: _FakeValueStream_0<_i8.Album?>( + this, + Invocation.getter(#albumOfDayStream), + ), + ) as _i2.ValueStream<_i8.Album?>); + @override + _i2.ValueStream<_i9.Artist?> get artistOfDayStream => (super.noSuchMethod( + Invocation.getter(#artistOfDayStream), + returnValue: _FakeValueStream_0<_i9.Artist?>( + this, + Invocation.getter(#artistOfDayStream), + ), + returnValueForMissingStub: _FakeValueStream_0<_i9.Artist?>( + this, + Invocation.getter(#artistOfDayStream), + ), + ) as _i2.ValueStream<_i9.Artist?>); + @override + _i2.ValueStream> get blockedFilesStream => (super.noSuchMethod( + Invocation.getter(#blockedFilesStream), + returnValue: _FakeValueStream_0>( + this, + Invocation.getter(#blockedFilesStream), + ), + returnValueForMissingStub: _FakeValueStream_0>( + this, + Invocation.getter(#blockedFilesStream), + ), + ) as _i2.ValueStream>); + @override + _i5.Future updateDatabase() => (super.noSuchMethod( + Invocation.method( + #updateDatabase, + [], + ), + returnValue: _i5.Future.value(), + returnValueForMissingStub: _i5.Future.value(), + ) as _i5.Future); + @override + _i5.Future setSongsBlockLevel( + List<_i3.Song>? songs, + int? blockLevel, + ) => + (super.noSuchMethod( + Invocation.method( + #setSongsBlockLevel, + [ + songs, + blockLevel, + ], + ), + returnValue: _i5.Future.value(), + returnValueForMissingStub: _i5.Future.value(), + ) as _i5.Future); + @override + _i5.Future setLikeCount( + List<_i3.Song>? songs, + int? count, + ) => + (super.noSuchMethod( + Invocation.method( + #setLikeCount, + [ + songs, + count, + ], + ), + returnValue: _i5.Future.value(), + returnValueForMissingStub: _i5.Future.value(), + ) as _i5.Future); + @override + _i5.Future incrementLikeCount(_i3.Song? song) => (super.noSuchMethod( + Invocation.method( + #incrementLikeCount, + [song], + ), + returnValue: _i5.Future.value(), + returnValueForMissingStub: _i5.Future.value(), + ) as _i5.Future); + @override + _i5.Future<_i3.Song> incrementPlayCount(_i3.Song? song) => + (super.noSuchMethod( + Invocation.method( + #incrementPlayCount, + [song], + ), + returnValue: _i5.Future<_i3.Song>.value(_FakeSong_1( + this, + Invocation.method( + #incrementPlayCount, + [song], + ), + )), + returnValueForMissingStub: _i5.Future<_i3.Song>.value(_FakeSong_1( + this, + Invocation.method( + #incrementPlayCount, + [song], + ), + )), + ) as _i5.Future<_i3.Song>); + @override + _i5.Future<_i3.Song> togglePreviousSongLink(_i3.Song? song) => + (super.noSuchMethod( + Invocation.method( + #togglePreviousSongLink, + [song], + ), + returnValue: _i5.Future<_i3.Song>.value(_FakeSong_1( + this, + Invocation.method( + #togglePreviousSongLink, + [song], + ), + )), + returnValueForMissingStub: _i5.Future<_i3.Song>.value(_FakeSong_1( + this, + Invocation.method( + #togglePreviousSongLink, + [song], + ), + )), + ) as _i5.Future<_i3.Song>); + @override + _i5.Future<_i3.Song> toggleNextSongLink(_i3.Song? song) => + (super.noSuchMethod( + Invocation.method( + #toggleNextSongLink, + [song], + ), + returnValue: _i5.Future<_i3.Song>.value(_FakeSong_1( + this, + Invocation.method( + #toggleNextSongLink, + [song], + ), + )), + returnValueForMissingStub: _i5.Future<_i3.Song>.value(_FakeSong_1( + this, + Invocation.method( + #toggleNextSongLink, + [song], + ), + )), + ) as _i5.Future<_i3.Song>); + @override + _i5.Future insertPlaylist( + String? name, + String? iconString, + String? gradientString, + _i10.ShuffleMode? shuffleMode, + ) => + (super.noSuchMethod( + Invocation.method( + #insertPlaylist, + [ + name, + iconString, + gradientString, + shuffleMode, + ], + ), + returnValue: _i5.Future.value(), + returnValueForMissingStub: _i5.Future.value(), + ) as _i5.Future); + @override + _i5.Future updatePlaylist(_i6.Playlist? playlist) => + (super.noSuchMethod( + Invocation.method( + #updatePlaylist, + [playlist], + ), + returnValue: _i5.Future.value(), + returnValueForMissingStub: _i5.Future.value(), + ) as _i5.Future); + @override + _i5.Future removePlaylist(_i6.Playlist? playlist) => + (super.noSuchMethod( + Invocation.method( + #removePlaylist, + [playlist], + ), + returnValue: _i5.Future.value(), + returnValueForMissingStub: _i5.Future.value(), + ) as _i5.Future); + @override + _i5.Future addSongsToPlaylist( + _i6.Playlist? playlist, + List<_i3.Song>? songs, + ) => + (super.noSuchMethod( + Invocation.method( + #addSongsToPlaylist, + [ + playlist, + songs, + ], + ), + returnValue: _i5.Future.value(), + returnValueForMissingStub: _i5.Future.value(), + ) as _i5.Future); + @override + _i5.Future removePlaylistEntry( + int? playlistId, + int? index, + ) => + (super.noSuchMethod( + Invocation.method( + #removePlaylistEntry, + [ + playlistId, + index, + ], + ), + returnValue: _i5.Future.value(), + returnValueForMissingStub: _i5.Future.value(), + ) as _i5.Future); + @override + _i5.Future movePlaylistEntry( + int? playlistId, + int? oldIndex, + int? newIndex, + ) => + (super.noSuchMethod( + Invocation.method( + #movePlaylistEntry, + [ + playlistId, + oldIndex, + newIndex, + ], + ), + returnValue: _i5.Future.value(), + returnValueForMissingStub: _i5.Future.value(), + ) as _i5.Future); + @override + _i5.Future insertSmartList({ + required String? name, + required _i7.Filter? filter, + required _i7.OrderBy? orderBy, + required String? iconString, + required String? gradientString, + _i10.ShuffleMode? shuffleMode, + }) => + (super.noSuchMethod( + Invocation.method( + #insertSmartList, + [], + { + #name: name, + #filter: filter, + #orderBy: orderBy, + #iconString: iconString, + #gradientString: gradientString, + #shuffleMode: shuffleMode, + }, + ), + returnValue: _i5.Future.value(), + returnValueForMissingStub: _i5.Future.value(), + ) as _i5.Future); + @override + _i5.Future updateSmartList(_i7.SmartList? smartList) => + (super.noSuchMethod( + Invocation.method( + #updateSmartList, + [smartList], + ), + returnValue: _i5.Future.value(), + returnValueForMissingStub: _i5.Future.value(), + ) as _i5.Future); + @override + _i5.Future removeSmartList(_i7.SmartList? smartList) => + (super.noSuchMethod( + Invocation.method( + #removeSmartList, + [smartList], + ), + returnValue: _i5.Future.value(), + returnValueForMissingStub: _i5.Future.value(), + ) as _i5.Future); + @override + _i5.Future addBlockedFiles( + List? paths, + bool? delete, + ) => + (super.noSuchMethod( + Invocation.method( + #addBlockedFiles, + [ + paths, + delete, + ], + ), + returnValue: _i5.Future.value(), + returnValueForMissingStub: _i5.Future.value(), + ) as _i5.Future); + @override + _i5.Future removeBlockedFiles(List? paths) => + (super.noSuchMethod( + Invocation.method( + #removeBlockedFiles, + [paths], + ), + returnValue: _i5.Future.value(), + returnValueForMissingStub: _i5.Future.value(), + ) as _i5.Future); + @override + _i5.Future<_i3.Song> getSongByPath(String? path) => (super.noSuchMethod( + Invocation.method( + #getSongByPath, + [path], + ), + returnValue: _i5.Future<_i3.Song>.value(_FakeSong_1( + this, + Invocation.method( + #getSongByPath, + [path], + ), + )), + returnValueForMissingStub: _i5.Future<_i3.Song>.value(_FakeSong_1( + this, + Invocation.method( + #getSongByPath, + [path], + ), + )), + ) as _i5.Future<_i3.Song>); + @override + _i5.Stream<_i3.Song> getSongStream(String? path) => (super.noSuchMethod( + Invocation.method( + #getSongStream, + [path], + ), + returnValue: _i5.Stream<_i3.Song>.empty(), + returnValueForMissingStub: _i5.Stream<_i3.Song>.empty(), + ) as _i5.Stream<_i3.Song>); + @override + _i5.Stream> getAlbumSongStream(_i8.Album? album) => + (super.noSuchMethod( + Invocation.method( + #getAlbumSongStream, + [album], + ), + returnValue: _i5.Stream>.empty(), + returnValueForMissingStub: _i5.Stream>.empty(), + ) as _i5.Stream>); + @override + _i5.Stream> getArtistSongStream(_i9.Artist? artist) => + (super.noSuchMethod( + Invocation.method( + #getArtistSongStream, + [artist], + ), + returnValue: _i5.Stream>.empty(), + returnValueForMissingStub: _i5.Stream>.empty(), + ) as _i5.Stream>); + @override + _i5.Stream> getArtistHighlightedSongStream( + _i9.Artist? artist) => + (super.noSuchMethod( + Invocation.method( + #getArtistHighlightedSongStream, + [artist], + ), + returnValue: _i5.Stream>.empty(), + returnValueForMissingStub: _i5.Stream>.empty(), + ) as _i5.Stream>); + @override + _i5.Stream> getPlaylistSongStream(_i6.Playlist? playlist) => + (super.noSuchMethod( + Invocation.method( + #getPlaylistSongStream, + [playlist], + ), + returnValue: _i5.Stream>.empty(), + returnValueForMissingStub: _i5.Stream>.empty(), + ) as _i5.Stream>); + @override + _i5.Stream> getSmartListSongStream(_i7.SmartList? smartList) => + (super.noSuchMethod( + Invocation.method( + #getSmartListSongStream, + [smartList], + ), + returnValue: _i5.Stream>.empty(), + returnValueForMissingStub: _i5.Stream>.empty(), + ) as _i5.Stream>); + @override + _i5.Future> getPredecessors(_i3.Song? song) => + (super.noSuchMethod( + Invocation.method( + #getPredecessors, + [song], + ), + returnValue: _i5.Future>.value(<_i3.Song>[]), + returnValueForMissingStub: + _i5.Future>.value(<_i3.Song>[]), + ) as _i5.Future>); + @override + _i5.Future> getSuccessors(_i3.Song? song) => + (super.noSuchMethod( + Invocation.method( + #getSuccessors, + [song], + ), + returnValue: _i5.Future>.value(<_i3.Song>[]), + returnValueForMissingStub: + _i5.Future>.value(<_i3.Song>[]), + ) as _i5.Future>); + @override + _i5.Future> isSongFirstLast(_i3.Song? song) => (super.noSuchMethod( + Invocation.method( + #isSongFirstLast, + [song], + ), + returnValue: _i5.Future>.value([]), + returnValueForMissingStub: _i5.Future>.value([]), + ) as _i5.Future>); + @override + _i5.Stream<_i6.Playlist> getPlaylistStream(int? playlistId) => + (super.noSuchMethod( + Invocation.method( + #getPlaylistStream, + [playlistId], + ), + returnValue: _i5.Stream<_i6.Playlist>.empty(), + returnValueForMissingStub: _i5.Stream<_i6.Playlist>.empty(), + ) as _i5.Stream<_i6.Playlist>); + @override + _i5.Stream<_i7.SmartList> getSmartListStream(int? smartListId) => + (super.noSuchMethod( + Invocation.method( + #getSmartListStream, + [smartListId], + ), + returnValue: _i5.Stream<_i7.SmartList>.empty(), + returnValueForMissingStub: _i5.Stream<_i7.SmartList>.empty(), + ) as _i5.Stream<_i7.SmartList>); + @override + _i5.Stream> getCustomListsStream({ + _i12.HomePlaylistsOrder? orderCriterion = _i12.HomePlaylistsOrder.name, + _i13.OrderDirection? orderDirection = _i13.OrderDirection.ascending, + _i12.HomePlaylistsFilter? filter = _i12.HomePlaylistsFilter.both, + int? limit, + }) => + (super.noSuchMethod( + Invocation.method( + #getCustomListsStream, + [], + { + #orderCriterion: orderCriterion, + #orderDirection: orderDirection, + #filter: filter, + #limit: limit, + }, + ), + returnValue: _i5.Stream>.empty(), + returnValueForMissingStub: _i5.Stream>.empty(), + ) as _i5.Stream>); + @override + _i5.Stream> getArtistAlbumStream(_i9.Artist? artist) => + (super.noSuchMethod( + Invocation.method( + #getArtistAlbumStream, + [artist], + ), + returnValue: _i5.Stream>.empty(), + returnValueForMissingStub: _i5.Stream>.empty(), + ) as _i5.Stream>); + @override + _i5.Future getAlbumId( + String? title, + String? artist, + int? year, + ) => + (super.noSuchMethod( + Invocation.method( + #getAlbumId, + [ + title, + artist, + year, + ], + ), + returnValue: _i5.Future.value(), + returnValueForMissingStub: _i5.Future.value(), + ) as _i5.Future); + @override + _i5.Future> searchArtists( + String? searchText, { + int? limit, + }) => + (super.noSuchMethod( + Invocation.method( + #searchArtists, + [searchText], + {#limit: limit}, + ), + returnValue: _i5.Future>.value(<_i9.Artist>[]), + returnValueForMissingStub: + _i5.Future>.value(<_i9.Artist>[]), + ) as _i5.Future>); + @override + _i5.Future> searchAlbums( + String? searchText, { + int? limit, + }) => + (super.noSuchMethod( + Invocation.method( + #searchAlbums, + [searchText], + {#limit: limit}, + ), + returnValue: _i5.Future>.value(<_i8.Album>[]), + returnValueForMissingStub: + _i5.Future>.value(<_i8.Album>[]), + ) as _i5.Future>); + @override + _i5.Future> searchSongs( + String? searchText, { + int? limit, + }) => + (super.noSuchMethod( + Invocation.method( + #searchSongs, + [searchText], + {#limit: limit}, + ), + returnValue: _i5.Future>.value(<_i3.Song>[]), + returnValueForMissingStub: + _i5.Future>.value(<_i3.Song>[]), + ) as _i5.Future>); + @override + _i5.Future> searchSmartLists( + String? searchText, { + int? limit, + }) => + (super.noSuchMethod( + Invocation.method( + #searchSmartLists, + [searchText], + {#limit: limit}, + ), + returnValue: _i5.Future>.value(<_i7.SmartList>[]), + returnValueForMissingStub: + _i5.Future>.value(<_i7.SmartList>[]), + ) as _i5.Future>); + @override + _i5.Future> searchPlaylists( + String? searchText, { + int? limit, + }) => + (super.noSuchMethod( + Invocation.method( + #searchPlaylists, + [searchText], + {#limit: limit}, + ), + returnValue: _i5.Future>.value(<_i6.Playlist>[]), + returnValueForMissingStub: + _i5.Future>.value(<_i6.Playlist>[]), + ) as _i5.Future>); +} + +/// A class which mocks [Playable]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockPlayable extends _i1.Mock implements _i14.Playable { + @override + String get identifier => (super.noSuchMethod( + Invocation.getter(#identifier), + returnValue: '', + returnValueForMissingStub: '', + ) as String); + @override + _i14.PlayableType get type => (super.noSuchMethod( + Invocation.getter(#type), + returnValue: _i14.PlayableType.all, + returnValueForMissingStub: _i14.PlayableType.all, + ) as _i14.PlayableType); + @override + String get title => (super.noSuchMethod( + Invocation.getter(#title), + returnValue: '', + returnValueForMissingStub: '', + ) as String); +}