diff --git a/dev/a11y_assessments/lib/common/dynamic_title.dart b/dev/a11y_assessments/lib/common/dynamic_title.dart new file mode 100644 index 00000000000..56ef31c113b --- /dev/null +++ b/dev/a11y_assessments/lib/common/dynamic_title.dart @@ -0,0 +1,21 @@ +// Copyright 2014 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:flutter/material.dart'; + +class DynamicTitle extends StatelessWidget { + const DynamicTitle({super.key, required this.title, required this.child}); + + final String title; + final Widget child; + + @override + Widget build(BuildContext context) { + return Title( + title: title, + color: Theme.of(context).colorScheme.primary, + child: child, + ); + } +} diff --git a/dev/a11y_assessments/lib/main.dart b/dev/a11y_assessments/lib/main.dart index d3a6f990207..db6c71a0497 100644 --- a/dev/a11y_assessments/lib/main.dart +++ b/dev/a11y_assessments/lib/main.dart @@ -35,10 +35,11 @@ class App extends StatelessWidget { final Map routes = Map.fromEntries( useCases.map((UseCase useCase) => - MapEntry(useCase.route, useCase.build)), + MapEntry(useCase.route, (BuildContext context) => useCase.buildWithTitle(context))), ); + return MaterialApp( - title: 'Accessibility Assessments', + title: 'Accessibility Assessments Home Page', theme: lightTheme, darkTheme: darkTheme, routes: {'/': (_) => const HomePage(), ...routes}, @@ -68,7 +69,7 @@ class HomePageState extends State { child: Builder(builder: (BuildContext context) { return TextButton( key: Key(useCase.name), - onPressed: () => Navigator.of(context).pushNamed(useCase.route), + onPressed: () => Navigator.of(context).pushNamed(useCase.route, arguments: useCase.name), child: Text(useCase.name), ); })); @@ -76,9 +77,10 @@ class HomePageState extends State { @override Widget build(BuildContext context) { + return Scaffold( appBar: AppBar( - title: Semantics(headingLevel: 1, child: const Text('Accessibility Assessments')), + title: Semantics(headingLevel: 1, child: const Text('Accessibility Assessments')), ), body: Center( child: ListView( diff --git a/dev/a11y_assessments/lib/use_cases/action_chip.dart b/dev/a11y_assessments/lib/use_cases/action_chip.dart index 5472f97cbc3..007f69738e6 100644 --- a/dev/a11y_assessments/lib/use_cases/action_chip.dart +++ b/dev/a11y_assessments/lib/use_cases/action_chip.dart @@ -3,7 +3,7 @@ // found in the LICENSE file. import 'package:flutter/material.dart'; - +import '../utils.dart'; import 'use_cases.dart'; class ActionChipUseCase extends UseCase { @@ -26,12 +26,15 @@ class MainWidget extends StatefulWidget { class MainWidgetState extends State { bool favorite = false; + + String pageTitle = getUseCaseName(ActionChipUseCase()); + @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( backgroundColor: Theme.of(context).colorScheme.inversePrimary, - title: Semantics(headingLevel:1, child: const Text('ActionChip')), + title: Semantics(headingLevel:1, child: Text('$pageTitle Demo')), ), body: Center( child: Column( diff --git a/dev/a11y_assessments/lib/use_cases/auto_complete.dart b/dev/a11y_assessments/lib/use_cases/auto_complete.dart index 12a10dcf694..b3c618e2059 100644 --- a/dev/a11y_assessments/lib/use_cases/auto_complete.dart +++ b/dev/a11y_assessments/lib/use_cases/auto_complete.dart @@ -3,7 +3,7 @@ // found in the LICENSE file. import 'package:flutter/material.dart'; - +import '../utils.dart'; import 'use_cases.dart'; class AutoCompleteUseCase extends UseCase { @@ -45,12 +45,14 @@ class _MainWidgetState extends State<_MainWidget> { ); } + String pageTitle = getUseCaseName(AutoCompleteUseCase()); + @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( backgroundColor: Theme.of(context).colorScheme.inversePrimary, - title: Semantics(headingLevel: 1, child: const Text('AutoComplete Demo')), + title: Semantics(headingLevel: 1, child: Text('$pageTitle Demo')), ), body: Center( child: Column( diff --git a/dev/a11y_assessments/lib/use_cases/badge.dart b/dev/a11y_assessments/lib/use_cases/badge.dart index 1cd2c3d643e..1389b631a29 100644 --- a/dev/a11y_assessments/lib/use_cases/badge.dart +++ b/dev/a11y_assessments/lib/use_cases/badge.dart @@ -3,7 +3,7 @@ // found in the LICENSE file. import 'package:flutter/material.dart'; - +import '../utils.dart'; import 'use_cases.dart'; class BadgeUseCase extends UseCase { @@ -25,13 +25,14 @@ class MainWidget extends StatefulWidget { } class MainWidgetState extends State { + String pageTitle = getUseCaseName(BadgeUseCase()); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( backgroundColor: Theme.of(context).colorScheme.inversePrimary, - title: Semantics(headingLevel: 1, child: const Text('Badge Demo')), + title: Semantics(headingLevel: 1, child: Text('$pageTitle Demo')), ), body: const Center( child: Badge( diff --git a/dev/a11y_assessments/lib/use_cases/card.dart b/dev/a11y_assessments/lib/use_cases/card.dart index 369cd0d2b30..01ebd6ea569 100644 --- a/dev/a11y_assessments/lib/use_cases/card.dart +++ b/dev/a11y_assessments/lib/use_cases/card.dart @@ -3,7 +3,7 @@ // found in the LICENSE file. import 'package:flutter/material.dart'; - +import '../utils.dart'; import 'use_cases.dart'; class CardUseCase extends UseCase { @@ -26,12 +26,15 @@ class MainWidget extends StatefulWidget { class MainWidgetState extends State { bool favorite = false; + + String pageTitle = getUseCaseName(CardUseCase()); + @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( backgroundColor: Theme.of(context).colorScheme.inversePrimary, - title: Semantics(headingLevel: 1, child: const Text('Card')), + title: Semantics(headingLevel: 1, child: Text('$pageTitle Demo')), ), body: const Center( child: Column( diff --git a/dev/a11y_assessments/lib/use_cases/check_box_list_tile.dart b/dev/a11y_assessments/lib/use_cases/check_box_list_tile.dart index 36125eec6b5..e0058263313 100644 --- a/dev/a11y_assessments/lib/use_cases/check_box_list_tile.dart +++ b/dev/a11y_assessments/lib/use_cases/check_box_list_tile.dart @@ -3,7 +3,7 @@ // found in the LICENSE file. import 'package:flutter/material.dart'; - +import '../utils.dart'; import 'use_cases.dart'; class CheckBoxListTile extends UseCase { @@ -25,11 +25,13 @@ class _MainWidget extends StatefulWidget { class _MainWidgetState extends State<_MainWidget> { bool _checked = false; + String pageTitle = getUseCaseName(CheckBoxListTile()); + @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( - title: Semantics(headingLevel: 1, child: const Text('CheckBoxListTile Demo')), + title: Semantics(headingLevel: 1, child: Text('$pageTitle Demo')), ), body: ListView( children: [ diff --git a/dev/a11y_assessments/lib/use_cases/date_picker.dart b/dev/a11y_assessments/lib/use_cases/date_picker.dart index 3b9df403545..d9719bcd3d7 100644 --- a/dev/a11y_assessments/lib/use_cases/date_picker.dart +++ b/dev/a11y_assessments/lib/use_cases/date_picker.dart @@ -3,7 +3,7 @@ // found in the LICENSE file. import 'package:flutter/material.dart'; - +import '../utils.dart'; import 'use_cases.dart'; class DatePickerUseCase extends UseCase { @@ -25,12 +25,15 @@ class _MainWidget extends StatefulWidget { } class _MainWidgetState extends State<_MainWidget> { + + String pageTitle = getUseCaseName(DatePickerUseCase()); + @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( backgroundColor: Theme.of(context).colorScheme.inversePrimary, - title: Semantics(headingLevel: 1, child: const Text('DatePicker Demo')), + title: Semantics(headingLevel: 1, child: Text('$pageTitle Demo')), ), body: Center( child: TextButton( diff --git a/dev/a11y_assessments/lib/use_cases/dialog.dart b/dev/a11y_assessments/lib/use_cases/dialog.dart index fa47216b152..942930110dd 100644 --- a/dev/a11y_assessments/lib/use_cases/dialog.dart +++ b/dev/a11y_assessments/lib/use_cases/dialog.dart @@ -3,7 +3,7 @@ // found in the LICENSE file. import 'package:flutter/material.dart'; - +import '../utils.dart'; import 'use_cases.dart'; class DialogUseCase extends UseCase { @@ -14,17 +14,20 @@ class DialogUseCase extends UseCase { String get route => '/dialog'; @override - Widget build(BuildContext context) => const _MainWidget(); + Widget build(BuildContext context) => _MainWidget(); } class _MainWidget extends StatelessWidget { - const _MainWidget(); + _MainWidget(); + + final String pageTitle = getUseCaseName(DialogUseCase()); + @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( backgroundColor: Theme.of(context).colorScheme.inversePrimary, - title: Semantics(headingLevel: 1, child: const Text('Dialog Demo')), + title: Semantics(headingLevel: 1, child: Text('$pageTitle Demo')), ), body: Center( child: TextButton( diff --git a/dev/a11y_assessments/lib/use_cases/drawer.dart b/dev/a11y_assessments/lib/use_cases/drawer.dart index 5e8f41154e2..45b2552fb25 100644 --- a/dev/a11y_assessments/lib/use_cases/drawer.dart +++ b/dev/a11y_assessments/lib/use_cases/drawer.dart @@ -3,7 +3,7 @@ // found in the LICENSE file. import 'package:flutter/material.dart'; - +import '../utils.dart'; import 'use_cases.dart'; class DrawerUseCase extends UseCase { @@ -27,12 +27,14 @@ class DrawerExample extends StatefulWidget { class _DrawerExampleState extends State { String selectedPage = ''; + String pageTitle = getUseCaseName(DrawerUseCase()); + @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( backgroundColor: Theme.of(context).colorScheme.inversePrimary, - title: Semantics(headingLevel: 1, child: const Text('Drawer Demo')), + title: Semantics(headingLevel: 1, child: Text('$pageTitle Demo')), ), endDrawer: Drawer( child: ListView( diff --git a/dev/a11y_assessments/lib/use_cases/expansion_tile.dart b/dev/a11y_assessments/lib/use_cases/expansion_tile.dart index 03736f712ff..e090c081b73 100644 --- a/dev/a11y_assessments/lib/use_cases/expansion_tile.dart +++ b/dev/a11y_assessments/lib/use_cases/expansion_tile.dart @@ -3,7 +3,7 @@ // found in the LICENSE file. import 'package:flutter/material.dart'; - +import '../utils.dart'; import 'use_cases.dart'; class ExpansionTileUseCase extends UseCase { @@ -27,12 +27,14 @@ class ExpansionTileExample extends StatefulWidget { class _ExpansionTileExampleState extends State { bool _customTileExpanded = false; + String pageTitle = getUseCaseName(ExpansionTileUseCase()); + @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( backgroundColor: Theme.of(context).colorScheme.inversePrimary, - title: Semantics(headingLevel: 1, child: const Text('ExpansionTile')), + title: Semantics(headingLevel: 1, child: Text('$pageTitle Demo')), ), body: Column( children: [ @@ -47,9 +49,7 @@ class _ExpansionTileExampleState extends State { title: const Text('ExpansionTile 2'), subtitle: const Text('Custom expansion arrow icon'), trailing: Icon( - _customTileExpanded - ? Icons.arrow_drop_down_circle - : Icons.arrow_drop_down, + _customTileExpanded ? Icons.arrow_drop_down_circle : Icons.arrow_drop_down, ), children: const [ ListTile(title: Text('This is tile number 2')), diff --git a/dev/a11y_assessments/lib/use_cases/material_banner.dart b/dev/a11y_assessments/lib/use_cases/material_banner.dart index 2ba15dd39e1..ec31c85ffd4 100644 --- a/dev/a11y_assessments/lib/use_cases/material_banner.dart +++ b/dev/a11y_assessments/lib/use_cases/material_banner.dart @@ -3,7 +3,7 @@ // found in the LICENSE file. import 'package:flutter/material.dart'; - +import '../utils.dart'; import 'use_cases.dart'; class MaterialBannerUseCase extends UseCase { @@ -29,6 +29,8 @@ class MainWidgetState extends State { final FocusNode dismissButtonFocusNode = FocusNode(); final FocusNode showButtonFocusNode = FocusNode(); + String pageTitle = getUseCaseName(MaterialBannerUseCase()); + @override void dispose() { dismissButtonFocusNode.dispose(); @@ -62,10 +64,10 @@ class MainWidgetState extends State { @override Widget build(BuildContext context) { - return Scaffold( + return Scaffold( appBar: AppBar( backgroundColor: Theme.of(context).colorScheme.inversePrimary, - title: Semantics(headingLevel: 1, child: const Text('MaterialBanner Demo')), + title: Semantics(headingLevel: 1, child: Text('$pageTitle Demo')), ), body: Center( child: ElevatedButton( diff --git a/dev/a11y_assessments/lib/use_cases/navigation_bar.dart b/dev/a11y_assessments/lib/use_cases/navigation_bar.dart index b19cc49062c..7b3c84e9a44 100644 --- a/dev/a11y_assessments/lib/use_cases/navigation_bar.dart +++ b/dev/a11y_assessments/lib/use_cases/navigation_bar.dart @@ -3,7 +3,7 @@ // found in the LICENSE file. import 'package:flutter/material.dart'; - +import '../utils.dart'; import 'use_cases.dart'; class NavigationBarUseCase extends UseCase { @@ -27,12 +27,14 @@ class MainWidget extends StatefulWidget { class MainWidgetState extends State { int currentPageIndex = 0; + String pageTitle = getUseCaseName(NavigationBarUseCase()); + @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( backgroundColor: Theme.of(context).colorScheme.inversePrimary, - title: Semantics(headingLevel: 1, child: const Text('NavigationBar Demo')), + title: Semantics(headingLevel: 1, child: Text('$pageTitle Demo')), ), bottomNavigationBar: NavigationBar( onDestinationSelected: (int index) { diff --git a/dev/a11y_assessments/lib/use_cases/navigation_drawer.dart b/dev/a11y_assessments/lib/use_cases/navigation_drawer.dart index 4bdc3ef139c..ddc1b84010a 100644 --- a/dev/a11y_assessments/lib/use_cases/navigation_drawer.dart +++ b/dev/a11y_assessments/lib/use_cases/navigation_drawer.dart @@ -2,10 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'package:flutter/material.dart'; +import 'package:flutter/material.dart'; +import '../utils.dart'; import 'use_cases.dart'; + class ExampleDestination { const ExampleDestination(this.label, this.icon, this.selectedIcon); @@ -58,12 +60,14 @@ class _NavigationDrawerExampleState extends State { scaffoldKey.currentState!.openEndDrawer(); } + String pageTitle = getUseCaseName(NavigationDrawerUseCase()); + Widget buildDrawerScaffold(BuildContext context) { return Scaffold( key: scaffoldKey, appBar: AppBar( backgroundColor: Theme.of(context).colorScheme.inversePrimary, - title: Semantics(headingLevel: 1, child: const Text('Navigation Drawer Demo')), + title: Semantics(headingLevel: 1, child: Text('$pageTitle Demo')), ), body: SafeArea( bottom: false, diff --git a/dev/a11y_assessments/lib/use_cases/navigation_rail.dart b/dev/a11y_assessments/lib/use_cases/navigation_rail.dart index d5a69ae3d0e..c7061a33f8a 100644 --- a/dev/a11y_assessments/lib/use_cases/navigation_rail.dart +++ b/dev/a11y_assessments/lib/use_cases/navigation_rail.dart @@ -3,7 +3,7 @@ // found in the LICENSE file. import 'package:flutter/material.dart'; - +import '../utils.dart'; import 'use_cases.dart'; class NavigationRailUseCase extends UseCase { @@ -31,6 +31,8 @@ class _NavRailExampleState extends State { bool showTrailing = false; double groupAlignment = -1.0; + String pageTitle = getUseCaseName(NavigationRailUseCase()); + @override Widget build(BuildContext context) { return Scaffold( diff --git a/dev/a11y_assessments/lib/use_cases/radio_list_tile.dart b/dev/a11y_assessments/lib/use_cases/radio_list_tile.dart index 74f3a239834..d314271d591 100644 --- a/dev/a11y_assessments/lib/use_cases/radio_list_tile.dart +++ b/dev/a11y_assessments/lib/use_cases/radio_list_tile.dart @@ -3,7 +3,7 @@ // found in the LICENSE file. import 'package:flutter/material.dart'; - +import '../utils.dart'; import 'use_cases.dart'; class RadioListTileUseCase extends UseCase { @@ -33,11 +33,13 @@ class _MainWidgetState extends State<_MainWidget> { }); } + String pageTitle = getUseCaseName(RadioListTileUseCase()); + @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( - title: Semantics(headingLevel: 1, child: const Text('Radio button demo')) + title: Semantics(headingLevel: 1, child: Text('$pageTitle Demo')) ), body: ListView( children: [ diff --git a/dev/a11y_assessments/lib/use_cases/slider.dart b/dev/a11y_assessments/lib/use_cases/slider.dart index 06ff2e0edf2..2bc1cc12d39 100644 --- a/dev/a11y_assessments/lib/use_cases/slider.dart +++ b/dev/a11y_assessments/lib/use_cases/slider.dart @@ -3,7 +3,7 @@ // found in the LICENSE file. import 'package:flutter/material.dart'; - +import '../utils.dart'; import 'use_cases.dart'; class SliderUseCase extends UseCase { @@ -28,12 +28,14 @@ class MainWidgetState extends State { double currentSliderValue = 20; static const String accessibilityLabel = 'Accessibility Test Slider'; + String pageTitle = getUseCaseName(SliderUseCase()); + @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( backgroundColor: Theme.of(context).colorScheme.inversePrimary, - title: Semantics(headingLevel: 1, child: const Text('Slider demo')), + title: Semantics(headingLevel: 1, child: Text('$pageTitle demo')), ), body: Center( child: Semantics( diff --git a/dev/a11y_assessments/lib/use_cases/snack_bar.dart b/dev/a11y_assessments/lib/use_cases/snack_bar.dart index 706598b1898..b4f6176676e 100644 --- a/dev/a11y_assessments/lib/use_cases/snack_bar.dart +++ b/dev/a11y_assessments/lib/use_cases/snack_bar.dart @@ -3,7 +3,7 @@ // found in the LICENSE file. import 'package:flutter/material.dart'; - +import '../utils.dart'; import 'use_cases.dart'; class SnackBarUseCase extends UseCase { @@ -25,12 +25,15 @@ class MainWidget extends StatefulWidget { } class MainWidgetState extends State { + + String pageTitle = getUseCaseName(SnackBarUseCase()); + @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( backgroundColor: Theme.of(context).colorScheme.inversePrimary, - title: Semantics(headingLevel: 1, child: const Text('SnackBar')), + title: Semantics(headingLevel: 1, child: Text('$pageTitle Demo')), ), body: Center( child: Column( diff --git a/dev/a11y_assessments/lib/use_cases/switch_list_tile.dart b/dev/a11y_assessments/lib/use_cases/switch_list_tile.dart index 43dd5468f54..a2353f1c7bb 100644 --- a/dev/a11y_assessments/lib/use_cases/switch_list_tile.dart +++ b/dev/a11y_assessments/lib/use_cases/switch_list_tile.dart @@ -3,7 +3,7 @@ // found in the LICENSE file. import 'package:flutter/material.dart'; - +import '../utils.dart'; import 'use_cases.dart'; class SwitchListTileUseCase extends UseCase { @@ -27,12 +27,15 @@ class SwitchListTileExample extends StatefulWidget { class _SwitchListTileExampleState extends State { bool _lights1 = false; bool _lights2 = false; + + String pageTitle = getUseCaseName(SwitchListTileUseCase()); + @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( backgroundColor: Theme.of(context).colorScheme.inversePrimary, - title: Semantics(headingLevel: 1, child: const Text('SwitchListTile')), + title: Semantics(headingLevel: 1, child: Text('$pageTitle Demo')), ), body: Center( child: Column( diff --git a/dev/a11y_assessments/lib/use_cases/text_button.dart b/dev/a11y_assessments/lib/use_cases/text_button.dart index 6e763fa7f06..e39552af719 100644 --- a/dev/a11y_assessments/lib/use_cases/text_button.dart +++ b/dev/a11y_assessments/lib/use_cases/text_button.dart @@ -3,7 +3,7 @@ // found in the LICENSE file. import 'package:flutter/material.dart'; - +import '../utils.dart'; import 'use_cases.dart'; class TextButtonUseCase extends UseCase { @@ -27,12 +27,14 @@ class MainWidget extends StatefulWidget { class MainWidgetState extends State { int _count = 0; + String pageTitle = getUseCaseName(TextButtonUseCase()); + @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( backgroundColor: Theme.of(context).colorScheme.inversePrimary, - title: Semantics(headingLevel: 1, child: const Text('TextButton Demo')), + title: Semantics(headingLevel: 1, child: Text('$pageTitle Demo')), ), body: Center( child: Column( @@ -45,9 +47,7 @@ class MainWidgetState extends State { const Text('This is a TextButton:'), TextButton( onPressed: () { - setState(() { - _count++; - }); + setState(() { _count++; }); }, child: const Text('Action'), ), diff --git a/dev/a11y_assessments/lib/use_cases/text_field.dart b/dev/a11y_assessments/lib/use_cases/text_field.dart index 8669d520d2d..e6705933117 100644 --- a/dev/a11y_assessments/lib/use_cases/text_field.dart +++ b/dev/a11y_assessments/lib/use_cases/text_field.dart @@ -3,7 +3,7 @@ // found in the LICENSE file. import 'package:flutter/material.dart'; - +import '../utils.dart'; import 'use_cases.dart'; class TextFieldUseCase extends UseCase { @@ -14,18 +14,20 @@ class TextFieldUseCase extends UseCase { String get route => '/text-field'; @override - Widget build(BuildContext context) => const _MainWidget(); + Widget build(BuildContext context) => _MainWidget(); } class _MainWidget extends StatelessWidget { - const _MainWidget(); + _MainWidget(); + + final String pageTitle = getUseCaseName(TextFieldUseCase()); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( backgroundColor: Theme.of(context).colorScheme.inversePrimary, - title: Semantics(headingLevel: 1, child: const Text('TextField demo')), + title: Semantics(headingLevel: 1, child: Text('$pageTitle Demo')), ), body: ListView( children: [ diff --git a/dev/a11y_assessments/lib/use_cases/text_field_password.dart b/dev/a11y_assessments/lib/use_cases/text_field_password.dart index d44028cd18c..ae4d2fb811b 100644 --- a/dev/a11y_assessments/lib/use_cases/text_field_password.dart +++ b/dev/a11y_assessments/lib/use_cases/text_field_password.dart @@ -3,7 +3,7 @@ // found in the LICENSE file. import 'package:flutter/material.dart'; - +import '../utils.dart'; import 'use_cases.dart'; class TextFieldPasswordUseCase extends UseCase { @@ -14,18 +14,20 @@ class TextFieldPasswordUseCase extends UseCase { String get route => '/text-field-password'; @override - Widget build(BuildContext context) => const _MainWidget(); + Widget build(BuildContext context) => _MainWidget(); } class _MainWidget extends StatelessWidget { - const _MainWidget(); + _MainWidget(); + + final String pageTitle = getUseCaseName(TextFieldPasswordUseCase()); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( backgroundColor: Theme.of(context).colorScheme.inversePrimary, - title: Semantics(headingLevel: 1, child: const Text('TextField password demo')), + title: Semantics(headingLevel: 1, child: Text('$pageTitle Demo')), ), body: ListView( children: const [ diff --git a/dev/a11y_assessments/lib/use_cases/use_cases.dart b/dev/a11y_assessments/lib/use_cases/use_cases.dart index 2f638881820..28436d6d71a 100644 --- a/dev/a11y_assessments/lib/use_cases/use_cases.dart +++ b/dev/a11y_assessments/lib/use_cases/use_cases.dart @@ -4,6 +4,7 @@ import 'package:flutter/widgets.dart'; +import '../common/dynamic_title.dart'; import 'action_chip.dart'; import 'auto_complete.dart'; import 'badge.dart'; @@ -28,6 +29,14 @@ import 'text_field_password.dart'; abstract class UseCase { String get name; String get route; + + Widget buildWithTitle(BuildContext context) { + return DynamicTitle( + title: name, + child: build(context), + ); + } + Widget build(BuildContext context); } diff --git a/dev/a11y_assessments/lib/utils.dart b/dev/a11y_assessments/lib/utils.dart new file mode 100644 index 00000000000..a65c24c3626 --- /dev/null +++ b/dev/a11y_assessments/lib/utils.dart @@ -0,0 +1,7 @@ +// Copyright 2014 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import './use_cases/use_cases.dart'; + +String getUseCaseName(UseCase useCase) => useCase.name; diff --git a/dev/a11y_assessments/test/action_chip_test.dart b/dev/a11y_assessments/test/action_chip_test.dart index 0a3a349df92..b98f6e82065 100644 --- a/dev/a11y_assessments/test/action_chip_test.dart +++ b/dev/a11y_assessments/test/action_chip_test.dart @@ -13,4 +13,11 @@ void main() { await pumpsUseCase(tester, ActionChipUseCase()); expect(find.byType(ActionChip), findsExactly(2)); }); + + testWidgets('action chip has one h1 tag', (WidgetTester tester) async { + await pumpsUseCase(tester, ActionChipUseCase()); + final Finder findHeadingLevelOnes = find.bySemanticsLabel(RegExp('ActionChip Demo')); + await tester.pumpAndSettle(); + expect(findHeadingLevelOnes, findsOne); + }); } diff --git a/dev/a11y_assessments/test/card_test.dart b/dev/a11y_assessments/test/card_test.dart index c8237b0223a..285c0fdbf10 100644 --- a/dev/a11y_assessments/test/card_test.dart +++ b/dev/a11y_assessments/test/card_test.dart @@ -13,4 +13,11 @@ void main() { await pumpsUseCase(tester, CardUseCase()); expect(find.byType(Card), findsExactly(1)); }); + + testWidgets('card has one h1 tag', (WidgetTester tester) async { + await pumpsUseCase(tester, CardUseCase()); + final Finder findHeadingLevelOnes = find.bySemanticsLabel(RegExp('Card Demo')); + await tester.pumpAndSettle(); + expect(findHeadingLevelOnes, findsOne); + }); } diff --git a/dev/a11y_assessments/test/drawer_test.dart b/dev/a11y_assessments/test/drawer_test.dart index 9f5d294ddf5..8023cb7f130 100644 --- a/dev/a11y_assessments/test/drawer_test.dart +++ b/dev/a11y_assessments/test/drawer_test.dart @@ -23,7 +23,7 @@ void main() { testWidgets('drawer has one h1 tag', (WidgetTester tester) async { await pumpsUseCase(tester, DrawerUseCase()); - final Finder findHeadingLevelOnes = find.bySemanticsLabel('Drawer Demo'); + final Finder findHeadingLevelOnes = find.bySemanticsLabel('drawer Demo'); await tester.pumpAndSettle(); expect(findHeadingLevelOnes, findsOne); }); diff --git a/dev/a11y_assessments/test/expansion_tile_test.dart b/dev/a11y_assessments/test/expansion_tile_test.dart index 5882488a5e4..98202198cb7 100644 --- a/dev/a11y_assessments/test/expansion_tile_test.dart +++ b/dev/a11y_assessments/test/expansion_tile_test.dart @@ -9,8 +9,15 @@ import 'package:flutter_test/flutter_test.dart'; import 'test_utils.dart'; void main() { - testWidgets('action chip can run', (WidgetTester tester) async { + testWidgets('expansion tile can run', (WidgetTester tester) async { await pumpsUseCase(tester, ExpansionTileUseCase()); expect(find.byType(ExpansionTile), findsExactly(3)); }); + + testWidgets('exapansion tile has one h1 tag', (WidgetTester tester) async { + await pumpsUseCase(tester, ExpansionTileUseCase()); + final Finder findHeadingLevelOnes = find.bySemanticsLabel('ExpansionTile Demo'); + await tester.pumpAndSettle(); + expect(findHeadingLevelOnes, findsOne); + }); } diff --git a/dev/a11y_assessments/test/home_page_test.dart b/dev/a11y_assessments/test/home_page_test.dart index 06e5aa294c0..46278128ba1 100644 --- a/dev/a11y_assessments/test/home_page_test.dart +++ b/dev/a11y_assessments/test/home_page_test.dart @@ -2,11 +2,36 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +// ignore_for_file: avoid_dynamic_calls + import 'package:a11y_assessments/main.dart'; +import 'package:a11y_assessments/use_cases/action_chip.dart'; +import 'package:a11y_assessments/use_cases/auto_complete.dart'; +import 'package:a11y_assessments/use_cases/badge.dart'; +import 'package:a11y_assessments/use_cases/card.dart'; +import 'package:a11y_assessments/use_cases/check_box_list_tile.dart'; +import 'package:a11y_assessments/use_cases/date_picker.dart'; +import 'package:a11y_assessments/use_cases/dialog.dart'; +import 'package:a11y_assessments/use_cases/drawer.dart'; +import 'package:a11y_assessments/use_cases/expansion_tile.dart'; +import 'package:a11y_assessments/use_cases/material_banner.dart'; +import 'package:a11y_assessments/use_cases/navigation_bar.dart'; +import 'package:a11y_assessments/use_cases/navigation_drawer.dart'; +import 'package:a11y_assessments/use_cases/navigation_rail.dart'; +import 'package:a11y_assessments/use_cases/radio_list_tile.dart'; +import 'package:a11y_assessments/use_cases/slider.dart'; +import 'package:a11y_assessments/use_cases/snack_bar.dart'; +import 'package:a11y_assessments/use_cases/switch_list_tile.dart'; +import 'package:a11y_assessments/use_cases/text_button.dart'; +import 'package:a11y_assessments/use_cases/text_field.dart'; +import 'package:a11y_assessments/use_cases/text_field_password.dart'; import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:material_color_utilities/material_color_utilities.dart'; +import 'test_utils.dart'; + void main() { testWidgets('Has light and dark theme', (WidgetTester tester) async { await tester.pumpWidget(const App()); @@ -141,6 +166,149 @@ void main() { MaterialDynamicColors.inversePrimary.getArgb(highContrastScheme)); }); + testWidgets('Each A11y Assessments page has a unique page title.', (WidgetTester tester) async { + final List log = []; + + tester.binding.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.platform, (MethodCall methodCall) async { + if (methodCall.method == 'SystemChrome.setApplicationSwitcherDescription') { + log.add(methodCall); + } + return null; + }); + + await tester.pumpWidget(Title( + color: const Color(0xFF00FF00), + title: 'Accessibility Assessments', + child: Container(), + )); + expect(log[0], isMethodCall( + 'SystemChrome.setApplicationSwitcherDescription', + arguments: {'label': 'Accessibility Assessments', 'primaryColor': 4278255360}, + )); + + await pumpsUseCase(tester, AutoCompleteUseCase()); + expect(log[2], isMethodCall( + 'SystemChrome.setApplicationSwitcherDescription', + arguments: {'label': 'AutoComplete', 'primaryColor': 4284960932}, + )); + + await pumpsUseCase(tester, ActionChipUseCase()); + expect(log[4], isMethodCall( + 'SystemChrome.setApplicationSwitcherDescription', + arguments: {'label': 'ActionChip', 'primaryColor': 4284960932}, + )); + + await pumpsUseCase(tester, BadgeUseCase()); + expect(log[6], isMethodCall( + 'SystemChrome.setApplicationSwitcherDescription', + arguments: {'label': 'Badge', 'primaryColor': 4284960932}, + )); + + await pumpsUseCase(tester, CardUseCase()); + expect(log[8], isMethodCall( + 'SystemChrome.setApplicationSwitcherDescription', + arguments: {'label': 'Card', 'primaryColor': 4284960932}, + )); + + await pumpsUseCase(tester, CheckBoxListTile()); + expect(log[10], isMethodCall( + 'SystemChrome.setApplicationSwitcherDescription', + arguments: {'label': 'CheckBoxListTile', 'primaryColor': 4284960932}, + )); + + await pumpsUseCase(tester, DatePickerUseCase()); + expect(log[12], isMethodCall( + 'SystemChrome.setApplicationSwitcherDescription', + arguments: {'label': 'DatePicker', 'primaryColor': 4284960932}, + )); + + await pumpsUseCase(tester, DialogUseCase()); + expect(log[14], isMethodCall( + 'SystemChrome.setApplicationSwitcherDescription', + arguments: {'label': 'Dialog', 'primaryColor': 4284960932}, + )); + + await pumpsUseCase(tester, ExpansionTileUseCase()); + expect(log[16], isMethodCall( + 'SystemChrome.setApplicationSwitcherDescription', + arguments: {'label': 'ExpansionTile', 'primaryColor': 4284960932}, + )); + + await pumpsUseCase(tester, MaterialBannerUseCase()); + expect(log[18], isMethodCall( + 'SystemChrome.setApplicationSwitcherDescription', + arguments: {'label': 'MaterialBanner', 'primaryColor': 4284960932}, + )); + + await pumpsUseCase(tester, NavigationBarUseCase()); + expect(log[20], isMethodCall( + 'SystemChrome.setApplicationSwitcherDescription', + arguments: {'label': 'NavigationBar', 'primaryColor': 4284960932}, + )); + + await pumpsUseCase(tester, RadioListTileUseCase()); + expect(log[22], isMethodCall( + 'SystemChrome.setApplicationSwitcherDescription', + arguments: {'label': 'RadioListTile', 'primaryColor': 4284960932}, + )); + + await pumpsUseCase(tester, SliderUseCase()); + expect(log[24], isMethodCall( + 'SystemChrome.setApplicationSwitcherDescription', + arguments: {'label': 'Slider', 'primaryColor': 4284960932}, + )); + + await pumpsUseCase(tester, SnackBarUseCase()); + expect(log[26], isMethodCall( + 'SystemChrome.setApplicationSwitcherDescription', + arguments: {'label': 'SnackBar', 'primaryColor': 4284960932}, + )); + + await pumpsUseCase(tester, SwitchListTileUseCase()); + expect(log[28], isMethodCall( + 'SystemChrome.setApplicationSwitcherDescription', + arguments: {'label': 'SwitchListTile', 'primaryColor': 4284960932}, + )); + + await pumpsUseCase(tester, TextButtonUseCase()); + expect(log[30], isMethodCall( + 'SystemChrome.setApplicationSwitcherDescription', + arguments: {'label': 'TextButton', 'primaryColor': 4284960932}, + )); + + await pumpsUseCase(tester, TextFieldUseCase()); + expect(log[32], isMethodCall( + 'SystemChrome.setApplicationSwitcherDescription', + arguments: {'label': 'TextField', 'primaryColor': 4284960932}, + )); + + await pumpsUseCase(tester, TextFieldPasswordUseCase()); + expect(log[34], isMethodCall( + 'SystemChrome.setApplicationSwitcherDescription', + arguments: {'label': 'TextField password', 'primaryColor': 4284960932}, + )); + + await pumpsUseCase(tester, NavigationDrawerUseCase()); + expect(log[36], isMethodCall( + 'SystemChrome.setApplicationSwitcherDescription', + arguments: {'label': 'NavigationDrawer', 'primaryColor': 4284960932}, + )); + + await pumpsUseCase(tester, NavigationRailUseCase()); + expect(log[38], isMethodCall( + 'SystemChrome.setApplicationSwitcherDescription', + arguments: {'label': 'NavigationRail', 'primaryColor': 4284960932}, + )); + + await pumpsUseCase(tester, DrawerUseCase()); + expect(log[40], isMethodCall( + 'SystemChrome.setApplicationSwitcherDescription', + arguments: {'label': 'drawer', 'primaryColor': 4284960932}, + )); + + + }); + testWidgets('a11y assessments home page has one h1 tag', (WidgetTester tester) async { await tester.pumpWidget(const App()); final Finder findHeadingLevelOnes = find.bySemanticsLabel('Accessibility Assessments'); diff --git a/dev/a11y_assessments/test/navigation_drawer_test.dart b/dev/a11y_assessments/test/navigation_drawer_test.dart index 5da2780d83b..c7b31315372 100644 --- a/dev/a11y_assessments/test/navigation_drawer_test.dart +++ b/dev/a11y_assessments/test/navigation_drawer_test.dart @@ -23,7 +23,7 @@ void main() { testWidgets('navigation drawer has one h1 tag', (WidgetTester tester) async { await pumpsUseCase(tester, NavigationDrawerUseCase()); - final Finder findHeadingLevelOnes = find.bySemanticsLabel('Navigation Drawer Demo'); + final Finder findHeadingLevelOnes = find.bySemanticsLabel('NavigationDrawer Demo'); await tester.pumpAndSettle(); expect(findHeadingLevelOnes, findsOne); }); diff --git a/dev/a11y_assessments/test/radio_list_tile_test.dart b/dev/a11y_assessments/test/radio_list_tile_test.dart index 98f17a164ed..1ce2219eff4 100644 --- a/dev/a11y_assessments/test/radio_list_tile_test.dart +++ b/dev/a11y_assessments/test/radio_list_tile_test.dart @@ -15,9 +15,9 @@ void main() { expect(find.text('Jefferson'), findsOneWidget); }); - testWidgets('radio button demo page has one h1 tag', (WidgetTester tester) async { + testWidgets('radio list tile demo page has one h1 tag', (WidgetTester tester) async { await pumpsUseCase(tester, RadioListTileUseCase()); - final Finder findHeadingLevelOnes = find.bySemanticsLabel('Radio button demo'); + final Finder findHeadingLevelOnes = find.bySemanticsLabel('RadioListTile Demo'); await tester.pumpAndSettle(); expect(findHeadingLevelOnes, findsOne); }); diff --git a/dev/a11y_assessments/test/snack_bar_test.dart b/dev/a11y_assessments/test/snack_bar_test.dart index 1cce3e8260e..d141a544d16 100644 --- a/dev/a11y_assessments/test/snack_bar_test.dart +++ b/dev/a11y_assessments/test/snack_bar_test.dart @@ -17,4 +17,11 @@ void main() { await tester.pump(); expect(find.text(snackBarText), findsOneWidget); }); + + testWidgets('snack bar demo page has one h1 tag', (WidgetTester tester) async { + await pumpsUseCase(tester, SnackBarUseCase()); + final Finder findHeadingLevelOnes = find.bySemanticsLabel('SnackBar Demo'); + await tester.pumpAndSettle(); + expect(findHeadingLevelOnes, findsOne); + }); } diff --git a/dev/a11y_assessments/test/switch_list_tile_test.dart b/dev/a11y_assessments/test/switch_list_tile_test.dart index c272ec97ff8..8740b62dace 100644 --- a/dev/a11y_assessments/test/switch_list_tile_test.dart +++ b/dev/a11y_assessments/test/switch_list_tile_test.dart @@ -9,8 +9,15 @@ import 'package:flutter_test/flutter_test.dart'; import 'test_utils.dart'; void main() { - testWidgets('action chip can run', (WidgetTester tester) async { + testWidgets('switch list can run', (WidgetTester tester) async { await pumpsUseCase(tester, SwitchListTileUseCase()); expect(find.byType(SwitchListTile), findsExactly(2)); }); + + testWidgets('switch list demo page has one h1 tag', (WidgetTester tester) async { + await pumpsUseCase(tester, SwitchListTileUseCase()); + final Finder findHeadingLevelOnes = find.bySemanticsLabel('SwitchListTile Demo'); + await tester.pumpAndSettle(); + expect(findHeadingLevelOnes, findsOne); + }); } diff --git a/dev/a11y_assessments/test/test_utils.dart b/dev/a11y_assessments/test/test_utils.dart index 8b2ae281dbe..1cb03267ba7 100644 --- a/dev/a11y_assessments/test/test_utils.dart +++ b/dev/a11y_assessments/test/test_utils.dart @@ -10,7 +10,7 @@ Future pumpsUseCase(WidgetTester tester, UseCase useCase) async { await tester.pumpWidget(MaterialApp( home: Builder( builder: (BuildContext context) { - return useCase.build(context); + return useCase.buildWithTitle(context); }, ), )); diff --git a/dev/a11y_assessments/test/text_field_password_test.dart b/dev/a11y_assessments/test/text_field_password_test.dart index 1fc7e8ba5dc..b67ef08aa50 100644 --- a/dev/a11y_assessments/test/text_field_password_test.dart +++ b/dev/a11y_assessments/test/text_field_password_test.dart @@ -53,7 +53,7 @@ void main() { 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'); + final Finder findHeadingLevelOnes = find.bySemanticsLabel('TextField password Demo'); await tester.pumpAndSettle(); expect(findHeadingLevelOnes, findsOne); }); diff --git a/dev/a11y_assessments/test/text_field_test.dart b/dev/a11y_assessments/test/text_field_test.dart index c5bfe09ad1d..25a150aafd3 100644 --- a/dev/a11y_assessments/test/text_field_test.dart +++ b/dev/a11y_assessments/test/text_field_test.dart @@ -67,7 +67,7 @@ void main() { testWidgets('text field demo page has one h1 tag', (WidgetTester tester) async { await pumpsUseCase(tester, TextFieldUseCase()); - final Finder findHeadingLevelOnes = find.bySemanticsLabel('TextField demo'); + final Finder findHeadingLevelOnes = find.bySemanticsLabel('TextField Demo'); await tester.pumpAndSettle(); expect(findHeadingLevelOnes, findsOne); });