dialog_test.dart 11.6 KB
Newer Older
1 2 3 4
// Copyright 2016 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
import 'dart:ui';

7 8
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
9 10 11
import 'package:matcher/matcher.dart';

import '../widgets/semantics_tester.dart';
12 13 14 15 16 17 18 19 20 21 22 23

void main() {
  testWidgets('Dialog is scrollable', (WidgetTester tester) async {
    bool didPressOk = false;

    await tester.pumpWidget(
      new MaterialApp(
        home: new Material(
          child: new Builder(
            builder: (BuildContext context) {
              return new Center(
                child: new RaisedButton(
24
                  child: const Text('X'),
25
                  onPressed: () {
26
                    showDialog<void>(
27
                      context: context,
28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
                      builder: (BuildContext context) {
                        return new AlertDialog(
                          content: new Container(
                            height: 5000.0,
                            width: 300.0,
                            color: Colors.green[500],
                          ),
                          actions: <Widget>[
                            new FlatButton(
                              onPressed: () {
                                didPressOk = true;
                              },
                              child: const Text('OK')
                            )
                          ],
                        );
                      },
45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62
                    );
                  }
                )
              );
            }
          )
        )
      )
    );

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

    expect(didPressOk, false);
    await tester.tap(find.text('OK'));
    expect(didPressOk, true);
  });
63

64 65 66 67 68 69 70 71 72 73
  testWidgets('Dialog background color', (WidgetTester tester) async {

    await tester.pumpWidget(
      new MaterialApp(
        theme: new ThemeData(brightness: Brightness.dark),
        home: new Material(
          child: new Builder(
            builder: (BuildContext context) {
              return new Center(
                child: new RaisedButton(
74
                  child: const Text('X'),
75
                  onPressed: () {
76
                    showDialog<void>(
77
                      context: context,
78 79
                      builder: (BuildContext context) {
                        return const AlertDialog(
80 81 82
                          title: const Text('Title'),
                          content: const Text('Y'),
                          actions: const <Widget>[ ],
83 84
                        );
                      },
85
                    );
86 87
                  },
                ),
88
              );
89 90 91 92
            },
          ),
        ),
      ),
93 94 95 96 97 98
    );

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

99
    final StatefulElement widget = tester.element(find.byType(Material).last);
100
    final Material materialWidget = widget.state.widget;
101
    //first and second expect check that the material is the dialog's one
102 103 104
    expect(materialWidget.type, MaterialType.card);
    expect(materialWidget.elevation, 24);
    expect(materialWidget.color, Colors.grey[800]);
105
  });
106 107 108 109

  testWidgets('Simple dialog control test', (WidgetTester tester) async {
    await tester.pumpWidget(
      new MaterialApp(
110
        home: const Material(
111 112
          child: const Center(
            child: const RaisedButton(
113
              onPressed: null,
114
              child: const Text('Go'),
115 116 117 118 119 120
            ),
          ),
        ),
      ),
    );

121
    final BuildContext context = tester.element(find.text('Go'));
122

123
    final Future<int> result = showDialog<int>(
124
      context: context,
125 126 127 128 129 130 131 132 133 134 135
      builder: (BuildContext context) {
        return new SimpleDialog(
          title: const Text('Title'),
          children: <Widget>[
            new SimpleDialogOption(
              onPressed: () {
                Navigator.pop(context, 42);
              },
              child: const Text('First option'),
            ),
            const SimpleDialogOption(
136
              child: const Text('Second option'),
137 138 139 140
            ),
          ],
        );
      },
141 142
    );

143
    await tester.pumpAndSettle(const Duration(seconds: 1));
144 145 146 147 148
    expect(find.text('Title'), findsOneWidget);
    await tester.tap(find.text('First option'));

    expect(await result, equals(42));
  });
149

150
  testWidgets('Barrier dismissible', (WidgetTester tester) async {
151 152
    await tester.pumpWidget(
      new MaterialApp(
153
        home: const Material(
154 155
          child: const Center(
            child: const RaisedButton(
156
              onPressed: null,
157
              child: const Text('Go'),
158 159 160 161 162 163
            ),
          ),
        ),
      ),
    );

164
    final BuildContext context = tester.element(find.text('Go'));
165

166
    showDialog<void>(
167
      context: context,
168 169 170 171 172 173 174 175
      builder: (BuildContext context) {
        return new Container(
          width: 100.0,
          height: 100.0,
          alignment: Alignment.center,
          child: const Text('Dialog1'),
        );
      },
176 177
    );

178
    await tester.pumpAndSettle(const Duration(seconds: 1));
179 180 181
    expect(find.text('Dialog1'), findsOneWidget);

    // Tap on the barrier.
182
    await tester.tapAt(const Offset(10.0, 10.0));
183

184
    await tester.pumpAndSettle(const Duration(seconds: 1));
185 186
    expect(find.text('Dialog1'), findsNothing);

187
    showDialog<void>(
188
      context: context,
189
      barrierDismissible: false,
190 191 192 193 194 195 196 197
      builder: (BuildContext context) {
        return new Container(
          width: 100.0,
          height: 100.0,
          alignment: Alignment.center,
          child: const Text('Dialog2'),
        );
      },
198 199
    );

200
    await tester.pumpAndSettle(const Duration(seconds: 1));
201 202 203
    expect(find.text('Dialog2'), findsOneWidget);

    // Tap on the barrier, which shouldn't do anything this time.
204
    await tester.tapAt(const Offset(10.0, 10.0));
205

206
    await tester.pumpAndSettle(const Duration(seconds: 1));
207 208 209
    expect(find.text('Dialog2'), findsOneWidget);

  });
210 211 212 213 214 215 216

  testWidgets('Dialog hides underlying semantics tree', (WidgetTester tester) async {
    final SemanticsTester semantics = new SemanticsTester(tester);
    const String buttonText = 'A button covered by dialog overlay';
    await tester.pumpWidget(
      new MaterialApp(
        home: const Material(
217 218
          child: const Center(
            child: const RaisedButton(
219
              onPressed: null,
220
              child: const Text(buttonText),
221 222 223 224 225 226
            ),
          ),
        ),
      ),
    );

227
    expect(semantics, includesNodeWith(label: buttonText));
228 229 230 231

    final BuildContext context = tester.element(find.text(buttonText));

    const String alertText = 'A button in an overlay alert';
232
    showDialog<void>(
233
      context: context,
234
      builder: (BuildContext context) {
235
        return const AlertDialog(title: const Text(alertText));
236
      },
237 238 239 240
    );

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

241 242
    expect(semantics, includesNodeWith(label: alertText));
    expect(semantics, isNot(includesNodeWith(label: buttonText)));
243 244 245

    semantics.dispose();
  });
246

247
  testWidgets('Dialogs removes MediaQuery padding and view insets', (WidgetTester tester) async {
248
    BuildContext outerContext;
249
    BuildContext routeContext;
250 251
    BuildContext dialogContext;

252 253
    await tester.pumpWidget(new Localizations(
      locale: const Locale('en', 'US'),
254
      delegates: const <LocalizationsDelegate<dynamic>>[
255 256 257
        DefaultWidgetsLocalizations.delegate,
        DefaultMaterialLocalizations.delegate,
      ],
258
      child: new MediaQuery(
259
        data: const MediaQueryData(
260 261
          padding: const EdgeInsets.all(50.0),
          viewInsets: const EdgeInsets.only(left: 25.0, bottom: 75.0),
262
        ),
263 264
        child: new Navigator(
          onGenerateRoute: (_) {
265
            return new PageRouteBuilder<void>(
266 267 268 269 270 271
              pageBuilder: (BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation) {
                outerContext = context;
                return new Container();
              },
            );
          },
272
        ),
273
      ),
274 275
    ));

276
    showDialog<void>(
277
      context: outerContext,
278
      barrierDismissible: false,
279
      builder: (BuildContext context) {
280 281 282 283 284 285 286 287 288
        routeContext = context;
        return new Dialog(
          child: new Builder(
            builder: (BuildContext context) {
              dialogContext = context;
              return const Placeholder();
            },
          ),
        );
289
      },
290 291 292 293
    );

    await tester.pump();

294
    expect(MediaQuery.of(outerContext).padding, const EdgeInsets.all(50.0));
295
    expect(MediaQuery.of(routeContext).padding, EdgeInsets.zero);
296
    expect(MediaQuery.of(dialogContext).padding, EdgeInsets.zero);
297 298 299 300 301 302 303 304
    expect(MediaQuery.of(outerContext).viewInsets, const EdgeInsets.only(left: 25.0, bottom: 75.0));
    expect(MediaQuery.of(routeContext).viewInsets, const EdgeInsets.only(left: 25.0, bottom: 75.0));
    expect(MediaQuery.of(dialogContext).viewInsets, EdgeInsets.zero);
  });

  testWidgets('Dialog widget insets by viewInsets', (WidgetTester tester) async {
    await tester.pumpWidget(
      const MediaQuery(
305 306
        data: const MediaQueryData(
          viewInsets: const EdgeInsets.fromLTRB(10.0, 20.0, 30.0, 40.0),
307
        ),
308 309
        child: const Dialog(
          child: const Placeholder(),
310 311 312 313 314 315 316 317 318
        ),
      ),
    );
    expect(
      tester.getRect(find.byType(Placeholder)),
      new Rect.fromLTRB(10.0 + 40.0, 20.0 + 24.0, 800.0 - (40.0 + 30.0), 600.0 - (24.0 + 40.0)),
    );
    await tester.pumpWidget(
      const MediaQuery(
319 320
        data: const MediaQueryData(
          viewInsets: const EdgeInsets.fromLTRB(0.0, 0.0, 0.0, 0.0),
321
        ),
322 323
        child: const Dialog(
          child: const Placeholder(),
324 325 326 327 328 329 330 331 332 333 334 335
        ),
      ),
    );
    expect( // no change because this is an animation
      tester.getRect(find.byType(Placeholder)),
      new Rect.fromLTRB(10.0 + 40.0, 20.0 + 24.0, 800.0 - (40.0 + 30.0), 600.0 - (24.0 + 40.0)),
    );
    await tester.pump(const Duration(seconds: 1));
    expect( // animation finished
      tester.getRect(find.byType(Placeholder)),
      new Rect.fromLTRB(40.0, 24.0, 800.0 - 40.0, 600.0 - 24.0),
    );
336
  });
337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352

  testWidgets('Dialog widget contains route semantics from title', (WidgetTester tester) async {
    final SemanticsTester semantics = new SemanticsTester(tester);
    await tester.pumpWidget(
      new MaterialApp(
        home: new Material(
          child: new Builder(
            builder: (BuildContext context) {
              return new Center(
                child: new RaisedButton(
                  child: const Text('X'),
                  onPressed: () {
                    showDialog<void>(
                      context: context,
                      builder: (BuildContext context) {
                        return const AlertDialog(
353 354 355
                          title: const Text('Title'),
                          content: const Text('Y'),
                          actions: const <Widget>[],
356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383
                        );
                      },
                    );
                  },
                ),
              );
            },
          ),
        ),
      ),
    );

    expect(semantics, isNot(includesNodeWith(
        label: 'Title',
        flags: <SemanticsFlag>[SemanticsFlag.namesRoute]
    )));

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

    expect(semantics, includesNodeWith(
      label: 'Title',
      flags: <SemanticsFlag>[SemanticsFlag.namesRoute],
    ));

    semantics.dispose();
  });
384
}