Unverified Commit 147bb4db authored by Michael Goderbauer's avatar Michael Goderbauer Committed by GitHub

More null-safety fixes for flutter_driver (#75343)

parent 3c9ae131
...@@ -64,20 +64,6 @@ class WaitFor extends CommandWithTarget { ...@@ -64,20 +64,6 @@ class WaitFor extends CommandWithTarget {
String get kind => 'waitFor'; String get kind => 'waitFor';
} }
/// The result of a [WaitFor] command.
class WaitForResult extends Result {
/// Creates a [WaitForResult].
const WaitForResult();
/// Deserializes the result from JSON.
static WaitForResult fromJson(Map<String, dynamic> json) {
return const WaitForResult();
}
@override
Map<String, dynamic> toJson() => <String, dynamic>{};
}
/// A Flutter Driver command that waits until [finder] can no longer locate the target. /// A Flutter Driver command that waits until [finder] can no longer locate the target.
class WaitForAbsent extends CommandWithTarget { class WaitForAbsent extends CommandWithTarget {
/// Creates a command that waits for the widget identified by [finder] to /// Creates a command that waits for the widget identified by [finder] to
...@@ -94,20 +80,6 @@ class WaitForAbsent extends CommandWithTarget { ...@@ -94,20 +80,6 @@ class WaitForAbsent extends CommandWithTarget {
String get kind => 'waitForAbsent'; String get kind => 'waitForAbsent';
} }
/// The result of a [WaitForAbsent] command.
class WaitForAbsentResult extends Result {
/// Creates a [WaitForAbsentResult].
const WaitForAbsentResult();
/// Deserializes the result from JSON.
static WaitForAbsentResult fromJson(Map<String, dynamic> json) {
return const WaitForAbsentResult();
}
@override
Map<String, dynamic> toJson() => <String, dynamic>{};
}
/// Base class for Flutter Driver finders, objects that describe how the driver /// Base class for Flutter Driver finders, objects that describe how the driver
/// should search for elements. /// should search for elements.
abstract class SerializableFinder { abstract class SerializableFinder {
......
...@@ -25,17 +25,3 @@ class SetFrameSync extends Command { ...@@ -25,17 +25,3 @@ class SetFrameSync extends Command {
'enabled': '$enabled', 'enabled': '$enabled',
}); });
} }
/// The result of a [SetFrameSync] command.
class SetFrameSyncResult extends Result {
/// Creates a [SetFrameSyncResult].
const SetFrameSyncResult();
/// Deserializes this result from JSON.
static SetFrameSyncResult fromJson(Map<String, dynamic> json) {
return const SetFrameSyncResult();
}
@override
Map<String, dynamic> toJson() => <String, dynamic>{};
}
...@@ -4,7 +4,6 @@ ...@@ -4,7 +4,6 @@
import 'deserialization_factory.dart'; import 'deserialization_factory.dart';
import 'find.dart'; import 'find.dart';
import 'message.dart';
/// A Flutter Driver command that taps on a target widget located by [finder]. /// A Flutter Driver command that taps on a target widget located by [finder].
class Tap extends CommandWithTarget { class Tap extends CommandWithTarget {
...@@ -18,21 +17,6 @@ class Tap extends CommandWithTarget { ...@@ -18,21 +17,6 @@ class Tap extends CommandWithTarget {
String get kind => 'tap'; String get kind => 'tap';
} }
/// The result of a [Tap] command.
class TapResult extends Result {
/// Creates a [TapResult].
const TapResult();
/// Deserializes this result from JSON.
static TapResult fromJson(Map<String, dynamic> json) {
return const TapResult();
}
@override
Map<String, dynamic> toJson() => <String, dynamic>{};
}
/// A Flutter Driver command that commands the driver to perform a scrolling action. /// A Flutter Driver command that commands the driver to perform a scrolling action.
class Scroll extends CommandWithTarget { class Scroll extends CommandWithTarget {
/// Creates a scroll command that will attempt to scroll a scrollable view by /// Creates a scroll command that will attempt to scroll a scrollable view by
...@@ -78,20 +62,6 @@ class Scroll extends CommandWithTarget { ...@@ -78,20 +62,6 @@ class Scroll extends CommandWithTarget {
}); });
} }
/// The result of a [Scroll] command.
class ScrollResult extends Result {
/// Creates a [ScrollResult].
const ScrollResult();
/// Deserializes this result from JSON.
static ScrollResult fromJson(Map<String, dynamic> json) {
return const ScrollResult();
}
@override
Map<String, dynamic> toJson() => <String, dynamic>{};
}
/// A Flutter Driver command that commands the driver to ensure that the element /// A Flutter Driver command that commands the driver to ensure that the element
/// represented by [finder] has been scrolled completely into view. /// represented by [finder] has been scrolled completely into view.
class ScrollIntoView extends CommandWithTarget { class ScrollIntoView extends CommandWithTarget {
......
...@@ -154,7 +154,7 @@ mixin CommandHandlerFactory { ...@@ -154,7 +154,7 @@ mixin CommandHandlerFactory {
final TestTextInput _testTextInput = TestTextInput(); final TestTextInput _testTextInput = TestTextInput();
/// Deserializes the finder from JSON generated by [Command.serialize] or [CommandWithTarget.serialize]. /// Deserializes the finder from JSON generated by [Command.serialize] or [CommandWithTarget.serialize].
Future<Result?> handleCommand(Command command, WidgetController prober, CreateFinderFactory finderFactory) { Future<Result> handleCommand(Command command, WidgetController prober, CreateFinderFactory finderFactory) {
switch(command.kind) { switch(command.kind) {
case 'get_health': return _getHealth(command); case 'get_health': return _getHealth(command);
case 'get_layer_tree': return _getLayerTree(command); case 'get_layer_tree': return _getLayerTree(command);
...@@ -192,14 +192,14 @@ mixin CommandHandlerFactory { ...@@ -192,14 +192,14 @@ mixin CommandHandlerFactory {
return RenderTree(RendererBinding.instance?.renderView.toStringDeep()); return RenderTree(RendererBinding.instance?.renderView.toStringDeep());
} }
Future<EnterTextResult> _enterText(Command command) async { Future<Result> _enterText(Command command) async {
if (!_testTextInput.isRegistered) { if (!_testTextInput.isRegistered) {
throw 'Unable to fulfill `FlutterDriver.enterText`. Text emulation is ' throw 'Unable to fulfill `FlutterDriver.enterText`. Text emulation is '
'disabled. You can enable it using `FlutterDriver.setTextEntryEmulation`.'; 'disabled. You can enable it using `FlutterDriver.setTextEntryEmulation`.';
} }
final EnterText enterTextCommand = command as EnterText; final EnterText enterTextCommand = command as EnterText;
_testTextInput.enterText(enterTextCommand.text); _testTextInput.enterText(enterTextCommand.text);
return const EnterTextResult(); return Result.empty;
} }
Future<RequestDataResult> _requestData(Command command) async { Future<RequestDataResult> _requestData(Command command) async {
...@@ -210,49 +210,49 @@ mixin CommandHandlerFactory { ...@@ -210,49 +210,49 @@ mixin CommandHandlerFactory {
: await dataHandler(requestDataCommand.message)); : await dataHandler(requestDataCommand.message));
} }
Future<SetFrameSyncResult> _setFrameSync(Command command) async { Future<Result> _setFrameSync(Command command) async {
final SetFrameSync setFrameSyncCommand = command as SetFrameSync; final SetFrameSync setFrameSyncCommand = command as SetFrameSync;
_frameSync = setFrameSyncCommand.enabled; _frameSync = setFrameSyncCommand.enabled;
return const SetFrameSyncResult(); return Result.empty;
} }
Future<TapResult> _tap(Command command, WidgetController prober, CreateFinderFactory finderFactory) async { Future<Result> _tap(Command command, WidgetController prober, CreateFinderFactory finderFactory) async {
final Tap tapCommand = command as Tap; final Tap tapCommand = command as Tap;
final Finder computedFinder = await waitForElement( final Finder computedFinder = await waitForElement(
finderFactory.createFinder(tapCommand.finder).hitTestable(), finderFactory.createFinder(tapCommand.finder).hitTestable(),
); );
await prober.tap(computedFinder); await prober.tap(computedFinder);
return const TapResult(); return Result.empty;
} }
Future<WaitForResult> _waitFor(Command command, CreateFinderFactory finderFactory) async { Future<Result> _waitFor(Command command, CreateFinderFactory finderFactory) async {
final WaitFor waitForCommand = command as WaitFor; final WaitFor waitForCommand = command as WaitFor;
await waitForElement(finderFactory.createFinder(waitForCommand.finder)); await waitForElement(finderFactory.createFinder(waitForCommand.finder));
return const WaitForResult(); return Result.empty;
} }
Future<WaitForAbsentResult> _waitForAbsent(Command command, CreateFinderFactory finderFactory) async { Future<Result> _waitForAbsent(Command command, CreateFinderFactory finderFactory) async {
final WaitForAbsent waitForAbsentCommand = command as WaitForAbsent; final WaitForAbsent waitForAbsentCommand = command as WaitForAbsent;
await waitForAbsentElement(finderFactory.createFinder(waitForAbsentCommand.finder)); await waitForAbsentElement(finderFactory.createFinder(waitForAbsentCommand.finder));
return const WaitForAbsentResult(); return Result.empty;
} }
Future<Result?> _waitForCondition(Command command) async { Future<Result> _waitForCondition(Command command) async {
assert(command != null); assert(command != null);
final WaitForCondition waitForConditionCommand = command as WaitForCondition; final WaitForCondition waitForConditionCommand = command as WaitForCondition;
final WaitCondition condition = deserializeCondition(waitForConditionCommand.condition); final WaitCondition condition = deserializeCondition(waitForConditionCommand.condition);
await condition.wait(); await condition.wait();
return null; return Result.empty;
} }
@Deprecated( @Deprecated(
'This method has been deprecated in favor of _waitForCondition. ' 'This method has been deprecated in favor of _waitForCondition. '
'This feature was deprecated after v1.9.3.' 'This feature was deprecated after v1.9.3.'
) )
Future<Result?> _waitUntilNoTransientCallbacks(Command command) async { Future<Result> _waitUntilNoTransientCallbacks(Command command) async {
if (SchedulerBinding.instance!.transientCallbackCount != 0) if (SchedulerBinding.instance!.transientCallbackCount != 0)
await _waitUntilFrame(() => SchedulerBinding.instance!.transientCallbackCount == 0); await _waitUntilFrame(() => SchedulerBinding.instance!.transientCallbackCount == 0);
return null; return Result.empty;
} }
/// Returns a future that waits until no pending frame is scheduled (frame is synced). /// Returns a future that waits until no pending frame is scheduled (frame is synced).
...@@ -278,12 +278,12 @@ mixin CommandHandlerFactory { ...@@ -278,12 +278,12 @@ mixin CommandHandlerFactory {
'This method has been deprecated in favor of _waitForCondition. ' 'This method has been deprecated in favor of _waitForCondition. '
'This feature was deprecated after v1.9.3.' 'This feature was deprecated after v1.9.3.'
) )
Future<Result?> _waitUntilNoPendingFrame(Command command) async { Future<Result> _waitUntilNoPendingFrame(Command command) async {
await _waitUntilFrame(() { await _waitUntilFrame(() {
return SchedulerBinding.instance!.transientCallbackCount == 0 return SchedulerBinding.instance!.transientCallbackCount == 0
&& !SchedulerBinding.instance!.hasScheduledFrame; && !SchedulerBinding.instance!.hasScheduledFrame;
}); });
return null; return Result.empty;
} }
Future<GetSemanticsIdResult> _getSemanticsId(Command command, CreateFinderFactory finderFactory) async { Future<GetSemanticsIdResult> _getSemanticsId(Command command, CreateFinderFactory finderFactory) async {
...@@ -351,7 +351,7 @@ mixin CommandHandlerFactory { ...@@ -351,7 +351,7 @@ mixin CommandHandlerFactory {
))); )));
} }
Future<ScrollResult> _scroll(Command command, WidgetController _prober, CreateFinderFactory finderFactory) async { Future<Result> _scroll(Command command, WidgetController _prober, CreateFinderFactory finderFactory) async {
final Scroll scrollCommand = command as Scroll; final Scroll scrollCommand = command as Scroll;
final Finder target = await waitForElement(finderFactory.createFinder(scrollCommand.finder)); final Finder target = await waitForElement(finderFactory.createFinder(scrollCommand.finder));
final int totalMoves = scrollCommand.duration.inMicroseconds * scrollCommand.frequency ~/ Duration.microsecondsPerSecond; final int totalMoves = scrollCommand.duration.inMicroseconds * scrollCommand.frequency ~/ Duration.microsecondsPerSecond;
...@@ -369,14 +369,14 @@ mixin CommandHandlerFactory { ...@@ -369,14 +369,14 @@ mixin CommandHandlerFactory {
} }
_prober.binding.handlePointerEvent(pointer.up()); _prober.binding.handlePointerEvent(pointer.up());
return const ScrollResult(); return Result.empty;
} }
Future<ScrollResult> _scrollIntoView(Command command, CreateFinderFactory finderFactory) async { Future<Result> _scrollIntoView(Command command, CreateFinderFactory finderFactory) async {
final ScrollIntoView scrollIntoViewCommand = command as ScrollIntoView; final ScrollIntoView scrollIntoViewCommand = command as ScrollIntoView;
final Finder target = await waitForElement(finderFactory.createFinder(scrollIntoViewCommand.finder)); final Finder target = await waitForElement(finderFactory.createFinder(scrollIntoViewCommand.finder));
await Scrollable.ensureVisible(target.evaluate().single, duration: const Duration(milliseconds: 100), alignment: scrollIntoViewCommand.alignment); await Scrollable.ensureVisible(target.evaluate().single, duration: const Duration(milliseconds: 100), alignment: scrollIntoViewCommand.alignment);
return const ScrollResult(); return Result.empty;
} }
Future<GetTextResult> _getText(Command command, CreateFinderFactory finderFactory) async { Future<GetTextResult> _getText(Command command, CreateFinderFactory finderFactory) async {
...@@ -408,14 +408,14 @@ mixin CommandHandlerFactory { ...@@ -408,14 +408,14 @@ mixin CommandHandlerFactory {
return GetTextResult(text); return GetTextResult(text);
} }
Future<SetTextEntryEmulationResult> _setTextEntryEmulation(Command command) async { Future<Result> _setTextEntryEmulation(Command command) async {
final SetTextEntryEmulation setTextEntryEmulationCommand = command as SetTextEntryEmulation; final SetTextEntryEmulation setTextEntryEmulationCommand = command as SetTextEntryEmulation;
if (setTextEntryEmulationCommand.enabled) { if (setTextEntryEmulationCommand.enabled) {
_testTextInput.register(); _testTextInput.register();
} else { } else {
_testTextInput.unregister(); _testTextInput.unregister();
} }
return const SetTextEntryEmulationResult(); return Result.empty;
} }
SemanticsHandle? _semantics; SemanticsHandle? _semantics;
...@@ -446,9 +446,9 @@ mixin CommandHandlerFactory { ...@@ -446,9 +446,9 @@ mixin CommandHandlerFactory {
'This method has been deprecated in favor of _waitForCondition. ' 'This method has been deprecated in favor of _waitForCondition. '
'This feature was deprecated after v1.9.3.' 'This feature was deprecated after v1.9.3.'
) )
Future<Result?> _waitUntilFirstFrameRasterized(Command command) async { Future<Result> _waitUntilFirstFrameRasterized(Command command) async {
await WidgetsBinding.instance!.waitUntilFirstFrameRasterized; await WidgetsBinding.instance!.waitUntilFirstFrameRasterized;
return null; return Result.empty;
} }
/// Runs `finder` repeatedly until it finds one or more [Element]s. /// Runs `finder` repeatedly until it finds one or more [Element]s.
......
...@@ -64,6 +64,19 @@ abstract class Result { ...@@ -64,6 +64,19 @@ abstract class Result {
/// A const constructor to allow subclasses to be const. /// A const constructor to allow subclasses to be const.
const Result(); const Result();
/// An empty responds that does not include any result data.
///
/// Consider using this object as a result for [Command]s that do not return
/// any data.
static const Result empty = _EmptyResult();
/// Serializes this message to a JSON map. /// Serializes this message to a JSON map.
Map<String, dynamic> toJson(); Map<String, dynamic> toJson();
} }
class _EmptyResult extends Result {
const _EmptyResult();
@override
Map<String, dynamic> toJson() => <String, dynamic>{};
}
...@@ -59,20 +59,6 @@ class EnterText extends Command { ...@@ -59,20 +59,6 @@ class EnterText extends Command {
}); });
} }
/// The result of the [EnterText] command.
class EnterTextResult extends Result {
/// Creates a successful result of entering the text.
const EnterTextResult();
/// Deserializes the result from JSON.
static EnterTextResult fromJson(Map<String, dynamic> json) {
return const EnterTextResult();
}
@override
Map<String, dynamic> toJson() => const <String, String>{};
}
/// A Flutter Driver command that enables and disables text entry emulation. /// A Flutter Driver command that enables and disables text entry emulation.
class SetTextEntryEmulation extends Command { class SetTextEntryEmulation extends Command {
/// Creates a command that enables and disables text entry emulation. /// Creates a command that enables and disables text entry emulation.
...@@ -94,17 +80,3 @@ class SetTextEntryEmulation extends Command { ...@@ -94,17 +80,3 @@ class SetTextEntryEmulation extends Command {
'enabled': '$enabled', 'enabled': '$enabled',
}); });
} }
/// The result of the [SetTextEntryEmulation] command.
class SetTextEntryEmulationResult extends Result {
/// Creates a successful result.
const SetTextEntryEmulationResult();
/// Deserializes the result from JSON.
static SetTextEntryEmulationResult fromJson(Map<String, dynamic> json) {
return const SetTextEntryEmulationResult();
}
@override
Map<String, dynamic> toJson() => const <String, String>{};
}
...@@ -433,7 +433,7 @@ class FlutterDriverExtension with DeserializeFinderFactory, CreateFinderFactory, ...@@ -433,7 +433,7 @@ class FlutterDriverExtension with DeserializeFinderFactory, CreateFinderFactory,
} }
@override @override
Future<Result?> handleCommand(Command command, WidgetController prober, CreateFinderFactory finderFactory) { Future<Result> handleCommand(Command command, WidgetController prober, CreateFinderFactory finderFactory) {
final String kind = command.kind; final String kind = command.kind;
if(_commandExtensions.containsKey(kind)) { if(_commandExtensions.containsKey(kind)) {
return _commandExtensions[kind]!.call(command, prober, finderFactory, this); return _commandExtensions[kind]!.call(command, prober, finderFactory, this);
......
...@@ -56,7 +56,7 @@ void main() { ...@@ -56,7 +56,7 @@ void main() {
result, result,
<String, dynamic>{ <String, dynamic>{
'isError': false, 'isError': false,
'response': null, 'response': <String, dynamic>{},
}, },
); );
}); });
...@@ -81,7 +81,7 @@ void main() { ...@@ -81,7 +81,7 @@ void main() {
result, result,
<String, dynamic>{ <String, dynamic>{
'isError': false, 'isError': false,
'response': null, 'response': <String, dynamic>{},
}, },
); );
}); });
...@@ -117,7 +117,7 @@ void main() { ...@@ -117,7 +117,7 @@ void main() {
result, result,
<String, dynamic>{ <String, dynamic>{
'isError': false, 'isError': false,
'response': null, 'response': <String, dynamic>{},
}, },
); );
}); });
...@@ -142,7 +142,7 @@ void main() { ...@@ -142,7 +142,7 @@ void main() {
result, result,
<String, dynamic>{ <String, dynamic>{
'isError': false, 'isError': false,
'response': null, 'response': <String, dynamic>{},
}, },
); );
}); });
...@@ -159,7 +159,7 @@ void main() { ...@@ -159,7 +159,7 @@ void main() {
result, result,
<String, dynamic>{ <String, dynamic>{
'isError': false, 'isError': false,
'response': null, 'response': <String, dynamic>{},
}, },
); );
}); });
...@@ -182,7 +182,7 @@ void main() { ...@@ -182,7 +182,7 @@ void main() {
result, result,
<String, dynamic>{ <String, dynamic>{
'isError': false, 'isError': false,
'response': null, 'response': <String, dynamic>{},
}, },
); );
}); });
...@@ -201,7 +201,7 @@ void main() { ...@@ -201,7 +201,7 @@ void main() {
result, result,
<String, dynamic>{ <String, dynamic>{
'isError': false, 'isError': false,
'response': null, 'response': <String, dynamic>{},
}, },
); );
}); });
...@@ -230,7 +230,7 @@ void main() { ...@@ -230,7 +230,7 @@ void main() {
result, result,
<String, dynamic>{ <String, dynamic>{
'isError': false, 'isError': false,
'response': null, 'response': <String, dynamic>{},
}, },
); );
}); });
...@@ -259,7 +259,7 @@ void main() { ...@@ -259,7 +259,7 @@ void main() {
result, result,
<String, dynamic>{ <String, dynamic>{
'isError': false, 'isError': false,
'response': null, 'response': <String, dynamic>{},
}, },
); );
}); });
...@@ -277,7 +277,7 @@ void main() { ...@@ -277,7 +277,7 @@ void main() {
result, result,
<String, dynamic>{ <String, dynamic>{
'isError': false, 'isError': false,
'response': null, 'response': <String, dynamic>{},
}, },
); );
}); });
...@@ -310,7 +310,7 @@ void main() { ...@@ -310,7 +310,7 @@ void main() {
result, result,
<String, dynamic>{ <String, dynamic>{
'isError': false, 'isError': false,
'response': null, 'response': <String, dynamic>{},
}, },
); );
}); });
...@@ -359,7 +359,7 @@ void main() { ...@@ -359,7 +359,7 @@ void main() {
result, result,
<String, dynamic>{ <String, dynamic>{
'isError': false, 'isError': false,
'response': null, 'response': <String, dynamic>{},
}, },
); );
}); });
...@@ -410,7 +410,7 @@ void main() { ...@@ -410,7 +410,7 @@ void main() {
result, result,
<String, dynamic>{ <String, dynamic>{
'isError': false, 'isError': false,
'response': null, 'response': <String, dynamic>{},
}, },
); );
}); });
...@@ -460,7 +460,7 @@ void main() { ...@@ -460,7 +460,7 @@ void main() {
result, result,
<String, dynamic>{ <String, dynamic>{
'isError': false, 'isError': false,
'response': null, 'response': <String, dynamic>{},
}, },
); );
}); });
...@@ -1145,7 +1145,7 @@ void main() { ...@@ -1145,7 +1145,7 @@ void main() {
result, result,
<String, dynamic>{ <String, dynamic>{
'isError': false, 'isError': false,
'response': null, 'response': <String, dynamic>{},
}, },
); );
}); });
...@@ -1171,7 +1171,7 @@ void main() { ...@@ -1171,7 +1171,7 @@ void main() {
result, result,
<String, dynamic>{ <String, dynamic>{
'isError': false, 'isError': false,
'response': null, 'response': <String, dynamic>{},
}, },
); );
}); });
...@@ -1195,7 +1195,7 @@ void main() { ...@@ -1195,7 +1195,7 @@ void main() {
result, result,
<String, dynamic>{ <String, dynamic>{
'isError': false, 'isError': false,
'response': null, 'response': <String, dynamic>{},
}, },
); );
}); });
......
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