100% doc coverage in package:flutter_driver (#6738)
This commit is contained in:
parent
64609588f4
commit
0cd69826f5
@ -6,6 +6,7 @@ import 'dart:async';
|
||||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
import 'package:json_rpc_2/json_rpc_2.dart' as rpc;
|
||||
import 'package:meta/meta.dart';
|
||||
import 'package:vm_service_client/vm_service_client.dart';
|
||||
import 'package:web_socket_channel/io.dart';
|
||||
|
||||
@ -17,8 +18,34 @@ import 'input.dart';
|
||||
import 'message.dart';
|
||||
import 'timeline.dart';
|
||||
|
||||
/// Timeline stream identifier.
|
||||
enum TimelineStream {
|
||||
all, api, compiler, dart, debugger, embedder, gc, isolate, vm
|
||||
/// A meta-identifier that instructs the Dart VM to record all streams.
|
||||
all,
|
||||
|
||||
/// Marks events related to calls made via Dart's C API.
|
||||
api,
|
||||
|
||||
/// Marks events from the Dart VM's JIT compiler.
|
||||
compiler,
|
||||
|
||||
/// Marks events emitted using the `dart:developer` API.
|
||||
dart,
|
||||
|
||||
/// Marks events from the Dart VM debugger.
|
||||
debugger,
|
||||
|
||||
/// Marks events emitted using the `dart_tools_api.h` C API.
|
||||
embedder,
|
||||
|
||||
/// Marks events from the garbage collector.
|
||||
gc,
|
||||
|
||||
/// Marks events related to message passing between Dart isolates.
|
||||
isolate,
|
||||
|
||||
/// Marks internal VM events.
|
||||
vm,
|
||||
}
|
||||
|
||||
const List<TimelineStream> _defaultStreams = const <TimelineStream>[TimelineStream.all];
|
||||
@ -62,6 +89,9 @@ typedef dynamic EvaluatorFunction();
|
||||
|
||||
/// Drives a Flutter Application running in another process.
|
||||
class FlutterDriver {
|
||||
/// Creates a driver that uses a connection provided by the given
|
||||
/// [_serviceClient], [_peer] and [_appIsolate].
|
||||
@visibleForTesting
|
||||
FlutterDriver.connectedTo(this._serviceClient, this._peer, this._appIsolate);
|
||||
|
||||
static const String _kFlutterExtensionMethod = 'ext.flutter.driver';
|
||||
@ -316,6 +346,9 @@ class FlutterDriver {
|
||||
///
|
||||
/// This is merely a convenience wrapper on top of [startTracing] and
|
||||
/// [stopTracingAndDownloadTimeline].
|
||||
///
|
||||
/// [streams] limits the recorded timeline event streams to only the ones
|
||||
/// listed. By default, all streams are recorded.
|
||||
Future<Timeline> traceAction(Future<dynamic> action(), { List<TimelineStream> streams: _defaultStreams }) async {
|
||||
await startTracing(streams: streams);
|
||||
await action();
|
||||
@ -334,6 +367,7 @@ class FlutterDriver {
|
||||
}
|
||||
|
||||
/// Encapsulates connection information to an instance of a Flutter application.
|
||||
@visibleForTesting
|
||||
class VMServiceClientConnection {
|
||||
/// Use this for structured access to the VM service's public APIs.
|
||||
final VMServiceClient client;
|
||||
@ -344,6 +378,7 @@ class VMServiceClientConnection {
|
||||
/// caution.
|
||||
final rpc.Peer peer;
|
||||
|
||||
/// Creates an instance of this class given a [client] and a [peer].
|
||||
VMServiceClientConnection(this.client, this.peer);
|
||||
}
|
||||
|
||||
|
@ -7,12 +7,17 @@ import 'dart:io' show stderr;
|
||||
|
||||
/// Standard error thrown by Flutter Driver API.
|
||||
class DriverError extends Error {
|
||||
/// Create an error with a [message] and (optionally) the [originalError] and
|
||||
/// [originalStackTrace] that caused it.
|
||||
DriverError(this.message, [this.originalError, this.originalStackTrace]);
|
||||
|
||||
/// Human-readable error message.
|
||||
final String message;
|
||||
|
||||
/// The error object that was caught and wrapped by this error object.
|
||||
final dynamic originalError;
|
||||
|
||||
/// The stack trace that was caught and wrapped by this error object.
|
||||
final dynamic originalStackTrace;
|
||||
|
||||
@override
|
||||
@ -47,44 +52,99 @@ void _log(LogLevel level, String loggerName, Object message) {
|
||||
final Stream<LogRecord> flutterDriverLog = _logger.stream;
|
||||
|
||||
/// Severity of a log entry.
|
||||
enum LogLevel { trace, info, warning, error, critical }
|
||||
enum LogLevel {
|
||||
/// Messages used to supplement the higher-level messages with more details.
|
||||
///
|
||||
/// This will likely produce a lot of output.
|
||||
trace,
|
||||
|
||||
/// Informational messages that do not indicate a problem.
|
||||
info,
|
||||
|
||||
/// A potential problem.
|
||||
warning,
|
||||
|
||||
/// A certain problem but the program will attempt to continue.
|
||||
error,
|
||||
|
||||
/// A critical problem; the program will attempt to quit immediately.
|
||||
critical,
|
||||
}
|
||||
|
||||
/// A log entry.
|
||||
class LogRecord {
|
||||
const LogRecord._(this.level, this.loggerName, this.message);
|
||||
|
||||
/// The severity of the log record.
|
||||
final LogLevel level;
|
||||
|
||||
/// The name of the logger that logged the message.
|
||||
final String loggerName;
|
||||
|
||||
/// The log message.
|
||||
///
|
||||
/// The message should be a normal and complete sentence ending with a period.
|
||||
/// It is OK to omit the subject in the message to imply [loggerName]. It is
|
||||
/// also OK to omit article, such as "the" and "a".
|
||||
///
|
||||
/// Example: if [loggerName] is "FlutterDriver" and [message] is "Failed to
|
||||
/// connect to application." then this log record means that FlutterDriver
|
||||
/// failed to connect to the application.
|
||||
final String message;
|
||||
|
||||
/// Short description of the log level.
|
||||
///
|
||||
/// It is meant to be read by humans. There's no guarantee that this value is
|
||||
/// stable enough to be parsed by machines.
|
||||
String get levelDescription => level.toString().split(".").last;
|
||||
|
||||
@override
|
||||
String toString() => '[${levelDescription.padRight(5)}] $loggerName: $message';
|
||||
}
|
||||
|
||||
/// Package-private; users should use other public logging libraries.
|
||||
/// Logger used internally by Flutter Driver to avoid mandating any specific
|
||||
/// logging library.
|
||||
///
|
||||
/// By default the output from this logger is printed to [stderr]. However, a
|
||||
/// subscriber to the [flutterDriverLog] stream may redirect the log records
|
||||
/// elsewhere, including other logging API. The logger stops sending messages to
|
||||
/// [stderr] upon first subscriber.
|
||||
///
|
||||
/// This class is package-private. Flutter users should use other public logging
|
||||
/// libraries.
|
||||
class Logger {
|
||||
/// Creates a new logger.
|
||||
Logger(this.name);
|
||||
|
||||
/// Identifies the part of the system that emits message into this object.
|
||||
///
|
||||
/// It is common for [name] to be used as an implicit subject of an action
|
||||
/// described in a log message. For example, if you emit message "failed" and
|
||||
/// [name] is "FlutterDriver", the meaning of the message should be understood
|
||||
/// as "FlutterDriver failed". See also [LogRecord.message].
|
||||
final String name;
|
||||
|
||||
/// Emits a [LogLevel.trace] record into `this` logger.
|
||||
void trace(Object message) {
|
||||
_log(LogLevel.trace, name, message);
|
||||
}
|
||||
|
||||
/// Emits a [LogLevel.info] record into `this` logger.
|
||||
void info(Object message) {
|
||||
_log(LogLevel.info, name, message);
|
||||
}
|
||||
|
||||
/// Emits a [LogLevel.warning] record into `this` logger.
|
||||
void warning(Object message) {
|
||||
_log(LogLevel.warning, name, message);
|
||||
}
|
||||
|
||||
/// Emits a [LogLevel.error] record into `this` logger.
|
||||
void error(Object message) {
|
||||
_log(LogLevel.error, name, message);
|
||||
}
|
||||
|
||||
/// Emits a [LogLevel.critical] record into `this` logger.
|
||||
void critical(Object message) {
|
||||
_log(LogLevel.critical, name, message);
|
||||
}
|
||||
|
@ -25,7 +25,7 @@ class _DriverBinding extends WidgetsFlutterBinding { // TODO(ianh): refactor so
|
||||
@override
|
||||
void initServiceExtensions() {
|
||||
super.initServiceExtensions();
|
||||
FlutterDriverExtension extension = new FlutterDriverExtension();
|
||||
_FlutterDriverExtension extension = new _FlutterDriverExtension._();
|
||||
registerServiceExtension(
|
||||
name: _extensionMethodName,
|
||||
callback: extension.call
|
||||
@ -55,10 +55,10 @@ typedef Command CommandDeserializerCallback(Map<String, String> params);
|
||||
/// Runs the finder and returns the [Element] found, or `null`.
|
||||
typedef Finder FinderConstructor(SerializableFinder finder);
|
||||
|
||||
class FlutterDriverExtension {
|
||||
class _FlutterDriverExtension {
|
||||
static final Logger _log = new Logger('FlutterDriverExtension');
|
||||
|
||||
FlutterDriverExtension() {
|
||||
_FlutterDriverExtension._() {
|
||||
_commandHandlers.addAll(<String, CommandHandlerCallback>{
|
||||
'get_health': _getHealth,
|
||||
'tap': _tap,
|
||||
@ -88,11 +88,21 @@ class FlutterDriverExtension {
|
||||
});
|
||||
}
|
||||
|
||||
final WidgetController prober = new WidgetController(WidgetsBinding.instance);
|
||||
final WidgetController _prober = new WidgetController(WidgetsBinding.instance);
|
||||
final Map<String, CommandHandlerCallback> _commandHandlers = <String, CommandHandlerCallback>{};
|
||||
final Map<String, CommandDeserializerCallback> _commandDeserializers = <String, CommandDeserializerCallback>{};
|
||||
final Map<String, FinderConstructor> _finders = <String, FinderConstructor>{};
|
||||
|
||||
/// Processes a driver command configured by [params] and returns a result
|
||||
/// as an arbitrary JSON object.
|
||||
///
|
||||
/// [params] must contain key "command" whose value is a string that
|
||||
/// identifies the kind of the command and its corresponding
|
||||
/// [CommandDeserializerCallback]. Other keys and values are specific to the
|
||||
/// concrete implementation of [Command] and [CommandDeserializerCallback].
|
||||
///
|
||||
/// The returned JSON is command specific. Generally the caller deserializes
|
||||
/// the result into a subclass of [Result], but that's not strictly required.
|
||||
Future<Map<String, dynamic>> call(Map<String, String> params) async {
|
||||
try {
|
||||
String commandKind = params['command'];
|
||||
@ -181,7 +191,7 @@ class FlutterDriverExtension {
|
||||
|
||||
Future<TapResult> _tap(Command command) async {
|
||||
Tap tapCommand = command;
|
||||
await prober.tap(await _waitForElement(_createFinder(tapCommand.finder)));
|
||||
await _prober.tap(await _waitForElement(_createFinder(tapCommand.finder)));
|
||||
return new TapResult();
|
||||
}
|
||||
|
||||
@ -199,20 +209,20 @@ class FlutterDriverExtension {
|
||||
final int totalMoves = scrollCommand.duration.inMicroseconds * scrollCommand.frequency ~/ Duration.MICROSECONDS_PER_SECOND;
|
||||
Offset delta = new Offset(scrollCommand.dx, scrollCommand.dy) / totalMoves.toDouble();
|
||||
Duration pause = scrollCommand.duration ~/ totalMoves;
|
||||
Point startLocation = prober.getCenter(target);
|
||||
Point startLocation = _prober.getCenter(target);
|
||||
Point currentLocation = startLocation;
|
||||
TestPointer pointer = new TestPointer(1);
|
||||
HitTestResult hitTest = new HitTestResult();
|
||||
|
||||
prober.binding.hitTest(hitTest, startLocation);
|
||||
prober.binding.dispatchEvent(pointer.down(startLocation), hitTest);
|
||||
_prober.binding.hitTest(hitTest, startLocation);
|
||||
_prober.binding.dispatchEvent(pointer.down(startLocation), hitTest);
|
||||
await new Future<Null>.value(); // so that down and move don't happen in the same microtask
|
||||
for (int moves = 0; moves < totalMoves; moves++) {
|
||||
currentLocation = currentLocation + delta;
|
||||
prober.binding.dispatchEvent(pointer.move(currentLocation), hitTest);
|
||||
_prober.binding.dispatchEvent(pointer.move(currentLocation), hitTest);
|
||||
await new Future<Null>.delayed(pause);
|
||||
}
|
||||
prober.binding.dispatchEvent(pointer.up(), hitTest);
|
||||
_prober.binding.dispatchEvent(pointer.up(), hitTest);
|
||||
|
||||
return new ScrollResult();
|
||||
}
|
||||
|
@ -2,6 +2,8 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
import 'package:meta/meta.dart';
|
||||
|
||||
import 'error.dart';
|
||||
import 'message.dart';
|
||||
|
||||
@ -17,6 +19,7 @@ DriverError _createInvalidKeyValueTypeError(String invalidType) {
|
||||
/// required beyond the [finder] the implementation may override [serialize]
|
||||
/// and add more keys to the returned map.
|
||||
abstract class CommandWithTarget extends Command {
|
||||
/// Constructs this command given a [finder].
|
||||
CommandWithTarget(this.finder) {
|
||||
if (finder == null)
|
||||
throw new DriverError('${this.runtimeType} target cannot be null');
|
||||
@ -42,11 +45,20 @@ class WaitFor extends CommandWithTarget {
|
||||
@override
|
||||
final String kind = 'waitFor';
|
||||
|
||||
/// Creates a command that waits for the widget identified by [finder] to
|
||||
/// appear within the [timeout] amount of time.
|
||||
///
|
||||
/// If [timeout] is not specified the command times out after 5 seconds.
|
||||
WaitFor(SerializableFinder finder, {this.timeout})
|
||||
: super(finder);
|
||||
|
||||
/// The maximum amount of time to wait for the [finder] to locate the desired
|
||||
/// widgets before timing out the command.
|
||||
///
|
||||
/// Defaults to 5 seconds.
|
||||
final Duration timeout;
|
||||
|
||||
/// Deserializes the command from JSON generated by [serialize].
|
||||
static WaitFor deserialize(Map<String, String> json) {
|
||||
Duration timeout = json['timeout'] != null
|
||||
? new Duration(milliseconds: int.parse(json['timeout']))
|
||||
@ -66,9 +78,9 @@ class WaitFor extends CommandWithTarget {
|
||||
}
|
||||
}
|
||||
|
||||
/// The result of a [WaitFor] command.
|
||||
class WaitForResult extends Result {
|
||||
WaitForResult();
|
||||
|
||||
/// Deserializes the result from JSON.
|
||||
static WaitForResult fromJson(Map<String, dynamic> json) {
|
||||
return new WaitForResult();
|
||||
}
|
||||
@ -79,8 +91,10 @@ class WaitForResult extends Result {
|
||||
|
||||
/// Describes how to the driver should search for elements.
|
||||
abstract class SerializableFinder {
|
||||
/// Identifies the type of finder to be used by the driver extension.
|
||||
String get finderType;
|
||||
|
||||
/// Deserializes a finder from JSON generated by [serialize].
|
||||
static SerializableFinder deserialize(Map<String, String> json) {
|
||||
String finderType = json['finderType'];
|
||||
switch(finderType) {
|
||||
@ -91,6 +105,11 @@ abstract class SerializableFinder {
|
||||
throw new DriverError('Unsupported search specification type $finderType');
|
||||
}
|
||||
|
||||
/// Serializes common fields to JSON.
|
||||
///
|
||||
/// Methods that override [serialize] are expected to call `super.serialize`
|
||||
/// and add more fields to the returned [Map].
|
||||
@mustCallSuper
|
||||
Map<String, String> serialize() => <String, String>{
|
||||
'finderType': finderType,
|
||||
};
|
||||
@ -101,6 +120,7 @@ class ByTooltipMessage extends SerializableFinder {
|
||||
@override
|
||||
final String finderType = 'ByTooltipMessage';
|
||||
|
||||
/// Creates a tooltip finder given the tooltip's message [text].
|
||||
ByTooltipMessage(this.text);
|
||||
|
||||
/// Tooltip message text.
|
||||
@ -111,6 +131,7 @@ class ByTooltipMessage extends SerializableFinder {
|
||||
'text': text,
|
||||
});
|
||||
|
||||
/// Deserializes the finder from JSON generated by [serialize].
|
||||
static ByTooltipMessage deserialize(Map<String, String> json) {
|
||||
return new ByTooltipMessage(json['text']);
|
||||
}
|
||||
@ -121,8 +142,10 @@ class ByText extends SerializableFinder {
|
||||
@override
|
||||
final String finderType = 'ByText';
|
||||
|
||||
/// Creates a text finder given the text.
|
||||
ByText(this.text);
|
||||
|
||||
/// The text that appears inside the `Text` widget.
|
||||
final String text;
|
||||
|
||||
@override
|
||||
@ -130,6 +153,7 @@ class ByText extends SerializableFinder {
|
||||
'text': text,
|
||||
});
|
||||
|
||||
/// Deserializes the finder from JSON generated by [serialize].
|
||||
static ByText deserialize(Map<String, String> json) {
|
||||
return new ByText(json['text']);
|
||||
}
|
||||
@ -140,6 +164,7 @@ class ByValueKey extends SerializableFinder {
|
||||
@override
|
||||
final String finderType = 'ByValueKey';
|
||||
|
||||
/// Creates a finder given the key value.
|
||||
ByValueKey(dynamic keyValue)
|
||||
: this.keyValue = keyValue,
|
||||
this.keyValueString = '$keyValue',
|
||||
@ -165,6 +190,7 @@ class ByValueKey extends SerializableFinder {
|
||||
'keyValueType': keyValueType,
|
||||
});
|
||||
|
||||
/// Deserializes the finder from JSON generated by [serialize].
|
||||
static ByValueKey deserialize(Map<String, String> json) {
|
||||
String keyValueString = json['keyValueString'];
|
||||
String keyValueType = json['keyValueType'];
|
||||
@ -187,6 +213,7 @@ class GetText extends CommandWithTarget {
|
||||
@override
|
||||
final String kind = 'get_text';
|
||||
|
||||
/// Deserializes the command from JSON generated by [serialize].
|
||||
static GetText deserialize(Map<String, String> json) {
|
||||
return new GetText(SerializableFinder.deserialize(json));
|
||||
}
|
||||
@ -195,11 +222,15 @@ class GetText extends CommandWithTarget {
|
||||
Map<String, String> serialize() => super.serialize();
|
||||
}
|
||||
|
||||
/// The result of the [GetText] command.
|
||||
class GetTextResult extends Result {
|
||||
/// Creates a result with the given [text].
|
||||
GetTextResult(this.text);
|
||||
|
||||
/// The text extracted by the [GetText] command.
|
||||
final String text;
|
||||
|
||||
/// Deserializes the result from JSON.
|
||||
static GetTextResult fromJson(Map<String, dynamic> json) {
|
||||
return new GetTextResult(json['text']);
|
||||
}
|
||||
|
@ -5,12 +5,15 @@
|
||||
import 'message.dart';
|
||||
import 'find.dart';
|
||||
|
||||
/// Taps on a target widget located by [finder].
|
||||
class Tap extends CommandWithTarget {
|
||||
@override
|
||||
final String kind = 'tap';
|
||||
|
||||
/// Creates a tap command to tap on a widget located by [finder].
|
||||
Tap(SerializableFinder finder) : super(finder);
|
||||
|
||||
/// Deserializes this command from JSON generated by [serialize].
|
||||
static Tap deserialize(Map<String, String> json) {
|
||||
return new Tap(SerializableFinder.deserialize(json));
|
||||
}
|
||||
@ -19,7 +22,9 @@ class Tap extends CommandWithTarget {
|
||||
Map<String, String> serialize() => super.serialize();
|
||||
}
|
||||
|
||||
/// The result of a [Tap] command.
|
||||
class TapResult extends Result {
|
||||
/// Deserializes this result from JSON.
|
||||
static TapResult fromJson(Map<String, dynamic> json) {
|
||||
return new TapResult();
|
||||
}
|
||||
@ -34,6 +39,8 @@ class Scroll extends CommandWithTarget {
|
||||
@override
|
||||
final String kind = 'scroll';
|
||||
|
||||
/// Creates a scroll command that will attempt to scroll a scrollable view by
|
||||
/// dragging a widget located by the given [finder].
|
||||
Scroll(
|
||||
SerializableFinder finder,
|
||||
this.dx,
|
||||
@ -42,6 +49,7 @@ class Scroll extends CommandWithTarget {
|
||||
this.frequency
|
||||
) : super(finder);
|
||||
|
||||
/// Deserializes this command from JSON generated by [serialize].
|
||||
static Scroll deserialize(Map<String, dynamic> json) {
|
||||
return new Scroll(
|
||||
SerializableFinder.deserialize(json),
|
||||
@ -73,20 +81,9 @@ class Scroll extends CommandWithTarget {
|
||||
});
|
||||
}
|
||||
|
||||
/// Command the driver to ensure that the element represented by [finder]
|
||||
/// has been scrolled completely into view.
|
||||
class ScrollIntoView extends CommandWithTarget {
|
||||
@override
|
||||
final String kind = 'scrollIntoView';
|
||||
|
||||
ScrollIntoView(SerializableFinder finder) : super(finder);
|
||||
|
||||
static ScrollIntoView deserialize(Map<String, dynamic> json) {
|
||||
return new ScrollIntoView(SerializableFinder.deserialize(json));
|
||||
}
|
||||
}
|
||||
|
||||
/// The result of a [Scroll] command.
|
||||
class ScrollResult extends Result {
|
||||
/// Deserializes this result from JSON.
|
||||
static ScrollResult fromJson(Map<String, dynamic> json) {
|
||||
return new ScrollResult();
|
||||
}
|
||||
@ -94,3 +91,24 @@ class ScrollResult extends Result {
|
||||
@override
|
||||
Map<String, dynamic> toJson() => <String, dynamic>{};
|
||||
}
|
||||
|
||||
/// Command the driver to ensure that the element represented by [finder]
|
||||
/// has been scrolled completely into view.
|
||||
class ScrollIntoView extends CommandWithTarget {
|
||||
@override
|
||||
final String kind = 'scrollIntoView';
|
||||
|
||||
/// Creates this command given a [finder] used to locate the widget to be
|
||||
/// scrolled into view.
|
||||
ScrollIntoView(SerializableFinder finder) : super(finder);
|
||||
|
||||
/// Deserializes this command from JSON generated by [serialize].
|
||||
static ScrollIntoView deserialize(Map<String, dynamic> json) {
|
||||
return new ScrollIntoView(SerializableFinder.deserialize(json));
|
||||
}
|
||||
|
||||
// This is here just to be clear that this command isn't adding any extra
|
||||
// fields.
|
||||
@override
|
||||
Map<String, String> serialize() => super.serialize();
|
||||
}
|
||||
|
@ -10,6 +10,7 @@ class GetHealth implements Command {
|
||||
@override
|
||||
final String kind = 'get_health';
|
||||
|
||||
/// Deserializes the command from JSON generated by [serialize].
|
||||
static GetHealth deserialize(Map<String, String> json) => new GetHealth();
|
||||
|
||||
@override
|
||||
@ -30,10 +31,12 @@ final EnumIndex<HealthStatus> _healthStatusIndex =
|
||||
|
||||
/// Application health status.
|
||||
class Health extends Result {
|
||||
/// Creates a [Health] object with the given [status].
|
||||
Health(this.status) {
|
||||
assert(status != null);
|
||||
}
|
||||
|
||||
/// Deserializes the result from JSON.
|
||||
static Health fromJson(Map<String, dynamic> json) {
|
||||
return new Health(_healthStatusIndex.lookupBySimpleName(json['status']));
|
||||
}
|
||||
|
@ -5,14 +5,21 @@
|
||||
import 'message.dart';
|
||||
import 'find.dart';
|
||||
|
||||
/// Sets [text] in a text input widget.
|
||||
class SetInputText extends CommandWithTarget {
|
||||
@override
|
||||
final String kind = 'setInputText';
|
||||
|
||||
/// Creates a command.
|
||||
///
|
||||
/// [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);
|
||||
|
||||
/// The value of the text input to set.
|
||||
final String text;
|
||||
|
||||
/// Deserializes this command from JSON generated by [serialize].
|
||||
static SetInputText deserialize(Map<String, dynamic> json) {
|
||||
String text = json['text'];
|
||||
return new SetInputText(SerializableFinder.deserialize(json), text);
|
||||
@ -26,7 +33,9 @@ class SetInputText extends CommandWithTarget {
|
||||
}
|
||||
}
|
||||
|
||||
/// The result of a [SetInputText] command.
|
||||
class SetInputTextResult extends Result {
|
||||
/// Deserializes this result from JSON.
|
||||
static SetInputTextResult fromJson(Map<String, dynamic> json) {
|
||||
return new SetInputTextResult();
|
||||
}
|
||||
@ -35,22 +44,32 @@ class SetInputTextResult extends Result {
|
||||
Map<String, dynamic> toJson() => <String, dynamic>{};
|
||||
}
|
||||
|
||||
/// Submits text entered in a text input widget.
|
||||
///
|
||||
/// The definition of submitting input text can be found
|
||||
/// [here](https://docs.flutter.io/flutter/material/Input/onSubmitted.html).
|
||||
class SubmitInputText extends CommandWithTarget {
|
||||
@override
|
||||
final String kind = 'submitInputText';
|
||||
|
||||
/// Create a command that submits text on input widget identified by [finder].
|
||||
SubmitInputText(SerializableFinder finder) : super(finder);
|
||||
|
||||
/// Deserializes this command from JSON generated by [serialize].
|
||||
static SubmitInputText deserialize(Map<String, dynamic> json) {
|
||||
return new SubmitInputText(SerializableFinder.deserialize(json));
|
||||
}
|
||||
}
|
||||
|
||||
/// The result of a [SubmitInputText] command.
|
||||
class SubmitInputTextResult extends Result {
|
||||
/// Creates a result with [text] as the submitted value.
|
||||
SubmitInputTextResult(this.text);
|
||||
|
||||
/// The submitted value.
|
||||
final String text;
|
||||
|
||||
/// Deserializes this result from JSON.
|
||||
static SubmitInputTextResult fromJson(Map<String, dynamic> json) {
|
||||
return new SubmitInputTextResult(json['text']);
|
||||
}
|
||||
|
@ -3,12 +3,13 @@
|
||||
// found in the LICENSE file.
|
||||
|
||||
/// Timeline data recorded by the Flutter runtime.
|
||||
///
|
||||
/// The data is in the `chrome://tracing` format. It can be saved to a file
|
||||
/// and loaded in Chrome for visual inspection.
|
||||
///
|
||||
/// See https://docs.google.com/document/d/1CvAClvFfyA5R-PhYUmn5OOQtYMH4h6I0nSsKchNAySU/preview
|
||||
class Timeline {
|
||||
/// Creates a timeline given JSON-encoded timeline data.
|
||||
///
|
||||
/// [json] is in the `chrome://tracing` format. It can be saved to a file
|
||||
/// and loaded in Chrome for visual inspection.
|
||||
///
|
||||
/// See https://docs.google.com/document/d/1CvAClvFfyA5R-PhYUmn5OOQtYMH4h6I0nSsKchNAySU/preview
|
||||
factory Timeline.fromJson(Map<String, dynamic> json) {
|
||||
return new Timeline._(json, _parseEvents(json));
|
||||
}
|
||||
@ -24,6 +25,7 @@ class Timeline {
|
||||
|
||||
/// A single timeline event.
|
||||
class TimelineEvent {
|
||||
/// Creates a timeline event given JSON-encoded event data.
|
||||
factory TimelineEvent(Map<String, dynamic> json) {
|
||||
return new TimelineEvent._(
|
||||
json,
|
||||
|
@ -19,8 +19,9 @@ final JsonEncoder _prettyEncoder = new JsonEncoder.withIndent(' ');
|
||||
/// phase. Anything past that is in the danger of missing the frame as 60FPS.
|
||||
const Duration kBuildBudget = const Duration(milliseconds: 8);
|
||||
|
||||
/// Extracts statistics from the event loop timeline.
|
||||
/// Extracts statistics from a [Timeline].
|
||||
class TimelineSummary {
|
||||
/// Creates a timeline summary given a full timeline object.
|
||||
TimelineSummary.summarize(this._timeline);
|
||||
|
||||
final Timeline _timeline;
|
||||
@ -142,6 +143,7 @@ class TimedEvent {
|
||||
/// The duration of the event.
|
||||
final Duration duration;
|
||||
|
||||
/// Creates a timed event given begin and end timestamps in microseconds.
|
||||
TimedEvent(int beginTimeMicros, int endTimeMicros)
|
||||
: this.beginTimeMicros = beginTimeMicros,
|
||||
this.endTimeMicros = endTimeMicros,
|
||||
|
Loading…
x
Reference in New Issue
Block a user