-
Notifications
You must be signed in to change notification settings - Fork 4k
[material_ui] Migrate MaterialApp API doc snippets to {@example} and add unit tests (batch 6) #13021
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
[material_ui] Migrate MaterialApp API doc snippets to {@example} and add unit tests (batch 6) #13021
Changes from all commits
0a5dfa4
ea057d1
3c2d34f
2d46c71
a4ba046
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,23 @@ | ||
| // Copyright 2013 The Flutter Authors | ||
| // Use of this source code is governed by a BSD-style license that can be | ||
| // found in the LICENSE file. | ||
|
|
||
| import 'package:material_ui/material_ui.dart'; | ||
|
|
||
| /// Flutter code sample for [MaterialApp]. | ||
|
|
||
| class MaterialAppExample extends StatelessWidget { | ||
| const MaterialAppExample({super.key}); | ||
|
|
||
| @override | ||
| Widget build(BuildContext context) { | ||
| return | ||
| // #region body | ||
| MaterialApp( | ||
| home: Scaffold(appBar: AppBar(title: const Text('Home'))), | ||
| debugShowCheckedModeBanner: false, | ||
| ) | ||
| // #endregion body | ||
| ; | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,29 @@ | ||
| // Copyright 2013 The Flutter Authors | ||
| // Use of this source code is governed by a BSD-style license that can be | ||
| // found in the LICENSE file. | ||
|
|
||
| import 'package:material_ui/material_ui.dart'; | ||
|
|
||
| /// Flutter code sample for [MaterialApp]. | ||
|
|
||
| class MaterialAppExample extends StatelessWidget { | ||
| const MaterialAppExample({super.key}); | ||
|
|
||
| @override | ||
| Widget build(BuildContext context) { | ||
| return | ||
| // #region body | ||
| MaterialApp( | ||
| routes: <String, WidgetBuilder>{ | ||
| '/': (BuildContext context) { | ||
| return Scaffold(appBar: AppBar(title: const Text('Home Route'))); | ||
| }, | ||
| '/about': (BuildContext context) { | ||
| return Scaffold(appBar: AppBar(title: const Text('About Route'))); | ||
| }, | ||
| }, | ||
| ) | ||
| // #endregion body | ||
| ; | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,26 @@ | ||
| // Copyright 2013 The Flutter Authors | ||
| // Use of this source code is governed by a BSD-style license that can be | ||
| // found in the LICENSE file. | ||
|
|
||
| import 'package:material_ui/material_ui.dart'; | ||
|
|
||
| /// Flutter code sample for [MaterialApp]. | ||
|
|
||
| class MaterialAppExample extends StatelessWidget { | ||
| const MaterialAppExample({super.key}); | ||
|
|
||
| @override | ||
| Widget build(BuildContext context) { | ||
| return | ||
| // #region body | ||
| MaterialApp( | ||
| theme: ThemeData( | ||
| brightness: Brightness.dark, | ||
| primaryColor: Colors.blueGrey, | ||
| ), | ||
| home: Scaffold(appBar: AppBar(title: const Text('MaterialApp Theme'))), | ||
| ) | ||
| // #endregion body | ||
| ; | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,29 @@ | ||
| // Copyright 2013 The Flutter Authors | ||
| // Use of this source code is governed by a BSD-style license that can be | ||
| // found in the LICENSE file. | ||
|
|
||
| import 'package:flutter/services.dart'; | ||
| import 'package:material_ui/material_ui.dart'; | ||
|
|
||
| /// Flutter code sample for [MaterialApp.shortcuts]. | ||
|
|
||
| class MaterialAppExample extends StatelessWidget { | ||
| const MaterialAppExample({super.key}); | ||
|
|
||
| // #region body | ||
| @override | ||
| Widget build(BuildContext context) { | ||
| return WidgetsApp( | ||
| shortcuts: <ShortcutActivator, Intent>{ | ||
| ...WidgetsApp.defaultShortcuts, | ||
| const SingleActivator(LogicalKeyboardKey.keyE): | ||
| const ActivateIntent(), | ||
| }, | ||
| color: const Color(0xFFFF0000), | ||
| builder: (BuildContext context, Widget? child) { | ||
| return const Placeholder(); | ||
| }, | ||
| ); | ||
| } | ||
| // #endregion body | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,35 @@ | ||
| // Copyright 2013 The Flutter Authors | ||
| // Use of this source code is governed by a BSD-style license that can be | ||
| // found in the LICENSE file. | ||
|
|
||
| import 'package:material_ui/material_ui.dart'; | ||
|
|
||
| /// Flutter code sample for [MaterialApp.actions]. | ||
|
|
||
| class MaterialAppExample extends StatelessWidget { | ||
| const MaterialAppExample({super.key, this.onActivated}); | ||
|
|
||
| final VoidCallback? onActivated; | ||
|
|
||
| // #region body | ||
| @override | ||
| Widget build(BuildContext context) { | ||
| return WidgetsApp( | ||
| actions: <Type, Action<Intent>>{ | ||
| ...WidgetsApp.defaultActions, | ||
| ActivateIntent: CallbackAction<Intent>( | ||
| onInvoke: (Intent intent) { | ||
| // Do something here... | ||
| onActivated?.call(); | ||
| return null; | ||
| }, | ||
| ), | ||
| }, | ||
| color: const Color(0xFFFF0000), | ||
| builder: (BuildContext context, Widget? child) { | ||
| return const Placeholder(); | ||
| }, | ||
| ); | ||
| } | ||
| // #endregion body | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,19 @@ | ||
| // Copyright 2013 The Flutter Authors | ||
| // Use of this source code is governed by a BSD-style license that can be | ||
| // found in the LICENSE file. | ||
|
|
||
| import 'package:flutter_test/flutter_test.dart'; | ||
| import 'package:material_ui/material_ui.dart'; | ||
| import 'package:material_ui_examples/app/app.snippet.0.dart' as example; | ||
|
|
||
| void main() { | ||
| testWidgets( | ||
| 'MaterialApp displays home route and disables debug mode banner', | ||
| (WidgetTester tester) async { | ||
| await tester.pumpWidget(const example.MaterialAppExample()); | ||
|
|
||
| expect(find.byType(CheckedModeBanner), findsNothing); | ||
| expect(find.widgetWithText(AppBar, 'Home'), findsOneWidget); | ||
| }, | ||
| ); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| // Copyright 2013 The Flutter Authors | ||
| // Use of this source code is governed by a BSD-style license that can be | ||
| // found in the LICENSE file. | ||
|
|
||
| import 'package:flutter_test/flutter_test.dart'; | ||
| import 'package:material_ui/material_ui.dart'; | ||
| import 'package:material_ui_examples/app/app.snippet.1.dart' as example; | ||
|
|
||
| void main() { | ||
| testWidgets('MaterialApp routes map navigates between Home and About', ( | ||
| WidgetTester tester, | ||
| ) async { | ||
| await tester.pumpWidget(const example.MaterialAppExample()); | ||
|
|
||
| expect(find.widgetWithText(AppBar, 'Home Route'), findsOneWidget); | ||
| expect(find.widgetWithText(AppBar, 'About Route'), findsNothing); | ||
|
|
||
| final BuildContext context = tester.element(find.text('Home Route')); | ||
| Navigator.of(context).pushNamed('/about'); | ||
| await tester.pumpAndSettle(); | ||
|
|
||
| expect(find.widgetWithText(AppBar, 'About Route'), findsOneWidget); | ||
| }); | ||
| } | ||
| Original file line number | Diff line number | Diff line change | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,22 @@ | ||||||||||
| // Copyright 2013 The Flutter Authors | ||||||||||
| // Use of this source code is governed by a BSD-style license that can be | ||||||||||
| // found in the LICENSE file. | ||||||||||
|
|
||||||||||
| import 'package:flutter_test/flutter_test.dart'; | ||||||||||
| import 'package:material_ui/material_ui.dart'; | ||||||||||
| import 'package:material_ui_examples/app/app.snippet.2.dart' as example; | ||||||||||
|
|
||||||||||
| void main() { | ||||||||||
| testWidgets('MaterialApp applies custom ThemeData', ( | ||||||||||
| WidgetTester tester, | ||||||||||
| ) async { | ||||||||||
| await tester.pumpWidget(const example.MaterialAppExample()); | ||||||||||
|
|
||||||||||
| expect(find.widgetWithText(AppBar, 'MaterialApp Theme'), findsOneWidget); | ||||||||||
|
|
||||||||||
| final BuildContext context = tester.element(find.text('MaterialApp Theme')); | ||||||||||
| final ThemeData theme = Theme.of(context); | ||||||||||
|
Comment on lines
+17
to
+18
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Obtaining the
Suggested change
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this isn't significant. |
||||||||||
| expect(theme.brightness, Brightness.dark); | ||||||||||
| expect(theme.primaryColor, Colors.blueGrey); | ||||||||||
| }); | ||||||||||
| } | ||||||||||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,38 @@ | ||||||
| // Copyright 2013 The Flutter Authors | ||||||
| // Use of this source code is governed by a BSD-style license that can be | ||||||
| // found in the LICENSE file. | ||||||
|
|
||||||
| import 'package:flutter/services.dart'; | ||||||
| import 'package:flutter_test/flutter_test.dart'; | ||||||
| import 'package:material_ui/material_ui.dart'; | ||||||
| import 'package:material_ui_examples/app/app.snippet.3.dart' as example; | ||||||
|
|
||||||
| void main() { | ||||||
| testWidgets('WidgetsApp shortcuts maps select key to ActivateIntent', ( | ||||||
| WidgetTester tester, | ||||||
| ) async { | ||||||
| bool invoked = false; | ||||||
| await tester.pumpWidget( | ||||||
| Actions( | ||||||
| actions: <Type, Action<Intent>>{ | ||||||
| ActivateIntent: CallbackAction<ActivateIntent>( | ||||||
| onInvoke: (ActivateIntent intent) { | ||||||
| invoked = true; | ||||||
| return null; | ||||||
| }, | ||||||
| ), | ||||||
| }, | ||||||
| child: const example.MaterialAppExample(), | ||||||
| ), | ||||||
| ); | ||||||
|
|
||||||
| final Element placeholderElement = tester.element(find.byType(Placeholder)); | ||||||
| final FocusNode focusNode = Focus.of(placeholderElement); | ||||||
| focusNode.canRequestFocus = true; | ||||||
| focusNode.requestFocus(); | ||||||
| await tester.pump(); | ||||||
|
|
||||||
| await tester.sendKeyEvent(LogicalKeyboardKey.keyE); | ||||||
| expect(invoked, isTrue); | ||||||
| }); | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: maybe we can test this against iOS like
Suggested change
This test still passes if the snippet's one extra shortcut,
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Really good point! I've changed the activating key from Select to keyE, which should be more useful as an example than having the platform set to iOS. |
||||||
| } | ||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,32 @@ | ||
| // Copyright 2013 The Flutter Authors | ||
| // Use of this source code is governed by a BSD-style license that can be | ||
| // found in the LICENSE file. | ||
|
|
||
| import 'package:flutter/services.dart'; | ||
| import 'package:flutter_test/flutter_test.dart'; | ||
| import 'package:material_ui/material_ui.dart'; | ||
| import 'package:material_ui_examples/app/app.snippet.4.dart' as example; | ||
|
|
||
| void main() { | ||
| testWidgets('WidgetsApp actions handles ActivateIntent', ( | ||
| WidgetTester tester, | ||
| ) async { | ||
| bool activated = false; | ||
| await tester.pumpWidget( | ||
| example.MaterialAppExample( | ||
| onActivated: () { | ||
| activated = true; | ||
| }, | ||
| ), | ||
| ); | ||
|
|
||
| final Element placeholderElement = tester.element(find.byType(Placeholder)); | ||
| final FocusNode focusNode = Focus.of(placeholderElement); | ||
| focusNode.canRequestFocus = true; | ||
| focusNode.requestFocus(); | ||
| await tester.pump(); | ||
|
|
||
| await tester.sendKeyEvent(LogicalKeyboardKey.space); | ||
| expect(activated, isTrue); | ||
| }); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using
tester.element(find.text('Home Route'))to obtain aBuildContextfor navigation makes the test fragile, as it relies on the specific text content of the UI. A more robust and idiomatic approach in Flutter widget tests is to access theNavigatorStatedirectly usingtester.state.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this isn't significant.