import 'package:test/test.dart'; import 'package:practice_engine/models/deck.dart'; import 'package:practice_engine/models/deck_config.dart'; import 'package:practice_engine/models/question.dart'; void main() { group('Deck', () { late DeckConfig defaultConfig; late List sampleQuestions; setUp(() { defaultConfig = const DeckConfig(); sampleQuestions = [ Question( id: 'q1', prompt: 'What is 2+2?', answers: ['3', '4', '5'], correctAnswerIndices: [1], isKnown: true, ), Question( id: 'q2', prompt: 'What is 3+3?', answers: ['5', '6', '7'], correctAnswerIndices: [1], isKnown: false, ), Question( id: 'q3', prompt: 'What is 4+4?', answers: ['7', '8', '9'], correctAnswerIndices: [1], isKnown: true, ), ]; }); test('calculates numberOfQuestions correctly', () { final deck = Deck( id: 'deck1', title: 'Math Deck', description: 'Basic math', questions: sampleQuestions, config: defaultConfig, ); expect(deck.numberOfQuestions, equals(3)); }); test('calculates knownCount correctly', () { final deck = Deck( id: 'deck1', title: 'Math Deck', description: 'Basic math', questions: sampleQuestions, config: defaultConfig, ); expect(deck.knownCount, equals(2)); }); test('calculates practicePercentage correctly', () { final deck = Deck( id: 'deck1', title: 'Math Deck', description: 'Basic math', questions: sampleQuestions, config: defaultConfig, ); expect(deck.practicePercentage, closeTo(66.67, 0.01)); }); test('practicePercentage is 0 for empty deck', () { final deck = Deck( id: 'deck1', title: 'Empty Deck', description: 'No questions', questions: [], config: defaultConfig, ); expect(deck.practicePercentage, equals(0.0)); }); test('practicePercentage is 100 when all questions are known', () { final allKnown = sampleQuestions.map((q) => q.copyWith(isKnown: true)).toList(); final deck = Deck( id: 'deck1', title: 'All Known', description: 'All known', questions: allKnown, config: defaultConfig, ); expect(deck.practicePercentage, equals(100.0)); }); test('progressPercentage is 0 for empty deck', () { final deck = Deck( id: 'deck1', title: 'Empty Deck', description: 'No questions', questions: [], config: defaultConfig, ); expect(deck.progressPercentage, equals(0.0)); }); test('progressPercentage equals practicePercentage when no partial streak', () { final deck = Deck( id: 'deck1', title: 'Math Deck', description: 'Basic math', questions: sampleQuestions, config: defaultConfig, ); expect(deck.progressPercentage, closeTo(deck.practicePercentage, 0.01)); }); test('progressPercentage is 100 when all questions are known', () { final allKnown = sampleQuestions.map((q) => q.copyWith(isKnown: true)).toList(); final deck = Deck( id: 'deck1', title: 'All Known', description: 'All known', questions: allKnown, config: defaultConfig, ); expect(deck.progressPercentage, equals(100.0)); }); test('progressPercentage includes partial credit from consecutiveCorrect', () { // requiredConsecutiveCorrect is 3 (default). 3 questions: none known, each at 2/3 final withPartial = [ Question(id: 'q1', prompt: 'A', answers: ['x'], correctAnswerIndices: [0], consecutiveCorrect: 2, isKnown: false), Question(id: 'q2', prompt: 'B', answers: ['x'], correctAnswerIndices: [0], consecutiveCorrect: 2, isKnown: false), Question(id: 'q3', prompt: 'C', answers: ['x'], correctAnswerIndices: [0], consecutiveCorrect: 2, isKnown: false), ]; final deck = Deck( id: 'deck1', title: 'Partial', description: 'Partial progress', questions: withPartial, config: defaultConfig, ); expect(deck.practicePercentage, equals(0.0)); expect(deck.progressPercentage, closeTo(66.67, 0.01)); // 3 * (2/3) / 3 * 100 }); test('progressPercentage mixes known and partial correctly', () { final config = DeckConfig(requiredConsecutiveCorrect: 3); final questions = [ Question(id: 'q1', prompt: 'A', answers: ['x'], correctAnswerIndices: [0], isKnown: true), Question(id: 'q2', prompt: 'B', answers: ['x'], correctAnswerIndices: [0], consecutiveCorrect: 2, isKnown: false), Question(id: 'q3', prompt: 'C', answers: ['x'], correctAnswerIndices: [0], consecutiveCorrect: 0, isKnown: false), ]; final deck = Deck( id: 'deck1', title: 'Mixed', description: 'Mixed', questions: questions, config: config, ); // 1.0 + 2/3 + 0 = 1.667; 1.667/3*100 ≈ 55.56 expect(deck.progressPercentage, closeTo(55.56, 0.01)); }); test('copyWith creates new deck with updated fields', () { final deck = Deck( id: 'deck1', title: 'Math Deck', description: 'Basic math', questions: sampleQuestions, config: defaultConfig, ); final updated = deck.copyWith(title: 'Updated Title'); expect(updated.title, equals('Updated Title')); expect(updated.id, equals(deck.id)); expect(updated.questions, equals(deck.questions)); }); }); }