diff --git a/.cirrus.yml b/.cirrus.yml index 1236002fecd6..753bc90911ae 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -6,6 +6,8 @@ task: dockerfile: .ci/Dockerfile cpu: 8 memory: 16G + env: + E2E_PATH: "./packages/e2e" upgrade_script: - flutter channel stable - flutter upgrade @@ -45,6 +47,19 @@ task: - if [[ "$CHANNEL" -eq "stable" ]]; then find . | grep _web$ | xargs rm -rf; fi - flutter channel $CHANNEL - ./script/build_all_plugins_app.sh apk + - name: e2e_web_smoke_test + # Tests e2e example test in web. + only_if: "changesInclude('.cirrus.yml', 'packages/e2e/**') || $CIRRUS_PR == ''" + install_script: + - flutter config --enable-web + - git clone https://github.com/flutter/web_installers.git + - cd web_installers/packages/web_drivers/ + - pub get + - dart lib/web_driver_installer.dart chromedriver --install-only + - ./chromedriver/chromedriver --port=4444 & + test_script: + - cd $E2E_PATH/example/ + - flutter drive -v --target=test_driver/example_e2e.dart -d web-server --release --browser-name=chrome - name: build-apks+java-test+firebase-test-lab env: matrix: diff --git a/packages/e2e/CHANGELOG.md b/packages/e2e/CHANGELOG.md index 35d3159e05b4..86f37b291549 100644 --- a/packages/e2e/CHANGELOG.md +++ b/packages/e2e/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.2.4+4 + +* Fixed a hang that occurred on platforms that don't have a `MethodChannel` listener registered.. + ## 0.2.4+3 * Fixed code snippet in the readme under the "Using Flutter driver to run tests" section. diff --git a/packages/e2e/README.md b/packages/e2e/README.md index ed892ab6e7ff..3e27ff36afa3 100644 --- a/packages/e2e/README.md +++ b/packages/e2e/README.md @@ -69,6 +69,15 @@ cd example flutter drive --driver=test_driver/_test.dart test/_e2e.dart ``` +You can run tests on web on release mode. + +First you need to make sure you have downloaded the driver for the browser. + +``` +cd example +flutter drive -v --target=test_driver/dart -d web-server --release --browser-name=chrome +``` + ## Android device testing Create an instrumentation test file in your application's diff --git a/packages/e2e/example/lib/main.dart b/packages/e2e/example/lib/main.dart index 2509fb390ff4..1f33324acd01 100644 --- a/packages/e2e/example/lib/main.dart +++ b/packages/e2e/example/lib/main.dart @@ -1,27 +1,5 @@ -import 'dart:io' show Platform; -import 'package:flutter/material.dart'; +import 'my_app.dart' if (dart.library.html) 'my_web_app.dart'; // ignore_for_file: public_member_api_docs -void main() => runApp(MyApp()); - -class MyApp extends StatefulWidget { - @override - _MyAppState createState() => _MyAppState(); -} - -class _MyAppState extends State { - @override - Widget build(BuildContext context) { - return MaterialApp( - home: Scaffold( - appBar: AppBar( - title: const Text('Plugin example app'), - ), - body: Center( - child: Text('Platform: ${Platform.operatingSystem}\n'), - ), - ), - ); - } -} +void main() => startApp(); diff --git a/packages/e2e/example/lib/my_app.dart b/packages/e2e/example/lib/my_app.dart new file mode 100644 index 000000000000..bfbdb860c76d --- /dev/null +++ b/packages/e2e/example/lib/my_app.dart @@ -0,0 +1,27 @@ +import 'dart:io' show Platform; +import 'package:flutter/material.dart'; + +// ignore_for_file: public_member_api_docs + +void startApp() => runApp(MyApp()); + +class MyApp extends StatefulWidget { + @override + _MyAppState createState() => _MyAppState(); +} + +class _MyAppState extends State { + @override + Widget build(BuildContext context) { + return MaterialApp( + home: Scaffold( + appBar: AppBar( + title: const Text('Plugin example app'), + ), + body: Center( + child: Text('Platform: ${Platform.operatingSystem}\n'), + ), + ), + ); + } +} diff --git a/packages/e2e/example/lib/my_web_app.dart b/packages/e2e/example/lib/my_web_app.dart new file mode 100644 index 000000000000..c2ced1af97ae --- /dev/null +++ b/packages/e2e/example/lib/my_web_app.dart @@ -0,0 +1,28 @@ +import 'dart:html' as html; +import 'package:flutter/material.dart'; + +// ignore_for_file: public_member_api_docs + +void startApp() => runApp(MyWebApp()); + +class MyWebApp extends StatefulWidget { + @override + _MyWebAppState createState() => _MyWebAppState(); +} + +class _MyWebAppState extends State { + @override + Widget build(BuildContext context) { + return MaterialApp( + home: Scaffold( + appBar: AppBar( + title: const Text('Plugin example app'), + ), + body: Center( + key: Key('mainapp'), + child: Text('Platform: ${html.window.navigator.platform}\n'), + ), + ), + ); + } +} diff --git a/packages/e2e/example/test_driver/example_e2e.dart b/packages/e2e/example/test_driver/example_e2e.dart index e91dd4d0ce9f..d97702d5d7cf 100644 --- a/packages/e2e/example/test_driver/example_e2e.dart +++ b/packages/e2e/example/test_driver/example_e2e.dart @@ -5,27 +5,12 @@ // gestures. You can also use WidgetTester to find child widgets in the widget // tree, read text, and verify that the values of widget properties are correct. -import 'dart:io' show Platform; -import 'package:flutter/material.dart'; -import 'package:flutter_test/flutter_test.dart'; import 'package:e2e/e2e.dart'; -import 'package:e2e_example/main.dart'; +import 'example_e2e_io.dart' if (dart.library.html) 'example_e2e_web.dart' + as tests; void main() { E2EWidgetsFlutterBinding.ensureInitialized(); - testWidgets('verify text', (WidgetTester tester) async { - // Build our app and trigger a frame. - await tester.pumpWidget(MyApp()); - - // Verify that platform version is retrieved. - expect( - find.byWidgetPredicate( - (Widget widget) => - widget is Text && - widget.data.startsWith('Platform: ${Platform.operatingSystem}'), - ), - findsOneWidget, - ); - }); + tests.main(); } diff --git a/packages/e2e/example/test_driver/example_e2e_io.dart b/packages/e2e/example/test_driver/example_e2e_io.dart new file mode 100644 index 000000000000..9766f568b654 --- /dev/null +++ b/packages/e2e/example/test_driver/example_e2e_io.dart @@ -0,0 +1,34 @@ +// This is a basic Flutter widget test. +// +// To perform an interaction with a widget in your test, use the WidgetTester +// utility that Flutter provides. For example, you can send tap and scroll +// gestures. You can also use WidgetTester to find child widgets in the widget +// tree, read text, and verify that the values of widget properties are correct. + +import 'dart:io' show Platform; +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:e2e/e2e.dart'; + +import 'package:e2e_example/main.dart' as app; + +void main() { + E2EWidgetsFlutterBinding.ensureInitialized(); + testWidgets('verify text', (WidgetTester tester) async { + // Build our app and trigger a frame. + app.main(); + + // Trigger a frame. + await tester.pumpAndSettle(); + + // Verify that platform version is retrieved. + expect( + find.byWidgetPredicate( + (Widget widget) => + widget is Text && + widget.data.startsWith('Platform: ${Platform.operatingSystem}'), + ), + findsOneWidget, + ); + }); +} diff --git a/packages/e2e/example/test_driver/example_e2e_web.dart b/packages/e2e/example/test_driver/example_e2e_web.dart new file mode 100644 index 000000000000..24c3f2cbb2a4 --- /dev/null +++ b/packages/e2e/example/test_driver/example_e2e_web.dart @@ -0,0 +1,35 @@ +// This is a basic Flutter widget test. +// +// To perform an interaction with a widget in your test, use the WidgetTester +// utility that Flutter provides. For example, you can send tap and scroll +// gestures. You can also use WidgetTester to find child widgets in the widget +// tree, read text, and verify that the values of widget properties are correct. + +import 'dart:html' as html; +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:e2e/e2e.dart'; + +import 'package:e2e_example/main.dart' as app; + +void main() { + E2EWidgetsFlutterBinding.ensureInitialized(); + testWidgets('verify text', (WidgetTester tester) async { + // Build our app and trigger a frame. + app.main(); + + // Trigger a frame. + await tester.pumpAndSettle(); + + // Verify that platform is retrieved. + expect( + find.byWidgetPredicate( + (Widget widget) => + widget is Text && + widget.data + .startsWith('Platform: ${html.window.navigator.platform}\n'), + ), + findsOneWidget, + ); + }); +} diff --git a/packages/e2e/example/test_driver/failure.dart b/packages/e2e/example/test_driver/failure.dart index 64d83bf5c13b..ddeeb800bb06 100644 --- a/packages/e2e/example/test_driver/failure.dart +++ b/packages/e2e/example/test_driver/failure.dart @@ -6,7 +6,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:e2e/e2e.dart'; -import 'package:e2e_example/main.dart'; +import 'package:e2e_example/main.dart' as app; // Tests the failure behavior of the E2EWidgetsFlutterBinding // @@ -21,10 +21,10 @@ void main() { testWidgets('failure 1', (WidgetTester tester) async { // Build our app and trigger a frame. - await tester.pumpWidget(MyApp()); + app.main(); // Verify that platform version is retrieved. - expect( + await expectLater( find.byWidgetPredicate( (Widget widget) => widget is Text && widget.data.startsWith('This should fail'), diff --git a/packages/e2e/example/web/favicon.png b/packages/e2e/example/web/favicon.png new file mode 100644 index 000000000000..8aaa46ac1ae2 Binary files /dev/null and b/packages/e2e/example/web/favicon.png differ diff --git a/packages/e2e/example/web/icons/Icon-192.png b/packages/e2e/example/web/icons/Icon-192.png new file mode 100644 index 000000000000..b749bfef0747 Binary files /dev/null and b/packages/e2e/example/web/icons/Icon-192.png differ diff --git a/packages/e2e/example/web/icons/Icon-512.png b/packages/e2e/example/web/icons/Icon-512.png new file mode 100644 index 000000000000..88cfd48dff11 Binary files /dev/null and b/packages/e2e/example/web/icons/Icon-512.png differ diff --git a/packages/e2e/example/web/index.html b/packages/e2e/example/web/index.html new file mode 100644 index 000000000000..96629657328f --- /dev/null +++ b/packages/e2e/example/web/index.html @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + example + + + + + + + + diff --git a/packages/e2e/example/web/manifest.json b/packages/e2e/example/web/manifest.json new file mode 100644 index 000000000000..c63800102369 --- /dev/null +++ b/packages/e2e/example/web/manifest.json @@ -0,0 +1,23 @@ +{ + "name": "example", + "short_name": "example", + "start_url": ".", + "display": "minimal-ui", + "background_color": "#0175C2", + "theme_color": "#0175C2", + "description": "A new Flutter project.", + "orientation": "portrait-primary", + "prefer_related_applications": false, + "icons": [ + { + "src": "icons/Icon-192.png", + "sizes": "192x192", + "type": "image/png" + }, + { + "src": "icons/Icon-512.png", + "sizes": "512x512", + "type": "image/png" + } + ] +} diff --git a/packages/e2e/lib/e2e.dart b/packages/e2e/lib/e2e.dart index afcbeb0d703e..eef594a6f99e 100644 --- a/packages/e2e/lib/e2e.dart +++ b/packages/e2e/lib/e2e.dart @@ -19,6 +19,12 @@ class E2EWidgetsFlutterBinding extends LiveTestWidgetsFlutterBinding { // TODO(jackson): Report test results as they arrive tearDownAll(() async { try { + // For web integration tests we are not using the + // `plugins.flutter.io/e2e`. Mark the tests as complete before invoking + // the channel. + if (kIsWeb) { + if (!_allTestsPassed.isCompleted) _allTestsPassed.complete(true); + } await _channel.invokeMethod( 'allTestsFinished', {'results': _results}); } on MissingPluginException { diff --git a/packages/e2e/pubspec.yaml b/packages/e2e/pubspec.yaml index 68735867218c..21e1210bd23e 100644 --- a/packages/e2e/pubspec.yaml +++ b/packages/e2e/pubspec.yaml @@ -1,6 +1,6 @@ name: e2e description: Runs tests that use the flutter_test API as integration tests. -version: 0.2.4+3 +version: 0.2.4+4 homepage: https://github.com/flutter/plugins/tree/master/packages/e2e environment: