mirror of
https://github.com/wger-project/flutter.git
synced 2026-02-18 00:17:48 +01:00
Start working on automatic screenshot generation
This commit is contained in:
8
integration_test/README.md
Normal file
8
integration_test/README.md
Normal file
@@ -0,0 +1,8 @@
|
||||
Start emulator and run
|
||||
|
||||
`flutter drive --driver=test_driver/screenshot_driver.dart --target=integration_test/app_test.dart`
|
||||
|
||||
|
||||
See
|
||||
* <https://github.com/openfoodfacts/smooth-app/issues/217#issuecomment-1092678779>
|
||||
* <https://dev.to/mjablecnik/take-screenshot-during-flutter-integration-tests-435k>
|
||||
434
integration_test/app_test.dart
Normal file
434
integration_test/app_test.dart
Normal file
@@ -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<void> 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<NavigatorState>();
|
||||
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<NutritionPlansProvider>(
|
||||
create: (context) => NutritionPlansProvider(testAuthProvider, [], client),
|
||||
),
|
||||
ChangeNotifierProvider<BodyWeightProvider>(
|
||||
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<void>(
|
||||
settings: RouteSettings(arguments: plan),
|
||||
builder: (_) => NutritionalPlanScreen(),
|
||||
),
|
||||
),
|
||||
child: const SizedBox(),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget createWeightScreen({locale = 'en'}) {
|
||||
return ChangeNotifierProvider<BodyWeightProvider>(
|
||||
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<NavigatorState>();
|
||||
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<WorkoutPlansProvider>(
|
||||
create: (context) => WorkoutPlansProvider(
|
||||
testAuthProvider,
|
||||
mockExerciseProvider,
|
||||
[workout],
|
||||
client,
|
||||
),
|
||||
child: ChangeNotifierProvider<ExercisesProvider>(
|
||||
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<void>(
|
||||
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');
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -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();
|
||||
|
||||
@@ -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(
|
||||
|
||||
99
pubspec.lock
99
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"
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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<void> setFilters(_i8.Filters? newFilters) =>
|
||||
(super.noSuchMethod(Invocation.method(#setFilters, [newFilters]),
|
||||
returnValue: Future<void>.value(),
|
||||
returnValueForMissingStub: Future<void>.value()) as _i9.Future<void>);
|
||||
@override
|
||||
_i9.Future<void> findByFilters() => (super.noSuchMethod(Invocation.method(#findByFilters, []),
|
||||
returnValue: Future<void>.value(),
|
||||
returnValueForMissingStub: Future<void>.value()) as _i9.Future<void>);
|
||||
@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<void> fetchAndSetCategories() =>
|
||||
(super.noSuchMethod(Invocation.method(#fetchAndSetCategories, []),
|
||||
returnValue: Future<void>.value(),
|
||||
returnValueForMissingStub: Future<void>.value()) as _i9.Future<void>);
|
||||
@override
|
||||
_i9.Future<void> fetchAndSetVariations() =>
|
||||
(super.noSuchMethod(Invocation.method(#fetchAndSetVariations, []),
|
||||
returnValue: Future<void>.value(),
|
||||
returnValueForMissingStub: Future<void>.value()) as _i9.Future<void>);
|
||||
@override
|
||||
_i9.Future<void> fetchAndSetMuscles() =>
|
||||
(super.noSuchMethod(Invocation.method(#fetchAndSetMuscles, []),
|
||||
returnValue: Future<void>.value(),
|
||||
returnValueForMissingStub: Future<void>.value()) as _i9.Future<void>);
|
||||
@override
|
||||
_i9.Future<void> fetchAndSetEquipment() =>
|
||||
(super.noSuchMethod(Invocation.method(#fetchAndSetEquipment, []),
|
||||
returnValue: Future<void>.value(),
|
||||
returnValueForMissingStub: Future<void>.value()) as _i9.Future<void>);
|
||||
@override
|
||||
_i9.Future<void> fetchAndSetLanguages() =>
|
||||
(super.noSuchMethod(Invocation.method(#fetchAndSetLanguages, []),
|
||||
returnValue: Future<void>.value(),
|
||||
returnValueForMissingStub: Future<void>.value()) as _i9.Future<void>);
|
||||
@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<dynamic> mapBases(List<_i10.ExerciseBase>? bases, List<_i3.Exercise>? exercises) => (super
|
||||
.noSuchMethod(Invocation.method(#mapBases, [bases, exercises]), returnValue: <dynamic>[])
|
||||
as List<dynamic>);
|
||||
@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<void> checkExerciseCacheVersion() =>
|
||||
(super.noSuchMethod(Invocation.method(#checkExerciseCacheVersion, []),
|
||||
returnValue: Future<void>.value(),
|
||||
returnValueForMissingStub: Future<void>.value()) as _i9.Future<void>);
|
||||
@override
|
||||
_i9.Future<void> fetchAndSetExercises() =>
|
||||
(super.noSuchMethod(Invocation.method(#fetchAndSetExercises, []),
|
||||
returnValue: Future<void>.value(),
|
||||
returnValueForMissingStub: Future<void>.value()) as _i9.Future<void>);
|
||||
@override
|
||||
_i9.Future<List<_i3.Exercise>> searchExercise(String? name, [String? languageCode = r'en']) =>
|
||||
(super.noSuchMethod(Invocation.method(#searchExercise, [name, languageCode]),
|
||||
returnValue: Future<List<_i3.Exercise>>.value(<_i3.Exercise>[]))
|
||||
as _i9.Future<List<_i3.Exercise>>);
|
||||
@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);
|
||||
}
|
||||
@@ -69,6 +69,11 @@ class MockExercisesProvider extends _i1.Mock implements _i8.ExercisesProvider {
|
||||
Invocation.setter(#filteredExerciseBases, newFilteredExercises),
|
||||
returnValueForMissingStub: null);
|
||||
@override
|
||||
Map<int, List<_i9.ExerciseBase>> get exerciseBasesByVariation =>
|
||||
(super.noSuchMethod(Invocation.getter(#exerciseBasesByVariation),
|
||||
returnValue: <int, List<_i9.ExerciseBase>>{})
|
||||
as Map<int, List<_i9.ExerciseBase>>);
|
||||
@override
|
||||
List<_i3.Exercise> get items => (super.noSuchMethod(Invocation.getter(#items),
|
||||
returnValue: <_i3.Exercise>[]) as List<_i3.Exercise>);
|
||||
@override
|
||||
|
||||
@@ -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<Exercise> getTestExercises() {
|
||||
|
||||
18
test_driver/screenshot_driver.dart
Normal file
18
test_driver/screenshot_driver.dart
Normal file
@@ -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<void> main() async {
|
||||
try {
|
||||
await integrationDriver(
|
||||
onScreenshot: (String screenshotName, List<int> 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');
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user