rsflutterapp

Bahnhofsfoto-App for Android and iOS using Flutter
git clone git://archive.git.mtrnord.blog/MTRNord/rsflutterapp.git
Log | Files | Refs | README

commit b0f4f75a489716ae140057ce793a6a35e3c0abe9
parent 6bb7fadb20c32ae33aaad991e1735b3c37638176
Author: Marcel <mtrnord1@gmail.com>
Date:   Fri, 21 Feb 2020 19:15:04 +0100

Fix tests

Diffstat:
Mlib/main.dart | 9---------
Mpubspec.lock | 299++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
Mpubspec.yaml | 3+++
Atest/utils.dart | 121+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mtest/widget_test.dart | 19+------------------
Atest_driver/app.dart | 11+++++++++++
Atest_driver/app_test.dart | 48++++++++++++++++++++++++++++++++++++++++++++++++
7 files changed, 482 insertions(+), 28 deletions(-)

diff --git a/lib/main.dart b/lib/main.dart @@ -9,15 +9,6 @@ class MyApp extends StatelessWidget { return MaterialApp( title: 'Bahnhofsfotos', theme: ThemeData( - // This is the theme of your application. - // - // Try running your application with "flutter run". You'll see the - // application has a blue toolbar. Then, without quitting the app, try - // changing the primarySwatch below to Colors.green and then invoke - // "hot reload" (press "r" in the console where you ran "flutter run", - // or simply save your changes to "hot reload" in a Flutter IDE). - // Notice that the counter didn't reset back to zero; the application - // is not restarted. primarySwatch: Colors.blue, ), home: Container(), diff --git a/pubspec.lock b/pubspec.lock @@ -1,6 +1,20 @@ # Generated by pub # See https://dart.dev/tools/pub/glossary#lockfile packages: + _fe_analyzer_shared: + dependency: transitive + description: + name: _fe_analyzer_shared + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.3" + analyzer: + dependency: transitive + description: + name: analyzer + url: "https://pub.dartlang.org" + source: hosted + version: "0.39.4" archive: dependency: transitive description: @@ -50,6 +64,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.1.1" + coverage: + dependency: transitive + description: + name: coverage + url: "https://pub.dartlang.org" + source: hosted + version: "0.13.6" crypto: dependency: transitive description: @@ -57,6 +78,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.1.3" + csslib: + dependency: transitive + description: + name: csslib + url: "https://pub.dartlang.org" + source: hosted + version: "0.16.1" cupertino_icons: dependency: "direct main" description: @@ -64,16 +92,68 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "0.1.3" + file: + dependency: transitive + description: + name: file + url: "https://pub.dartlang.org" + source: hosted + version: "5.1.0" flutter: dependency: "direct main" description: flutter source: sdk version: "0.0.0" + flutter_driver: + dependency: "direct dev" + description: flutter + source: sdk + version: "0.0.0" flutter_test: dependency: "direct dev" description: flutter source: sdk version: "0.0.0" + fuchsia_remote_debug_protocol: + dependency: transitive + description: flutter + source: sdk + version: "0.0.0" + glob: + dependency: transitive + description: + name: glob + url: "https://pub.dartlang.org" + source: hosted + version: "1.2.0" + html: + dependency: transitive + description: + name: html + url: "https://pub.dartlang.org" + source: hosted + version: "0.14.0+3" + http: + dependency: transitive + description: + name: http + url: "https://pub.dartlang.org" + source: hosted + version: "0.12.0+4" + http_multi_server: + dependency: transitive + description: + name: http_multi_server + url: "https://pub.dartlang.org" + source: hosted + version: "2.2.0" + http_parser: + dependency: transitive + description: + name: http_parser + url: "https://pub.dartlang.org" + source: hosted + version: "3.1.3" image: dependency: transitive description: @@ -81,6 +161,41 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.1.4" + intl: + dependency: transitive + description: + name: intl + url: "https://pub.dartlang.org" + source: hosted + version: "0.16.1" + io: + dependency: transitive + description: + name: io + url: "https://pub.dartlang.org" + source: hosted + version: "0.3.3" + js: + dependency: transitive + description: + name: js + url: "https://pub.dartlang.org" + source: hosted + version: "0.6.1+1" + json_rpc_2: + dependency: transitive + description: + name: json_rpc_2 + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.0" + logging: + dependency: transitive + description: + name: logging + url: "https://pub.dartlang.org" + source: hosted + version: "0.11.4" matcher: dependency: transitive description: @@ -95,6 +210,55 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.1.8" + mime: + dependency: transitive + description: + name: mime + url: "https://pub.dartlang.org" + source: hosted + version: "0.9.6+3" + multi_server_socket: + dependency: transitive + description: + name: multi_server_socket + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.2" + node_interop: + dependency: transitive + description: + name: node_interop + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.3" + node_io: + dependency: transitive + description: + name: node_io + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.1+2" + node_preamble: + dependency: transitive + description: + name: node_preamble + url: "https://pub.dartlang.org" + source: hosted + version: "1.4.8" + package_config: + dependency: transitive + description: + name: package_config + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.0" + package_resolver: + dependency: transitive + description: + name: package_resolver + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.10" path: dependency: transitive description: @@ -116,6 +280,34 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.4.0" + platform: + dependency: transitive + description: + name: platform + url: "https://pub.dartlang.org" + source: hosted + version: "2.2.1" + pool: + dependency: transitive + description: + name: pool + url: "https://pub.dartlang.org" + source: hosted + version: "1.4.0" + process: + dependency: transitive + description: + name: process + url: "https://pub.dartlang.org" + source: hosted + version: "3.0.12" + pub_semver: + dependency: transitive + description: + name: pub_semver + url: "https://pub.dartlang.org" + source: hosted + version: "1.4.2" quiver: dependency: transitive description: @@ -123,11 +315,53 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.0.5" + shelf: + dependency: transitive + description: + name: shelf + url: "https://pub.dartlang.org" + source: hosted + version: "0.7.5" + shelf_packages_handler: + dependency: transitive + description: + name: shelf_packages_handler + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.4" + shelf_static: + dependency: transitive + description: + name: shelf_static + url: "https://pub.dartlang.org" + source: hosted + version: "0.2.8" + shelf_web_socket: + dependency: transitive + description: + name: shelf_web_socket + url: "https://pub.dartlang.org" + source: hosted + version: "0.2.3" sky_engine: dependency: transitive description: flutter source: sdk version: "0.0.99" + source_map_stack_trace: + dependency: transitive + description: + name: source_map_stack_trace + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.5" + source_maps: + dependency: transitive + description: + name: source_maps + url: "https://pub.dartlang.org" + source: hosted + version: "0.10.9" source_span: dependency: transitive description: @@ -156,6 +390,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.0.5" + sync_http: + dependency: transitive + description: + name: sync_http + url: "https://pub.dartlang.org" + source: hosted + version: "0.1.4" term_glyph: dependency: transitive description: @@ -163,6 +404,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.1.0" + test: + dependency: "direct dev" + description: + name: test + url: "https://pub.dartlang.org" + source: hosted + version: "1.9.4" test_api: dependency: transitive description: @@ -170,6 +418,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "0.2.11" + test_core: + dependency: transitive + description: + name: test_core + url: "https://pub.dartlang.org" + source: hosted + version: "0.2.15" typed_data: dependency: transitive description: @@ -184,6 +439,41 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.0.8" + vm_service: + dependency: transitive + description: + name: vm_service + url: "https://pub.dartlang.org" + source: hosted + version: "2.3.1" + 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+13" + web_socket_channel: + dependency: transitive + description: + name: web_socket_channel + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.0" + webdriver: + dependency: transitive + description: + name: webdriver + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.1" xml: dependency: transitive description: @@ -191,5 +481,12 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "3.5.0" + yaml: + dependency: transitive + description: + name: yaml + url: "https://pub.dartlang.org" + source: hosted + version: "2.2.0" sdks: - dart: ">=2.4.0 <3.0.0" + dart: ">=2.6.0 <3.0.0" diff --git a/pubspec.yaml b/pubspec.yaml @@ -28,6 +28,9 @@ dev_dependencies: flutter_test: sdk: flutter + flutter_driver: + sdk: flutter + test: any # For information on the generic Dart part of this file, see the # following page: https://dart.dev/tools/pub/pubspec diff --git a/test/utils.dart b/test/utils.dart @@ -0,0 +1,121 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; + +class Utils { + static printWidgets(WidgetTester tester) { + debugPrint(tester.allWidgets.toList().join("\n").toString()); + } + + static bool isWidgetInWidgets(WidgetTester tester, Type widget) { + debugPrint(tester.allWidgets + .toList() + .map((e) => e.runtimeType) + .join("\n") + .toString()); + return tester.allWidgets + .toList() + .map((e) => e.runtimeType) + .contains(widget); + } + + static Widget getWidgetWrapper(Widget child, TestObserver routeObserver) { + return MaterialApp( + title: "Fluffychat", + theme: ThemeData( + primarySwatch: Colors.blue, + ), + navigatorObservers: <NavigatorObserver>[routeObserver], + home: child, + ); + } + + static double getOpacity(WidgetTester tester, String textValue) { + final FadeTransition opacityWidget = tester.widget<FadeTransition>(find + .ancestor( + of: find.text(textValue), + matching: find.byType(FadeTransition), + ) + .first); + return opacityWidget.opacity.value; + } + + static Future<Null> tapItem(WidgetTester tester, Key key) async { + /// Tap the button which should open the PopupMenu. + /// By calling tester.pumpAndSettle(), we ensure that all animations + /// have completed before we continue further. + await tester.tap(find.byKey(key)); + await tester.pumpAndSettle(); + } +} + +typedef OnObservation = void Function( + Route<dynamic> route, Route<dynamic> previousRoute); + +/// Example Usage: +/// +/// ``` +/// bool isPushed = false; +// bool isPopped = false; +// +// final TestObserver observer = TestObserver() +// ..onPushed = (Route<dynamic> route, Route<dynamic> previousRoute) { +// // Pushes the initial route. +// expect(route is PageRoute && route.settings.name == '/', isTrue); +// expect(previousRoute, isNull); +// isPushed = true; +// } +// ..onPopped = (Route<dynamic> route, Route<dynamic> previousRoute) { +// isPopped = true; +// }; +/// ``` +/// +class TestObserver extends NavigatorObserver { + OnObservation onPushed; + OnObservation onPopped; + OnObservation onRemoved; + OnObservation onReplaced; + + @override + void didPush(Route<dynamic> route, Route<dynamic> previousRoute) { + if (onPushed != null) { + onPushed(route, previousRoute); + } + } + + @override + void didPop(Route<dynamic> route, Route<dynamic> previousRoute) { + if (onPopped != null) { + onPopped(route, previousRoute); + } + } + + @override + void didRemove(Route<dynamic> route, Route<dynamic> previousRoute) { + if (onRemoved != null) onRemoved(route, previousRoute); + } + + @override + void didReplace({Route<dynamic> oldRoute, Route<dynamic> newRoute}) { + if (onReplaced != null) onReplaced(newRoute, oldRoute); + } +} + +class RouteMatcher extends Matcher { + final String expected; + bool contains = false; + + RouteMatcher(this.expected, {this.contains}); + + @override + Description describe(Description description) { + return null; + } + + @override + bool matches(covariant String item, Map matchState) { + if (contains) { + return item.toString().contains(expected); + } + return item == expected; + } +} diff --git a/test/widget_test.dart b/test/widget_test.dart @@ -10,21 +10,4 @@ import 'package:flutter_test/flutter_test.dart'; import 'package:rs_flutter_app/main.dart'; -void main() { - testWidgets('Counter increments smoke test', (WidgetTester tester) async { - // Build our app and trigger a frame. - await tester.pumpWidget(MyApp()); - - // Verify that our counter starts at 0. - expect(find.text('0'), findsOneWidget); - expect(find.text('1'), findsNothing); - - // Tap the '+' icon and trigger a frame. - await tester.tap(find.byIcon(Icons.add)); - await tester.pump(); - - // Verify that our counter has incremented. - expect(find.text('0'), findsNothing); - expect(find.text('1'), findsOneWidget); - }); -} +void main() {} diff --git a/test_driver/app.dart b/test_driver/app.dart @@ -0,0 +1,11 @@ +import 'package:rs_flutter_app/main.dart' as app; +import 'package:flutter_driver/driver_extension.dart'; + +void main() { + // This line enables the extension + enableFlutterDriverExtension(); + + // Call the `main()` function of your app or call `runApp` with any widget you + // are interested in testing. + app.main(); +} diff --git a/test_driver/app_test.dart b/test_driver/app_test.dart @@ -0,0 +1,48 @@ +// Imports the Flutter Driver API +import 'package:flutter_driver/flutter_driver.dart'; +import 'package:test/test.dart'; + +void main() { + group('Bahnhofsfotos App', () { + FlutterDriver driver; + final String backButtonToolTip = "Back"; // Set to your preferred language + + // Connect to the Flutter driver before running any tests + setUpAll(() async { + driver = await FlutterDriver.connect(); + }); + + // Close the connection to the driver after the tests have completed + tearDownAll(() async { + if (driver != null) { + await driver.close(); + } + }); + + var waitFor = (String key) async { + print("[Integration Test] Wait for $key"); + await driver.waitFor(find.byValueKey(key)); + }; + + var tap = (String key) async { + print("[Integration Test] Tap on $key"); + await driver.waitFor(find.byValueKey(key)); + await driver.tap(find.byValueKey(key)); + }; + + var tapOnText = (String text) async { + print("[Integration Test] Tap on $text"); + await driver.waitFor(find.text(text)); + await driver.tap(find.text(text)); + }; + + var enterText = (String text) async { + print("[Integration Test] Enter text: $text"); + await driver.enterText(text); + }; + var goBack = () async { + await driver.waitFor(find.byTooltip(backButtonToolTip)); + await driver.tap(find.byTooltip(backButtonToolTip)); + }; + }); +}