web_driver_test.dart 3.9 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139
// Copyright 2014 The Flutter 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_driver/src/common/error.dart';
import 'package:flutter_driver/src/common/health.dart';
import 'package:flutter_driver/src/driver/web_driver.dart';
import 'package:webdriver/src/common/log.dart';

import '../../common.dart';

void main() {
  group('WebDriver', () {
    late FakeFlutterWebConnection fakeConnection;
    late WebFlutterDriver driver;

    setUp(() {
      fakeConnection = FakeFlutterWebConnection();
      driver = WebFlutterDriver.connectedTo(fakeConnection);
    });

    test('sendCommand succeeds', () async {
      fakeConnection.fakeResponse = '''
{
  "isError": false,
  "response": {
    "test": "hello"
  }
}
''';

      final Map<String, Object?> response = await driver.sendCommand(const GetHealth());
      expect(response['test'], 'hello');
    });

    test('sendCommand fails on communication error', () async {
      fakeConnection.communicationError = Error();
      expect(
        () => driver.sendCommand(const GetHealth()),
        _throwsDriverErrorWithMessage(
          'FlutterDriver command GetHealth failed due to a remote error.\n'
          'Command sent: {"command":"get_health"}'
        ),
      );
    });

    test('sendCommand fails on null', () async {
      fakeConnection.fakeResponse = null;
      expect(
        () => driver.sendCommand(const GetHealth()),
        _throwsDriverErrorWithDataString('Null', 'null'),
      );
    });

    test('sendCommand fails when response data is not a string', () async {
      fakeConnection.fakeResponse = 1234;
      expect(
        () => driver.sendCommand(const GetHealth()),
        _throwsDriverErrorWithDataString('int', '1234'),
      );
    });

    test('sendCommand fails when isError is true', () async {
      fakeConnection.fakeResponse = '''
{
  "isError": true,
  "response": "test error message"
}
''';
      expect(
        () => driver.sendCommand(const GetHealth()),
        _throwsDriverErrorWithMessage(
          'Error in Flutter application: test error message'
        ),
      );
    });

    test('sendCommand fails when isError is not bool', () async {
      fakeConnection.fakeResponse = '{ "isError": 5 }';
      expect(
        () => driver.sendCommand(const GetHealth()),
        _throwsDriverErrorWithDataString('String', '{ "isError": 5 }'),
      );
    });

    test('sendCommand fails when "response" field is not a JSON map', () async {
      fakeConnection.fakeResponse = '{ "response": 5 }';
      expect(
        () => driver.sendCommand(const GetHealth()),
        _throwsDriverErrorWithDataString('String', '{ "response": 5 }'),
      );
    });
  });
}

Matcher _throwsDriverErrorWithMessage(String expectedMessage) {
  return throwsA(allOf(
    isA<DriverError>(),
    predicate<DriverError>((DriverError error) {
      final String actualMessage = error.message;
      return actualMessage == expectedMessage;
    }, 'contains message: $expectedMessage'),
  ));
}

Matcher _throwsDriverErrorWithDataString(String dataType, String dataString) {
  return _throwsDriverErrorWithMessage(
    'Received malformed response from the FlutterDriver extension.\n'
    'Expected a JSON map containing a "response" field and, optionally, an '
    '"isError" field, but got $dataType: $dataString'
  );
}

class FakeFlutterWebConnection implements FlutterWebConnection {
  @override
  bool supportsTimelineAction = false;

  @override
  Future<void> close() async {}

  @override
  Stream<LogEntry> get logs => throw UnimplementedError();

  @override
  Future<List<int>> screenshot() {
    throw UnimplementedError();
  }

  Object? fakeResponse;
  Error? communicationError;

  @override
  Future<Object?> sendCommand(String script, Duration? duration) async {
    if (communicationError != null) {
      throw communicationError!;
    }
    return fakeResponse;
  }
}