test: add volume provider tests

This commit is contained in:
Kingkor Roy Tirtho 2025-04-14 23:31:34 +06:00
parent 472f379f3d
commit dcf0c62e5d
9 changed files with 78 additions and 58 deletions

View File

@ -37,4 +37,3 @@ analyzer:
- "**.g.dart" - "**.g.dart"
- "**.gr.dart" - "**.gr.dart"
- "**/generated_plugin_registrant.dart" - "**/generated_plugin_registrant.dart"
- test/**/*.dart

View File

@ -21,6 +21,7 @@ import 'package:spotube/collections/env.dart';
import 'package:spotube/collections/initializers.dart'; import 'package:spotube/collections/initializers.dart';
import 'package:spotube/collections/intents.dart'; import 'package:spotube/collections/intents.dart';
import 'package:spotube/collections/routes.dart'; import 'package:spotube/collections/routes.dart';
import 'package:spotube/collections/vars.dart';
import 'package:spotube/hooks/configurators/use_close_behavior.dart'; import 'package:spotube/hooks/configurators/use_close_behavior.dart';
import 'package:spotube/hooks/configurators/use_deep_linking.dart'; import 'package:spotube/hooks/configurators/use_deep_linking.dart';
import 'package:spotube/hooks/configurators/use_disable_battery_optimizations.dart'; import 'package:spotube/hooks/configurators/use_disable_battery_optimizations.dart';
@ -67,13 +68,12 @@ Future<void> main(List<String> rawArgs) async {
AppLogger.runZoned(() async { AppLogger.runZoned(() async {
final widgetsBinding = WidgetsFlutterBinding.ensureInitialized(); final widgetsBinding = WidgetsFlutterBinding.ensureInitialized();
GetIt.I.registerSingleton<SharedPreferences>( getIt.registerSingleton(await SharedPreferences.getInstance());
await SharedPreferences.getInstance(), getIt.registerSingletonWithDependencies(
);
GetIt.I.registerSingletonWithDependencies<KVStoreService>(
() => KVStoreService.init(), () => KVStoreService.init(),
dependsOn: [SharedPreferences], dependsOn: [SharedPreferences],
); );
getIt.registerSingleton(SpotubeAudioPlayer());
await registerWindowsScheme("spotify"); await registerWindowsScheme("spotify");

View File

@ -5,25 +5,21 @@ import 'package:spotube/services/audio_player/audio_player.dart';
import 'package:spotube/services/kv_store/kv_store.dart'; import 'package:spotube/services/kv_store/kv_store.dart';
class VolumeProvider extends Notifier<double> { class VolumeProvider extends Notifier<double> {
final SpotubeAudioPlayer _audioPlayer; VolumeProvider();
VolumeProvider({
required SpotubeAudioPlayer audioPlayer,
}) : _audioPlayer = audioPlayer;
@override @override
build() { build() {
_audioPlayer.setVolume(KVStoreService().volume); audioPlayer.setVolume(KVStoreService().volume);
return KVStoreService().volume; return KVStoreService().volume;
} }
Future<void> setVolume(double volume) async { Future<void> setVolume(double volume) async {
state = volume; state = volume;
await _audioPlayer.setVolume(volume); await audioPlayer.setVolume(volume);
KVStoreService().setVolume(volume); await KVStoreService().setVolume(volume);
} }
} }
final volumeProvider = NotifierProvider<VolumeProvider, double>(() { final volumeProvider = NotifierProvider<VolumeProvider, double>(() {
return VolumeProvider(audioPlayer: audioPlayer); return VolumeProvider();
}); });

View File

@ -1,6 +1,7 @@
import 'dart:io'; import 'dart:io';
import 'package:media_kit/media_kit.dart' hide Track; import 'package:media_kit/media_kit.dart' hide Track;
import 'package:spotube/collections/vars.dart';
import 'package:spotube/services/logger/logger.dart'; import 'package:spotube/services/logger/logger.dart';
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:spotify/spotify.dart' hide Playlist; import 'package:spotify/spotify.dart' hide Playlist;

View File

@ -1,6 +1,8 @@
part of 'audio_player.dart'; part of 'audio_player.dart';
final audioPlayer = SpotubeAudioPlayer(); SpotubeAudioPlayer get audioPlayer {
return getIt.get<SpotubeAudioPlayer>();
}
class SpotubeAudioPlayer extends AudioPlayerInterface class SpotubeAudioPlayer extends AudioPlayerInterface
with SpotubeAudioPlayersStreams { with SpotubeAudioPlayersStreams {

View File

@ -7,9 +7,9 @@ import 'package:spotube/models/database/database.dart';
import 'package:spotube/services/wm_tools/wm_tools.dart'; import 'package:spotube/services/wm_tools/wm_tools.dart';
import 'package:uuid/uuid.dart'; import 'package:uuid/uuid.dart';
final class KVStoreService { class KVStoreService {
factory KVStoreService() { factory KVStoreService() {
return getIt<KVStoreService>(); return getIt.get<KVStoreService>();
} }
KVStoreService.init(); KVStoreService.init();

View File

@ -161,7 +161,6 @@ dev_dependencies:
pub_api_client: ^3.0.0 pub_api_client: ^3.0.0
xml: ^6.5.0 xml: ^6.5.0
io: ^1.0.4 io: ^1.0.4
test: ^1.25.2
mocktail: ^1.0.4 mocktail: ^1.0.4
drift_dev: ^2.21.0 drift_dev: ^2.21.0
auto_route_generator: ^9.0.0 auto_route_generator: ^9.0.0

View File

@ -1,40 +0,0 @@
import 'package:flutter_test/flutter_test.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:spotube/provider/volume_provider.dart';
import 'package:spotube/services/audio_player/audio_player.dart';
import 'package:spotube/services/kv_store/kv_store.dart';
void main() {
late ProviderContainer container;
late VolumeProvider volumeProvider;
setUp(() {
container = ProviderContainer();
volumeProvider = container.read(volumeProvider.notifier);
});
tearDown(() {
container.dispose();
});
test('initial volume is set from KVStore', () {
expect(container.read(volumeProvider), KVStoreService().volume);
});
test('setVolume updates state and KVStore', () async {
const testVolume = 0.75;
await volumeProvider.setVolume(testVolume);
expect(container.read(volumeProvider), testVolume);
expect(KVStoreService().volume, testVolume);
});
test('setVolume updates audio player', () async {
const testVolume = 0.5;
await volumeProvider.setVolume(testVolume);
// Verify that the audio player's volume was set
// Note: This assumes audioPlayer.setVolume is properly mocked or can be verified
expect(audioPlayer.volume, testVolume);
});
}

View File

@ -0,0 +1,63 @@
import 'package:flutter_test/flutter_test.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:mocktail/mocktail.dart';
import 'package:spotube/collections/vars.dart';
import 'package:spotube/provider/volume_provider.dart';
import 'package:spotube/services/audio_player/audio_player.dart';
import 'package:spotube/services/kv_store/kv_store.dart';
class MockSpotubeAudioPlayer extends Mock implements SpotubeAudioPlayer {}
class MockKVStoreService extends Mock implements KVStoreService {}
void main() {
TestWidgetsFlutterBinding.ensureInitialized();
late ProviderContainer container;
late SpotubeAudioPlayer audioPlayer;
late KVStoreService kvStoreService;
setUp(() {
kvStoreService =
getIt.registerSingleton<KVStoreService>(MockKVStoreService());
audioPlayer =
getIt.registerSingleton<SpotubeAudioPlayer>(MockSpotubeAudioPlayer());
container = ProviderContainer();
when(() => kvStoreService.volume).thenAnswer((_) => 1.0);
when(() => kvStoreService.setVolume(any())).thenAnswer((_) async {});
when(() => audioPlayer.setVolume(any())).thenAnswer((_) async {});
});
tearDown(() {
getIt.reset();
container.dispose();
});
group("VolumeProvider", () {
test("initial volume should be 1", () {
final volume = container.read(volumeProvider);
expect(volume, 1.0);
});
group("setVolume", () {
test("should set volume to specified value", () async {
await container.read(volumeProvider.notifier).setVolume(0.5);
final volume = container.read(volumeProvider);
expect(volume, 0.5);
});
test("should update audioPlayer volume", () {
container.read(volumeProvider.notifier).setVolume(0.5);
verify(() => audioPlayer.setVolume(0.5)).called(1);
});
test("should persist the volume", () async {
await container.read(volumeProvider.notifier).setVolume(0.5);
verify(() => kvStoreService.setVolume(0.5)).called(1);
});
});
});
}