box_decoration_test.dart 10.9 KB
Newer Older
Hixie's avatar
Hixie committed
1 2 3 4
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

5 6 7 8 9
import 'dart:async';
import 'dart:typed_data';
import 'dart:ui' as ui show Image;

import 'package:flutter/foundation.dart';
10
import 'package:flutter/material.dart';
11
import 'package:flutter/painting.dart';
12
import 'package:flutter/widgets.dart';
13
import 'package:flutter_test/flutter_test.dart';
14

15
import '../painting/image_data.dart';
16 17
import '../rendering/mock_canvas.dart';

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 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92
class TestImageProvider extends ImageProvider<TestImageProvider> {
  TestImageProvider(this.future);

  final Future<Null> future;

  static ui.Image image;

  @override
  Future<TestImageProvider> obtainKey(ImageConfiguration configuration) {
    return new SynchronousFuture<TestImageProvider>(this);
  }

  @override
  ImageStreamCompleter load(TestImageProvider key) {
    return new OneFrameImageStreamCompleter(
      future.then<ImageInfo>((Null value) => new ImageInfo(image: image))
    );
  }
}

Future<Null> main() async {
  TestImageProvider.image = await decodeImageFromList(new Uint8List.fromList(kTransparentImage));

  testWidgets('DecoratedBox handles loading images', (WidgetTester tester) async {
    final GlobalKey key = new GlobalKey();
    final Completer<Null> completer = new Completer<Null>();
    await tester.pumpWidget(
      new KeyedSubtree(
        key: key,
        child: new DecoratedBox(
          decoration: new BoxDecoration(
            image: new DecorationImage(
              image: new TestImageProvider(completer.future),
            ),
          ),
        ),
      ),
    );
    expect(tester.binding.hasScheduledFrame, isFalse);
    completer.complete();
    await tester.idle();
    expect(tester.binding.hasScheduledFrame, isTrue);
    await tester.pump();
    expect(tester.binding.hasScheduledFrame, isFalse);
  });

  testWidgets('Moving a DecoratedBox', (WidgetTester tester) async {
    final Completer<Null> completer = new Completer<Null>();
    final Widget subtree = new KeyedSubtree(
      key: new GlobalKey(),
      child: new RepaintBoundary(
        child: new DecoratedBox(
          decoration: new BoxDecoration(
            image: new DecorationImage(
              image: new TestImageProvider(completer.future),
            ),
          ),
        ),
      ),
    );
    await tester.pumpWidget(subtree);
    await tester.idle();
    expect(tester.binding.hasScheduledFrame, isFalse);
    await tester.pumpWidget(new Container(child: subtree));
    await tester.idle();
    expect(tester.binding.hasScheduledFrame, isFalse);
    completer.complete(); // schedules microtask, does not run it
    expect(tester.binding.hasScheduledFrame, isFalse);
    await tester.idle(); // runs microtask
    expect(tester.binding.hasScheduledFrame, isTrue);
    await tester.pump();
    await tester.idle();
    expect(tester.binding.hasScheduledFrame, isFalse);
  });

93 94
  testWidgets('Circles can have uniform borders', (WidgetTester tester) async {
    await tester.pumpWidget(
95
      new Container(
96
        padding: const EdgeInsets.all(50.0),
97 98 99
        decoration: new BoxDecoration(
          shape: BoxShape.circle,
          border: new Border.all(width: 10.0, color: const Color(0x80FF00FF)),
100
          color: Colors.teal[600]
101
        )
102 103
      )
    );
104
  });
105

106
  testWidgets('Bordered Container insets its child', (WidgetTester tester) async {
107
    const Key key = const Key('outerContainer');
108
    await tester.pumpWidget(
109 110 111 112
      new Center(
        child: new Container(
          key: key,
          decoration: new BoxDecoration(border: new Border.all(width: 10.0)),
113
          child: new Container(
114 115
            width: 25.0,
            height: 25.0
116 117
          )
        )
118 119 120
      )
    );
    expect(tester.getSize(find.byKey(key)), equals(const Size(45.0, 45.0)));
121
  });
122 123 124 125

  testWidgets('BoxDecoration paints its border correctly', (WidgetTester tester) async {
    // Regression test for https://github.com/flutter/flutter/issues/7672

126
    const Key key = const Key('Container with BoxDecoration');
127 128 129 130 131 132 133 134 135 136 137
    Widget buildFrame(Border border) {
      return new Center(
        child: new Container(
          key: key,
          width: 100.0,
          height: 50.0,
          decoration: new BoxDecoration(border: border),
        ),
      );
    }

138
    const Color black = const Color(0xFF000000);
139 140 141

    await tester.pumpWidget(buildFrame(new Border.all()));
    expect(find.byKey(key), paints
142
      ..rect(color: black, style: PaintingStyle.stroke, strokeWidth: 1.0));
143 144 145

    await tester.pumpWidget(buildFrame(new Border.all(width: 0.0)));
    expect(find.byKey(key), paints
146
      ..rect(color: black, style: PaintingStyle.stroke, strokeWidth: 0.0));
147

148 149
    const Color green = const Color(0xFF00FF00);
    const BorderSide greenSide = const BorderSide(color: green, width: 10.0);
150

151
    await tester.pumpWidget(buildFrame(const Border(top: greenSide)));
152 153
    expect(find.byKey(key), paints..path(color: green, style: PaintingStyle.fill));

154
    await tester.pumpWidget(buildFrame(const Border(left: greenSide)));
155 156
    expect(find.byKey(key), paints..path(color: green, style: PaintingStyle.fill));

157
    await tester.pumpWidget(buildFrame(const Border(right: greenSide)));
158 159
    expect(find.byKey(key), paints..path(color: green, style: PaintingStyle.fill));

160
    await tester.pumpWidget(buildFrame(const Border(bottom: greenSide)));
161
    expect(find.byKey(key), paints..path(color: green, style: PaintingStyle.fill));
162

163 164
    const Color blue = const Color(0xFF0000FF);
    const BorderSide blueSide = const BorderSide(color: blue, width: 0.0);
165

166
    await tester.pumpWidget(buildFrame(const Border(top: blueSide, right: greenSide, bottom: greenSide)));
167 168 169 170
    expect(find.byKey(key), paints
      ..path() // There's not much point checking the arguments to these calls because paintBorder
      ..path() // reuses the same Paint object each time, configured differently, and so they will
      ..path()); // all appear to have the same settings here (that of the last call).
171 172
  });

173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 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
  testWidgets('BoxDecoration paints its border correctly', (WidgetTester tester) async {
    // Regression test for https://github.com/flutter/flutter/issues/12165
    await tester.pumpWidget(
      new Column(
        children: <Widget>[
          new Container(
            // There's not currently a way to verify that this paints the same size as the others,
            // so the pattern below just asserts that there's four paths but doesn't check the geometry.
            width: 100.0,
            height: 100.0,
            decoration: const BoxDecoration(
              border: const Border(
                top: const BorderSide(
                  width: 10.0,
                  color: const Color(0xFFEEEEEE),
                ),
                left: const BorderSide(
                  width: 10.0,
                  color: const Color(0xFFFFFFFF),
                ),
                right: const BorderSide(
                  width: 10.0,
                  color: const Color(0xFFFFFFFF),
                ),
                bottom: const BorderSide(
                  width: 10.0,
                  color: const Color(0xFFFFFFFF),
                ),
              ),
            ),
          ),
          new Container(
            width: 100.0,
            height: 100.0,
            decoration: new BoxDecoration(
              border: new Border.all(
                width: 10.0,
                color: const Color(0xFFFFFFFF),
              ),
            ),
          ),
          new Container(
            width: 100.0,
            height: 100.0,
            decoration: new BoxDecoration(
              border: new Border.all(
                width: 10.0,
                color: const Color(0xFFFFFFFF),
              ),
              borderRadius: const BorderRadius.only(
                topRight: const Radius.circular(10.0),
              ),
            ),
          ),
          new Container(
            width: 100.0,
            height: 100.0,
            decoration: new BoxDecoration(
              border: new Border.all(
                width: 10.0,
                color: const Color(0xFFFFFFFF),
              ),
              shape: BoxShape.circle,
            ),
          ),
        ],
      ),
    );
    expect(find.byType(Column), paints
      ..path()
      ..path()
      ..path()
      ..path()
      ..rect(rect: new Rect.fromLTRB(355.0, 105.0, 445.0, 195.0))
      ..drrect(
        outer: new RRect.fromLTRBAndCorners(
          350.0, 200.0, 450.0, 300.0,
          topLeft: Radius.zero,
          topRight: const Radius.circular(10.0),
          bottomRight: Radius.zero,
          bottomLeft: Radius.zero,
        ),
        inner: new RRect.fromLTRBAndCorners(
          360.0, 210.0, 440.0, 290.0,
          topLeft: const Radius.circular(-10.0),
          topRight: Radius.zero,
          bottomRight: const Radius.circular(-10.0),
          bottomLeft: const Radius.circular(-10.0),
        ),
      )
      ..circle(x: 400.0, y: 350.0, radius: 45.0)
    );
  });
266 267 268 269 270

  testWidgets('Can hit test on BoxDecoration', (WidgetTester tester) async {

    List<int> itemsTapped;

271
    const Key key = const Key('Container with BoxDecoration');
272 273 274
    Widget buildFrame(Border border) {
      itemsTapped = <int>[];
      return new Center(
275 276 277
        child: new GestureDetector(
          behavior: HitTestBehavior.deferToChild,
          child: new Container(
278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300
            key: key,
            width: 100.0,
            height: 50.0,
            decoration: new BoxDecoration(border: border),
          ),
          onTap: () {
            itemsTapped.add(1);
          },
        )
      );
    }

    await tester.pumpWidget(buildFrame(new Border.all()));
    expect(itemsTapped, isEmpty);

    await tester.tap(find.byKey(key));
    expect(itemsTapped, <int>[1]);

    await tester.tapAt(const Offset(350.0, 275.0));
    expect(itemsTapped, <int>[1,1]);

    await tester.tapAt(const Offset(449.0, 324.0));
    expect(itemsTapped, <int>[1,1,1]);
301

302 303 304 305 306 307
  });

  testWidgets('Can hit test on BoxDecoration circle', (WidgetTester tester) async {

    List<int> itemsTapped;

308
    const Key key = const Key('Container with BoxDecoration');
309 310 311
    Widget buildFrame(Border border) {
      itemsTapped = <int>[];
      return new Center(
312
        child: new GestureDetector(
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
            behavior: HitTestBehavior.deferToChild,
            child: new Container(
            key: key,
            width: 100.0,
            height: 50.0,
            decoration: new BoxDecoration(border: border, shape: BoxShape.circle),
          ),
          onTap: () {
            itemsTapped.add(1);
          },
        )
      );
    }

    await tester.pumpWidget(buildFrame(new Border.all()));
    expect(itemsTapped, isEmpty);

    await tester.tapAt(const Offset(0.0, 0.0));
    expect(itemsTapped, isEmpty);

    await tester.tapAt(const Offset(350.0, 275.0));
    expect(itemsTapped, isEmpty);

    await tester.tapAt(const Offset(400.0, 300.0));
    expect(itemsTapped, <int>[1]);

    await tester.tap(find.byKey(key));
    expect(itemsTapped, <int>[1,1]);
341

342 343
  });

344
}