Formatting + Dropdown Widgets

This commit is contained in:
Sarah Jamie Lewis 2023-02-08 14:55:24 -08:00
parent 9b817676e4
commit f20a14f3d8
26 changed files with 100 additions and 133 deletions

View File

@ -130,8 +130,7 @@ abstract class AppDriverAdapter<TNativeAdapter, TFinderType, TWidgetBaseType> {
return Future.microtask(
() async {
final completer = Completer<void>();
var maxAttempts =
(timeout!.inMilliseconds / pollInterval!.inMilliseconds).round();
var maxAttempts = (timeout!.inMilliseconds / pollInterval!.inMilliseconds).round();
var attempts = 0;
while (attempts < maxAttempts) {

View File

@ -4,8 +4,7 @@ import 'package:flutter_driver/flutter_driver.dart';
import 'app_driver_adapter.dart';
class FlutterDriverAppDriverAdapter
extends AppDriverAdapter<FlutterDriver, SerializableFinder, dynamic> {
class FlutterDriverAppDriverAdapter extends AppDriverAdapter<FlutterDriver, SerializableFinder, dynamic> {
FlutterDriverAppDriverAdapter(FlutterDriver rawAdapter) : super(rawAdapter);
@override

View File

@ -4,5 +4,4 @@ import 'package:build/build.dart';
import 'package:flutter_gherkin/src/flutter/code_generation/generators/gherkin_suite_test_generator.dart';
import 'package:source_gen/source_gen.dart';
Builder gherkinTestSuiteBuilder(BuilderOptions options) =>
SharedPartBuilder([GherkinSuiteTestGenerator()], 'gherkin_tests');
Builder gherkinTestSuiteBuilder(BuilderOptions options) => SharedPartBuilder([GherkinSuiteTestGenerator()], 'gherkin_tests');

View File

@ -25,8 +25,7 @@ class NoOpReporter extends MessageReporter {
}
}
class GherkinSuiteTestGenerator
extends GeneratorForAnnotation<GherkinTestSuite> {
class GherkinSuiteTestGenerator extends GeneratorForAnnotation<GherkinTestSuite> {
static const String template = '''
class _CustomGherkinIntegrationTestRunner extends GherkinIntegrationTestRunner {
_CustomGherkinIntegrationTestRunner({
@ -79,21 +78,15 @@ Future<void> executeTestSuite({
_languageService.initialise(
annotation.read('featureDefaultLanguage').literalValue.toString(),
);
final idx = annotation
.read('executionOrder')
.objectValue
.getField('index')!
.toIntValue()!;
final idx = annotation.read('executionOrder').objectValue.getField('index')!.toIntValue()!;
final executionOrder = ExecutionOrder.values[idx];
final featureFiles = annotation
.read('featurePaths')
.listValue
.map((path) => Glob(path.toStringValue()!))
.map((glob) =>
glob.listSync().map((entity) => File(entity.path)).toList())
.map((glob) => glob.listSync().map((entity) => File(entity.path)).toList())
.reduce((value, element) => value..addAll(element));
final useAbsolutePaths =
annotation.read('useAbsolutePaths').objectValue.toBoolValue();
final useAbsolutePaths = annotation.read('useAbsolutePaths').objectValue.toBoolValue();
if (executionOrder == ExecutionOrder.random) {
featureFiles.shuffle();
@ -119,10 +112,7 @@ Future<void> executeTestSuite({
}
}
return template
.replaceAll('{{feature_functions}}',
featureExecutionFunctionsBuilder.toString())
.replaceAll(
return template.replaceAll('{{feature_functions}}', featureExecutionFunctionsBuilder.toString()).replaceAll(
'{{features_to_execute}}',
featuresToExecute.toString(),
);
@ -333,9 +323,7 @@ class FeatureFileTestGeneratorVisitor extends FeatureFileVisitor {
code = _replaceVariable(
code,
'step_table',
table == null
? 'null'
: 'GherkinTable.fromJson(\'${_escapeText(table.toJson())}\')',
table == null ? 'null' : 'GherkinTable.fromJson(\'${_escapeText(table.toJson())}\')',
);
_stepBuffer.writeln(code);
@ -380,8 +368,5 @@ class FeatureFileTestGeneratorVisitor extends FeatureFileVisitor {
return content.replaceAll('{{$property}}', value ?? 'null');
}
String? _escapeText(String? text) => text
?.replaceAll("\\", "\\\\")
.replaceAll("'", "\\'")
.replaceAll(r"$", r"\$");
String? _escapeText(String? text) => text?.replaceAll("\\", "\\\\").replaceAll("'", "\\'").replaceAll(r"$", r"\$");
}

View File

@ -142,15 +142,13 @@ class FlutterDriverTestConfiguration extends FlutterTestConfiguration {
/// Called after the successful connection of Flutter driver to the running application. Depending on your configuration this
/// method will be called on each new connection usually before each scenario is run.
final Future<void> Function(FlutterDriver driver)?
onAfterFlutterDriverConnect;
final Future<void> Function(FlutterDriver driver)? onAfterFlutterDriverConnect;
void setObservatoryDebuggerUri(String uri) => _observatoryDebuggerUri = uri;
Future<FlutterDriver> createFlutterDriver([String? dartVmServiceUrl]) async {
final completer = Completer<FlutterDriver>();
dartVmServiceUrl = (dartVmServiceUrl ?? _observatoryDebuggerUri) ??
Platform.environment['VM_SERVICE_URL'];
dartVmServiceUrl = (dartVmServiceUrl ?? _observatoryDebuggerUri) ?? Platform.environment['VM_SERVICE_URL'];
await runZonedGuarded(
() async {
@ -183,9 +181,7 @@ class FlutterDriverTestConfiguration extends FlutterTestConfiguration {
world = world ?? FlutterDriverWorld();
final driver = await createFlutterDriver(
flutterConfig.runningAppProtocolEndpointUri?.isNotEmpty ?? false
? flutterConfig.runningAppProtocolEndpointUri
: null,
flutterConfig.runningAppProtocolEndpointUri?.isNotEmpty ?? false ? flutterConfig.runningAppProtocolEndpointUri : null,
);
(world as FlutterDriverWorld).setFlutterDriver(driver);

View File

@ -35,6 +35,8 @@ class FlutterTestConfiguration extends TestConfiguration {
tapWidgetOfTypeStep(),
tapWidgetOfTypeWithinStep(),
tapWidgetWithTextStep(),
selectDropDownWithTextStep(),
scrollDropDown(),
textExistsStep(),
textExistsWithinStep(),
waitUntilKeyExistsStep(),

View File

@ -21,8 +21,7 @@ class FlutterAppRunnerHook extends Hook {
}
@override
Future<void> onAfterRun(TestConfiguration config) async =>
await _terminateApp();
Future<void> onAfterRun(TestConfiguration config) async => await _terminateApp();
@override
Future<void> onBeforeScenario(
@ -45,8 +44,7 @@ class FlutterAppRunnerHook extends Hook {
}) async {
final flutterConfig = _castConfig(config);
haveRunFirstScenario = true;
if (_flutterRunProcessHandler != null &&
flutterConfig.restartAppBetweenScenarios) {
if (_flutterRunProcessHandler != null && flutterConfig.restartAppBetweenScenarios) {
await _restartApp();
}
}
@ -86,8 +84,7 @@ class FlutterAppRunnerHook extends Hook {
"Starting Flutter app under test '${config.targetAppPath}', this might take a few moments",
);
await _flutterRunProcessHandler!.run();
final observatoryUri = await _flutterRunProcessHandler!
.waitForObservatoryDebuggerUri(config.flutterBuildTimeout);
final observatoryUri = await _flutterRunProcessHandler!.waitForObservatoryDebuggerUri(config.flutterBuildTimeout);
config.setObservatoryDebuggerUri(observatoryUri);
}
}
@ -107,8 +104,7 @@ class FlutterAppRunnerHook extends Hook {
}
}
FlutterDriverTestConfiguration _castConfig(TestConfiguration config) =>
config as FlutterDriverTestConfiguration;
FlutterDriverTestConfiguration _castConfig(TestConfiguration config) => config as FlutterDriverTestConfiguration;
void _log(String text) {
if (!kIsWeb) {

View File

@ -10,9 +10,7 @@ class AttachScreenshotOnFailedStepHook extends Hook {
String step,
StepResult stepResult,
) async {
if (stepResult.result == StepExecutionResult.fail ||
stepResult.result == StepExecutionResult.error ||
stepResult.result == StepExecutionResult.timeout) {
if (stepResult.result == StepExecutionResult.fail || stepResult.result == StepExecutionResult.error || stepResult.result == StepExecutionResult.timeout) {
try {
final screenshotData = await _takeScreenshot(world);
world.attach(screenshotData, 'image/png', step);

View File

@ -17,8 +17,7 @@ class ExistenceParameter extends CustomParameter<Existence> {
case 'absent':
return Existence.absent;
default:
throw ArgumentError(
'Value `$c` must be defined for this Existence parameter');
throw ArgumentError('Value `$c` must be defined for this Existence parameter');
}
},
);

View File

@ -18,8 +18,7 @@ class SwipeDirectionParameter extends CustomParameter<SwipeDirection> {
case 'up':
return SwipeDirection.up;
default:
throw ArgumentError(
'"down", "left", "right", or "up" must be defined for this parameter');
throw ArgumentError('"down", "left", "right", or "up" must be defined for this parameter');
}
},
);

View File

@ -13,8 +13,7 @@ enum _FlutterDriverMessageLogLevel { info, warning, error }
/// This can cause problems with CI servers for example as they will mark a process as failed if it logs to the
/// stderr stream. So Flutter driver will log a normal info message to the stderr and thus make
/// the process fail from the perspective of a CI server.
class FlutterDriverReporter extends Reporter
implements DisposableReporter, TestReporter {
class FlutterDriverReporter extends Reporter implements DisposableReporter, TestReporter {
final bool logErrorMessages;
final bool logWarningMessages;
final bool logInfoMessages;
@ -48,8 +47,7 @@ class FlutterDriverReporter extends Reporter
if (logWarningMessages && level == _FlutterDriverMessageLogLevel.warning) {
stdout.writeln(log);
} else if (logErrorMessages &&
level == _FlutterDriverMessageLogLevel.error) {
} else if (logErrorMessages && level == _FlutterDriverMessageLogLevel.error) {
stderr.writeln(log);
} else {
stdout.writeln(log);

View File

@ -132,13 +132,9 @@ class FlutterRunProcessHandler extends ProcessHandler {
runInShell: true,
);
_processStdoutStream =
_runningProcess!.stdout.transform(utf8.decoder).asBroadcastStream();
_processStdoutStream = _runningProcess!.stdout.transform(utf8.decoder).asBroadcastStream();
_openSubscriptions.add(_runningProcess!.stderr
.map((events) => String.fromCharCodes(events).trim())
.where((event) => event.isNotEmpty)
.listen((event) {
_openSubscriptions.add(_runningProcess!.stderr.map((events) => String.fromCharCodes(events).trim()).where((event) => event.isNotEmpty).listen((event) {
if (event.contains(_errorMessageRegex)) {
stderr.writeln(
'${StdoutReporter.kFailColor}Flutter build error: $event${StdoutReporter.kResetColor}',
@ -257,8 +253,7 @@ class FlutterRunProcessHandler extends ProcessHandler {
void _ensureRunningProcess() {
if (_runningProcess == null) {
throw Exception(
'FlutterRunProcessHandler: flutter run process is not active');
throw Exception('FlutterRunProcessHandler: flutter run process is not active');
}
}
}

View File

@ -32,8 +32,7 @@ class TestDependencies {
}
abstract class GherkinIntegrationTestRunner {
final TagExpressionEvaluator _tagExpressionEvaluator =
TagExpressionEvaluator();
final TagExpressionEvaluator _tagExpressionEvaluator = TagExpressionEvaluator();
final FlutterTestConfiguration configuration;
final StartAppFn appMainFunction;
final AppLifecyclePumpHandlerFn? appLifecyclePumpHandler;
@ -69,8 +68,7 @@ abstract class GherkinIntegrationTestRunner {
configuration.prepare();
_registerReporters(configuration.reporters);
_hook = _registerHooks(configuration.hooks);
_customParameters =
_registerCustomParameters(configuration.customStepParameterDefinitions);
_customParameters = _registerCustomParameters(configuration.customStepParameterDefinitions);
_executableSteps = _registerStepDefinitions(
configuration.stepDefinitions!,
_customParameters!,
@ -130,8 +128,7 @@ abstract class GherkinIntegrationTestRunner {
Iterable<String>? tags,
}) async {
final debugInformation = RunnableDebugInformation(path, 0, name);
final featureTags =
(tags ?? const Iterable<Tag>.empty()).map((t) => Tag(t.toString(), 0));
final featureTags = (tags ?? const Iterable<Tag>.empty()).map((t) => Tag(t.toString(), 0));
await reporter.feature.onStarted.invoke(
FeatureMessage(
name: name,
@ -291,8 +288,7 @@ abstract class GherkinIntegrationTestRunner {
WidgetTester tester,
) async {
World? world;
final attachmentManager =
await configuration.getAttachmentManager(configuration);
final attachmentManager = await configuration.getAttachmentManager(configuration);
if (configuration.createWorld != null) {
world = await configuration.createWorld!(configuration);
@ -305,9 +301,7 @@ abstract class GherkinIntegrationTestRunner {
WidgetTesterAppDriverAdapter(
rawAdapter: tester,
binding: _binding,
waitImplicitlyAfterAction: configuration is FlutterTestConfiguration
? (configuration).waitImplicitlyAfterAction
: true,
waitImplicitlyAfterAction: configuration is FlutterTestConfiguration ? (configuration).waitImplicitlyAfterAction : true,
),
);
@ -366,8 +360,7 @@ abstract class GherkinIntegrationTestRunner {
parameters,
);
if (!_isNegativeResult(result.result) ||
configuration.stepMaxRetries == 0) {
if (!_isNegativeResult(result.result) || configuration.stepMaxRetries == 0) {
break;
} else {
await Future.delayed(configuration.retryDelay);
@ -486,9 +479,7 @@ abstract class GherkinIntegrationTestRunner {
name: step,
context: RunnableDebugInformation('', 0, step),
result: result,
attachments: dependencies.attachmentManager
.getAttachmentsForContext(step)
.toList(),
attachments: dependencies.attachmentManager.getAttachmentsForContext(step).toList(),
),
);
}
@ -505,8 +496,7 @@ abstract class GherkinIntegrationTestRunner {
name: step,
context: RunnableDebugInformation('', 0, step),
table: table,
multilineString:
multiLineStrings.isNotEmpty ? multiLineStrings.first : null,
multilineString: multiLineStrings.isNotEmpty ? multiLineStrings.first : null,
),
);
}
@ -524,9 +514,7 @@ abstract class GherkinIntegrationTestRunner {
}
bool _isNegativeResult(StepExecutionResult result) {
return result == StepExecutionResult.error ||
result == StepExecutionResult.fail ||
result == StepExecutionResult.timeout;
return result == StepExecutionResult.error || result == StepExecutionResult.fail || result == StepExecutionResult.timeout;
}
Future<void> _appLifecyclePhasePumper(

View File

@ -5,16 +5,14 @@ import 'package:gherkin/gherkin.dart';
import '../parameters/swipe_direction_parameter.dart';
mixin _SwipeHelper
on When3WithWorld<SwipeDirection, int, String, FlutterWorld> {
mixin _SwipeHelper on When3WithWorld<SwipeDirection, int, String, FlutterWorld> {
Future<void> swipeOnFinder(
dynamic finder,
SwipeDirection direction,
int swipeAmount,
) async {
if (direction == SwipeDirection.left || direction == SwipeDirection.right) {
final offset =
direction == SwipeDirection.right ? swipeAmount : (swipeAmount * -1);
final offset = direction == SwipeDirection.right ? swipeAmount : (swipeAmount * -1);
await world.appDriver.scroll(
finder,
@ -23,8 +21,7 @@ mixin _SwipeHelper
timeout: timeout,
);
} else {
final offset =
direction == SwipeDirection.up ? swipeAmount : (swipeAmount * -1);
final offset = direction == SwipeDirection.up ? swipeAmount : (swipeAmount * -1);
await world.appDriver.scroll(
finder,
@ -42,9 +39,7 @@ mixin _SwipeHelper
///
/// `Then I swipe up by 800 pixels on the "login_screen"`
/// `Then I swipe left by 200 pixels on the "dismissible_list_item"`
class SwipeOnKeyStep
extends When3WithWorld<SwipeDirection, int, String, FlutterWorld>
with _SwipeHelper {
class SwipeOnKeyStep extends When3WithWorld<SwipeDirection, int, String, FlutterWorld> with _SwipeHelper {
@override
Future<void> executeStep(
SwipeDirection direction,
@ -56,8 +51,7 @@ class SwipeOnKeyStep
}
@override
RegExp get pattern =>
RegExp(r'I swipe {swipe_direction} by {int} pixels on the {string}');
RegExp get pattern => RegExp(r'I swipe {swipe_direction} by {int} pixels on the {string}');
}
/// Swipes in a cardinal direction on a widget discovered by its test.
@ -65,9 +59,7 @@ class SwipeOnKeyStep
/// Examples:
///
/// `Then I swipe left by 400 pixels on the widget that contains the text "Dismiss Me"`
class SwipeOnTextStep
extends When3WithWorld<SwipeDirection, int, String, FlutterWorld>
with _SwipeHelper {
class SwipeOnTextStep extends When3WithWorld<SwipeDirection, int, String, FlutterWorld> with _SwipeHelper {
@override
Future<void> executeStep(
SwipeDirection direction,
@ -79,6 +71,5 @@ class SwipeOnTextStep
}
@override
RegExp get pattern => RegExp(
r'I swipe {swipe_direction} by {int} pixels on the (?:button|element|label|field|text|widget|dialog|popup) that contains the text {string}');
RegExp get pattern => RegExp(r'I swipe {swipe_direction} by {int} pixels on the (?:button|element|label|field|text|widget|dialog|popup) that contains the text {string}');
}

View File

@ -9,11 +9,9 @@ import 'package:gherkin/gherkin.dart';
/// `Then I tap the label that contains the text "Logout" within the "user_settings_list"`
StepDefinitionGeneric tapTextWithinWidgetStep() {
return given2<String, String, FlutterWorld>(
RegExp(
r'I tap the (?:button|element|label|field|text|widget) that contains the text {string} within the {string}'),
RegExp(r'I tap the (?:button|element|label|field|text|widget) that contains the text {string} within the {string}'),
(text, ancestorKey, context) async {
final timeout =
context.configuration.timeout ?? const Duration(seconds: 20);
final timeout = context.configuration.timeout ?? const Duration(seconds: 20);
final finder = context.world.appDriver.findByDescendant(
context.world.appDriver.findBy(ancestorKey, FindType.key),
context.world.appDriver.findBy(text, FindType.text),

View File

@ -10,8 +10,7 @@ import 'package:gherkin/gherkin.dart';
/// `Then I tap the field of type "TextField"`
StepDefinitionGeneric tapWidgetOfTypeStep() {
return given1<String, FlutterWorld>(
RegExp(
r'I tap the (?:button|element|label|icon|field|text|widget) of type {string}$'),
RegExp(r'I tap the (?:button|element|label|icon|field|text|widget) of type {string}$'),
(input1, context) async {
await context.world.appDriver.tap(
context.world.appDriver.findBy(

View File

@ -8,8 +8,7 @@ import 'package:gherkin/gherkin.dart';
/// `Then I tap the element of type "MaterialButton" within the "user_settings_list"`
StepDefinitionGeneric tapWidgetOfTypeWithinStep() {
return when2<String, String, FlutterWorld>(
RegExp(
r'I tap the (?:button|element|label|icon|field|text|widget) of type {string} within the {string}$'),
RegExp(r'I tap the (?:button|element|label|icon|field|text|widget) of type {string} within the {string}$'),
(widgetType, ancestorKey, context) async {
final finder = context.world.appDriver.findByDescendant(
context.world.appDriver.findBy(ancestorKey, FindType.key),

View File

@ -1,3 +1,6 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_driver/flutter_driver.dart';
import 'package:flutter_gherkin/flutter_gherkin.dart';
import 'package:gherkin/gherkin.dart';
@ -10,8 +13,7 @@ import 'package:gherkin/gherkin.dart';
/// `Then I tap the widget that contains the text "My User Profile"`
StepDefinitionGeneric tapWidgetWithTextStep() {
return then1<String, FlutterWorld>(
RegExp(
r'I tap the (?:button|element|label|field|text|widget) that contains the text {string}$'),
RegExp(r'I tap the (?:button|element|label|field|text|widget) that contains the text {string}$'),
(input1, context) async {
final finder = context.world.appDriver.findBy(input1, FindType.text);
print("to tap: $finder");
@ -20,3 +22,39 @@ StepDefinitionGeneric tapWidgetWithTextStep() {
},
);
}
/// Select and scroll a dropdown list in a given direction
///
/// Examples:
///
/// `Then I scroll the dropdown list "LanguageList" by -10`
StepDefinitionGeneric scrollDropDown() {
return then2<String, double, FlutterWorld>(
RegExp(r'I scroll the dropdown list {string} by {num}'),
(input1, distance, context) async {
final finder = context.world.appDriver.findBy(input1, FindType.key);
await context.world.appDriver.tap(finder);
await context.world.appDriver.waitForAppToSettle();
final dropdownListFinder = context.world.appDriver.findBy(Scrollable, FindType.type);
await context.world.appDriver.scroll(dropdownListFinder.last, dy: distance);
await context.world.appDriver.waitForAppToSettle();
},
);
}
/// Taps a dropdown that contains text.
///
/// Examples:
///
/// `Then I tap the dropdown button that contains the text "Logout"`
StepDefinitionGeneric selectDropDownWithTextStep() {
return then1<String, FlutterWorld>(
RegExp(r'I tap the dropdown button that contains the text {string}$'),
(input1, context) async {
final finder = context.world.appDriver.findBy(input1, FindType.text);
print("to tap: $finder");
await context.world.appDriver.scrollIntoView(finder.last);
await context.world.appDriver.tap(finder.last);
},
);
}

View File

@ -11,8 +11,7 @@ import '../parameters/existence_parameter.dart';
/// `But I expect the text "Sign up" to be absent within the "login_screen"`
StepDefinitionGeneric textExistsWithinStep() {
return then3<String, Existence, String, FlutterWorld>(
RegExp(
r'I expect the text {string} to be {existence} within the {string}$'),
RegExp(r'I expect the text {string} to be {existence} within the {string}$'),
(text, exists, ancestorKey, context) async {
final finder = context.world.appDriver.findByDescendant(
context.world.appDriver.findBy(ancestorKey, FindType.key),

View File

@ -13,8 +13,7 @@ import 'package:gherkin/gherkin.dart';
/// `Then I expect the button 'save' to be present within 1 second`
StepDefinitionGeneric thenExpectWidgetToBePresent() {
return given2<String, int, FlutterWorld>(
RegExp(
r'I expect the (?:button|element|label|icon|field|text|widget|dialog|popup) {string} to be present within {int} second(s)$'),
RegExp(r'I expect the (?:button|element|label|icon|field|text|widget|dialog|popup) {string} to be present within {int} second(s)$'),
(key, seconds, context) async {
await context.world.appDriver.waitUntil(
() async {
@ -27,7 +26,6 @@ StepDefinitionGeneric thenExpectWidgetToBePresent() {
timeout: Duration(seconds: seconds),
);
},
configuration: StepDefinitionConfiguration()
..timeout = const Duration(days: 1),
configuration: StepDefinitionConfiguration()..timeout = const Duration(days: 1),
);
}

View File

@ -18,8 +18,7 @@ import 'package:gherkin/gherkin.dart';
/// `When I long press "controlKey" widget`
StepDefinitionGeneric whenLongPressWidget() {
return when1<String, FlutterWorld>(
RegExp(
r'I long press the {string} (?:button|element|label|icon|field|text|widget)$'),
RegExp(r'I long press the {string} (?:button|element|label|icon|field|text|widget)$'),
(key, context) async {
final finder = context.world.appDriver.findBy(key, FindType.key);
@ -33,8 +32,7 @@ StepDefinitionGeneric whenLongPressWidget() {
/// Long presses the widget found with the given control key, without scrolling into view
StepDefinitionGeneric whenLongPressWidgetWithoutScroll() {
return when1<String, FlutterWorld>(
RegExp(
r'I long press the {string} (?:button|element|label|icon|field|text|widget) without scrolling it into view$'),
RegExp(r'I long press the {string} (?:button|element|label|icon|field|text|widget) without scrolling it into view$'),
(key, context) async {
final finder = context.world.appDriver.findBy(key, FindType.key);
@ -48,8 +46,7 @@ StepDefinitionGeneric whenLongPressWidgetWithoutScroll() {
/// Long presses the widget found with the given control key, for the given duration
StepDefinitionGeneric whenLongPressWidgetForDuration() {
return when2<String, int, FlutterWorld>(
RegExp(
r'I long press the {string} (?:button|element|label|icon|field|text|widget) for {int} milliseconds$'),
RegExp(r'I long press the {string} (?:button|element|label|icon|field|text|widget) for {int} milliseconds$'),
(key, milliseconds, context) async {
final finder = context.world.appDriver.findBy(key, FindType.key);

View File

@ -13,6 +13,7 @@ StepDefinitionGeneric whenTapBackButtonWidget() {
RegExp(r'I tap the back (?:button|element|widget|icon|text)$'),
(context) async {
await context.world.appDriver.pageBack();
await context.world.appDriver.waitForAppToSettle();
},
);
}

View File

@ -18,8 +18,7 @@ import 'package:gherkin/gherkin.dart';
/// `When I tap "controlKey" widget"`
StepDefinitionGeneric whenTapWidget() {
return when1<String, FlutterWorld>(
RegExp(
r'I tap the {string} (?:button|element|label|icon|field|text|widget)$'),
RegExp(r'I tap the {string} (?:button|element|label|icon|field|text|widget)$'),
(key, context) async {
final finder = context.world.appDriver.findBy(key, FindType.key);
@ -36,11 +35,9 @@ StepDefinitionGeneric whenTapWidget() {
StepDefinitionGeneric whenTapWidgetWithoutScroll() {
return when1<String, FlutterWorld>(
RegExp(
r'I tap the {string} (?:button|element|label|icon|field|text|widget) without scrolling it into view$'),
RegExp(r'I tap the {string} (?:button|element|label|icon|field|text|widget) without scrolling it into view$'),
(key, context) async {
final finder =
context.world.appDriver.findByDescendant(key, FindType.key);
final finder = context.world.appDriver.findByDescendant(key, FindType.key);
await context.world.appDriver.tap(
finder,

View File

@ -4,8 +4,7 @@ import 'package:flutter_gherkin/flutter_gherkin_with_driver.dart';
import '../runners/flutter_run_process_handler.dart';
/// Driver version of the FlutterWorld with a typed driver
class FlutterDriverWorld extends FlutterTypedAdapterWorld<FlutterDriver,
SerializableFinder, dynamic> {
class FlutterDriverWorld extends FlutterTypedAdapterWorld<FlutterDriver, SerializableFinder, dynamic> {
FlutterRunProcessHandler? _flutterRunProcessHandler;
void setFlutterDriver(FlutterDriver flutterDriver) {

View File

@ -6,5 +6,4 @@ import 'package:flutter_gherkin/flutter_gherkin.dart';
/// It also allows interaction with the app under test through the `appDriver`
/// which exposes an instance of `AppDriverAdapter` and an
/// instance of `WidgetTester` via the property `rawAppDriver`
class FlutterWidgetTesterWorld
extends FlutterTypedAdapterWorld<WidgetTester, Finder, Widget> {}
class FlutterWidgetTesterWorld extends FlutterTypedAdapterWorld<WidgetTester, Finder, Widget> {}

View File

@ -38,6 +38,5 @@ class FlutterTypedAdapterWorld<TDriver, TFinder, TWidget> extends FlutterWorld {
/// The adapter that is used to agnostically drive the app under test
@override
AppDriverAdapter<TDriver, TFinder, TWidget> get appDriver =>
_adapter as AppDriverAdapter<TDriver, TFinder, TWidget>;
AppDriverAdapter<TDriver, TFinder, TWidget> get appDriver => _adapter as AppDriverAdapter<TDriver, TFinder, TWidget>;
}