import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:smplayer/core/domain/ports/sm_account_gateway.dart'; import 'package:smplayer/providers/sm_account_provider.dart'; import 'package:smplayer/providers/tmdb_settings_provider.dart'; void main() { TestWidgetsFlutterBinding.ensureInitialized(); const tmdbEnabledKey = 'smplayer.tmdb_enabled'; const tmdbAccessModeKey = 'smplayer.tmdb_access_mode'; const tmdbApiKeyKey = 'smplayer.tmdb_api_key'; const tmdbLanguageKey = 'smplayer.tmdb_language'; ProviderContainer makeContainer(SmLoginResult loginResult) { final c = ProviderContainer( overrides: [ smAccountGatewayProvider.overrideWithValue( _FakeSmAccountGateway(loginResult), ), ], ); addTearDown(c.dispose); return c; } test('VIP login enables TMDB through sm-server proxy', () async { SharedPreferences.setMockInitialValues({ tmdbEnabledKey: false, tmdbAccessModeKey: TmdbAccessMode.official.name, tmdbApiKeyKey: 'keep-me', tmdbLanguageKey: 'en-US', }); final c = makeContainer( const SmLoginResult( ok: true, email: 'vip@example.com', accessToken: 'access', refreshToken: 'refresh', expiresIn: 900, isVip: true, ), ); await c.read(smAccountProvider.future); final result = await c .read(smAccountProvider.notifier) .login('vip@example.com', 'password'); expect(result.ok, isTrue); final settings = await c.read(tmdbSettingsProvider.future); expect(settings.enabled, isTrue); expect(settings.accessMode, TmdbAccessMode.smAccount); expect(settings.apiKey, 'keep-me'); expect(settings.language, 'en-US'); final prefs = await SharedPreferences.getInstance(); expect(prefs.getBool(tmdbEnabledKey), isTrue); expect(prefs.getString(tmdbAccessModeKey), TmdbAccessMode.smAccount.name); }); test('non-VIP login leaves TMDB settings unchanged', () async { SharedPreferences.setMockInitialValues({ tmdbEnabledKey: false, tmdbAccessModeKey: TmdbAccessMode.official.name, }); final c = makeContainer( const SmLoginResult( ok: true, email: 'user@example.com', accessToken: 'access', refreshToken: 'refresh', expiresIn: 900, ), ); await c.read(smAccountProvider.future); final result = await c .read(smAccountProvider.notifier) .login('user@example.com', 'password'); expect(result.ok, isTrue); final settings = await c.read(tmdbSettingsProvider.future); expect(settings.enabled, isFalse); expect(settings.accessMode, TmdbAccessMode.official); final prefs = await SharedPreferences.getInstance(); expect(prefs.getBool(tmdbEnabledKey), isFalse); expect(prefs.getString(tmdbAccessModeKey), TmdbAccessMode.official.name); }); } class _FakeSmAccountGateway implements SmAccountGateway { final SmLoginResult loginResult; _FakeSmAccountGateway(this.loginResult); @override Future login({ required String baseUrl, required String email, required String password, }) async => loginResult; @override Future logout({ required String baseUrl, required String refreshToken, }) async {} @override Future refreshAccessToken({ required String baseUrl, required String refreshToken, }) async => const SmTokenRefreshResult(ok: false); @override Future registerStart({ required String baseUrl, required String email, }) async => SmActionResult.failure('unused'); @override Future registerVerify({ required String baseUrl, required String email, required String password, required String code, }) async => loginResult; @override Future resendCode({ required String baseUrl, required String email, }) async => SmActionResult.failure('unused'); }