implemented comprehensive accessibility (A11y) support across the app

This commit is contained in:
2026-07-13 23:41:47 +02:00
parent 8274dd46cd
commit 478f0ff20b
46 changed files with 590 additions and 226 deletions
+63
View File
@@ -0,0 +1,63 @@
import 'package:flutter_test/flutter_test.dart';
import 'package:jiffy/jiffy.dart';
import 'package:marianum_mobile/widget/a11y/a11y_labels.dart';
void main() {
setUpAll(() async {
// appointmentLabel formatiert über formatHm() (Jiffy) Locale einmal laden.
await Jiffy.setLocale('de');
});
group('A11yLabels.appointmentLabel', () {
test('setzt Fach, Ort und Zeitspanne zusammen', () {
final label = A11yLabels.appointmentLabel(
subject: 'Mathe',
location: 'Raum 101',
start: DateTime(2026, 5, 8, 8, 0),
end: DateTime(2026, 5, 8, 8, 45),
crossedOut: false,
);
expect(label, 'Mathe, Raum 101, 08:0008:45');
});
test('hängt bei Ausfall den Ausfall-Hinweis an', () {
final label = A11yLabels.appointmentLabel(
subject: 'Deutsch',
location: 'Raum 5',
start: DateTime(2026, 5, 8, 9, 0),
end: DateTime(2026, 5, 8, 9, 45),
crossedOut: true,
);
expect(label, endsWith(A11yLabels.cancelled));
expect(label, 'Deutsch, Raum 5, 09:0009:45, Ausfall');
});
test('glättet Zeilenumbrüche im Ort zu Trennern', () {
final label = A11yLabels.appointmentLabel(
subject: 'Sport',
location: 'Halle\nHr. Müller',
start: DateTime(2026, 5, 8, 10, 0),
end: DateTime(2026, 5, 8, 10, 45),
crossedOut: false,
);
expect(label, 'Sport, Halle, Hr. Müller, 10:0010:45');
});
test('lässt einen leeren Ort weg', () {
final label = A11yLabels.appointmentLabel(
subject: 'Pause',
location: '',
start: DateTime(2026, 5, 8, 11, 0),
end: DateTime(2026, 5, 8, 11, 15),
crossedOut: false,
);
expect(label, 'Pause, 11:0011:15');
});
});
group('A11yLabels.moreAppointments', () {
test('pluralisiert die Overflow-Beschriftung', () {
expect(A11yLabels.moreAppointments(3), '+3 weitere Termine');
});
});
}
@@ -0,0 +1,30 @@
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:marianum_mobile/widget/a11y/a11y_labels.dart';
import 'package:marianum_mobile/widget/app_progress_indicator.dart';
void main() {
Widget wrap(Widget child) => MaterialApp(home: Scaffold(body: child));
testWidgets('trägt standardmäßig das Lade-Label an den Screenreader', (
tester,
) async {
await tester.pumpWidget(wrap(const AppProgressIndicator.large()));
final indicator = tester.widget<CircularProgressIndicator>(
find.byType(CircularProgressIndicator),
);
expect(indicator.semanticsLabel, A11yLabels.loading);
});
testWidgets('reicht ein spezifisches Label durch', (tester) async {
await tester.pumpWidget(
wrap(const AppProgressIndicator.small(semanticsLabel: 'Wird gesendet')),
);
final indicator = tester.widget<CircularProgressIndicator>(
find.byType(CircularProgressIndicator),
);
expect(indicator.semanticsLabel, 'Wird gesendet');
});
}