// Copyright 2021 The Flutter team. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // ignore_for_file: avoid_types_on_closure_parameters import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:material_3_demo/component_screen.dart'; import 'package:material_3_demo/main.dart'; void main() { testWidgets('Default main page shows all M3 components', (tester) async { await tester.pumpWidget(const Material3Demo()); // Elements on the app bar expect(find.text('Material 3'), findsOneWidget); expect(find.widgetWithIcon(IconButton, Icons.wb_sunny_outlined), findsOneWidget); expect(find.widgetWithIcon(IconButton, Icons.filter_3), findsOneWidget); expect(find.widgetWithIcon(IconButton, Icons.more_vert), findsOneWidget); // Elements on the component screen // Buttons expect(find.widgetWithText(ElevatedButton, "Elevated"), findsNWidgets(2)); expect(find.widgetWithText(ElevatedButton, "Filled"), findsNWidgets(2)); expect( find.widgetWithText(ElevatedButton, "Filled Tonal"), findsNWidgets(2)); expect(find.widgetWithText(OutlinedButton, "Outlined"), findsNWidgets(2)); expect(find.widgetWithText(TextButton, "Text"), findsNWidgets(2)); expect(find.text("Icon"), findsNWidgets(5)); // FABs Finder floatingActionButton = find.text("Create"); await tester.scrollUntilVisible( floatingActionButton, 500.0, ); expect( find.widgetWithIcon(FloatingActionButton, Icons.add), findsNWidgets(4)); expect(find.widgetWithText(FloatingActionButton, "Create"), findsOneWidget); // Cards expect(find.widgetWithText(Card, "Elevated"), findsOneWidget); expect(find.widgetWithText(Card, "Filled"), findsOneWidget); expect(find.widgetWithText(Card, "Outlined"), findsOneWidget); // Alert Dialog Finder dialogExample = find.widgetWithText(TextButton, "Open Dialog"); await tester.scrollUntilVisible( dialogExample, 500.0, ); expect(dialogExample, findsOneWidget); }); testWidgets( 'NavigationRail doesn\'t show when width value is small than 450 ' '(in Portrait mode or narrow screen)', (tester) async { widgetSetup(tester, 449); await tester.pumpWidget(const Material3Demo()); // When screen width is less than 450, NavigationBar will show. At the same // time, the NavigationRail and the NavigationBar example will NOT show. expect(find.byType(NavigationBars), findsOneWidget); expect(find.widgetWithText(NavigationBar, "Components"), findsOneWidget); expect(find.widgetWithText(NavigationBar, "Color"), findsOneWidget); expect(find.widgetWithText(NavigationBar, "Typography"), findsOneWidget); expect(find.widgetWithText(NavigationBar, "Elevation"), findsOneWidget); expect(find.byType(NavigationRailSection), findsNothing); expect(find.widgetWithText(NavigationBar, "Explore"), findsNothing); expect(find.widgetWithText(NavigationBar, "Pets"), findsNothing); expect(find.widgetWithText(NavigationBar, "Account"), findsNothing); }); testWidgets( 'NavigationRail shows when width value is greater than or equal ' 'to 450 (in Landscape mode or wider screen)', (tester) async { widgetSetup(tester, 450); await tester.pumpWidget(const Material3Demo()); // When screen width is greater than or equal to 450, NavigationRail and // NavigationBar example will show. At the same time, the NavigationBar // will NOT show. expect(find.byType(NavigationRailSection), findsOneWidget); expect(find.byType(Tooltip, skipOffstage: false), findsWidgets); expect(find.widgetWithText(NavigationRailSection, "Components"), findsOneWidget); expect(find.widgetWithText(NavigationRailSection, "Color"), findsOneWidget); expect(find.widgetWithText(NavigationRailSection, "Typography"), findsOneWidget); expect(find.widgetWithText(NavigationRailSection, "Elevation"), findsOneWidget); final navbarExample = find.byType(NavigationBars); await tester.scrollUntilVisible( navbarExample, 500.0, ); expect(find.byType(NavigationBars), findsOneWidget); expect(find.widgetWithText(NavigationBar, "Explore"), findsOneWidget); expect(find.widgetWithText(NavigationBar, "Pets"), findsOneWidget); expect(find.widgetWithText(NavigationBar, "Account"), findsOneWidget); expect(find.widgetWithText(NavigationBar, "Components"), findsNothing); expect(find.widgetWithText(NavigationBar, "Colors"), findsNothing); expect(find.widgetWithText(NavigationBar, "Typography"), findsNothing); expect(find.widgetWithText(NavigationBar, "Elevation"), findsNothing); }); testWidgets( 'Material version switches between Material3 and Material2 when' 'the version icon is clicked', (tester) async { await tester.pumpWidget(const Material3Demo()); Finder m3Icon = find.widgetWithIcon(IconButton, Icons.filter_3); Finder m2Icon = find.widgetWithIcon(IconButton, Icons.filter_2); BuildContext defaultElevatedButton = tester.firstElement(find.byType(ElevatedButton)); BuildContext defaultFAB = tester.firstElement(find.byType(FloatingActionButton)); BuildContext defaultCard = tester.firstElement(find.byType(Card)); Finder dialog = find.text("Open Dialog"); await tester.scrollUntilVisible( dialog, 500.0, ); await tester.tap(dialog); await tester.pumpAndSettle(const Duration(microseconds: 500)); BuildContext defaultAlertDialog = tester.element(find.byType(AlertDialog)); expect(Theme.of(defaultAlertDialog).useMaterial3, true); Finder dismiss = find.text("Dismiss"); await tester.scrollUntilVisible( dismiss, 500.0, ); await tester.tap(dismiss); await tester.pumpAndSettle(const Duration(microseconds: 500)); expect(m3Icon, findsOneWidget); expect(m2Icon, findsNothing); expect(find.text("Material 3"), findsOneWidget); expect(Theme.of(defaultElevatedButton).useMaterial3, true); expect(Theme.of(defaultFAB).useMaterial3, true); expect(Theme.of(defaultCard).useMaterial3, true); await tester.tap(m3Icon); await tester.pumpAndSettle(const Duration(microseconds: 500)); BuildContext updatedElevatedButton = tester.firstElement(find.byType(ElevatedButton)); BuildContext updatedFAB = tester.firstElement(find.byType(FloatingActionButton)); BuildContext updatedCard = tester.firstElement(find.byType(Card)); Finder updatedDialog = find.text("Open Dialog"); await tester.scrollUntilVisible( updatedDialog, 500.0, ); await tester.tap(updatedDialog); await tester.pumpAndSettle(const Duration(microseconds: 500)); BuildContext updatedAlertDialog = tester.firstElement(find.byType(AlertDialog)); expect(Theme.of(updatedAlertDialog).useMaterial3, false); Finder updatedDismiss = find.text("Dismiss"); await tester.scrollUntilVisible( updatedDismiss, 500.0, ); await tester.tap(updatedDismiss); await tester.pumpAndSettle(const Duration(microseconds: 500)); expect(m3Icon, findsNothing); expect(m2Icon, findsOneWidget); expect(find.text("Material 2"), findsOneWidget); expect(Theme.of(updatedElevatedButton).useMaterial3, false); expect(Theme.of(updatedFAB).useMaterial3, false); expect(Theme.of(updatedCard).useMaterial3, false); }); testWidgets( 'Other screens become Material2 mode after changing mode from ' 'main screen', (tester) async { await tester.pumpWidget(const Material3Demo()); await tester.tap(find.widgetWithIcon(IconButton, Icons.filter_3)); await tester.tap(find.byIcon(Icons.format_paint_outlined)); await tester.pumpAndSettle(const Duration(microseconds: 500)); BuildContext lightThemeText = tester.element(find.text("Light Theme")); expect(Theme.of(lightThemeText).useMaterial3, false); await tester.tap(find.byIcon(Icons.text_snippet_outlined)); await tester.pumpAndSettle(const Duration(microseconds: 500)); BuildContext displayLargeText = tester.element(find.text("Display Large")); expect(Theme.of(displayLargeText).useMaterial3, false); await tester.tap(find.byIcon(Icons.invert_colors_on_outlined)); await tester.pumpAndSettle(const Duration(microseconds: 500)); BuildContext material = tester.firstElement(find.byType(Material)); expect(Theme.of(material).useMaterial3, false); }); testWidgets( 'Brightness mode switches between dark and light when' 'the brightness icon is clicked', (tester) async { await tester.pumpWidget(const Material3Demo()); Finder lightIcon = find.widgetWithIcon(IconButton, Icons.wb_sunny_outlined); Finder darkIcon = find.widgetWithIcon(IconButton, Icons.wb_sunny); BuildContext appBar = tester.element(find.byType(AppBar)); BuildContext body = tester.element(find.byType(Scaffold)); BuildContext navigationRail = tester.element(find.byType(NavigationRail)); expect(lightIcon, findsOneWidget); expect(darkIcon, findsNothing); expect(Theme.of(appBar).brightness, Brightness.light); expect(Theme.of(body).brightness, Brightness.light); expect(Theme.of(navigationRail).brightness, Brightness.light); await tester.tap(lightIcon); await tester.pumpAndSettle(const Duration(microseconds: 500)); BuildContext appBar2 = tester.element(find.byType(AppBar)); BuildContext body2 = tester.element(find.byType(Scaffold)); BuildContext navigationRail2 = tester.element(find.byType(NavigationRail)); expect(lightIcon, findsNothing); expect(darkIcon, findsOneWidget); expect(Theme.of(appBar2).brightness, Brightness.dark); expect(Theme.of(body2).brightness, Brightness.dark); expect(Theme.of(navigationRail2).brightness, Brightness.dark); }); testWidgets('Color theme changes when a color is selected from menu', (tester) async { await tester.pumpWidget(const Material3Demo()); Finder menuIcon = find.widgetWithIcon(IconButton, Icons.more_vert); BuildContext appBar = tester.element(find.byType(AppBar)); BuildContext body = tester.element(find.byType(Scaffold)); BuildContext navigationRail = tester.element(find.byType(NavigationRail)); expect(Theme.of(appBar).primaryColor, m3BaseColor); expect(Theme.of(body).primaryColor, m3BaseColor); expect(Theme.of(navigationRail).primaryColor, m3BaseColor); await tester.tap(menuIcon); await tester.pumpAndSettle(); await tester.tap(find.text("Blue")); await tester.pumpAndSettle(); BuildContext appBar2 = tester.element(find.byType(AppBar)); BuildContext body2 = tester.element(find.byType(Scaffold)); BuildContext navigationRail2 = tester.element(find.byType(NavigationRail)); ThemeData expectedTheme = ThemeData(colorSchemeSeed: Colors.blue); expect(Theme.of(appBar2).primaryColor, expectedTheme.primaryColor); expect(Theme.of(body2).primaryColor, expectedTheme.primaryColor); expect(Theme.of(navigationRail2).primaryColor, expectedTheme.primaryColor); }); } void widgetSetup(WidgetTester tester, double width) { const height = 846; tester.binding.window.devicePixelRatioTestValue = (2); final dpi = tester.binding.window.devicePixelRatio; tester.binding.window.physicalSizeTestValue = Size(width * dpi, height * dpi); }