mirror of
https://github.com/flutter/flutter
synced 2024-10-13 03:32:55 +00:00
167 lines
5.9 KiB
Dart
167 lines
5.9 KiB
Dart
// 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 'dart:async';
|
|
|
|
import 'common.dart';
|
|
|
|
/// The dart:html implementation of [CallbackManager].
|
|
///
|
|
/// See also:
|
|
///
|
|
/// * `_callback_io.dart`, which has the dart:io implementation
|
|
CallbackManager get callbackManager => _singletonWebDriverCommandManager;
|
|
|
|
/// WebDriverCommandManager singleton.
|
|
final WebCallbackManager _singletonWebDriverCommandManager =
|
|
WebCallbackManager();
|
|
|
|
/// Manages communication between `integration_tests` and the `driver_tests`.
|
|
///
|
|
/// Along with responding to callbacks from the driver side this calls enables
|
|
/// usage of Web Driver commands by sending [WebDriverCommand]s to driver side.
|
|
///
|
|
/// Tests can execute an Web Driver commands such as `screenshot` using browsers'
|
|
/// WebDriver APIs.
|
|
///
|
|
/// See: https://www.w3.org/TR/webdriver/
|
|
class WebCallbackManager implements CallbackManager {
|
|
/// App side tests will put the command requests from WebDriver to this pipe.
|
|
Completer<WebDriverCommand> _webDriverCommandPipe =
|
|
Completer<WebDriverCommand>();
|
|
|
|
/// Updated when WebDriver completes the request by the test method.
|
|
///
|
|
/// For example, a test method will ask for a screenshot by calling
|
|
/// `takeScreenshot`. When this screenshot is taken [_driverCommandComplete]
|
|
/// will complete.
|
|
Completer<bool> _driverCommandComplete = Completer<bool>();
|
|
|
|
/// Takes screenshot using WebDriver screenshot command.
|
|
///
|
|
/// Only works on Web when tests are run via `flutter driver` command.
|
|
///
|
|
/// See: https://www.w3.org/TR/webdriver/#screen-capture.
|
|
@override
|
|
Future<void> takeScreenshot(String screenshotName) async {
|
|
await _sendWebDriverCommand(WebDriverCommand.screenshot(screenshotName));
|
|
}
|
|
|
|
Future<void> _sendWebDriverCommand(WebDriverCommand command) async {
|
|
try {
|
|
_webDriverCommandPipe.complete(command);
|
|
final bool awaitCommand = await _driverCommandComplete.future;
|
|
if (!awaitCommand) {
|
|
throw Exception(
|
|
'Web Driver Command ${command.type} failed while waiting for '
|
|
'driver side');
|
|
}
|
|
} catch (exception) {
|
|
throw Exception('Web Driver Command failed: ${command.type} with '
|
|
'exception $exception');
|
|
} finally {
|
|
// Reset the completer.
|
|
_driverCommandComplete = Completer<bool>();
|
|
}
|
|
}
|
|
|
|
/// The callback function to response the driver side input.
|
|
///
|
|
/// Provides a handshake mechanism for executing [WebDriverCommand]s on the
|
|
/// driver side.
|
|
@override
|
|
Future<Map<String, dynamic>> callback(
|
|
Map<String, String> params, IntegrationTestResults testRunner) async {
|
|
final String command = params['command']!;
|
|
Map<String, String> response;
|
|
switch (command) {
|
|
case 'request_data':
|
|
return params['message'] == null
|
|
? _requestData(testRunner)
|
|
: _requestDataWithMessage(params['message']!, testRunner);
|
|
case 'get_health':
|
|
response = <String, String>{'status': 'ok'};
|
|
break;
|
|
default:
|
|
throw UnimplementedError('$command is not implemented');
|
|
}
|
|
return <String, dynamic>{
|
|
'isError': false,
|
|
'response': response,
|
|
};
|
|
}
|
|
|
|
Future<Map<String, dynamic>> _requestDataWithMessage(
|
|
String extraMessage, IntegrationTestResults testRunner) async {
|
|
Map<String, String> response;
|
|
// Driver side tests' status is added as an extra message.
|
|
final DriverTestMessage message =
|
|
DriverTestMessage.fromString(extraMessage);
|
|
// If driver side tests are pending send the first command in the
|
|
// `commandPipe` to the tests.
|
|
if (message.isPending) {
|
|
final WebDriverCommand command = await _webDriverCommandPipe.future;
|
|
switch (command.type) {
|
|
case WebDriverCommandType.screenshot:
|
|
final Map<String, dynamic> data = Map<String, dynamic>.from(command.values);
|
|
data.addAll(
|
|
WebDriverCommand.typeToMap(WebDriverCommandType.screenshot));
|
|
response = <String, String>{
|
|
'message': Response.webDriverCommand(data: data).toJson(),
|
|
};
|
|
break;
|
|
case WebDriverCommandType.noop:
|
|
final Map<String, dynamic> data = <String, dynamic>{};
|
|
data.addAll(WebDriverCommand.typeToMap(WebDriverCommandType.noop));
|
|
response = <String, String>{
|
|
'message': Response.webDriverCommand(data: data).toJson(),
|
|
};
|
|
break;
|
|
default:
|
|
throw UnimplementedError('${command.type} is not implemented');
|
|
}
|
|
} else {
|
|
final Map<String, dynamic> data = <String, dynamic>{};
|
|
data.addAll(WebDriverCommand.typeToMap(WebDriverCommandType.ack));
|
|
response = <String, String>{
|
|
'message': Response.webDriverCommand(data: data).toJson(),
|
|
};
|
|
_driverCommandComplete.complete(message.isSuccess);
|
|
_webDriverCommandPipe = Completer<WebDriverCommand>();
|
|
}
|
|
return <String, dynamic>{
|
|
'isError': false,
|
|
'response': response,
|
|
};
|
|
}
|
|
|
|
Future<Map<String, dynamic>> _requestData(IntegrationTestResults testRunner) async {
|
|
final bool allTestsPassed = await testRunner.allTestsPassed.future;
|
|
final Map<String, String> response = <String, String>{
|
|
'message': allTestsPassed
|
|
? Response.allTestsPassed(data: testRunner.reportData).toJson()
|
|
: Response.someTestsFailed(
|
|
testRunner.failureMethodsDetails,
|
|
data: testRunner.reportData,
|
|
).toJson(),
|
|
};
|
|
return <String, dynamic>{
|
|
'isError': false,
|
|
'response': response,
|
|
};
|
|
}
|
|
|
|
@override
|
|
void cleanup() {
|
|
if (!_webDriverCommandPipe.isCompleted) {
|
|
_webDriverCommandPipe
|
|
.complete(Future<WebDriverCommand>.value(WebDriverCommand.noop()));
|
|
}
|
|
|
|
if (!_driverCommandComplete.isCompleted) {
|
|
_driverCommandComplete.complete(Future<bool>.value(false));
|
|
}
|
|
}
|
|
}
|