merged develop
This commit is contained in:
@@ -11,13 +11,10 @@ CacheableFile _file({
|
||||
bool isDirectory = false,
|
||||
}) => CacheableFile(path: path, isDirectory: isDirectory, name: name);
|
||||
|
||||
Map<String, dynamic> _doc(ListFilesResponse listing) => {
|
||||
'json': jsonEncode(listing.toJson()),
|
||||
'lastupdate': 0,
|
||||
};
|
||||
String _payload(ListFilesResponse listing) => jsonEncode(listing.toJson());
|
||||
|
||||
void main() {
|
||||
group('searchLocalCaches', () {
|
||||
group('local cache index', () {
|
||||
final root = ListFilesResponse({
|
||||
_file(path: 'Documents/', name: 'Documents', isDirectory: true),
|
||||
_file(path: 'Photos/', name: 'Photos', isDirectory: true),
|
||||
@@ -27,51 +24,45 @@ void main() {
|
||||
_file(path: 'Documents/Tax-Report.pdf', name: 'Tax-Report.pdf'),
|
||||
_file(path: 'Documents/Notes.txt', name: 'Notes.txt'),
|
||||
});
|
||||
final docs = {
|
||||
'/MarianumMobile/wd-folder-aaa': _doc(root),
|
||||
'/MarianumMobile/wd-folder-bbb': _doc(documents),
|
||||
'/MarianumMobile/get-room-ccc': {'json': '{}', 'lastupdate': 0},
|
||||
};
|
||||
final index = buildLocalCacheIndex([
|
||||
_payload(root),
|
||||
_payload(documents),
|
||||
]);
|
||||
|
||||
test('matches by name case-insensitively across all caches', () async {
|
||||
final hits = await searchLocalCaches('report', docs: docs);
|
||||
test('matches by name case-insensitively across all caches', () {
|
||||
final hits = searchLocalCacheIndex(index, 'report');
|
||||
final paths = hits.map((f) => f.path).toSet();
|
||||
expect(paths, {'Reports.pdf', 'Documents/Tax-Report.pdf'});
|
||||
});
|
||||
|
||||
test('returns empty list for empty query', () async {
|
||||
expect(await searchLocalCaches(' ', docs: docs), isEmpty);
|
||||
test('returns empty list for empty query', () {
|
||||
expect(searchLocalCacheIndex(index, ' '), isEmpty);
|
||||
});
|
||||
|
||||
test('respects pathScope prefix', () async {
|
||||
final hits = await searchLocalCaches(
|
||||
test('respects pathScope prefix', () {
|
||||
final hits = searchLocalCacheIndex(
|
||||
index,
|
||||
'report',
|
||||
pathScope: ['Documents'],
|
||||
docs: docs,
|
||||
);
|
||||
expect(hits.map((f) => f.path), ['Documents/Tax-Report.pdf']);
|
||||
});
|
||||
|
||||
test('ignores non-folder cache documents', () async {
|
||||
final hits = await searchLocalCaches('anything', docs: docs);
|
||||
// Only documents starting with `wd-folder-` are scanned. The unrelated
|
||||
// `get-room-ccc` doc must not crash the helper.
|
||||
expect(hits, isEmpty);
|
||||
test('skips payloads that are not folder listings', () {
|
||||
expect(buildLocalCacheIndex(['not json', '{"foo": 1}']), isEmpty);
|
||||
});
|
||||
|
||||
test('deduplicates entries that appear in multiple cached folders',
|
||||
() async {
|
||||
test('deduplicates entries that appear in multiple cached folders', () {
|
||||
final shared = _file(
|
||||
path: 'Documents/Tax-Report.pdf',
|
||||
name: 'Tax-Report.pdf',
|
||||
);
|
||||
final dedupRoot = ListFilesResponse({shared});
|
||||
final dedupDocs = {
|
||||
'/MarianumMobile/wd-folder-aaa': _doc(dedupRoot),
|
||||
'/MarianumMobile/wd-folder-bbb': _doc(dedupRoot),
|
||||
};
|
||||
final hits = await searchLocalCaches('tax', docs: dedupDocs);
|
||||
expect(hits, hasLength(1));
|
||||
final dedupIndex = buildLocalCacheIndex([
|
||||
_payload(dedupRoot),
|
||||
_payload(dedupRoot),
|
||||
]);
|
||||
expect(searchLocalCacheIndex(dedupIndex, 'tax'), hasLength(1));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:marianum_mobile/api/marianumconnect/queries/timetable_get_week/timetable_get_week_response.dart';
|
||||
import 'package:marianum_mobile/view/pages/timetable/data/lesson_type_label.dart';
|
||||
|
||||
McTimetableEntry _entry({
|
||||
String lessonType = 'LESSON',
|
||||
String? substitutionText,
|
||||
String? lessonText,
|
||||
}) => McTimetableEntry(
|
||||
id: 1,
|
||||
date: DateTime(2026, 5, 4),
|
||||
startTime: DateTime(1970, 1, 1, 8),
|
||||
endTime: DateTime(1970, 1, 1, 15),
|
||||
subjects: const [],
|
||||
teachers: const [],
|
||||
rooms: const ['A101'],
|
||||
classNames: const ['8a'],
|
||||
lessonType: lessonType,
|
||||
status: 'REGULAR',
|
||||
substitutionText: substitutionText,
|
||||
lessonText: lessonText,
|
||||
infoText: null,
|
||||
);
|
||||
|
||||
void main() {
|
||||
group('LessonTypeLabel.forEntry', () {
|
||||
test('prefers the substitution text', () {
|
||||
expect(
|
||||
LessonTypeLabel.forEntry(
|
||||
_entry(substitutionText: 'Klassenfahrt 8a', lessonText: 'Anderes'),
|
||||
),
|
||||
'Klassenfahrt 8a',
|
||||
);
|
||||
});
|
||||
|
||||
test('falls back to the lesson text', () {
|
||||
expect(
|
||||
LessonTypeLabel.forEntry(_entry(lessonText: ' Wandertag\n8a ')),
|
||||
'Wandertag 8a',
|
||||
);
|
||||
});
|
||||
|
||||
test('falls back to "Event" with room when no text is set', () {
|
||||
expect(
|
||||
LessonTypeLabel.forEntry(_entry(substitutionText: ' ')),
|
||||
'A101 Event',
|
||||
);
|
||||
});
|
||||
|
||||
test('keeps known lesson types over free text', () {
|
||||
expect(
|
||||
LessonTypeLabel.forEntry(
|
||||
_entry(lessonType: 'BREAK_SUPERVISION', lessonText: 'Hof'),
|
||||
),
|
||||
'A101 Aufsicht',
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -65,10 +65,10 @@ void main() {
|
||||
);
|
||||
});
|
||||
|
||||
test('falls back to the teacher when the entry has no class', () {
|
||||
test('shows only the room when the entry has no class', () {
|
||||
expect(
|
||||
_location(showClassInsteadOfTeacher: true, classNames: const []),
|
||||
'A101\nMüller',
|
||||
'A101',
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user