Formatting + Dropdown Widgets
This commit is contained in:
parent
9b817676e4
commit
f20a14f3d8
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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');
|
||||
|
|
|
@ -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"\$");
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -35,6 +35,8 @@ class FlutterTestConfiguration extends TestConfiguration {
|
|||
tapWidgetOfTypeStep(),
|
||||
tapWidgetOfTypeWithinStep(),
|
||||
tapWidgetWithTextStep(),
|
||||
selectDropDownWithTextStep(),
|
||||
scrollDropDown(),
|
||||
textExistsStep(),
|
||||
textExistsWithinStep(),
|
||||
waitUntilKeyExistsStep(),
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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');
|
||||
}
|
||||
},
|
||||
);
|
||||
|
|
|
@ -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');
|
||||
}
|
||||
},
|
||||
);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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}');
|
||||
}
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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),
|
||||
);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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();
|
||||
},
|
||||
);
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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> {}
|
||||
|
|
|
@ -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>;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue