chore(merge): updated merged in steps to use function based implementation

This commit is contained in:
Jon Samwell 2020-07-19 11:58:46 +10:00
parent 48bee80cc6
commit b2f86e0446
17 changed files with 212 additions and 199 deletions

View File

@ -1,7 +1,6 @@
import 'dart:async';
import 'package:flutter_gherkin/flutter_gherkin.dart';
import 'package:gherkin/gherkin.dart';
import 'package:glob/glob.dart';
import 'hooks/hook_example.dart';
import 'steps/colour_parameter.dart';
import 'steps/given_I_pick_a_colour_step.dart';

View File

@ -2,10 +2,8 @@ Feature: Startup
Scenario: should increment counter
Given I expect the "counter" to be "0"
#! profile "action speed"
When I tap the "increment" button
And I tap the "increment" button
#! end
Then I expect the "counter" to be "2"
Scenario: counter should reset when app is restarted

File diff suppressed because one or more lines are too long

View File

@ -1,6 +1,9 @@
import 'package:gherkin/gherkin.dart';
enum Existence { present, absent }
enum Existence {
present,
absent,
}
class ExistenceParameter extends CustomParameter<Existence> {
ExistenceParameter()
@ -14,7 +17,8 @@ class ExistenceParameter extends CustomParameter<Existence> {
case 'absent':
return Existence.absent;
default:
throw ArgumentError('"present" or "absent" must be defined for this parameter');
throw ArgumentError(
'Value `$c` must be defined for this Existence parameter');
}
},
);

View File

@ -13,33 +13,29 @@ import 'package:gherkin/gherkin.dart';
/// Examples:
///
/// `Then I expect a "Row" that contains the text "X" to also contain the text "Y"`
class SiblingContainsTextStep
extends When3WithWorld<String, String, String, FlutterWorld> {
@override
Future<void> executeStep(
String ancestorType, String leadingText, String valueText) async {
final ancestor = await find.ancestor(
of: find.text(leadingText),
matching: find.byType(ancestorType),
firstMatchOnly: true,
);
StepDefinitionGeneric SiblingContainsTextStep() {
return given3<String, String, String, FlutterWorld>(
'I expect a {string} that contains the text {string} to also contain the text {string}',
(ancestorType, leadingText, valueText, context) async {
final ancestor = await find.ancestor(
of: find.text(leadingText),
matching: find.byType(ancestorType),
firstMatchOnly: true,
);
final valueWidget = await find.descendant(
of: ancestor,
matching: find.text(valueText),
firstMatchOnly: true,
);
final valueWidget = await find.descendant(
of: ancestor,
matching: find.text(valueText),
firstMatchOnly: true,
);
final isPresent = await FlutterDriverUtils.isPresent(
world.driver,
valueWidget,
timeout: timeout,
);
final isPresent = await FlutterDriverUtils.isPresent(
context.world.driver,
valueWidget,
timeout: context.configuration?.timeout ?? const Duration(seconds: 20),
);
expect(isPresent, true);
}
@override
RegExp get pattern => RegExp(
r'I expect a {string} that contains the text {string} to also contain the text {string}');
context.expect(isPresent, true);
},
);
}

View File

@ -8,8 +8,11 @@ import '../parameters/swipe_direction_parameter.dart';
mixin _SwipeHelper
on When3WithWorld<SwipeDirection, int, String, FlutterWorld> {
@protected
Future<void> swipeOnFinder(SerializableFinder finder,
SwipeDirection direction, int swipeAmount) async {
Future<void> swipeOnFinder(
SerializableFinder finder,
SwipeDirection direction,
int swipeAmount,
) async {
if (direction == SwipeDirection.left || direction == SwipeDirection.right) {
final offset =
direction == SwipeDirection.right ? swipeAmount : (swipeAmount * -1);
@ -47,7 +50,10 @@ class SwipeOnKeyStep
with _SwipeHelper {
@override
Future<void> executeStep(
SwipeDirection direction, int swipeAmount, String key) async {
SwipeDirection direction,
int swipeAmount,
String key,
) async {
final finder = find.byValueKey(key);
await swipeOnFinder(finder, direction, swipeAmount);
}
@ -67,7 +73,10 @@ class SwipeOnTextStep
with _SwipeHelper {
@override
Future<void> executeStep(
SwipeDirection direction, int swipeAmount, String text) async {
SwipeDirection direction,
int swipeAmount,
String text,
) async {
final finder = find.text(text);
await swipeOnFinder(finder, direction, swipeAmount);
}

View File

@ -8,39 +8,39 @@ import 'package:gherkin/gherkin.dart';
/// Examples:
///
/// `Then I tap the label that contains the text "Logout" within the "user_settings_list"`
class TapTextWithinWidgetStep
extends When2WithWorld<String, String, FlutterWorld> {
@override
Future<void> executeStep(String text, String ancestorKey) async {
final finder = find.descendant(
of: find.byValueKey(ancestorKey),
matching: find.text(text),
firstMatchOnly: true,
);
final isPresent = await FlutterDriverUtils.isPresent(
world.driver,
finder,
timeout: timeout * .2,
);
if (!isPresent) {
await world.driver.scrollUntilVisible(
find.byValueKey(ancestorKey),
find.text(text),
dyScroll: -100.0,
timeout: timeout * .9,
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}'),
(text, ancestorKey, context) async {
final timeout =
context.configuration?.timeout ?? const Duration(seconds: 20);
final finder = find.descendant(
of: find.byValueKey(ancestorKey),
matching: find.text(text),
firstMatchOnly: true,
);
}
await FlutterDriverUtils.tap(
world.driver,
finder,
timeout: timeout,
);
}
final isPresent = await FlutterDriverUtils.isPresent(
context.world.driver,
finder,
timeout: timeout * .2,
);
@override
RegExp get pattern => RegExp(
r'I tap the (?:button|element|label|field|text|widget) that contains the text {string} within the {string}');
if (!isPresent) {
await context.world.driver.scrollUntilVisible(
find.byValueKey(ancestorKey),
find.text(text),
dyScroll: -100.0,
timeout: timeout * .9,
);
}
await FlutterDriverUtils.tap(
context.world.driver,
finder,
timeout: timeout,
);
},
);
}

View File

@ -9,17 +9,15 @@ import 'package:gherkin/gherkin.dart';
/// `Then I tap the element of type "MaterialButton"`
/// `Then I tap the label of type "ListTile"`
/// `Then I tap the field of type "TextField"`
class TapWidgetOfTypeStep extends When1WithWorld<String, FlutterWorld> {
@override
Future<void> executeStep(String input1) async {
await FlutterDriverUtils.tap(
world.driver,
find.byType(input1),
timeout: timeout,
);
}
@override
RegExp get pattern => RegExp(
r'I tap the (?:button|element|label|icon|field|text|widget) of type {string}$');
StepDefinitionGeneric TapWidgetOfTypeStep() {
return given1<String, FlutterWorld>(
RegExp(
r'I tap the (?:button|element|label|icon|field|text|widget) of type {string}$'),
(input1, context) async {
await FlutterDriverUtils.tap(
context.world.driver,
find.byType(input1),
);
},
);
}

View File

@ -7,23 +7,20 @@ import 'package:gherkin/gherkin.dart';
/// Examples:
///
/// `Then I tap the element of type "MaterialButton" within the "user_settings_list"`
class TapWidgetOfTypeWithinStep
extends When2WithWorld<String, String, FlutterWorld> {
@override
Future<void> executeStep(String widgetType, String ancestorKey) async {
final finder = find.descendant(
of: find.byValueKey(ancestorKey),
matching: find.byType(widgetType),
firstMatchOnly: true,
);
await FlutterDriverUtils.tap(
world.driver,
finder,
timeout: timeout,
);
}
@override
RegExp get pattern => RegExp(
r'I tap the (?:button|element|label|icon|field|text|widget) of type {string} within the {string}$');
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}$'),
(widgetType, ancestorKey, context) async {
final finder = find.descendant(
of: find.byValueKey(ancestorKey),
matching: find.byType(widgetType),
firstMatchOnly: true,
);
await FlutterDriverUtils.tap(
context.world.driver,
finder,
);
},
);
}

View File

@ -9,19 +9,17 @@ import 'package:gherkin/gherkin.dart';
/// `Then I tap the label that contains the text "Logout"`
/// `Then I tap the button that contains the text "Sign up"`
/// `Then I tap the widget that contains the text "My User Profile"`
class TapWidgetWithTextStep extends When1WithWorld<String, FlutterWorld> {
@override
Future<void> executeStep(String input1) async {
final finder = find.text(input1);
await world.driver.scrollIntoView(finder, timeout: timeout);
await FlutterDriverUtils.tap(
world.driver,
finder,
timeout: timeout,
);
}
@override
RegExp get pattern => RegExp(
r'I tap the (?:button|element|label|field|text|widget) that contains the text {string}$');
StepDefinitionGeneric TapWidgetWithTextStep() {
return then1<String, FlutterWorld>(
RegExp(
r'I tap the (?:button|element|label|field|text|widget) that contains the text {string}$'),
(input1, context) async {
final finder = find.text(input1);
await context.world.driver.scrollIntoView(finder);
await FlutterDriverUtils.tap(
context.world.driver,
finder,
);
},
);
}

View File

@ -10,28 +10,24 @@ import '../parameters/existence_parameter.dart';
///
/// `Then I expect the text "Logout" to be present`
/// `But I expect the text "Signup" to be absent`
class TextExistsStep extends When2WithWorld<String, Existence, FlutterWorld> {
@override
Future<void> executeStep(String text, Existence exists) async {
if (exists == Existence.present) {
final isPresent = await FlutterDriverUtils.isPresent(
world.driver,
find.text(text),
timeout: timeout,
);
StepDefinitionGeneric TextExistsStep() {
return then2<String, Existence, FlutterWorld>(
RegExp(r'I expect the text {string} to be {existence}$'),
(text, exists, context) async {
if (exists == Existence.present) {
final isPresent = await FlutterDriverUtils.isPresent(
context.world.driver,
find.text(text),
);
expect(isPresent, true);
} else {
final isAbsent = await FlutterDriverUtils.isAbsent(
world.driver,
find.text(text),
timeout: timeout,
);
expect(isAbsent, true);
}
}
@override
RegExp get pattern =>
RegExp(r'I expect the text {string} to be {existence}$');
context.expect(isPresent, true);
} else {
final isAbsent = await FlutterDriverUtils.isAbsent(
context.world.driver,
find.text(text),
);
context.expect(isAbsent, true);
}
},
);
}

View File

@ -10,26 +10,23 @@ import '../parameters/existence_parameter.dart';
///
/// `Then I expect the text "Logout" to be present within the "user_settings_list"`
/// `But I expect the text "Signup" to be absent within the "login_screen"`
class TextExistsWithinStep
extends When3WithWorld<String, Existence, String, FlutterWorld> {
@override
Future<void> executeStep(
String text, Existence exists, String ancestorKey) async {
final finder = find.descendant(
of: find.byValueKey(ancestorKey),
matching: find.text(text),
firstMatchOnly: true,
);
StepDefinitionGeneric TextExistsWithinStep() {
return then3<String, Existence, String, FlutterWorld>(
RegExp(
r'I expect the text {string} to be {existence} within the {string}$'),
(text, exists, ancestorKey, context) async {
final finder = find.descendant(
of: find.byValueKey(ancestorKey),
matching: find.text(text),
firstMatchOnly: true,
);
final isPresent = await FlutterDriverUtils.isPresent(
world.driver,
finder,
timeout: timeout,
);
expect(isPresent, exists == Existence.present);
}
final isPresent = await FlutterDriverUtils.isPresent(
context.world.driver,
finder,
);
@override
RegExp get pattern => RegExp(
r'I expect the text {string} to be {existence} within the {string}$');
context.expect(isPresent, exists == Existence.present);
},
);
}

View File

@ -10,23 +10,24 @@ import '../parameters/existence_parameter.dart';
///
/// `Then I wait until the "login_loading_indicator" is absent`
/// `And I wait until the "login_screen" is present`
class WaitUntilKeyExistsStep
extends When2WithWorld<String, Existence, FlutterWorld> {
@override
Future<void> executeStep(String keyString, Existence existence) async {
await FlutterDriverUtils.waitUntil(
world.driver,
() {
return existence == Existence.absent
? FlutterDriverUtils.isAbsent(
world.driver, find.byValueKey(keyString))
: FlutterDriverUtils.isPresent(
world.driver, find.byValueKey(keyString));
},
timeout: timeout,
);
}
@override
RegExp get pattern => RegExp(r'I wait until the {string} is {existence}');
StepDefinitionGeneric WaitUntilKeyExistsStep() {
return then2<String, Existence, FlutterWorld>(
'I wait until the {string} is {existence}',
(keyString, existence, context) async {
await FlutterDriverUtils.waitUntil(
context.world.driver,
() {
return existence == Existence.absent
? FlutterDriverUtils.isAbsent(
context.world.driver,
find.byValueKey(keyString),
)
: FlutterDriverUtils.isPresent(
context.world.driver,
find.byValueKey(keyString),
);
},
);
},
);
}

View File

@ -10,22 +10,24 @@ import '../parameters/existence_parameter.dart';
///
/// `Then I wait until the element of type "ProgressIndicator" is absent`
/// `And I wait until the button of type the "MaterialButton" is present`
class WaitUntilTypeExistsStep
extends When2WithWorld<String, Existence, FlutterWorld> {
@override
Future<void> executeStep(String ofType, Existence existence) async {
await FlutterDriverUtils.waitUntil(
world.driver,
() {
return existence == Existence.absent
? FlutterDriverUtils.isAbsent(world.driver, find.byType(ofType))
: FlutterDriverUtils.isPresent(world.driver, find.byType(ofType));
},
timeout: timeout,
);
}
@override
RegExp get pattern => RegExp(
r'I wait until the (?:button|element|label|icon|field|text|widget) of type {string} is {existence}');
StepDefinitionGeneric WaitUntilTypeExistsStep() {
return then2<String, Existence, FlutterWorld>(
'I wait until the (?:button|element|label|icon|field|text|widget) of type {string} is {existence}',
(ofType, existence, context) async {
await FlutterDriverUtils.waitUntil(
context.world.driver,
() {
return existence == Existence.absent
? FlutterDriverUtils.isAbsent(
context.world.driver,
find.byType(ofType),
)
: FlutterDriverUtils.isPresent(
context.world.driver,
find.byType(ofType),
);
},
);
},
);
}

View File

@ -12,7 +12,7 @@ import 'package:gherkin/gherkin.dart';
/// `When I tap the back widget"`
StepDefinitionGeneric WhenTapBackButtonWidget() {
return when1<String, FlutterWorld>(
RegExp(r'I tap the back (?:button|element|widget)$'),
RegExp(r'I tap the back (?:button|element|widget|icon|text)$'),
(_, context) async {
await FlutterDriverUtils.tap(
context.world.driver,

View File

@ -2,6 +2,7 @@ import 'package:flutter_gherkin/flutter_gherkin.dart';
import 'package:flutter_gherkin/src/flutter/hooks/app_runner_hook.dart';
import 'package:test/test.dart';
import 'mocks/parameter_mock.dart';
import 'mocks/step_definition_mock.dart';
void main() {
@ -22,19 +23,26 @@ void main() {
config.prepare();
expect(config.stepDefinitions, isNotNull);
expect(config.stepDefinitions.length, 9);
expect(config.stepDefinitions.length, 20);
expect(config.customStepParameterDefinitions, isNotNull);
expect(config.customStepParameterDefinitions.length, 2);
});
test('common step definition added to existing steps', () {
final config = FlutterTestConfiguration()
..stepDefinitions = [MockStepDefinition()];
..stepDefinitions = [MockStepDefinition()]
..customStepParameterDefinitions = [MockParameter()];
expect(config.stepDefinitions.length, 1);
config.prepare();
expect(config.stepDefinitions, isNotNull);
expect(config.stepDefinitions.length, 10);
expect(config.stepDefinitions.length, 21);
expect(config.stepDefinitions.elementAt(0),
(x) => x is MockStepDefinition);
expect(config.customStepParameterDefinitions, isNotNull);
expect(config.customStepParameterDefinitions.length, 3);
expect(config.customStepParameterDefinitions.elementAt(0),
(x) => x is MockParameter);
});
});
});

View File

@ -0,0 +1,10 @@
import 'package:gherkin/gherkin.dart';
class MockParameter extends CustomParameter<String> {
MockParameter()
: super(
'MockStringParam',
RegExp('a'),
(a) => 'a',
);
}