@@ -153,6 +153,185 @@ void main() {
153
153
},
154
154
);
155
155
156
+ testWidgets (
157
+ 'showModal builds a new route with specified barrier properties '
158
+ 'with default configuration(FadeScaleTransitionConfiguration)' ,
159
+ (WidgetTester tester) async {
160
+ await tester.pumpWidget (
161
+ MaterialApp (
162
+ home: Scaffold (
163
+ body: Builder (builder: (BuildContext context) {
164
+ return Center (
165
+ child: RaisedButton (
166
+ onPressed: () {
167
+ showModal <void >(
168
+ context: context,
169
+ builder: (BuildContext context) {
170
+ return const _FlutterLogoModal ();
171
+ },
172
+ );
173
+ },
174
+ child: const Icon (Icons .add),
175
+ ),
176
+ );
177
+ }),
178
+ ),
179
+ ),
180
+ );
181
+ await tester.tap (find.byType (RaisedButton ));
182
+ await tester.pumpAndSettle ();
183
+
184
+ // New route containing _FlutterLogoModal is present.
185
+ expect (find.byType (_FlutterLogoModal ), findsOneWidget);
186
+ final ModalBarrier topModalBarrier = tester.widget <ModalBarrier >(
187
+ find.byType (ModalBarrier ).at (1 ),
188
+ );
189
+
190
+ // Verify new route's modal barrier properties are correct.
191
+ expect (topModalBarrier.color, Colors .black54);
192
+ expect (topModalBarrier.barrierSemanticsDismissible, true );
193
+ expect (topModalBarrier.semanticsLabel, 'Dismiss' );
194
+ },
195
+ );
196
+
197
+ testWidgets (
198
+ 'showModal forwards animation '
199
+ 'with default configuration(FadeScaleTransitionConfiguration)' ,
200
+ (WidgetTester tester) async {
201
+ final GlobalKey key = GlobalKey ();
202
+ await tester.pumpWidget (
203
+ MaterialApp (
204
+ home: Scaffold (
205
+ body: Builder (builder: (BuildContext context) {
206
+ return Center (
207
+ child: RaisedButton (
208
+ onPressed: () {
209
+ showModal <void >(
210
+ context: context,
211
+ builder: (BuildContext context) {
212
+ return _FlutterLogoModal (key: key);
213
+ },
214
+ );
215
+ },
216
+ child: const Icon (Icons .add),
217
+ ),
218
+ );
219
+ }),
220
+ ),
221
+ ),
222
+ );
223
+
224
+ // Start forwards animation
225
+ await tester.tap (find.byType (RaisedButton ));
226
+ await tester.pump ();
227
+
228
+ // Opacity duration: First 30% of 150ms, linear transition
229
+ double topFadeTransitionOpacity = _getOpacity (key, tester);
230
+ double topScale = _getScale (key, tester);
231
+ expect (topFadeTransitionOpacity, 0.0 );
232
+ expect (topScale, 0.80 );
233
+
234
+ // 3/10 * 150ms = 45ms (total opacity animation duration)
235
+ // 1/2 * 45ms = ~23ms elapsed for halfway point of opacity
236
+ // animation
237
+ await tester.pump (const Duration (milliseconds: 23 ));
238
+ topFadeTransitionOpacity = _getOpacity (key, tester);
239
+ expect (topFadeTransitionOpacity, closeTo (0.5 , 0.05 ));
240
+ topScale = _getScale (key, tester);
241
+ expect (topScale, greaterThan (0.80 ));
242
+ expect (topScale, lessThan (1.0 ));
243
+
244
+ // End of opacity animation.
245
+ await tester.pump (const Duration (milliseconds: 22 ));
246
+ topFadeTransitionOpacity = _getOpacity (key, tester);
247
+ expect (topFadeTransitionOpacity, 1.0 );
248
+ topScale = _getScale (key, tester);
249
+ expect (topScale, greaterThan (0.80 ));
250
+ expect (topScale, lessThan (1.0 ));
251
+
252
+ // 100ms into the animation
253
+ await tester.pump (const Duration (milliseconds: 55 ));
254
+ topScale = _getScale (key, tester);
255
+ expect (topScale, greaterThan (0.80 ));
256
+ expect (topScale, lessThan (1.0 ));
257
+
258
+ // Get to the end of the animation
259
+ await tester.pump (const Duration (milliseconds: 50 ));
260
+ topScale = _getScale (key, tester);
261
+ expect (topScale, 1.0 );
262
+
263
+ await tester.pump (const Duration (milliseconds: 1 ));
264
+ expect (find.byType (_FlutterLogoModal ), findsOneWidget);
265
+ },
266
+ );
267
+
268
+ testWidgets (
269
+ 'showModal reverse animation '
270
+ 'with default configuration(FadeScaleTransitionConfiguration)' ,
271
+ (WidgetTester tester) async {
272
+ final GlobalKey key = GlobalKey ();
273
+ await tester.pumpWidget (
274
+ MaterialApp (
275
+ home: Scaffold (
276
+ body: Builder (builder: (BuildContext context) {
277
+ return Center (
278
+ child: RaisedButton (
279
+ onPressed: () {
280
+ showModal <void >(
281
+ context: context,
282
+ builder: (BuildContext context) {
283
+ return _FlutterLogoModal (key: key);
284
+ },
285
+ );
286
+ },
287
+ child: const Icon (Icons .add),
288
+ ),
289
+ );
290
+ }),
291
+ ),
292
+ ),
293
+ );
294
+
295
+ // Start forwards animation
296
+ await tester.tap (find.byType (RaisedButton ));
297
+ await tester.pumpAndSettle ();
298
+ expect (find.byType (_FlutterLogoModal ), findsOneWidget);
299
+
300
+ // Tap on modal barrier to start reverse animation.
301
+ await tester.tapAt (Offset .zero);
302
+ await tester.pump ();
303
+
304
+ // Opacity duration: Linear transition throughout 75ms
305
+ // No scale animations on exit transition.
306
+ double topFadeTransitionOpacity = _getOpacity (key, tester);
307
+ double topScale = _getScale (key, tester);
308
+ expect (topFadeTransitionOpacity, 1.0 );
309
+ expect (topScale, 1.0 );
310
+
311
+ await tester.pump (const Duration (milliseconds: 25 ));
312
+ topFadeTransitionOpacity = _getOpacity (key, tester);
313
+ topScale = _getScale (key, tester);
314
+ expect (topFadeTransitionOpacity, closeTo (0.66 , 0.05 ));
315
+ expect (topScale, 1.0 );
316
+
317
+ await tester.pump (const Duration (milliseconds: 25 ));
318
+ topFadeTransitionOpacity = _getOpacity (key, tester);
319
+ topScale = _getScale (key, tester);
320
+ expect (topFadeTransitionOpacity, closeTo (0.33 , 0.05 ));
321
+ expect (topScale, 1.0 );
322
+
323
+ // End of opacity animation
324
+ await tester.pump (const Duration (milliseconds: 25 ));
325
+ topFadeTransitionOpacity = _getOpacity (key, tester);
326
+ expect (topFadeTransitionOpacity, 0.0 );
327
+ topScale = _getScale (key, tester);
328
+ expect (topScale, 1.0 );
329
+
330
+ await tester.pump (const Duration (milliseconds: 1 ));
331
+ expect (find.byType (_FlutterLogoModal ), findsNothing);
332
+ },
333
+ );
334
+
156
335
testWidgets (
157
336
'State is not lost when transitioning' ,
158
337
(WidgetTester tester) async {
@@ -290,6 +469,17 @@ double _getOpacity(GlobalKey key, WidgetTester tester) {
290
469
});
291
470
}
292
471
472
+ double _getScale (GlobalKey key, WidgetTester tester) {
473
+ final Finder finder = find.ancestor (
474
+ of: find.byKey (key),
475
+ matching: find.byType (ScaleTransition ),
476
+ );
477
+ return tester.widgetList (finder).fold <double >(1.0 , (double a, Widget widget) {
478
+ final ScaleTransition transition = widget;
479
+ return a * transition.scale.value;
480
+ });
481
+ }
482
+
293
483
class _FlutterLogoModal extends StatefulWidget {
294
484
const _FlutterLogoModal ({
295
485
Key key,
0 commit comments