From f20a14f3d860b7f3a2d2cbc715ee1d4669822f3d Mon Sep 17 00:00:00 2001 From: Sarah Jamie Lewis Date: Wed, 8 Feb 2023 14:55:24 -0800 Subject: [PATCH] Formatting + Dropdown Widgets --- .../flutter/adapters/app_driver_adapter.dart | 3 +- .../flutter_driver_app_driver_adapter.dart | 3 +- .../builders/gherkin_test_suite_builder.dart | 3 +- .../gherkin_suite_test_generator.dart | 29 ++++--------- .../flutter_driver_test_configuration.dart | 10 ++--- .../flutter_test_configuration.dart | 2 + lib/src/flutter/hooks/app_runner_hook.dart | 12 ++---- ...attach_screenshot_on_failed_step_hook.dart | 4 +- .../parameters/existence_parameter.dart | 3 +- .../parameters/swipe_direction_parameter.dart | 3 +- .../reporters/flutter_driver_reporter.dart | 6 +-- .../runners/flutter_run_process_handler.dart | 11 ++--- .../gherkin_integration_test_runner.dart | 30 ++++--------- lib/src/flutter/steps/swipe_step.dart | 23 ++++------ .../steps/tap_text_within_widget_step.dart | 6 +-- .../steps/tap_widget_of_type_step.dart | 3 +- .../steps/tap_widget_of_type_within_step.dart | 3 +- .../steps/tap_widget_with_text_step.dart | 42 ++++++++++++++++++- .../steps/text_exists_within_step.dart | 3 +- ...then_expect_widget_to_be_present_step.dart | 6 +-- .../steps/when_long_press_widget_step.dart | 9 ++-- .../steps/when_tap_the_back_button_step.dart | 1 + .../flutter/steps/when_tap_widget_step.dart | 9 ++-- .../flutter/world/flutter_driver_world.dart | 3 +- .../world/flutter_widget_tester_world.dart | 3 +- lib/src/flutter/world/flutter_world.dart | 3 +- 26 files changed, 100 insertions(+), 133 deletions(-) diff --git a/lib/src/flutter/adapters/app_driver_adapter.dart b/lib/src/flutter/adapters/app_driver_adapter.dart index 082eb66..d5f7626 100644 --- a/lib/src/flutter/adapters/app_driver_adapter.dart +++ b/lib/src/flutter/adapters/app_driver_adapter.dart @@ -130,8 +130,7 @@ abstract class AppDriverAdapter { return Future.microtask( () async { final completer = Completer(); - var maxAttempts = - (timeout!.inMilliseconds / pollInterval!.inMilliseconds).round(); + var maxAttempts = (timeout!.inMilliseconds / pollInterval!.inMilliseconds).round(); var attempts = 0; while (attempts < maxAttempts) { diff --git a/lib/src/flutter/adapters/flutter_driver_app_driver_adapter.dart b/lib/src/flutter/adapters/flutter_driver_app_driver_adapter.dart index fb423ed..9c82b0d 100644 --- a/lib/src/flutter/adapters/flutter_driver_app_driver_adapter.dart +++ b/lib/src/flutter/adapters/flutter_driver_app_driver_adapter.dart @@ -4,8 +4,7 @@ import 'package:flutter_driver/flutter_driver.dart'; import 'app_driver_adapter.dart'; -class FlutterDriverAppDriverAdapter - extends AppDriverAdapter { +class FlutterDriverAppDriverAdapter extends AppDriverAdapter { FlutterDriverAppDriverAdapter(FlutterDriver rawAdapter) : super(rawAdapter); @override diff --git a/lib/src/flutter/code_generation/builders/gherkin_test_suite_builder.dart b/lib/src/flutter/code_generation/builders/gherkin_test_suite_builder.dart index 81df0c1..8302ba6 100644 --- a/lib/src/flutter/code_generation/builders/gherkin_test_suite_builder.dart +++ b/lib/src/flutter/code_generation/builders/gherkin_test_suite_builder.dart @@ -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'); diff --git a/lib/src/flutter/code_generation/generators/gherkin_suite_test_generator.dart b/lib/src/flutter/code_generation/generators/gherkin_suite_test_generator.dart index 745e0cf..4791e1c 100644 --- a/lib/src/flutter/code_generation/generators/gherkin_suite_test_generator.dart +++ b/lib/src/flutter/code_generation/generators/gherkin_suite_test_generator.dart @@ -25,8 +25,7 @@ class NoOpReporter extends MessageReporter { } } -class GherkinSuiteTestGenerator - extends GeneratorForAnnotation { +class GherkinSuiteTestGenerator extends GeneratorForAnnotation { static const String template = ''' class _CustomGherkinIntegrationTestRunner extends GherkinIntegrationTestRunner { _CustomGherkinIntegrationTestRunner({ @@ -79,21 +78,15 @@ Future 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 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"\$"); } diff --git a/lib/src/flutter/configuration/flutter_driver_test_configuration.dart b/lib/src/flutter/configuration/flutter_driver_test_configuration.dart index cb440ef..3e09985 100644 --- a/lib/src/flutter/configuration/flutter_driver_test_configuration.dart +++ b/lib/src/flutter/configuration/flutter_driver_test_configuration.dart @@ -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 Function(FlutterDriver driver)? - onAfterFlutterDriverConnect; + final Future Function(FlutterDriver driver)? onAfterFlutterDriverConnect; void setObservatoryDebuggerUri(String uri) => _observatoryDebuggerUri = uri; Future createFlutterDriver([String? dartVmServiceUrl]) async { final completer = Completer(); - 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); diff --git a/lib/src/flutter/configuration/flutter_test_configuration.dart b/lib/src/flutter/configuration/flutter_test_configuration.dart index 211a5e8..77617f4 100644 --- a/lib/src/flutter/configuration/flutter_test_configuration.dart +++ b/lib/src/flutter/configuration/flutter_test_configuration.dart @@ -35,6 +35,8 @@ class FlutterTestConfiguration extends TestConfiguration { tapWidgetOfTypeStep(), tapWidgetOfTypeWithinStep(), tapWidgetWithTextStep(), + selectDropDownWithTextStep(), + scrollDropDown(), textExistsStep(), textExistsWithinStep(), waitUntilKeyExistsStep(), diff --git a/lib/src/flutter/hooks/app_runner_hook.dart b/lib/src/flutter/hooks/app_runner_hook.dart index ece11b9..84be3c2 100644 --- a/lib/src/flutter/hooks/app_runner_hook.dart +++ b/lib/src/flutter/hooks/app_runner_hook.dart @@ -21,8 +21,7 @@ class FlutterAppRunnerHook extends Hook { } @override - Future onAfterRun(TestConfiguration config) async => - await _terminateApp(); + Future onAfterRun(TestConfiguration config) async => await _terminateApp(); @override Future 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) { diff --git a/lib/src/flutter/hooks/attach_screenshot_on_failed_step_hook.dart b/lib/src/flutter/hooks/attach_screenshot_on_failed_step_hook.dart index 26df932..ae7159a 100644 --- a/lib/src/flutter/hooks/attach_screenshot_on_failed_step_hook.dart +++ b/lib/src/flutter/hooks/attach_screenshot_on_failed_step_hook.dart @@ -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); diff --git a/lib/src/flutter/parameters/existence_parameter.dart b/lib/src/flutter/parameters/existence_parameter.dart index 6e6d47c..0dcbf44 100644 --- a/lib/src/flutter/parameters/existence_parameter.dart +++ b/lib/src/flutter/parameters/existence_parameter.dart @@ -17,8 +17,7 @@ class ExistenceParameter extends CustomParameter { 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'); } }, ); diff --git a/lib/src/flutter/parameters/swipe_direction_parameter.dart b/lib/src/flutter/parameters/swipe_direction_parameter.dart index d9efaaa..ee5ed6d 100644 --- a/lib/src/flutter/parameters/swipe_direction_parameter.dart +++ b/lib/src/flutter/parameters/swipe_direction_parameter.dart @@ -18,8 +18,7 @@ class SwipeDirectionParameter extends CustomParameter { 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'); } }, ); diff --git a/lib/src/flutter/reporters/flutter_driver_reporter.dart b/lib/src/flutter/reporters/flutter_driver_reporter.dart index 775495f..a435075 100644 --- a/lib/src/flutter/reporters/flutter_driver_reporter.dart +++ b/lib/src/flutter/reporters/flutter_driver_reporter.dart @@ -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); diff --git a/lib/src/flutter/runners/flutter_run_process_handler.dart b/lib/src/flutter/runners/flutter_run_process_handler.dart index 0d70e22..d031c39 100644 --- a/lib/src/flutter/runners/flutter_run_process_handler.dart +++ b/lib/src/flutter/runners/flutter_run_process_handler.dart @@ -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'); } } } diff --git a/lib/src/flutter/runners/gherkin_integration_test_runner.dart b/lib/src/flutter/runners/gherkin_integration_test_runner.dart index 78f59ef..833011b 100644 --- a/lib/src/flutter/runners/gherkin_integration_test_runner.dart +++ b/lib/src/flutter/runners/gherkin_integration_test_runner.dart @@ -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? tags, }) async { final debugInformation = RunnableDebugInformation(path, 0, name); - final featureTags = - (tags ?? const Iterable.empty()).map((t) => Tag(t.toString(), 0)); + final featureTags = (tags ?? const Iterable.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 _appLifecyclePhasePumper( diff --git a/lib/src/flutter/steps/swipe_step.dart b/lib/src/flutter/steps/swipe_step.dart index 43d312a..79249f7 100644 --- a/lib/src/flutter/steps/swipe_step.dart +++ b/lib/src/flutter/steps/swipe_step.dart @@ -5,16 +5,14 @@ import 'package:gherkin/gherkin.dart'; import '../parameters/swipe_direction_parameter.dart'; -mixin _SwipeHelper - on When3WithWorld { +mixin _SwipeHelper on When3WithWorld { Future 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 - with _SwipeHelper { +class SwipeOnKeyStep extends When3WithWorld with _SwipeHelper { @override Future 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 - with _SwipeHelper { +class SwipeOnTextStep extends When3WithWorld with _SwipeHelper { @override Future 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}'); } diff --git a/lib/src/flutter/steps/tap_text_within_widget_step.dart b/lib/src/flutter/steps/tap_text_within_widget_step.dart index 7d51084..5ad2a6d 100644 --- a/lib/src/flutter/steps/tap_text_within_widget_step.dart +++ b/lib/src/flutter/steps/tap_text_within_widget_step.dart @@ -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( - 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), diff --git a/lib/src/flutter/steps/tap_widget_of_type_step.dart b/lib/src/flutter/steps/tap_widget_of_type_step.dart index 1832a37..61fd718 100644 --- a/lib/src/flutter/steps/tap_widget_of_type_step.dart +++ b/lib/src/flutter/steps/tap_widget_of_type_step.dart @@ -10,8 +10,7 @@ import 'package:gherkin/gherkin.dart'; /// `Then I tap the field of type "TextField"` StepDefinitionGeneric tapWidgetOfTypeStep() { return given1( - 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( diff --git a/lib/src/flutter/steps/tap_widget_of_type_within_step.dart b/lib/src/flutter/steps/tap_widget_of_type_within_step.dart index d77953a..5543b20 100644 --- a/lib/src/flutter/steps/tap_widget_of_type_within_step.dart +++ b/lib/src/flutter/steps/tap_widget_of_type_within_step.dart @@ -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( - 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), diff --git a/lib/src/flutter/steps/tap_widget_with_text_step.dart b/lib/src/flutter/steps/tap_widget_with_text_step.dart index fb32d14..23f95d0 100644 --- a/lib/src/flutter/steps/tap_widget_with_text_step.dart +++ b/lib/src/flutter/steps/tap_widget_with_text_step.dart @@ -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( - 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( + 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( + 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); + }, + ); +} diff --git a/lib/src/flutter/steps/text_exists_within_step.dart b/lib/src/flutter/steps/text_exists_within_step.dart index bd9cda2..f26d68c 100644 --- a/lib/src/flutter/steps/text_exists_within_step.dart +++ b/lib/src/flutter/steps/text_exists_within_step.dart @@ -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( - 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), diff --git a/lib/src/flutter/steps/then_expect_widget_to_be_present_step.dart b/lib/src/flutter/steps/then_expect_widget_to_be_present_step.dart index 1c86cdc..225bbff 100644 --- a/lib/src/flutter/steps/then_expect_widget_to_be_present_step.dart +++ b/lib/src/flutter/steps/then_expect_widget_to_be_present_step.dart @@ -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( - 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), ); } diff --git a/lib/src/flutter/steps/when_long_press_widget_step.dart b/lib/src/flutter/steps/when_long_press_widget_step.dart index f55958b..066fd43 100644 --- a/lib/src/flutter/steps/when_long_press_widget_step.dart +++ b/lib/src/flutter/steps/when_long_press_widget_step.dart @@ -18,8 +18,7 @@ import 'package:gherkin/gherkin.dart'; /// `When I long press "controlKey" widget` StepDefinitionGeneric whenLongPressWidget() { return when1( - 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( - 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( - 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); diff --git a/lib/src/flutter/steps/when_tap_the_back_button_step.dart b/lib/src/flutter/steps/when_tap_the_back_button_step.dart index 4f4846c..385540c 100644 --- a/lib/src/flutter/steps/when_tap_the_back_button_step.dart +++ b/lib/src/flutter/steps/when_tap_the_back_button_step.dart @@ -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(); }, ); } diff --git a/lib/src/flutter/steps/when_tap_widget_step.dart b/lib/src/flutter/steps/when_tap_widget_step.dart index 213780e..c6404e7 100644 --- a/lib/src/flutter/steps/when_tap_widget_step.dart +++ b/lib/src/flutter/steps/when_tap_widget_step.dart @@ -18,8 +18,7 @@ import 'package:gherkin/gherkin.dart'; /// `When I tap "controlKey" widget"` StepDefinitionGeneric whenTapWidget() { return when1( - 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( - 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, diff --git a/lib/src/flutter/world/flutter_driver_world.dart b/lib/src/flutter/world/flutter_driver_world.dart index d904f40..84ead19 100644 --- a/lib/src/flutter/world/flutter_driver_world.dart +++ b/lib/src/flutter/world/flutter_driver_world.dart @@ -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 { +class FlutterDriverWorld extends FlutterTypedAdapterWorld { FlutterRunProcessHandler? _flutterRunProcessHandler; void setFlutterDriver(FlutterDriver flutterDriver) { diff --git a/lib/src/flutter/world/flutter_widget_tester_world.dart b/lib/src/flutter/world/flutter_widget_tester_world.dart index a3125dc..dfbc5fb 100644 --- a/lib/src/flutter/world/flutter_widget_tester_world.dart +++ b/lib/src/flutter/world/flutter_widget_tester_world.dart @@ -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 {} +class FlutterWidgetTesterWorld extends FlutterTypedAdapterWorld {} diff --git a/lib/src/flutter/world/flutter_world.dart b/lib/src/flutter/world/flutter_world.dart index c10ea65..c276f67 100644 --- a/lib/src/flutter/world/flutter_world.dart +++ b/lib/src/flutter/world/flutter_world.dart @@ -38,6 +38,5 @@ class FlutterTypedAdapterWorld extends FlutterWorld { /// The adapter that is used to agnostically drive the app under test @override - AppDriverAdapter get appDriver => - _adapter as AppDriverAdapter; + AppDriverAdapter get appDriver => _adapter as AppDriverAdapter; }