banner_theme_test.dart 14.5 KB
Newer Older
Ian Hickson's avatar
Ian Hickson committed
1
// Copyright 2014 The Flutter Authors. All rights reserved.
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
// 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/rendering.dart';
import 'package:flutter_test/flutter_test.dart';

void main() {
  test('MaterialBannerThemeData copyWith, ==, hashCode basics', () {
    expect(const MaterialBannerThemeData(), const MaterialBannerThemeData().copyWith());
    expect(const MaterialBannerThemeData().hashCode, const MaterialBannerThemeData().copyWith().hashCode);
  });

  test('MaterialBannerThemeData null fields by default', () {
    const MaterialBannerThemeData bannerTheme = MaterialBannerThemeData();
    expect(bannerTheme.backgroundColor, null);
    expect(bannerTheme.contentTextStyle, null);
  });

  testWidgets('Default MaterialBannerThemeData debugFillProperties', (WidgetTester tester) async {
    final DiagnosticPropertiesBuilder builder = DiagnosticPropertiesBuilder();
    const MaterialBannerThemeData().debugFillProperties(builder);

    final List<String> description = builder.properties
        .where((DiagnosticsNode node) => !node.isFiltered(DiagnosticLevel.info))
        .map((DiagnosticsNode node) => node.toString())
        .toList();

    expect(description, <String>[]);
  });

  testWidgets('MaterialBannerThemeData implements debugFillProperties', (WidgetTester tester) async {
    final DiagnosticPropertiesBuilder builder = DiagnosticPropertiesBuilder();
    const MaterialBannerThemeData(
      backgroundColor: Color(0xFFFFFFFF),
      contentTextStyle: TextStyle(color: Color(0xFFFFFFFF)),
    ).debugFillProperties(builder);

    final List<String> description = builder.properties
        .where((DiagnosticsNode node) => !node.isFiltered(DiagnosticLevel.info))
        .map((DiagnosticsNode node) => node.toString())
        .toList();

    expect(description, <String>[
      'backgroundColor: Color(0xffffffff)',
      'contentTextStyle: TextStyle(inherit: true, color: Color(0xffffffff))',
    ]);
  });

  testWidgets('Passing no MaterialBannerThemeData returns defaults', (WidgetTester tester) async {
    const String contentText = 'Content';
    await tester.pumpWidget(MaterialApp(
      home: Scaffold(
        body: MaterialBanner(
          content: const Text(contentText),
          actions: <Widget>[
58
            TextButton(
59 60 61 62 63 64 65 66
              child: const Text('Action'),
              onPressed: () { },
            ),
          ],
        ),
      ),
    ));

67
    final Material material = _getMaterialFromText(tester, contentText);
68
    final RenderParagraph content = _getTextRenderObjectFromDialog(tester, contentText);
69
    expect(material.color, const Color(0xffffffff));
70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106
    // Default value for ThemeData.typography is Typography.material2014()
    expect(content.text.style, Typography.material2014().englishLike.bodyText2!.merge(Typography.material2014().black.bodyText2));
  });

  testWidgets('Passing no MaterialBannerThemeData returns defaults when presented by ScaffoldMessenger', (WidgetTester tester) async {
    const String contentText = 'Content';
    const Key tapTarget = Key('tap-target');
    await tester.pumpWidget(MaterialApp(
      home: Scaffold(
        body: Builder(
          builder: (BuildContext context) {
            return GestureDetector(
              key: tapTarget,
              onTap: () {
                ScaffoldMessenger.of(context).showMaterialBanner(MaterialBanner(
                  content: const Text(contentText),
                  actions: <Widget>[
                    TextButton(
                      child: const Text('Action'),
                      onPressed: () { },
                    ),
                  ],
                ));
              },
              behavior: HitTestBehavior.opaque,
              child: const SizedBox(
                height: 100.0,
                width: 100.0,
              ),
            );
          },
        ),
      ),
    ));
    await tester.tap(find.byKey(tapTarget));
    await tester.pumpAndSettle();

107
    final Material material = _getMaterialFromText(tester, contentText);
108
    final RenderParagraph content = _getTextRenderObjectFromDialog(tester, contentText);
109
    expect(material.color, const Color(0xffffffff));
110
    // Default value for ThemeData.typography is Typography.material2014()
111
    expect(content.text.style, Typography.material2014().englishLike.bodyText2!.merge(Typography.material2014().black.bodyText2));
112 113 114 115 116 117 118 119 120 121 122 123
  });

  testWidgets('MaterialBanner uses values from MaterialBannerThemeData', (WidgetTester tester) async {
    final MaterialBannerThemeData bannerTheme = _bannerTheme();
    const String contentText = 'Content';
    await tester.pumpWidget(MaterialApp(
      theme: ThemeData(bannerTheme: bannerTheme),
      home: Scaffold(
        body: MaterialBanner(
          leading: const Icon(Icons.ac_unit),
          content: const Text(contentText),
          actions: <Widget>[
124
            TextButton(
125 126 127 128 129 130 131 132
              child: const Text('Action'),
              onPressed: () { },
            ),
          ],
        ),
      ),
    ));

133
    final Material material = _getMaterialFromText(tester, contentText);
134
    final RenderParagraph content = _getTextRenderObjectFromDialog(tester, contentText);
135
    expect(material.color, bannerTheme.backgroundColor);
136 137 138
    expect(content.text.style, bannerTheme.contentTextStyle);

    final Offset contentTopLeft = tester.getTopLeft(_textFinder(contentText));
139
    final Offset materialTopLeft = tester.getTopLeft(_materialFinder());
140
    final Offset leadingTopLeft = tester.getTopLeft(find.byIcon(Icons.ac_unit));
141 142 143 144
    expect(contentTopLeft.dy - materialTopLeft.dy, 24);
    expect(contentTopLeft.dx - materialTopLeft.dx, 41);
    expect(leadingTopLeft.dy - materialTopLeft.dy, 19);
    expect(leadingTopLeft.dx - materialTopLeft.dx, 11);
145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182
  });

  testWidgets('MaterialBanner uses values from MaterialBannerThemeData when presented by ScaffoldMessenger', (WidgetTester tester) async {
    final MaterialBannerThemeData bannerTheme = _bannerTheme();
    const String contentText = 'Content';
    const Key tapTarget = Key('tap-target');
    await tester.pumpWidget(MaterialApp(
      theme: ThemeData(bannerTheme: bannerTheme),
      home: Scaffold(
        body: Builder(
          builder: (BuildContext context) {
            return GestureDetector(
              key: tapTarget,
              onTap: () {
                ScaffoldMessenger.of(context).showMaterialBanner(MaterialBanner(
                  leading: const Icon(Icons.ac_unit),
                  content: const Text(contentText),
                  actions: <Widget>[
                    TextButton(
                      child: const Text('Action'),
                      onPressed: () { },
                    ),
                  ],
                ));
              },
              behavior: HitTestBehavior.opaque,
              child: const SizedBox(
                height: 100.0,
                width: 100.0,
              ),
            );
          },
        ),
      ),
    ));
    await tester.tap(find.byKey(tapTarget));
    await tester.pumpAndSettle();

183
    final Material material = _getMaterialFromText(tester, contentText);
184
    final RenderParagraph content = _getTextRenderObjectFromDialog(tester, contentText);
185
    expect(material.color, bannerTheme.backgroundColor);
186 187 188
    expect(content.text.style, bannerTheme.contentTextStyle);

    final Offset contentTopLeft = tester.getTopLeft(_textFinder(contentText));
189
    final Offset materialTopLeft = tester.getTopLeft(_materialFinder());
190
    final Offset leadingTopLeft = tester.getTopLeft(find.byIcon(Icons.ac_unit));
191 192 193 194
    expect(contentTopLeft.dy - materialTopLeft.dy, 24);
    expect(contentTopLeft.dx - materialTopLeft.dx, 41);
    expect(leadingTopLeft.dy - materialTopLeft.dy, 19);
    expect(leadingTopLeft.dx - materialTopLeft.dx, 11);
195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210
  });

  testWidgets('MaterialBanner widget properties take priority over theme', (WidgetTester tester) async {
    const Color backgroundColor = Colors.purple;
    const TextStyle textStyle = TextStyle(color: Colors.green);
    final MaterialBannerThemeData bannerTheme = _bannerTheme();
    const String contentText = 'Content';
    await tester.pumpWidget(MaterialApp(
      theme: ThemeData(bannerTheme: bannerTheme),
      home: Scaffold(
        body: MaterialBanner(
          backgroundColor: backgroundColor,
          leading: const Icon(Icons.ac_unit),
          contentTextStyle: textStyle,
          content: const Text(contentText),
          padding: const EdgeInsets.all(10),
211
          leadingPadding: const EdgeInsets.all(12),
212
          actions: <Widget>[
213
            TextButton(
214 215 216 217 218 219 220 221
              child: const Text('Action'),
              onPressed: () { },
            ),
          ],
        ),
      ),
    ));

222
    final Material material = _getMaterialFromText(tester, contentText);
223
    final RenderParagraph content = _getTextRenderObjectFromDialog(tester, contentText);
224
    expect(material.color, backgroundColor);
225 226 227
    expect(content.text.style, textStyle);

    final Offset contentTopLeft = tester.getTopLeft(_textFinder(contentText));
228
    final Offset materialTopLeft = tester.getTopLeft(_materialFinder());
229
    final Offset leadingTopLeft = tester.getTopLeft(find.byIcon(Icons.ac_unit));
230 231 232 233
    expect(contentTopLeft.dy - materialTopLeft.dy, 29);
    expect(contentTopLeft.dx - materialTopLeft.dx, 58);
    expect(leadingTopLeft.dy - materialTopLeft.dy, 24);
    expect(leadingTopLeft.dx - materialTopLeft.dx, 22);
234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277
  });

  testWidgets('MaterialBanner widget properties take priority over theme when presented by ScaffoldMessenger', (WidgetTester tester) async {
    const Color backgroundColor = Colors.purple;
    const TextStyle textStyle = TextStyle(color: Colors.green);
    final MaterialBannerThemeData bannerTheme = _bannerTheme();
    const String contentText = 'Content';
    const Key tapTarget = Key('tap-target');
    await tester.pumpWidget(MaterialApp(
      theme: ThemeData(bannerTheme: bannerTheme),
      home: Scaffold(
        body: Builder(
          builder: (BuildContext context) {
            return GestureDetector(
              key: tapTarget,
              onTap: () {
                ScaffoldMessenger.of(context).showMaterialBanner(MaterialBanner(
                  backgroundColor: backgroundColor,
                  leading: const Icon(Icons.ac_unit),
                  contentTextStyle: textStyle,
                  content: const Text(contentText),
                  padding: const EdgeInsets.all(10),
                  leadingPadding: const EdgeInsets.all(12),
                  actions: <Widget>[
                    TextButton(
                      child: const Text('Action'),
                      onPressed: () { },
                    ),
                  ],
                ));
              },
              behavior: HitTestBehavior.opaque,
              child: const SizedBox(
                height: 100.0,
                width: 100.0,
              ),
            );
          },
        ),
      ),
    ));
    await tester.tap(find.byKey(tapTarget));
    await tester.pumpAndSettle();

278
    final Material material = _getMaterialFromText(tester, contentText);
279
    final RenderParagraph content = _getTextRenderObjectFromDialog(tester, contentText);
280
    expect(material.color, backgroundColor);
281 282 283
    expect(content.text.style, textStyle);

    final Offset contentTopLeft = tester.getTopLeft(_textFinder(contentText));
284
    final Offset materialTopLeft = tester.getTopLeft(_materialFinder());
285
    final Offset leadingTopLeft = tester.getTopLeft(find.byIcon(Icons.ac_unit));
286 287 288 289
    expect(contentTopLeft.dy - materialTopLeft.dy, 29);
    expect(contentTopLeft.dx - materialTopLeft.dx, 58);
    expect(leadingTopLeft.dy - materialTopLeft.dy, 24);
    expect(leadingTopLeft.dx - materialTopLeft.dx, 22);
290 291 292 293
  });

  testWidgets('MaterialBanner uses color scheme when necessary', (WidgetTester tester) async {
    final ColorScheme colorScheme = const ColorScheme.light().copyWith(surface: Colors.purple);
294
    const String contentText = 'Content';
295 296 297 298
    await tester.pumpWidget(MaterialApp(
      theme: ThemeData(colorScheme: colorScheme),
      home: Scaffold(
        body: MaterialBanner(
299
          content: const Text(contentText),
300
          actions: <Widget>[
301
            TextButton(
302 303 304 305 306 307 308 309
              child: const Text('Action'),
              onPressed: () { },
            ),
          ],
        ),
      ),
    ));

310 311
    final Material material = _getMaterialFromText(tester, contentText);
    expect(material.color, colorScheme.surface);
312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348
  });

  testWidgets('MaterialBanner uses color scheme when necessary when presented by ScaffoldMessenger', (WidgetTester tester) async {
    final ColorScheme colorScheme = const ColorScheme.light().copyWith(surface: Colors.purple);
    const String contentText = 'Content';
    const Key tapTarget = Key('tap-target');
    await tester.pumpWidget(MaterialApp(
      theme: ThemeData(colorScheme: colorScheme),
      home: Scaffold(
        body: Builder(
          builder: (BuildContext context) {
            return GestureDetector(
              key: tapTarget,
              onTap: () {
                ScaffoldMessenger.of(context).showMaterialBanner(MaterialBanner(
                  content: const Text(contentText),
                  actions: <Widget>[
                    TextButton(
                      child: const Text('Action'),
                      onPressed: () { },
                    ),
                  ],
                ));
              },
              behavior: HitTestBehavior.opaque,
              child: const SizedBox(
                height: 100.0,
                width: 100.0,
              ),
            );
          },
        ),
      ),
    ));
    await tester.tap(find.byKey(tapTarget));
    await tester.pumpAndSettle();

349 350
    final Material material = _getMaterialFromText(tester, contentText);
    expect(material.color, colorScheme.surface);
351 352 353 354 355 356 357 358
  });
}

MaterialBannerThemeData _bannerTheme() {
  return const MaterialBannerThemeData(
    backgroundColor: Colors.orange,
    contentTextStyle: TextStyle(color: Colors.pink),
    padding: EdgeInsets.all(5),
359
    leadingPadding: EdgeInsets.all(6),
360 361 362
  );
}

363 364
Material _getMaterialFromText(WidgetTester tester, String text) {
  return tester.widget<Material>(find.widgetWithText(Material, text).first);
365 366
}

367 368
Finder _materialFinder() {
  return find.descendant(of: find.byType(MaterialBanner), matching: find.byType(Material)).first;
369 370 371
}

RenderParagraph _getTextRenderObjectFromDialog(WidgetTester tester, String text) {
372
  return tester.element<StatelessElement>(_textFinder(text)).renderObject! as RenderParagraph;
373 374 375 376
}

Finder _textFinder(String text) {
  return find.descendant(of: find.byType(MaterialBanner), matching: find.text(text));
377
}