From 826810f17af7430c44548092e7c88c8fa3f02584 Mon Sep 17 00:00:00 2001 From: Roland Geider Date: Mon, 11 Apr 2022 17:50:08 +0200 Subject: [PATCH] Start working on automatic screenshot generation --- integration_test/README.md | 8 + integration_test/app_test.dart | 434 ++++++++++++++++++ lib/models/nutrition/meal_item.dart | 5 + lib/widgets/exercises/exercises.dart | 4 +- pubspec.lock | 99 ++-- pubspec.yaml | 4 +- .../exercises_detail_widget_test.dart | 2 +- test/gym_mode_screen_test.mocks.dart | 184 -------- test/workout/workout_set_form_test.mocks.dart | 5 + test_data/exercises.dart | 13 +- test_driver/screenshot_driver.dart | 18 + 11 files changed, 553 insertions(+), 223 deletions(-) create mode 100644 integration_test/README.md create mode 100644 integration_test/app_test.dart delete mode 100644 test/gym_mode_screen_test.mocks.dart create mode 100644 test_driver/screenshot_driver.dart diff --git a/integration_test/README.md b/integration_test/README.md new file mode 100644 index 00000000..fedbcbf7 --- /dev/null +++ b/integration_test/README.md @@ -0,0 +1,8 @@ +Start emulator and run + +`flutter drive --driver=test_driver/screenshot_driver.dart --target=integration_test/app_test.dart` + + +See +* +* diff --git a/integration_test/app_test.dart b/integration_test/app_test.dart new file mode 100644 index 00000000..91ef7f0b --- /dev/null +++ b/integration_test/app_test.dart @@ -0,0 +1,434 @@ +import 'dart:io'; + +import 'package:flutter/material.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:integration_test/integration_test.dart'; +import 'package:mockito/mockito.dart'; +import 'package:provider/provider.dart'; +import 'package:wger/models/body_weight/weight_entry.dart'; +import 'package:wger/models/exercises/exercise.dart'; +import 'package:wger/models/nutrition/ingredient.dart'; +import 'package:wger/models/nutrition/log.dart'; +import 'package:wger/models/nutrition/meal.dart'; +import 'package:wger/models/nutrition/meal_item.dart'; +import 'package:wger/models/nutrition/nutritional_plan.dart'; +import 'package:wger/models/workouts/day.dart'; +import 'package:wger/models/workouts/set.dart'; +import 'package:wger/models/workouts/setting.dart'; +import 'package:wger/models/workouts/workout_plan.dart'; +import 'package:wger/providers/body_weight.dart'; +import 'package:wger/providers/exercises.dart'; +import 'package:wger/providers/nutrition.dart'; +import 'package:wger/providers/workout_plans.dart'; +import 'package:wger/screens/form_screen.dart'; +import 'package:wger/screens/gym_mode.dart'; +import 'package:wger/screens/nutritional_plan_screen.dart'; +import 'package:wger/screens/weight_screen.dart'; +import 'package:wger/screens/workout_plan_screen.dart'; +import 'package:wger/theme/theme.dart'; + +import '../test/other/base_provider_test.mocks.dart'; +import '../test/utils.dart'; +import '../test/workout/gym_mode_screen_test.mocks.dart'; +import '../test_data/exercises.dart'; +import '../test_data/workouts.dart'; + +Future takeScreenshot(tester, binding, name) async { + if (Platform.isAndroid) { + await binding.convertFlutterSurfaceToImage(); + await tester.pumpAndSettle(); + } + await binding.takeScreenshot(name); +} + +// Languages for which the translations are almost complete in weblate +const languages = ['de', 'en', 'es', 'it', 'jp', 'ca', 'pt', 'ru', 'tr', 'zh', 'fr', 'he']; + +void main() { + final binding = IntegrationTestWidgetsFlutterBinding.ensureInitialized(); + + Widget createNutritionalPlanScreen({locale = 'en'}) { + final key = GlobalKey(); + final client = MockClient(); + + final muesli = Ingredient( + id: 1, + code: '123456787', + name: 'Müsli', + creationDate: DateTime(2021, 5, 1), + energy: 500, + carbohydrates: 10, + carbohydratesSugar: 2, + protein: 5, + fat: 20, + fatSaturated: 7, + fibres: 12, + sodium: 0.5, + ); + final milk = Ingredient( + id: 1, + code: '123456787', + name: 'Milk', + creationDate: DateTime(2021, 5, 1), + energy: 500, + carbohydrates: 10, + carbohydratesSugar: 2, + protein: 5, + fat: 20, + fatSaturated: 7, + fibres: 12, + sodium: 0.5, + ); + final apple = Ingredient( + id: 1, + code: '123456787', + name: 'Apple', + creationDate: DateTime(2021, 5, 1), + energy: 500, + carbohydrates: 10, + carbohydratesSugar: 2, + protein: 5, + fat: 20, + fatSaturated: 7, + fibres: 12, + sodium: 0.5, + ); + + final mealItem1 = MealItem(ingredientId: 1, amount: 100, ingredient: muesli); + final mealItem2 = MealItem(ingredientId: 2, amount: 75, ingredient: milk); + final mealItem3 = MealItem(ingredientId: 3, amount: 100, ingredient: apple); + + final meal1 = Meal( + id: 1, + plan: 1, + time: const TimeOfDay(hour: 8, minute: 30), + name: 'Breakfast', + mealItems: [mealItem1, mealItem2], + ); + + final meal2 = Meal( + id: 2, + plan: 1, + time: const TimeOfDay(hour: 11, minute: 0), + name: 'Snack 1', + mealItems: [mealItem3], + ); + + final NutritionalPlan plan = NutritionalPlan( + id: 1, + description: 'Mini diet', + creationDate: DateTime(2021, 5, 23), + meals: [meal1, meal2], + ); + + // Add logs + plan.logs.add(Log.fromMealItem(mealItem1, 1, 1, DateTime(2021, 6, 1))); + plan.logs.add(Log.fromMealItem(mealItem2, 1, 1, DateTime(2021, 6, 1))); + plan.logs.add(Log.fromMealItem(mealItem3, 1, 1, DateTime(2021, 6, 10))); + + return MultiProvider( + providers: [ + ChangeNotifierProvider( + create: (context) => NutritionPlansProvider(testAuthProvider, [], client), + ), + ChangeNotifierProvider( + create: (context) => BodyWeightProvider(testAuthProvider, [], client), + ), + ], + child: MaterialApp( + locale: Locale(locale), + localizationsDelegates: AppLocalizations.localizationsDelegates, + supportedLocales: AppLocalizations.supportedLocales, + theme: wgerTheme, + navigatorKey: key, + home: TextButton( + onPressed: () => key.currentState!.push( + MaterialPageRoute( + settings: RouteSettings(arguments: plan), + builder: (_) => NutritionalPlanScreen(), + ), + ), + child: const SizedBox(), + ), + ), + ); + } + + Widget createWeightScreen({locale = 'en'}) { + return ChangeNotifierProvider( + create: (context) => BodyWeightProvider( + testAuthProvider, + [ + WeightEntry(id: 1, weight: 86, date: DateTime(2021, 01, 01)), + WeightEntry(id: 2, weight: 81, date: DateTime(2021, 01, 10)), + WeightEntry(id: 3, weight: 82, date: DateTime(2021, 01, 20)), + WeightEntry(id: 4, weight: 83, date: DateTime(2021, 01, 30)), + WeightEntry(id: 5, weight: 86, date: DateTime(2021, 02, 20)), + WeightEntry(id: 6, weight: 90, date: DateTime(2021, 02, 28)), + WeightEntry(id: 7, weight: 91, date: DateTime(2021, 03, 20)), + WeightEntry(id: 8, weight: 91.1, date: DateTime(2021, 03, 30)), + WeightEntry(id: 9, weight: 90, date: DateTime(2021, 05, 1)), + WeightEntry(id: 10, weight: 91, date: DateTime(2021, 6, 5)), + WeightEntry(id: 11, weight: 89, date: DateTime(2021, 6, 20)), + WeightEntry(id: 12, weight: 88, date: DateTime(2021, 7, 15)), + WeightEntry(id: 13, weight: 86, date: DateTime(2021, 7, 20)), + WeightEntry(id: 14, weight: 83, date: DateTime(2021, 7, 30)), + WeightEntry(id: 15, weight: 80, date: DateTime(2021, 8, 10)) + ], + MockClient(), + ), + child: MaterialApp( + locale: Locale(locale), + localizationsDelegates: AppLocalizations.localizationsDelegates, + supportedLocales: AppLocalizations.supportedLocales, + theme: wgerTheme, + home: WeightScreen(), + routes: { + FormScreen.routeName: (ctx) => FormScreen(), + }, + ), + ); + } + + Widget createGymModeScreen({locale = 'en'}) { + final key = GlobalKey(); + final client = MockClient(); + + final squats = Exercise( + id: 1, + uuid: 'uuid', + creationDate: DateTime(2021, 1, 15), + name: 'Squats', + description: 'add clever text', + base: tBase1, + language: tLanguage1, + ); + + final benchPress = Exercise( + id: 1, + uuid: 'uuid', + creationDate: DateTime(2021, 1, 15), + name: 'Bench press', + description: 'add clever text', + base: tBase1, + language: tLanguage1, + ); + + final deadLift = Exercise( + id: 1, + uuid: 'uuid', + creationDate: DateTime(2021, 1, 15), + name: 'deadLift', + description: 'add clever text', + base: tBase1, + language: tLanguage1, + ); + + final crunches = Exercise( + id: 1, + uuid: 'uuid', + creationDate: DateTime(2021, 1, 15), + name: 'Crunches', + description: 'add clever text', + base: tBase1, + language: tLanguage1, + ); + + final mockExerciseProvider = MockExercisesProvider(); + when(mockExerciseProvider.findExerciseById(1)).thenReturn(squats); + when(mockExerciseProvider.findExerciseById(2)).thenReturn(benchPress); + when(mockExerciseProvider.findExerciseById(3)).thenReturn(crunches); + + final setting1 = Setting( + setId: 1, + order: 1, + exerciseId: 1, + repetitionUnitId: 1, + reps: 5, + weightUnitId: 1, + comment: 'ddd', + rir: '2', + ); + setting1.repetitionUnit = repetitionUnit1; + setting1.weightUnit = weightUnit1; + setting1.exercise = squats; + setting1.weight = 100; + + final setting2 = Setting( + setId: 1, + order: 1, + exerciseId: 2, + repetitionUnitId: 1, + reps: 6, + weightUnitId: 1, + comment: 'ddd', + rir: '1.5', + ); + setting2.repetitionUnit = repetitionUnit1; + setting2.weightUnit = weightUnit1; + setting2.exercise = benchPress; + setting2.weight = 80; + + final setting2b = Setting( + setId: 1, + order: 1, + exerciseId: 2, + repetitionUnitId: 1, + reps: 8, + weightUnitId: 1, + comment: 'ddd', + rir: '2', + ); + setting2b.repetitionUnit = repetitionUnit1; + setting2b.weightUnit = weightUnit1; + setting2b.exercise = benchPress; + setting2b.weight = 60; + + final setting3 = Setting( + setId: 1, + order: 1, + exerciseId: 2, + repetitionUnitId: 1, + reps: 20, + weightUnitId: 1, + comment: '', + rir: null, + ); + setting3.repetitionUnit = repetitionUnit1; + setting3.weightUnit = weightUnit1; + setting3.exercise = crunches; + + final setting4 = Setting( + setId: 1, + order: 1, + exerciseId: 2, + repetitionUnitId: 1, + reps: 8, + weightUnitId: 1, + comment: '', + rir: null, + ); + setting4.repetitionUnit = repetitionUnit1; + setting4.weightUnit = weightUnit1; + setting4.exercise = deadLift; + setting4.weight = 120; + + final set1 = Set.withData( + id: 1, + day: 1, + sets: 3, + order: 1, + ); + set1.addExercise(squats); + set1.settings.add(setting1); + set1.settings.add(setting1); + set1.settings.add(setting1); + set1.settings.add(setting1); + + final set2 = Set.withData( + id: 2, + day: 1, + sets: 3, + order: 1, + ); + set2.addExercise(benchPress); + set2.settings.add(setting2); + set2.settings.add(setting2); + set2.settings.add(setting2b); + set2.settings.add(setting2b); + + final set3 = Set.withData( + id: 3, + day: 1, + sets: 3, + order: 1, + ); + set3.addExercise(crunches); + set3.settings.add(setting3); + + final set4 = Set.withData( + id: 4, + day: 1, + sets: 3, + order: 1, + ); + set4.addExercise(deadLift); + set4.settings.add(setting4); + set4.settings.add(setting4); + set4.settings.add(setting4); + set4.settings.add(setting4); + + final day1 = Day() + ..id = 1 + ..workoutId = 1 + ..description = 'test day 1' + ..daysOfWeek = [1, 2]; + day1.sets.add(set1); + day1.sets.add(set2); + day1.sets.add(set4); + day1.sets.add(set3); + + final workout = WorkoutPlan( + id: 1, + creationDate: DateTime(2021, 01, 01), + name: 'test workout 1', + days: [day1], + ); + + return ChangeNotifierProvider( + create: (context) => WorkoutPlansProvider( + testAuthProvider, + mockExerciseProvider, + [workout], + client, + ), + child: ChangeNotifierProvider( + create: (context) => mockExerciseProvider, + child: MaterialApp( + locale: Locale(locale), + localizationsDelegates: AppLocalizations.localizationsDelegates, + supportedLocales: AppLocalizations.supportedLocales, + navigatorKey: key, + theme: wgerTheme, + home: TextButton( + onPressed: () => key.currentState!.push( + MaterialPageRoute( + settings: RouteSettings(arguments: workout.days.first), + builder: (_) => GymModeScreen(), + ), + ), + child: const SizedBox(), + ), + routes: { + WorkoutPlanScreen.routeName: (ctx) => WorkoutPlanScreen(), + }, + ), + ), + ); + } + + group('Generate screenshots', () { + for (final language in languages) { + testWidgets('nutritional plan detail - $language', (WidgetTester tester) async { + await tester.pumpWidget(createNutritionalPlanScreen(locale: language)); + await tester.tap(find.byType(TextButton)); + await tester.pumpAndSettle(); + await takeScreenshot(tester, binding, '$language/03-nutritional-plan'); + }); + + testWidgets('body weight screen - $language', (WidgetTester tester) async { + await tester.pumpWidget(createWeightScreen(locale: language)); + await tester.pumpAndSettle(); + await takeScreenshot(tester, binding, '$language/05-weight'); + }); + + testWidgets('gym mode screen - $language', (WidgetTester tester) async { + await tester.pumpWidget(createGymModeScreen(locale: language)); + await tester.tap(find.byType(TextButton)); + await tester.pumpAndSettle(); + await takeScreenshot(tester, binding, '$language/05-gym-mode'); + }); + } + }); +} diff --git a/lib/models/nutrition/meal_item.dart b/lib/models/nutrition/meal_item.dart index 38ed9318..0906b7ba 100644 --- a/lib/models/nutrition/meal_item.dart +++ b/lib/models/nutrition/meal_item.dart @@ -53,10 +53,15 @@ class MealItem { required this.ingredientId, this.weightUnitId, required this.amount, + Ingredient? ingredient, }) { if (mealId != null) { this.mealId = mealId; } + if (ingredient != null) { + ingredientObj = ingredient; + ingredientId = ingredient.id; + } } MealItem.empty(); diff --git a/lib/widgets/exercises/exercises.dart b/lib/widgets/exercises/exercises.dart index b0996f19..df9127cf 100644 --- a/lib/widgets/exercises/exercises.dart +++ b/lib/widgets/exercises/exercises.dart @@ -270,8 +270,8 @@ class MuscleRowWidget extends StatelessWidget { @override Widget build(BuildContext context) { return Row( - mainAxisAlignment: MainAxisAlignment.spaceAround, - crossAxisAlignment: CrossAxisAlignment.start, + //mainAxisAlignment: MainAxisAlignment.spaceAround, + //crossAxisAlignment: CrossAxisAlignment.start, children: [ Expanded( child: Padding( diff --git a/pubspec.lock b/pubspec.lock index 04abb240..20d933e3 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -7,14 +7,14 @@ packages: name: _fe_analyzer_shared url: "https://pub.dartlang.org" source: hosted - version: "34.0.0" + version: "38.0.0" analyzer: dependency: transitive description: name: analyzer url: "https://pub.dartlang.org" source: hosted - version: "3.2.0" + version: "3.4.1" android_metadata: dependency: "direct main" description: @@ -28,7 +28,7 @@ packages: name: archive url: "https://pub.dartlang.org" source: hosted - version: "3.2.1" + version: "3.1.6" args: dependency: transitive description: @@ -112,7 +112,7 @@ packages: name: camera url: "https://pub.dartlang.org" source: hosted - version: "0.9.4+17" + version: "0.9.4+19" camera_platform_interface: dependency: transitive description: @@ -175,7 +175,7 @@ packages: name: chewie url: "https://pub.dartlang.org" source: hosted - version: "1.3.0" + version: "1.3.1" chewie_audio: dependency: transitive description: @@ -190,13 +190,6 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "0.1.1" - cli_util: - dependency: transitive - description: - name: cli_util - url: "https://pub.dartlang.org" - source: hosted - version: "0.3.5" clock: dependency: transitive description: @@ -259,7 +252,7 @@ packages: name: dart_style url: "https://pub.dartlang.org" source: hosted - version: "2.2.1" + version: "2.2.2" equatable: dependency: "direct main" description: @@ -314,6 +307,11 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.1.0" + flutter_driver: + dependency: transitive + description: flutter + source: sdk + version: "0.0.0" flutter_html: dependency: "direct main" description: @@ -355,7 +353,7 @@ packages: name: flutter_layout_grid url: "https://pub.dartlang.org" source: hosted - version: "1.0.3" + version: "1.0.6" flutter_lints: dependency: "direct dev" description: @@ -420,6 +418,11 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.1.2" + fuchsia_remote_debug_protocol: + dependency: transitive + description: flutter + source: sdk + version: "0.0.0" glob: dependency: transitive description: @@ -475,6 +478,13 @@ packages: name: image_picker url: "https://pub.dartlang.org" source: hosted + version: "0.8.5" + image_picker_android: + dependency: transitive + description: + name: image_picker_android + url: "https://pub.dartlang.org" + source: hosted version: "0.8.4+11" image_picker_for_web: dependency: transitive @@ -483,6 +493,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.1.6" + image_picker_ios: + dependency: transitive + description: + name: image_picker_ios + url: "https://pub.dartlang.org" + source: hosted + version: "0.8.4+11" image_picker_platform_interface: dependency: transitive description: @@ -490,6 +507,11 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.4.4" + integration_test: + dependency: "direct dev" + description: flutter + source: sdk + version: "0.0.0" intl: dependency: "direct main" description: @@ -727,7 +749,7 @@ packages: name: pub_semver url: "https://pub.dartlang.org" source: hosted - version: "2.1.0" + version: "2.1.1" pubspec_parse: dependency: transitive description: @@ -748,14 +770,14 @@ packages: name: rfc_6901 url: "https://pub.dartlang.org" source: hosted - version: "0.1.0" + version: "0.1.1" rive: dependency: "direct main" description: name: rive url: "https://pub.dartlang.org" source: hosted - version: "0.8.1" + version: "0.8.4" shared_preferences: dependency: "direct main" description: @@ -818,7 +840,7 @@ packages: name: shelf url: "https://pub.dartlang.org" source: hosted - version: "1.2.0" + version: "1.3.0" shelf_web_socket: dependency: transitive description: @@ -887,6 +909,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.1.0" + sync_http: + dependency: transitive + description: + name: sync_http + url: "https://pub.dartlang.org" + source: hosted + version: "0.3.0" table_calendar: dependency: "direct main" description: @@ -977,7 +1006,7 @@ packages: name: url_launcher_web url: "https://pub.dartlang.org" source: hosted - version: "2.0.6" + version: "2.0.9" url_launcher_windows: dependency: transitive description: @@ -1026,21 +1055,21 @@ packages: name: video_player_android url: "https://pub.dartlang.org" source: hosted - version: "2.3.0" + version: "2.3.2" video_player_avfoundation: dependency: transitive description: name: video_player_avfoundation url: "https://pub.dartlang.org" source: hosted - version: "2.3.0" + version: "2.3.1" video_player_platform_interface: dependency: transitive description: name: video_player_platform_interface url: "https://pub.dartlang.org" source: hosted - version: "5.1.0" + version: "5.1.1" video_player_web: dependency: transitive description: @@ -1048,13 +1077,20 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.0.7" + vm_service: + dependency: transitive + description: + name: vm_service + url: "https://pub.dartlang.org" + source: hosted + version: "7.5.0" wakelock: dependency: transitive description: name: wakelock url: "https://pub.dartlang.org" source: hosted - version: "0.6.1+1" + version: "0.6.1+2" wakelock_macos: dependency: transitive description: @@ -1097,6 +1133,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.1.0" + webdriver: + dependency: transitive + description: + name: webdriver + url: "https://pub.dartlang.org" + source: hosted + version: "3.0.0" webview_flutter: dependency: transitive description: @@ -1110,7 +1153,7 @@ packages: name: webview_flutter_android url: "https://pub.dartlang.org" source: hosted - version: "2.8.3" + version: "2.8.5" webview_flutter_platform_interface: dependency: transitive description: @@ -1124,14 +1167,14 @@ packages: name: webview_flutter_wkwebview url: "https://pub.dartlang.org" source: hosted - version: "2.7.1" + version: "2.7.2" win32: dependency: transitive description: name: win32 url: "https://pub.dartlang.org" source: hosted - version: "2.4.1" + version: "2.5.1" xdg_directories: dependency: transitive description: @@ -1154,5 +1197,5 @@ packages: source: hosted version: "3.1.0" sdks: - dart: ">=2.15.1 <3.0.0" - flutter: ">=2.8.0" + dart: ">=2.16.0 <3.0.0" + flutter: ">=2.10.0" diff --git a/pubspec.yaml b/pubspec.yaml index fc7c4ce2..92e4041a 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -60,8 +60,8 @@ dependencies: dev_dependencies: flutter_test: sdk: flutter - #flutter_driver: - # sdk: flutter + integration_test: + sdk: flutter build_runner: ^2.1.2 flutter_launcher_icons: ^0.9.1 json_serializable: ^6.1.5 diff --git a/test/exercises/exercises_detail_widget_test.dart b/test/exercises/exercises_detail_widget_test.dart index 37e3d36e..ed4738a1 100644 --- a/test/exercises/exercises_detail_widget_test.dart +++ b/test/exercises/exercises_detail_widget_test.dart @@ -24,7 +24,7 @@ import 'package:wger/providers/exercises.dart'; import 'package:wger/widgets/exercises/exercises.dart'; import '../../test_data/exercises.dart'; -import '../gym_mode_screen_test.mocks.dart'; +import '../workout/gym_mode_screen_test.mocks.dart'; void main() { final mockProvider = MockExercisesProvider(); diff --git a/test/gym_mode_screen_test.mocks.dart b/test/gym_mode_screen_test.mocks.dart deleted file mode 100644 index bfc7bc35..00000000 --- a/test/gym_mode_screen_test.mocks.dart +++ /dev/null @@ -1,184 +0,0 @@ -// Mocks generated by Mockito 5.0.15 from annotations -// in wger/test/gym_mode_screen_test.dart. -// Do not manually edit this file. - -import 'dart:async' as _i9; -import 'dart:ui' as _i11; - -import 'package:mockito/mockito.dart' as _i1; -import 'package:wger/models/exercises/base.dart' as _i10; -import 'package:wger/models/exercises/category.dart' as _i4; -import 'package:wger/models/exercises/equipment.dart' as _i5; -import 'package:wger/models/exercises/exercise.dart' as _i3; -import 'package:wger/models/exercises/language.dart' as _i7; -import 'package:wger/models/exercises/muscle.dart' as _i6; -import 'package:wger/providers/base_provider.dart' as _i2; -import 'package:wger/providers/exercises.dart' as _i8; - -// ignore_for_file: avoid_redundant_argument_values -// ignore_for_file: avoid_setters_without_getters -// ignore_for_file: comment_references -// ignore_for_file: implementation_imports -// ignore_for_file: invalid_use_of_visible_for_testing_member -// ignore_for_file: prefer_const_constructors -// ignore_for_file: unnecessary_parenthesis - -class _FakeWgerBaseProvider_0 extends _i1.Fake implements _i2.WgerBaseProvider {} - -class _FakeExercise_1 extends _i1.Fake implements _i3.Exercise {} - -class _FakeExerciseCategory_2 extends _i1.Fake implements _i4.ExerciseCategory {} - -class _FakeEquipment_3 extends _i1.Fake implements _i5.Equipment {} - -class _FakeMuscle_4 extends _i1.Fake implements _i6.Muscle {} - -class _FakeLanguage_5 extends _i1.Fake implements _i7.Language {} - -/// A class which mocks [ExercisesProvider]. -/// -/// See the documentation for Mockito's code generation for more information. -class MockExercisesProvider extends _i1.Mock implements _i8.ExercisesProvider { - MockExercisesProvider() { - _i1.throwOnMissingStub(this); - } - - @override - _i2.WgerBaseProvider get baseProvider => - (super.noSuchMethod(Invocation.getter(#baseProvider), returnValue: _FakeWgerBaseProvider_0()) - as _i2.WgerBaseProvider); - @override - set exercises(List<_i3.Exercise>? exercises) => - super.noSuchMethod(Invocation.setter(#exercises, exercises), returnValueForMissingStub: null); - @override - set filteredExerciseBases(List<_i3.Exercise>? newfilteredExercises) => - super.noSuchMethod(Invocation.setter(#filteredExercises, newfilteredExercises), - returnValueForMissingStub: null); - @override - List<_i3.Exercise> get items => - (super.noSuchMethod(Invocation.getter(#items), returnValue: <_i3.Exercise>[]) - as List<_i3.Exercise>); - @override - List<_i4.ExerciseCategory> get categories => - (super.noSuchMethod(Invocation.getter(#categories), returnValue: <_i4.ExerciseCategory>[]) - as List<_i4.ExerciseCategory>); - @override - bool get hasListeners => - (super.noSuchMethod(Invocation.getter(#hasListeners), returnValue: false) as bool); - @override - _i9.Future setFilters(_i8.Filters? newFilters) => - (super.noSuchMethod(Invocation.method(#setFilters, [newFilters]), - returnValue: Future.value(), - returnValueForMissingStub: Future.value()) as _i9.Future); - @override - _i9.Future findByFilters() => (super.noSuchMethod(Invocation.method(#findByFilters, []), - returnValue: Future.value(), - returnValueForMissingStub: Future.value()) as _i9.Future); - @override - List<_i3.Exercise> findByCategory(_i4.ExerciseCategory? category) => - (super.noSuchMethod(Invocation.method(#findByCategory, [category]), - returnValue: <_i3.Exercise>[]) as List<_i3.Exercise>); - @override - _i3.Exercise findExerciseById(int? id) => (super - .noSuchMethod(Invocation.method(#findExerciseById, [id]), returnValue: _FakeExercise_1()) - as _i3.Exercise); - @override - _i4.ExerciseCategory findCategoryById(int? id) => - (super.noSuchMethod(Invocation.method(#findCategoryById, [id]), - returnValue: _FakeExerciseCategory_2()) as _i4.ExerciseCategory); - @override - _i5.Equipment findEquipmentById(int? id) => - (super.noSuchMethod(Invocation.method(#findEquipmentById, [id]), - returnValue: _FakeEquipment_3()) as _i5.Equipment); - @override - _i6.Muscle findMuscleById(int? id) => - (super.noSuchMethod(Invocation.method(#findMuscleById, [id]), returnValue: _FakeMuscle_4()) - as _i6.Muscle); - @override - _i7.Language findLanguageById(int? id) => (super - .noSuchMethod(Invocation.method(#findLanguageById, [id]), returnValue: _FakeLanguage_5()) - as _i7.Language); - @override - _i9.Future fetchAndSetCategories() => - (super.noSuchMethod(Invocation.method(#fetchAndSetCategories, []), - returnValue: Future.value(), - returnValueForMissingStub: Future.value()) as _i9.Future); - @override - _i9.Future fetchAndSetVariations() => - (super.noSuchMethod(Invocation.method(#fetchAndSetVariations, []), - returnValue: Future.value(), - returnValueForMissingStub: Future.value()) as _i9.Future); - @override - _i9.Future fetchAndSetMuscles() => - (super.noSuchMethod(Invocation.method(#fetchAndSetMuscles, []), - returnValue: Future.value(), - returnValueForMissingStub: Future.value()) as _i9.Future); - @override - _i9.Future fetchAndSetEquipment() => - (super.noSuchMethod(Invocation.method(#fetchAndSetEquipment, []), - returnValue: Future.value(), - returnValueForMissingStub: Future.value()) as _i9.Future); - @override - _i9.Future fetchAndSetLanguages() => - (super.noSuchMethod(Invocation.method(#fetchAndSetLanguages, []), - returnValue: Future.value(), - returnValueForMissingStub: Future.value()) as _i9.Future); - @override - _i9.Future<_i3.Exercise> fetchAndSetExercise(int? exerciseId) => - (super.noSuchMethod(Invocation.method(#fetchAndSetExercise, [exerciseId]), - returnValue: Future<_i3.Exercise>.value(_FakeExercise_1())) as _i9.Future<_i3.Exercise>); - @override - List<_i10.ExerciseBase> mapImages(dynamic data, List<_i10.ExerciseBase>? bases) => - (super.noSuchMethod(Invocation.method(#mapImages, [data, bases]), - returnValue: <_i10.ExerciseBase>[]) as List<_i10.ExerciseBase>); - @override - List<_i10.ExerciseBase> setBaseData(dynamic data, List<_i3.Exercise>? exercises) => - (super.noSuchMethod(Invocation.method(#setBaseData, [data, exercises]), - returnValue: <_i10.ExerciseBase>[]) as List<_i10.ExerciseBase>); - @override - List mapBases(List<_i10.ExerciseBase>? bases, List<_i3.Exercise>? exercises) => (super - .noSuchMethod(Invocation.method(#mapBases, [bases, exercises]), returnValue: []) - as List); - @override - List<_i3.Exercise> mapLanguages(List<_i3.Exercise>? exercises) => - (super.noSuchMethod(Invocation.method(#mapLanguages, [exercises]), - returnValue: <_i3.Exercise>[]) as List<_i3.Exercise>); - @override - List<_i3.Exercise> mapAliases(dynamic data, List<_i3.Exercise>? exercises) => - (super.noSuchMethod(Invocation.method(#mapAliases, [data, exercises]), - returnValue: <_i3.Exercise>[]) as List<_i3.Exercise>); - @override - List<_i3.Exercise> mapComments(dynamic data, List<_i3.Exercise>? exercises) => - (super.noSuchMethod(Invocation.method(#mapComments, [data, exercises]), - returnValue: <_i3.Exercise>[]) as List<_i3.Exercise>); - @override - _i9.Future checkExerciseCacheVersion() => - (super.noSuchMethod(Invocation.method(#checkExerciseCacheVersion, []), - returnValue: Future.value(), - returnValueForMissingStub: Future.value()) as _i9.Future); - @override - _i9.Future fetchAndSetExercises() => - (super.noSuchMethod(Invocation.method(#fetchAndSetExercises, []), - returnValue: Future.value(), - returnValueForMissingStub: Future.value()) as _i9.Future); - @override - _i9.Future> searchExercise(String? name, [String? languageCode = r'en']) => - (super.noSuchMethod(Invocation.method(#searchExercise, [name, languageCode]), - returnValue: Future>.value(<_i3.Exercise>[])) - as _i9.Future>); - @override - String toString() => super.toString(); - @override - void addListener(_i11.VoidCallback? listener) => super - .noSuchMethod(Invocation.method(#addListener, [listener]), returnValueForMissingStub: null); - @override - void removeListener(_i11.VoidCallback? listener) => - super.noSuchMethod(Invocation.method(#removeListener, [listener]), - returnValueForMissingStub: null); - @override - void dispose() => - super.noSuchMethod(Invocation.method(#dispose, []), returnValueForMissingStub: null); - @override - void notifyListeners() => - super.noSuchMethod(Invocation.method(#notifyListeners, []), returnValueForMissingStub: null); -} diff --git a/test/workout/workout_set_form_test.mocks.dart b/test/workout/workout_set_form_test.mocks.dart index cb9f2bf4..82385bd0 100644 --- a/test/workout/workout_set_form_test.mocks.dart +++ b/test/workout/workout_set_form_test.mocks.dart @@ -69,6 +69,11 @@ class MockExercisesProvider extends _i1.Mock implements _i8.ExercisesProvider { Invocation.setter(#filteredExerciseBases, newFilteredExercises), returnValueForMissingStub: null); @override + Map> get exerciseBasesByVariation => + (super.noSuchMethod(Invocation.getter(#exerciseBasesByVariation), + returnValue: >{}) + as Map>); + @override List<_i3.Exercise> get items => (super.noSuchMethod(Invocation.getter(#items), returnValue: <_i3.Exercise>[]) as List<_i3.Exercise>); @override diff --git a/test_data/exercises.dart b/test_data/exercises.dart index 1ffb384e..aa63efac 100644 --- a/test_data/exercises.dart +++ b/test_data/exercises.dart @@ -20,8 +20,12 @@ import 'package:wger/models/exercises/base.dart'; import 'package:wger/models/exercises/category.dart'; import 'package:wger/models/exercises/equipment.dart'; import 'package:wger/models/exercises/exercise.dart'; +import 'package:wger/models/exercises/language.dart'; import 'package:wger/models/exercises/muscle.dart'; +const tLanguage1 = Language(id: 1, shortName: 'de', fullName: 'Deutsch'); +const tLanguage2 = Language(id: 2, shortName: 'en', fullName: 'English'); + const tMuscle1 = Muscle(id: 1, name: 'Flutterus maximus', isFront: true); const tMuscle2 = Muscle(id: 2, name: 'Biceps', isFront: true); const tMuscle3 = Muscle(id: 3, name: 'Booty', isFront: false); @@ -70,35 +74,32 @@ final tBase3 = ExerciseBase( final tExercise1 = Exercise( id: 1, - baseId: 1, uuid: 'uuid', - languageId: 1, creationDate: DateTime(2021, 1, 15), name: 'test exercise 1', description: 'add clever text', base: tBase1, + language: tLanguage1, ); final tExercise2 = Exercise( id: 2, - baseId: 2, uuid: '111-2222-44444', - languageId: 2, creationDate: DateTime(2021, 1, 15), name: 'test exercise 2', description: 'Lorem ipsum etc', base: tBase2, + language: tLanguage2, ); final tExercise3 = Exercise( id: 3, - baseId: 2, uuid: 'a3b6c7bb-9d22-4119-a5fc-818584d5e9bc', - languageId: 2, creationDate: DateTime(2021, 4, 1), name: 'test exercise 3', description: 'The man in black fled across the desert, and the gunslinger followed', base: tBase3, + language: tLanguage2, ); List getTestExercises() { diff --git a/test_driver/screenshot_driver.dart b/test_driver/screenshot_driver.dart new file mode 100644 index 00000000..22c08824 --- /dev/null +++ b/test_driver/screenshot_driver.dart @@ -0,0 +1,18 @@ +import 'dart:io'; + +import 'package:integration_test/integration_test_driver_extended.dart'; + +// cf. https://dev.to/mjablecnik/take-screenshot-during-flutter-integration-tests-435k +Future main() async { + try { + await integrationDriver( + onScreenshot: (String screenshotName, List screenshotBytes) async { + final File image = await File('screenshots/$screenshotName.png').create(recursive: true); + image.writeAsBytesSync(screenshotBytes); + return true; + }, + ); + } catch (e) { + print('An error occurred: $e'); + } +}