Files
999/test/houses_service_test.dart
T

116 lines
4.1 KiB
Dart

import 'package:flutter_test/flutter_test.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:words999/services/houses_service.dart';
import 'package:words999/services/words_repository.dart';
void main() {
TestWidgetsFlutterBinding.ensureInitialized();
group('HousesService 33x30 Field & 10 Archons Tests', () {
late HousesService service;
setUp(() async {
SharedPreferences.setMockInitialValues({});
final repo = WordsRepository();
await repo.init(remoteDailyShuffle: false);
service = HousesService();
});
test('Session generation creates exactly 10 Archons and 990 Houses without overlap', () {
final session = service.createNewSession(question: 'Тестовый вопрос');
expect(session.sectors.length, equals(10));
expect(session.grid.length, equals(990));
final allWords = <String>{};
// Check Archons
for (int i = 0; i < 10; i++) {
final s = session.sectors[i];
expect(s.index, equals(i));
expect(s.startCol, equals(i * 3));
expect(s.endCol, equals(i * 3 + 2));
expect(s.archonWord.word.isNotEmpty, isTrue);
allWords.add(s.archonWord.word.toLowerCase());
}
expect(allWords.length, equals(10), reason: '10 Archons must be unique');
// Check Houses (33 rows x 30 cols)
for (int r = 0; r < 33; r++) {
for (int c = 0; c < 30; c++) {
final idx = r * 30 + c;
final cell = session.grid[idx];
expect(cell.row, equals(r));
expect(cell.col, equals(c));
expect(cell.houseIndex, equals(idx));
expect(cell.sectorIndex, equals(c ~/ 3));
expect(cell.houseWord.word.isNotEmpty, isTrue);
allWords.add(cell.houseWord.word.toLowerCase());
}
}
// Exactly 1000 unique words partitioned
expect(allWords.length, equals(1000));
});
test('Divination with 5 chosen houses populates guests and computes chains', () {
final session = service.createNewSession();
final chosen = [
session.grid[0].copyWith(selectionOrder: 1),
session.grid[15].copyWith(selectionOrder: 2),
session.grid[42].copyWith(selectionOrder: 3),
session.grid[100].copyWith(selectionOrder: 4),
session.grid[500].copyWith(selectionOrder: 5),
];
final result = service.completeDivination(session, chosen);
expect(result.selectedHouses.length, equals(5));
for (int i = 0; i < 5; i++) {
final h = result.selectedHouses[i];
expect(h.guestWord, isNotNull);
expect(h.selectionOrder, equals(i + 1));
}
expect(result.chains.isNotEmpty, isTrue);
for (final chain in result.chains) {
expect(chain.steps.isNotEmpty, isTrue);
expect(chain.steps.first.house, isNotNull);
expect(chain.steps.first.guest, isNotNull);
}
});
test('Chain length is capped at maximum 9 links', () {
final session = service.createNewSession();
final chosen = [
session.grid[0].copyWith(selectionOrder: 1),
];
final result = service.completeDivination(session, chosen);
for (final chain in result.chains) {
expect(chain.steps.length, lessThanOrEqualTo(9));
}
});
test('Querent word is guaranteed to be in houses and its index matches dynamically', () {
final repo = WordsRepository();
final manWord = repo.allWords.firstWhere((w) => w.word.toLowerCase() == 'мужчина');
final session1 = service.createNewSession(querentWord: manWord);
expect(session1.querentHouseIndex, isNotNull);
final qIndex1 = session1.querentHouseIndex!;
expect(session1.grid[qIndex1].houseWord.word.toLowerCase(), equals('мужчина'));
// Reshuffle matrix multiple times: the querent must always match the house word at its index
for (int i = 0; i < 5; i++) {
final sessionRe = service.createNewSession(querentWord: manWord);
expect(sessionRe.querentHouseIndex, isNotNull);
final qIdx = sessionRe.querentHouseIndex!;
expect(sessionRe.grid[qIdx].houseWord.word.toLowerCase(), equals('мужчина'));
}
});
});
}