scaffold_test.dart 12.7 KB
Newer Older
1 2 3 4 5 6 7 8 9
// 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.

import 'package:flutter_test/flutter_test.dart';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';

void main() {
10
  testWidgets('Scaffold control test', (WidgetTester tester) async {
11
    final Key bodyKey = new UniqueKey();
12
    await tester.pumpWidget(new Scaffold(
13
      appBar: new AppBar(title: const Text('Title')),
14 15
      body: new Container(key: bodyKey)
    ));
16

17
    RenderBox bodyBox = tester.renderObject(find.byKey(bodyKey));
18
    expect(bodyBox.size, equals(const Size(800.0, 544.0)));
19

20
    await tester.pumpWidget(new MediaQuery(
21
      data: const MediaQueryData(padding: const EdgeInsets.only(bottom: 100.0)),
22
      child: new Scaffold(
23
        appBar: new AppBar(title: const Text('Title')),
24 25 26
        body: new Container(key: bodyKey)
      )
    ));
27

28
    bodyBox = tester.renderObject(find.byKey(bodyKey));
29
    expect(bodyBox.size, equals(const Size(800.0, 444.0)));
30

31
    await tester.pumpWidget(new MediaQuery(
32
      data: const MediaQueryData(padding: const EdgeInsets.only(bottom: 100.0)),
33
      child: new Scaffold(
34
        appBar: new AppBar(title: const Text('Title')),
35 36 37 38
        body: new Container(key: bodyKey),
        resizeToAvoidBottomPadding: false
      )
    ));
39

40
    bodyBox = tester.renderObject(find.byKey(bodyKey));
41
    expect(bodyBox.size, equals(const Size(800.0, 544.0)));
42
  });
43

44
  testWidgets('Scaffold large bottom padding test', (WidgetTester tester) async {
45
    final Key bodyKey = new UniqueKey();
46
    await tester.pumpWidget(new MediaQuery(
47
      data: const MediaQueryData(
48 49 50 51 52 53 54
        padding: const EdgeInsets.only(bottom: 700.0),
      ),
      child: new Scaffold(
        body: new Container(key: bodyKey),
      ),
    ));

55
    final RenderBox bodyBox = tester.renderObject(find.byKey(bodyKey));
56 57 58
    expect(bodyBox.size, equals(const Size(800.0, 0.0)));

    await tester.pumpWidget(new MediaQuery(
59
      data: const MediaQueryData(
60 61 62 63 64 65 66 67 68 69
        padding: const EdgeInsets.only(bottom: 500.0),
      ),
      child: new Scaffold(
        body: new Container(key: bodyKey),
      ),
    ));

    expect(bodyBox.size, equals(const Size(800.0, 100.0)));

    await tester.pumpWidget(new MediaQuery(
70
      data: const MediaQueryData(
71 72 73 74
        padding: const EdgeInsets.only(bottom: 580.0),
      ),
      child: new Scaffold(
        appBar: new AppBar(
75
          title: const Text('Title'),
76 77 78 79 80 81 82 83
        ),
        body: new Container(key: bodyKey),
      ),
    ));

    expect(bodyBox.size, equals(const Size(800.0, 0.0)));
  });

84 85
  testWidgets('Floating action animation', (WidgetTester tester) async {
    await tester.pumpWidget(new Scaffold(
86
      floatingActionButton: const FloatingActionButton(
87
        key: const Key('one'),
88
        onPressed: null,
89
        child: const Text("1")
90 91 92 93 94 95
      )
    ));

    expect(tester.binding.transientCallbackCount, 0);

    await tester.pumpWidget(new Scaffold(
96
      floatingActionButton: const FloatingActionButton(
97
        key: const Key('two'),
98
        onPressed: null,
99
        child: const Text("2")
100 101 102 103 104 105 106 107 108 109
      )
    ));

    expect(tester.binding.transientCallbackCount, greaterThan(0));
    await tester.pumpWidget(new Container());
    expect(tester.binding.transientCallbackCount, 0);
    await tester.pumpWidget(new Scaffold());
    expect(tester.binding.transientCallbackCount, 0);

    await tester.pumpWidget(new Scaffold(
110
      floatingActionButton: const FloatingActionButton(
111
        key: const Key('one'),
112
        onPressed: null,
113
        child: const Text("1")
114 115 116 117 118
      )
    ));

    expect(tester.binding.transientCallbackCount, greaterThan(0));
  });
119 120

  testWidgets('Drawer scrolling', (WidgetTester tester) async {
121
    final Key drawerKey = new UniqueKey();
122 123
    const double appBarHeight = 256.0;

124
    final ScrollController scrollOffset = new ScrollController();
125

126 127 128 129
    await tester.pumpWidget(
      new MaterialApp(
        home: new Scaffold(
          drawer: new Drawer(
130 131 132
            key: drawerKey,
            child: new ListView(
              controller: scrollOffset,
133 134 135 136 137
              children: new List<Widget>.generate(10,
                (int index) => new SizedBox(height: 100.0, child: new Text('D$index'))
              )
            )
          ),
138 139 140 141 142
          body: new CustomScrollView(
            slivers: <Widget>[
              new SliverAppBar(
                pinned: true,
                expandedHeight: appBarHeight,
143 144
                title: const Text('Title'),
                flexibleSpace: new FlexibleSpaceBar(title: const Text('Title')),
145 146 147
              ),
              new SliverPadding(
                padding: const EdgeInsets.only(top: appBarHeight),
148
                sliver: new SliverList(
149 150 151 152 153 154
                  delegate: new SliverChildListDelegate(new List<Widget>.generate(
                    10, (int index) => new SizedBox(height: 100.0, child: new Text('B$index')),
                  )),
                ),
              ),
            ],
155 156 157 158 159
          ),
        )
      )
    );

160
    final ScaffoldState state = tester.firstState(find.byType(Scaffold));
161 162 163 164 165
    state.openDrawer();

    await tester.pump();
    await tester.pump(const Duration(seconds: 1));

166
    expect(scrollOffset.offset, 0.0);
167 168

    const double scrollDelta = 80.0;
169
    await tester.drag(find.byKey(drawerKey), const Offset(0.0, -scrollDelta));
170 171
    await tester.pump();

172
    expect(scrollOffset.offset, scrollDelta);
173

174
    final RenderBox renderBox = tester.renderObject(find.byType(AppBar));
175 176
    expect(renderBox.size.height, equals(appBarHeight));
  });
177

178 179 180 181 182 183 184 185 186 187
  Widget _buildStatusBarTestApp(TargetPlatform platform) {
    return new MaterialApp(
      theme: new ThemeData(platform: platform),
      home: new MediaQuery(
        data: const MediaQueryData(padding: const EdgeInsets.only(top: 25.0)), // status bar
        child: new Scaffold(
          body: new CustomScrollView(
            primary: true,
            slivers: <Widget>[
              new SliverAppBar(
188
                title: const Text('Title')
189 190 191 192 193 194 195 196 197 198
              ),
              new SliverList(
                delegate: new SliverChildListDelegate(new List<Widget>.generate(
                  20, (int index) => new SizedBox(height: 100.0, child: new Text('$index')),
                )),
              ),
            ],
          ),
        ),
      ),
199
    );
200
  }
201

202 203
  testWidgets('Tapping the status bar scrolls to top on iOS', (WidgetTester tester) async {
    await tester.pumpWidget(_buildStatusBarTestApp(TargetPlatform.iOS));
Adam Barth's avatar
Adam Barth committed
204
    final ScrollableState scrollable = tester.state(find.byType(Scrollable));
205 206
    scrollable.position.jumpTo(500.0);
    expect(scrollable.position.pixels, equals(500.0));
207
    await tester.tapAt(const Point(100.0, 10.0));
208
    await tester.pumpAndSettle();
209
    expect(scrollable.position.pixels, equals(0.0));
210 211 212
  });

  testWidgets('Tapping the status bar does not scroll to top on Android', (WidgetTester tester) async {
213
    await tester.pumpWidget(_buildStatusBarTestApp(TargetPlatform.android));
Adam Barth's avatar
Adam Barth committed
214
    final ScrollableState scrollable = tester.state(find.byType(Scrollable));
215 216
    scrollable.position.jumpTo(500.0);
    expect(scrollable.position.pixels, equals(500.0));
217 218
    await tester.tapAt(const Point(100.0, 10.0));
    await tester.pump();
219
    await tester.pump(const Duration(seconds: 1));
220
    expect(scrollable.position.pixels, equals(500.0));
221
  });
222 223

  testWidgets('Bottom sheet cannot overlap app bar', (WidgetTester tester) async {
224
    final Key sheetKey = new UniqueKey();
225 226 227 228 229 230

    await tester.pumpWidget(
      new MaterialApp(
        theme: new ThemeData(platform: TargetPlatform.android),
        home: new Scaffold(
          appBar: new AppBar(
231
            title: const Text('Title'),
232 233 234 235 236
          ),
          body: new Builder(
            builder: (BuildContext context) {
              return new GestureDetector(
                onTap: () {
237
                  Scaffold.of(context).showBottomSheet<Null>((BuildContext context) {
238 239
                    return new Container(
                      key: sheetKey,
240
                      color: Colors.blue[500],
241 242 243
                    );
                  });
                },
244
                child: const Text('X'),
245
              );
246 247 248 249
            },
          ),
        ),
      ),
250 251 252 253 254 255
    );

    await tester.tap(find.text('X'));
    await tester.pump(); // start animation
    await tester.pump(const Duration(seconds: 1));

256 257
    final RenderBox appBarBox = tester.renderObject(find.byType(AppBar));
    final RenderBox sheetBox = tester.renderObject(find.byKey(sheetKey));
258

259 260
    final Point appBarBottomRight = appBarBox.localToGlobal(appBarBox.size.bottomRight(Point.origin));
    final Point sheetTopRight = sheetBox.localToGlobal(sheetBox.size.topRight(Point.origin));
261 262 263

    expect(appBarBottomRight, equals(sheetTopRight));
  });
264

265 266 267 268 269
  testWidgets('Persistent bottom buttons are persistent', (WidgetTester tester) async {
    bool didPressButton = false;
    await tester.pumpWidget(
      new MaterialApp(
        home: new Scaffold(
270
          body: new SingleChildScrollView(
271 272 273 274 275
            child: new Container(
              decoration: new BoxDecoration(
                backgroundColor: Colors.amber[500],
              ),
              height: 5000.0,
276
              child: const Text('body'),
277 278 279 280 281 282 283
            ),
          ),
          persistentFooterButtons: <Widget>[
            new FlatButton(
              onPressed: () {
                didPressButton = true;
              },
284
              child: const Text('X'),
285 286 287 288 289 290
            )
          ],
        ),
      ),
    );

291
    await tester.drag(find.text('body'), const Offset(0.0, -1000.0));
292 293 294 295 296
    expect(didPressButton, isFalse);
    await tester.tap(find.text('X'));
    expect(didPressButton, isTrue);
  });

297 298
  group('back arrow', () {
    Future<Null> expectBackIcon(WidgetTester tester, TargetPlatform platform, IconData expectedIcon) async {
299
      final GlobalKey rootKey = new GlobalKey();
300
      final Map<String, WidgetBuilder> routes = <String, WidgetBuilder>{
301
        '/': (_) => new Container(key: rootKey, child: const Text('Home')),
302 303
        '/scaffold': (_) => new Scaffold(
            appBar: new AppBar(),
304
            body: const Text('Scaffold'),
305 306 307 308 309 310 311 312 313 314
        )
      };
      await tester.pumpWidget(
        new MaterialApp(theme: new ThemeData(platform: platform), routes: routes)
      );

      Navigator.pushNamed(rootKey.currentContext, '/scaffold');
      await tester.pump();
      await tester.pump(const Duration(seconds: 1));

315
      final Icon icon = tester.widget(find.byType(Icon));
316 317 318 319 320 321 322 323 324 325 326 327 328 329 330
      expect(icon.icon, expectedIcon);
    }

    testWidgets('Back arrow uses correct default on Android', (WidgetTester tester) async {
      await expectBackIcon(tester, TargetPlatform.android, Icons.arrow_back);
    });

    testWidgets('Back arrow uses correct default on Fuchsia', (WidgetTester tester) async {
      await expectBackIcon(tester, TargetPlatform.fuchsia, Icons.arrow_back);
    });

    testWidgets('Back arrow uses correct default on iOS', (WidgetTester tester) async {
      await expectBackIcon(tester, TargetPlatform.iOS, Icons.arrow_back_ios);
    });
  });
331 332 333

  group('body size', () {
    testWidgets('body size with container', (WidgetTester tester) async {
334
      final Key testKey = new UniqueKey();
335 336 337 338
      await tester.pumpWidget(
        new Scaffold(body: new Container(key: testKey))
      );
      expect(tester.element(find.byKey(testKey)).size, const Size(800.0, 600.0));
339
      expect(tester.renderObject<RenderBox>(find.byKey(testKey)).localToGlobal(Point.origin), const Point(0.0, 0.0));
340 341 342
    });

    testWidgets('body size with sized container', (WidgetTester tester) async {
343
      final Key testKey = new UniqueKey();
344 345 346 347
      await tester.pumpWidget(
        new Scaffold(body: new Container(key: testKey, height: 100.0))
      );
      expect(tester.element(find.byKey(testKey)).size, const Size(800.0, 100.0));
348
      expect(tester.renderObject<RenderBox>(find.byKey(testKey)).localToGlobal(Point.origin), const Point(0.0, 0.0));
349 350 351
    });

    testWidgets('body size with centered container', (WidgetTester tester) async {
352
      final Key testKey = new UniqueKey();
353 354 355 356
      await tester.pumpWidget(
        new Scaffold(body: new Center(child: new Container(key: testKey)))
      );
      expect(tester.element(find.byKey(testKey)).size, const Size(800.0, 600.0));
357
      expect(tester.renderObject<RenderBox>(find.byKey(testKey)).localToGlobal(Point.origin), const Point(0.0, 0.0));
358 359 360
    });

    testWidgets('body size with button', (WidgetTester tester) async {
361
      final Key testKey = new UniqueKey();
362
      await tester.pumpWidget(
363
        new Scaffold(body: new FlatButton(key: testKey, onPressed: () { }, child: const Text('')))
364 365
      );
      expect(tester.element(find.byKey(testKey)).size, const Size(88.0, 36.0));
366
      expect(tester.renderObject<RenderBox>(find.byKey(testKey)).localToGlobal(Point.origin), const Point(0.0, 0.0));
367 368
    });
  });
369
}