diff --git a/CHANGELOG.md b/CHANGELOG.md index 24357c9..4d03a5f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,12 @@ +## [1.1.8+7] - 11/08/2020 +- Added well know steps and a driver helper method to long press a widget + +``` +When I long press "controlKey" button + +When I long press "controlKey" icon for 1500 milliseconds +``` + ## [1.1.8+6] - 05/08/2020 - Upgraded to latest Gherkin library version which fixes issues with non-alpha-numeric characters in multiline strings and comments https://github.com/jonsamwell/dart_gherkin/issues/14 https://github.com/jonsamwell/dart_gherkin/issues/15 https://github.com/jonsamwell/dart_gherkin/issues/16 diff --git a/README.md b/README.md index 6513b2c..aef3608 100644 --- a/README.md +++ b/README.md @@ -926,16 +926,19 @@ For convenience the library defines a number of pre-defined steps so you can get | I restart the app | Restarts the app under test | `Then I restart the app` | | I tap the back button | Taps the page default back button widget | `Then I tap the back button` | | I expect a {string} that contains the text {string} to also contain the text {string} | Discovers a sibling based on its parent widget type and asserts that the both text string exist within the parent. | `Then I expect a "Row" that contains the text "X" to also contain the text "Y"` | -| I swipe [down\|left\|right\|up] by {int} pixels on the {string} | Swipes in a cardinal direction on a widget discovered by its key. | `Then I swipe up by 800 pixels on the "login_screen"`, `Then I swipe left by 200 pixels on the "dismissible_list_item"` | +| I swipe [down\|left\|right\|up] by {int} pixels on the {string} | Swipes in a cardinal direction on a widget discovered by its key. | `Then I swipe up by 800 pixels on the "login_screen"` , `Then I swipe left by 200 pixels on the "dismissible_list_item"` | | I swipe [down\|left\|right\|up] by {int} pixels on the on the [button\|element\|label\|field\|text\|widget\|dialog\|popup] that contains the text {string} | Swipes in a cardinal direction on a widget discovered by its test. | `Then I swipe left by 400 pixels on the widget that contains the text "Dismiss Me"` | | I tap the [button\|element\|label\|field\|text\|widget] that contains the text {string} within the {string} | Taps a widget that contains the text within another widget. If the text is not visible, the ancestor will be scrolled. | `Then I tap the label that contains the text "Logout" within the "user_settings_list"` | -| I tap the [button\|element\|label\|icon\|field\|text\|widget] of type {string} | Taps a widget of type. | `Then I tap the element of type "MaterialButton"`, `Then I tap the label of type "ListTile"`, `Then I tap the field of type "TextField"` | +| I tap the [button\|element\|label\|icon\|field\|text\|widget] of type {string} | Taps a widget of type. | `Then I tap the element of type "MaterialButton"` , `Then I tap the label of type "ListTile"` , `Then I tap the field of type "TextField"` | | I tap the [button\|element\|label\|icon\|field\|text\|widget] of type {string} within the {string} | Taps a widget of type within another widget. | `Then I tap the element of type "MaterialButton" within the "user_settings_list"` | -| I tap the [button\|element\|label\|icon\|field\|text\|widget] that contains the text {string} | Taps a widget that contains text. | `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"` | -| I expect the text {string} to be [present\|absent] | Asserts the existence of text on the screen. | `Then I expect the text "Logout" to be present`, `But I expect the text "Signup" to be absent` | -| I expect the text {string} to be [present\|absent] within the {string} | Asserts the existence of text within a parent widget. | `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"` | -| I wait until the {string} is [present\absent] | Delays until a widget is present or absent. | `Then I wait until the "login_loading_indicator" is absent`, `And I wait until the "login_screen" is present` | -| I wait until the [button\|element\|label\|icon\|field\|text\|widget] of type {string} is [present\absent] | Waits until a widget type is present or absent. | `Then I wait until the element of type "ProgressIndicator" is absent`, `And I wait until the button of type "MaterialButton" is present` | +| I tap the [button\|element\|label\|icon\|field\|text\|widget] that contains the text {string} | Taps a widget that contains text. | `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"` | +| I expect the text {string} to be [present\|absent] | Asserts the existence of text on the screen. | `Then I expect the text "Logout" to be present` , `But I expect the text "Signup" to be absent` | +| I expect the text {string} to be [present\|absent] within the {string} | Asserts the existence of text within a parent widget. | `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"` | +| I wait until the {string} is [present\absent] | Delays until a widget is present or absent. | `Then I wait until the "login_loading_indicator" is absent` , `And I wait until the "login_screen" is present` | +| I wait until the [button\|element\|label\|icon\|field\|text\|widget] of type {string} is [present\absent] | Waits until a widget type is present or absent. | `Then I wait until the element of type "ProgressIndicator" is absent` , `And I wait until the button of type "MaterialButton" is present` | +| I long press the {string} [button\|element\|label\|icon\|field\|text\|widget] | Scrolls into view and long presses the widget for 500 milliseconds. | `When I long press "controlKey" button` | +| I long press the {string} [button\|element\|label\|icon\|field\|text\|widget] without scrolling it into view | Long presses the widget for 500 milliseconds. | `When I long press "controlKey" button without scrolling it into view` | +| I long press the {string} [button\|element\|label\|icon\|field\|text\|widget] for {int} milliseconds | Scrolls into view and long presses the widget for the give number of milliseconds. | `When I long press "controlKey" button without scrolling it into view for 1500 milliseconds` | #### Flutter Driver Utilities diff --git a/example/ios/Flutter/flutter_export_environment.sh b/example/ios/Flutter/flutter_export_environment.sh index 37acd34..863594b 100644 --- a/example/ios/Flutter/flutter_export_environment.sh +++ b/example/ios/Flutter/flutter_export_environment.sh @@ -9,3 +9,7 @@ export "OTHER_LDFLAGS=$(inherited) -framework Flutter" export "FLUTTER_FRAMEWORK_DIR=C:\Google\flutter\bin\cache\artifacts\engine\ios" export "FLUTTER_BUILD_NAME=1.0.0" export "FLUTTER_BUILD_NUMBER=1" +export "DART_OBFUSCATION=false" +export "TRACK_WIDGET_CREATION=false" +export "TREE_SHAKE_ICONS=false" +export "PACKAGE_CONFIG=.packages" diff --git a/example/lib/main.dart b/example/lib/main.dart index 6b7825e..5b3a211 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -23,6 +23,7 @@ class MyHomePage extends StatefulWidget { class _MyHomePageState extends State { int _counter = 0; + bool hasLongPressedText = false; void _incrementCounter() { setState(() { @@ -91,7 +92,24 @@ class _MyHomePageState extends State { MaterialPageRoute(builder: (context) => PageTwo()), ); }, - ) + ), + GestureDetector( + onLongPress: () { + setState(() { + hasLongPressedText = true; + }); + }, + child: Container( + color: + hasLongPressedText ? Colors.blueGrey : Colors.transparent, + child: Text( + hasLongPressedText + ? 'Text has been long pressed!' + : 'Text that has not been long pressed', + key: const Key('longPressText'), + ), + ), + ), ], ), ), diff --git a/example/test_driver/features/long_press_widget.feature b/example/test_driver/features/long_press_widget.feature new file mode 100644 index 0000000..e21914c --- /dev/null +++ b/example/test_driver/features/long_press_widget.feature @@ -0,0 +1,6 @@ +Feature: Interaction + + Scenario: Widget can be long pressed + Given I expect the "longPressText" to be "Text that has not been long pressed" + When I long press the "longPressText" text + Then I expect the "longPressText" to be "Text has been long pressed!" diff --git a/example/test_driver/report.json b/example/test_driver/report.json index 999bf84..fd078da 100644 --- a/example/test_driver/report.json +++ b/example/test_driver/report.json @@ -1 +1 @@ -[{"description":"","id":"startup","keyword":"Feature","line":1,"name":"Startup","uri":".\\features\\app_restart.feature","elements":[{"keyword":"Scenario","type":"scenario","id":"startup;counter should reset when app is restarted","name":"counter should reset when app is restarted","description":"","line":3,"steps":[{"keyword":"Given ","name":"I expect the \"counter\" to be \"0\"","line":4,"match":{"location":".\\features\\app_restart.feature:4"},"result":{"status":"passed","duration":78000000}},{"keyword":"When ","name":"I tap the \"increment\" button","line":5,"match":{"location":".\\features\\app_restart.feature:5"},"result":{"status":"passed","duration":336000000}},{"keyword":"Then ","name":"I expect the \"counter\" to be \"1\"","line":6,"match":{"location":".\\features\\app_restart.feature:6"},"result":{"status":"passed","duration":29000000}},{"keyword":"When ","name":"I restart the app","line":7,"match":{"location":".\\features\\app_restart.feature:7"},"result":{"status":"passed","duration":3204000000}},{"keyword":"Then ","name":"I expect the \"counter\" to be \"0\"","line":8,"match":{"location":".\\features\\app_restart.feature:8"},"result":{"status":"passed","duration":36000000}}]}]},{"description":"","id":"counter","keyword":"Feature","line":1,"name":"Counter","uri":".\\features\\counter_increases_scenerio_outline_example.feature","elements":[{"keyword":"Scenario Outline","type":"scenario","id":"counter;counter increases when the button is pressed (example 1)","name":"Counter increases when the button is pressed (Example 1)","description":"","line":5,"tags":[{"line":4,"name":"@scenario_outline"}],"steps":[{"keyword":"Given ","name":"I pick the colour red","line":6,"match":{"location":".\\features\\counter_increases_scenerio_outline_example.feature:6"},"result":{"status":"passed","duration":0}},{"keyword":"Given ","name":"I expect the \"counter\" to be \"0\"","line":7,"match":{"location":".\\features\\counter_increases_scenerio_outline_example.feature:7"},"result":{"status":"passed","duration":40000000}},{"keyword":"When ","name":"I tap the \"increment\" button 1 times","line":8,"match":{"location":".\\features\\counter_increases_scenerio_outline_example.feature:8"},"result":{"status":"passed","duration":302000000}},{"keyword":"Then ","name":"I expect the \"counter\" to be \"1\"","line":9,"match":{"location":".\\features\\counter_increases_scenerio_outline_example.feature:9"},"result":{"status":"passed","duration":26000000}}]},{"keyword":"Scenario Outline","type":"scenario","id":"counter;counter increases when the button is pressed (example 2)","name":"Counter increases when the button is pressed (Example 2)","description":"","line":5,"tags":[{"line":4,"name":"@scenario_outline"}],"steps":[{"keyword":"Given ","name":"I pick the colour red","line":6,"match":{"location":".\\features\\counter_increases_scenerio_outline_example.feature:6"},"result":{"status":"passed","duration":0}},{"keyword":"Given ","name":"I expect the \"counter\" to be \"0\"","line":7,"match":{"location":".\\features\\counter_increases_scenerio_outline_example.feature:7"},"result":{"status":"passed","duration":37000000}},{"keyword":"When ","name":"I tap the \"increment\" button 2 times","line":8,"match":{"location":".\\features\\counter_increases_scenerio_outline_example.feature:8"},"result":{"status":"passed","duration":549000000}},{"keyword":"Then ","name":"I expect the \"counter\" to be \"2\"","line":9,"match":{"location":".\\features\\counter_increases_scenerio_outline_example.feature:9"},"result":{"status":"passed","duration":22000000}}]},{"keyword":"Scenario Outline","type":"scenario","id":"counter;counter increases when the button is pressed (example 3)","name":"Counter increases when the button is pressed (Example 3)","description":"","line":5,"tags":[{"line":4,"name":"@scenario_outline"}],"steps":[{"keyword":"Given ","name":"I pick the colour red","line":6,"match":{"location":".\\features\\counter_increases_scenerio_outline_example.feature:6"},"result":{"status":"passed","duration":0}},{"keyword":"Given ","name":"I expect the \"counter\" to be \"0\"","line":7,"match":{"location":".\\features\\counter_increases_scenerio_outline_example.feature:7"},"result":{"status":"passed","duration":38000000}},{"keyword":"When ","name":"I tap the \"increment\" button 5 times","line":8,"match":{"location":".\\features\\counter_increases_scenerio_outline_example.feature:8"},"result":{"status":"passed","duration":1277000000}},{"keyword":"Then ","name":"I expect the \"counter\" to be \"5\"","line":9,"match":{"location":".\\features\\counter_increases_scenerio_outline_example.feature:9"},"result":{"status":"passed","duration":29000000}}]},{"keyword":"Scenario Outline","type":"scenario","id":"counter;counter increases when the button is pressed (example 4)","name":"Counter increases when the button is pressed (Example 4)","description":"","line":5,"tags":[{"line":4,"name":"@scenario_outline"}],"steps":[{"keyword":"Given ","name":"I pick the colour red","line":6,"match":{"location":".\\features\\counter_increases_scenerio_outline_example.feature:6"},"result":{"status":"passed","duration":7000000}},{"keyword":"Given ","name":"I expect the \"counter\" to be \"0\"","line":7,"match":{"location":".\\features\\counter_increases_scenerio_outline_example.feature:7"},"result":{"status":"passed","duration":37000000}},{"keyword":"When ","name":"I tap the \"increment\" button 10 times","line":8,"match":{"location":".\\features\\counter_increases_scenerio_outline_example.feature:8"},"result":{"status":"passed","duration":2479000000}},{"keyword":"Then ","name":"I expect the \"counter\" to be \"10\"","line":9,"match":{"location":".\\features\\counter_increases_scenerio_outline_example.feature:9"},"result":{"status":"passed","duration":29000000}}]}]},{"description":"","id":"counter","keyword":"Feature","line":1,"name":"Counter","uri":".\\features\\sub-features\\counter_increases.feature","elements":[{"keyword":"Scenario","type":"scenario","id":"counter;counter increases when the button is pressed","name":"Counter increases when the button is pressed","description":"","line":5,"tags":[{"line":4,"name":"@perf"}],"steps":[{"keyword":"Given ","name":"I expect the \"counter\" to be \"0\"","line":6,"match":{"location":".\\features\\sub-features\\counter_increases.feature:6"},"result":{"status":"passed","duration":38000000}},{"keyword":"When ","name":"I tap the \"increment\" button 20 times","line":7,"match":{"location":".\\features\\sub-features\\counter_increases.feature:7"},"result":{"status":"passed","duration":4905000000}},{"keyword":"Then ","name":"I expect the \"counter\" to be \"20\"","line":8,"match":{"location":".\\features\\sub-features\\counter_increases.feature:8"},"result":{"status":"passed","duration":24000000}}]}]},{"description":"","id":"drawer","keyword":"Feature","line":1,"name":"Drawer","uri":".\\features\\drawer.feature","elements":[{"keyword":"Scenario","type":"scenario","id":"drawer;should open the drawer","name":"should open the drawer","description":"","line":3,"steps":[{"keyword":"Given ","name":"I open the drawer","line":4,"match":{"location":".\\features\\drawer.feature:4"},"result":{"status":"passed","duration":1457000000}},{"keyword":"Given ","name":"I close the drawer","line":5,"match":{"location":".\\features\\drawer.feature:5"},"result":{"status":"passed","duration":419000000}}]}]},{"description":"","id":"counter","keyword":"Feature","line":2,"name":"Counter","uri":".\\features\\counter_increases_french.feature","elements":[{"keyword":"Scenario","type":"scenario","id":"counter;counter increases when the button is pressed","name":"Counter increases when the button is pressed","description":"","line":5,"steps":[{"keyword":"Etant ","name":"donné que I pick the colour red","line":6,"match":{"location":".\\features\\counter_increases_french.feature:6"},"result":{"status":"passed","duration":0}},{"keyword":"Et ","name":"I expect the \"counter\" to be \"0\"","line":7,"match":{"location":".\\features\\counter_increases_french.feature:7"},"result":{"status":"passed","duration":42000000}},{"keyword":"Quand ","name":"I tap the \"increment\" button 10 times","line":8,"match":{"location":".\\features\\counter_increases_french.feature:8"},"result":{"status":"passed","duration":2505000000}},{"keyword":"Alors ","name":"I expect the \"counter\" to be \"10\"","line":9,"match":{"location":".\\features\\counter_increases_french.feature:9"},"result":{"status":"passed","duration":24000000}}]}]},{"description":"","id":"startup","keyword":"Feature","line":1,"name":"Startup","uri":".\\features\\counter.feature","elements":[{"keyword":"Scenario","type":"scenario","id":"startup;should increment counter","name":"should increment counter","description":"","line":3,"steps":[{"keyword":"Given ","name":"I expect the \"counter\" to be \"0\"","line":4,"match":{"location":".\\features\\counter.feature:4"},"result":{"status":"passed","duration":38000000}},{"keyword":"When ","name":"I tap the \"increment\" button","line":5,"match":{"location":".\\features\\counter.feature:5"},"result":{"status":"passed","duration":317000000}},{"keyword":"And ","name":"I tap the \"increment\" button","line":6,"match":{"location":".\\features\\counter.feature:6"},"result":{"status":"passed","duration":260000000}},{"keyword":"Then ","name":"I expect the \"counter\" to be \"2\"","line":7,"match":{"location":".\\features\\counter.feature:7"},"result":{"status":"passed","duration":28000000}}]},{"keyword":"Scenario","type":"scenario","id":"startup;counter should reset when app is restarted","name":"counter should reset when app is restarted","description":"","line":9,"steps":[{"keyword":"Given ","name":"I expect the \"counter\" to be \"0\"","line":10,"match":{"location":".\\features\\counter.feature:10"},"result":{"status":"passed","duration":37000000}},{"keyword":"When ","name":"I tap the \"increment\" button","line":11,"match":{"location":".\\features\\counter.feature:11"},"result":{"status":"passed","duration":321000000}},{"keyword":"Then ","name":"I expect the \"counter\" to be \"1\"","line":12,"match":{"location":".\\features\\counter.feature:12"},"result":{"status":"passed","duration":33000000}},{"keyword":"When ","name":"I restart the app","line":13,"match":{"location":".\\features\\counter.feature:13"},"result":{"status":"passed","duration":3091000000}},{"keyword":"Then ","name":"I expect the \"counter\" to be \"0\"","line":14,"match":{"location":".\\features\\counter.feature:14"},"result":{"status":"passed","duration":35000000}}]}]},{"description":"","id":"custom parameter example","keyword":"Feature","line":1,"name":"Custom Parameter Example","uri":".\\features\\custom_parameter_example.feature","elements":[{"keyword":"Scenario","type":"scenario","id":"custom parameter example;custom colour parameter","name":"Custom colour parameter","description":"","line":4,"steps":[{"keyword":"Given ","name":"I pick the colour red","line":5,"match":{"location":".\\features\\custom_parameter_example.feature:5"},"result":{"status":"passed","duration":0}},{"keyword":"Given ","name":"I pick the colour green","line":6,"match":{"location":".\\features\\custom_parameter_example.feature:6"},"result":{"status":"passed","duration":0}},{"keyword":"Given ","name":"I pick the colour blue","line":7,"match":{"location":".\\features\\custom_parameter_example.feature:7"},"result":{"status":"passed","duration":0}}]}]},{"description":"","id":"navigation","keyword":"Feature","line":1,"name":"Navigation","uri":".\\features\\back_navigation.feature","elements":[{"keyword":"Scenario","type":"scenario","id":"navigation;user can navigate back from page two","name":"User can navigate back from page two","description":"","line":4,"tags":[{"line":3,"name":"@debug"}],"steps":[{"keyword":"Given ","name":"I expect the \"counter\" to be \"0\"","line":5,"match":{"location":".\\features\\back_navigation.feature:5"},"result":{"status":"passed","duration":40000000}},{"keyword":"When ","name":"I tap the \"increment\" button","line":6,"match":{"location":".\\features\\back_navigation.feature:6"},"result":{"status":"passed","duration":330000000}},{"keyword":"Then ","name":"I expect the \"counter\" to be \"1\"","line":7,"match":{"location":".\\features\\back_navigation.feature:7"},"result":{"status":"passed","duration":35000000}},{"keyword":"Given ","name":"I tap the label that contains the text \"Open page 2\"","line":9,"match":{"location":".\\features\\back_navigation.feature:9"},"result":{"status":"passed","duration":376000000}},{"keyword":"Then ","name":"I expect the text \"Contents of page 2\" to be present","line":10,"match":{"location":".\\features\\back_navigation.feature:10"},"result":{"status":"passed","duration":18000000}},{"keyword":"Given ","name":"I tap the back button","line":12,"match":{"location":".\\features\\back_navigation.feature:12"},"result":{"status":"passed","duration":358000000}},{"keyword":"Then ","name":"I expect the \"counter\" to be \"1\"","line":13,"match":{"location":".\\features\\back_navigation.feature:13"},"result":{"status":"passed","duration":26000000}}]}]},{"description":"","id":"counter","keyword":"Feature","line":1,"name":"Counter","uri":".\\features\\counter_increases.feature","elements":[{"keyword":"Scenario","type":"scenario","id":"counter;counter increases when the button is pressed","name":"Counter increases when the button is pressed","description":"","line":4,"steps":[{"keyword":"Given ","name":"I pick the colour red","line":5,"match":{"location":".\\features\\counter_increases.feature:5"},"result":{"status":"passed","duration":0}},{"keyword":"Given ","name":"I expect the \"counter\" to be \"0\"","line":6,"match":{"location":".\\features\\counter_increases.feature:6"},"result":{"status":"passed","duration":35000000}},{"keyword":"When ","name":"I tap the \"increment\" button 10 times","line":7,"match":{"location":".\\features\\counter_increases.feature:7"},"result":{"status":"passed","duration":2494000000}},{"keyword":"Then ","name":"I expect the \"counter\" to be \"10\"","line":8,"match":{"location":".\\features\\counter_increases.feature:8"},"result":{"status":"passed","duration":20000000}}]}]}] \ No newline at end of file +[{"description":"","id":"navigation","keyword":"Feature","line":1,"name":"Navigation","uri":".\\features\\back_navigation.feature","elements":[{"keyword":"Scenario","type":"scenario","id":"navigation;user can navigate back from page two","name":"User can navigate back from page two","description":"","line":4,"tags":[{"line":3,"name":"@debug"}],"steps":[{"keyword":"Given ","name":"I expect the \"counter\" to be \"0\"","line":5,"match":{"location":".\\features\\back_navigation.feature:5"},"result":{"status":"passed","duration":59000000}},{"keyword":"When ","name":"I tap the \"increment\" button","line":6,"match":{"location":".\\features\\back_navigation.feature:6"},"result":{"status":"passed","duration":393000000}},{"keyword":"Then ","name":"I expect the \"counter\" to be \"1\"","line":7,"match":{"location":".\\features\\back_navigation.feature:7"},"result":{"status":"passed","duration":30000000}},{"keyword":"Given ","name":"I tap the label that contains the text \"Open page 2\"","line":9,"match":{"location":".\\features\\back_navigation.feature:9"},"result":{"status":"passed","duration":443000000}},{"keyword":"Then ","name":"I expect the text \"Contents of page 2\" to be present","line":10,"match":{"location":".\\features\\back_navigation.feature:10"},"result":{"status":"passed","duration":18000000}},{"keyword":"Given ","name":"I tap the back button","line":12,"match":{"location":".\\features\\back_navigation.feature:12"},"result":{"status":"passed","duration":386000000}},{"keyword":"Then ","name":"I expect the \"counter\" to be \"1\"","line":13,"match":{"location":".\\features\\back_navigation.feature:13"},"result":{"status":"passed","duration":26000000}}]}]},{"description":"","id":"counter","keyword":"Feature","line":1,"name":"Counter","uri":".\\features\\sub-features\\counter_increases.feature"},{"description":"","id":"startup","keyword":"Feature","line":1,"name":"Startup","uri":".\\features\\counter.feature","elements":[{"keyword":"Scenario","type":"scenario","id":"startup;should increment counter","name":"should increment counter","description":"","line":4,"tags":[{"line":3,"name":"@debug"}],"steps":[{"keyword":"Given ","name":"I expect the \"longPressText\" to be \"Text that has not been long pressed\"","line":5,"match":{"location":".\\features\\counter.feature:5"},"result":{"status":"passed","duration":49000000}},{"keyword":"When ","name":"I long press the \"longPressText\" text","line":6,"match":{"location":".\\features\\counter.feature:6"},"result":{"status":"passed","duration":683000000}},{"keyword":"Then ","name":"I expect the \"longPressText\" to be \"Text has been long pressed!\"","line":7,"match":{"location":".\\features\\counter.feature:7"},"result":{"status":"passed","duration":31000000}}]}]},{"description":"","id":"custom parameter example","keyword":"Feature","line":1,"name":"Custom Parameter Example","uri":".\\features\\custom_parameter_example.feature"},{"description":"","id":"counter","keyword":"Feature","line":1,"name":"Counter","uri":".\\features\\counter_increases.feature"},{"description":"","id":"startup","keyword":"Feature","line":1,"name":"Startup","uri":".\\features\\app_restart.feature"},{"description":"","id":"interaction","keyword":"Feature","line":1,"name":"Interaction","uri":".\\features\\long_press_widget.feature"},{"description":"","id":"counter","keyword":"Feature","line":2,"name":"Counter","uri":".\\features\\counter_increases_french.feature"},{"description":"","id":"counter","keyword":"Feature","line":1,"name":"Counter","uri":".\\features\\counter_increases_scenerio_outline_example.feature"},{"description":"","id":"drawer","keyword":"Feature","line":1,"name":"Drawer","uri":".\\features\\drawer.feature"}] \ No newline at end of file diff --git a/lib/src/flutter/flutter_test_configuration.dart b/lib/src/flutter/flutter_test_configuration.dart index a15bf09..dadd7a2 100644 --- a/lib/src/flutter/flutter_test_configuration.dart +++ b/lib/src/flutter/flutter_test_configuration.dart @@ -27,6 +27,7 @@ import 'package:gherkin/gherkin.dart'; import 'package:glob/glob.dart'; import 'steps/then_expect_widget_to_be_present_step.dart'; +import 'steps/when_long_press_widget_step.dart'; class FlutterTestConfiguration extends TestConfiguration { String _observatoryDebuggerUri; @@ -194,6 +195,9 @@ class FlutterTestConfiguration extends TestConfiguration { WhenTapBackButtonWidget(), WhenTapWidget(), WhenTapWidgetWithoutScroll(), + WhenLongPressWidget(), + WhenLongPressWidgetWithoutScroll(), + WhenLongPressWidgetForDuration(), GivenOpenDrawer(), WhenPauseStep(), WhenFillFieldStep(), diff --git a/lib/src/flutter/steps/when_long_press_widget_step.dart b/lib/src/flutter/steps/when_long_press_widget_step.dart new file mode 100644 index 0000000..75ead4c --- /dev/null +++ b/lib/src/flutter/steps/when_long_press_widget_step.dart @@ -0,0 +1,70 @@ +import 'package:flutter_gherkin/src/flutter/flutter_world.dart'; +import 'package:flutter_gherkin/src/flutter/utils/driver_utils.dart'; +import 'package:flutter_driver/flutter_driver.dart'; +import 'package:gherkin/gherkin.dart'; + +/// Long presses the widget found with the given control key. +/// +/// Parameters: +/// 1 - {string} the control key +/// +/// Examples: +/// +/// `When I long press "controlKey" button` +/// `When I long press "controlKey" element` +/// `When I long press "controlKey" label` +/// `When I long press "controlKey" icon` +/// `When I long press "controlKey" field` +/// `When I long press "controlKey" text` +/// `When I long press "controlKey" widget` +StepDefinitionGeneric WhenLongPressWidget() { + return when1( + RegExp( + r'I long press the {string} (?:button|element|label|icon|field|text|widget)$'), + (key, context) async { + final finder = find.byValueKey(key); + + await context.world.driver.scrollIntoView( + finder, + ); + await FlutterDriverUtils.longPress( + context.world.driver, + finder, + ); + }, + ); +} + +StepDefinitionGeneric WhenLongPressWidgetWithoutScroll() { + return when1( + RegExp( + r'I long press the {string} (?:button|element|label|icon|field|text|widget) without scrolling it into view$'), + (key, context) async { + final finder = find.byValueKey(key); + + await FlutterDriverUtils.tap( + context.world.driver, + finder, + ); + }, + ); +} + +StepDefinitionGeneric WhenLongPressWidgetForDuration() { + return when2( + RegExp( + r'I long press the {string} (?:button|element|label|icon|field|text|widget) for {int} milliseconds$'), + (key, milliseconds, context) async { + final finder = find.byValueKey(key); + + await context.world.driver.scrollIntoView( + finder, + ); + await FlutterDriverUtils.longPress( + context.world.driver, + finder, + pressDuration: Duration(milliseconds: milliseconds), + ); + }, + ); +} diff --git a/lib/src/flutter/utils/driver_utils.dart b/lib/src/flutter/utils/driver_utils.dart index cfecfe7..4f23dd0 100644 --- a/lib/src/flutter/utils/driver_utils.dart +++ b/lib/src/flutter/utils/driver_utils.dart @@ -70,6 +70,16 @@ class FlutterDriverUtils { await FlutterDriverUtils.waitForFlutter(driver, timeout: timeout); } + static Future longPress( + FlutterDriver driver, + SerializableFinder finder, { + Duration pressDuration = const Duration(milliseconds: 500), + Duration timeout = const Duration(seconds: 30), + }) async { + await driver.scroll(finder, 0, 0, pressDuration, timeout: timeout); + await FlutterDriverUtils.waitForFlutter(driver, timeout: timeout); + } + /// Waits until the [condition] returns true /// Will raise a complete with a [TimeoutException] if the /// condition does not return true with the timeout period. diff --git a/pubspec.lock b/pubspec.lock index d91adbc..e900aa6 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -35,7 +35,7 @@ packages: name: async url: "https://pub.dartlang.org" source: hosted - version: "2.4.1" + version: "2.4.2" boolean_selector: dependency: transitive description: @@ -43,6 +43,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.0.0" + characters: + dependency: transitive + description: + name: characters + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.0" charcode: dependency: transitive description: @@ -57,13 +64,20 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "0.1.4" + clock: + dependency: transitive + description: + name: clock + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.1" collection: dependency: transitive description: name: collection url: "https://pub.dartlang.org" source: hosted - version: "1.14.12" + version: "1.14.13" convert: dependency: transitive description: @@ -77,14 +91,14 @@ packages: name: coverage url: "https://pub.dartlang.org" source: hosted - version: "0.13.11" + version: "0.14.0" crypto: dependency: transitive description: name: crypto url: "https://pub.dartlang.org" source: hosted - version: "2.1.4" + version: "2.1.5" csslib: dependency: transitive description: @@ -92,13 +106,20 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "0.16.2" + fake_async: + dependency: transitive + description: + name: fake_async + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.0" file: dependency: transitive description: name: file url: "https://pub.dartlang.org" source: hosted - version: "5.1.0" + version: "5.2.1" flutter: dependency: "direct main" description: flutter @@ -161,13 +182,6 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "3.1.4" - image: - dependency: transitive - description: - name: image - url: "https://pub.dartlang.org" - source: hosted - version: "2.1.12" intl: dependency: transitive description: @@ -195,7 +209,7 @@ packages: name: json_rpc_2 url: "https://pub.dartlang.org" source: hosted - version: "2.1.0" + version: "2.2.1" logging: dependency: transitive description: @@ -209,7 +223,7 @@ packages: name: matcher url: "https://pub.dartlang.org" source: hosted - version: "0.12.6" + version: "0.12.8" meta: dependency: "direct main" description: @@ -224,13 +238,6 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "0.9.6+3" - multi_server_socket: - dependency: transitive - description: - name: multi_server_socket - url: "https://pub.dartlang.org" - source: hosted - version: "1.0.2" node_interop: dependency: transitive description: @@ -265,7 +272,7 @@ packages: name: path url: "https://pub.dartlang.org" source: hosted - version: "1.6.4" + version: "1.7.0" pedantic: dependency: "direct dev" description: @@ -273,13 +280,6 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.9.0" - petitparser: - dependency: transitive - description: - name: petitparser - url: "https://pub.dartlang.org" - source: hosted - version: "2.4.0" platform: dependency: transitive description: @@ -300,7 +300,7 @@ packages: name: process url: "https://pub.dartlang.org" source: hosted - version: "3.0.12" + version: "3.0.13" pub_semver: dependency: transitive description: @@ -308,13 +308,6 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.4.4" - quiver: - dependency: transitive - description: - name: quiver - url: "https://pub.dartlang.org" - source: hosted - version: "2.1.3" shelf: dependency: transitive description: @@ -375,7 +368,7 @@ packages: name: stack_trace url: "https://pub.dartlang.org" source: hosted - version: "1.9.3" + version: "1.9.5" stream_channel: dependency: transitive description: @@ -410,28 +403,28 @@ packages: name: test url: "https://pub.dartlang.org" source: hosted - version: "1.14.4" + version: "1.15.2" test_api: dependency: transitive description: name: test_api url: "https://pub.dartlang.org" source: hosted - version: "0.2.15" + version: "0.2.17" test_core: dependency: transitive description: name: test_core url: "https://pub.dartlang.org" source: hosted - version: "0.3.4" + version: "0.3.10" typed_data: dependency: transitive description: name: typed_data url: "https://pub.dartlang.org" source: hosted - version: "1.1.6" + version: "1.2.0" vector_math: dependency: transitive description: @@ -481,13 +474,6 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "0.7.3" - xml: - dependency: transitive - description: - name: xml - url: "https://pub.dartlang.org" - source: hosted - version: "3.6.1" yaml: dependency: transitive description: @@ -496,5 +482,5 @@ packages: source: hosted version: "2.2.1" sdks: - dart: ">=2.7.0 <3.0.0" + dart: ">=2.9.0-14.0.dev <3.0.0" flutter: ">=1.13.0" diff --git a/pubspec.yaml b/pubspec.yaml index 5b23c9b..b4e107f 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: flutter_gherkin description: A Gherkin / Cucumber parser and test runner for Dart and Flutter -version: 1.1.8+6 +version: 1.1.8+7 homepage: https://github.com/jonsamwell/flutter_gherkin environment: diff --git a/test/flutter_configuration_test.dart b/test/flutter_configuration_test.dart index 6b1b87c..d979ab2 100644 --- a/test/flutter_configuration_test.dart +++ b/test/flutter_configuration_test.dart @@ -23,7 +23,7 @@ void main() { config.prepare(); expect(config.stepDefinitions, isNotNull); - expect(config.stepDefinitions.length, 20); + expect(config.stepDefinitions.length, 23); expect(config.customStepParameterDefinitions, isNotNull); expect(config.customStepParameterDefinitions.length, 2); }); @@ -36,7 +36,7 @@ void main() { config.prepare(); expect(config.stepDefinitions, isNotNull); - expect(config.stepDefinitions.length, 21); + expect(config.stepDefinitions.length, 24); expect(config.stepDefinitions.elementAt(0), (x) => x is MockStepDefinition); expect(config.customStepParameterDefinitions, isNotNull);