mirror of
https://github.com/flutter/flutter.git
synced 2025-06-03 00:51:18 +00:00
Revert "Flutter Driver - Create widget finders from serialized finders extensions (#67456)" (#67687)
This reverts commit 74f6fa4564
.
This commit is contained in:
parent
74f6fa4564
commit
4042eb97b9
@ -1,115 +0,0 @@
|
||||
// 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_test/flutter_test.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
|
||||
import 'find.dart';
|
||||
|
||||
/// A factory which creates [Finder]s from [SerializableFinder]s.
|
||||
mixin CreateFinderFactory {
|
||||
/// Creates the flutter widget finder from [SerializableFinder].
|
||||
Finder createFinder(SerializableFinder finder) {
|
||||
switch (finder.finderType) {
|
||||
case 'ByText':
|
||||
return _createByTextFinder(finder as ByText);
|
||||
case 'ByTooltipMessage':
|
||||
return _createByTooltipMessageFinder(finder as ByTooltipMessage);
|
||||
case 'BySemanticsLabel':
|
||||
return _createBySemanticsLabelFinder(finder as BySemanticsLabel);
|
||||
case 'ByValueKey':
|
||||
return _createByValueKeyFinder(finder as ByValueKey);
|
||||
case 'ByType':
|
||||
return _createByTypeFinder(finder as ByType);
|
||||
case 'PageBack':
|
||||
return _createPageBackFinder();
|
||||
case 'Ancestor':
|
||||
return _createAncestorFinder(finder as Ancestor);
|
||||
case 'Descendant':
|
||||
return _createDescendantFinder(finder as Descendant);
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
Finder _createByTextFinder(ByText arguments) {
|
||||
return find.text(arguments.text);
|
||||
}
|
||||
|
||||
Finder _createByTooltipMessageFinder(ByTooltipMessage arguments) {
|
||||
return find.byElementPredicate((Element element) {
|
||||
final Widget widget = element.widget;
|
||||
if (widget is Tooltip) {
|
||||
return widget.message == arguments.text;
|
||||
}
|
||||
return false;
|
||||
}, description: 'widget with text tooltip "${arguments.text}"');
|
||||
}
|
||||
|
||||
Finder _createBySemanticsLabelFinder(BySemanticsLabel arguments) {
|
||||
return find.byElementPredicate((Element element) {
|
||||
if (element is! RenderObjectElement) {
|
||||
return false;
|
||||
}
|
||||
final String semanticsLabel = element.renderObject?.debugSemantics?.label;
|
||||
if (semanticsLabel == null) {
|
||||
return false;
|
||||
}
|
||||
final Pattern label = arguments.label;
|
||||
return label is RegExp
|
||||
? label.hasMatch(semanticsLabel)
|
||||
: label == semanticsLabel;
|
||||
}, description: 'widget with semantic label "${arguments.label}"');
|
||||
}
|
||||
|
||||
Finder _createByValueKeyFinder(ByValueKey arguments) {
|
||||
switch (arguments.keyValueType) {
|
||||
case 'int':
|
||||
return find.byKey(ValueKey<int>(arguments.keyValue as int));
|
||||
case 'String':
|
||||
return find.byKey(ValueKey<String>(arguments.keyValue as String));
|
||||
default:
|
||||
throw 'Unsupported ByValueKey type: ${arguments.keyValueType}';
|
||||
}
|
||||
}
|
||||
|
||||
Finder _createByTypeFinder(ByType arguments) {
|
||||
return find.byElementPredicate((Element element) {
|
||||
return element.widget.runtimeType.toString() == arguments.type;
|
||||
}, description: 'widget with runtimeType "${arguments.type}"');
|
||||
}
|
||||
|
||||
Finder _createPageBackFinder() {
|
||||
return find.byElementPredicate((Element element) {
|
||||
final Widget widget = element.widget;
|
||||
if (widget is Tooltip) {
|
||||
return widget.message == 'Back';
|
||||
}
|
||||
if (widget is CupertinoNavigationBarBackButton) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}, description: 'Material or Cupertino back button');
|
||||
}
|
||||
|
||||
Finder _createAncestorFinder(Ancestor arguments) {
|
||||
final Finder finder = find.ancestor(
|
||||
of: createFinder(arguments.of),
|
||||
matching: createFinder(arguments.matching),
|
||||
matchRoot: arguments.matchRoot,
|
||||
);
|
||||
return arguments.firstMatchOnly ? finder.first : finder;
|
||||
}
|
||||
|
||||
Finder _createDescendantFinder(Descendant arguments) {
|
||||
final Finder finder = find.descendant(
|
||||
of: createFinder(arguments.of),
|
||||
matching: createFinder(arguments.matching),
|
||||
matchRoot: arguments.matchRoot,
|
||||
);
|
||||
return arguments.firstMatchOnly ? finder.first : finder;
|
||||
}
|
||||
}
|
@ -24,7 +24,7 @@ mixin DeserializeFinderFactory {
|
||||
case 'Descendant': return Descendant.deserialize(json, this);
|
||||
case 'Ancestor': return Ancestor.deserialize(json, this);
|
||||
}
|
||||
return null;
|
||||
throw DriverError('Unsupported search specification type $finderType');
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4,7 +4,6 @@
|
||||
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flutter_driver/src/common/create_finder_factory.dart';
|
||||
import 'package:meta/meta.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
@ -124,7 +123,7 @@ class _DriverBinding extends BindingBase with SchedulerBinding, ServicesBinding,
|
||||
/// return Some(json['title']);
|
||||
/// }
|
||||
///
|
||||
/// Finder createFinder(SerializableFinder finder, CreateFinderFactory finderFactory) {
|
||||
/// Finder createFinder(SerializableFinder finder) {
|
||||
/// Some someFinder = finder as Some;
|
||||
///
|
||||
/// return find.byElementPredicate((Element element) {
|
||||
@ -157,13 +156,11 @@ abstract class FinderExtension {
|
||||
String get finderType;
|
||||
|
||||
/// Deserializes the finder from JSON generated by [SerializableFinder.serialize].
|
||||
/// [finderFactory] could be used to deserialize nested finders.
|
||||
SerializableFinder deserialize(Map<String, String> params, DeserializeFinderFactory finderFactory);
|
||||
|
||||
/// Signature for functions that run the given finder and return the [Element]
|
||||
/// found, if any, or null otherwise.
|
||||
/// [finderFactory] could be used to create nested finders.
|
||||
Finder createFinder(SerializableFinder finder, CreateFinderFactory finderFactory);
|
||||
Finder createFinder(SerializableFinder finder);
|
||||
}
|
||||
|
||||
/// The class that manages communication between a Flutter Driver test and the
|
||||
@ -172,7 +169,7 @@ abstract class FinderExtension {
|
||||
/// This is not normally used directly. It is instantiated automatically when
|
||||
/// calling [enableFlutterDriverExtension].
|
||||
@visibleForTesting
|
||||
class FlutterDriverExtension with DeserializeFinderFactory, CreateFinderFactory {
|
||||
class FlutterDriverExtension with DeserializeFinderFactory {
|
||||
/// Creates an object to manage a Flutter Driver connection.
|
||||
FlutterDriverExtension(
|
||||
this._requestDataHandler,
|
||||
@ -357,39 +354,112 @@ class FlutterDriverExtension with DeserializeFinderFactory, CreateFinderFactory
|
||||
return finder;
|
||||
}
|
||||
|
||||
@override
|
||||
SerializableFinder deserializeFinder(Map<String, String> json) {
|
||||
final SerializableFinder standard = super.deserializeFinder(json);
|
||||
if (standard != null) {
|
||||
return standard;
|
||||
}
|
||||
|
||||
final String finderType = json['finderType'];
|
||||
if (_finderExtensions.containsKey(finderType)) {
|
||||
return _finderExtensions[finderType].deserialize(json, this);
|
||||
}
|
||||
|
||||
throw DriverError('Unsupported search specification type $finderType');
|
||||
Finder _createByTextFinder(ByText arguments) {
|
||||
return find.text(arguments.text);
|
||||
}
|
||||
|
||||
@override
|
||||
Finder createFinder(SerializableFinder finder) {
|
||||
final Finder standard = super.createFinder(finder);
|
||||
if(standard != null) {
|
||||
return standard;
|
||||
}
|
||||
Finder _createByTooltipMessageFinder(ByTooltipMessage arguments) {
|
||||
return find.byElementPredicate((Element element) {
|
||||
final Widget widget = element.widget;
|
||||
if (widget is Tooltip)
|
||||
return widget.message == arguments.text;
|
||||
return false;
|
||||
}, description: 'widget with text tooltip "${arguments.text}"');
|
||||
}
|
||||
|
||||
if (_finderExtensions.containsKey(finder.finderType)) {
|
||||
return _finderExtensions[finder.finderType].createFinder(finder, this);
|
||||
}
|
||||
Finder _createBySemanticsLabelFinder(BySemanticsLabel arguments) {
|
||||
return find.byElementPredicate((Element element) {
|
||||
if (element is! RenderObjectElement) {
|
||||
return false;
|
||||
}
|
||||
final String semanticsLabel = element.renderObject?.debugSemantics?.label;
|
||||
if (semanticsLabel == null) {
|
||||
return false;
|
||||
}
|
||||
final Pattern label = arguments.label;
|
||||
return label is RegExp
|
||||
? label.hasMatch(semanticsLabel)
|
||||
: label == semanticsLabel;
|
||||
}, description: 'widget with semantic label "${arguments.label}"');
|
||||
}
|
||||
|
||||
throw DriverError('Unsupported search specification type ${finder.finderType}');
|
||||
Finder _createByValueKeyFinder(ByValueKey arguments) {
|
||||
switch (arguments.keyValueType) {
|
||||
case 'int':
|
||||
return find.byKey(ValueKey<int>(arguments.keyValue as int));
|
||||
case 'String':
|
||||
return find.byKey(ValueKey<String>(arguments.keyValue as String));
|
||||
default:
|
||||
throw 'Unsupported ByValueKey type: ${arguments.keyValueType}';
|
||||
}
|
||||
}
|
||||
|
||||
Finder _createByTypeFinder(ByType arguments) {
|
||||
return find.byElementPredicate((Element element) {
|
||||
return element.widget.runtimeType.toString() == arguments.type;
|
||||
}, description: 'widget with runtimeType "${arguments.type}"');
|
||||
}
|
||||
|
||||
Finder _createPageBackFinder() {
|
||||
return find.byElementPredicate((Element element) {
|
||||
final Widget widget = element.widget;
|
||||
if (widget is Tooltip)
|
||||
return widget.message == 'Back';
|
||||
if (widget is CupertinoNavigationBarBackButton)
|
||||
return true;
|
||||
return false;
|
||||
}, description: 'Material or Cupertino back button');
|
||||
}
|
||||
|
||||
Finder _createAncestorFinder(Ancestor arguments) {
|
||||
final Finder finder = find.ancestor(
|
||||
of: _createFinder(arguments.of),
|
||||
matching: _createFinder(arguments.matching),
|
||||
matchRoot: arguments.matchRoot,
|
||||
);
|
||||
return arguments.firstMatchOnly ? finder.first : finder;
|
||||
}
|
||||
|
||||
Finder _createDescendantFinder(Descendant arguments) {
|
||||
final Finder finder = find.descendant(
|
||||
of: _createFinder(arguments.of),
|
||||
matching: _createFinder(arguments.matching),
|
||||
matchRoot: arguments.matchRoot,
|
||||
);
|
||||
return arguments.firstMatchOnly ? finder.first : finder;
|
||||
}
|
||||
|
||||
Finder _createFinder(SerializableFinder finder) {
|
||||
switch (finder.finderType) {
|
||||
case 'ByText':
|
||||
return _createByTextFinder(finder as ByText);
|
||||
case 'ByTooltipMessage':
|
||||
return _createByTooltipMessageFinder(finder as ByTooltipMessage);
|
||||
case 'BySemanticsLabel':
|
||||
return _createBySemanticsLabelFinder(finder as BySemanticsLabel);
|
||||
case 'ByValueKey':
|
||||
return _createByValueKeyFinder(finder as ByValueKey);
|
||||
case 'ByType':
|
||||
return _createByTypeFinder(finder as ByType);
|
||||
case 'PageBack':
|
||||
return _createPageBackFinder();
|
||||
case 'Ancestor':
|
||||
return _createAncestorFinder(finder as Ancestor);
|
||||
case 'Descendant':
|
||||
return _createDescendantFinder(finder as Descendant);
|
||||
default:
|
||||
if (_finderExtensions.containsKey(finder.finderType)) {
|
||||
return _finderExtensions[finder.finderType].createFinder(finder);
|
||||
} else {
|
||||
throw 'Unsupported finder type: ${finder.finderType}';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Future<TapResult> _tap(Command command) async {
|
||||
final Tap tapCommand = command as Tap;
|
||||
final Finder computedFinder = await _waitForElement(
|
||||
createFinder(tapCommand.finder).hitTestable()
|
||||
_createFinder(tapCommand.finder).hitTestable()
|
||||
);
|
||||
await _prober.tap(computedFinder);
|
||||
return const TapResult();
|
||||
@ -397,13 +467,13 @@ class FlutterDriverExtension with DeserializeFinderFactory, CreateFinderFactory
|
||||
|
||||
Future<WaitForResult> _waitFor(Command command) async {
|
||||
final WaitFor waitForCommand = command as WaitFor;
|
||||
await _waitForElement(createFinder(waitForCommand.finder));
|
||||
await _waitForElement(_createFinder(waitForCommand.finder));
|
||||
return const WaitForResult();
|
||||
}
|
||||
|
||||
Future<WaitForAbsentResult> _waitForAbsent(Command command) async {
|
||||
final WaitForAbsent waitForAbsentCommand = command as WaitForAbsent;
|
||||
await _waitForAbsentElement(createFinder(waitForAbsentCommand.finder));
|
||||
await _waitForAbsentElement(_createFinder(waitForAbsentCommand.finder));
|
||||
return const WaitForAbsentResult();
|
||||
}
|
||||
|
||||
@ -458,7 +528,7 @@ class FlutterDriverExtension with DeserializeFinderFactory, CreateFinderFactory
|
||||
|
||||
Future<GetSemanticsIdResult> _getSemanticsId(Command command) async {
|
||||
final GetSemanticsId semanticsCommand = command as GetSemanticsId;
|
||||
final Finder target = await _waitForElement(createFinder(semanticsCommand.finder));
|
||||
final Finder target = await _waitForElement(_createFinder(semanticsCommand.finder));
|
||||
final Iterable<Element> elements = target.evaluate();
|
||||
if (elements.length > 1) {
|
||||
throw StateError('Found more than one element with the same ID: $elements');
|
||||
@ -477,7 +547,7 @@ class FlutterDriverExtension with DeserializeFinderFactory, CreateFinderFactory
|
||||
|
||||
Future<GetOffsetResult> _getOffset(Command command) async {
|
||||
final GetOffset getOffsetCommand = command as GetOffset;
|
||||
final Finder finder = await _waitForElement(createFinder(getOffsetCommand.finder));
|
||||
final Finder finder = await _waitForElement(_createFinder(getOffsetCommand.finder));
|
||||
final Element element = finder.evaluate().single;
|
||||
final RenderBox box = element.renderObject as RenderBox;
|
||||
Offset localPoint;
|
||||
@ -504,7 +574,7 @@ class FlutterDriverExtension with DeserializeFinderFactory, CreateFinderFactory
|
||||
|
||||
Future<DiagnosticsTreeResult> _getDiagnosticsTree(Command command) async {
|
||||
final GetDiagnosticsTree diagnosticsCommand = command as GetDiagnosticsTree;
|
||||
final Finder finder = await _waitForElement(createFinder(diagnosticsCommand.finder));
|
||||
final Finder finder = await _waitForElement(_createFinder(diagnosticsCommand.finder));
|
||||
final Element element = finder.evaluate().single;
|
||||
DiagnosticsNode diagnosticsNode;
|
||||
switch (diagnosticsCommand.diagnosticsType) {
|
||||
@ -523,7 +593,7 @@ class FlutterDriverExtension with DeserializeFinderFactory, CreateFinderFactory
|
||||
|
||||
Future<ScrollResult> _scroll(Command command) async {
|
||||
final Scroll scrollCommand = command as Scroll;
|
||||
final Finder target = await _waitForElement(createFinder(scrollCommand.finder));
|
||||
final Finder target = await _waitForElement(_createFinder(scrollCommand.finder));
|
||||
final int totalMoves = scrollCommand.duration.inMicroseconds * scrollCommand.frequency ~/ Duration.microsecondsPerSecond;
|
||||
final Offset delta = Offset(scrollCommand.dx, scrollCommand.dy) / totalMoves.toDouble();
|
||||
final Duration pause = scrollCommand.duration ~/ totalMoves;
|
||||
@ -544,14 +614,14 @@ class FlutterDriverExtension with DeserializeFinderFactory, CreateFinderFactory
|
||||
|
||||
Future<ScrollResult> _scrollIntoView(Command command) async {
|
||||
final ScrollIntoView scrollIntoViewCommand = command as ScrollIntoView;
|
||||
final Finder target = await _waitForElement(createFinder(scrollIntoViewCommand.finder));
|
||||
final Finder target = await _waitForElement(_createFinder(scrollIntoViewCommand.finder));
|
||||
await Scrollable.ensureVisible(target.evaluate().single, duration: const Duration(milliseconds: 100), alignment: scrollIntoViewCommand.alignment ?? 0.0);
|
||||
return const ScrollResult();
|
||||
}
|
||||
|
||||
Future<GetTextResult> _getText(Command command) async {
|
||||
final GetText getTextCommand = command as GetText;
|
||||
final Finder target = await _waitForElement(createFinder(getTextCommand.finder));
|
||||
final Finder target = await _waitForElement(_createFinder(getTextCommand.finder));
|
||||
|
||||
final Widget widget = target.evaluate().single.widget;
|
||||
String text;
|
||||
|
@ -18,9 +18,6 @@ import 'package:flutter_driver/src/common/wait.dart';
|
||||
import 'package:flutter_driver/src/extension/extension.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
import 'stubs/stub_finder.dart';
|
||||
import 'stubs/stub_finder_extension.dart';
|
||||
|
||||
Future<void> silenceDriverLogger(AsyncCallback callback) async {
|
||||
final DriverLogCallback oldLogger = driverLog;
|
||||
driverLog = (String source, String message) { };
|
||||
@ -33,18 +30,18 @@ Future<void> silenceDriverLogger(AsyncCallback callback) async {
|
||||
|
||||
void main() {
|
||||
group('waitUntilNoTransientCallbacks', () {
|
||||
FlutterDriverExtension driverExtension;
|
||||
FlutterDriverExtension extension;
|
||||
Map<String, dynamic> result;
|
||||
int messageId = 0;
|
||||
final List<String> log = <String>[];
|
||||
|
||||
setUp(() {
|
||||
result = null;
|
||||
driverExtension = FlutterDriverExtension((String message) async { log.add(message); return (messageId += 1).toString(); }, false);
|
||||
extension = FlutterDriverExtension((String message) async { log.add(message); return (messageId += 1).toString(); }, false);
|
||||
});
|
||||
|
||||
testWidgets('returns immediately when transient callback queue is empty', (WidgetTester tester) async {
|
||||
driverExtension.call(const WaitUntilNoTransientCallbacks().serialize())
|
||||
extension.call(const WaitUntilNoTransientCallbacks().serialize())
|
||||
.then<void>(expectAsync1((Map<String, dynamic> r) {
|
||||
result = r;
|
||||
}));
|
||||
@ -64,7 +61,7 @@ void main() {
|
||||
// Intentionally blank. We only care about existence of a callback.
|
||||
});
|
||||
|
||||
driverExtension.call(const WaitUntilNoTransientCallbacks().serialize())
|
||||
extension.call(const WaitUntilNoTransientCallbacks().serialize())
|
||||
.then<void>(expectAsync1((Map<String, dynamic> r) {
|
||||
result = r;
|
||||
}));
|
||||
@ -86,7 +83,7 @@ void main() {
|
||||
|
||||
testWidgets('handler', (WidgetTester tester) async {
|
||||
expect(log, isEmpty);
|
||||
final Map<String, dynamic> response = await driverExtension.call(const RequestData('hello').serialize());
|
||||
final Map<String, dynamic> response = await extension.call(const RequestData('hello').serialize());
|
||||
final RequestDataResult result = RequestDataResult.fromJson(response['response'] as Map<String, dynamic>);
|
||||
expect(log, <String>['hello']);
|
||||
expect(result.message, '1');
|
||||
@ -94,18 +91,18 @@ void main() {
|
||||
});
|
||||
|
||||
group('waitForCondition', () {
|
||||
FlutterDriverExtension driverExtension;
|
||||
FlutterDriverExtension extension;
|
||||
Map<String, dynamic> result;
|
||||
int messageId = 0;
|
||||
final List<String> log = <String>[];
|
||||
|
||||
setUp(() {
|
||||
result = null;
|
||||
driverExtension = FlutterDriverExtension((String message) async { log.add(message); return (messageId += 1).toString(); }, false);
|
||||
extension = FlutterDriverExtension((String message) async { log.add(message); return (messageId += 1).toString(); }, false);
|
||||
});
|
||||
|
||||
testWidgets('waiting for NoTransientCallbacks returns immediately when transient callback queue is empty', (WidgetTester tester) async {
|
||||
driverExtension.call(const WaitForCondition(NoTransientCallbacks()).serialize())
|
||||
extension.call(const WaitForCondition(NoTransientCallbacks()).serialize())
|
||||
.then<void>(expectAsync1((Map<String, dynamic> r) {
|
||||
result = r;
|
||||
}));
|
||||
@ -125,7 +122,7 @@ void main() {
|
||||
// Intentionally blank. We only care about existence of a callback.
|
||||
});
|
||||
|
||||
driverExtension.call(const WaitForCondition(NoTransientCallbacks()).serialize())
|
||||
extension.call(const WaitForCondition(NoTransientCallbacks()).serialize())
|
||||
.then<void>(expectAsync1((Map<String, dynamic> r) {
|
||||
result = r;
|
||||
}));
|
||||
@ -147,7 +144,7 @@ void main() {
|
||||
|
||||
testWidgets('waiting for NoPendingFrame returns immediately when frame is synced', (
|
||||
WidgetTester tester) async {
|
||||
driverExtension.call(const WaitForCondition(NoPendingFrame()).serialize())
|
||||
extension.call(const WaitForCondition(NoPendingFrame()).serialize())
|
||||
.then<void>(expectAsync1((Map<String, dynamic> r) {
|
||||
result = r;
|
||||
}));
|
||||
@ -165,7 +162,7 @@ void main() {
|
||||
testWidgets('waiting for NoPendingFrame returns until no pending scheduled frame', (WidgetTester tester) async {
|
||||
SchedulerBinding.instance.scheduleFrame();
|
||||
|
||||
driverExtension.call(const WaitForCondition(NoPendingFrame()).serialize())
|
||||
extension.call(const WaitForCondition(NoPendingFrame()).serialize())
|
||||
.then<void>(expectAsync1((Map<String, dynamic> r) {
|
||||
result = r;
|
||||
}));
|
||||
@ -189,7 +186,7 @@ void main() {
|
||||
'waiting for combined conditions returns immediately', (WidgetTester tester) async {
|
||||
const SerializableWaitCondition combinedCondition =
|
||||
CombinedCondition(<SerializableWaitCondition>[NoTransientCallbacks(), NoPendingFrame()]);
|
||||
driverExtension.call(const WaitForCondition(combinedCondition).serialize())
|
||||
extension.call(const WaitForCondition(combinedCondition).serialize())
|
||||
.then<void>(expectAsync1((Map<String, dynamic> r) {
|
||||
result = r;
|
||||
}));
|
||||
@ -213,7 +210,7 @@ void main() {
|
||||
|
||||
const SerializableWaitCondition combinedCondition =
|
||||
CombinedCondition(<SerializableWaitCondition>[NoTransientCallbacks(), NoPendingFrame()]);
|
||||
driverExtension.call(const WaitForCondition(combinedCondition).serialize())
|
||||
extension.call(const WaitForCondition(combinedCondition).serialize())
|
||||
.then<void>(expectAsync1((Map<String, dynamic> r) {
|
||||
result = r;
|
||||
}));
|
||||
@ -242,7 +239,7 @@ void main() {
|
||||
|
||||
const SerializableWaitCondition combinedCondition =
|
||||
CombinedCondition(<SerializableWaitCondition>[NoPendingFrame(), NoTransientCallbacks()]);
|
||||
driverExtension.call(const WaitForCondition(combinedCondition).serialize())
|
||||
extension.call(const WaitForCondition(combinedCondition).serialize())
|
||||
.then<void>(expectAsync1((Map<String, dynamic> r) {
|
||||
result = r;
|
||||
}));
|
||||
@ -264,7 +261,7 @@ void main() {
|
||||
|
||||
testWidgets(
|
||||
"waiting for NoPendingPlatformMessages returns immediately when there're no platform messages", (WidgetTester tester) async {
|
||||
driverExtension
|
||||
extension
|
||||
.call(const WaitForCondition(NoPendingPlatformMessages()).serialize())
|
||||
.then<void>(expectAsync1((Map<String, dynamic> r) {
|
||||
result = r;
|
||||
@ -292,7 +289,7 @@ void main() {
|
||||
});
|
||||
channel.invokeMethod<String>('sayHello', 'hello');
|
||||
|
||||
driverExtension
|
||||
extension
|
||||
.call(const WaitForCondition(NoPendingPlatformMessages()).serialize())
|
||||
.then<void>(expectAsync1((Map<String, dynamic> r) {
|
||||
result = r;
|
||||
@ -337,7 +334,7 @@ void main() {
|
||||
channel1.invokeMethod<String>('sayHello', 'hello');
|
||||
channel2.invokeMethod<String>('sayHello', 'hello');
|
||||
|
||||
driverExtension
|
||||
extension
|
||||
.call(const WaitForCondition(NoPendingPlatformMessages()).serialize())
|
||||
.then<void>(expectAsync1((Map<String, dynamic> r) {
|
||||
result = r;
|
||||
@ -386,7 +383,7 @@ void main() {
|
||||
channel1.invokeMethod<String>('sayHello', 'hello');
|
||||
|
||||
// Calls the waiting API before the second channel message is sent.
|
||||
driverExtension
|
||||
extension
|
||||
.call(const WaitForCondition(NoPendingPlatformMessages()).serialize())
|
||||
.then<void>(expectAsync1((Map<String, dynamic> r) {
|
||||
result = r;
|
||||
@ -436,7 +433,7 @@ void main() {
|
||||
|
||||
channel1.invokeMethod<String>('sayHello', 'hello');
|
||||
|
||||
driverExtension
|
||||
extension
|
||||
.call(const WaitForCondition(NoPendingPlatformMessages()).serialize())
|
||||
.then<void>(expectAsync1((Map<String, dynamic> r) {
|
||||
result = r;
|
||||
@ -465,9 +462,9 @@ void main() {
|
||||
});
|
||||
|
||||
group('getSemanticsId', () {
|
||||
FlutterDriverExtension driverExtension;
|
||||
FlutterDriverExtension extension;
|
||||
setUp(() {
|
||||
driverExtension = FlutterDriverExtension((String arg) async => '', true);
|
||||
extension = FlutterDriverExtension((String arg) async => '', true);
|
||||
});
|
||||
|
||||
testWidgets('works when semantics are enabled', (WidgetTester tester) async {
|
||||
@ -476,7 +473,7 @@ void main() {
|
||||
const Text('hello', textDirection: TextDirection.ltr));
|
||||
|
||||
final Map<String, String> arguments = GetSemanticsId(const ByText('hello')).serialize();
|
||||
final Map<String, dynamic> response = await driverExtension.call(arguments);
|
||||
final Map<String, dynamic> response = await extension.call(arguments);
|
||||
final GetSemanticsIdResult result = GetSemanticsIdResult.fromJson(response['response'] as Map<String, dynamic>);
|
||||
|
||||
expect(result.id, 1);
|
||||
@ -488,7 +485,7 @@ void main() {
|
||||
const Text('hello', textDirection: TextDirection.ltr));
|
||||
|
||||
final Map<String, String> arguments = GetSemanticsId(const ByText('hello')).serialize();
|
||||
final Map<String, dynamic> response = await driverExtension.call(arguments);
|
||||
final Map<String, dynamic> response = await extension.call(arguments);
|
||||
|
||||
expect(response['isError'], true);
|
||||
expect(response['response'], contains('Bad state: No semantics data found'));
|
||||
@ -507,7 +504,7 @@ void main() {
|
||||
);
|
||||
|
||||
final Map<String, String> arguments = GetSemanticsId(const ByText('hello')).serialize();
|
||||
final Map<String, dynamic> response = await driverExtension.call(arguments);
|
||||
final Map<String, dynamic> response = await extension.call(arguments);
|
||||
|
||||
expect(response['isError'], true);
|
||||
expect(response['response'], contains('Bad state: Found more than one element with the same ID'));
|
||||
@ -516,11 +513,11 @@ void main() {
|
||||
});
|
||||
|
||||
testWidgets('getOffset', (WidgetTester tester) async {
|
||||
final FlutterDriverExtension driverExtension = FlutterDriverExtension((String arg) async => '', true);
|
||||
final FlutterDriverExtension extension = FlutterDriverExtension((String arg) async => '', true);
|
||||
|
||||
Future<Offset> getOffset(OffsetType offset) async {
|
||||
final Map<String, String> arguments = GetOffset(ByValueKey(1), offset).serialize();
|
||||
final Map<String, dynamic> response = await driverExtension.call(arguments);
|
||||
final Map<String, dynamic> response = await extension.call(arguments);
|
||||
final GetOffsetResult result = GetOffsetResult.fromJson(response['response'] as Map<String, dynamic>);
|
||||
return Offset(result.dx, result.dy);
|
||||
}
|
||||
@ -548,11 +545,11 @@ void main() {
|
||||
|
||||
testWidgets('getText', (WidgetTester tester) async {
|
||||
await silenceDriverLogger(() async {
|
||||
final FlutterDriverExtension driverExtension = FlutterDriverExtension((String arg) async => '', true);
|
||||
final FlutterDriverExtension extension = FlutterDriverExtension((String arg) async => '', true);
|
||||
|
||||
Future<String> getTextInternal(SerializableFinder search) async {
|
||||
final Map<String, String> arguments = GetText(search, timeout: const Duration(seconds: 1)).serialize();
|
||||
final Map<String, dynamic> result = await driverExtension.call(arguments);
|
||||
final Map<String, dynamic> result = await extension.call(arguments);
|
||||
if (result['isError'] as bool) {
|
||||
return null;
|
||||
}
|
||||
@ -610,7 +607,7 @@ void main() {
|
||||
|
||||
// Check if error thrown for other types
|
||||
final Map<String, String> arguments = GetText(ByValueKey('column'), timeout: const Duration(seconds: 1)).serialize();
|
||||
final Map<String, dynamic> response = await driverExtension.call(arguments);
|
||||
final Map<String, dynamic> response = await extension.call(arguments);
|
||||
expect(response['isError'], true);
|
||||
expect(response['response'], contains('is currently not supported by getText'));
|
||||
});
|
||||
@ -618,7 +615,7 @@ void main() {
|
||||
|
||||
testWidgets('descendant finder', (WidgetTester tester) async {
|
||||
await silenceDriverLogger(() async {
|
||||
final FlutterDriverExtension driverExtension = FlutterDriverExtension((String arg) async => '', true);
|
||||
final FlutterDriverExtension extension = FlutterDriverExtension((String arg) async => '', true);
|
||||
|
||||
Future<String> getDescendantText({ String of, bool matchRoot = false}) async {
|
||||
final Map<String, String> arguments = GetText(Descendant(
|
||||
@ -626,7 +623,7 @@ void main() {
|
||||
matching: ByValueKey('text2'),
|
||||
matchRoot: matchRoot,
|
||||
), timeout: const Duration(seconds: 1)).serialize();
|
||||
final Map<String, dynamic> result = await driverExtension.call(arguments);
|
||||
final Map<String, dynamic> result = await extension.call(arguments);
|
||||
if (result['isError'] as bool) {
|
||||
return null;
|
||||
}
|
||||
@ -663,7 +660,7 @@ void main() {
|
||||
|
||||
testWidgets('descendant finder firstMatchOnly', (WidgetTester tester) async {
|
||||
await silenceDriverLogger(() async {
|
||||
final FlutterDriverExtension driverExtension = FlutterDriverExtension((String arg) async => '', true);
|
||||
final FlutterDriverExtension extension = FlutterDriverExtension((String arg) async => '', true);
|
||||
|
||||
Future<String> getDescendantText() async {
|
||||
final Map<String, String> arguments = GetText(Descendant(
|
||||
@ -671,7 +668,7 @@ void main() {
|
||||
matching: const ByType('Text'),
|
||||
firstMatchOnly: true,
|
||||
), timeout: const Duration(seconds: 1)).serialize();
|
||||
final Map<String, dynamic> result = await driverExtension.call(arguments);
|
||||
final Map<String, dynamic> result = await extension.call(arguments);
|
||||
if (result['isError'] as bool) {
|
||||
return null;
|
||||
}
|
||||
@ -697,7 +694,7 @@ void main() {
|
||||
|
||||
testWidgets('ancestor finder', (WidgetTester tester) async {
|
||||
await silenceDriverLogger(() async {
|
||||
final FlutterDriverExtension driverExtension = FlutterDriverExtension((String arg) async => '', true);
|
||||
final FlutterDriverExtension extension = FlutterDriverExtension((String arg) async => '', true);
|
||||
|
||||
Future<Offset> getAncestorTopLeft({ String of, String matching, bool matchRoot = false}) async {
|
||||
final Map<String, String> arguments = GetOffset(Ancestor(
|
||||
@ -705,7 +702,7 @@ void main() {
|
||||
matching: ByValueKey(matching),
|
||||
matchRoot: matchRoot,
|
||||
), OffsetType.topLeft, timeout: const Duration(seconds: 1)).serialize();
|
||||
final Map<String, dynamic> response = await driverExtension.call(arguments);
|
||||
final Map<String, dynamic> response = await extension.call(arguments);
|
||||
if (response['isError'] as bool) {
|
||||
return null;
|
||||
}
|
||||
@ -767,7 +764,7 @@ void main() {
|
||||
|
||||
testWidgets('ancestor finder firstMatchOnly', (WidgetTester tester) async {
|
||||
await silenceDriverLogger(() async {
|
||||
final FlutterDriverExtension driverExtension = FlutterDriverExtension((String arg) async => '', true);
|
||||
final FlutterDriverExtension extension = FlutterDriverExtension((String arg) async => '', true);
|
||||
|
||||
Future<Offset> getAncestorTopLeft() async {
|
||||
final Map<String, String> arguments = GetOffset(Ancestor(
|
||||
@ -775,7 +772,7 @@ void main() {
|
||||
matching: const ByType('Container'),
|
||||
firstMatchOnly: true,
|
||||
), OffsetType.topLeft, timeout: const Duration(seconds: 1)).serialize();
|
||||
final Map<String, dynamic> response = await driverExtension.call(arguments);
|
||||
final Map<String, dynamic> response = await extension.call(arguments);
|
||||
if (response['isError'] as bool) {
|
||||
return null;
|
||||
}
|
||||
@ -815,11 +812,11 @@ void main() {
|
||||
});
|
||||
|
||||
testWidgets('GetDiagnosticsTree', (WidgetTester tester) async {
|
||||
final FlutterDriverExtension driverExtension = FlutterDriverExtension((String arg) async => '', true);
|
||||
final FlutterDriverExtension extension = FlutterDriverExtension((String arg) async => '', true);
|
||||
|
||||
Future<Map<String, Object>> getDiagnosticsTree(DiagnosticsType type, SerializableFinder finder, { int depth = 0, bool properties = true }) async {
|
||||
final Map<String, String> arguments = GetDiagnosticsTree(finder, type, subtreeDepth: depth, includeProperties: properties).serialize();
|
||||
final Map<String, dynamic> response = await driverExtension.call(arguments);
|
||||
final Map<String, dynamic> response = await extension.call(arguments);
|
||||
final DiagnosticsTreeResult result = DiagnosticsTreeResult(response['response'] as Map<String, dynamic>);
|
||||
return result.json;
|
||||
}
|
||||
@ -880,120 +877,18 @@ void main() {
|
||||
expect(children.single['children'], isEmpty);
|
||||
});
|
||||
|
||||
group('extension finders', () {
|
||||
final Widget debugTree = Directionality(
|
||||
textDirection: TextDirection.ltr,
|
||||
child: Center(
|
||||
child: Column(
|
||||
key: const ValueKey<String>('Column'),
|
||||
children: <Widget>[
|
||||
const Text('Foo', key: ValueKey<String>('Text1')),
|
||||
const Text('Bar', key: ValueKey<String>('Text2')),
|
||||
FlatButton(
|
||||
child: const Text('Whatever'),
|
||||
key: const ValueKey<String>('Button'),
|
||||
onPressed: () {},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
testWidgets('unknown extension finder', (WidgetTester tester) async {
|
||||
final FlutterDriverExtension driverExtension = FlutterDriverExtension(
|
||||
(String arg) async => '',
|
||||
true,
|
||||
finders: <FinderExtension>[],
|
||||
);
|
||||
|
||||
Future<Map<String, dynamic>> getText(SerializableFinder finder) async {
|
||||
final Map<String, String> arguments = GetText(finder, timeout: const Duration(seconds: 1)).serialize();
|
||||
return await driverExtension.call(arguments);
|
||||
}
|
||||
|
||||
await tester.pumpWidget(debugTree);
|
||||
|
||||
final Map<String, dynamic> result = await getText(StubFinder('Text1'));
|
||||
expect(result['isError'], true);
|
||||
expect(result['response'] is String, true);
|
||||
expect(result['response'] as String, contains('Unsupported search specification type Stub'));
|
||||
});
|
||||
|
||||
testWidgets('simple extension finder', (WidgetTester tester) async {
|
||||
final FlutterDriverExtension driverExtension = FlutterDriverExtension(
|
||||
(String arg) async => '',
|
||||
true,
|
||||
finders: <FinderExtension>[
|
||||
StubFinderExtension(),
|
||||
],
|
||||
);
|
||||
|
||||
Future<GetTextResult> getText(SerializableFinder finder) async {
|
||||
final Map<String, String> arguments = GetText(finder, timeout: const Duration(seconds: 1)).serialize();
|
||||
final Map<String, dynamic> response = await driverExtension.call(arguments);
|
||||
return GetTextResult.fromJson(response['response'] as Map<String, dynamic>);
|
||||
}
|
||||
|
||||
await tester.pumpWidget(debugTree);
|
||||
|
||||
final GetTextResult result = await getText(StubFinder('Text1'));
|
||||
expect(result.text, 'Foo');
|
||||
});
|
||||
|
||||
testWidgets('complex extension finder', (WidgetTester tester) async {
|
||||
final FlutterDriverExtension driverExtension = FlutterDriverExtension(
|
||||
(String arg) async => '',
|
||||
true,
|
||||
finders: <FinderExtension>[
|
||||
StubFinderExtension(),
|
||||
],
|
||||
);
|
||||
|
||||
Future<GetTextResult> getText(SerializableFinder finder) async {
|
||||
final Map<String, String> arguments = GetText(finder, timeout: const Duration(seconds: 1)).serialize();
|
||||
final Map<String, dynamic> response = await driverExtension.call(arguments);
|
||||
return GetTextResult.fromJson(response['response'] as Map<String, dynamic>);
|
||||
}
|
||||
|
||||
await tester.pumpWidget(debugTree);
|
||||
|
||||
final GetTextResult result = await getText(Descendant(of: StubFinder('Column'), matching: StubFinder('Text1')));
|
||||
expect(result.text, 'Foo');
|
||||
});
|
||||
|
||||
testWidgets('extension finder with command', (WidgetTester tester) async {
|
||||
final FlutterDriverExtension driverExtension = FlutterDriverExtension(
|
||||
(String arg) async => '',
|
||||
true,
|
||||
finders: <FinderExtension>[
|
||||
StubFinderExtension(),
|
||||
],
|
||||
);
|
||||
|
||||
Future<Map<String, dynamic>> tap(SerializableFinder finder) async {
|
||||
final Map<String, String> arguments = Tap(finder, timeout: const Duration(seconds: 1)).serialize();
|
||||
return await driverExtension.call(arguments);
|
||||
}
|
||||
|
||||
await tester.pumpWidget(debugTree);
|
||||
|
||||
final Map<String, dynamic> result = await tap(StubFinder('Button'));
|
||||
expect(result['isError'], false);
|
||||
});
|
||||
});
|
||||
|
||||
group('waitUntilFrameSync', () {
|
||||
FlutterDriverExtension driverExtension;
|
||||
FlutterDriverExtension extension;
|
||||
Map<String, dynamic> result;
|
||||
|
||||
setUp(() {
|
||||
driverExtension = FlutterDriverExtension((String arg) async => '', true);
|
||||
extension = FlutterDriverExtension((String arg) async => '', true);
|
||||
result = null;
|
||||
});
|
||||
|
||||
testWidgets('returns immediately when frame is synced', (
|
||||
WidgetTester tester) async {
|
||||
driverExtension.call(const WaitUntilNoPendingFrame().serialize())
|
||||
extension.call(const WaitUntilNoPendingFrame().serialize())
|
||||
.then<void>(expectAsync1((Map<String, dynamic> r) {
|
||||
result = r;
|
||||
}));
|
||||
@ -1014,7 +909,7 @@ void main() {
|
||||
// Intentionally blank. We only care about existence of a callback.
|
||||
});
|
||||
|
||||
driverExtension.call(const WaitUntilNoPendingFrame().serialize())
|
||||
extension.call(const WaitUntilNoPendingFrame().serialize())
|
||||
.then<void>(expectAsync1((Map<String, dynamic> r) {
|
||||
result = r;
|
||||
}));
|
||||
@ -1038,7 +933,7 @@ void main() {
|
||||
'waits until no pending scheduled frame', (WidgetTester tester) async {
|
||||
SchedulerBinding.instance.scheduleFrame();
|
||||
|
||||
driverExtension.call(const WaitUntilNoPendingFrame().serialize())
|
||||
extension.call(const WaitUntilNoPendingFrame().serialize())
|
||||
.then<void>(expectAsync1((Map<String, dynamic> r) {
|
||||
result = r;
|
||||
}));
|
||||
|
@ -1,19 +0,0 @@
|
||||
// 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/flutter_driver.dart';
|
||||
|
||||
class StubFinder extends SerializableFinder {
|
||||
StubFinder(this.keyString);
|
||||
|
||||
final String keyString;
|
||||
|
||||
@override
|
||||
String get finderType => 'Stub';
|
||||
|
||||
@override
|
||||
Map<String, String> serialize() {
|
||||
return super.serialize()..addAll(<String, String>{'keyString': keyString});
|
||||
}
|
||||
}
|
@ -1,38 +0,0 @@
|
||||
// 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/src/widgets/framework.dart';
|
||||
import 'package:flutter_driver/driver_extension.dart';
|
||||
import 'package:flutter_driver/src/common/create_finder_factory.dart';
|
||||
import 'package:flutter_test/src/finders.dart';
|
||||
import 'package:flutter_driver/src/common/find.dart';
|
||||
|
||||
import 'stub_finder.dart';
|
||||
|
||||
class StubFinderExtension extends FinderExtension {
|
||||
@override
|
||||
Finder createFinder(
|
||||
SerializableFinder finder,
|
||||
CreateFinderFactory finderFactory,
|
||||
) {
|
||||
return find.byWidgetPredicate((Widget widget) {
|
||||
final Key key = widget.key;
|
||||
if (key is! ValueKey<String>) {
|
||||
return false;
|
||||
}
|
||||
return (key as ValueKey<String>).value == (finder as StubFinder).keyString;
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
SerializableFinder deserialize(
|
||||
Map<String, String> params,
|
||||
DeserializeFinderFactory finderFactory,
|
||||
) {
|
||||
return StubFinder(params['keyString']);
|
||||
}
|
||||
|
||||
@override
|
||||
String get finderType => 'Stub';
|
||||
}
|
Loading…
Reference in New Issue
Block a user