From 2be7dfbcab993e3d3190aa4d10f4e358a51426ce Mon Sep 17 00:00:00 2001 From: Nils Reichardt Date: Fri, 24 Feb 2023 11:24:27 +0100 Subject: [PATCH] Integrate Android integration tests into CI pipeline (#230) Closes #176 --------- Co-authored-by: Jonas Sander <29028262+Jonas-Sander@users.noreply.github.com> --- .github/workflows/main.yml | 93 ++++++++++++++++++- .../blocs/homework/homework_page_bloc.dart | 9 +- ...ebase_messaging_callback_configurator.dart | 12 +++ 3 files changed, 112 insertions(+), 2 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index a630b49c6..c5bbd72d0 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -131,7 +131,98 @@ jobs: # We ignore it when no files could be found because the test command # could also be failed because of an unit test. In this case there # would be no failed golden test to upload. - if-no-files-found: ignore + if-no-files-found: ignore + + android-integration-test: + # Is recommended to run the job with a macOS machine to take advantage of + # hardware acceleration support provided by HAXM. See more details in the + # README.md of the Android emulator action: + # https://github.com/ReactiveCircus/android-emulator-runner#usage + runs-on: macos-latest + if: ${{ github.event.pull_request.draft == false }} + timeout-minutes: 60 + steps: + - uses: actions/checkout@v3 + + # Java is needed for building the APK, see + # https://github.com/marketplace/actions/flutter-action. + - uses: actions/setup-java@v3 + with: + distribution: 'temurin' + java-version: '11' + + - name: Set Flutter version from FVM config file to environment variables + uses: kuhnroyal/flutter-fvm-config-action@v1 + + - uses: subosito/flutter-action@main + with: + flutter-version: ${{ env.FLUTTER_VERSION }} + channel: ${{ env.FLUTTER_CHANNEL }} + + # Building the Android app as workaround for the timeout problem with + # integration tests. + # + # We need to build the Android app first to hope that the build for the + # integration test needs less than 12 minutes. Currently, it's not + # possible to increase the timeout for integration tests: + # https://github.com/flutter/flutter/issues/105913. + # + # Using `flutter drive` as workaround is not an option because it's super + # flaky in terms of stability. With `flutter drive` ~ 30% the Android + # Emulator have difficulties to start properly. + - name: Build Android App + working-directory: ./app + env: + USER_1_EMAIL: ${{ secrets.INTEGRATION_TEST_USER_1_EMAIL }} + USER_1_PASSWORD: ${{ secrets.INTEGRATION_TEST_USER_1_PASSWORD }} + run: flutter build apk --target=integration_test/app_test.dart --flavor dev --dart-define USER_1_EMAIL=$USER_1_EMAIL --dart-define USER_1_PASSWORD=$USER_1_PASSWORD + + - name: Run integration tests + uses: reactivecircus/android-emulator-runner@v2 + env: + USER_1_EMAIL: ${{ secrets.INTEGRATION_TEST_USER_1_EMAIL }} + USER_1_PASSWORD: ${{ secrets.INTEGRATION_TEST_USER_1_PASSWORD }} + with: + # When you are going to change something here (like a different + # target, arch, profile, channel, etc.), please check if these + # configurations are stable. + # + # You can do this by running this workflow multiple times. Use a + # matrix to run multiple tests in parallel (matrix needs to be copied + # to above the "with"): + # strategy: + # fail-fast: false + # matrix: + # test1: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] + # test2: [1, 2, 3] + api-level: 30 + target: google_apis + arch: x86_64 + profile: Nexus 5X + channel: canary + # We use some emulator options for the following reasons: + # * "-no-snapshot": Disables the quick boot feature. Therefore, the + # emulator does not load or save the emulator state. We want to have + # * "-no-window": Disables the graphical windows, so no display is + # required. + # a fresh testing environment for every test run. + # * "-no-boot-anim": Disables the boot animation for faster booting. + # * "-camera-back virtualscene": Shows this virtual room when opening + # the back camera where you can walk. Default option for emulators + # created by Android Studio. We use this so we have the same + # environment locally as when using this action. Is needed when + # testing things with the camera. It's also possible to inject + # images into the virtual scene to test things like qr code scanner. + # * "-camera-front": Shows this green monster when opening the front + # camera. Default option for emulators created by Android Studio. We + # use this so we have the same environment locally as when using + # this action. Is needed when testing things with camera. + emulator-options: -no-snapshot -no-window -no-boot-anim -camera-back virtualscene -camera-front emulated + working-directory: ./app + # We can not use a multiline command because the + # "android-emulator-runner" action doesn't support it. It just takes every + # line as separate command. + script: flutter test integration_test --flavor dev --dart-define USER_1_EMAIL=$USER_1_EMAIL --dart-define USER_1_PASSWORD=$USER_1_PASSWORD ios-integration-test: # It seems so that our integration tests are not working `macos-12`. The diff --git a/app/lib/blocs/homework/homework_page_bloc.dart b/app/lib/blocs/homework/homework_page_bloc.dart index 30af7fcc4..566d4d2e5 100644 --- a/app/lib/blocs/homework/homework_page_bloc.dart +++ b/app/lib/blocs/homework/homework_page_bloc.dart @@ -128,7 +128,14 @@ class HomeworkPageBloc extends BlocBase { /// Take care of closing streams. @override - void dispose() { + Future dispose() async { + await Future.wait([ + _homeworkNotDoneSubject.drain(), + _homeworkDoneSubject.drain(), + _errorsSubject.drain(), + _homeworkListSubject.drain(), + ]); + _homeworkNotDoneSubject.close(); _homeworkDoneSubject.close(); _toggleIsHomeworkDoneToController.close(); diff --git a/app/lib/notifications/firebase_messaging_callback_configurator.dart b/app/lib/notifications/firebase_messaging_callback_configurator.dart index 6c2f26c16..2bee5e6b4 100644 --- a/app/lib/notifications/firebase_messaging_callback_configurator.dart +++ b/app/lib/notifications/firebase_messaging_callback_configurator.dart @@ -21,6 +21,7 @@ import 'package:sharezone/notifications/widgets/error_dialog.dart'; import 'package:sharezone/notifications/widgets/in_app_notification.dart'; import 'package:sharezone/onboarding/group_onboarding/logic/signed_up_bloc.dart'; import 'package:sharezone/util/navigation_service.dart'; +import 'package:sharezone_utils/platform.dart'; import 'action_requests/action_requests.dart'; @@ -125,7 +126,18 @@ class FirebaseMessagingCallbackConfigurator { } } +/// Prompts the native iOS permissions dialog to ask the user if we are allowed +/// to send push notifications. +/// +/// Does nothing if the platform is not iOS. Future _requestIOSPermission(BuildContext context) async { + if (!PlatformCheck.isIOS) { + // We are only using push notifications for iOS and Android. Android does + // not required to get the permission from the user. Therefore, we can skip + // this for Android devices. + return; + } + final signUpBloc = BlocProvider.of(context); final signedUp = await signUpBloc.signedUp.first;