expectNoA11yViolations function
Future<void>
expectNoA11yViolations(
- WidgetTester tester, {
- Finder? finder,
- List<
A11yRule> rules = const [ContrastRule(), TapTargetSizeRule()], - List<
A11ySemanticsRule> semanticsRules = const [SemanticLabelRule(), FocusOrderRule()], - A11ySeverity minimumSeverity = A11ySeverity.warning,
- A11yReport? baseline,
Fails the current test if A11yReport.generate finds any violation at
or above minimumSeverity below finder (the whole app, if omitted).
Runs headless: no real device or screen reader needed. Semantics-based
rules (on by default via semanticsRules) need an active
SemanticsHandle to see anything — testWidgets provides one
automatically unless the test opted out with semanticsEnabled: false.
Pass baseline — e.g. loaded from a checked-in JSON report via
A11yReport.fromJson(jsonDecode(await File(...).readAsString())) — to
only fail on violations not already present in it, via
A11yReport.newViolationsComparedTo. That's the "fail the PR build on
new violations" workflow: known, accepted issues don't block every
unrelated change.
Implementation
Future<void> expectNoA11yViolations(
WidgetTester tester, {
Finder? finder,
List<A11yRule> rules = const [ContrastRule(), TapTargetSizeRule()],
List<A11ySemanticsRule> semanticsRules = const [
SemanticLabelRule(),
FocusOrderRule(),
],
A11ySeverity minimumSeverity = A11ySeverity.warning,
A11yReport? baseline,
}) async {
final context = finder != null
? tester.element(finder)
: tester.binding.rootElement!;
final report = A11yReport.generate(
context,
rules: rules,
semanticsRules: semanticsRules,
);
var relevant = [
for (final v in report.violations)
if (_severityRank(v.severity) >= _severityRank(minimumSeverity)) v,
];
if (baseline != null) {
relevant = A11yReport(
violations: relevant,
generatedAt: report.generatedAt,
).newViolationsComparedTo(baseline);
}
if (relevant.isEmpty) return;
final buffer = StringBuffer(
'flutter_a11y_lens found ${relevant.length} violation(s):\n',
);
for (final v in relevant) {
buffer.writeln(
' [${v.severity.name}] ${v.ruleId} on ${v.widgetType ?? 'unknown widget'}: '
'${v.message}',
);
if (v.suggestedFix != null) {
buffer.writeln(' fix: ${v.suggestedFix}');
}
}
fail(buffer.toString());
}