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