Flutter driver handle minimalized application

Issue

I am making some testing scenarios for my flutter application. One of the functionalities is "About us" section. When tapping on "About Us" user is redirected to the web page and application is minimalized. This is an issue because test scenario fails on this spot. Flutter is not able to find any components and it fails on this particular error

Unhandled exception:
DriverError: Failed to fulfill Tap due to remote error
Original error: Bad state: The client closed with pending request "ext.flutter.driver".
Original stack trace:
#0      new Client.withoutJson.<anonymous closure> (package:json_rpc_2/src/client.dart:70:24)
#1      _RootZone.run (dart:async/zone.dart:1445:54)
#2      _FutureListener.handleWhenComplete (dart:async/future_impl.dart:167:18)
#3      Future._propagateToListeners.handleWhenCompleteCallback (dart:async/future_impl.dart:666:39)
#4      Future._propagateToListeners (dart:async/future_impl.dart:722:37)
#5      Future._propagateToListeners (dart:async/future_impl.dart:621:9)
#6      Future._completeWithValue (dart:async/future_impl.dart:529:5)
#7      Future._asyncCompleteWithValue.<anonymous closure> (dart:async/future_impl.dart:567:7)
#8      _microtaskLoop (dart:async/schedule_microtask.dart:41:21)
#9      _startMicrotaskLoop (dart:async/schedule_microtask.dart:50:5)
#10     _runPendingImmediateCallback (dart:isolate-patch/isolate_patch.dart:118:13)
#11     _Timer._runTimers (dart:isolate-patch/timer_impl.dart:404:11)
#12     _Timer._handleMessage (dart:isolate-patch/timer_impl.dart:428:5)
#13     _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:168:12)


#0      VMServiceFlutterDriver.sendCommand (package:flutter_driver/src/driver/vmservice_driver.dart:345:7)
<asynchronous suspension>
#1      FlutterDriver.tap (package:flutter_driver/src/driver/driver.dart:207:11)
#2      LoginPage.tapOnAboutUs (file:///D:/Projects/app/test_driver/page_objects/login_page.dart:52:19)
#3      aboutUs_steps.iClickOnAboutUsOnLoginPage (file:///D:/Projects/app/test_driver/steps/aboutUs_steps.dart:16:15)
<asynchronous suspension>
#4      _InstanceMirror._invoke (dart:mirrors-patch/mirrors_impl.dart:337:37)
#5      _InstanceMirror.invoke (dart:mirrors-patch/mirrors_impl.dart:333:25)
#6      OguretsState.invokeStep.<anonymous closure> (package:ogurets/src/ogurets_internal.dart:316:29)
#7      new Future.sync (dart:async/future.dart:223:31)
#8      OguretsState.invokeStep (package:ogurets/src/ogurets_internal.dart:315:25)
#9      OguretsState.executeStep (package:ogurets/src/ogurets_internal.dart:296:13)
<asynchronous suspension>
#10     OguretsState._findClassStyleStepRunners.<anonymous closure> (package:ogurets/src/ogurets_internal.dart:270:19)
#11     _Scenario._executeSubScenario (package:ogurets/src/model/scenario.dart:163:43)
<asynchronous suspension>
#12     _Scenario.execute (package:ogurets/src/model/scenario.dart:57:17)
#13     _Feature.execute (package:ogurets/src/model/feature.dart:41:64)
#14     OguretsOpts.processFeatureFile (package:ogurets/src/ogurets_opts.dart:327:49)
<asynchronous suspension>
#15     OguretsOpts.run (package:ogurets/src/ogurets_opts.dart:303:17)
<asynchronous suspension>
#16     main (file:///D:/Projects/app/test_driver/ogurets_flutter_test.dart:30:13)
#17     _startIsolate.<anonymous closure> (dart:isolate-patch/isolate_patch.dart:299:32)
#18     _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:168:12)

Is there any possible solution which could unminimalize the app from background?

I was trying to use default flutter hooks, but with no correct result.

These are files and methods which I use

Feature: AboutUsLink
  As a tester I test the functionality of the About Us link


  Scenario: Login - About us - Button functionality
    Given I click on About us on Login Page



class aboutUs_steps {
  FlutterOgurets _world;

  aboutUs_steps(this._world);

  @Given(r'I click on About us on Login Page')
  void iClickOnAboutUsOnLoginPage() async {
    LoginPage loginPage = new LoginPage(_world.driver);
    await Future.delayed(Duration(seconds: FUTURE_DELAY));
    loginPage.tapOnAboutUs();
  }
}

and the method in LoginPage

  Future<void> tapOnAboutUs() async {
    await _driver.tap(aboutUs);
  }

Solution

This is a scenario where I would choose a widget test over an integration test (using flutter driver), as it is quicker to execute and easier to verify the correct behaviour

Q: How to write a test for a feature opening an external application (like a URL in a webbrowser).

A: When redirecting to a website or any other external URL using a method like launch() you want to test that you are passing the correct parameter to launch() – in your case that would be something like https://example.com/about

Implementation:
You need to mock launch() and verify it has been called with the correct parameter, a test could look something like this, where your LoginPage can be passed a mock for the launcher:

class MockLauncher extends Mock {}

void main() {
  MockLauncher mockLauncher; 
  setUp() {
    mockLauncher = MockLauncher();
    when(mockLauncher.launch(any)).thenReturn(true);
  }
  testWidgets('click on About us', (WidgetTester tester)
  async {
    await tester.pumpWidget(LoginPage(launcher: mockLauncher.launch));
    await tester.tap(find.byKey(ValueKey('about_us_link')));
    verify(mockLauncher.launch('https://example.com/about'));
    verifyNoMoreInteractions(mockLauncher);
  });
}
import 'package:url_launcher/url_launcher.dart';

class LoginPage extends ...{
  Function urlLauncher;

  LoginPage({this.urlLauncher}) {
    urlLauncher ??= launcher // use mock if it is passed in
  }
}

The same approach could also be used for integration testing, but I would suggest to reassess your reasons for doing so, as the test strategy above should be sufficent for most redirect scenarios.

Answered By – Damian K. Bast

Answer Checked By – Marie Seifert (FlutterFixes Admin)

Leave a Reply

Your email address will not be published.