mirror of
https://github.com/flutter/flutter
synced 2024-10-13 11:42:54 +00:00
Add material tap target size and text contrast test to gallery (#21581)
This commit is contained in:
parent
387948a239
commit
fa0a857d02
471
examples/flutter_gallery/test/accessibility_test.dart
Normal file
471
examples/flutter_gallery/test/accessibility_test.dart
Normal file
|
@ -0,0 +1,471 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
|
import 'package:flutter_gallery/demo/all.dart';
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
group('All material demos meet recommended tap target sizes', () {
|
||||||
|
testWidgets('backdrop_demo', (WidgetTester tester) async {
|
||||||
|
final SemanticsHandle handle = tester.ensureSemantics();
|
||||||
|
await tester.pumpWidget(new MaterialApp(home: new BackdropDemo()));
|
||||||
|
expect(tester, meetsGuideline(androidTapTargetGuideline));
|
||||||
|
handle.dispose();
|
||||||
|
});
|
||||||
|
|
||||||
|
testWidgets('bottom_app_bar_demo', (WidgetTester tester) async {
|
||||||
|
final SemanticsHandle handle = tester.ensureSemantics();
|
||||||
|
await tester.pumpWidget(new MaterialApp(home: new BottomAppBarDemo()));
|
||||||
|
expect(tester, meetsGuideline(androidTapTargetGuideline));
|
||||||
|
handle.dispose();
|
||||||
|
});
|
||||||
|
|
||||||
|
testWidgets('bottom_navigation_demo', (WidgetTester tester) async {
|
||||||
|
final SemanticsHandle handle = tester.ensureSemantics();
|
||||||
|
await tester.pumpWidget(new MaterialApp(home: new BottomNavigationDemo()));
|
||||||
|
expect(tester, meetsGuideline(androidTapTargetGuideline));
|
||||||
|
handle.dispose();
|
||||||
|
});
|
||||||
|
|
||||||
|
testWidgets('buttons_demo', (WidgetTester tester) async {
|
||||||
|
final SemanticsHandle handle = tester.ensureSemantics();
|
||||||
|
await tester.pumpWidget(new MaterialApp(home: new ButtonsDemo()));
|
||||||
|
expect(tester, meetsGuideline(androidTapTargetGuideline));
|
||||||
|
handle.dispose();
|
||||||
|
});
|
||||||
|
|
||||||
|
testWidgets('cards_demo', (WidgetTester tester) async {
|
||||||
|
final SemanticsHandle handle = tester.ensureSemantics();
|
||||||
|
await tester.pumpWidget(new MaterialApp(home: new CardsDemo()));
|
||||||
|
expect(tester, meetsGuideline(androidTapTargetGuideline));
|
||||||
|
handle.dispose();
|
||||||
|
});
|
||||||
|
|
||||||
|
testWidgets('chip_demo', (WidgetTester tester) async {
|
||||||
|
final SemanticsHandle handle = tester.ensureSemantics();
|
||||||
|
await tester.pumpWidget(new MaterialApp(home: new ChipDemo()));
|
||||||
|
expect(tester, meetsGuideline(androidTapTargetGuideline));
|
||||||
|
handle.dispose();
|
||||||
|
});
|
||||||
|
|
||||||
|
testWidgets('data_table_demo', (WidgetTester tester) async {
|
||||||
|
final SemanticsHandle handle = tester.ensureSemantics();
|
||||||
|
await tester.pumpWidget(new MaterialApp(home: new DataTableDemo()));
|
||||||
|
expect(tester, meetsGuideline(androidTapTargetGuideline));
|
||||||
|
handle.dispose();
|
||||||
|
});
|
||||||
|
|
||||||
|
testWidgets('date_and_time_picker_demo', (WidgetTester tester) async {
|
||||||
|
final SemanticsHandle handle = tester.ensureSemantics();
|
||||||
|
await tester.pumpWidget(new MaterialApp(home: new DateAndTimePickerDemo()));
|
||||||
|
expect(tester, meetsGuideline(androidTapTargetGuideline));
|
||||||
|
handle.dispose();
|
||||||
|
}, skip: true); // https://github.com/flutter/flutter/issues/21578
|
||||||
|
|
||||||
|
testWidgets('dialog_demo', (WidgetTester tester) async {
|
||||||
|
final SemanticsHandle handle = tester.ensureSemantics();
|
||||||
|
await tester.pumpWidget(new MaterialApp(home: new DialogDemo()));
|
||||||
|
expect(tester, meetsGuideline(androidTapTargetGuideline));
|
||||||
|
handle.dispose();
|
||||||
|
});
|
||||||
|
|
||||||
|
testWidgets('drawer_demo', (WidgetTester tester) async {
|
||||||
|
final SemanticsHandle handle = tester.ensureSemantics();
|
||||||
|
await tester.pumpWidget(new MaterialApp(home: new DrawerDemo()));
|
||||||
|
expect(tester, meetsGuideline(androidTapTargetGuideline));
|
||||||
|
handle.dispose();
|
||||||
|
});
|
||||||
|
|
||||||
|
testWidgets('elevation_demo', (WidgetTester tester) async {
|
||||||
|
final SemanticsHandle handle = tester.ensureSemantics();
|
||||||
|
await tester.pumpWidget(new MaterialApp(home: new ElevationDemo()));
|
||||||
|
expect(tester, meetsGuideline(androidTapTargetGuideline));
|
||||||
|
handle.dispose();
|
||||||
|
});
|
||||||
|
|
||||||
|
testWidgets('expansion_panels_demo', (WidgetTester tester) async {
|
||||||
|
final SemanticsHandle handle = tester.ensureSemantics();
|
||||||
|
await tester.pumpWidget(new MaterialApp(home: new ExpansionPanelsDemo()));
|
||||||
|
expect(tester, meetsGuideline(androidTapTargetGuideline));
|
||||||
|
handle.dispose();
|
||||||
|
});
|
||||||
|
|
||||||
|
testWidgets('grid_list_demo', (WidgetTester tester) async {
|
||||||
|
final SemanticsHandle handle = tester.ensureSemantics();
|
||||||
|
await tester.pumpWidget(new MaterialApp(home: const GridListDemo()));
|
||||||
|
expect(tester, meetsGuideline(androidTapTargetGuideline));
|
||||||
|
handle.dispose();
|
||||||
|
});
|
||||||
|
|
||||||
|
testWidgets('icons_demo', (WidgetTester tester) async {
|
||||||
|
final SemanticsHandle handle = tester.ensureSemantics();
|
||||||
|
await tester.pumpWidget(new MaterialApp(home: new IconsDemo()));
|
||||||
|
expect(tester, meetsGuideline(androidTapTargetGuideline));
|
||||||
|
handle.dispose();
|
||||||
|
});
|
||||||
|
|
||||||
|
testWidgets('leave_behind_demo', (WidgetTester tester) async {
|
||||||
|
final SemanticsHandle handle = tester.ensureSemantics();
|
||||||
|
await tester.pumpWidget(new MaterialApp(home: const LeaveBehindDemo()));
|
||||||
|
expect(tester, meetsGuideline(androidTapTargetGuideline));
|
||||||
|
handle.dispose();
|
||||||
|
});
|
||||||
|
|
||||||
|
testWidgets('list_demo', (WidgetTester tester) async {
|
||||||
|
final SemanticsHandle handle = tester.ensureSemantics();
|
||||||
|
await tester.pumpWidget(new MaterialApp(home: const ListDemo()));
|
||||||
|
expect(tester, meetsGuideline(androidTapTargetGuideline));
|
||||||
|
handle.dispose();
|
||||||
|
});
|
||||||
|
|
||||||
|
testWidgets('menu_demo', (WidgetTester tester) async {
|
||||||
|
final SemanticsHandle handle = tester.ensureSemantics();
|
||||||
|
await tester.pumpWidget(new MaterialApp(home: const MenuDemo()));
|
||||||
|
expect(tester, meetsGuideline(androidTapTargetGuideline));
|
||||||
|
handle.dispose();
|
||||||
|
});
|
||||||
|
|
||||||
|
testWidgets('modal_bottom_sheet_demo', (WidgetTester tester) async {
|
||||||
|
final SemanticsHandle handle = tester.ensureSemantics();
|
||||||
|
await tester.pumpWidget(new MaterialApp(home: new ModalBottomSheetDemo()));
|
||||||
|
expect(tester, meetsGuideline(androidTapTargetGuideline));
|
||||||
|
handle.dispose();
|
||||||
|
});
|
||||||
|
|
||||||
|
testWidgets('overscroll_demo', (WidgetTester tester) async {
|
||||||
|
final SemanticsHandle handle = tester.ensureSemantics();
|
||||||
|
await tester.pumpWidget(new MaterialApp(home: const OverscrollDemo()));
|
||||||
|
expect(tester, meetsGuideline(androidTapTargetGuideline));
|
||||||
|
handle.dispose();
|
||||||
|
});
|
||||||
|
|
||||||
|
testWidgets('page_selector_demo', (WidgetTester tester) async {
|
||||||
|
final SemanticsHandle handle = tester.ensureSemantics();
|
||||||
|
await tester.pumpWidget(new MaterialApp(home: new PageSelectorDemo()));
|
||||||
|
expect(tester, meetsGuideline(androidTapTargetGuideline));
|
||||||
|
handle.dispose();
|
||||||
|
});
|
||||||
|
|
||||||
|
testWidgets('persistent_bottom_sheet_demo', (WidgetTester tester) async {
|
||||||
|
final SemanticsHandle handle = tester.ensureSemantics();
|
||||||
|
await tester.pumpWidget(new MaterialApp(home: new PersistentBottomSheetDemo()));
|
||||||
|
expect(tester, meetsGuideline(androidTapTargetGuideline));
|
||||||
|
handle.dispose();
|
||||||
|
});
|
||||||
|
|
||||||
|
testWidgets('progress_indicator_demo', (WidgetTester tester) async {
|
||||||
|
final SemanticsHandle handle = tester.ensureSemantics();
|
||||||
|
await tester.pumpWidget(new MaterialApp(home: new ProgressIndicatorDemo()));
|
||||||
|
expect(tester, meetsGuideline(androidTapTargetGuideline));
|
||||||
|
handle.dispose();
|
||||||
|
});
|
||||||
|
|
||||||
|
testWidgets('reorderable_list_demo', (WidgetTester tester) async {
|
||||||
|
final SemanticsHandle handle = tester.ensureSemantics();
|
||||||
|
await tester.pumpWidget(new MaterialApp(home: const ReorderableListDemo()));
|
||||||
|
expect(tester, meetsGuideline(androidTapTargetGuideline));
|
||||||
|
handle.dispose();
|
||||||
|
});
|
||||||
|
|
||||||
|
testWidgets('scrollable_tabs_demo', (WidgetTester tester) async {
|
||||||
|
final SemanticsHandle handle = tester.ensureSemantics();
|
||||||
|
await tester.pumpWidget(new MaterialApp(home: new ScrollableTabsDemo()));
|
||||||
|
expect(tester, meetsGuideline(androidTapTargetGuideline));
|
||||||
|
handle.dispose();
|
||||||
|
});
|
||||||
|
|
||||||
|
testWidgets('search_demo', (WidgetTester tester) async {
|
||||||
|
final SemanticsHandle handle = tester.ensureSemantics();
|
||||||
|
await tester.pumpWidget(new MaterialApp(home: new SearchDemo()));
|
||||||
|
expect(tester, meetsGuideline(androidTapTargetGuideline));
|
||||||
|
handle.dispose();
|
||||||
|
});
|
||||||
|
|
||||||
|
testWidgets('selection_controls_demo', (WidgetTester tester) async {
|
||||||
|
final SemanticsHandle handle = tester.ensureSemantics();
|
||||||
|
await tester.pumpWidget(new MaterialApp(home: new SelectionControlsDemo()));
|
||||||
|
expect(tester, meetsGuideline(androidTapTargetGuideline));
|
||||||
|
handle.dispose();
|
||||||
|
});
|
||||||
|
|
||||||
|
testWidgets('slider_demo', (WidgetTester tester) async {
|
||||||
|
final SemanticsHandle handle = tester.ensureSemantics();
|
||||||
|
await tester.pumpWidget(new MaterialApp(home: new SliderDemo()));
|
||||||
|
expect(tester, meetsGuideline(androidTapTargetGuideline));
|
||||||
|
handle.dispose();
|
||||||
|
});
|
||||||
|
|
||||||
|
testWidgets('snack_bar_demo', (WidgetTester tester) async {
|
||||||
|
final SemanticsHandle handle = tester.ensureSemantics();
|
||||||
|
await tester.pumpWidget(new MaterialApp(home: const SnackBarDemo()));
|
||||||
|
expect(tester, meetsGuideline(androidTapTargetGuideline));
|
||||||
|
handle.dispose();
|
||||||
|
});
|
||||||
|
|
||||||
|
testWidgets('tabs_demo', (WidgetTester tester) async {
|
||||||
|
final SemanticsHandle handle = tester.ensureSemantics();
|
||||||
|
await tester.pumpWidget(new MaterialApp(home: new TabsDemo()));
|
||||||
|
expect(tester, meetsGuideline(androidTapTargetGuideline));
|
||||||
|
handle.dispose();
|
||||||
|
});
|
||||||
|
|
||||||
|
testWidgets('tabs_fab_demo', (WidgetTester tester) async {
|
||||||
|
final SemanticsHandle handle = tester.ensureSemantics();
|
||||||
|
await tester.pumpWidget(new MaterialApp(home: new TabsFabDemo()));
|
||||||
|
expect(tester, meetsGuideline(androidTapTargetGuideline));
|
||||||
|
handle.dispose();
|
||||||
|
});
|
||||||
|
|
||||||
|
testWidgets('text_form_field_demo', (WidgetTester tester) async {
|
||||||
|
final SemanticsHandle handle = tester.ensureSemantics();
|
||||||
|
await tester.pumpWidget(new MaterialApp(home: const TextFormFieldDemo()));
|
||||||
|
expect(tester, meetsGuideline(androidTapTargetGuideline));
|
||||||
|
handle.dispose();
|
||||||
|
});
|
||||||
|
|
||||||
|
testWidgets('tooltip_demo', (WidgetTester tester) async {
|
||||||
|
final SemanticsHandle handle = tester.ensureSemantics();
|
||||||
|
await tester.pumpWidget(new MaterialApp(home: new TooltipDemo()));
|
||||||
|
expect(tester, meetsGuideline(androidTapTargetGuideline));
|
||||||
|
handle.dispose();
|
||||||
|
});
|
||||||
|
|
||||||
|
testWidgets('two_level_list_demo', (WidgetTester tester) async {
|
||||||
|
final SemanticsHandle handle = tester.ensureSemantics();
|
||||||
|
await tester.pumpWidget(new MaterialApp(home: new TwoLevelListDemo()));
|
||||||
|
expect(tester, meetsGuideline(androidTapTargetGuideline));
|
||||||
|
handle.dispose();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
group('All material demos meet text contrast guidelines', () {
|
||||||
|
testWidgets('backdrop_demo', (WidgetTester tester) async {
|
||||||
|
final SemanticsHandle handle = tester.ensureSemantics();
|
||||||
|
await tester.pumpWidget(new MaterialApp(home: new BackdropDemo()));
|
||||||
|
await expectLater(tester, meetsGuideline(textContrastGuideline));
|
||||||
|
handle.dispose();
|
||||||
|
});
|
||||||
|
|
||||||
|
testWidgets('bottom_app_bar_demo', (WidgetTester tester) async {
|
||||||
|
final SemanticsHandle handle = tester.ensureSemantics();
|
||||||
|
await tester.pumpWidget(new MaterialApp(home: new BottomAppBarDemo()));
|
||||||
|
await expectLater(tester, meetsGuideline(textContrastGuideline));
|
||||||
|
handle.dispose();
|
||||||
|
}, skip: true); // https://github.com/flutter/flutter/issues/21651
|
||||||
|
|
||||||
|
testWidgets('bottom_navigation_demo', (WidgetTester tester) async {
|
||||||
|
final SemanticsHandle handle = tester.ensureSemantics();
|
||||||
|
await tester.pumpWidget(new MaterialApp(home: new BottomNavigationDemo()));
|
||||||
|
await expectLater(tester, meetsGuideline(textContrastGuideline));
|
||||||
|
handle.dispose();
|
||||||
|
});
|
||||||
|
|
||||||
|
testWidgets('buttons_demo', (WidgetTester tester) async {
|
||||||
|
final SemanticsHandle handle = tester.ensureSemantics();
|
||||||
|
await tester.pumpWidget(new MaterialApp(home: new ButtonsDemo()));
|
||||||
|
await expectLater(tester, meetsGuideline(textContrastGuideline));
|
||||||
|
handle.dispose();
|
||||||
|
}, skip: true); // https://github.com/flutter/flutter/issues/21647
|
||||||
|
|
||||||
|
testWidgets('cards_demo', (WidgetTester tester) async {
|
||||||
|
final SemanticsHandle handle = tester.ensureSemantics();
|
||||||
|
await tester.pumpWidget(new MaterialApp(home: new CardsDemo()));
|
||||||
|
await expectLater(tester, meetsGuideline(textContrastGuideline));
|
||||||
|
handle.dispose();
|
||||||
|
}, skip: true); // https://github.com/flutter/flutter/issues/21651
|
||||||
|
|
||||||
|
testWidgets('chip_demo', (WidgetTester tester) async {
|
||||||
|
final SemanticsHandle handle = tester.ensureSemantics();
|
||||||
|
await tester.pumpWidget(new MaterialApp(home: new ChipDemo()));
|
||||||
|
await expectLater(tester, meetsGuideline(textContrastGuideline));
|
||||||
|
handle.dispose();
|
||||||
|
}, skip: true); // https://github.com/flutter/flutter/issues/21647
|
||||||
|
|
||||||
|
testWidgets('data_table_demo', (WidgetTester tester) async {
|
||||||
|
final SemanticsHandle handle = tester.ensureSemantics();
|
||||||
|
await tester.pumpWidget(new MaterialApp(home: new DataTableDemo()));
|
||||||
|
await expectLater(tester, meetsGuideline(textContrastGuideline));
|
||||||
|
handle.dispose();
|
||||||
|
}, skip: true); // https://github.com/flutter/flutter/issues/21647
|
||||||
|
|
||||||
|
testWidgets('date_and_time_picker_demo', (WidgetTester tester) async {
|
||||||
|
final SemanticsHandle handle = tester.ensureSemantics();
|
||||||
|
await tester.pumpWidget(new MaterialApp(home: new DateAndTimePickerDemo()));
|
||||||
|
await expectLater(tester, meetsGuideline(textContrastGuideline));
|
||||||
|
handle.dispose();
|
||||||
|
}, skip: true); // https://github.com/flutter/flutter/issues/21647
|
||||||
|
|
||||||
|
testWidgets('dialog_demo', (WidgetTester tester) async {
|
||||||
|
final SemanticsHandle handle = tester.ensureSemantics();
|
||||||
|
await tester.pumpWidget(new MaterialApp(home: new DialogDemo()));
|
||||||
|
await expectLater(tester, meetsGuideline(textContrastGuideline));
|
||||||
|
handle.dispose();
|
||||||
|
});
|
||||||
|
|
||||||
|
testWidgets('drawer_demo', (WidgetTester tester) async {
|
||||||
|
final SemanticsHandle handle = tester.ensureSemantics();
|
||||||
|
await tester.pumpWidget(new MaterialApp(home: new DrawerDemo()));
|
||||||
|
await expectLater(tester, meetsGuideline(textContrastGuideline));
|
||||||
|
handle.dispose();
|
||||||
|
});
|
||||||
|
|
||||||
|
testWidgets('elevation_demo', (WidgetTester tester) async {
|
||||||
|
final SemanticsHandle handle = tester.ensureSemantics();
|
||||||
|
await tester.pumpWidget(new MaterialApp(home: new ElevationDemo()));
|
||||||
|
await expectLater(tester, meetsGuideline(textContrastGuideline));
|
||||||
|
handle.dispose();
|
||||||
|
});
|
||||||
|
|
||||||
|
testWidgets('expansion_panels_demo', (WidgetTester tester) async {
|
||||||
|
final SemanticsHandle handle = tester.ensureSemantics();
|
||||||
|
await tester.pumpWidget(new MaterialApp(home: new ExpansionPanelsDemo()));
|
||||||
|
await expectLater(tester, meetsGuideline(textContrastGuideline));
|
||||||
|
handle.dispose();
|
||||||
|
});
|
||||||
|
|
||||||
|
testWidgets('grid_list_demo', (WidgetTester tester) async {
|
||||||
|
final SemanticsHandle handle = tester.ensureSemantics();
|
||||||
|
await tester.pumpWidget(new MaterialApp(home: const GridListDemo()));
|
||||||
|
await expectLater(tester, meetsGuideline(textContrastGuideline));
|
||||||
|
handle.dispose();
|
||||||
|
});
|
||||||
|
|
||||||
|
testWidgets('icons_demo', (WidgetTester tester) async {
|
||||||
|
final SemanticsHandle handle = tester.ensureSemantics();
|
||||||
|
await tester.pumpWidget(new MaterialApp(home: new IconsDemo()));
|
||||||
|
await expectLater(tester, meetsGuideline(textContrastGuideline));
|
||||||
|
handle.dispose();
|
||||||
|
}, skip: true); // https://github.com/flutter/flutter/issues/21647
|
||||||
|
|
||||||
|
testWidgets('leave_behind_demo', (WidgetTester tester) async {
|
||||||
|
final SemanticsHandle handle = tester.ensureSemantics();
|
||||||
|
await tester.pumpWidget(new MaterialApp(home: const LeaveBehindDemo()));
|
||||||
|
await expectLater(tester, meetsGuideline(textContrastGuideline));
|
||||||
|
handle.dispose();
|
||||||
|
});
|
||||||
|
|
||||||
|
testWidgets('list_demo', (WidgetTester tester) async {
|
||||||
|
final SemanticsHandle handle = tester.ensureSemantics();
|
||||||
|
await tester.pumpWidget(new MaterialApp(home: const ListDemo()));
|
||||||
|
await expectLater(tester, meetsGuideline(textContrastGuideline));
|
||||||
|
handle.dispose();
|
||||||
|
});
|
||||||
|
|
||||||
|
testWidgets('menu_demo', (WidgetTester tester) async {
|
||||||
|
final SemanticsHandle handle = tester.ensureSemantics();
|
||||||
|
await tester.pumpWidget(new MaterialApp(home: const MenuDemo()));
|
||||||
|
await expectLater(tester, meetsGuideline(textContrastGuideline));
|
||||||
|
handle.dispose();
|
||||||
|
});
|
||||||
|
|
||||||
|
testWidgets('modal_bottom_sheet_demo', (WidgetTester tester) async {
|
||||||
|
final SemanticsHandle handle = tester.ensureSemantics();
|
||||||
|
await tester.pumpWidget(new MaterialApp(home: new ModalBottomSheetDemo()));
|
||||||
|
await expectLater(tester, meetsGuideline(textContrastGuideline));
|
||||||
|
handle.dispose();
|
||||||
|
});
|
||||||
|
|
||||||
|
testWidgets('overscroll_demo', (WidgetTester tester) async {
|
||||||
|
final SemanticsHandle handle = tester.ensureSemantics();
|
||||||
|
await tester.pumpWidget(new MaterialApp(home: const OverscrollDemo()));
|
||||||
|
await expectLater(tester, meetsGuideline(textContrastGuideline));
|
||||||
|
handle.dispose();
|
||||||
|
});
|
||||||
|
|
||||||
|
testWidgets('page_selector_demo', (WidgetTester tester) async {
|
||||||
|
final SemanticsHandle handle = tester.ensureSemantics();
|
||||||
|
await tester.pumpWidget(new MaterialApp(home: new PageSelectorDemo()));
|
||||||
|
await expectLater(tester, meetsGuideline(textContrastGuideline));
|
||||||
|
handle.dispose();
|
||||||
|
});
|
||||||
|
|
||||||
|
testWidgets('persistent_bottom_sheet_demo', (WidgetTester tester) async {
|
||||||
|
final SemanticsHandle handle = tester.ensureSemantics();
|
||||||
|
await tester.pumpWidget(new MaterialApp(home: new PersistentBottomSheetDemo()));
|
||||||
|
await expectLater(tester, meetsGuideline(textContrastGuideline));
|
||||||
|
handle.dispose();
|
||||||
|
});
|
||||||
|
|
||||||
|
testWidgets('progress_indicator_demo', (WidgetTester tester) async {
|
||||||
|
final SemanticsHandle handle = tester.ensureSemantics();
|
||||||
|
await tester.pumpWidget(new MaterialApp(home: new ProgressIndicatorDemo()));
|
||||||
|
await expectLater(tester, meetsGuideline(textContrastGuideline));
|
||||||
|
handle.dispose();
|
||||||
|
});
|
||||||
|
|
||||||
|
testWidgets('reorderable_list_demo', (WidgetTester tester) async {
|
||||||
|
final SemanticsHandle handle = tester.ensureSemantics();
|
||||||
|
await tester.pumpWidget(new MaterialApp(home: const ReorderableListDemo()));
|
||||||
|
await expectLater(tester, meetsGuideline(textContrastGuideline));
|
||||||
|
handle.dispose();
|
||||||
|
});
|
||||||
|
|
||||||
|
testWidgets('scrollable_tabs_demo', (WidgetTester tester) async {
|
||||||
|
final SemanticsHandle handle = tester.ensureSemantics();
|
||||||
|
await tester.pumpWidget(new MaterialApp(home: new ScrollableTabsDemo()));
|
||||||
|
await expectLater(tester, meetsGuideline(textContrastGuideline));
|
||||||
|
handle.dispose();
|
||||||
|
});
|
||||||
|
|
||||||
|
testWidgets('search_demo', (WidgetTester tester) async {
|
||||||
|
final SemanticsHandle handle = tester.ensureSemantics();
|
||||||
|
await tester.pumpWidget(new MaterialApp(home: new SearchDemo()));
|
||||||
|
await expectLater(tester, meetsGuideline(textContrastGuideline));
|
||||||
|
handle.dispose();
|
||||||
|
}, skip: true); // https://github.com/flutter/flutter/issues/21651
|
||||||
|
|
||||||
|
testWidgets('selection_controls_demo', (WidgetTester tester) async {
|
||||||
|
final SemanticsHandle handle = tester.ensureSemantics();
|
||||||
|
await tester.pumpWidget(new MaterialApp(home: new SelectionControlsDemo()));
|
||||||
|
await expectLater(tester, meetsGuideline(textContrastGuideline));
|
||||||
|
handle.dispose();
|
||||||
|
});
|
||||||
|
|
||||||
|
testWidgets('slider_demo', (WidgetTester tester) async {
|
||||||
|
final SemanticsHandle handle = tester.ensureSemantics();
|
||||||
|
await tester.pumpWidget(new MaterialApp(home: new SliderDemo()));
|
||||||
|
await expectLater(tester, meetsGuideline(textContrastGuideline));
|
||||||
|
handle.dispose();
|
||||||
|
});
|
||||||
|
|
||||||
|
testWidgets('snack_bar_demo', (WidgetTester tester) async {
|
||||||
|
final SemanticsHandle handle = tester.ensureSemantics();
|
||||||
|
await tester.pumpWidget(new MaterialApp(home: const SnackBarDemo()));
|
||||||
|
await expectLater(tester, meetsGuideline(textContrastGuideline));
|
||||||
|
handle.dispose();
|
||||||
|
});
|
||||||
|
|
||||||
|
testWidgets('tabs_demo', (WidgetTester tester) async {
|
||||||
|
final SemanticsHandle handle = tester.ensureSemantics();
|
||||||
|
await tester.pumpWidget(new MaterialApp(home: new TabsDemo()));
|
||||||
|
await expectLater(tester, meetsGuideline(textContrastGuideline));
|
||||||
|
handle.dispose();
|
||||||
|
});
|
||||||
|
|
||||||
|
testWidgets('tabs_fab_demo', (WidgetTester tester) async {
|
||||||
|
final SemanticsHandle handle = tester.ensureSemantics();
|
||||||
|
await tester.pumpWidget(new MaterialApp(home: new TabsFabDemo()));
|
||||||
|
await expectLater(tester, meetsGuideline(textContrastGuideline));
|
||||||
|
handle.dispose();
|
||||||
|
});
|
||||||
|
|
||||||
|
testWidgets('text_form_field_demo', (WidgetTester tester) async {
|
||||||
|
final SemanticsHandle handle = tester.ensureSemantics();
|
||||||
|
await tester.pumpWidget(new MaterialApp(home: const TextFormFieldDemo()));
|
||||||
|
await expectLater(tester, meetsGuideline(textContrastGuideline));
|
||||||
|
handle.dispose();
|
||||||
|
});
|
||||||
|
|
||||||
|
testWidgets('tooltip_demo', (WidgetTester tester) async {
|
||||||
|
final SemanticsHandle handle = tester.ensureSemantics();
|
||||||
|
await tester.pumpWidget(new MaterialApp(home: new TooltipDemo()));
|
||||||
|
await expectLater(tester, meetsGuideline(textContrastGuideline));
|
||||||
|
handle.dispose();
|
||||||
|
});
|
||||||
|
|
||||||
|
testWidgets('two_level_list_demo', (WidgetTester tester) async {
|
||||||
|
final SemanticsHandle handle = tester.ensureSemantics();
|
||||||
|
await tester.pumpWidget(new MaterialApp(home: new TwoLevelListDemo()));
|
||||||
|
await expectLater(tester, meetsGuideline(textContrastGuideline));
|
||||||
|
handle.dispose();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
|
@ -40,8 +40,10 @@ class Evaluation {
|
||||||
if (other == null)
|
if (other == null)
|
||||||
return this;
|
return this;
|
||||||
final StringBuffer buffer = new StringBuffer();
|
final StringBuffer buffer = new StringBuffer();
|
||||||
if (reason != null)
|
if (reason != null) {
|
||||||
buffer.write(reason);
|
buffer.write(reason);
|
||||||
|
buffer.write(' ');
|
||||||
|
}
|
||||||
if (other.reason != null)
|
if (other.reason != null)
|
||||||
buffer.write(other.reason);
|
buffer.write(other.reason);
|
||||||
return new Evaluation._(passed && other.passed, buffer.isEmpty ? null : buffer.toString());
|
return new Evaluation._(passed && other.passed, buffer.isEmpty ? null : buffer.toString());
|
||||||
|
@ -84,8 +86,13 @@ class MinimumTapTargetGuideline extends AccessibilityGuideline {
|
||||||
result += traverse(child);
|
result += traverse(child);
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
|
if (node.isMergedIntoParent)
|
||||||
|
return result;
|
||||||
final SemanticsData data = node.getSemanticsData();
|
final SemanticsData data = node.getSemanticsData();
|
||||||
if (!data.hasAction(ui.SemanticsAction.longPress) && !data.hasAction(ui.SemanticsAction.tap))
|
// Skip node if it has no actions, or is marked as hidden.
|
||||||
|
if ((!data.hasAction(ui.SemanticsAction.longPress)
|
||||||
|
&& !data.hasAction(ui.SemanticsAction.tap))
|
||||||
|
|| data.hasFlag(ui.SemanticsFlag.isHidden))
|
||||||
return result;
|
return result;
|
||||||
Rect paintBounds = node.rect;
|
Rect paintBounds = node.rect;
|
||||||
SemanticsNode current = node;
|
SemanticsNode current = node;
|
||||||
|
@ -94,6 +101,14 @@ class MinimumTapTargetGuideline extends AccessibilityGuideline {
|
||||||
paintBounds = MatrixUtils.transformRect(current.transform, paintBounds);
|
paintBounds = MatrixUtils.transformRect(current.transform, paintBounds);
|
||||||
current = current.parent;
|
current = current.parent;
|
||||||
}
|
}
|
||||||
|
// skip node if it is touching the edge of the screen, since it might
|
||||||
|
// be partially scrolled offscreen.
|
||||||
|
const double delta = 0.001;
|
||||||
|
if (paintBounds.left <= delta
|
||||||
|
|| paintBounds.top <= delta
|
||||||
|
|| (paintBounds.bottom - ui.window.physicalSize.height).abs() <= delta
|
||||||
|
|| (paintBounds.right - ui.window.physicalSize.width).abs() <= delta)
|
||||||
|
return result;
|
||||||
// shrink by device pixel ratio.
|
// shrink by device pixel ratio.
|
||||||
final Size candidateSize = paintBounds.size / ui.window.devicePixelRatio;
|
final Size candidateSize = paintBounds.size / ui.window.devicePixelRatio;
|
||||||
if (candidateSize.width < size.width || candidateSize.height < size.height)
|
if (candidateSize.width < size.width || candidateSize.height < size.height)
|
||||||
|
@ -146,6 +161,8 @@ class MinimumTextContrastGuideline extends AccessibilityGuideline {
|
||||||
final OffsetLayer layer = renderView.layer;
|
final OffsetLayer layer = renderView.layer;
|
||||||
ui.Image image;
|
ui.Image image;
|
||||||
final ByteData byteData = await tester.binding.runAsync<ByteData>(() async {
|
final ByteData byteData = await tester.binding.runAsync<ByteData>(() async {
|
||||||
|
// Needs to be the same pixel ratio otherwise our dimensions won't match the
|
||||||
|
// last transform layer.
|
||||||
image = await layer.toImage(renderView.paintBounds, pixelRatio: 1.0);
|
image = await layer.toImage(renderView.paintBounds, pixelRatio: 1.0);
|
||||||
return image.toByteData();
|
return image.toByteData();
|
||||||
});
|
});
|
||||||
|
@ -168,7 +185,7 @@ class MinimumTextContrastGuideline extends AccessibilityGuideline {
|
||||||
double fontSize;
|
double fontSize;
|
||||||
bool isBold;
|
bool isBold;
|
||||||
final String text = (data.label?.isEmpty == true) ? data.value : data.label;
|
final String text = (data.label?.isEmpty == true) ? data.value : data.label;
|
||||||
final List<Element> elements = find.text(text).evaluate().toList();
|
final List<Element> elements = find.text(text).hitTestable().evaluate().toList();
|
||||||
if (elements.length == 1) {
|
if (elements.length == 1) {
|
||||||
final Element element = elements.single;
|
final Element element = elements.single;
|
||||||
final Widget widget = element.widget;
|
final Widget widget = element.widget;
|
||||||
|
@ -186,28 +203,38 @@ class MinimumTextContrastGuideline extends AccessibilityGuideline {
|
||||||
assert(false);
|
assert(false);
|
||||||
}
|
}
|
||||||
} else if (elements.length > 1) {
|
} else if (elements.length > 1) {
|
||||||
return const Evaluation.fail('Multiple nodes with the same label');
|
return new Evaluation.fail('Multiple nodes with the same label: ${data.label}\n');
|
||||||
} else {
|
} else {
|
||||||
// If we can't find the text node, then look up the default text
|
// If we can't find the text node then assume the label does not
|
||||||
fontSize = 12.0;
|
// correspond to actual text.
|
||||||
isBold = false;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Transform local coordinate to screen coordinates.
|
// Transform local coordinate to screen coordinates.
|
||||||
Rect paintBounds = node.rect;
|
Rect paintBounds = node.rect;
|
||||||
SemanticsNode current = node;
|
SemanticsNode current = node;
|
||||||
while (current != null) {
|
while (current != null && current.parent != null) {
|
||||||
if (current.transform != null)
|
if (current.transform != null)
|
||||||
paintBounds = MatrixUtils.transformRect(current.transform, paintBounds);
|
paintBounds = MatrixUtils.transformRect(current.transform, paintBounds);
|
||||||
paintBounds = paintBounds.shift(current.parent?.rect?.topLeft ?? Offset.zero);
|
paintBounds = paintBounds.shift(current.parent?.rect?.topLeft ?? Offset.zero);
|
||||||
current = current.parent;
|
current = current.parent;
|
||||||
}
|
}
|
||||||
|
if (_isNodeOffScreen(paintBounds))
|
||||||
|
return result;
|
||||||
final List<int> subset = _subsetToRect(byteData, paintBounds, image.width, image.height);
|
final List<int> subset = _subsetToRect(byteData, paintBounds, image.width, image.height);
|
||||||
|
// Node was too far off screen.
|
||||||
|
if (subset.isEmpty)
|
||||||
|
return result;
|
||||||
final _ContrastReport report = new _ContrastReport(subset);
|
final _ContrastReport report = new _ContrastReport(subset);
|
||||||
final double contrastRatio = report.contrastRatio();
|
final double contrastRatio = report.contrastRatio();
|
||||||
final double targetContrastRatio = (isBold && fontSize > kBoldTextMinimumSize) ?
|
const double delta = -0.01;
|
||||||
kMinimumRatioLargeText : kMinimumRatioNormalText;
|
double targetContrastRatio;
|
||||||
if (contrastRatio >= targetContrastRatio)
|
if ((isBold && fontSize > kBoldTextMinimumSize) || (fontSize ?? 12.0) > kLargeTextMinimumSize) {
|
||||||
|
targetContrastRatio = kMinimumRatioLargeText;
|
||||||
|
} else {
|
||||||
|
targetContrastRatio = kMinimumRatioNormalText;
|
||||||
|
}
|
||||||
|
if (contrastRatio - targetContrastRatio >= delta)
|
||||||
return result + const Evaluation.pass();
|
return result + const Evaluation.pass();
|
||||||
return result + new Evaluation.fail(
|
return result + new Evaluation.fail(
|
||||||
'$node:\nExpected contrast ratio of at least '
|
'$node:\nExpected contrast ratio of at least '
|
||||||
|
@ -229,6 +256,17 @@ class MinimumTextContrastGuideline extends AccessibilityGuideline {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Returns a rect that is entirely on screen, or null if it is too far off.
|
||||||
|
//
|
||||||
|
// Given an 1800 * 2400 pixel buffer, can we actually get all the data from
|
||||||
|
// this node? allow a small delta overlap before culling the node.
|
||||||
|
bool _isNodeOffScreen(Rect paintBounds) {
|
||||||
|
return paintBounds.top < -50.0
|
||||||
|
|| paintBounds.left < -50.0
|
||||||
|
|| paintBounds.bottom > 2400.0 + 50.0
|
||||||
|
|| paintBounds.right > 1800.0 + 50.0;
|
||||||
|
}
|
||||||
|
|
||||||
List<int> _subsetToRect(ByteData data, Rect paintBounds, int width, int height) {
|
List<int> _subsetToRect(ByteData data, Rect paintBounds, int width, int height) {
|
||||||
final int newWidth = paintBounds.size.width.ceil();
|
final int newWidth = paintBounds.size.width.ceil();
|
||||||
final int newHeight = paintBounds.size.height.ceil();
|
final int newHeight = paintBounds.size.height.ceil();
|
||||||
|
@ -241,8 +279,8 @@ class MinimumTextContrastGuideline extends AccessibilityGuideline {
|
||||||
// Data is stored in row major order.
|
// Data is stored in row major order.
|
||||||
for (int i = 0; i < data.lengthInBytes; i+=4) {
|
for (int i = 0; i < data.lengthInBytes; i+=4) {
|
||||||
final int index = i ~/ 4;
|
final int index = i ~/ 4;
|
||||||
final int dy = index % width;
|
final int dx = index % width;
|
||||||
final int dx = index ~/ width;
|
final int dy = index ~/ width;
|
||||||
if (dx >= leftX && dx <= rightX && dy >= topY && dy <= bottomY) {
|
if (dx >= leftX && dx <= rightX && dy >= topY && dy <= bottomY) {
|
||||||
final int r = data.getUint8(i);
|
final int r = data.getUint8(i);
|
||||||
final int g = data.getUint8(i + 1);
|
final int g = data.getUint8(i + 1);
|
||||||
|
@ -271,19 +309,15 @@ class _ContrastReport {
|
||||||
final Color hslColor = new Color(colorHistogram.keys.first);
|
final Color hslColor = new Color(colorHistogram.keys.first);
|
||||||
return new _ContrastReport._(hslColor, hslColor);
|
return new _ContrastReport._(hslColor, hslColor);
|
||||||
}
|
}
|
||||||
if (colorHistogram.length == 2) {
|
|
||||||
final Color firstColor = new Color(colorHistogram.keys.first);
|
|
||||||
final Color lastColor = new Color(colorHistogram.keys.last);
|
|
||||||
if (firstColor.computeLuminance() < lastColor.computeLuminance()) {
|
|
||||||
return new _ContrastReport._(lastColor, firstColor);
|
|
||||||
}
|
|
||||||
return new _ContrastReport._(firstColor, lastColor);
|
|
||||||
}
|
|
||||||
// to determine the lighter and darker color, partition the colors
|
// to determine the lighter and darker color, partition the colors
|
||||||
// by lightness and then choose the mode from each group.
|
// by lightness and then choose the mode from each group.
|
||||||
final double averageLightness = colorHistogram.keys.fold(0.0, (double total, int color) {
|
double averageLightness = 0.0;
|
||||||
return total + new HSLColor.fromColor(new Color(color)).lightness;
|
for (int color in colorHistogram.keys) {
|
||||||
}) / colorHistogram.length;
|
final HSLColor hslColor = new HSLColor.fromColor(new Color(color));
|
||||||
|
averageLightness += hslColor.lightness * colorHistogram[color];
|
||||||
|
}
|
||||||
|
averageLightness /= colors.length;
|
||||||
|
assert(averageLightness != double.nan);
|
||||||
int lightColor = 0;
|
int lightColor = 0;
|
||||||
int darkColor = 0;
|
int darkColor = 0;
|
||||||
int lightCount = 0;
|
int lightCount = 0;
|
||||||
|
@ -292,14 +326,15 @@ class _ContrastReport {
|
||||||
for (MapEntry<int, int> entry in colorHistogram.entries) {
|
for (MapEntry<int, int> entry in colorHistogram.entries) {
|
||||||
final HSLColor color = new HSLColor.fromColor(new Color(entry.key));
|
final HSLColor color = new HSLColor.fromColor(new Color(entry.key));
|
||||||
final int count = entry.value;
|
final int count = entry.value;
|
||||||
if (color.lightness <= averageLightness && count > lightCount) {
|
if (color.lightness <= averageLightness && count > darkCount) {
|
||||||
darkColor = entry.key;
|
darkColor = entry.key;
|
||||||
darkCount = count;
|
darkCount = count;
|
||||||
} else if (color.lightness > averageLightness && count > darkCount) {
|
} else if (color.lightness > averageLightness && count > lightCount) {
|
||||||
lightColor = entry.key;
|
lightColor = entry.key;
|
||||||
lightCount = count;
|
lightCount = count;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
assert (lightColor != 0 && darkColor != 0);
|
||||||
return new _ContrastReport._(new Color(lightColor), new Color(darkColor));
|
return new _ContrastReport._(new Color(lightColor), new Color(darkColor));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -103,7 +103,7 @@ void main() {
|
||||||
handle.dispose();
|
handle.dispose();
|
||||||
});
|
});
|
||||||
|
|
||||||
testWidgets('grey text on white background fails with correct message', (WidgetTester tester) async {
|
testWidgets('yellow text on yellow background fails with correct message', (WidgetTester tester) async {
|
||||||
final SemanticsHandle handle = tester.ensureSemantics();
|
final SemanticsHandle handle = tester.ensureSemantics();
|
||||||
await tester.pumpWidget(_boilerplate(
|
await tester.pumpWidget(_boilerplate(
|
||||||
new Container(
|
new Container(
|
||||||
|
@ -121,12 +121,57 @@ void main() {
|
||||||
expect(result.reason,
|
expect(result.reason,
|
||||||
'SemanticsNode#21(Rect.fromLTRB(300.0, 200.0, 500.0, 400.0), label: "this is a test",'
|
'SemanticsNode#21(Rect.fromLTRB(300.0, 200.0, 500.0, 400.0), label: "this is a test",'
|
||||||
' textDirection: ltr):\nExpected contrast ratio of at least '
|
' textDirection: ltr):\nExpected contrast ratio of at least '
|
||||||
'4.5 but found 1.17 for a font size of 14.0. '
|
'4.5 but found 0.88 for a font size of 14.0. '
|
||||||
'The computed foreground color was: Color(0xfffafafa), '
|
'The computed foreground color was: Color(0xffffeb3b), '
|
||||||
'The computed background color was: Color(0xffffeb3b)\n'
|
'The computed background color was: Color(0xffffff00)\n'
|
||||||
'See also: https://www.w3.org/TR/UNDERSTANDING-WCAG20/visual-audio-contrast-contrast.html');
|
'See also: https://www.w3.org/TR/UNDERSTANDING-WCAG20/visual-audio-contrast-contrast.html');
|
||||||
handle.dispose();
|
handle.dispose();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
testWidgets('label without corresponding text is skipped', (WidgetTester tester) async {
|
||||||
|
final SemanticsHandle handle = tester.ensureSemantics();
|
||||||
|
await tester.pumpWidget(_boilerplate(
|
||||||
|
new Semantics(
|
||||||
|
label: 'This is not text',
|
||||||
|
container: true,
|
||||||
|
child: new Container(
|
||||||
|
width: 200.0,
|
||||||
|
height: 200.0,
|
||||||
|
child: const Placeholder(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
));
|
||||||
|
|
||||||
|
final Evaluation result = await textContrastGuideline.evaluate(tester);
|
||||||
|
expect(result.passed, true);
|
||||||
|
handle.dispose();
|
||||||
|
});
|
||||||
|
|
||||||
|
testWidgets('offscreen text is skipped', (WidgetTester tester) async {
|
||||||
|
final SemanticsHandle handle = tester.ensureSemantics();
|
||||||
|
await tester.pumpWidget(_boilerplate(
|
||||||
|
new Stack(
|
||||||
|
children: <Widget>[
|
||||||
|
new Positioned(
|
||||||
|
left: -300.0,
|
||||||
|
child: new Container(
|
||||||
|
width: 200.0,
|
||||||
|
height: 200.0,
|
||||||
|
color: Colors.yellow,
|
||||||
|
child: const Text(
|
||||||
|
'this is a test',
|
||||||
|
style: TextStyle(fontSize: 14.0, color: Colors.yellowAccent),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
)
|
||||||
|
));
|
||||||
|
|
||||||
|
final Evaluation result = await textContrastGuideline.evaluate(tester);
|
||||||
|
expect(result.passed, true);
|
||||||
|
handle.dispose();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
group('tap target size guideline', () {
|
group('tap target size guideline', () {
|
||||||
|
@ -207,11 +252,114 @@ void main() {
|
||||||
final Evaluation result = await androidTapTargetGuideline.evaluate(tester);
|
final Evaluation result = await androidTapTargetGuideline.evaluate(tester);
|
||||||
expect(result.passed, false);
|
expect(result.passed, false);
|
||||||
expect(result.reason,
|
expect(result.reason,
|
||||||
'SemanticsNode#36(Rect.fromLTRB(376.0, 276.5, 424.0, 323.5), actions: [tap]): expected tap '
|
'SemanticsNode#41(Rect.fromLTRB(376.0, 276.5, 424.0, 323.5), actions: [tap]): expected tap '
|
||||||
'target size of at least Size(48.0, 48.0), but found Size(48.0, 47.0)\n'
|
'target size of at least Size(48.0, 48.0), but found Size(48.0, 47.0)\n'
|
||||||
'See also: https://support.google.com/accessibility/android/answer/7101858?hl=en');
|
'See also: https://support.google.com/accessibility/android/answer/7101858?hl=en');
|
||||||
handle.dispose();
|
handle.dispose();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
testWidgets('Box that overlaps edge of window is skipped', (WidgetTester tester) async {
|
||||||
|
final SemanticsHandle handle = tester.ensureSemantics();
|
||||||
|
final Widget smallBox = new SizedBox(
|
||||||
|
width: 48.0,
|
||||||
|
height: 47.0,
|
||||||
|
child: new GestureDetector(
|
||||||
|
onTap: () {},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
await tester.pumpWidget(
|
||||||
|
new MaterialApp(
|
||||||
|
home: new Stack(
|
||||||
|
children: <Widget>[
|
||||||
|
new Positioned(
|
||||||
|
left: 0.0,
|
||||||
|
top: -1.0,
|
||||||
|
child: smallBox,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
final Evaluation overlappingTopResult = await androidTapTargetGuideline.evaluate(tester);
|
||||||
|
expect(overlappingTopResult.passed, true);
|
||||||
|
|
||||||
|
await tester.pumpWidget(
|
||||||
|
new MaterialApp(
|
||||||
|
home: new Stack(
|
||||||
|
children: <Widget>[
|
||||||
|
new Positioned(
|
||||||
|
left: -1.0,
|
||||||
|
top: 0.0,
|
||||||
|
child: smallBox,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
final Evaluation overlappingLeftResult = await androidTapTargetGuideline.evaluate(tester);
|
||||||
|
expect(overlappingLeftResult.passed, true);
|
||||||
|
|
||||||
|
await tester.pumpWidget(
|
||||||
|
new MaterialApp(
|
||||||
|
home: new Stack(
|
||||||
|
children: <Widget>[
|
||||||
|
new Positioned(
|
||||||
|
bottom: -1.0,
|
||||||
|
child: smallBox,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
final Evaluation overlappingBottomResult = await androidTapTargetGuideline.evaluate(tester);
|
||||||
|
expect(overlappingBottomResult.passed, true);
|
||||||
|
|
||||||
|
await tester.pumpWidget(
|
||||||
|
new MaterialApp(
|
||||||
|
home: new Stack(
|
||||||
|
children: <Widget>[
|
||||||
|
new Positioned(
|
||||||
|
right: -1.0,
|
||||||
|
child: smallBox,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
final Evaluation overlappingRightResult = await androidTapTargetGuideline.evaluate(tester);
|
||||||
|
expect(overlappingRightResult.passed, true);
|
||||||
|
handle.dispose();
|
||||||
|
});
|
||||||
|
|
||||||
|
testWidgets('Does not fail on mergedIntoParent child', (WidgetTester tester) async {
|
||||||
|
final SemanticsHandle handle = tester.ensureSemantics();
|
||||||
|
await tester.pumpWidget(_boilerplate(
|
||||||
|
new MergeSemantics(
|
||||||
|
child: new Semantics(
|
||||||
|
container: true,
|
||||||
|
child: new SizedBox(
|
||||||
|
width: 50.0,
|
||||||
|
height: 50.0,
|
||||||
|
child: new Semantics(
|
||||||
|
container: true,
|
||||||
|
child: new GestureDetector(
|
||||||
|
onTap: () {},
|
||||||
|
child: const SizedBox(width: 4.0, height: 4.0),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
));
|
||||||
|
|
||||||
|
final Evaluation overlappingRightResult = await androidTapTargetGuideline.evaluate(tester);
|
||||||
|
expect(overlappingRightResult.passed, true);
|
||||||
|
handle.dispose();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue