fix(flutter/a11y assessments): h1 missing a11y from each page on the web app (#152198)
Adds Semantic Widget to wrap the contents of each page's AppBar title attribute and adds header: true and headingLevel: 1 as Semantic attributes so the content of the title is compiled as an h1 tag to meet accessibility guidelines that each page must have a h1 tag present. Also updates the test cases for the home page and each use case page to check for its respective h1. [Before Screenshot - Accessibility Assessments Home Page](https://screenshot.googleplex.com/4i9LuiGwvLnEcZ8) [Before Screenshot - Checkbox List Title -- note: each use case page is missing an h1](https://screenshot.googleplex.com/3qQjfqvAMTehRsm) [After Screenshot - Accessibility Assessments Home Page](https://screenshot.googleplex.com/APSJJXBmwNBP35m) [After Screenshot - Checkbox List Title-- note: change is similar across each Accessibility use case page](https://screenshot.googleplex.com/6EGgZnTusEgeN5L) Fixes b/338035526
This commit is contained in:
parent
87abed2b23
commit
85b3d97673
@ -77,7 +77,9 @@ class HomePageState extends State<HomePage> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(title: const Text('Accessibility Assessments')),
|
||||
appBar: AppBar(
|
||||
title: Semantics(headingLevel: 1, child: const Text('Accessibility Assessments')),
|
||||
),
|
||||
body: Center(
|
||||
child: ListView(
|
||||
controller: scrollController,
|
||||
|
@ -31,7 +31,7 @@ class MainWidgetState extends State<MainWidget> {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
|
||||
title: const Text('ActionChip'),
|
||||
title: Semantics(headingLevel:1, child: const Text('ActionChip')),
|
||||
),
|
||||
body: Center(
|
||||
child: Column(
|
||||
|
@ -50,7 +50,7 @@ class _MainWidgetState extends State<_MainWidget> {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
|
||||
title: const Text('AutoComplete'),
|
||||
title: Semantics(headingLevel: 1, child: const Text('AutoComplete Demo')),
|
||||
),
|
||||
body: Center(
|
||||
child: Column(
|
||||
|
@ -25,12 +25,13 @@ class MainWidget extends StatefulWidget {
|
||||
}
|
||||
|
||||
class MainWidgetState extends State<MainWidget> {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
|
||||
title: const Text('Badge'),
|
||||
title: Semantics(headingLevel: 1, child: const Text('Badge Demo')),
|
||||
),
|
||||
body: const Center(
|
||||
child: Badge(
|
||||
|
@ -31,7 +31,7 @@ class MainWidgetState extends State<MainWidget> {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
|
||||
title: const Text('Card'),
|
||||
title: Semantics(headingLevel: 1, child: const Text('Card')),
|
||||
),
|
||||
body: const Center(
|
||||
child: Column(
|
||||
|
@ -28,7 +28,9 @@ class _MainWidgetState extends State<_MainWidget> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(title: const Text('CheckBoxListTile')),
|
||||
appBar: AppBar(
|
||||
title: Semantics(headingLevel: 1, child: const Text('CheckBoxListTile Demo')),
|
||||
),
|
||||
body: ListView(
|
||||
children: <Widget>[
|
||||
CheckboxListTile(
|
||||
|
@ -30,7 +30,7 @@ class _MainWidgetState extends State<_MainWidget> {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
|
||||
title: const Text('DatePicker'),
|
||||
title: Semantics(headingLevel: 1, child: const Text('DatePicker Demo')),
|
||||
),
|
||||
body: Center(
|
||||
child: TextButton(
|
||||
|
@ -24,7 +24,7 @@ class _MainWidget extends StatelessWidget {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
|
||||
title: const Text('Dialog'),
|
||||
title: Semantics(headingLevel: 1, child: const Text('Dialog Demo')),
|
||||
),
|
||||
body: Center(
|
||||
child: TextButton(
|
||||
|
@ -31,8 +31,8 @@ class _DrawerExampleState extends State<DrawerExample> {
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: const Text('Drawer Example'),
|
||||
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
|
||||
title: Semantics(headingLevel: 1, child: const Text('Drawer Demo')),
|
||||
),
|
||||
endDrawer: Drawer(
|
||||
child: ListView(
|
||||
|
@ -32,7 +32,7 @@ class _ExpansionTileExampleState extends State<ExpansionTileExample> {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
|
||||
title: const Text('ExpansionTile'),
|
||||
title: Semantics(headingLevel: 1, child: const Text('ExpansionTile')),
|
||||
),
|
||||
body: Column(
|
||||
children: <Widget>[
|
||||
|
@ -60,7 +60,7 @@ class MainWidgetState extends State<MainWidget> {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
|
||||
title: const Text('MaterialBanner'),
|
||||
title: Semantics(headingLevel: 1, child: const Text('MaterialBanner Demo')),
|
||||
),
|
||||
body: Center(
|
||||
child: ElevatedButton(
|
||||
|
@ -32,7 +32,7 @@ class MainWidgetState extends State<MainWidget> {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
|
||||
title: const Text('NavigationBar'),
|
||||
title: Semantics(headingLevel: 1, child: const Text('NavigationBar Demo')),
|
||||
),
|
||||
bottomNavigationBar: NavigationBar(
|
||||
onDestinationSelected: (int index) {
|
||||
|
@ -62,8 +62,8 @@ class _NavigationDrawerExampleState extends State<NavigationDrawerExample> {
|
||||
return Scaffold(
|
||||
key: scaffoldKey,
|
||||
appBar: AppBar(
|
||||
title: const Text('Navigation Drawer Example'),
|
||||
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
|
||||
title: Semantics(headingLevel: 1, child: const Text('Navigation Drawer Demo')),
|
||||
),
|
||||
body: SafeArea(
|
||||
bottom: false,
|
||||
|
@ -36,7 +36,9 @@ class _MainWidgetState extends State<_MainWidget> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(title: const Text('Radio button')),
|
||||
appBar: AppBar(
|
||||
title: Semantics(headingLevel: 1, child: const Text('Radio button demo'))
|
||||
),
|
||||
body: ListView(
|
||||
children: <Widget>[
|
||||
RadioListTile<SingingCharacter>(
|
||||
|
@ -33,7 +33,7 @@ class MainWidgetState extends State<MainWidget> {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
|
||||
title: const Text('Slider'),
|
||||
title: Semantics(headingLevel: 1, child: const Text('Slider demo')),
|
||||
),
|
||||
body: Center(
|
||||
child: Semantics(
|
||||
|
@ -30,7 +30,7 @@ class MainWidgetState extends State<MainWidget> {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
|
||||
title: const Text('SnackBar'),
|
||||
title: Semantics(headingLevel: 1, child: const Text('SnackBar')),
|
||||
),
|
||||
body: Center(
|
||||
child: Column(
|
||||
|
@ -32,7 +32,7 @@ class _SwitchListTileExampleState extends State<SwitchListTileExample> {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
|
||||
title: const Text('SwitchListTile'),
|
||||
title: Semantics(headingLevel: 1, child: const Text('SwitchListTile')),
|
||||
),
|
||||
body: Center(
|
||||
child: Column(
|
||||
|
@ -32,7 +32,7 @@ class MainWidgetState extends State<MainWidget> {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
|
||||
title: const Text('TextButton'),
|
||||
title: Semantics(headingLevel: 1, child: const Text('TextButton Demo')),
|
||||
),
|
||||
body: Center(
|
||||
child: Column(
|
||||
|
@ -25,7 +25,7 @@ class _MainWidget extends StatelessWidget {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
|
||||
title: const Text('TextField'),
|
||||
title: Semantics(headingLevel: 1, child: const Text('TextField demo')),
|
||||
),
|
||||
body: ListView(
|
||||
children: <Widget>[
|
||||
|
@ -25,7 +25,7 @@ class _MainWidget extends StatelessWidget {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
|
||||
title: const Text('TextField password'),
|
||||
title: Semantics(headingLevel: 1, child: const Text('TextField password demo')),
|
||||
),
|
||||
body: ListView(
|
||||
children: const <Widget>[
|
||||
|
@ -16,4 +16,11 @@ void main() {
|
||||
|
||||
expect(find.text('apple'), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets('auto complete has one h1 tag', (WidgetTester tester) async {
|
||||
await pumpsUseCase(tester, AutoCompleteUseCase());
|
||||
final Finder findHeadingLevelOnes = find.bySemanticsLabel(RegExp('AutoComplete Demo'));
|
||||
await tester.pumpAndSettle();
|
||||
expect(findHeadingLevelOnes, findsOne);
|
||||
});
|
||||
}
|
||||
|
@ -13,4 +13,11 @@ void main() {
|
||||
expect(find.semantics.byLabel('5 new messages'), findsOne);
|
||||
expect(find.semantics.byLabel('Messages'), findsOne);
|
||||
});
|
||||
|
||||
testWidgets('badge has one h1 tag', (WidgetTester tester) async {
|
||||
await pumpsUseCase(tester, BadgeUseCase());
|
||||
final Finder findHeadingLevelOnes = find.bySemanticsLabel(RegExp('Badge Demo'));
|
||||
await tester.pumpAndSettle();
|
||||
expect(findHeadingLevelOnes, findsOne);
|
||||
});
|
||||
}
|
||||
|
@ -14,4 +14,11 @@ void main() {
|
||||
expect(find.text('a check box list title'), findsOneWidget);
|
||||
expect(find.text('a disabled check box list title'), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets('check box list has one h1 tag', (WidgetTester tester) async {
|
||||
await pumpsUseCase(tester, CheckBoxListTile());
|
||||
final Finder findHeadingLevelOnes = find.bySemanticsLabel(RegExp('CheckBoxListTile Demo'));
|
||||
await tester.pumpAndSettle();
|
||||
expect(findHeadingLevelOnes, findsOne);
|
||||
});
|
||||
}
|
||||
|
@ -17,4 +17,11 @@ void main() {
|
||||
await tester.pumpAndSettle();
|
||||
expect(find.byType(DatePickerDialog), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets('datepicker has one h1 tag', (WidgetTester tester) async {
|
||||
await pumpsUseCase(tester, DatePickerUseCase());
|
||||
final Finder findHeadingLevelOnes = find.bySemanticsLabel('DatePicker Demo');
|
||||
await tester.pumpAndSettle();
|
||||
expect(findHeadingLevelOnes, findsOne);
|
||||
});
|
||||
}
|
||||
|
@ -28,4 +28,11 @@ void main() {
|
||||
await tester.pumpAndSettle();
|
||||
expect(find.text('This is a typical dialog.'), findsNothing);
|
||||
});
|
||||
|
||||
testWidgets('dialog has one h1 tag', (WidgetTester tester) async {
|
||||
await pumpsUseCase(tester, DialogUseCase());
|
||||
final Finder findHeadingLevelOnes = find.bySemanticsLabel('Dialog Demo');
|
||||
await tester.pumpAndSettle();
|
||||
expect(findHeadingLevelOnes, findsOne);
|
||||
});
|
||||
}
|
||||
|
@ -20,4 +20,11 @@ void main() {
|
||||
|
||||
expect(find.byType(Drawer), findsExactly(1));
|
||||
});
|
||||
|
||||
testWidgets('drawer has one h1 tag', (WidgetTester tester) async {
|
||||
await pumpsUseCase(tester, DrawerUseCase());
|
||||
final Finder findHeadingLevelOnes = find.bySemanticsLabel('Drawer Demo');
|
||||
await tester.pumpAndSettle();
|
||||
expect(findHeadingLevelOnes, findsOne);
|
||||
});
|
||||
}
|
||||
|
@ -140,4 +140,11 @@ void main() {
|
||||
expect(appScheme.inversePrimary.value,
|
||||
MaterialDynamicColors.inversePrimary.getArgb(highContrastScheme));
|
||||
});
|
||||
|
||||
testWidgets('a11y assessments home page has one h1 tag', (WidgetTester tester) async {
|
||||
await tester.pumpWidget(const App());
|
||||
final Finder findHeadingLevelOnes = find.bySemanticsLabel('Accessibility Assessments');
|
||||
await tester.pumpAndSettle();
|
||||
expect(findHeadingLevelOnes, findsOne);
|
||||
});
|
||||
}
|
||||
|
@ -20,4 +20,11 @@ void main() {
|
||||
await tester.pumpAndSettle();
|
||||
expect(find.text('Hello, I am a Material Banner'), findsNothing);
|
||||
});
|
||||
|
||||
testWidgets('material banner has one h1 tag', (WidgetTester tester) async {
|
||||
await pumpsUseCase(tester, MaterialBannerUseCase());
|
||||
final Finder findHeadingLevelOnes = find.bySemanticsLabel('MaterialBanner Demo');
|
||||
await tester.pumpAndSettle();
|
||||
expect(findHeadingLevelOnes, findsOne);
|
||||
});
|
||||
}
|
||||
|
@ -20,4 +20,11 @@ void main() {
|
||||
await tester.pumpAndSettle();
|
||||
expect(find.text('Page 3'), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets('navigation bar has one h1 tag', (WidgetTester tester) async {
|
||||
await pumpsUseCase(tester, NavigationBarUseCase());
|
||||
final Finder findHeadingLevelOnes = find.bySemanticsLabel('NavigationBar Demo');
|
||||
await tester.pumpAndSettle();
|
||||
expect(findHeadingLevelOnes, findsOne);
|
||||
});
|
||||
}
|
||||
|
@ -20,4 +20,11 @@ void main() {
|
||||
|
||||
expect(find.byType(NavigationDrawer), findsExactly(1));
|
||||
});
|
||||
|
||||
testWidgets('navigation drawer has one h1 tag', (WidgetTester tester) async {
|
||||
await pumpsUseCase(tester, NavigationDrawerUseCase());
|
||||
final Finder findHeadingLevelOnes = find.bySemanticsLabel('Navigation Drawer Demo');
|
||||
await tester.pumpAndSettle();
|
||||
expect(findHeadingLevelOnes, findsOne);
|
||||
});
|
||||
}
|
||||
|
@ -14,4 +14,11 @@ void main() {
|
||||
expect(find.text('Lafayette'), findsOneWidget);
|
||||
expect(find.text('Jefferson'), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets('radio button demo page has one h1 tag', (WidgetTester tester) async {
|
||||
await pumpsUseCase(tester, RadioListTileUseCase());
|
||||
final Finder findHeadingLevelOnes = find.bySemanticsLabel('Radio button demo');
|
||||
await tester.pumpAndSettle();
|
||||
expect(findHeadingLevelOnes, findsOne);
|
||||
});
|
||||
}
|
||||
|
@ -26,4 +26,11 @@ void main() {
|
||||
find.bySemanticsLabel('Accessibility Test Slider');
|
||||
expect(semanticsWidget, findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets('slider demo page has one h1 tag', (WidgetTester tester) async {
|
||||
await pumpsUseCase(tester, SliderUseCase());
|
||||
final Finder findHeadingLevelOnes = find.bySemanticsLabel('Slider demo');
|
||||
await tester.pumpAndSettle();
|
||||
expect(findHeadingLevelOnes, findsOne);
|
||||
});
|
||||
}
|
||||
|
@ -27,4 +27,11 @@ void main() {
|
||||
await tester.pumpAndSettle();
|
||||
expect(find.text('Clicked 2 time(s).'), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets('text button demo page has one h1 tag', (WidgetTester tester) async {
|
||||
await pumpsUseCase(tester, TextButtonUseCase());
|
||||
final Finder findHeadingLevelOnes = find.bySemanticsLabel('TextButton Demo');
|
||||
await tester.pumpAndSettle();
|
||||
expect(findHeadingLevelOnes, findsOne);
|
||||
});
|
||||
}
|
||||
|
@ -50,4 +50,11 @@ void main() {
|
||||
expect(textField.decoration?.hintText, isNull);
|
||||
}
|
||||
});
|
||||
|
||||
testWidgets('text field password demo page has one h1 tag', (WidgetTester tester) async {
|
||||
await pumpsUseCase(tester, TextFieldPasswordUseCase());
|
||||
final Finder findHeadingLevelOnes = find.bySemanticsLabel('TextField password demo');
|
||||
await tester.pumpAndSettle();
|
||||
expect(findHeadingLevelOnes, findsOne);
|
||||
});
|
||||
}
|
||||
|
@ -64,4 +64,11 @@ void main() {
|
||||
find.bySemanticsLabel(RegExp(textFieldLabel));
|
||||
expect(semanticsWidgets, findsExactly(2));
|
||||
});
|
||||
|
||||
testWidgets('text field demo page has one h1 tag', (WidgetTester tester) async {
|
||||
await pumpsUseCase(tester, TextFieldUseCase());
|
||||
final Finder findHeadingLevelOnes = find.bySemanticsLabel('TextField demo');
|
||||
await tester.pumpAndSettle();
|
||||
expect(findHeadingLevelOnes, findsOne);
|
||||
});
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user