You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
decky/packages/practice_engine/test/attempt_flow_test.dart

158 lines
4.4 KiB

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';
import 'package:practice_engine/logic/attempt_service.dart';
void main() {
group('Attempt Flow', () {
late Deck deck;
late AttemptService attemptService;
setUp(() {
final config = const DeckConfig(
defaultAttemptSize: 5,
requiredConsecutiveCorrect: 3,
);
final questions = List.generate(10, (i) {
return Question(
id: 'q$i',
prompt: 'Question $i',
answers: ['A', 'B', 'C'],
correctAnswerIndices: [0],
priorityPoints: i,
);
});
deck = Deck(
id: 'deck1',
title: 'Test Deck',
description: 'Test',
questions: questions,
config: config,
);
attemptService = AttemptService(seed: 42);
});
test('createAttempt selects correct number of questions', () {
final attempt = attemptService.createAttempt(deck: deck);
expect(attempt.questions.length, equals(deck.config.defaultAttemptSize));
});
test('createAttempt uses custom attempt size', () {
final attempt = attemptService.createAttempt(
deck: deck,
attemptSize: 3,
);
expect(attempt.questions.length, equals(3));
});
test('createAttempt has no duplicate questions', () {
final attempt = attemptService.createAttempt(deck: deck);
final ids = attempt.questions.map((q) => q.id).toList();
final uniqueIds = ids.toSet();
expect(uniqueIds.length, equals(ids.length));
});
test('processAttempt updates deck with results', () {
final attempt = attemptService.createAttempt(deck: deck);
final answers = <String, int>{};
// Answer all questions correctly
for (final question in attempt.questions) {
answers[question.id] = question.correctIndices.first;
}
final result = attemptService.processAttempt(
deck: deck,
attempt: attempt,
answers: answers,
);
expect(result.updatedDeck.currentAttemptIndex,
equals(deck.currentAttemptIndex + 1));
});
test('processAttempt calculates correct percentage', () {
final attempt = attemptService.createAttempt(
deck: deck,
attemptSize: 3,
);
final answers = <String, int>{};
// Answer 2 out of 3 correctly
answers[attempt.questions[0].id] =
attempt.questions[0].correctIndices.first;
answers[attempt.questions[1].id] =
attempt.questions[1].correctIndices.first;
answers[attempt.questions[2].id] = 999; // Wrong answer
final result = attemptService.processAttempt(
deck: deck,
attempt: attempt,
answers: answers,
);
expect(result.result.percentageCorrect, closeTo(66.67, 0.01));
expect(result.result.correctCount, equals(2));
});
test('processAttempt tracks incorrect questions', () {
final attempt = attemptService.createAttempt(
deck: deck,
attemptSize: 3,
);
final answers = <String, int>{};
// Answer first correctly, rest incorrectly
answers[attempt.questions[0].id] =
attempt.questions[0].correctIndices.first;
answers[attempt.questions[1].id] = 999;
answers[attempt.questions[2].id] = 999;
final result = attemptService.processAttempt(
deck: deck,
attempt: attempt,
answers: answers,
);
expect(result.result.incorrectQuestions.length, equals(2));
});
test('processAttempt updates question streaks correctly', () {
final question = Question(
id: 'q1',
prompt: 'Test',
answers: ['A', 'B'],
correctAnswerIndices: [0],
consecutiveCorrect: 2,
);
final testDeck = deck.copyWith(questions: [question]);
final attempt = attemptService.createAttempt(
deck: testDeck,
attemptSize: 1,
);
final answers = {question.id: question.correctIndices.first};
final result = attemptService.processAttempt(
deck: testDeck,
attempt: attempt,
answers: answers,
);
final updated = result.updatedDeck.questions.first;
expect(updated.consecutiveCorrect, equals(3));
expect(updated.isKnown, equals(true));
});
});
}

Powered by TurnKey Linux.