From 31bf38cef1e6c019631abf83ae2bdf7c0f250a01 Mon Sep 17 00:00:00 2001 From: Jon Samwell Date: Sat, 1 May 2021 13:56:17 +1000 Subject: [PATCH] feat(null-safety): first pass of null safety --- .flutter-plugins | 2 +- .flutter-plugins-dependencies | 2 +- CHANGELOG.md | 2 +- example_with_flutter_driver/lib/main.dart | 6 +- example_with_flutter_driver/pubspec.lock | 184 ++++----------- example_with_flutter_driver/pubspec.yaml | 7 +- .../test_driver/test_harness.dart | 27 +-- .../integration_response_data.json | 3 - .../gherkin/configuration.dart | 2 +- .../gherkin/steps/expect_todos_step.dart | 3 +- .../gherkin/steps/when_await_animation.dart | 2 +- .../gherkin/steps/when_step_has_timeout.dart | 2 +- .../gherkin/world/custom_world.dart | 6 +- .../integration_test/gherkin_suite_test.dart | 12 +- .../gherkin_suite_test.g.dart | 7 + .../lib/blocs/todo_bloc.dart | 2 +- example_with_integration_test/lib/main.dart | 6 +- .../lib/models/todo_model.dart | 10 +- .../lib/models/todo_model.g.dart | 60 ++--- .../lib/repositories/todo_repository.dart | 2 +- .../components/add_todo_component.dart | 6 +- .../lib/widgets/view_utils_mixin.dart | 8 +- .../lib/widgets/views/home_view.dart | 10 +- example_with_integration_test/pubspec.lock | 220 +++++++----------- example_with_integration_test/pubspec.yaml | 26 ++- lib/flutter_gherkin.dart | 16 +- ....dart => flutter_gherkin_with_driver.dart} | 15 +- .../flutter/adapters/app_driver_adapter.dart | 30 +-- .../flutter_driver_app_driver_adapter.dart | 49 ++-- .../widget_tester_app_driver_adapter.dart | 69 +++--- .../gherkin_full_test_suite_annotation.dart | 2 +- .../gherkin_suite_test_generator.dart | 42 ++-- .../flutter_driver_test_configuration.dart | 55 ++--- .../flutter_test_configuration.dart | 6 +- lib/src/flutter/hooks/app_runner_hook.dart | 19 +- .../reporters/flutter_driver_reporter.dart | 2 +- .../runners/flutter_run_process_handler.dart | 52 +++-- .../gherkin_integration_test_runner.dart | 76 +++--- .../steps/given_i_open_the_drawer_step.dart | 2 +- lib/src/flutter/steps/restart_app_step.dart | 2 +- .../steps/sibling_contains_text_step.dart | 2 +- .../steps/tap_text_within_widget_step.dart | 2 +- .../flutter/world/flutter_driver_world.dart | 13 +- .../world/flutter_widget_tester_world.dart | 2 +- lib/src/flutter/world/flutter_world.dart | 8 +- pubspec.lock | 191 ++++++--------- pubspec.yaml | 39 ++-- test/flutter_configuration_test.dart | 20 +- test/mocks/step_definition_mock.dart | 6 +- 49 files changed, 585 insertions(+), 752 deletions(-) delete mode 100644 example_with_integration_test/integration_response_data.json rename lib/{flutter_gherkin_integration_test.dart => flutter_gherkin_with_driver.dart} (68%) diff --git a/.flutter-plugins b/.flutter-plugins index 339e328..272ca46 100644 --- a/.flutter-plugins +++ b/.flutter-plugins @@ -1,2 +1,2 @@ # This is a generated file; do not edit or check into version control. -integration_test=C:\\Google\\flutter\\.pub-cache\\hosted\\pub.dartlang.org\\integration_test-1.0.2+2\\ +integration_test=C:\\Google\\flutter\\packages\\integration_test\\ diff --git a/.flutter-plugins-dependencies b/.flutter-plugins-dependencies index cb3112e..dfb7b26 100644 --- a/.flutter-plugins-dependencies +++ b/.flutter-plugins-dependencies @@ -1 +1 @@ -{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"integration_test","path":"C:\\\\Google\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\integration_test-1.0.2+2\\\\","dependencies":[]}],"android":[{"name":"integration_test","path":"C:\\\\Google\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\integration_test-1.0.2+2\\\\","dependencies":[]}],"macos":[],"linux":[],"windows":[],"web":[]},"dependencyGraph":[{"name":"integration_test","dependencies":[]}],"date_created":"2021-02-10 11:35:15.103743","version":"1.22.6"} \ No newline at end of file +{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"integration_test","path":"C:\\\\Google\\\\flutter\\\\packages\\\\integration_test\\\\","dependencies":[]}],"android":[{"name":"integration_test","path":"C:\\\\Google\\\\flutter\\\\packages\\\\integration_test\\\\","dependencies":[]}],"macos":[],"linux":[],"windows":[],"web":[]},"dependencyGraph":[{"name":"integration_test","dependencies":[]}],"date_created":"2021-05-01 13:05:07.936285","version":"2.0.5"} \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 4ea64c2..b10e0cf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,7 +27,7 @@ targets: # Allows the code generator to target files outside of the lib folder - integration_test/**.dart ``` -3. Add the following file (and folder) `example_with_integration_test\test_driver\integration_test_driver.dart`. This file is the entry point to run your tests. See `https://flutter.dev/docs/testing/integration-tests` for more information. +3. Add the following file (and folder) `\test_driver\integration_test_driver.dart`. This file is the entry point to run your tests. See `https://flutter.dev/docs/testing/integration-tests` for more information. ```dart import 'package:integration_test/integration_test_driver.dart' as integration_test_driver; diff --git a/example_with_flutter_driver/lib/main.dart b/example_with_flutter_driver/lib/main.dart index b770764..a351836 100644 --- a/example_with_flutter_driver/lib/main.dart +++ b/example_with_flutter_driver/lib/main.dart @@ -13,13 +13,13 @@ class MyApp extends StatelessWidget { primarySwatch: Colors.blue, visualDensity: VisualDensity.adaptivePlatformDensity, ), - home: MyHomePage(title: 'Flutter Demo Home Page'), + home: MyHomePage('Flutter Demo Home Page'), ); } } class MyHomePage extends StatefulWidget { - MyHomePage({Key key, this.title}) : super(key: key); + MyHomePage(this.title) : super(); final String title; @@ -60,8 +60,8 @@ class _MyHomePageState extends State { floatingActionButton: FloatingActionButton( onPressed: _incrementCounter, tooltip: 'Increment', - child: Icon(Icons.add), key: const Key('increment'), + child: Icon(Icons.add), ), ); } diff --git a/example_with_flutter_driver/pubspec.lock b/example_with_flutter_driver/pubspec.lock index f5d8b2c..13fa1aa 100644 --- a/example_with_flutter_driver/pubspec.lock +++ b/example_with_flutter_driver/pubspec.lock @@ -35,49 +35,28 @@ packages: name: async url: "https://pub.dartlang.org" source: hosted - version: "2.5.0-nullsafety.1" + version: "2.5.0" boolean_selector: dependency: transitive description: name: boolean_selector url: "https://pub.dartlang.org" source: hosted - version: "2.1.0-nullsafety.1" - build: - dependency: transitive - description: - name: build - url: "https://pub.dartlang.org" - source: hosted - version: "1.6.0" - build_config: - dependency: transitive - description: - name: build_config - url: "https://pub.dartlang.org" - source: hosted - version: "0.4.5" + version: "2.1.0" characters: dependency: transitive description: name: characters url: "https://pub.dartlang.org" source: hosted - version: "1.1.0-nullsafety.3" + version: "1.1.0" charcode: dependency: transitive description: name: charcode url: "https://pub.dartlang.org" source: hosted - version: "1.2.0-nullsafety.1" - checked_yaml: - dependency: transitive - description: - name: checked_yaml - url: "https://pub.dartlang.org" - source: hosted - version: "1.0.4" + version: "1.2.0" cli_util: dependency: transitive description: @@ -91,14 +70,14 @@ packages: name: clock url: "https://pub.dartlang.org" source: hosted - version: "1.1.0-nullsafety.1" + version: "1.1.0" collection: dependency: transitive description: name: collection url: "https://pub.dartlang.org" source: hosted - version: "1.15.0-nullsafety.3" + version: "1.15.0" convert: dependency: transitive description: @@ -112,7 +91,7 @@ packages: name: coverage url: "https://pub.dartlang.org" source: hosted - version: "0.14.2" + version: "0.15.2" crypto: dependency: transitive description: @@ -120,34 +99,20 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.1.5" - cupertino_icons: - dependency: "direct main" - description: - name: cupertino_icons - url: "https://pub.dartlang.org" - source: hosted - version: "1.0.0" - dart_style: - dependency: transitive - description: - name: dart_style - url: "https://pub.dartlang.org" - source: hosted - version: "1.3.10" fake_async: dependency: transitive description: name: fake_async url: "https://pub.dartlang.org" source: hosted - version: "1.2.0-nullsafety.1" + version: "1.2.0" file: dependency: transitive description: name: file url: "https://pub.dartlang.org" source: hosted - version: "6.0.0-nullsafety.2" + version: "6.0.0" flutter: dependency: "direct main" description: flutter @@ -178,12 +143,10 @@ packages: gherkin: dependency: transitive description: - path: "." - ref: "2eb30d84c3f7d7f6fa2ad5f93c8d9bfb160a3ced" - resolved-ref: "2eb30d84c3f7d7f6fa2ad5f93c8d9bfb160a3ced" - url: "https://github.com/jonsamwell/dart_gherkin.git" - source: git - version: "1.1.10" + name: gherkin + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.0" glob: dependency: transitive description: @@ -191,90 +154,62 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.2.0" - http: - dependency: transitive - description: - name: http - url: "https://pub.dartlang.org" - source: hosted - version: "0.12.2" http_multi_server: dependency: transitive description: name: http_multi_server url: "https://pub.dartlang.org" source: hosted - version: "2.2.0" + version: "3.0.1" http_parser: dependency: transitive description: name: http_parser url: "https://pub.dartlang.org" source: hosted - version: "3.1.4" - integration_test: - dependency: transitive - description: - name: integration_test - url: "https://pub.dartlang.org" - source: hosted - version: "1.0.1" + version: "4.0.0" io: dependency: transitive description: name: io url: "https://pub.dartlang.org" source: hosted - version: "0.3.4" + version: "1.0.0" js: dependency: transitive description: name: js url: "https://pub.dartlang.org" source: hosted - version: "0.6.3-nullsafety.2" - json_annotation: - dependency: transitive - description: - name: json_annotation - url: "https://pub.dartlang.org" - source: hosted - version: "3.1.1" - json_rpc_2: - dependency: transitive - description: - name: json_rpc_2 - url: "https://pub.dartlang.org" - source: hosted - version: "2.2.2" + version: "0.6.3" logging: dependency: transitive description: name: logging url: "https://pub.dartlang.org" source: hosted - version: "0.11.4" + version: "1.0.1" matcher: dependency: transitive description: name: matcher url: "https://pub.dartlang.org" source: hosted - version: "0.12.10-nullsafety.1" + version: "0.12.10" meta: dependency: transitive description: name: meta url: "https://pub.dartlang.org" source: hosted - version: "1.3.0-nullsafety.3" + version: "1.3.0" mime: dependency: transitive description: name: mime url: "https://pub.dartlang.org" source: hosted - version: "0.9.7" + version: "1.0.0" node_interop: dependency: transitive description: @@ -295,7 +230,7 @@ packages: name: node_preamble url: "https://pub.dartlang.org" source: hosted - version: "1.4.12" + version: "1.4.13" package_config: dependency: transitive description: @@ -309,35 +244,35 @@ packages: name: path url: "https://pub.dartlang.org" source: hosted - version: "1.8.0-nullsafety.1" + version: "1.8.0" pedantic: dependency: transitive description: name: pedantic url: "https://pub.dartlang.org" source: hosted - version: "1.10.0-nullsafety.2" + version: "1.11.0" platform: dependency: transitive description: name: platform url: "https://pub.dartlang.org" source: hosted - version: "3.0.0-nullsafety.2" + version: "3.0.0" pool: dependency: transitive description: name: pool url: "https://pub.dartlang.org" source: hosted - version: "1.5.0-nullsafety.2" + version: "1.5.0" process: dependency: transitive description: name: process url: "https://pub.dartlang.org" source: hosted - version: "4.0.0-nullsafety.2" + version: "4.0.0" pub_semver: dependency: transitive description: @@ -345,95 +280,81 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.4.4" - pubspec_parse: - dependency: transitive - description: - name: pubspec_parse - url: "https://pub.dartlang.org" - source: hosted - version: "0.1.7" shelf: dependency: transitive description: name: shelf url: "https://pub.dartlang.org" source: hosted - version: "0.7.9" + version: "1.1.1" shelf_packages_handler: dependency: transitive description: name: shelf_packages_handler url: "https://pub.dartlang.org" source: hosted - version: "2.0.0" + version: "2.0.1" shelf_static: dependency: transitive description: name: shelf_static url: "https://pub.dartlang.org" source: hosted - version: "0.2.9+1" + version: "0.2.9+2" shelf_web_socket: dependency: transitive description: name: shelf_web_socket url: "https://pub.dartlang.org" source: hosted - version: "0.2.3" + version: "0.2.4+1" sky_engine: dependency: transitive description: flutter source: sdk version: "0.0.99" - source_gen: - dependency: transitive - description: - name: source_gen - url: "https://pub.dartlang.org" - source: hosted - version: "0.9.10+1" source_map_stack_trace: dependency: transitive description: name: source_map_stack_trace url: "https://pub.dartlang.org" source: hosted - version: "2.1.0-nullsafety.3" + version: "2.1.0" source_maps: dependency: transitive description: name: source_maps url: "https://pub.dartlang.org" source: hosted - version: "0.10.10-nullsafety.2" + version: "0.10.10" source_span: dependency: transitive description: name: source_span url: "https://pub.dartlang.org" source: hosted - version: "1.8.0-nullsafety.2" + version: "1.8.0" stack_trace: dependency: transitive description: name: stack_trace url: "https://pub.dartlang.org" source: hosted - version: "1.10.0-nullsafety.1" + version: "1.10.0" stream_channel: dependency: transitive description: name: stream_channel url: "https://pub.dartlang.org" source: hosted - version: "2.1.0-nullsafety.1" + version: "2.1.0" string_scanner: dependency: transitive description: name: string_scanner url: "https://pub.dartlang.org" source: hosted - version: "1.1.0-nullsafety.1" + version: "1.1.0" sync_http: dependency: transitive description: @@ -447,42 +368,42 @@ packages: name: term_glyph url: "https://pub.dartlang.org" source: hosted - version: "1.2.0-nullsafety.1" + version: "1.2.0" test: - dependency: transitive + dependency: "direct overridden" description: name: test url: "https://pub.dartlang.org" source: hosted - version: "1.16.0-nullsafety.5" + version: "1.16.5" test_api: - dependency: transitive + dependency: "direct overridden" description: name: test_api url: "https://pub.dartlang.org" source: hosted - version: "0.2.19-nullsafety.2" + version: "0.3.0" test_core: dependency: transitive description: name: test_core url: "https://pub.dartlang.org" source: hosted - version: "0.3.12-nullsafety.5" + version: "0.3.15" typed_data: dependency: transitive description: name: typed_data url: "https://pub.dartlang.org" source: hosted - version: "1.3.0-nullsafety.3" + version: "1.3.0" vector_math: dependency: transitive description: name: vector_math url: "https://pub.dartlang.org" source: hosted - version: "2.1.0-nullsafety.3" + version: "2.1.0" vm_service: dependency: transitive description: @@ -490,13 +411,6 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "5.5.0" - vm_service_client: - dependency: transitive - description: - name: vm_service_client - url: "https://pub.dartlang.org" - source: hosted - version: "0.2.6+2" watcher: dependency: transitive description: @@ -510,7 +424,7 @@ packages: name: web_socket_channel url: "https://pub.dartlang.org" source: hosted - version: "1.1.0" + version: "1.2.0" webdriver: dependency: transitive description: @@ -524,7 +438,7 @@ packages: name: webkit_inspection_protocol url: "https://pub.dartlang.org" source: hosted - version: "0.7.4" + version: "1.0.0" yaml: dependency: transitive description: @@ -533,5 +447,5 @@ packages: source: hosted version: "2.2.1" sdks: - dart: ">=2.10.0 <2.11.0" - flutter: ">=1.17.0 <2.0.0" + dart: ">=2.12.3 <3.0.0" + flutter: ">=2.0.0" diff --git a/example_with_flutter_driver/pubspec.yaml b/example_with_flutter_driver/pubspec.yaml index 0851742..c265839 100644 --- a/example_with_flutter_driver/pubspec.yaml +++ b/example_with_flutter_driver/pubspec.yaml @@ -6,13 +6,15 @@ publish_to: 'none' version: 1.0.0+1 environment: - sdk: ">=2.7.0 <3.0.0" + sdk: '>=2.12.0 <3.0.0' dependencies: flutter: sdk: flutter - cupertino_icons: ^1.0.0 +dependency_overrides: + test: ^1.16.5 # gherkin still depends on 1.16.8 :-( + test_api: ^0.3.0 # flutter_test still depends on 0.2.19 :-( dev_dependencies: flutter_test: @@ -21,5 +23,4 @@ dev_dependencies: path: ../ flutter: - uses-material-design: true diff --git a/example_with_flutter_driver/test_driver/test_harness.dart b/example_with_flutter_driver/test_driver/test_harness.dart index 4b9a222..ac7cdf0 100644 --- a/example_with_flutter_driver/test_driver/test_harness.dart +++ b/example_with_flutter_driver/test_driver/test_harness.dart @@ -1,29 +1,24 @@ import 'dart:async'; -import 'package:flutter_gherkin/flutter_gherkin.dart'; +import 'package:flutter_gherkin/flutter_gherkin_with_driver.dart'; import 'package:gherkin/gherkin.dart'; Future main() { - final steps = []; - final config = FlutterDriverTestConfiguration.DEFAULT( - steps, + Iterable.empty(), featurePath: 'features/**.feature', targetAppPath: 'test_driver/app.dart', ) - ..hooks = [] - ..customStepParameterDefinitions = [] ..restartAppBetweenScenarios = true ..targetAppWorkingDirectory = '../' - ..targetAppPath = 'test_driver/app.dart' - // ..buildFlavor = "staging" // uncomment when using build flavor and check android/ios flavor setup see android file android\app\build.gradle - // ..targetDeviceId = "all" // uncomment to run tests on all connected devices or set specific device target id - // ..tagExpression = '@smoke and not @ignore' // uncomment to see an example of running scenarios based on tag expressions - // ..logFlutterProcessOutput = true // uncomment to see command invoked to start the flutter test app - // ..verboseFlutterProcessLogs = true // uncomment to see the verbose output from the Flutter process - // ..flutterBuildTimeout = Duration(minutes: 3) // uncomment to change the default period that flutter is expected to build and start the app within - // ..runningAppProtocolEndpointUri = - // 'http://127.0.0.1:51540/bkegoer6eH8=/' // already running app observatory / service protocol uri (with enableFlutterDriverExtension method invoked) to test against if you use this set `restartAppBetweenScenarios` to false - ..exitAfterTestRun = true; // set to false if debugging to exit cleanly + ..targetAppPath = 'test_driver/app.dart'; + // ..buildFlavor = "staging" // uncomment when using build flavor and check android/ios flavor setup see android file android\app\build.gradle + // ..targetDeviceId = "all" // uncomment to run tests on all connected devices or set specific device target id + // ..tagExpression = '@smoke and not @ignore' // uncomment to see an example of running scenarios based on tag expressions + // ..logFlutterProcessOutput = true // uncomment to see command invoked to start the flutter test app + // ..verboseFlutterProcessLogs = true // uncomment to see the verbose output from the Flutter process + // ..flutterBuildTimeout = Duration(minutes: 3) // uncomment to change the default period that flutter is expected to build and start the app within + // ..runningAppProtocolEndpointUri = + // 'http://127.0.0.1:51540/bkegoer6eH8=/' // already running app observatory / service protocol uri (with enableFlutterDriverExtension method invoked) to test against if you use this set `restartAppBetweenScenarios` to false return GherkinRunner().execute(config); } diff --git a/example_with_integration_test/integration_response_data.json b/example_with_integration_test/integration_response_data.json deleted file mode 100644 index e174586..0000000 --- a/example_with_integration_test/integration_response_data.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "gherkin_results": "{\"test\":\"moo1\"}" -} \ No newline at end of file diff --git a/example_with_integration_test/integration_test/gherkin/configuration.dart b/example_with_integration_test/integration_test/gherkin/configuration.dart index 722f129..e5b7bf7 100644 --- a/example_with_integration_test/integration_test/gherkin/configuration.dart +++ b/example_with_integration_test/integration_test/gherkin/configuration.dart @@ -1,7 +1,7 @@ import 'package:example_with_integration_test/main.dart'; import 'package:example_with_integration_test/services/external_application_manager.dart'; import 'package:flutter/widgets.dart'; -import 'package:flutter_gherkin/flutter_gherkin_integration_test.dart'; +import 'package:flutter_gherkin/flutter_gherkin.dart'; import 'package:flutter_simple_dependency_injection/injector.dart'; import 'package:gherkin/gherkin.dart'; diff --git a/example_with_integration_test/integration_test/gherkin/steps/expect_todos_step.dart b/example_with_integration_test/integration_test/gherkin/steps/expect_todos_step.dart index bdfdcb5..d2357a9 100644 --- a/example_with_integration_test/integration_test/gherkin/steps/expect_todos_step.dart +++ b/example_with_integration_test/integration_test/gherkin/steps/expect_todos_step.dart @@ -1,6 +1,5 @@ import 'package:flutter/material.dart'; import 'package:flutter_gherkin/flutter_gherkin.dart'; -import 'package:flutter_gherkin/flutter_gherkin_integration_test.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:gherkin/gherkin.dart'; @@ -8,7 +7,7 @@ final thenIExpectTheTodos = then1( 'I expect the todo list', (table, context) async { expect(context.configuration.timeout, isNotNull); - expect(context.configuration.timeout.inSeconds, 5); + expect(context.configuration.timeout!.inSeconds, 5); // get the parent list final listTileFinder = context.world.appDriver.findBy( diff --git a/example_with_integration_test/integration_test/gherkin/steps/when_await_animation.dart b/example_with_integration_test/integration_test/gherkin/steps/when_await_animation.dart index 58b4b10..95383e6 100644 --- a/example_with_integration_test/integration_test/gherkin/steps/when_await_animation.dart +++ b/example_with_integration_test/integration_test/gherkin/steps/when_await_animation.dart @@ -1,6 +1,6 @@ import 'package:flutter/widgets.dart'; +import 'package:flutter_gherkin/flutter_gherkin.dart'; import 'package:gherkin/gherkin.dart'; -import 'package:flutter_gherkin/flutter_gherkin_integration_test.dart'; import 'package:flutter_test/flutter_test.dart'; /// Shows are example of using the `WidgetTester` from the `World` context rather than diff --git a/example_with_integration_test/integration_test/gherkin/steps/when_step_has_timeout.dart b/example_with_integration_test/integration_test/gherkin/steps/when_step_has_timeout.dart index 14e540b..9153c92 100644 --- a/example_with_integration_test/integration_test/gherkin/steps/when_step_has_timeout.dart +++ b/example_with_integration_test/integration_test/gherkin/steps/when_step_has_timeout.dart @@ -1,5 +1,5 @@ +import 'package:flutter_gherkin/flutter_gherkin.dart'; import 'package:gherkin/gherkin.dart'; -import 'package:flutter_gherkin/flutter_gherkin_integration_test.dart'; import 'package:flutter_test/flutter_test.dart'; final whenStepHasTimeout = when( diff --git a/example_with_integration_test/integration_test/gherkin/world/custom_world.dart b/example_with_integration_test/integration_test/gherkin/world/custom_world.dart index dc5ee6c..21d46df 100644 --- a/example_with_integration_test/integration_test/gherkin/world/custom_world.dart +++ b/example_with_integration_test/integration_test/gherkin/world/custom_world.dart @@ -1,11 +1,11 @@ import 'package:example_with_integration_test/services/external_application_manager.dart'; -import 'package:flutter_gherkin/flutter_gherkin_integration_test.dart'; +import 'package:flutter_gherkin/flutter_gherkin.dart'; class CustomWorld extends FlutterWidgetTesterWorld { - ExternalApplicationManager _externalApplicationManager; + ExternalApplicationManager? _externalApplicationManager; ExternalApplicationManager get externalApplicationManager => - _externalApplicationManager; + _externalApplicationManager!; void setExternalApplicationManager(ExternalApplicationManager manager) { _externalApplicationManager = manager; diff --git a/example_with_integration_test/integration_test/gherkin_suite_test.dart b/example_with_integration_test/integration_test/gherkin_suite_test.dart index f5aebf6..87ffec7 100644 --- a/example_with_integration_test/integration_test/gherkin_suite_test.dart +++ b/example_with_integration_test/integration_test/gherkin_suite_test.dart @@ -1,14 +1,12 @@ -import 'package:flutter_gherkin/flutter_gherkin_integration_test.dart'; +import 'package:flutter_gherkin/flutter_gherkin.dart'; import 'package:gherkin/gherkin.dart'; -import 'gherkin/configuration.dart'; - part 'gherkin_suite_test.g.dart'; @GherkinTestSuite() void main() { - executeTestSuite( - gherkinTestConfiguration, - appInitializationFn, - ); + // executeTestSuite( + // gherkinTestConfiguration, + // appInitializationFn, + // ); } diff --git a/example_with_integration_test/integration_test/gherkin_suite_test.g.dart b/example_with_integration_test/integration_test/gherkin_suite_test.g.dart index 6dcf261..6703bc8 100644 --- a/example_with_integration_test/integration_test/gherkin_suite_test.g.dart +++ b/example_with_integration_test/integration_test/gherkin_suite_test.g.dart @@ -109,6 +109,13 @@ class _CustomGherkinIntegrationTestRunner extends GherkinIntegrationTestRunner { null, dependencies, ); + + await runStep( + 'When I test the default step timeout is not applied to step with custom timeout', + [], + null, + dependencies, + ); }, ); }, diff --git a/example_with_integration_test/lib/blocs/todo_bloc.dart b/example_with_integration_test/lib/blocs/todo_bloc.dart index 506c1b8..59fe042 100644 --- a/example_with_integration_test/lib/blocs/todo_bloc.dart +++ b/example_with_integration_test/lib/blocs/todo_bloc.dart @@ -7,7 +7,7 @@ class TodoBloc { final Subject _dataRefresher = BehaviorSubject.seeded(null); final Subject _newModel = ReplaySubject(maxSize: 1); final TodoRepository _repository; - Stream> _todos; + late final Stream> _todos; Stream> get todos => _todos; Stream get newModel => _newModel; diff --git a/example_with_integration_test/lib/main.dart b/example_with_integration_test/lib/main.dart index fcea997..60dce68 100644 --- a/example_with_integration_test/lib/main.dart +++ b/example_with_integration_test/lib/main.dart @@ -14,11 +14,11 @@ void main() { } class TodoApp extends StatelessWidget { - final ExternalApplicationManager externalApplicationManager; + final ExternalApplicationManager? externalApplicationManager; final Injector injector; TodoApp({ - this.injector, + required this.injector, this.externalApplicationManager, }) : super() { ModuleContainer().initialise(injector); @@ -40,7 +40,7 @@ class TodoApp extends StatelessWidget { return externalApplicationManager == null ? app : StreamBuilder( - stream: externalApplicationManager.applicationReset, + stream: externalApplicationManager!.applicationReset, builder: (ctx, _) => app, ); } diff --git a/example_with_integration_test/lib/models/todo_model.dart b/example_with_integration_test/lib/models/todo_model.dart index c1c8006..6a762e1 100644 --- a/example_with_integration_test/lib/models/todo_model.dart +++ b/example_with_integration_test/lib/models/todo_model.dart @@ -5,11 +5,11 @@ part 'todo_model.g.dart'; @JsonSerializable() class Todo { - String id; - DateTime created; - DateTime updated; - String action; - TodoStatus status; + late String id; + late DateTime created; + late DateTime updated; + late String action; + late TodoStatus status; Todo(); diff --git a/example_with_integration_test/lib/models/todo_model.g.dart b/example_with_integration_test/lib/models/todo_model.g.dart index 888253f..fc28ff4 100644 --- a/example_with_integration_test/lib/models/todo_model.g.dart +++ b/example_with_integration_test/lib/models/todo_model.g.dart @@ -9,54 +9,44 @@ part of 'todo_model.dart'; Todo _$TodoFromJson(Map json) { return Todo() ..id = json['id'] as String - ..created = json['created'] == null - ? null - : DateTime.parse(json['created'] as String) - ..updated = json['updated'] == null - ? null - : DateTime.parse(json['updated'] as String) + ..created = DateTime.parse(json['created'] as String) + ..updated = DateTime.parse(json['updated'] as String) ..action = json['action'] as String - ..status = _$enumDecodeNullable(_$TodoStatusEnumMap, json['status']); + ..status = _$enumDecode(_$TodoStatusEnumMap, json['status']); } Map _$TodoToJson(Todo instance) => { 'id': instance.id, - 'created': instance.created?.toIso8601String(), - 'updated': instance.updated?.toIso8601String(), + 'created': instance.created.toIso8601String(), + 'updated': instance.updated.toIso8601String(), 'action': instance.action, 'status': _$TodoStatusEnumMap[instance.status], }; -T _$enumDecode( - Map enumValues, - dynamic source, { - T unknownValue, +K _$enumDecode( + Map enumValues, + Object? source, { + K? unknownValue, }) { if (source == null) { - throw ArgumentError('A value must be provided. Supported values: ' - '${enumValues.values.join(', ')}'); + throw ArgumentError( + 'A value must be provided. Supported values: ' + '${enumValues.values.join(', ')}', + ); } - final value = enumValues.entries - .singleWhere((e) => e.value == source, orElse: () => null) - ?.key; - - if (value == null && unknownValue == null) { - throw ArgumentError('`$source` is not one of the supported values: ' - '${enumValues.values.join(', ')}'); - } - return value ?? unknownValue; -} - -T _$enumDecodeNullable( - Map enumValues, - dynamic source, { - T unknownValue, -}) { - if (source == null) { - return null; - } - return _$enumDecode(enumValues, source, unknownValue: unknownValue); + return enumValues.entries.singleWhere( + (e) => e.value == source, + orElse: () { + if (unknownValue == null) { + throw ArgumentError( + '`$source` is not one of the supported values: ' + '${enumValues.values.join(', ')}', + ); + } + return MapEntry(unknownValue, enumValues.values.first); + }, + ).key; } const _$TodoStatusEnumMap = { diff --git a/example_with_integration_test/lib/repositories/todo_repository.dart b/example_with_integration_test/lib/repositories/todo_repository.dart index f56069e..f78e60c 100644 --- a/example_with_integration_test/lib/repositories/todo_repository.dart +++ b/example_with_integration_test/lib/repositories/todo_repository.dart @@ -15,7 +15,7 @@ class TodoRepository { ReplaySubject(maxSize: 1); TodoRepository() { - StreamSubscription sub; + StreamSubscription? sub; sub = SharedPreferences.getInstance().asStream().listen( (sp) { _storage.add(sp); diff --git a/example_with_integration_test/lib/widgets/components/add_todo_component.dart b/example_with_integration_test/lib/widgets/components/add_todo_component.dart index 51c4190..c3e4605 100644 --- a/example_with_integration_test/lib/widgets/components/add_todo_component.dart +++ b/example_with_integration_test/lib/widgets/components/add_todo_component.dart @@ -9,8 +9,8 @@ class AddTodoComponent extends StatefulWidget { final Stream todo; const AddTodoComponent({ - @required this.todo, - @required this.onAdded, + required this.todo, + required this.onAdded, }) : super(); @override @@ -63,12 +63,12 @@ class _AddTodoComponentState extends State ), ), FloatingActionButton( - child: Icon(Icons.add), key: const Key('add'), onPressed: onAdd, backgroundColor: Theme.of(context).primaryColor, focusElevation: 3, materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, + child: const Icon(Icons.add), ), ], ), diff --git a/example_with_integration_test/lib/widgets/view_utils_mixin.dart b/example_with_integration_test/lib/widgets/view_utils_mixin.dart index 45e1c93..e1437e1 100644 --- a/example_with_integration_test/lib/widgets/view_utils_mixin.dart +++ b/example_with_integration_test/lib/widgets/view_utils_mixin.dart @@ -7,11 +7,11 @@ class ViewUtilsMixin { @protected StreamSubscription subscribeOnce( Stream stream, { - void Function(T data) onData, - void Function(Object, StackTrace) onError, - void Function() onDone, + void Function(T data)? onData, + void Function(Object, StackTrace)? onError, + void Function()? onDone, }) { - StreamSubscription sub; + StreamSubscription? sub; var hasErrored = false; return sub = stream.listen( (data) { diff --git a/example_with_integration_test/lib/widgets/views/home_view.dart b/example_with_integration_test/lib/widgets/views/home_view.dart index a43cf00..c394063 100644 --- a/example_with_integration_test/lib/widgets/views/home_view.dart +++ b/example_with_integration_test/lib/widgets/views/home_view.dart @@ -11,8 +11,8 @@ class HomeView extends StatefulWidget { final TodoBloc Function() blocFactory; const HomeView({ - @required this.blocFactory, - Key key, + required this.blocFactory, + Key? key, }) : super(key: key); @override @@ -56,7 +56,7 @@ class _HomeViewState extends State with ViewUtilsMixin { stream: bloc.todos, builder: (_, snapshot) { if (snapshot.hasData) { - final data = snapshot.data; + final data = snapshot.data!; if (data.isEmpty) { return Center( child: Column( @@ -108,7 +108,7 @@ class _HomeViewState extends State with ViewUtilsMixin { subscribeOnce( bloc.remove(todo), onDone: () { - Scaffold.of(context).showSnackBar( + ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text('Todo deleted'), ), @@ -121,7 +121,7 @@ class _HomeViewState extends State with ViewUtilsMixin { todo.action, style: Theme.of(context) .textTheme - .bodyText1 + .bodyText1! .copyWith( decoration: todo.status == TodoStatus.complete diff --git a/example_with_integration_test/pubspec.lock b/example_with_integration_test/pubspec.lock index 377531e..87b4d1f 100644 --- a/example_with_integration_test/pubspec.lock +++ b/example_with_integration_test/pubspec.lock @@ -7,14 +7,14 @@ packages: name: _fe_analyzer_shared url: "https://pub.dartlang.org" source: hosted - version: "12.0.0" + version: "21.0.0" analyzer: dependency: transitive description: name: analyzer url: "https://pub.dartlang.org" source: hosted - version: "0.40.6" + version: "1.5.0" archive: dependency: transitive description: @@ -35,56 +35,56 @@ packages: name: async url: "https://pub.dartlang.org" source: hosted - version: "2.5.0-nullsafety.1" + version: "2.5.0" boolean_selector: dependency: transitive description: name: boolean_selector url: "https://pub.dartlang.org" source: hosted - version: "2.1.0-nullsafety.1" + version: "2.1.0" build: dependency: transitive description: name: build url: "https://pub.dartlang.org" source: hosted - version: "1.6.0" + version: "2.0.1" build_config: dependency: transitive description: name: build_config url: "https://pub.dartlang.org" source: hosted - version: "0.4.5" + version: "0.4.7" build_daemon: dependency: transitive description: name: build_daemon url: "https://pub.dartlang.org" source: hosted - version: "2.1.4" + version: "2.1.10" build_resolvers: dependency: transitive description: name: build_resolvers url: "https://pub.dartlang.org" source: hosted - version: "1.5.1" + version: "2.0.0" build_runner: dependency: "direct dev" description: name: build_runner url: "https://pub.dartlang.org" source: hosted - version: "1.10.11" + version: "1.12.2" build_runner_core: dependency: transitive description: name: build_runner_core url: "https://pub.dartlang.org" source: hosted - version: "6.1.5" + version: "6.1.12" built_collection: dependency: transitive description: @@ -105,35 +105,35 @@ packages: name: characters url: "https://pub.dartlang.org" source: hosted - version: "1.1.0-nullsafety.3" + version: "1.1.0" charcode: dependency: transitive description: name: charcode url: "https://pub.dartlang.org" source: hosted - version: "1.2.0-nullsafety.1" + version: "1.2.0" checked_yaml: dependency: transitive description: name: checked_yaml url: "https://pub.dartlang.org" source: hosted - version: "1.0.4" + version: "2.0.1" cli_util: dependency: transitive description: name: cli_util url: "https://pub.dartlang.org" source: hosted - version: "0.2.0" + version: "0.3.0" clock: dependency: transitive description: name: clock url: "https://pub.dartlang.org" source: hosted - version: "1.1.0-nullsafety.1" + version: "1.1.0" code_builder: dependency: transitive description: @@ -147,63 +147,56 @@ packages: name: collection url: "https://pub.dartlang.org" source: hosted - version: "1.15.0-nullsafety.3" + version: "1.15.0" convert: - dependency: transitive + dependency: "direct overridden" description: name: convert url: "https://pub.dartlang.org" source: hosted - version: "2.1.1" + version: "3.0.0" coverage: dependency: transitive description: name: coverage url: "https://pub.dartlang.org" source: hosted - version: "0.14.2" + version: "0.15.2" crypto: - dependency: transitive + dependency: "direct overridden" description: name: crypto url: "https://pub.dartlang.org" source: hosted - version: "2.1.5" - cupertino_icons: - dependency: "direct main" - description: - name: cupertino_icons - url: "https://pub.dartlang.org" - source: hosted - version: "1.0.0" + version: "3.0.1" dart_style: dependency: transitive description: name: dart_style url: "https://pub.dartlang.org" source: hosted - version: "1.3.10" + version: "2.0.1" fake_async: dependency: transitive description: name: fake_async url: "https://pub.dartlang.org" source: hosted - version: "1.2.0-nullsafety.1" + version: "1.2.0" ffi: dependency: transitive description: name: ffi url: "https://pub.dartlang.org" source: hosted - version: "0.1.3" + version: "1.0.0" file: dependency: transitive description: name: file url: "https://pub.dartlang.org" source: hosted - version: "6.0.0-nullsafety.2" + version: "6.0.0" fixnum: dependency: transitive description: @@ -234,7 +227,7 @@ packages: name: flutter_simple_dependency_injection url: "https://pub.dartlang.org" source: hosted - version: "1.0.4" + version: "2.0.0" flutter_test: dependency: "direct dev" description: flutter @@ -253,33 +246,24 @@ packages: gherkin: dependency: transitive description: - path: "." - ref: f0b3f955191b53a78075ed2c9387ea8bee12f111 - resolved-ref: f0b3f955191b53a78075ed2c9387ea8bee12f111 - url: "https://github.com/jonsamwell/dart_gherkin.git" - source: git - version: "1.1.10" + name: gherkin + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.0" glob: dependency: transitive description: name: glob url: "https://pub.dartlang.org" source: hosted - version: "1.2.0" + version: "2.0.1" graphs: dependency: transitive description: name: graphs url: "https://pub.dartlang.org" source: hosted - version: "0.2.0" - http: - dependency: transitive - description: - name: http - url: "https://pub.dartlang.org" - source: hosted - version: "0.12.2" + version: "1.0.0" http_multi_server: dependency: transitive description: @@ -296,11 +280,9 @@ packages: version: "3.1.4" integration_test: dependency: "direct dev" - description: - name: integration_test - url: "https://pub.dartlang.org" - source: hosted - version: "1.0.1" + description: flutter + source: sdk + version: "0.9.2+2" io: dependency: transitive description: @@ -314,49 +296,42 @@ packages: name: js url: "https://pub.dartlang.org" source: hosted - version: "0.6.3-nullsafety.2" + version: "0.6.3" json_annotation: dependency: "direct main" description: name: json_annotation url: "https://pub.dartlang.org" source: hosted - version: "3.1.1" - json_rpc_2: - dependency: transitive - description: - name: json_rpc_2 - url: "https://pub.dartlang.org" - source: hosted - version: "2.2.2" + version: "4.0.1" json_serializable: dependency: "direct main" description: name: json_serializable url: "https://pub.dartlang.org" source: hosted - version: "3.5.1" + version: "4.1.1" logging: dependency: transitive description: name: logging url: "https://pub.dartlang.org" source: hosted - version: "0.11.4" + version: "1.0.1" matcher: dependency: transitive description: name: matcher url: "https://pub.dartlang.org" source: hosted - version: "0.12.10-nullsafety.1" + version: "0.12.10" meta: dependency: transitive description: name: meta url: "https://pub.dartlang.org" source: hosted - version: "1.3.0-nullsafety.3" + version: "1.3.0" mime: dependency: transitive description: @@ -364,111 +339,97 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "0.9.7" - node_interop: - dependency: transitive - description: - name: node_interop - url: "https://pub.dartlang.org" - source: hosted - version: "1.2.1" - node_io: - dependency: transitive - description: - name: node_io - url: "https://pub.dartlang.org" - source: hosted - version: "1.1.1" node_preamble: dependency: transitive description: name: node_preamble url: "https://pub.dartlang.org" source: hosted - version: "1.4.12" + version: "1.4.13" package_config: dependency: transitive description: name: package_config url: "https://pub.dartlang.org" source: hosted - version: "1.9.3" + version: "2.0.0" path: dependency: transitive description: name: path url: "https://pub.dartlang.org" source: hosted - version: "1.8.0-nullsafety.1" + version: "1.8.0" path_provider_linux: dependency: transitive description: name: path_provider_linux url: "https://pub.dartlang.org" source: hosted - version: "0.0.1+2" + version: "2.0.0" path_provider_platform_interface: dependency: transitive description: name: path_provider_platform_interface url: "https://pub.dartlang.org" source: hosted - version: "1.0.4" + version: "2.0.1" path_provider_windows: dependency: transitive description: name: path_provider_windows url: "https://pub.dartlang.org" source: hosted - version: "0.0.4+3" + version: "2.0.1" pedantic: dependency: transitive description: name: pedantic url: "https://pub.dartlang.org" source: hosted - version: "1.10.0-nullsafety.2" + version: "1.11.0" platform: dependency: transitive description: name: platform url: "https://pub.dartlang.org" source: hosted - version: "3.0.0-nullsafety.2" + version: "3.0.0" plugin_platform_interface: dependency: transitive description: name: plugin_platform_interface url: "https://pub.dartlang.org" source: hosted - version: "1.0.3" + version: "2.0.0" pool: dependency: transitive description: name: pool url: "https://pub.dartlang.org" source: hosted - version: "1.5.0-nullsafety.2" + version: "1.5.0" process: dependency: transitive description: name: process url: "https://pub.dartlang.org" source: hosted - version: "4.0.0-nullsafety.2" + version: "4.0.0" pub_semver: dependency: transitive description: name: pub_semver url: "https://pub.dartlang.org" source: hosted - version: "1.4.4" + version: "2.0.0" pubspec_parse: dependency: transitive description: name: pubspec_parse url: "https://pub.dartlang.org" source: hosted - version: "0.1.7" + version: "1.0.0" quiver: dependency: transitive description: @@ -482,49 +443,49 @@ packages: name: rxdart url: "https://pub.dartlang.org" source: hosted - version: "0.25.0" + version: "0.26.0" shared_preferences: dependency: "direct main" description: name: shared_preferences url: "https://pub.dartlang.org" source: hosted - version: "0.5.12+4" + version: "2.0.5" shared_preferences_linux: dependency: transitive description: name: shared_preferences_linux url: "https://pub.dartlang.org" source: hosted - version: "0.0.2+4" + version: "2.0.0" shared_preferences_macos: dependency: transitive description: name: shared_preferences_macos url: "https://pub.dartlang.org" source: hosted - version: "0.0.1+11" + version: "2.0.0" shared_preferences_platform_interface: dependency: transitive description: name: shared_preferences_platform_interface url: "https://pub.dartlang.org" source: hosted - version: "1.0.4" + version: "2.0.0" shared_preferences_web: dependency: transitive description: name: shared_preferences_web url: "https://pub.dartlang.org" source: hosted - version: "0.1.2+7" + version: "2.0.0" shared_preferences_windows: dependency: transitive description: name: shared_preferences_windows url: "https://pub.dartlang.org" source: hosted - version: "0.0.1+3" + version: "2.0.0" shelf: dependency: transitive description: @@ -538,14 +499,14 @@ packages: name: shelf_packages_handler url: "https://pub.dartlang.org" source: hosted - version: "2.0.0" + version: "2.0.1" shelf_static: dependency: transitive description: name: shelf_static url: "https://pub.dartlang.org" source: hosted - version: "0.2.9+1" + version: "0.2.9+2" shelf_web_socket: dependency: transitive description: @@ -564,56 +525,56 @@ packages: name: source_gen url: "https://pub.dartlang.org" source: hosted - version: "0.9.10+1" + version: "1.0.0" source_map_stack_trace: dependency: transitive description: name: source_map_stack_trace url: "https://pub.dartlang.org" source: hosted - version: "2.1.0-nullsafety.3" + version: "2.1.0" source_maps: dependency: transitive description: name: source_maps url: "https://pub.dartlang.org" source: hosted - version: "0.10.10-nullsafety.2" + version: "0.10.10" source_span: dependency: transitive description: name: source_span url: "https://pub.dartlang.org" source: hosted - version: "1.8.0-nullsafety.2" + version: "1.8.0" stack_trace: dependency: transitive description: name: stack_trace url: "https://pub.dartlang.org" source: hosted - version: "1.10.0-nullsafety.1" + version: "1.10.0" stream_channel: dependency: transitive description: name: stream_channel url: "https://pub.dartlang.org" source: hosted - version: "2.1.0-nullsafety.1" + version: "2.1.0" stream_transform: dependency: transitive description: name: stream_transform url: "https://pub.dartlang.org" source: hosted - version: "1.2.0" + version: "2.0.0" string_scanner: dependency: transitive description: name: string_scanner url: "https://pub.dartlang.org" source: hosted - version: "1.1.0-nullsafety.1" + version: "1.1.0" sync_http: dependency: transitive description: @@ -627,28 +588,28 @@ packages: name: term_glyph url: "https://pub.dartlang.org" source: hosted - version: "1.2.0-nullsafety.1" + version: "1.2.0" test: - dependency: transitive + dependency: "direct overridden" description: name: test url: "https://pub.dartlang.org" source: hosted - version: "1.16.0-nullsafety.5" + version: "1.16.5" test_api: - dependency: transitive + dependency: "direct overridden" description: name: test_api url: "https://pub.dartlang.org" source: hosted - version: "0.2.19-nullsafety.2" + version: "0.3.0" test_core: dependency: transitive description: name: test_core url: "https://pub.dartlang.org" source: hosted - version: "0.3.12-nullsafety.5" + version: "0.3.15" timing: dependency: transitive description: @@ -662,21 +623,21 @@ packages: name: typed_data url: "https://pub.dartlang.org" source: hosted - version: "1.3.0-nullsafety.3" + version: "1.3.0" uuid: dependency: "direct main" description: name: uuid url: "https://pub.dartlang.org" source: hosted - version: "2.2.2" + version: "3.0.4" vector_math: dependency: transitive description: name: vector_math url: "https://pub.dartlang.org" source: hosted - version: "2.1.0-nullsafety.3" + version: "2.1.0" vm_service: dependency: transitive description: @@ -684,20 +645,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "5.5.0" - vm_service_client: - dependency: transitive - description: - name: vm_service_client - url: "https://pub.dartlang.org" - source: hosted - version: "0.2.6+2" watcher: dependency: transitive description: name: watcher url: "https://pub.dartlang.org" source: hosted - version: "0.9.7+15" + version: "1.0.0" web_socket_channel: dependency: transitive description: @@ -718,28 +672,28 @@ packages: name: webkit_inspection_protocol url: "https://pub.dartlang.org" source: hosted - version: "0.7.4" + version: "1.0.0" win32: dependency: transitive description: name: win32 url: "https://pub.dartlang.org" source: hosted - version: "1.7.4" + version: "2.0.5" xdg_directories: dependency: transitive description: name: xdg_directories url: "https://pub.dartlang.org" source: hosted - version: "0.1.2" + version: "0.2.0" yaml: dependency: transitive description: name: yaml url: "https://pub.dartlang.org" source: hosted - version: "2.2.1" + version: "3.1.0" sdks: - dart: ">=2.10.0 <2.11.0" - flutter: ">=1.17.0 <2.0.0" + dart: ">=2.12.3 <3.0.0" + flutter: ">=2.0.0" diff --git a/example_with_integration_test/pubspec.yaml b/example_with_integration_test/pubspec.yaml index aea88f9..767c5e1 100644 --- a/example_with_integration_test/pubspec.yaml +++ b/example_with_integration_test/pubspec.yaml @@ -6,26 +6,30 @@ publish_to: 'none' version: 1.0.0+1 environment: - sdk: ">=2.7.0 <3.0.0" + sdk: '>=2.12.0 <3.0.0' dependencies: flutter: sdk: flutter + json_serializable: ^4.1.1 + json_annotation: ^4.0.1 + rxdart: ^0.26.0 + shared_preferences: ^2.0.5 + uuid: ^3.0.4 + flutter_simple_dependency_injection: ^2.0.0 - cupertino_icons: ^1.0.0 - - json_serializable: ^3.5.1 - json_annotation: ^3.1.1 - rxdart: ^0.25.0 - shared_preferences: ^0.5.12+4 - uuid: ^2.2.2 - flutter_simple_dependency_injection: ^1.0.4 +dependency_overrides: + crypto: ^3.0.0 # flutter_driver still depends on 2.1.5 :-( + convert: ^3.0.0 # flutter_driver still depends on >=2.0.0 :-( + test: ^1.16.5 # gherkin still depends on 1.16.8 :-( + test_api: ^0.3.0 # flutter_test still depends on 0.2.19 :-( dev_dependencies: flutter_test: sdk: flutter - integration_test: ^1.0.0 - build_runner: ^1.10.11 + integration_test: + sdk: flutter + build_runner: flutter_gherkin: path: ../ diff --git a/lib/flutter_gherkin.dart b/lib/flutter_gherkin.dart index 378e379..1ee9704 100644 --- a/lib/flutter_gherkin.dart +++ b/lib/flutter_gherkin.dart @@ -1,5 +1,10 @@ library flutter_gherkin; +/// *************************************** +/// Library export for use with integration_test with include reference to flutter_test which reference dart:ui +/// which are not allowed when running tests with flutter_driver hence this separate library declaration file +/// *************************************** + // Flutter specific implementations export 'src/flutter/configuration/build_mode.dart'; export 'src/flutter/world/flutter_world.dart'; @@ -28,11 +33,8 @@ export 'src/flutter/steps/wait_until_type_exists_step.dart'; // Hooks export 'src/flutter/hooks/attach_screenshot_on_failed_step_hook.dart'; -// Flutter WidgetTester specific implementations +// integration_test specific exports +export 'src/flutter/adapters/widget_tester_app_driver_adapter.dart'; +export 'src/flutter/code_generation/annotations/gherkin_full_test_suite_annotation.dart'; +export 'src/flutter/runners/gherkin_integration_test_runner.dart'; export 'src/flutter/world/flutter_widget_tester_world.dart'; - -// Flutter driver specific implementations -export 'src/flutter/configuration/flutter_driver_test_configuration.dart'; -export 'src/flutter/adapters/flutter_driver_app_driver_adapter.dart'; -export 'src/flutter/reporters/flutter_driver_reporter.dart'; -export 'src/flutter/world/flutter_driver_world.dart'; diff --git a/lib/flutter_gherkin_integration_test.dart b/lib/flutter_gherkin_with_driver.dart similarity index 68% rename from lib/flutter_gherkin_integration_test.dart rename to lib/flutter_gherkin_with_driver.dart index 1ee9704..f7fc51c 100644 --- a/lib/flutter_gherkin_integration_test.dart +++ b/lib/flutter_gherkin_with_driver.dart @@ -1,10 +1,5 @@ library flutter_gherkin; -/// *************************************** -/// Library export for use with integration_test with include reference to flutter_test which reference dart:ui -/// which are not allowed when running tests with flutter_driver hence this separate library declaration file -/// *************************************** - // Flutter specific implementations export 'src/flutter/configuration/build_mode.dart'; export 'src/flutter/world/flutter_world.dart'; @@ -33,8 +28,8 @@ export 'src/flutter/steps/wait_until_type_exists_step.dart'; // Hooks export 'src/flutter/hooks/attach_screenshot_on_failed_step_hook.dart'; -// integration_test specific exports -export 'src/flutter/adapters/widget_tester_app_driver_adapter.dart'; -export 'src/flutter/code_generation/annotations/gherkin_full_test_suite_annotation.dart'; -export 'src/flutter/runners/gherkin_integration_test_runner.dart'; -export 'src/flutter/world/flutter_widget_tester_world.dart'; +// Flutter driver specific implementations +export 'src/flutter/configuration/flutter_driver_test_configuration.dart'; +export 'src/flutter/adapters/flutter_driver_app_driver_adapter.dart'; +export 'src/flutter/reporters/flutter_driver_reporter.dart'; +export 'src/flutter/world/flutter_driver_world.dart'; diff --git a/lib/src/flutter/adapters/app_driver_adapter.dart b/lib/src/flutter/adapters/app_driver_adapter.dart index 4b513c5..9f79f5e 100644 --- a/lib/src/flutter/adapters/app_driver_adapter.dart +++ b/lib/src/flutter/adapters/app_driver_adapter.dart @@ -61,34 +61,34 @@ abstract class AppDriverAdapter { Future isPresent( TFinderType finder, { - Duration timeout = const Duration(seconds: 1), + Duration? timeout = const Duration(seconds: 1), }); Future isAbsent( TFinderType finder, { - Duration timeout = const Duration(seconds: 1), + Duration? timeout = const Duration(seconds: 1), }); Future enterText( TFinderType finder, String text, { - Duration timeout = const Duration(seconds: 30), + Duration? timeout = const Duration(seconds: 30), }); - Future getText( + Future getText( TFinderType finder, { - Duration timeout = const Duration(seconds: 30), + Duration? timeout = const Duration(seconds: 30), }); Future tap( TFinderType finder, { - Duration timeout = const Duration(seconds: 30), + Duration? timeout = const Duration(seconds: 30), }); Future longPress( TFinderType finder, { Duration pressDuration = const Duration(milliseconds: 500), - Duration timeout = const Duration(seconds: 30), + Duration? timeout = const Duration(seconds: 30), }); Future pageBack(); @@ -98,8 +98,8 @@ abstract class AppDriverAdapter { TFinderType finder, { double dx, double dy, - Duration duration = const Duration(milliseconds: 200), - Duration timeout = const Duration(seconds: 30), + Duration? duration = const Duration(milliseconds: 200), + Duration? timeout = const Duration(seconds: 30), }); /// Repeatedly scrolls a [Scrollable] by delta until finder is visible. @@ -110,26 +110,26 @@ abstract class AppDriverAdapter { TFinderType scrollable, double dx, double dy, - Duration timeout = const Duration(seconds: 30), + Duration? timeout = const Duration(seconds: 30), }); Future scrollIntoView( TFinderType finder, { - Duration timeout = const Duration(seconds: 30), + Duration? timeout = const Duration(seconds: 30), }); /// Will wait until the give condition returns `true` polling every `pollInterval`. If `condition` has not returned true /// within the given `timeout` this will cause the returned future to complete with a [TimeoutException]. Future waitUntil( Future Function() condition, { - Duration timeout = const Duration(seconds: 10), - Duration pollInterval = const Duration(milliseconds: 500), + Duration? timeout = const Duration(seconds: 10), + Duration? pollInterval = const Duration(milliseconds: 500), }) async { return Future.microtask( () async { final completer = Completer(); var maxAttempts = - (timeout.inMilliseconds / pollInterval.inMilliseconds).round(); + (timeout!.inMilliseconds / pollInterval!.inMilliseconds).round(); var attempts = 0; while (attempts < maxAttempts) { @@ -143,7 +143,7 @@ abstract class AppDriverAdapter { } }, ).timeout( - timeout, + timeout!, ); } 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 a34f4aa..169d097 100644 --- a/lib/src/flutter/adapters/flutter_driver_app_driver_adapter.dart +++ b/lib/src/flutter/adapters/flutter_driver_app_driver_adapter.dart @@ -10,25 +10,26 @@ class FlutterDriverAppDriverAdapter @override Future waitForAppToSettle({ - Duration duration = const Duration(milliseconds: 100), - Duration timeout = const Duration(seconds: 30), + Duration? duration = const Duration(milliseconds: 100), + Duration? timeout = const Duration(seconds: 30), }) async { try { await rawDriver.waitUntilNoTransientCallbacks(timeout: timeout); } catch (_) { - return null; + return 1; } - return null; + return 0; } @override - Future widget( + Future widget( SerializableFinder finder, [ ExpectedWidgetResultType expectResultType = ExpectedWidgetResultType.first, ]) { throw UnimplementedError( - 'Flutter driver does not support directly interacting with the widget tree'); + 'Flutter driver does not support directly interacting with the widget tree', + ); } @override @@ -49,7 +50,7 @@ class FlutterDriverAppDriverAdapter @override Future isPresent( SerializableFinder finder, { - Duration timeout = const Duration(seconds: 1), + Duration? timeout = const Duration(seconds: 1), }) async { try { await rawDriver.waitFor( @@ -65,7 +66,7 @@ class FlutterDriverAppDriverAdapter @override Future isAbsent( SerializableFinder finder, { - Duration timeout = const Duration(seconds: 1), + Duration? timeout = const Duration(seconds: 1), }) async { try { await rawDriver.waitForAbsent( @@ -79,9 +80,9 @@ class FlutterDriverAppDriverAdapter } @override - Future getText( + Future getText( SerializableFinder finder, { - Duration timeout = const Duration(seconds: 30), + Duration? timeout = const Duration(seconds: 30), }) async { await waitForAppToSettle(timeout: timeout); @@ -95,7 +96,7 @@ class FlutterDriverAppDriverAdapter Future enterText( SerializableFinder finder, String text, { - Duration timeout = const Duration(seconds: 30), + Duration? timeout = const Duration(seconds: 30), }) async { await tap( finder, @@ -110,7 +111,7 @@ class FlutterDriverAppDriverAdapter @override Future tap( SerializableFinder finder, { - Duration timeout = const Duration(seconds: 30), + Duration? timeout = const Duration(seconds: 30), }) async { await rawDriver.tap(finder, timeout: timeout); await waitForAppToSettle(timeout: timeout); @@ -119,8 +120,8 @@ class FlutterDriverAppDriverAdapter @override Future longPress( SerializableFinder finder, { - Duration pressDuration = const Duration(milliseconds: 500), - Duration timeout = const Duration(seconds: 30), + Duration? pressDuration = const Duration(milliseconds: 500), + Duration? timeout = const Duration(seconds: 30), }) async { await scroll( finder, @@ -135,10 +136,10 @@ class FlutterDriverAppDriverAdapter @override Future scroll( SerializableFinder finder, { - double dx, - double dy, - Duration duration = const Duration(milliseconds: 200), - Duration timeout = const Duration(seconds: 30), + double? dx, + double? dy, + Duration? duration = const Duration(milliseconds: 200), + Duration? timeout = const Duration(seconds: 30), }) async { await rawDriver.scroll( finder, @@ -165,8 +166,6 @@ class FlutterDriverAppDriverAdapter case FindType.type: return find.byType(data.toString()); } - - throw Exception('unknown finder'); } @override @@ -202,10 +201,10 @@ class FlutterDriverAppDriverAdapter @override Future scrollUntilVisible( SerializableFinder item, { - SerializableFinder scrollable, - double dx, - double dy, - Duration timeout = const Duration(seconds: 30), + SerializableFinder? scrollable, + double? dx, + double? dy, + Duration? timeout = const Duration(seconds: 30), }) async { await rawDriver.scrollUntilVisible( scrollable, @@ -219,7 +218,7 @@ class FlutterDriverAppDriverAdapter @override Future scrollIntoView( SerializableFinder finder, { - Duration timeout = const Duration(seconds: 30), + Duration? timeout = const Duration(seconds: 30), }) async { await rawDriver.scrollIntoView( finder, diff --git a/lib/src/flutter/adapters/widget_tester_app_driver_adapter.dart b/lib/src/flutter/adapters/widget_tester_app_driver_adapter.dart index da50d20..889b4f5 100644 --- a/lib/src/flutter/adapters/widget_tester_app_driver_adapter.dart +++ b/lib/src/flutter/adapters/widget_tester_app_driver_adapter.dart @@ -14,20 +14,18 @@ class WidgetTesterAppDriverAdapter @override Future waitForAppToSettle({ - Duration duration = const Duration(milliseconds: 100), - Duration timeout = const Duration(seconds: 30), + Duration? duration = const Duration(milliseconds: 100), + Duration? timeout = const Duration(seconds: 30), }) async { try { - await rawDriver.pumpAndSettle( - duration, - EnginePhase.sendSemanticsUpdate, - timeout, + return await rawDriver.pumpAndSettle( + duration!, + EnginePhase.paint, + timeout!, ); } catch (_) { - return null; + return 1; } - - return null; } @override @@ -48,24 +46,25 @@ class WidgetTesterAppDriverAdapter @override Future> screenshot() { - var renderObject = rawDriver.binding.renderViewElement.renderObject; - while (!renderObject.isRepaintBoundary) { + var renderObject = rawDriver.binding.renderViewElement?.renderObject; + + while (renderObject != null && !renderObject.isRepaintBoundary) { renderObject = renderObject.parent as RenderObject; - assert(renderObject != null); } - assert(!renderObject.debugNeedsPaint); - final layer = renderObject.debugLayer as OffsetLayer; + + assert(renderObject != null && !renderObject.debugNeedsPaint); + final layer = renderObject!.debugLayer as OffsetLayer; return layer .toImage(renderObject.semanticBounds) .then((value) => value.toByteData(format: ui.ImageByteFormat.png)) - .then((value) => value.buffer.asUint8List()); + .then((value) => value?.buffer.asUint8List() ?? List.empty()); } @override Future isPresent( Finder finder, { - Duration timeout = const Duration(seconds: 1), + Duration? timeout = const Duration(seconds: 1), }) async { return finder.evaluate().isNotEmpty; } @@ -73,15 +72,15 @@ class WidgetTesterAppDriverAdapter @override Future isAbsent( Finder finder, { - Duration timeout = const Duration(seconds: 1), + Duration? timeout = const Duration(seconds: 1), }) async { return await isPresent(finder).then((value) => !value); } @override - Future getText( + Future getText( Finder finder, { - Duration timeout = const Duration(seconds: 30), + Duration? timeout = const Duration(seconds: 30), }) async { await waitForAppToSettle(timeout: timeout); @@ -102,7 +101,7 @@ class WidgetTesterAppDriverAdapter Future enterText( Finder finder, String text, { - Duration timeout = const Duration(seconds: 30), + Duration? timeout = const Duration(seconds: 30), }) async { await tap( finder, @@ -117,7 +116,7 @@ class WidgetTesterAppDriverAdapter @override Future tap( Finder finder, { - Duration timeout = const Duration(seconds: 30), + Duration? timeout = const Duration(seconds: 30), }) async { await rawDriver.tap(finder); await waitForAppToSettle(timeout: timeout); @@ -126,8 +125,8 @@ class WidgetTesterAppDriverAdapter @override Future longPress( Finder finder, { - Duration pressDuration = const Duration(milliseconds: 500), - Duration timeout = const Duration(seconds: 30), + Duration? pressDuration = const Duration(milliseconds: 500), + Duration? timeout = const Duration(seconds: 30), }) async { await scroll( finder, @@ -142,10 +141,10 @@ class WidgetTesterAppDriverAdapter @override Future scroll( Finder finder, { - double dx, - double dy, - Duration duration = const Duration(milliseconds: 200), - Duration timeout = const Duration(seconds: 30), + double? dx, + double? dy, + Duration? duration = const Duration(milliseconds: 200), + Duration? timeout = const Duration(seconds: 30), }) async { final scrollableFinder = findByDescendant( finder, @@ -154,7 +153,7 @@ class WidgetTesterAppDriverAdapter ); final state = rawDriver.state(scrollableFinder) as ScrollableState; final position = state.position; - position.jumpTo(dy ?? dx); + position.jumpTo(dy ?? dx ?? 0); await rawDriver.pump(); } @@ -174,8 +173,6 @@ class WidgetTesterAppDriverAdapter case FindType.type: return find.byType(data); } - - throw Exception('unknown finder'); } @override @@ -209,14 +206,14 @@ class WidgetTesterAppDriverAdapter @override Future scrollUntilVisible( Finder item, { - Finder scrollable, - double dx, - double dy, - Duration timeout = const Duration(seconds: 30), + Finder? scrollable, + double? dx, + double? dy, + Duration? timeout = const Duration(seconds: 30), }) async { await rawDriver.scrollUntilVisible( item, - dy ?? dx, + dy ?? dx ?? 0, scrollable: scrollable, ); } @@ -224,7 +221,7 @@ class WidgetTesterAppDriverAdapter @override Future scrollIntoView( Finder finder, { - Duration timeout = const Duration(seconds: 30), + Duration? timeout = const Duration(seconds: 30), }) async { await rawDriver.ensureVisible(finder); await waitForAppToSettle(); diff --git a/lib/src/flutter/code_generation/annotations/gherkin_full_test_suite_annotation.dart b/lib/src/flutter/code_generation/annotations/gherkin_full_test_suite_annotation.dart index e767b63..f898ebe 100644 --- a/lib/src/flutter/code_generation/annotations/gherkin_full_test_suite_annotation.dart +++ b/lib/src/flutter/code_generation/annotations/gherkin_full_test_suite_annotation.dart @@ -4,7 +4,7 @@ import 'package:gherkin/gherkin.dart'; /// to the style required by the integration_test package class GherkinTestSuite { /// Path to the feature files to generate tests for - final Iterable featurePaths; + final Iterable featurePaths; /// The execution order of features - this default to random to avoid any inter-test dependencies final ExecutionOrder executionOrder; 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 93cf4a0..6e03d40 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 @@ -5,6 +5,7 @@ import 'package:analyzer/dart/element/element.dart'; import 'package:flutter_gherkin/src/flutter/code_generation/annotations/gherkin_full_test_suite_annotation.dart'; import 'package:gherkin/gherkin.dart'; import 'package:glob/glob.dart'; +import 'package:glob/list_local_fs.dart'; import 'package:source_gen/source_gen.dart'; class NoOpReporter extends Reporter {} @@ -45,25 +46,25 @@ void executeTestSuite( _languageService.initialise( annotation.read('featureDefaultLanguage').literalValue.toString(), ); - final executionOrder = ExecutionOrder.values[annotation + final idx = annotation .read('executionOrder') .objectValue - .getField('index') - .toIntValue()]; + .getField('index')! + .toIntValue()!; + final executionOrder = ExecutionOrder.values[idx]; final featureFiles = annotation .read('featurePaths') .listValue - .map((path) => Glob(path.toStringValue())) + .map((path) => Glob(path.toStringValue()!)) .map( - (glob) => glob - .listSync() + (glob) => glob.listSync() .map((entity) => File(entity.path).readAsStringSync()) .toList(), ) .reduce((value, element) => value..addAll(element)); if (executionOrder == ExecutionOrder.random) { - featureFiles..shuffle(); + featureFiles.shuffle(); } final featureExecutionFunctionsBuilder = StringBuffer(); @@ -146,9 +147,9 @@ class FeatureFileTestGeneratorVisitor extends FeatureFileVisitor { '''; final StringBuffer _buffer = StringBuffer(); - int _id; - String _currentFeatureCode; - String _currentScenarioCode; + int? _id; + String? _currentFeatureCode; + String? _currentScenarioCode; final StringBuffer _scenarioBuffer = StringBuffer(); final StringBuffer _stepBuffer = StringBuffer(); @@ -176,18 +177,21 @@ class FeatureFileTestGeneratorVisitor extends FeatureFileVisitor { @override Future visitFeature( String name, - String description, + String? description, Iterable tags, ) async { - _currentFeatureCode = - _replaceVariable(FUNCTION_TEMPLATE, 'feature_number', _id.toString()); _currentFeatureCode = _replaceVariable( - _currentFeatureCode, + FUNCTION_TEMPLATE, + 'feature_number', + _id.toString(), + ); + _currentFeatureCode = _replaceVariable( + _currentFeatureCode!, 'feature_name', _escapeText(name), ); _currentFeatureCode = _replaceVariable( - _currentFeatureCode, + _currentFeatureCode!, 'tags', '[${tags.map((e) => "'$e'").join(', ')}]', ); @@ -202,7 +206,7 @@ class FeatureFileTestGeneratorVisitor extends FeatureFileVisitor { _escapeText(name), ); _currentScenarioCode = _replaceVariable( - _currentScenarioCode, + _currentScenarioCode!, 'tags', '[${tags.map((e) => "'$e'").join(', ')}]', ); @@ -212,7 +216,7 @@ class FeatureFileTestGeneratorVisitor extends FeatureFileVisitor { Future visitScenarioStep( String name, Iterable multiLineStrings, - GherkinTable table, + GherkinTable? table, ) async { var code = _replaceVariable( STEP_TEMPLATE, @@ -236,7 +240,7 @@ class FeatureFileTestGeneratorVisitor extends FeatureFileVisitor { void _flushFeature() { if (_currentFeatureCode != null) { _currentFeatureCode = _replaceVariable( - _currentFeatureCode, + _currentFeatureCode!, 'scenarios', _scenarioBuffer.toString(), ); @@ -252,7 +256,7 @@ class FeatureFileTestGeneratorVisitor extends FeatureFileVisitor { if (_currentScenarioCode != null) { if (_stepBuffer.isNotEmpty) { _currentScenarioCode = _replaceVariable( - _currentScenarioCode, + _currentScenarioCode!, 'steps', _stepBuffer.toString(), ); diff --git a/lib/src/flutter/configuration/flutter_driver_test_configuration.dart b/lib/src/flutter/configuration/flutter_driver_test_configuration.dart index b0b9835..5c1aa51 100644 --- a/lib/src/flutter/configuration/flutter_driver_test_configuration.dart +++ b/lib/src/flutter/configuration/flutter_driver_test_configuration.dart @@ -1,6 +1,6 @@ import 'dart:async'; import 'dart:io'; -import 'package:flutter_gherkin/flutter_gherkin.dart'; +import 'package:flutter_gherkin/flutter_gherkin_with_driver.dart'; import 'package:flutter_gherkin/src/flutter/configuration/build_mode.dart'; import 'package:flutter_gherkin/src/flutter/world/flutter_driver_world.dart'; import 'package:flutter_gherkin/src/flutter/world/flutter_world.dart'; @@ -12,7 +12,7 @@ import 'package:glob/glob.dart'; import 'flutter_test_configuration.dart'; class FlutterDriverTestConfiguration extends FlutterTestConfiguration { - String _observatoryDebuggerUri; + String? _observatoryDebuggerUri; /// Provide a configuration object with default settings such as the reports and feature file location /// Additional setting on the configuration object can be set on the returned instance. @@ -36,8 +36,7 @@ class FlutterDriverTestConfiguration extends FlutterTestConfiguration { ] ..targetAppPath = targetAppPath ..stepDefinitions = steps - ..restartAppBetweenScenarios = true - ..exitAfterTestRun = true; + ..restartAppBetweenScenarios = true; } /// restarts the application under test between each scenario. @@ -51,11 +50,11 @@ class FlutterDriverTestConfiguration extends FlutterTestConfiguration { /// Option to define the working directory for the process that runs the app under test (optional) /// Handy if your app is separated from your tests as flutter needs to be able to find a pubspec file - String targetAppWorkingDirectory; + String? targetAppWorkingDirectory; /// The build flavor to run the tests against (optional) - /// Defaults to empty - String buildFlavor = ''; + /// Defaults to null + String? buildFlavor; /// The default build mode used for running tests is --debug. /// We are exposing the option to run the tests also in --profile mode @@ -66,8 +65,8 @@ class FlutterDriverTestConfiguration extends FlutterTestConfiguration { bool build = true; /// The target device id to run the tests against when multiple devices detected - /// Defaults to empty - String targetDeviceId = ''; + /// Defaults to null + String? targetDeviceId; /// Will keep the Flutter application running when done testing /// Defaults to false @@ -100,19 +99,19 @@ class FlutterDriverTestConfiguration extends FlutterTestConfiguration { /// An observatory url that the test runner can connect to instead of creating a new running instance of the target application /// Url takes the form of `http://127.0.0.1:51540/EM72VtRsUV0=/` and usually printed to stdout in the form `Connecting to service protocol: http://127.0.0.1:51540/EM72VtRsUV0=/` /// You will have to add the `--verbose` flag to the command to start your flutter app to see this output and ensure `enableFlutterDriverExtension()` is called by the running app - String runningAppProtocolEndpointUri; + String? runningAppProtocolEndpointUri; /// Called before any attempt to connect Flutter driver to the running application, Depending on your configuration this /// method will be called before each scenario is run. - Future Function() onBeforeFlutterDriverConnect; + Future Function()? onBeforeFlutterDriverConnect; /// 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. - Future Function(FlutterDriver driver) onAfterFlutterDriverConnect; + Future Function(FlutterDriver driver)? onAfterFlutterDriverConnect; void setObservatoryDebuggerUri(String uri) => _observatoryDebuggerUri = uri; - Future createFlutterDriver([String dartVmServiceUrl]) async { + Future createFlutterDriver([String? dartVmServiceUrl]) async { final completer = Completer(); dartVmServiceUrl = (dartVmServiceUrl ?? _observatoryDebuggerUri) ?? Platform.environment['VM_SERVICE_URL']; @@ -120,12 +119,12 @@ class FlutterDriverTestConfiguration extends FlutterTestConfiguration { await runZonedGuarded( () async { if (onBeforeFlutterDriverConnect != null) { - await onBeforeFlutterDriverConnect(); + await onBeforeFlutterDriverConnect!(); } final driver = await _attemptDriverConnection(dartVmServiceUrl, 1, 3); if (onAfterFlutterDriverConnect != null) { - await onAfterFlutterDriverConnect(driver); + await onAfterFlutterDriverConnect!(driver); } completer.complete(driver); @@ -142,14 +141,15 @@ class FlutterDriverTestConfiguration extends FlutterTestConfiguration { Future createFlutterWorld( TestConfiguration config, - FlutterWorld world, + FlutterWorld? world, ) async { var flutterConfig = config as FlutterDriverTestConfiguration; world = world ?? FlutterDriverWorld(); final driver = await createFlutterDriver( flutterConfig.runningAppProtocolEndpointUri != null && - flutterConfig.runningAppProtocolEndpointUri.isNotEmpty + flutterConfig.runningAppProtocolEndpointUri != null && + flutterConfig.runningAppProtocolEndpointUri!.isNotEmpty ? flutterConfig.runningAppProtocolEndpointUri : null, ); @@ -165,19 +165,19 @@ class FlutterDriverTestConfiguration extends FlutterTestConfiguration { _ensureCorrectConfiguration(); final providedCreateWorld = createWorld; createWorld = (config) async { - FlutterWorld world; + FlutterWorld? world; if (providedCreateWorld != null) { - world = await providedCreateWorld(config); + world = await providedCreateWorld(config) as FlutterWorld; } return await createFlutterWorld(config, world); }; - hooks = List.from(hooks ?? [])..add(FlutterAppRunnerHook()); + hooks = List.from(hooks ?? Iterable.empty())..add(FlutterAppRunnerHook()); } Future _attemptDriverConnection( - String dartVmServiceUrl, + String? dartVmServiceUrl, int attempt, int maxAttempts, ) async { @@ -189,7 +189,8 @@ class FlutterDriverTestConfiguration extends FlutterTestConfiguration { throw e; } else { print( - 'Fluter driver error connecting to application at `$dartVmServiceUrl`, retrying after delay of $flutterDriverReconnectionDelay', + 'Fluter driver error connecting to application at `$dartVmServiceUrl`,' + 'retrying after delay of $flutterDriverReconnectionDelay', ); await Future.delayed(flutterDriverReconnectionDelay); @@ -205,15 +206,17 @@ class FlutterDriverTestConfiguration extends FlutterTestConfiguration { void _ensureCorrectConfiguration() { if (runningAppProtocolEndpointUri != null && - runningAppProtocolEndpointUri.isNotEmpty) { + runningAppProtocolEndpointUri!.isNotEmpty) { if (restartAppBetweenScenarios) { throw AssertionError( - 'Cannot restart app between scenarios if using runningAppProtocolEndpointUri'); + 'Cannot restart app between scenarios if using runningAppProtocolEndpointUri', + ); } - if (targetDeviceId != null && targetDeviceId.isNotEmpty) { + if (targetDeviceId != null && targetDeviceId!.isNotEmpty) { throw AssertionError( - 'Cannot target specific device id if using runningAppProtocolEndpointUri'); + 'Cannot target specific device id if using runningAppProtocolEndpointUri', + ); } } } diff --git a/lib/src/flutter/configuration/flutter_test_configuration.dart b/lib/src/flutter/configuration/flutter_test_configuration.dart index 36e2169..c6e4a9c 100644 --- a/lib/src/flutter/configuration/flutter_test_configuration.dart +++ b/lib/src/flutter/configuration/flutter_test_configuration.dart @@ -1,4 +1,4 @@ -import 'package:flutter_gherkin/flutter_gherkin.dart'; +import 'package:flutter_gherkin/flutter_gherkin_with_driver.dart'; import 'package:flutter_gherkin/src/flutter/parameters/existence_parameter.dart'; import 'package:flutter_gherkin/src/flutter/parameters/swipe_direction_parameter.dart'; import 'package:flutter_gherkin/src/flutter/steps/given_i_open_the_drawer_step.dart'; @@ -45,12 +45,12 @@ class FlutterTestConfiguration extends TestConfiguration { @override void prepare() { customStepParameterDefinitions = - List.from(customStepParameterDefinitions ?? []) + List.from(customStepParameterDefinitions ?? Iterable.empty()) ..addAll([ ExistenceParameter(), SwipeDirectionParameter(), ]); - stepDefinitions = List.from(stepDefinitions ?? []) + stepDefinitions = List.from(stepDefinitions ?? Iterable.empty()) ..addAll([ ThenExpectElementToHaveValue(), WhenTapBackButtonWidget(), diff --git a/lib/src/flutter/hooks/app_runner_hook.dart b/lib/src/flutter/hooks/app_runner_hook.dart index ef17fc4..e5da71b 100644 --- a/lib/src/flutter/hooks/app_runner_hook.dart +++ b/lib/src/flutter/hooks/app_runner_hook.dart @@ -7,7 +7,7 @@ import 'package:gherkin/gherkin.dart'; /// A hook that manages running the target flutter application /// that is under test class FlutterAppRunnerHook extends Hook { - FlutterRunProcessHandler _flutterRunProcessHandler; + FlutterRunProcessHandler? _flutterRunProcessHandler; bool haveRunFirstScenario = false; @override @@ -55,17 +55,18 @@ class FlutterAppRunnerHook extends Hook { Iterable tags, ) async { if (world is FlutterDriverWorld) { - world.setFlutterProcessHandler(_flutterRunProcessHandler); + world.setFlutterProcessHandler(_flutterRunProcessHandler!); } } Future _runApp(FlutterDriverTestConfiguration config) async { if (config.runningAppProtocolEndpointUri != null && - config.runningAppProtocolEndpointUri.isNotEmpty) { + config.runningAppProtocolEndpointUri!.isNotEmpty) { stdout.writeln( - "Connecting to running Flutter app under test at '${config.runningAppProtocolEndpointUri}', this might take a few moments", + "Connecting to running Flutter app under test at '${config.runningAppProtocolEndpointUri}', " + 'this might take a few moments', ); - config.setObservatoryDebuggerUri(config.runningAppProtocolEndpointUri); + config.setObservatoryDebuggerUri(config.runningAppProtocolEndpointUri!); } else { _flutterRunProcessHandler = FlutterRunProcessHandler() ..setLogFlutterProcessOutput(config.logFlutterProcessOutput) @@ -81,8 +82,8 @@ class FlutterAppRunnerHook extends Hook { stdout.writeln( "Starting Flutter app under test '${config.targetAppPath}', this might take a few moments"); - await _flutterRunProcessHandler.run(); - final observatoryUri = await _flutterRunProcessHandler + await _flutterRunProcessHandler!.run(); + final observatoryUri = await _flutterRunProcessHandler! .waitForObservatoryDebuggerUri(config.flutterBuildTimeout); config.setObservatoryDebuggerUri(observatoryUri); } @@ -91,7 +92,7 @@ class FlutterAppRunnerHook extends Hook { Future _terminateApp() async { if (_flutterRunProcessHandler != null) { stdout.writeln('Terminating Flutter app under test'); - await _flutterRunProcessHandler.terminate(); + await _flutterRunProcessHandler!.terminate(); _flutterRunProcessHandler = null; } } @@ -99,7 +100,7 @@ class FlutterAppRunnerHook extends Hook { Future _restartApp() async { if (_flutterRunProcessHandler != null) { stdout.writeln('Restarting Flutter app under test'); - await _flutterRunProcessHandler.restart(); + await _flutterRunProcessHandler!.restart(); } } diff --git a/lib/src/flutter/reporters/flutter_driver_reporter.dart b/lib/src/flutter/reporters/flutter_driver_reporter.dart index 2c97005..1b81f5b 100644 --- a/lib/src/flutter/reporters/flutter_driver_reporter.dart +++ b/lib/src/flutter/reporters/flutter_driver_reporter.dart @@ -31,7 +31,7 @@ class FlutterDriverReporter extends Reporter { @override Future dispose() async { - driverLog = null; + // driverLog = null; } void _driverLogMessageHandler(String source, String message) { diff --git a/lib/src/flutter/runners/flutter_run_process_handler.dart b/lib/src/flutter/runners/flutter_run_process_handler.dart index f088b88..9d386b5 100644 --- a/lib/src/flutter/runners/flutter_run_process_handler.dart +++ b/lib/src/flutter/runners/flutter_run_process_handler.dart @@ -41,20 +41,20 @@ class FlutterRunProcessHandler extends ProcessHandler { multiLine: false, ); - Process _runningProcess; - Stream _processStdoutStream; + Process? _runningProcess; + Stream? _processStdoutStream; final List _openSubscriptions = []; bool _buildApp = true; bool _logFlutterProcessOutput = false; bool _verboseFlutterLogs = false; bool _keepAppRunning = false; BuildMode _buildMode = BuildMode.Debug; - String _workingDirectory; - String _appTarget; - String _buildFlavor; - String _deviceTargetId; + String? _workingDirectory; + String? _appTarget; + String? _buildFlavor; + String? _deviceTargetId; Duration _driverConnectionDelay = const Duration(seconds: 2); - String currentObservatoryUri; + String? currentObservatoryUri; void setLogFlutterProcessOutput(bool logFlutterProcessOutput) { _logFlutterProcessOutput = logFlutterProcessOutput; @@ -64,15 +64,15 @@ class FlutterRunProcessHandler extends ProcessHandler { _appTarget = targetPath; } - void setDriverConnectionDelay(Duration duration) { + void setDriverConnectionDelay(Duration? duration) { _driverConnectionDelay = duration ?? _driverConnectionDelay; } - void setWorkingDirectory(String workingDirectory) { + void setWorkingDirectory(String? workingDirectory) { _workingDirectory = workingDirectory; } - void setBuildFlavor(String buildFlavor) { + void setBuildFlavor(String? buildFlavor) { _buildFlavor = buildFlavor; } @@ -80,7 +80,7 @@ class FlutterRunProcessHandler extends ProcessHandler { _buildMode = buildMode; } - void setDeviceTargetId(String deviceTargetId) { + void setDeviceTargetId(String? deviceTargetId) { _deviceTargetId = deviceTargetId; } @@ -110,11 +110,11 @@ class FlutterRunProcessHandler extends ProcessHandler { arguments.add('--no-build'); } - if (_buildFlavor != null && _buildFlavor.isNotEmpty) { + if (_buildFlavor != null && _buildFlavor!.isNotEmpty) { arguments.add('--flavor=$_buildFlavor'); } - if (_deviceTargetId != null && _deviceTargetId.isNotEmpty) { + if (_deviceTargetId != null && _deviceTargetId!.isNotEmpty) { arguments.add('--device-id=$_deviceTargetId'); } @@ -140,16 +140,16 @@ class FlutterRunProcessHandler extends ProcessHandler { ); _processStdoutStream = - _runningProcess.stdout.transform(utf8.decoder).asBroadcastStream(); + _runningProcess!.stdout.transform(utf8.decoder).asBroadcastStream(); - _openSubscriptions.add(_runningProcess.stderr + _openSubscriptions.add(_runningProcess!.stderr .map((events) => String.fromCharCodes(events).trim()) .where((event) => event.isNotEmpty) .listen((event) { if (event.contains(_errorMessageRegex)) { stderr.writeln('${FAIL_COLOR}Flutter build error: $event$RESET_COLOR'); } else { - // This is most likely a depricated api usage warnings (from Gradle) and should not + // This is most likely a deprecated api usage warnings (from Gradle) and should not // cause the test run to fail. stdout.writeln('$WARN_COLOR$event$RESET_COLOR'); } @@ -161,19 +161,21 @@ class FlutterRunProcessHandler extends ProcessHandler { var exitCode = -1; _ensureRunningProcess(); if (_runningProcess != null) { - _runningProcess.stdin.write('q'); + _runningProcess!.stdin.write('q'); _openSubscriptions.forEach((s) => s.cancel()); _openSubscriptions.clear(); - exitCode = await _runningProcess.exitCode; + exitCode = await _runningProcess!.exitCode; _runningProcess = null; } return exitCode; } - Future restart({Duration timeout = const Duration(seconds: 90)}) async { + Future restart({ + Duration? timeout = const Duration(seconds: 90), + }) async { _ensureRunningProcess(); - _runningProcess.stdin.write('R'); + _runningProcess!.stdin.write('R'); await _waitForStdOutMessage( _restartedApplicationSuccessRegex, 'Timeout waiting for app restart', @@ -196,18 +198,18 @@ class FlutterRunProcessHandler extends ProcessHandler { timeout, ); - return currentObservatoryUri; + return currentObservatoryUri!; } Future _waitForStdOutMessage( RegExp matcher, String timeoutMessage, [ - Duration timeout = const Duration(seconds: 90), + Duration? timeout = const Duration(seconds: 90), ]) { _ensureRunningProcess(); final completer = Completer(); - StreamSubscription sub; - sub = _processStdoutStream.timeout( + StreamSubscription? sub; + sub = _processStdoutStream!.timeout( timeout ?? const Duration(seconds: 90), onTimeout: (_) { sub?.cancel(); @@ -223,7 +225,7 @@ class FlutterRunProcessHandler extends ProcessHandler { if (matcher.hasMatch(logLine)) { sub?.cancel(); if (!completer.isCompleted) { - completer.complete(matcher.firstMatch(logLine).group(1)); + completer.complete(matcher.firstMatch(logLine)!.group(1)); } } else if (_noConnectedDeviceRegex.hasMatch(logLine)) { sub?.cancel(); diff --git a/lib/src/flutter/runners/gherkin_integration_test_runner.dart b/lib/src/flutter/runners/gherkin_integration_test_runner.dart index 32a035d..07f2ca1 100644 --- a/lib/src/flutter/runners/gherkin_integration_test_runner.dart +++ b/lib/src/flutter/runners/gherkin_integration_test_runner.dart @@ -1,10 +1,11 @@ -import 'package:flutter_gherkin/flutter_gherkin_integration_test.dart'; +import 'package:flutter_gherkin/flutter_gherkin.dart'; import 'package:flutter_gherkin/src/flutter/adapters/widget_tester_app_driver_adapter.dart'; import 'package:flutter_gherkin/src/flutter/world/flutter_world.dart'; import 'package:gherkin/gherkin.dart'; import 'package:flutter/widgets.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:integration_test/integration_test.dart'; +import 'package:collection/collection.dart'; class TestDependencies { final World world; @@ -21,15 +22,15 @@ abstract class GherkinIntegrationTestRunner { TagExpressionEvaluator(); final TestConfiguration configuration; final void Function(World world) appMainFunction; - Reporter _reporter; - Hook _hook; - Iterable _executableSteps; - Iterable _customParameters; + Reporter? _reporter; + Hook? _hook; + Iterable? _executableSteps; + Iterable? _customParameters; - IntegrationTestWidgetsFlutterBinding _binding; + IntegrationTestWidgetsFlutterBinding? _binding; - Reporter get reporter => _reporter; - Hook get hook => _hook; + Reporter get reporter => _reporter!; + Hook get hook => _hook!; Timeout scenarioExecutionTimeout = const Timeout(Duration(minutes: 10)); @@ -43,8 +44,8 @@ abstract class GherkinIntegrationTestRunner { _customParameters = _registerCustomParameters(configuration.customStepParameterDefinitions); _executableSteps = _registerStepDefinitions( - configuration.stepDefinitions, - _customParameters, + configuration.stepDefinitions!, + _customParameters!, ); } @@ -68,7 +69,7 @@ abstract class GherkinIntegrationTestRunner { void onRunComplete() { _safeInvokeFuture(() async => await reporter.onTestRunFinished()); _safeInvokeFuture(() async => await hook.onAfterRun(configuration)); - setTestResultData(_binding); + setTestResultData(_binding!); _safeInvokeFuture(() async => await reporter.dispose()); } @@ -82,7 +83,7 @@ abstract class GherkinIntegrationTestRunner { @protected void runFeature( String name, - Iterable tags, + Iterable? tags, void Function() runFeature, ) { group( @@ -90,7 +91,7 @@ abstract class GherkinIntegrationTestRunner { () { final debugInformation = RunnableDebugInformation('', 0, name); final featureTags = - (tags ?? Iterable.empty()).map((t) => Tag(t, 0)); + (tags ?? Iterable.empty()).map((t) => Tag(t.toString(), 0)); _safeInvokeFuture( () async => await reporter.onFeatureStarted( StartedMessage( @@ -120,7 +121,7 @@ abstract class GherkinIntegrationTestRunner { @protected void runScenario( String name, - Iterable tags, + Iterable? tags, Future Function(TestDependencies dependencies) runTest, ) { if (_evaluateTagFilterExpression(configuration.tagExpression, tags)) { @@ -129,13 +130,13 @@ abstract class GherkinIntegrationTestRunner { (WidgetTester tester) async { final debugInformation = RunnableDebugInformation('', 0, name); final scenarioTags = - (tags ?? Iterable.empty()).map((t) => Tag(t, 0)); + (tags ?? Iterable.empty()).map((t) => Tag(t.toString(), 0)); final dependencies = await createTestDependencies( configuration, tester, ); - await _hook.onBeforeScenario( + await hook.onBeforeScenario( configuration, name, scenarioTags, @@ -146,7 +147,7 @@ abstract class GherkinIntegrationTestRunner { dependencies.world, ); - await _hook.onAfterScenarioWorldCreated( + await hook.onAfterScenarioWorldCreated( dependencies.world, name, scenarioTags, @@ -163,7 +164,7 @@ abstract class GherkinIntegrationTestRunner { await runTest(dependencies); - await _reporter.onScenarioFinished( + await reporter.onScenarioFinished( ScenarioFinishedMessage( name, debugInformation, @@ -171,7 +172,7 @@ abstract class GherkinIntegrationTestRunner { ), ); - await _hook.onAfterScenario( + await hook.onAfterScenario( configuration, name, scenarioTags, @@ -184,7 +185,7 @@ abstract class GherkinIntegrationTestRunner { } else { _safeInvokeFuture( () async => reporter.message( - 'Ignoring scenario `${name}` as tag expression `${configuration.tagExpression}` not satisfied', + 'Ignoring scenario `$name` as tag expression `${configuration.tagExpression}` not satisfied', MessageLevel.info, ), ); @@ -205,12 +206,12 @@ abstract class GherkinIntegrationTestRunner { TestConfiguration configuration, WidgetTester tester, ) async { - World world; + World? world; final attachmentManager = await configuration.getAttachmentManager(configuration); if (configuration.createWorld != null) { - world = await configuration.createWorld(configuration); + world = await configuration.createWorld!(configuration); } world = world ?? FlutterWidgetTesterWorld(); @@ -231,9 +232,8 @@ abstract class GherkinIntegrationTestRunner { dynamic table, TestDependencies dependencies, ) async { - final executable = _executableSteps.firstWhere( + final executable = _executableSteps!.firstWhereOrNull( (s) => s.expression.isMatch(step), - orElse: () => null, ); if (executable == null) { @@ -280,11 +280,14 @@ abstract class GherkinIntegrationTestRunner { @protected void cleanupScenarioRun(TestDependencies dependencies) { _safeInvokeFuture( - () async => await dependencies.attachmentManager.dispose()); - _safeInvokeFuture(() async => await dependencies.world.dispose()); + () async => dependencies.attachmentManager.dispose(), + ); + _safeInvokeFuture( + () async => dependencies.world.dispose(), + ); } - Reporter _registerReporters(Iterable reporters) { + Reporter _registerReporters(Iterable? reporters) { final reporter = AggregatedReporter(); if (reporters != null) { reporters.forEach((r) => reporter.addReporter(r)); @@ -293,7 +296,7 @@ abstract class GherkinIntegrationTestRunner { return reporter; } - Hook _registerHooks(Iterable hooks) { + Hook _registerHooks(Iterable? hooks) { final hook = AggregatedHook(); if (hooks != null) { hook.addHooks(hooks); @@ -303,7 +306,7 @@ abstract class GherkinIntegrationTestRunner { } Iterable _registerCustomParameters( - Iterable customParameters, + Iterable? customParameters, ) { final parameters = []; @@ -332,7 +335,7 @@ abstract class GherkinIntegrationTestRunner { return stepDefinitions .map( (s) => ExecutableStep( - GherkinExpression(s.pattern, customParameters), + GherkinExpression(s.pattern as RegExp, customParameters), s, ), ) @@ -362,12 +365,13 @@ abstract class GherkinIntegrationTestRunner { StepResult result, TestDependencies dependencies, ) async { - await _hook.onAfterStep( + await hook.onAfterStep( dependencies.world, step, result, ); - await _reporter.onStepFinished( + + await reporter.onStepFinished( StepFinishedMessage( step, RunnableDebugInformation('', 0, step), @@ -383,7 +387,7 @@ abstract class GherkinIntegrationTestRunner { table, Iterable multiLineStrings, ) async { - await _hook.onBeforeStep(world, step); + await hook.onBeforeStep(world, step); await reporter.onStepStarted( StepStartedMessage( step, @@ -402,11 +406,11 @@ abstract class GherkinIntegrationTestRunner { } bool _evaluateTagFilterExpression( - String tagExpression, - List tags, + String? tagExpression, + Iterable? tags, ) { return tagExpression == null || tagExpression.isEmpty ? true - : _tagExpressionEvaluator.evaluate(tagExpression, tags); + : _tagExpressionEvaluator.evaluate(tagExpression, tags!.toList()); } } diff --git a/lib/src/flutter/steps/given_i_open_the_drawer_step.dart b/lib/src/flutter/steps/given_i_open_the_drawer_step.dart index 4d5388a..ec7a258 100644 --- a/lib/src/flutter/steps/given_i_open_the_drawer_step.dart +++ b/lib/src/flutter/steps/given_i_open_the_drawer_step.dart @@ -34,7 +34,7 @@ StepDefinitionGeneric GivenOpenDrawer() { 'Open navigation menu', FindType.tooltip, ), - timeout: context.configuration?.timeout, + timeout: context.configuration.timeout, ); } diff --git a/lib/src/flutter/steps/restart_app_step.dart b/lib/src/flutter/steps/restart_app_step.dart index ecb924b..e0602eb 100644 --- a/lib/src/flutter/steps/restart_app_step.dart +++ b/lib/src/flutter/steps/restart_app_step.dart @@ -6,7 +6,7 @@ StepDefinitionGeneric RestartAppStep() { 'I restart the app', (context) async { await context.world.restartApp( - timeout: context.configuration?.timeout, + timeout: context.configuration.timeout, ); }, ); diff --git a/lib/src/flutter/steps/sibling_contains_text_step.dart b/lib/src/flutter/steps/sibling_contains_text_step.dart index 2d4bab2..4bb167d 100644 --- a/lib/src/flutter/steps/sibling_contains_text_step.dart +++ b/lib/src/flutter/steps/sibling_contains_text_step.dart @@ -31,7 +31,7 @@ StepDefinitionGeneric SiblingContainsTextStep() { final isPresent = await context.world.appDriver.isPresent( valueWidget, - timeout: context.configuration?.timeout ?? const Duration(seconds: 20), + timeout: context.configuration.timeout ?? const Duration(seconds: 20), ); context.expect(isPresent, true); 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 c434fef..08d2176 100644 --- a/lib/src/flutter/steps/tap_text_within_widget_step.dart +++ b/lib/src/flutter/steps/tap_text_within_widget_step.dart @@ -14,7 +14,7 @@ StepDefinitionGeneric TapTextWithinWidgetStep() { 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); + 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/world/flutter_driver_world.dart b/lib/src/flutter/world/flutter_driver_world.dart index 2b0ed81..7575f4b 100644 --- a/lib/src/flutter/world/flutter_driver_world.dart +++ b/lib/src/flutter/world/flutter_driver_world.dart @@ -1,12 +1,12 @@ import 'package:flutter_driver/flutter_driver.dart'; -import 'package:flutter_gherkin/flutter_gherkin.dart'; +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 { - FlutterRunProcessHandler _flutterRunProcessHandler; + FlutterRunProcessHandler? _flutterRunProcessHandler; void setFlutterDriver(FlutterDriver flutterDriver) { setAppAdapter(FlutterDriverAppDriverAdapter(flutterDriver)); @@ -20,7 +20,7 @@ class FlutterDriverWorld extends FlutterTypedAdapterWorld restartApp({ - Duration timeout = const Duration(seconds: 60), + Duration? timeout = const Duration(seconds: 60), }) async { await _closeDriver(timeout: timeout); final result = await _flutterRunProcessHandler?.restart( @@ -28,12 +28,12 @@ class FlutterDriverWorld extends FlutterTypedAdapterWorld _closeDriver({ - Duration timeout = const Duration(seconds: 60), + Duration? timeout = const Duration(seconds: 60), }) async { + // ignore: unnecessary_null_comparison if (rawAppDriver != null) { await rawAppDriver.close().catchError( (e, st) { diff --git a/lib/src/flutter/world/flutter_widget_tester_world.dart b/lib/src/flutter/world/flutter_widget_tester_world.dart index 675777f..a3125dc 100644 --- a/lib/src/flutter/world/flutter_widget_tester_world.dart +++ b/lib/src/flutter/world/flutter_widget_tester_world.dart @@ -1,6 +1,6 @@ import 'package:flutter/widgets.dart'; import 'package:flutter_test/flutter_test.dart'; -import 'package:flutter_gherkin/flutter_gherkin_integration_test.dart'; +import 'package:flutter_gherkin/flutter_gherkin.dart'; /// The world object that can be used to store state during a single test. /// It also allows interaction with the app under test through the `appDriver` diff --git a/lib/src/flutter/world/flutter_world.dart b/lib/src/flutter/world/flutter_world.dart index 3ddb568..e92d2fc 100644 --- a/lib/src/flutter/world/flutter_world.dart +++ b/lib/src/flutter/world/flutter_world.dart @@ -7,10 +7,10 @@ import '../adapters/app_driver_adapter.dart'; /// It also allows interaction with the app under test through the `appDriver` /// which exposes an instance of `AppDriverAdapter` class FlutterWorld extends World { - AppDriverAdapter _adapter; + AppDriverAdapter? _adapter; /// The adapter that is used to agnostically drive the app under test - AppDriverAdapter get appDriver => _adapter; + AppDriverAdapter get appDriver => _adapter!; /// Sets the app driver that is used to control the app under test void setAppAdapter(AppDriverAdapter appAdapter) { @@ -19,7 +19,7 @@ class FlutterWorld extends World { /// Restart the app under test Future restartApp({ - Duration timeout = const Duration(seconds: 60), + Duration? timeout = const Duration(seconds: 60), }) { throw UnimplementedError('Unable to restart the app during the test'); } @@ -34,7 +34,7 @@ class FlutterTypedAdapterWorld extends FlutterWorld { /// It is suggested you use `appDriver` for all interactions with the app under tests /// however if you need a specific api not available on `appDriver` this property /// exposes the actual class that can interact with the app under test - TDriver get rawAppDriver => _adapter.rawDriver as TDriver; + TDriver get rawAppDriver => _adapter!.rawDriver as TDriver; /// The adapter that is used to agnostically drive the app under test @override diff --git a/pubspec.lock b/pubspec.lock index 6b006f1..ac31c84 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -7,14 +7,14 @@ packages: name: _fe_analyzer_shared url: "https://pub.dartlang.org" source: hosted - version: "12.0.0" + version: "21.0.0" analyzer: - dependency: "direct main" + dependency: transitive description: name: analyzer url: "https://pub.dartlang.org" source: hosted - version: "0.40.6" + version: "1.5.0" archive: dependency: transitive description: @@ -35,112 +35,112 @@ packages: name: async url: "https://pub.dartlang.org" source: hosted - version: "2.5.0-nullsafety.1" + version: "2.5.0" boolean_selector: dependency: transitive description: name: boolean_selector url: "https://pub.dartlang.org" source: hosted - version: "2.1.0-nullsafety.1" + version: "2.1.0" build: - dependency: "direct main" + dependency: "direct dev" description: name: build url: "https://pub.dartlang.org" source: hosted - version: "1.6.2" + version: "2.0.1" build_config: - dependency: "direct main" + dependency: "direct dev" description: name: build_config url: "https://pub.dartlang.org" source: hosted - version: "0.4.5" + version: "1.0.0" characters: dependency: transitive description: name: characters url: "https://pub.dartlang.org" source: hosted - version: "1.1.0-nullsafety.3" + version: "1.1.0" charcode: dependency: transitive description: name: charcode url: "https://pub.dartlang.org" source: hosted - version: "1.2.0-nullsafety.1" + version: "1.2.0" checked_yaml: dependency: transitive description: name: checked_yaml url: "https://pub.dartlang.org" source: hosted - version: "1.0.4" + version: "2.0.1" cli_util: dependency: transitive description: name: cli_util url: "https://pub.dartlang.org" source: hosted - version: "0.2.0" + version: "0.3.0" clock: dependency: transitive description: name: clock url: "https://pub.dartlang.org" source: hosted - version: "1.1.0-nullsafety.1" + version: "1.1.0" collection: dependency: transitive description: name: collection url: "https://pub.dartlang.org" source: hosted - version: "1.15.0-nullsafety.3" + version: "1.15.0" convert: - dependency: transitive + dependency: "direct overridden" description: name: convert url: "https://pub.dartlang.org" source: hosted - version: "2.1.1" + version: "3.0.0" coverage: dependency: transitive description: name: coverage url: "https://pub.dartlang.org" source: hosted - version: "0.14.2" + version: "0.15.2" crypto: - dependency: transitive + dependency: "direct overridden" description: name: crypto url: "https://pub.dartlang.org" source: hosted - version: "2.1.5" + version: "3.0.1" dart_style: dependency: transitive description: name: dart_style url: "https://pub.dartlang.org" source: hosted - version: "1.3.10" + version: "2.0.1" fake_async: dependency: transitive description: name: fake_async url: "https://pub.dartlang.org" source: hosted - version: "1.2.0-nullsafety.1" + version: "1.2.0" file: dependency: transitive description: name: file url: "https://pub.dartlang.org" source: hosted - version: "6.0.0-nullsafety.2" + version: "6.0.0" flutter: dependency: "direct main" description: flutter @@ -164,117 +164,85 @@ packages: gherkin: dependency: "direct main" description: - path: "." - ref: f0b3f955191b53a78075ed2c9387ea8bee12f111 - resolved-ref: f0b3f955191b53a78075ed2c9387ea8bee12f111 - url: "https://github.com/jonsamwell/dart_gherkin.git" - source: git - version: "1.1.10" + name: gherkin + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.0" glob: - dependency: "direct main" + dependency: "direct dev" description: name: glob url: "https://pub.dartlang.org" source: hosted - version: "1.2.0" - http: - dependency: transitive - description: - name: http - url: "https://pub.dartlang.org" - source: hosted - version: "0.12.2" + version: "2.0.1" http_multi_server: dependency: transitive description: name: http_multi_server url: "https://pub.dartlang.org" source: hosted - version: "2.2.0" + version: "3.0.1" http_parser: dependency: transitive description: name: http_parser url: "https://pub.dartlang.org" source: hosted - version: "3.1.4" + version: "4.0.0" integration_test: - dependency: "direct main" - description: - name: integration_test - url: "https://pub.dartlang.org" - source: hosted - version: "1.0.2+2" + dependency: "direct dev" + description: flutter + source: sdk + version: "0.9.2+2" io: dependency: transitive description: name: io url: "https://pub.dartlang.org" source: hosted - version: "0.3.4" + version: "1.0.0" js: dependency: transitive description: name: js url: "https://pub.dartlang.org" source: hosted - version: "0.6.3-nullsafety.2" + version: "0.6.3" json_annotation: dependency: transitive description: name: json_annotation url: "https://pub.dartlang.org" source: hosted - version: "3.1.1" - json_rpc_2: - dependency: transitive - description: - name: json_rpc_2 - url: "https://pub.dartlang.org" - source: hosted - version: "2.2.2" + version: "4.0.1" logging: dependency: transitive description: name: logging url: "https://pub.dartlang.org" source: hosted - version: "0.11.4" + version: "1.0.1" matcher: dependency: transitive description: name: matcher url: "https://pub.dartlang.org" source: hosted - version: "0.12.10-nullsafety.1" + version: "0.12.10" meta: - dependency: "direct main" + dependency: "direct dev" description: name: meta url: "https://pub.dartlang.org" source: hosted - version: "1.3.0-nullsafety.3" + version: "1.3.0" mime: dependency: transitive description: name: mime url: "https://pub.dartlang.org" source: hosted - version: "0.9.7" - node_interop: - dependency: transitive - description: - name: node_interop - url: "https://pub.dartlang.org" - source: hosted - version: "1.2.1" - node_io: - dependency: transitive - description: - name: node_io - url: "https://pub.dartlang.org" - source: hosted - version: "1.1.1" + version: "1.0.0" node_preamble: dependency: transitive description: @@ -288,138 +256,138 @@ packages: name: package_config url: "https://pub.dartlang.org" source: hosted - version: "1.9.3" + version: "2.0.0" path: dependency: transitive description: name: path url: "https://pub.dartlang.org" source: hosted - version: "1.8.0-nullsafety.1" + version: "1.8.0" pedantic: dependency: "direct dev" description: name: pedantic url: "https://pub.dartlang.org" source: hosted - version: "1.10.0-nullsafety.2" + version: "1.11.0" platform: dependency: transitive description: name: platform url: "https://pub.dartlang.org" source: hosted - version: "3.0.0-nullsafety.2" + version: "3.0.0" pool: dependency: transitive description: name: pool url: "https://pub.dartlang.org" source: hosted - version: "1.5.0-nullsafety.2" + version: "1.5.0" process: dependency: transitive description: name: process url: "https://pub.dartlang.org" source: hosted - version: "4.0.0-nullsafety.2" + version: "4.0.0" pub_semver: dependency: transitive description: name: pub_semver url: "https://pub.dartlang.org" source: hosted - version: "1.4.4" + version: "2.0.0" pubspec_parse: dependency: transitive description: name: pubspec_parse url: "https://pub.dartlang.org" source: hosted - version: "0.1.8" + version: "1.0.0" shelf: dependency: transitive description: name: shelf url: "https://pub.dartlang.org" source: hosted - version: "0.7.9" + version: "1.1.1" shelf_packages_handler: dependency: transitive description: name: shelf_packages_handler url: "https://pub.dartlang.org" source: hosted - version: "2.0.1" + version: "3.0.0" shelf_static: dependency: transitive description: name: shelf_static url: "https://pub.dartlang.org" source: hosted - version: "0.2.9+2" + version: "1.0.0" shelf_web_socket: dependency: transitive description: name: shelf_web_socket url: "https://pub.dartlang.org" source: hosted - version: "0.2.4" + version: "1.0.1" sky_engine: dependency: transitive description: flutter source: sdk version: "0.0.99" source_gen: - dependency: "direct main" + dependency: "direct dev" description: name: source_gen url: "https://pub.dartlang.org" source: hosted - version: "0.9.10+1" + version: "1.0.0" source_map_stack_trace: dependency: transitive description: name: source_map_stack_trace url: "https://pub.dartlang.org" source: hosted - version: "2.1.0-nullsafety.3" + version: "2.1.0" source_maps: dependency: transitive description: name: source_maps url: "https://pub.dartlang.org" source: hosted - version: "0.10.10-nullsafety.2" + version: "0.10.10" source_span: dependency: transitive description: name: source_span url: "https://pub.dartlang.org" source: hosted - version: "1.8.0-nullsafety.2" + version: "1.8.0" stack_trace: dependency: transitive description: name: stack_trace url: "https://pub.dartlang.org" source: hosted - version: "1.10.0-nullsafety.1" + version: "1.10.0" stream_channel: dependency: transitive description: name: stream_channel url: "https://pub.dartlang.org" source: hosted - version: "2.1.0-nullsafety.1" + version: "2.1.0" string_scanner: dependency: transitive description: name: string_scanner url: "https://pub.dartlang.org" source: hosted - version: "1.1.0-nullsafety.1" + version: "1.1.0" sync_http: dependency: transitive description: @@ -433,42 +401,42 @@ packages: name: term_glyph url: "https://pub.dartlang.org" source: hosted - version: "1.2.0-nullsafety.1" + version: "1.2.0" test: dependency: "direct dev" description: name: test url: "https://pub.dartlang.org" source: hosted - version: "1.16.0-nullsafety.5" + version: "1.16.5" test_api: - dependency: transitive + dependency: "direct overridden" description: name: test_api url: "https://pub.dartlang.org" source: hosted - version: "0.2.19-nullsafety.2" + version: "0.3.0" test_core: dependency: transitive description: name: test_core url: "https://pub.dartlang.org" source: hosted - version: "0.3.12-nullsafety.5" + version: "0.3.15" typed_data: dependency: transitive description: name: typed_data url: "https://pub.dartlang.org" source: hosted - version: "1.3.0-nullsafety.3" + version: "1.3.0" vector_math: dependency: transitive description: name: vector_math url: "https://pub.dartlang.org" source: hosted - version: "2.1.0-nullsafety.3" + version: "2.1.0" vm_service: dependency: transitive description: @@ -476,27 +444,20 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "5.5.0" - vm_service_client: - dependency: transitive - description: - name: vm_service_client - url: "https://pub.dartlang.org" - source: hosted - version: "0.2.6+2" watcher: dependency: transitive description: name: watcher url: "https://pub.dartlang.org" source: hosted - version: "0.9.7+15" + version: "1.0.0" web_socket_channel: dependency: transitive description: name: web_socket_channel url: "https://pub.dartlang.org" source: hosted - version: "1.1.0" + version: "2.0.0" webdriver: dependency: transitive description: @@ -510,14 +471,14 @@ packages: name: webkit_inspection_protocol url: "https://pub.dartlang.org" source: hosted - version: "0.7.5" + version: "1.0.0" yaml: dependency: transitive description: name: yaml url: "https://pub.dartlang.org" source: hosted - version: "2.2.1" + version: "3.1.0" sdks: - dart: ">=2.10.0 <2.11.0" - flutter: ">=1.17.0" + dart: ">=2.12.3 <3.0.0" + flutter: ">=2.0.0" diff --git a/pubspec.yaml b/pubspec.yaml index 2d27bf7..dde28cc 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -4,8 +4,8 @@ version: 1.2.0 homepage: https://github.com/jonsamwell/flutter_gherkin environment: - sdk: ">=2.7.0 <3.0.0" - flutter: ">=1.17.0" + sdk: '>=2.12.3 <3.0.0' + flutter: ">=2.0.0" dependencies: flutter: @@ -14,24 +14,29 @@ dependencies: sdk: flutter flutter_driver: sdk: flutter - analyzer: ">=0.37.0 <0.41.0" - glob: ^1.1.7 - meta: ">=1.1.6 <2.0.0" - source_gen: ^0.9.10+1 - build: ^1.6.0 - build_config: ^0.4.5 - integration_test: ^1.0.1 - # gherkin: ^1.1.9 + gherkin: ^2.0.0 # gherkin: # path: ../dart_gherkin - gherkin: - git: - url: https://github.com/jonsamwell/dart_gherkin.git - ref: f0b3f955191b53a78075ed2c9387ea8bee12f111 - # ref: code_gen_changes + # gherkin: + # git: + # url: https://github.com/jonsamwell/dart_gherkin.git + # ref: f0b3f955191b53a78075ed2c9387ea8bee12f111 + +dependency_overrides: + crypto: ^3.0.0 # flutter_driver still depends on 2.1.5 :-( + convert: ^3.0.0 # flutter_driver still depends on >=2.0.0 :-( + test: ^1.16.5 # gherkin still depends on 1.16.8 :-( + test_api: ^0.3.0 # flutter_test still depends on 0.2.19 :-( dev_dependencies: - test: - pedantic: ^1.9.2 + integration_test: + sdk: flutter + test: ^1.16.5 + meta: ^1.3.0 + pedantic: ^1.11.0 + glob: ^2.0.1 + source_gen: ^1.0.0 + build: ^2.0.1 + build_config: ^1.0.0 flutter: diff --git a/test/flutter_configuration_test.dart b/test/flutter_configuration_test.dart index 89dbe04..2b20a51 100644 --- a/test/flutter_configuration_test.dart +++ b/test/flutter_configuration_test.dart @@ -1,4 +1,4 @@ -import 'package:flutter_gherkin/flutter_gherkin.dart'; +import 'package:flutter_gherkin/flutter_gherkin_with_driver.dart'; import 'package:flutter_gherkin/src/flutter/hooks/app_runner_hook.dart'; import 'package:test/test.dart'; @@ -13,8 +13,8 @@ void main() { expect(config.hooks, isNull); config.prepare(); expect(config.hooks, isNotNull); - expect(config.hooks.length, 1); - expect(config.hooks.elementAt(0), (x) => x is FlutterAppRunnerHook); + expect(config.hooks!.length, 1); + expect(config.hooks!.elementAt(0), (x) => x is FlutterAppRunnerHook); }); test('common steps definition added', () { @@ -23,25 +23,25 @@ void main() { config.prepare(); expect(config.stepDefinitions, isNotNull); - expect(config.stepDefinitions.length, 23); + expect(config.stepDefinitions!.length, 23); expect(config.customStepParameterDefinitions, isNotNull); - expect(config.customStepParameterDefinitions.length, 2); + expect(config.customStepParameterDefinitions!.length, 2); }); test('common step definition added to existing steps', () { final config = FlutterTestConfiguration() ..stepDefinitions = [MockStepDefinition()] ..customStepParameterDefinitions = [MockParameter()]; - expect(config.stepDefinitions.length, 1); + expect(config.stepDefinitions!.length, 1); config.prepare(); expect(config.stepDefinitions, isNotNull); - expect(config.stepDefinitions.length, 24); - expect(config.stepDefinitions.elementAt(0), + expect(config.stepDefinitions!.length, 24); + expect(config.stepDefinitions!.elementAt(0), (x) => x is MockStepDefinition); expect(config.customStepParameterDefinitions, isNotNull); - expect(config.customStepParameterDefinitions.length, 3); - expect(config.customStepParameterDefinitions.elementAt(0), + expect(config.customStepParameterDefinitions!.length, 3); + expect(config.customStepParameterDefinitions!.elementAt(0), (x) => x is MockParameter); }); }); diff --git a/test/mocks/step_definition_mock.dart b/test/mocks/step_definition_mock.dart index 820c76f..c1197fa 100644 --- a/test/mocks/step_definition_mock.dart +++ b/test/mocks/step_definition_mock.dart @@ -5,7 +5,7 @@ typedef OnRunCode = Future Function(Iterable parameters); class MockStepDefinition extends StepDefinitionBase { bool hasRun = false; int runCount = 0; - final OnRunCode code; + final OnRunCode? code; MockStepDefinition([this.code, int expectedParameterCount = 0]) : super(null, expectedParameterCount); @@ -15,10 +15,10 @@ class MockStepDefinition extends StepDefinitionBase { hasRun = true; runCount += 1; if (code != null) { - await code(parameters); + await code!(parameters); } } @override - RegExp get pattern => null; + RegExp get pattern => RegExp(''); }