import 'package:cyberhybridhub/models/question_source_preference.dart'; import 'package:cyberhybridhub/repositories/question_source_config_repository.dart'; import 'package:flutter_test/flutter_test.dart'; void main() { setUp(() { QuestionSourceConfigRepository.instance.resetToDefaults(); }); test('mergeWithDefaults adds new sources from defaults', () { const List saved = [ QuestionSourcePreference( id: 'market_history', label: 'Market question', description: 'Prospective price-move guessing game', enabled: true, ratio: 100, ), ]; final List merged = QuestionSourceConfigRepository.mergeWithDefaults(saved); expect(merged.map((QuestionSourcePreference s) => s.id), [ 'market_history', 'spelling', ]); expect( merged.firstWhere((QuestionSourcePreference s) => s.id == 'market_history').ratio, 100, ); expect( merged.firstWhere((QuestionSourcePreference s) => s.id == 'spelling').comingSoon, isFalse, ); }); test('mergeWithDefaults drops removed legacy sources', () { const List saved = [ QuestionSourcePreference( id: 'geography', label: 'Geography', description: 'Legacy', ratio: 25, ), QuestionSourcePreference( id: 'market_history', label: 'Market question', description: 'Prospective price-move guessing game', ratio: 75, ), ]; final List merged = QuestionSourceConfigRepository.mergeWithDefaults(saved); expect(merged.map((QuestionSourcePreference s) => s.id), [ 'market_history', 'spelling', ]); }); test('mergeWithDefaults refreshes labels and disables comingSoon sources', () { const List saved = [ QuestionSourcePreference( id: 'market_history', label: 'Market history', description: 'Old description', ratio: 30, ), QuestionSourcePreference( id: 'spelling', label: 'Spelling', description: 'Old description', enabled: true, comingSoon: false, ratio: 70, ), ]; final List merged = QuestionSourceConfigRepository.mergeWithDefaults(saved); final QuestionSourcePreference market = merged.firstWhere( (QuestionSourcePreference s) => s.id == 'market_history', ); expect(market.label, 'Market question'); expect(market.description, 'Prospective price-move guessing game'); final QuestionSourcePreference spelling = merged.firstWhere( (QuestionSourcePreference s) => s.id == 'spelling', ); expect(spelling.comingSoon, isFalse); expect(spelling.enabled, isTrue); }); test('isSpellingFullyWeighted when spelling owns entire mix', () { final List sources = QuestionSourceConfigRepository.mergeWithDefaults( [ const QuestionSourcePreference( id: 'market_history', label: 'Market question', description: 'Prospective price-move guessing game', enabled: true, ratio: 0, ), const QuestionSourcePreference( id: 'spelling', label: 'Spelling', description: 'Spell-check quiz from curated word lists', enabled: true, ratio: 100, ), ], ); expect( QuestionSourceConfigRepository.isSpellingFullyWeighted(sources), isTrue, ); }); test('effectiveMix excludes disabled and comingSoon sources', () { final List sources = QuestionSourceConfigRepository.defaultPreferences; final Map mix = QuestionSourceConfigRepository.effectiveMix(sources); expect(mix.containsKey('spelling'), isTrue); expect(mix.length, 2); expect(mix['market_history'], 50); expect(mix['spelling'], 50); }); test('saveAll without active session updates in-memory preferences only', () async { await QuestionSourceConfigRepository.instance.saveAll( [ const QuestionSourcePreference( id: 'market_history', label: 'Market question', description: 'Prospective price-move guessing game', enabled: true, ratio: 75, ), const QuestionSourcePreference( id: 'spelling', label: 'Spelling', description: 'Spell-check quiz from curated word lists', enabled: true, ratio: 25, ), ], ); expect( QuestionSourceConfigRepository.instance.current .firstWhere((QuestionSourcePreference s) => s.id == 'market_history') .ratio, 75, ); }); }