From ae5c3d5f89abf3eb0cb72b6e65db76a652dfa1c4 Mon Sep 17 00:00:00 2001 From: Ian Hickson Date: Tue, 1 Aug 2017 14:23:44 -0700 Subject: [PATCH] Revert "Revert "Always evaluate the finder in `driver.waitFor*()`" (#11451)" (#11462) This reverts commit 5d9db106db23d14e22a9c326d97d50fb1fcdc4d7. --- dev/integration_tests/ui/lib/driver.dart | 57 +++++++++++++ .../ui/test_driver/driver_test.dart | 81 +++++++++++++++++++ .../flutter_driver/lib/src/extension.dart | 10 +-- 3 files changed, 142 insertions(+), 6 deletions(-) create mode 100644 dev/integration_tests/ui/lib/driver.dart create mode 100644 dev/integration_tests/ui/test_driver/driver_test.dart diff --git a/dev/integration_tests/ui/lib/driver.dart b/dev/integration_tests/ui/lib/driver.dart new file mode 100644 index 00000000000..b4625518ba6 --- /dev/null +++ b/dev/integration_tests/ui/lib/driver.dart @@ -0,0 +1,57 @@ +// Copyright 2017 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/material.dart'; +import 'package:flutter/widgets.dart'; +import 'package:flutter_driver/driver_extension.dart'; + +void main() { + enableFlutterDriverExtension(); + runApp(new DriverTestApp()); +} + +class DriverTestApp extends StatefulWidget { + @override + State createState() { + return new DriverTestAppState(); + } +} + +class DriverTestAppState extends State { + bool present = true; + + @override + Widget build(BuildContext context) { + return new MaterialApp( + home: new Scaffold( + appBar: new AppBar( + title: const Text('FlutterDriver test'), + ), + body: new ListView( + padding: const EdgeInsets.all(5.0), + children: [ + new Row( + children: [ + new Expanded( + child: new Text(present ? 'present' : 'absent'), + ), + new RaisedButton( + child: const Text( + 'toggle', + key: const ValueKey('togglePresent'), + ), + onPressed: () { + setState(() { + present = !present; + }); + }, + ), + ], + ), + ], + ), + ), + ); + } +} diff --git a/dev/integration_tests/ui/test_driver/driver_test.dart b/dev/integration_tests/ui/test_driver/driver_test.dart new file mode 100644 index 00000000000..b44ba955c20 --- /dev/null +++ b/dev/integration_tests/ui/test_driver/driver_test.dart @@ -0,0 +1,81 @@ +// Copyright 2017 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 'dart:async'; + +import 'package:flutter_driver/flutter_driver.dart'; +import 'package:test/test.dart'; + +void main() { + group('FlutterDriver', () { + final SerializableFinder presentText = find.text('present'); + FlutterDriver driver; + + setUpAll(() async { + driver = await FlutterDriver.connect(); + }); + + tearDownAll(() async { + await driver.close(); + }); + + test('waitFor should find text "present"', () async { + await driver.waitFor(presentText); + }); + + test('waitForAbsent should time out waiting for text "present" to disappear', () async { + try { + await driver.waitForAbsent(presentText, timeout: const Duration(seconds: 1)); + fail('expected DriverError'); + } on DriverError catch (error) { + expect(error.message, contains('Timeout while executing waitForAbsent')); + } + }); + + test('waitForAbsent should resolve when text "present" disappears', () async { + // Begin waiting for it to disappear + final Completer whenWaitForAbsentResolves = new Completer(); + driver.waitForAbsent(presentText).then( + whenWaitForAbsentResolves.complete, + onError: whenWaitForAbsentResolves.completeError, + ); + + // Wait 1 second then make it disappear + await new Future.delayed(const Duration(seconds: 1)); + await driver.tap(find.byValueKey('togglePresent')); + + // Ensure waitForAbsent resolves + await whenWaitForAbsentResolves.future; + }); + + test('waitFor times out waiting for "present" to reappear', () async { + try { + await driver.waitFor(presentText, timeout: const Duration(seconds: 1)); + fail('expected DriverError'); + } on DriverError catch (error) { + expect(error.message, contains('Timeout while executing waitFor')); + } + }); + + test('waitFor should resolve when text "present" reappears', () async { + // Begin waiting for it to reappear + final Completer whenWaitForResolves = new Completer(); + driver.waitFor(presentText).then( + whenWaitForResolves.complete, + onError: whenWaitForResolves.completeError, + ); + + // Wait 1 second then make it appear + await new Future.delayed(const Duration(seconds: 1)); + await driver.tap(find.byValueKey('togglePresent')); + + // Ensure waitFor resolves + await whenWaitForResolves.future; + }); + + test('waitForAbsent resolves immediately when the element does not exist', () async { + await driver.waitForAbsent(find.text('that does not exist')); + }); + }); +} diff --git a/packages/flutter_driver/lib/src/extension.dart b/packages/flutter_driver/lib/src/extension.dart index bae8aa3d63b..5f7e4cf4bbc 100644 --- a/packages/flutter_driver/lib/src/extension.dart +++ b/packages/flutter_driver/lib/src/extension.dart @@ -200,7 +200,7 @@ class FlutterDriverExtension { if (_frameSync) await _waitUntilFrame(() => SchedulerBinding.instance.transientCallbackCount == 0); - await _waitUntilFrame(() => finder.precache()); + await _waitUntilFrame(() => finder.evaluate().isNotEmpty); if (_frameSync) await _waitUntilFrame(() => SchedulerBinding.instance.transientCallbackCount == 0); @@ -213,7 +213,7 @@ class FlutterDriverExtension { if (_frameSync) await _waitUntilFrame(() => SchedulerBinding.instance.transientCallbackCount == 0); - await _waitUntilFrame(() => !finder.precache()); + await _waitUntilFrame(() => finder.evaluate().isEmpty); if (_frameSync) await _waitUntilFrame(() => SchedulerBinding.instance.transientCallbackCount == 0); @@ -268,10 +268,8 @@ class FlutterDriverExtension { Future _waitFor(Command command) async { final WaitFor waitForCommand = command; - if ((await _waitForElement(_createFinder(waitForCommand.finder))).evaluate().isNotEmpty) - return new WaitForResult(); - else - return null; + await _waitForElement(_createFinder(waitForCommand.finder)); + return new WaitForResult(); } Future _waitForAbsent(Command command) async {