diff --git a/.github/workflows/integration_tests.yaml b/.github/workflows/integration_tests.yaml index c24d729f..dcb1ee5c 100644 --- a/.github/workflows/integration_tests.yaml +++ b/.github/workflows/integration_tests.yaml @@ -97,4 +97,42 @@ jobs: adb -s emulator-5554 install build/app/outputs/flutter-apk/app-debug.apk adb -s emulator-5554 root adb -s emulator-5554 shell appops set com.codepup.workout_timer SCHEDULE_EXACT_ALARM allow - flutter drive -d emulator-5554 --driver=test_driver/integration_test.dart --target=integration_test/timer_test.dart \ No newline at end of file + flutter drive -d emulator-5554 --driver=test_driver/integration_test.dart --target=integration_test/timer_test.dart + + General: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - name: Set up JDK 17 + uses: actions/setup-java@v3 + with: + java-version: '17' + distribution: 'temurin' + - uses: subosito/flutter-action@v2 + with: + channel: 'stable' + - name: Check Version + run: flutter --version + - name: Flutter Doctor + run: flutter doctor -v + - name: Enable KVM + run: | + echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee /etc/udev/rules.d/99-kvm4all.rules + sudo udevadm control --reload-rules + sudo udevadm trigger --name-match=kvm + + - name: Setup Android SDK + uses: android-actions/setup-android@v3 + + - name: run tests + uses: reactivecircus/android-emulator-runner@v2 + with: + api-level: 35 + arch: x86_64 + script: | + # Build the APK + flutter build apk --debug + adb -s emulator-5554 install build/app/outputs/flutter-apk/app-debug.apk + adb -s emulator-5554 root + adb -s emulator-5554 shell appops set com.codepup.workout_timer SCHEDULE_EXACT_ALARM allow + flutter drive -d emulator-5554 --driver=test_driver/integration_test.dart --target=integration_test/general_test.dart \ No newline at end of file diff --git a/integration_test/functions.dart b/integration_test/functions/functions.dart similarity index 88% rename from integration_test/functions.dart rename to integration_test/functions/functions.dart index 5128f837..65cfe792 100644 --- a/integration_test/functions.dart +++ b/integration_test/functions/functions.dart @@ -7,6 +7,11 @@ import 'package:flutter_test/flutter_test.dart'; import 'package:integration_test/integration_test.dart'; import 'package:openhiit/main.dart'; +Future loadApp(WidgetTester tester) async { + await tester.pumpWidget(const WorkoutTimer()); + await tester.pumpAndSettle(); +} + Future selectSound(WidgetTester tester, Key key, String soundName) async { print("LOG --- tapping dropdown"); await tester.tap(find.byKey(key)); @@ -104,6 +109,50 @@ Future createOrEditWorkoutOrTimer( expect(find.text(workoutName), findsOneWidget); } +Future checkWorkoutOrTimer( + WidgetTester tester, + String name, + int numIntervals, + bool exercises, + Map times, + Map sounds) async { + await tester.tap(find.byIcon(Icons.edit)); + await tester.pumpAndSettle(); + + expect(find.text(name), findsOneWidget); + expect(find.text(numIntervals.toString()), findsOneWidget); + await tester.tap(find.text('Submit')); + await tester.pumpAndSettle(); + + if (exercises) { + expect(find.text('Push-ups'), findsOneWidget); + expect(find.text('Sit-ups'), findsOneWidget); + expect(find.text('Jumping Jacks'), findsOneWidget); + + await tester.tap(find.text('Submit')); + await tester.pumpAndSettle(); + } + + await tester.tap(find.byType(ExpansionTile).first); + await tester.pumpAndSettle(); + for (var key in times.keys) { + expect(find.text(key.toString()), findsExactly(times[key]!)); + } + await tester.tap(find.text('Submit')); + await tester.pumpAndSettle(); + + for (var key in sounds.keys) { + final workDropdown = find.byKey(Key(key)); + expect(find.descendant(of: workDropdown, matching: find.text(sounds[key]!)), + findsExactly(2)); + } + + await tester.tap(find.text('Submit')); + await tester.pump(Duration(seconds: 1)); + await tester.pumpAndSettle(); + expect(find.text(name), findsOneWidget); +} + Future editWorkoutOne( WidgetTester tester, String workoutName, @@ -145,11 +194,6 @@ Future editWorkoutOne( expect(find.text(workoutName), findsOneWidget); } -Future loadApp(WidgetTester tester) async { - await tester.pumpWidget(const WorkoutTimer()); - await tester.pumpAndSettle(); -} - Future navigateToAddWorkoutOrTimer( WidgetTester tester, bool isWorkout) async { await tester.tap(find.byIcon(Icons.add)); diff --git a/integration_test/functions/general_functions.dart b/integration_test/functions/general_functions.dart new file mode 100644 index 00000000..6777b154 --- /dev/null +++ b/integration_test/functions/general_functions.dart @@ -0,0 +1,13 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; + +Future tapInfo(WidgetTester tester) async { + await tester.tap(find.byIcon(Icons.info_outline)); + await tester.pumpAndSettle(); + expect(find.text("About OpenHIIT"), findsOneWidget); +} + +Future closeDialog(WidgetTester tester) async { + await tester.tap(find.text("Close")); + await tester.pumpAndSettle(); +} diff --git a/integration_test/general_test.dart b/integration_test/general_test.dart new file mode 100644 index 00000000..885daf51 --- /dev/null +++ b/integration_test/general_test.dart @@ -0,0 +1,23 @@ +import 'dart:ui'; + +import 'package:flutter_test/flutter_test.dart'; +import 'package:integration_test/integration_test.dart'; + +import 'functions/functions.dart'; +import 'functions/general_functions.dart'; + +void main() { + final binding = IntegrationTestWidgetsFlutterBinding.ensureInitialized(); + binding.framePolicy = LiveTestWidgetsFlutterBindingFramePolicy.fullyLive; + + group('end-to-end test', () { + testWidgets('verify app load', (tester) async { + await loadApp(tester); + await binding.setSurfaceSize(const Size(1080, 2400)); + expect(find.text('No saved timers'), findsOneWidget); + await tapInfo(tester); + await closeDialog(tester); + expect(find.text('About OpenHIIT'), findsNothing); + }); + }); +} diff --git a/integration_test/timer_test.dart b/integration_test/timer_test.dart index 7401829c..3bde43ca 100644 --- a/integration_test/timer_test.dart +++ b/integration_test/timer_test.dart @@ -3,7 +3,7 @@ import 'dart:ui'; import 'package:flutter_test/flutter_test.dart'; import 'package:integration_test/integration_test.dart'; -import 'functions.dart'; +import 'functions/functions.dart'; void main() { final binding = IntegrationTestWidgetsFlutterBinding.ensureInitialized(); @@ -12,16 +12,30 @@ void main() { const String timerName = 'Test Timer'; group('end-to-end test', () { - testWidgets('verify app load', (tester) async { - await loadApp(tester); - await binding.setSurfaceSize(const Size(1080, 2400)); - expect(find.text('No saved timers'), findsOneWidget); - }); testWidgets('create a timer', (tester) async { await loadApp(tester); + await binding.setSurfaceSize(const Size(1080, 2400)); await navigateToAddWorkoutOrTimer(tester, false); await createTimer(tester, timerName); }); + // testWidgets('check timer settings', (tester) async { + // await loadApp(tester); + // await verifyWorkoutOrTimerOpens(tester, timerName); + // await checkWorkoutOrTimer(tester, timerName, 1, false, { + // "10": 2, + // "40": 1, + // "30": 1, + // "90": 1, + // "20": 1, + // "2": 1 + // }, { + // "work-sound": "None", + // "rest-sound": "None", + // "halfway-sound": "None", + // "countdown-sound": "None", + // "end-sound": "None", + // }); + // }); testWidgets('run timer and cancel timer', (tester) async { await loadApp(tester); await verifyWorkoutOrTimerOpens(tester, timerName); diff --git a/integration_test/workout_test.dart b/integration_test/workout_test.dart index 03d7f733..4a0d1ae9 100644 --- a/integration_test/workout_test.dart +++ b/integration_test/workout_test.dart @@ -3,7 +3,7 @@ import 'dart:ui'; import 'package:flutter_test/flutter_test.dart'; import 'package:integration_test/integration_test.dart'; -import 'functions.dart'; +import 'functions/functions.dart'; void main() { final binding = IntegrationTestWidgetsFlutterBinding.ensureInitialized(); @@ -19,6 +19,19 @@ void main() { await navigateToAddWorkoutOrTimer(tester, true); await createWorkout(tester, workoutName); }); + testWidgets('check timer settings', (tester) async { + await loadApp(tester); + await verifyWorkoutOrTimerOpens(tester, workoutName); + await checkWorkoutOrTimer(tester, workoutName, 3, true, { + "10": 3, + }, { + "work-sound": "Harsh beep sequence", + "rest-sound": "Ding", + "halfway-sound": "Quick beep sequence", + "countdown-sound": "Beep", + "end-sound": "Horn", + }); + }); testWidgets('run a workout and restart', (tester) async { await loadApp(tester); await verifyWorkoutOrTimerOpens(tester, workoutName);