circle_avatar_test.dart 12.3 KB
Newer Older
Ian Hickson's avatar
Ian Hickson committed
1
// Copyright 2014 The Flutter Authors. All rights reserved.
2 3 4
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

5 6 7
// This file is run as part of a reduced test set in CI on Mac and Windows
// machines.
@Tags(<String>['reduced-test-set'])
8 9
library;

10 11
import 'dart:typed_data';

12
import 'package:flutter/material.dart';
13
import 'package:flutter/rendering.dart';
14 15
import 'package:flutter_test/flutter_test.dart';

16
import '../image_data.dart';
17
import '../painting/mocks_for_image_cache.dart';
18

19
void main() {
20 21
  testWidgets('CircleAvatar with dark background color', (WidgetTester tester) async {
    final Color backgroundColor = Colors.blue.shade900;
22
    await tester.pumpWidget(
Ian Hickson's avatar
Ian Hickson committed
23
      wrap(
24
        child: CircleAvatar(
25
          backgroundColor: backgroundColor,
26
          radius: 50.0,
27
          child: const Text('Z'),
28 29
        ),
      ),
30 31
    );

32
    final RenderConstrainedBox box = tester.renderObject(find.byType(CircleAvatar));
33
    expect(box.size, equals(const Size(100.0, 100.0)));
34
    final RenderDecoratedBox child = box.child! as RenderDecoratedBox;
35
    final BoxDecoration decoration = child.decoration as BoxDecoration;
36
    expect(decoration.color, equals(backgroundColor));
37

38
    final RenderParagraph paragraph = tester.renderObject(find.text('Z'));
39
    expect(paragraph.text.style!.color, equals(ThemeData.fallback().primaryColorLight));
40 41
  });

42 43 44 45
  testWidgets('CircleAvatar with light background color', (WidgetTester tester) async {
    final Color backgroundColor = Colors.blue.shade100;
    await tester.pumpWidget(
      wrap(
46
        child: CircleAvatar(
47 48 49 50 51 52 53 54
          backgroundColor: backgroundColor,
          radius: 50.0,
          child: const Text('Z'),
        ),
      ),
    );

    final RenderConstrainedBox box = tester.renderObject(find.byType(CircleAvatar));
55
    expect(box.size, equals(const Size(100.0, 100.0)));
56
    final RenderDecoratedBox child = box.child! as RenderDecoratedBox;
57
    final BoxDecoration decoration = child.decoration as BoxDecoration;
58 59 60
    expect(decoration.color, equals(backgroundColor));

    final RenderParagraph paragraph = tester.renderObject(find.text('Z'));
61
    expect(paragraph.text.style!.color, equals(ThemeData.fallback().primaryColorDark));
62 63
  });

64 65 66
  testWidgets('CircleAvatar with image background', (WidgetTester tester) async {
    await tester.pumpWidget(
      wrap(
67 68
        child: CircleAvatar(
          backgroundImage: MemoryImage(Uint8List.fromList(kTransparentImage)),
69 70 71 72 73 74 75
          radius: 50.0,
        ),
      ),
    );

    final RenderConstrainedBox box = tester.renderObject(find.byType(CircleAvatar));
    expect(box.size, equals(const Size(100.0, 100.0)));
76
    final RenderDecoratedBox child = box.child! as RenderDecoratedBox;
77
    final BoxDecoration decoration = child.decoration as BoxDecoration;
78
    expect(decoration.image!.fit, equals(BoxFit.cover));
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 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125
  testWidgets('CircleAvatar with image foreground', (WidgetTester tester) async {
    await tester.pumpWidget(
      wrap(
        child: CircleAvatar(
          foregroundImage: MemoryImage(Uint8List.fromList(kBlueRectPng)),
          radius: 50.0,
        ),
      ),
    );

    final RenderConstrainedBox box = tester.renderObject(find.byType(CircleAvatar));
    expect(box.size, equals(const Size(100.0, 100.0)));
    final RenderDecoratedBox child = box.child! as RenderDecoratedBox;
    final BoxDecoration decoration = child.decoration as BoxDecoration;
    expect(decoration.image!.fit, equals(BoxFit.cover));
  });

  testWidgets('CircleAvatar backgroundImage is used as a fallback for foregroundImage', (WidgetTester tester) async {
    final ErrorImageProvider errorImage = ErrorImageProvider();
    bool caughtForegroundImageError = false;
    await tester.pumpWidget(
      wrap(
        child: RepaintBoundary(
          child: CircleAvatar(
          foregroundImage: errorImage,
          backgroundImage: MemoryImage(Uint8List.fromList(kBlueRectPng)),
          radius: 50.0,
          onForegroundImageError: (_,__) => caughtForegroundImageError = true,
          ),
        ),
      ),
    );

    expect(caughtForegroundImageError, true);
    final RenderConstrainedBox box = tester.renderObject(find.byType(CircleAvatar));
    expect(box.size, equals(const Size(100.0, 100.0)));
    final RenderDecoratedBox child = box.child! as RenderDecoratedBox;
    final BoxDecoration decoration = child.decoration as BoxDecoration;
    expect(decoration.image!.fit, equals(BoxFit.cover));
    await expectLater(
      find.byType(CircleAvatar),
      matchesGoldenFile('circle_avatar.fallback.png'),
    );
  });

126 127 128
  testWidgets('CircleAvatar with foreground color', (WidgetTester tester) async {
    final Color foregroundColor = Colors.red.shade100;
    await tester.pumpWidget(
Ian Hickson's avatar
Ian Hickson committed
129
      wrap(
130
        child: CircleAvatar(
131
          foregroundColor: foregroundColor,
132
          child: const Text('Z'),
133 134 135 136
        ),
      ),
    );

137
    final ThemeData fallback = ThemeData.fallback();
138 139

    final RenderConstrainedBox box = tester.renderObject(find.byType(CircleAvatar));
140
    expect(box.size, equals(const Size(40.0, 40.0)));
141
    final RenderDecoratedBox child = box.child! as RenderDecoratedBox;
142
    final BoxDecoration decoration = child.decoration as BoxDecoration;
143
    expect(decoration.color, equals(fallback.primaryColorDark));
144 145

    final RenderParagraph paragraph = tester.renderObject(find.text('Z'));
146
    expect(paragraph.text.style!.color, equals(foregroundColor));
147 148
  });

149 150
  testWidgets('CircleAvatar default colors', (WidgetTester tester) async {
    final ThemeData theme = ThemeData(useMaterial3: true);
151 152
    await tester.pumpWidget(
      wrap(
153
        child: Theme(
154 155
          data: theme,
          child: const CircleAvatar(
156
            child: Text('Z'),
157 158 159 160 161 162
          ),
        ),
      ),
    );

    final RenderConstrainedBox box = tester.renderObject(find.byType(CircleAvatar));
163
    final RenderDecoratedBox child = box.child! as RenderDecoratedBox;
164
    final BoxDecoration decoration = child.decoration as BoxDecoration;
165
    expect(decoration.color, equals(theme.colorScheme.primaryContainer));
166 167

    final RenderParagraph paragraph = tester.renderObject(find.text('Z'));
168
    expect(paragraph.text.style!.color, equals(theme.colorScheme.onPrimaryContainer));
169
  });
170 171 172 173 174

  testWidgets('CircleAvatar text does not expand with textScaleFactor', (WidgetTester tester) async {
    final Color foregroundColor = Colors.red.shade100;
    await tester.pumpWidget(
      wrap(
175
        child: CircleAvatar(
176 177 178 179 180 181
          foregroundColor: foregroundColor,
          child: const Text('Z'),
        ),
      ),
    );

182
    expect(tester.getSize(find.text('Z')), equals(const Size(16.0, 16.0)));
183 184 185

    await tester.pumpWidget(
      wrap(
186
        child: MediaQuery(
187 188
          data: const MediaQueryData(
            textScaleFactor: 2.0,
189
            size: Size(111.0, 111.0),
190
            devicePixelRatio: 1.1,
191 192
            padding: EdgeInsets.all(11.0),
          ),
193 194
          child: CircleAvatar(
            child: Builder(
195
              builder: (BuildContext context) {
196
                final MediaQueryData data = MediaQuery.of(context);
197 198 199 200 201 202 203 204 205

                // These should not change.
                expect(data.size, equals(const Size(111.0, 111.0)));
                expect(data.devicePixelRatio, equals(1.1));
                expect(data.padding, equals(const EdgeInsets.all(11.0)));

                // This should be overridden to 1.0.
                expect(data.textScaleFactor, equals(1.0));
                return const Text('Z');
206
              },
207
            ),
208 209 210 211
          ),
        ),
      ),
    );
212
    expect(tester.getSize(find.text('Z')), equals(const Size(16.0, 16.0)));
213
  });
214 215 216 217 218

  testWidgets('CircleAvatar respects minRadius', (WidgetTester tester) async {
    final Color backgroundColor = Colors.blue.shade900;
    await tester.pumpWidget(
      wrap(
219 220
        child: UnconstrainedBox(
          child: CircleAvatar(
221 222 223 224 225 226 227 228 229
            backgroundColor: backgroundColor,
            minRadius: 50.0,
            child: const Text('Z'),
          ),
        ),
      ),
    );

    final RenderConstrainedBox box = tester.renderObject(find.byType(CircleAvatar));
230
    expect(box.size, equals(const Size(100.0, 100.0)));
231
    final RenderDecoratedBox child = box.child! as RenderDecoratedBox;
232
    final BoxDecoration decoration = child.decoration as BoxDecoration;
233 234 235
    expect(decoration.color, equals(backgroundColor));

    final RenderParagraph paragraph = tester.renderObject(find.text('Z'));
236
    expect(paragraph.text.style!.color, equals(ThemeData.fallback().primaryColorLight));
237 238 239 240 241 242
  });

  testWidgets('CircleAvatar respects maxRadius', (WidgetTester tester) async {
    final Color backgroundColor = Colors.blue.shade900;
    await tester.pumpWidget(
      wrap(
243
        child: CircleAvatar(
244 245 246 247 248 249 250 251
          backgroundColor: backgroundColor,
          maxRadius: 50.0,
          child: const Text('Z'),
        ),
      ),
    );

    final RenderConstrainedBox box = tester.renderObject(find.byType(CircleAvatar));
252
    expect(box.size, equals(const Size(100.0, 100.0)));
253
    final RenderDecoratedBox child = box.child! as RenderDecoratedBox;
254
    final BoxDecoration decoration = child.decoration as BoxDecoration;
255 256 257
    expect(decoration.color, equals(backgroundColor));

    final RenderParagraph paragraph = tester.renderObject(find.text('Z'));
258
    expect(paragraph.text.style!.color, equals(ThemeData.fallback().primaryColorLight));
259 260 261 262 263 264
  });

  testWidgets('CircleAvatar respects setting both minRadius and maxRadius', (WidgetTester tester) async {
    final Color backgroundColor = Colors.blue.shade900;
    await tester.pumpWidget(
      wrap(
265
        child: CircleAvatar(
266 267 268 269 270 271 272 273 274
          backgroundColor: backgroundColor,
          maxRadius: 50.0,
          minRadius: 50.0,
          child: const Text('Z'),
        ),
      ),
    );

    final RenderConstrainedBox box = tester.renderObject(find.byType(CircleAvatar));
275
    expect(box.size, equals(const Size(100.0, 100.0)));
276
    final RenderDecoratedBox child = box.child! as RenderDecoratedBox;
277
    final BoxDecoration decoration = child.decoration as BoxDecoration;
278 279 280
    expect(decoration.color, equals(backgroundColor));

    final RenderParagraph paragraph = tester.renderObject(find.text('Z'));
281
    expect(paragraph.text.style!.color, equals(ThemeData.fallback().primaryColorLight));
282
  });
283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 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

  group('Material 2', () {
    // Tests that are only relevant for Material 2. Once ThemeData.useMaterial3
    // is turned on by default, these tests can be removed.

    testWidgets('CircleAvatar default colors with light theme', (WidgetTester tester) async {
      final ThemeData theme = ThemeData(
        primaryColor: Colors.grey.shade100,
        primaryColorBrightness: Brightness.light,
      );
      await tester.pumpWidget(
        wrap(
          child: Theme(
            data: theme,
            child: const CircleAvatar(
              child: Text('Z'),
            ),
          ),
        ),
      );

      final RenderConstrainedBox box = tester.renderObject(find.byType(CircleAvatar));
      final RenderDecoratedBox child = box.child! as RenderDecoratedBox;
      final BoxDecoration decoration = child.decoration as BoxDecoration;
      expect(decoration.color, equals(theme.primaryColorLight));

      final RenderParagraph paragraph = tester.renderObject(find.text('Z'));
      expect(paragraph.text.style!.color, equals(theme.primaryTextTheme.titleLarge!.color));
    });

    testWidgets('CircleAvatar default colors with dark theme', (WidgetTester tester) async {
      final ThemeData theme = ThemeData(
        primaryColor: Colors.grey.shade800,
        primaryColorBrightness: Brightness.dark,
      );
      await tester.pumpWidget(
        wrap(
          child: Theme(
            data: theme,
            child: const CircleAvatar(
              child: Text('Z'),
            ),
          ),
        ),
      );

      final RenderConstrainedBox box = tester.renderObject(find.byType(CircleAvatar));
      final RenderDecoratedBox child = box.child! as RenderDecoratedBox;
      final BoxDecoration decoration = child.decoration as BoxDecoration;
      expect(decoration.color, equals(theme.primaryColorDark));

      final RenderParagraph paragraph = tester.renderObject(find.text('Z'));
      expect(paragraph.text.style!.color, equals(theme.primaryTextTheme.titleLarge!.color));
    });
  });
338
}
Ian Hickson's avatar
Ian Hickson committed
339

340
Widget wrap({ required Widget child }) {
341
  return Directionality(
Ian Hickson's avatar
Ian Hickson committed
342
    textDirection: TextDirection.ltr,
343
    child: MediaQuery(
344
      data: const MediaQueryData(),
345
      child: Center(child: child),
346
    ),
Ian Hickson's avatar
Ian Hickson committed
347 348
  );
}