Refactor widget so it's easier to test

This commit is contained in:
Roland Geider
2025-03-18 21:13:28 +01:00
parent 737a0d15f0
commit fea9d89621
2 changed files with 82 additions and 59 deletions

View File

@@ -22,6 +22,7 @@ import 'package:intl/intl.dart';
import 'package:provider/provider.dart';
import 'package:wger/helpers/platform.dart';
import 'package:wger/l10n/generated/app_localizations.dart';
import 'package:wger/models/gallery/image.dart' as gallery;
import 'package:wger/providers/gallery.dart';
import 'package:wger/screens/form_screen.dart';
import 'package:wger/widgets/core/text_prompt.dart';
@@ -52,64 +53,16 @@ class Gallery extends StatelessWidget {
return GestureDetector(
onTap: () {
showModalBottomSheet(
builder: (context) => Container(
key: Key('image-${currentImage.id}-detail'),
padding: const EdgeInsets.all(10),
child: Column(
children: [
Text(
DateFormat.yMd(Localizations.localeOf(context).languageCode)
.format(currentImage.date),
style: Theme.of(context).textTheme.headlineSmall,
),
Expanded(
child: Image.network(currentImage.url!),
),
Padding(
padding: const EdgeInsets.symmetric(vertical: 8),
child: Text(currentImage.description),
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
IconButton(
icon: const Icon(Icons.delete),
onPressed: () {
Provider.of<GalleryProvider>(
context,
listen: false,
).deleteImage(currentImage);
Navigator.of(context).pop();
},
),
if (!isDesktop)
IconButton(
icon: const Icon(Icons.edit),
onPressed: () {
Navigator.pushNamed(
context,
FormScreen.routeName,
arguments: FormScreenArguments(
AppLocalizations.of(context).edit,
ImageForm(currentImage),
hasListView: true,
),
);
},
),
],
),
],
),
),
builder: (context) => ImageDetail(image: currentImage),
context: context,
);
},
child: FadeInImage(
key: Key('image-${currentImage.id}'),
key: Key('image-${currentImage.id!}'),
placeholder: const AssetImage('assets/images/placeholder.png'),
image: NetworkImage(currentImage.url!),
fit: BoxFit.cover,
imageSemanticLabel: currentImage.description,
),
);
},
@@ -118,3 +71,65 @@ class Gallery extends StatelessWidget {
);
}
}
class ImageDetail extends StatelessWidget {
const ImageDetail({
super.key,
required this.image,
});
final gallery.Image image;
@override
Widget build(BuildContext context) {
return Container(
key: Key('image-${image.id!}-detail'),
padding: const EdgeInsets.all(10),
child: Column(
children: [
Text(
DateFormat.yMd(Localizations.localeOf(context).languageCode).format(image.date),
style: Theme.of(context).textTheme.headlineSmall,
),
Expanded(
child: Image.network(image.url!, semanticLabel: image.description),
),
Padding(
padding: const EdgeInsets.symmetric(vertical: 8),
child: Text(image.description),
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
IconButton(
icon: const Icon(Icons.delete),
onPressed: () {
Provider.of<GalleryProvider>(
context,
listen: false,
).deleteImage(image);
Navigator.of(context).pop();
},
),
if (!isDesktop)
IconButton(
icon: const Icon(Icons.edit),
onPressed: () {
Navigator.pushNamed(
context,
FormScreen.routeName,
arguments: FormScreenArguments(
AppLocalizations.of(context).edit,
ImageForm(image),
hasListView: true,
),
);
},
),
],
),
],
),
);
}
}

View File

@@ -25,7 +25,6 @@ import 'package:network_image_mock/network_image_mock.dart';
import 'package:provider/provider.dart';
import 'package:wger/l10n/generated/app_localizations.dart';
import 'package:wger/providers/gallery.dart';
import 'package:wger/screens/form_screen.dart';
import 'package:wger/widgets/gallery/overview.dart';
import '../../test_data/gallery.dart';
@@ -40,7 +39,7 @@ void main() {
when(mockGalleryProvider.images).thenAnswer((_) => getTestImages());
});
Widget createScreen({locale = 'en'}) {
Widget renderScreen({locale = 'en'}) {
return ChangeNotifierProvider<GalleryProvider>(
create: (context) => mockGalleryProvider,
child: MaterialApp(
@@ -48,29 +47,38 @@ void main() {
localizationsDelegates: AppLocalizations.localizationsDelegates,
supportedLocales: AppLocalizations.supportedLocales,
home: const Gallery(),
routes: {FormScreen.routeName: (ctx) => const FormScreen()},
),
);
}
Widget renderDetail({locale = 'en'}) {
return ChangeNotifierProvider<GalleryProvider>(
create: (context) => mockGalleryProvider,
child: MaterialApp(
locale: Locale(locale),
localizationsDelegates: AppLocalizations.localizationsDelegates,
supportedLocales: AppLocalizations.supportedLocales,
home: ImageDetail(image: getTestImages()[0]),
),
);
}
testWidgets('Test the widgets on the gallery screen', (WidgetTester tester) async {
await mockNetworkImagesFor(() => tester.pumpWidget(createScreen()));
await mockNetworkImagesFor(() => tester.pumpWidget(renderScreen()));
expect(find.byType(SliverMasonryGrid), findsOneWidget);
expect(find.byType(GestureDetector, skipOffstage: false), findsNWidgets(4));
});
testWidgets('Tests the localization of dates - EN', (WidgetTester tester) async {
await mockNetworkImagesFor(() => tester.pumpWidget(createScreen()));
await tester.tap(find.byKey(const Key('image-1')));
await mockNetworkImagesFor(() => tester.pumpWidget(renderDetail()));
await tester.pumpAndSettle();
expect(find.text('5/30/2021'), findsOneWidget);
});
testWidgets('Tests the localization of dates - DE', (WidgetTester tester) async {
await mockNetworkImagesFor(() => tester.pumpWidget(createScreen(locale: 'de')));
await tester.tap(find.byKey(const Key('image-1')));
await mockNetworkImagesFor(() => tester.pumpWidget(renderDetail(locale: 'de')));
await tester.pumpAndSettle();
expect(find.text('30.5.2021'), findsOneWidget);