183 lines
7.4 KiB
Dart
183 lines
7.4 KiB
Dart
import 'package:flutter_test/flutter_test.dart';
|
|
import 'package:shared_preferences/shared_preferences.dart';
|
|
import 'package:words999/models/history_entry_model.dart';
|
|
import 'package:words999/services/words_repository.dart';
|
|
|
|
void main() {
|
|
TestWidgetsFlutterBinding.ensureInitialized();
|
|
|
|
group('WordsRepository Oracle & Divination Tests', () {
|
|
late WordsRepository repo;
|
|
|
|
setUp(() async {
|
|
SharedPreferences.setMockInitialValues({});
|
|
repo = WordsRepository();
|
|
await repo.init(remoteDailyShuffle: false);
|
|
});
|
|
|
|
test('Dataset contains exactly 1000 words with unique randomized session numbers 000 to 999', () {
|
|
expect(repo.totalWords, equals(1000));
|
|
expect(repo.allWords.length, equals(1000));
|
|
|
|
final seenSessionNumbers = <int>{};
|
|
for (int i = 0; i <= 999; i++) {
|
|
final item = repo.getWordBySessionNumber(i);
|
|
expect(item, isNotNull, reason: 'Word with session number $i must exist');
|
|
expect(item!.sessionNumber, equals(i));
|
|
expect(item.formattedSessionNumber.length, equals(3));
|
|
expect(item.word.isNotEmpty, isTrue, reason: 'Word cannot be empty');
|
|
expect(item.description.isNotEmpty, isTrue, reason: 'Symbolic meaning must be present');
|
|
expect(item.partOfSpeech.isNotEmpty, isTrue);
|
|
seenSessionNumbers.add(item.sessionNumber);
|
|
}
|
|
expect(seenSessionNumbers.length, equals(1000));
|
|
});
|
|
|
|
test('Reshuffling changes the order / mapping of words to session numbers', () async {
|
|
await repo.reshuffleSessionNumbers();
|
|
expect(repo.totalWords, equals(1000));
|
|
for (int i = 0; i < 1000; i++) {
|
|
expect(repo.getWordBySessionNumber(i)?.sessionNumber, equals(i));
|
|
}
|
|
});
|
|
|
|
test('Same UTC day reuses the persisted word matrix', () async {
|
|
final first = [
|
|
for (int i = 0; i < 8; i++) repo.getWordBySessionNumber(i)!.word,
|
|
];
|
|
await repo.init(remoteDailyShuffle: false);
|
|
expect([
|
|
for (int i = 0; i < 8; i++) repo.getWordBySessionNumber(i)!.word,
|
|
], first);
|
|
expect(repo.dailyMappingDate, WordsRepository.utcDateStamp());
|
|
});
|
|
|
|
test('Search by number string returns correct session word', () {
|
|
final results0 = repo.search('0');
|
|
expect(results0.isNotEmpty, isTrue);
|
|
expect(results0.first.sessionNumber, equals(0));
|
|
|
|
final results42 = repo.search('42');
|
|
expect(results42.isNotEmpty, isTrue);
|
|
expect(results42.first.sessionNumber, equals(42));
|
|
|
|
final results999 = repo.search('999');
|
|
expect(results999.isNotEmpty, isTrue);
|
|
expect(results999.first.sessionNumber, equals(999));
|
|
});
|
|
|
|
test('Next and previous word navigation wraps around 000..999', () {
|
|
expect(repo.getNextWord(0).sessionNumber, equals(1));
|
|
expect(repo.getNextWord(999).sessionNumber, equals(0));
|
|
expect(repo.getPreviousWord(1).sessionNumber, equals(0));
|
|
expect(repo.getPreviousWord(0).sessionNumber, equals(999));
|
|
});
|
|
|
|
test('Multi-word session history can be saved, updated with AI interpretation, and cleared', () async {
|
|
await repo.clearHistory();
|
|
expect(repo.sessions.isEmpty, isTrue);
|
|
|
|
final session = OracleSession(
|
|
id: 'session_1',
|
|
timestamp: DateTime(2026, 8, 31, 12, 0),
|
|
question: 'В чем скрытый конфликт?',
|
|
wordsCount: 3,
|
|
words: [
|
|
const SessionWord(
|
|
word: 'огонь',
|
|
sessionNumber: 777,
|
|
partOfSpeech: 'существительное',
|
|
category: 'Образ',
|
|
symbolicMeaning: 'Очищающее пламя',
|
|
),
|
|
const SessionWord(
|
|
word: 'вода',
|
|
sessionNumber: 15,
|
|
partOfSpeech: 'существительное',
|
|
category: 'Образ',
|
|
symbolicMeaning: 'Поток интуиции',
|
|
),
|
|
const SessionWord(
|
|
word: 'мир',
|
|
sessionNumber: 999,
|
|
partOfSpeech: 'существительное',
|
|
category: 'Образ',
|
|
symbolicMeaning: 'Гармония согласия',
|
|
),
|
|
],
|
|
);
|
|
|
|
await repo.saveSession(session);
|
|
expect(repo.sessions.length, equals(1));
|
|
expect(repo.sessions.first.words.length, equals(3));
|
|
expect(repo.sessions.first.words[0].word, equals('огонь'));
|
|
expect(repo.sessions.first.words[1].word, equals('вода'));
|
|
expect(repo.sessions.first.question, equals('В чем скрытый конфликт?'));
|
|
|
|
// Update with AI interpretation
|
|
await repo.updateSession('session_1', aiInterpretation: 'Связка огня и воды рождает баланс мира.');
|
|
expect(repo.sessions.first.aiInterpretation, equals('Связка огня и воды рождает баланс мира.'));
|
|
|
|
await repo.clearHistory();
|
|
expect(repo.sessions.isEmpty, isTrue);
|
|
});
|
|
|
|
test('Custom edits: save, export, import, reset, and clear', () async {
|
|
expect(repo.customEditsCount, equals(0));
|
|
|
|
final testWord = repo.getWordBySessionNumber(100)!.word;
|
|
final originalWord = repo.getWordByName(testWord)!;
|
|
expect(originalWord.isUserEdited, isFalse);
|
|
|
|
// Save custom edit
|
|
await repo.saveCustomEdit(
|
|
testWord,
|
|
core: 'Тестовое ядро от пользователя',
|
|
oracle: 'Тестовое толкование от пользователя',
|
|
shadow: 'Тестовая тень',
|
|
asks: 'Тестовый вопрос',
|
|
step: 'Тестовый жест',
|
|
);
|
|
|
|
expect(repo.customEditsCount, equals(1));
|
|
final edited = repo.getWordByName(testWord)!;
|
|
expect(edited.isUserEdited, isTrue);
|
|
expect(edited.core, equals('Тестовое ядро от пользователя'));
|
|
expect(edited.oracle, equals('Тестовое толкование от пользователя'));
|
|
expect(edited.shadow, equals('Тестовая тень'));
|
|
expect(edited.asks, equals('Тестовый вопрос'));
|
|
expect(edited.step, equals('Тестовый жест'));
|
|
|
|
// Export json
|
|
final exportedJson = repo.exportCustomEditsJson();
|
|
expect(exportedJson.contains(testWord), isTrue);
|
|
expect(exportedJson.contains('Тестовое ядро от пользователя'), isTrue);
|
|
|
|
// Reset
|
|
await repo.resetCustomEdit(testWord);
|
|
expect(repo.customEditsCount, equals(0));
|
|
final resetWord = repo.getWordByName(testWord)!;
|
|
expect(resetWord.isUserEdited, isFalse);
|
|
expect(resetWord.core, isNot(equals('Тестовое ядро от пользователя')));
|
|
|
|
// Import back
|
|
final importedCount = await repo.importCustomEditsJson(exportedJson);
|
|
expect(importedCount, equals(1));
|
|
expect(repo.customEditsCount, equals(1));
|
|
final reimported = repo.getWordByName(testWord)!;
|
|
expect(reimported.isUserEdited, isTrue);
|
|
expect(reimported.core, equals('Тестовое ядро от пользователя'));
|
|
|
|
// Clear all
|
|
await repo.clearAllCustomEdits();
|
|
expect(repo.customEditsCount, equals(0));
|
|
expect(repo.getWordByName(testWord)!.isUserEdited, isFalse);
|
|
});
|
|
|
|
test('Word #581 вызывать has appropriate summoning / challenge emojis instead of wood/climbing', () async {
|
|
final word = repo.getWordByName('вызывать');
|
|
expect(word, isNotNull);
|
|
expect(word!.emoji, equals('📯 ⚡'));
|
|
});
|
|
});
|
|
} |