Flutter driver handle minimalized application

361

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.

Share:
361
Apuna12
Author by

Apuna12

Updated on December 01, 2022

Comments

  • Apuna12
    Apuna12 over 1 year

    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);
      }