Commit d09591bf authored by Yegor's avatar Yegor Committed by GitHub

consistently accept timeout in driver API (#8667)

parent 1ada132e
......@@ -56,6 +56,12 @@ enum TimelineStream {
const List<TimelineStream> _defaultStreams = const <TimelineStream>[TimelineStream.all];
/// Default timeout for long-running RPCs.
const Duration _kLongTimeout = const Duration(seconds: 20);
/// Default timeout for short-running RPCs.
const Duration _kShortTimeout = const Duration(seconds: 5);
// See https://github.com/dart-lang/sdk/blob/master/runtime/vm/timeline.cc#L32
String _timelineStreamsToString(List<TimelineStream> streams) {
final String contents = streams.map((TimelineStream stream) {
......@@ -300,18 +306,18 @@ class FlutterDriver {
}
/// Checks the status of the Flutter Driver extension.
Future<Health> checkHealth() async {
return Health.fromJson(await _sendCommand(new GetHealth()));
Future<Health> checkHealth({Duration timeout}) async {
return Health.fromJson(await _sendCommand(new GetHealth(timeout: timeout)));
}
/// Returns a dump of the render tree.
Future<RenderTree> getRenderTree() async {
return RenderTree.fromJson(await _sendCommand(new GetRenderTree()));
Future<RenderTree> getRenderTree({Duration timeout}) async {
return RenderTree.fromJson(await _sendCommand(new GetRenderTree(timeout: timeout)));
}
/// Taps at the center of the widget located by [finder].
Future<Null> tap(SerializableFinder finder) async {
await _sendCommand(new Tap(finder));
Future<Null> tap(SerializableFinder finder, {Duration timeout}) async {
await _sendCommand(new Tap(finder, timeout: timeout));
return null;
}
......@@ -319,8 +325,8 @@ class FlutterDriver {
///
/// This command invokes the `onChanged` handler of the `Input` widget with
/// the provided [text].
Future<Null> setInputText(SerializableFinder finder, String text) async {
await _sendCommand(new SetInputText(finder, text));
Future<Null> setInputText(SerializableFinder finder, String text, {Duration timeout}) async {
await _sendCommand(new SetInputText(finder, text, timeout: timeout));
return null;
}
......@@ -328,8 +334,8 @@ class FlutterDriver {
///
/// This command invokes the `onSubmitted` handler of the `Input` widget and
/// the returns the submitted text value.
Future<String> submitInputText(SerializableFinder finder) async {
final Map<String, dynamic> json = await _sendCommand(new SubmitInputText(finder));
Future<String> submitInputText(SerializableFinder finder, {Duration timeout}) async {
final Map<String, dynamic> json = await _sendCommand(new SubmitInputText(finder, timeout: timeout));
return json['text'];
}
......@@ -361,24 +367,24 @@ class FlutterDriver {
///
/// The move events are generated at a given [frequency] in Hz (or events per
/// second). It defaults to 60Hz.
Future<Null> scroll(SerializableFinder finder, double dx, double dy, Duration duration, {int frequency: 60}) async {
return await _sendCommand(new Scroll(finder, dx, dy, duration, frequency)).then((Map<String, dynamic> _) => null);
Future<Null> scroll(SerializableFinder finder, double dx, double dy, Duration duration, { int frequency: 60, Duration timeout }) async {
return await _sendCommand(new Scroll(finder, dx, dy, duration, frequency, timeout: timeout)).then((Map<String, dynamic> _) => null);
}
/// Scrolls the Scrollable ancestor of the widget located by [finder]
/// until the widget is completely visible.
Future<Null> scrollIntoView(SerializableFinder finder, { double alignment: 0.0 }) async {
return await _sendCommand(new ScrollIntoView(finder, alignment: alignment)).then((Map<String, dynamic> _) => null);
Future<Null> scrollIntoView(SerializableFinder finder, { double alignment: 0.0, Duration timeout }) async {
return await _sendCommand(new ScrollIntoView(finder, alignment: alignment, timeout: timeout)).then((Map<String, dynamic> _) => null);
}
/// Returns the text in the `Text` widget located by [finder].
Future<String> getText(SerializableFinder finder) async {
return GetTextResult.fromJson(await _sendCommand(new GetText(finder))).text;
Future<String> getText(SerializableFinder finder, { Duration timeout }) async {
return GetTextResult.fromJson(await _sendCommand(new GetText(finder, timeout: timeout))).text;
}
/// Take a screenshot. The image will be returned as a PNG.
Future<List<int>> screenshot() async {
final Map<String, dynamic> result = await _peer.sendRequest('_flutter.screenshot');
Future<List<int>> screenshot({ Duration timeout: _kLongTimeout }) async {
final Map<String, dynamic> result = await _peer.sendRequest('_flutter.screenshot').timeout(timeout);
return BASE64.decode(result['screenshot']);
}
......@@ -401,18 +407,18 @@ class FlutterDriver {
/// ]
///
/// [getFlagList]: https://github.com/dart-lang/sdk/blob/master/runtime/vm/service/service.md#getflaglist
Future<List<Map<String, dynamic>>> getVmFlags() async {
final Map<String, dynamic> result = await _peer.sendRequest('getFlagList');
Future<List<Map<String, dynamic>>> getVmFlags({ Duration timeout: _kShortTimeout }) async {
final Map<String, dynamic> result = await _peer.sendRequest('getFlagList').timeout(timeout);
return result['flags'];
}
/// Starts recording performance traces.
Future<Null> startTracing({List<TimelineStream> streams: _defaultStreams}) async {
Future<Null> startTracing({ List<TimelineStream> streams: _defaultStreams, Duration timeout: _kShortTimeout }) async {
assert(streams != null && streams.isNotEmpty);
try {
await _peer.sendRequest(_kSetVMTimelineFlagsMethod, <String, String>{
'recordedStreams': _timelineStreamsToString(streams)
});
}).timeout(timeout);
return null;
} catch(error, stackTrace) {
throw new DriverError(
......@@ -424,9 +430,11 @@ class FlutterDriver {
}
/// Stops recording performance traces and downloads the timeline.
Future<Timeline> stopTracingAndDownloadTimeline() async {
Future<Timeline> stopTracingAndDownloadTimeline({ Duration timeout: _kShortTimeout }) async {
try {
await _peer.sendRequest(_kSetVMTimelineFlagsMethod, <String, String>{'recordedStreams': '[]'});
await _peer
.sendRequest(_kSetVMTimelineFlagsMethod, <String, String>{'recordedStreams': '[]'})
.timeout(timeout);
return new Timeline.fromJson(await _peer.sendRequest(_kGetVMTimelineMethod));
} catch(error, stackTrace) {
throw new DriverError(
......@@ -469,13 +477,13 @@ class FlutterDriver {
/// With frame sync disabled, its the responsibility of the test author to
/// ensure that no action is performed while the app is undergoing a
/// transition to avoid flakiness.
Future<T> runUnsynchronized<T>(Future<T> action()) async {
await _sendCommand(new SetFrameSync(false));
Future<T> runUnsynchronized<T>(Future<T> action(), { Duration timeout }) async {
await _sendCommand(new SetFrameSync(false, timeout: timeout));
T result;
try {
result = await action();
} finally {
await _sendCommand(new SetFrameSync(true));
await _sendCommand(new SetFrameSync(true, timeout: timeout));
}
return result;
}
......
......@@ -207,7 +207,7 @@ class GetText extends CommandWithTarget {
final String kind = 'get_text';
/// [finder] looks for an element that contains a piece of text.
GetText(SerializableFinder finder) : super(finder);
GetText(SerializableFinder finder, { Duration timeout }) : super(finder, timeout: timeout);
/// Deserializes the command from JSON generated by [serialize].
GetText.deserialize(Map<String, dynamic> json) : super.deserialize(json);
......
......@@ -12,7 +12,7 @@ class SetFrameSync extends Command {
/// Whether frameSync should be enabled or disabled.
final bool enabled;
SetFrameSync(this.enabled) : super();
SetFrameSync(this.enabled, { Duration timeout }) : super(timeout: timeout);
/// Deserializes this command from the value generated by [serialize].
SetFrameSync.deserialize(Map<String, String> params)
......
......@@ -11,7 +11,7 @@ class Tap extends CommandWithTarget {
final String kind = 'tap';
/// Creates a tap command to tap on a widget located by [finder].
Tap(SerializableFinder finder) : super(finder);
Tap(SerializableFinder finder, {Duration timeout}) : super(finder, timeout: timeout);
/// Deserializes this command from JSON generated by [serialize].
Tap.deserialize(Map<String, String> json) : super.deserialize(json);
......@@ -44,8 +44,9 @@ class Scroll extends CommandWithTarget {
this.dx,
this.dy,
this.duration,
this.frequency
) : super(finder);
this.frequency,
{Duration timeout}
) : super(finder, timeout: timeout);
/// Deserializes this command from JSON generated by [serialize].
Scroll.deserialize(Map<String, String> json)
......@@ -95,7 +96,7 @@ class ScrollIntoView extends CommandWithTarget {
/// Creates this command given a [finder] used to locate the widget to be
/// scrolled into view.
ScrollIntoView(SerializableFinder finder, { this.alignment: 0.0 }) : super(finder);
ScrollIntoView(SerializableFinder finder, { this.alignment: 0.0, Duration timeout }) : super(finder, timeout: timeout);
/// Deserializes this command from JSON generated by [serialize].
ScrollIntoView.deserialize(Map<String, String> json)
......
......@@ -14,7 +14,7 @@ class SetInputText extends CommandWithTarget {
///
/// [finder] identifies the text input widget. [text] is the string that is
/// set as the value of the text input.
SetInputText(SerializableFinder finder, this.text) : super(finder);
SetInputText(SerializableFinder finder, this.text, {Duration timeout}) : super(finder, timeout: timeout);
/// The value of the text input to set.
final String text;
......@@ -52,7 +52,7 @@ class SubmitInputText extends CommandWithTarget {
final String kind = 'submitInputText';
/// Create a command that submits text on input widget identified by [finder].
SubmitInputText(SerializableFinder finder) : super(finder);
SubmitInputText(SerializableFinder finder, {Duration timeout}) : super(finder, timeout: timeout);
/// Deserializes this command from JSON generated by [serialize].
SubmitInputText.deserialize(Map<String, String> json)
......
......@@ -13,6 +13,10 @@ import 'package:mockito/mockito_no_mirrors.dart';
import 'package:test/test.dart';
import 'package:vm_service_client/vm_service_client.dart';
/// Magical timeout value that's different from the default.
const Duration _kTestTimeout = const Duration(milliseconds: 1234);
const String _kSerializedTestTimeout = '1234';
void main() {
group('FlutterDriver.connect', () {
List<LogRecord> log;
......@@ -127,14 +131,14 @@ void main() {
when(mockIsolate.invokeExtension(any, any)).thenAnswer((Invocation i) {
expect(i.positionalArguments[1], <String, String>{
'command': 'tap',
'timeout': '5000',
'timeout': _kSerializedTestTimeout,
'finderType': 'ByValueKey',
'keyValueString': 'foo',
'keyValueType': 'String'
});
return makeMockResponse(<String, dynamic>{});
});
await driver.tap(find.byValueKey('foo'));
await driver.tap(find.byValueKey('foo'), timeout: _kTestTimeout);
});
});
......@@ -147,13 +151,13 @@ void main() {
when(mockIsolate.invokeExtension(any, any)).thenAnswer((Invocation i) {
expect(i.positionalArguments[1], <String, dynamic>{
'command': 'tap',
'timeout': '5000',
'timeout': _kSerializedTestTimeout,
'finderType': 'ByText',
'text': 'foo',
});
return makeMockResponse(<String, dynamic>{});
});
await driver.tap(find.text('foo'));
await driver.tap(find.text('foo'), timeout: _kTestTimeout);
});
});
......@@ -166,7 +170,7 @@ void main() {
when(mockIsolate.invokeExtension(any, any)).thenAnswer((Invocation i) {
expect(i.positionalArguments[1], <String, dynamic>{
'command': 'get_text',
'timeout': '5000',
'timeout': _kSerializedTestTimeout,
'finderType': 'ByValueKey',
'keyValueString': '123',
'keyValueType': 'int'
......@@ -175,7 +179,7 @@ void main() {
'text': 'hello'
});
});
final String result = await driver.getText(find.byValueKey(123));
final String result = await driver.getText(find.byValueKey(123), timeout: _kTestTimeout);
expect(result, 'hello');
});
});
......@@ -191,11 +195,11 @@ void main() {
'command': 'waitFor',
'finderType': 'ByTooltipMessage',
'text': 'foo',
'timeout': '1000',
'timeout': _kSerializedTestTimeout,
});
return makeMockResponse(<String, dynamic>{});
});
await driver.waitFor(find.byTooltip('foo'), timeout: const Duration(seconds: 1));
await driver.waitFor(find.byTooltip('foo'), timeout: _kTestTimeout);
});
});
......@@ -204,11 +208,11 @@ void main() {
when(mockIsolate.invokeExtension(any, any)).thenAnswer((Invocation i) {
expect(i.positionalArguments[1], <String, dynamic>{
'command': 'waitUntilNoTransientCallbacks',
'timeout': '1000',
'timeout': _kSerializedTestTimeout,
});
return makeMockResponse(<String, dynamic>{});
});
await driver.waitUntilNoTransientCallbacks(timeout: const Duration(seconds: 1));
await driver.waitUntilNoTransientCallbacks(timeout: _kTestTimeout);
});
});
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment