mirror of
https://github.com/vodemn/m3_lightmeter.git
synced 2024-11-24 00:10:47 +00:00
30418a9cfd
* integrated `EquipmentProfilesStorageService` * implemented `EquipmentProfileEditScreen` * added equipment profiles screens to navigation * fixed tests * fixed splashscreen removal * replaced old `EquipmentProfilesScreen` * typo * use outlined icons * fixed storage mock for integration tests * recovered copy feature for profiles * added profile deletion to e2e test * added translations * added film translations * wip * add ability to toggle equipment profiles * lints * fixed tests * sync with iap rename * use `Toggleable` from resources * use iap 2.1.0 * use outlined edit icon
310 lines
11 KiB
Dart
310 lines
11 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:flutter_test/flutter_test.dart';
|
|
import 'package:lightmeter/providers/films_provider.dart';
|
|
import 'package:m3_lightmeter_iap/m3_lightmeter_iap.dart';
|
|
import 'package:m3_lightmeter_resources/m3_lightmeter_resources.dart';
|
|
import 'package:mocktail/mocktail.dart';
|
|
|
|
class _MockFilmsStorageService extends Mock implements FilmsStorageService {}
|
|
|
|
void main() {
|
|
TestWidgetsFlutterBinding.ensureInitialized();
|
|
late _MockFilmsStorageService storageService;
|
|
|
|
setUpAll(() {
|
|
storageService = _MockFilmsStorageService();
|
|
});
|
|
|
|
setUp(() {
|
|
registerFallbackValue(mockCustomFilms.first);
|
|
when(() => storageService.toggleFilm(any<Film>(), any<bool>())).thenAnswer((_) async {});
|
|
when(() => storageService.addFilm(any<FilmExponential>())).thenAnswer((_) async {});
|
|
when(() => storageService.updateFilm(any<FilmExponential>())).thenAnswer((_) async {});
|
|
when(() => storageService.deleteFilm(any<FilmExponential>())).thenAnswer((_) async {});
|
|
when(() => storageService.getPredefinedFilms()).thenAnswer((_) => Future.value(mockPredefinedFilms.toFilmsMap()));
|
|
when(() => storageService.getCustomFilms()).thenAnswer((_) => Future.value(mockCustomFilms.toFilmsMap()));
|
|
});
|
|
|
|
tearDown(() {
|
|
reset(storageService);
|
|
});
|
|
|
|
Future<void> pumpTestWidget(WidgetTester tester, IAPProductStatus productStatus) async {
|
|
await tester.pumpWidget(
|
|
IAPProducts(
|
|
products: [
|
|
IAPProduct(
|
|
storeId: IAPProductType.paidFeatures.storeId,
|
|
status: productStatus,
|
|
price: '0.0\$',
|
|
),
|
|
],
|
|
child: FilmsProvider(
|
|
storageService: storageService,
|
|
child: const _Application(),
|
|
),
|
|
),
|
|
);
|
|
await tester.pumpAndSettle();
|
|
}
|
|
|
|
void expectPredefinedFilmsCount(int count) {
|
|
expect(find.text(_PredefinedFilmsCount.text(count)), findsOneWidget);
|
|
}
|
|
|
|
void expectCustomFilmsCount(int count) {
|
|
expect(find.text(_CustomFilmsCount.text(count)), findsOneWidget);
|
|
}
|
|
|
|
void expectFilmsInUseCount(int count) {
|
|
expect(find.text(_FilmsInUseCount.text(count)), findsOneWidget);
|
|
}
|
|
|
|
void expectSelectedFilmName(String name) {
|
|
expect(find.text(_SelectedFilm.text(name)), findsOneWidget);
|
|
}
|
|
|
|
group(
|
|
'FilmsProvider dependency on IAPProductStatus',
|
|
() {
|
|
setUp(() {
|
|
when(() => storageService.selectedFilmId).thenReturn(mockPredefinedFilms.first.id);
|
|
when(() => storageService.getPredefinedFilms())
|
|
.thenAnswer((_) => Future.value(mockPredefinedFilms.toFilmsMap()));
|
|
when(() => storageService.getCustomFilms()).thenAnswer((_) => Future.value(mockCustomFilms.toFilmsMap()));
|
|
});
|
|
|
|
testWidgets(
|
|
'IAPProductStatus.purchased - show all saved films',
|
|
(tester) async {
|
|
await pumpTestWidget(tester, IAPProductStatus.purchased);
|
|
expectPredefinedFilmsCount(mockPredefinedFilms.length);
|
|
expectCustomFilmsCount(mockCustomFilms.length);
|
|
expectFilmsInUseCount(mockPredefinedFilms.length + mockCustomFilms.length + 1);
|
|
expectSelectedFilmName(mockPredefinedFilms.first.name);
|
|
},
|
|
);
|
|
|
|
testWidgets(
|
|
'IAPProductStatus.purchasable - show only default',
|
|
(tester) async {
|
|
await pumpTestWidget(tester, IAPProductStatus.purchasable);
|
|
expectPredefinedFilmsCount(0);
|
|
expectCustomFilmsCount(0);
|
|
expectFilmsInUseCount(1);
|
|
expectSelectedFilmName('');
|
|
},
|
|
);
|
|
|
|
testWidgets(
|
|
'IAPProductStatus.pending - show only default',
|
|
(tester) async {
|
|
await pumpTestWidget(tester, IAPProductStatus.pending);
|
|
expectPredefinedFilmsCount(0);
|
|
expectCustomFilmsCount(0);
|
|
expectFilmsInUseCount(1);
|
|
expectSelectedFilmName('');
|
|
},
|
|
);
|
|
},
|
|
);
|
|
|
|
group(
|
|
'toggleFilm',
|
|
() {
|
|
testWidgets(
|
|
'toggle predefined film',
|
|
(tester) async {
|
|
when(() => storageService.selectedFilmId).thenReturn(mockPredefinedFilms.first.id);
|
|
await pumpTestWidget(tester, IAPProductStatus.purchased);
|
|
expectPredefinedFilmsCount(mockPredefinedFilms.length);
|
|
expectCustomFilmsCount(mockCustomFilms.length);
|
|
expectFilmsInUseCount(mockPredefinedFilms.length + mockCustomFilms.length + 1);
|
|
expectSelectedFilmName(mockPredefinedFilms.first.name);
|
|
|
|
await tester.filmsProvider.toggleFilm(mockPredefinedFilms.first, false);
|
|
await tester.pump();
|
|
expectPredefinedFilmsCount(mockPredefinedFilms.length);
|
|
expectCustomFilmsCount(mockCustomFilms.length);
|
|
expectFilmsInUseCount(mockPredefinedFilms.length - 1 + mockCustomFilms.length + 1);
|
|
expectSelectedFilmName('');
|
|
|
|
verify(() => storageService.toggleFilm(mockPredefinedFilms.first, false)).called(1);
|
|
verify(() => storageService.selectedFilmId = '').called(1);
|
|
},
|
|
);
|
|
|
|
testWidgets(
|
|
'toggle custom film',
|
|
(tester) async {
|
|
when(() => storageService.selectedFilmId).thenReturn(mockCustomFilms.first.id);
|
|
await pumpTestWidget(tester, IAPProductStatus.purchased);
|
|
expectPredefinedFilmsCount(mockPredefinedFilms.length);
|
|
expectCustomFilmsCount(mockCustomFilms.length);
|
|
expectFilmsInUseCount(mockPredefinedFilms.length + mockCustomFilms.length + 1);
|
|
expectSelectedFilmName(mockCustomFilms.first.name);
|
|
|
|
await tester.filmsProvider.toggleFilm(mockCustomFilms.first, false);
|
|
await tester.pump();
|
|
expectPredefinedFilmsCount(mockPredefinedFilms.length);
|
|
expectCustomFilmsCount(mockCustomFilms.length);
|
|
expectFilmsInUseCount(mockPredefinedFilms.length - 1 + mockCustomFilms.length + 1);
|
|
expectSelectedFilmName('');
|
|
|
|
verify(() => storageService.toggleFilm(mockCustomFilms.first, false)).called(1);
|
|
verify(() => storageService.selectedFilmId = '').called(1);
|
|
},
|
|
);
|
|
},
|
|
);
|
|
|
|
testWidgets(
|
|
'selectFilm',
|
|
(tester) async {
|
|
when(() => storageService.selectedFilmId).thenReturn('');
|
|
await pumpTestWidget(tester, IAPProductStatus.purchased);
|
|
expectSelectedFilmName('');
|
|
|
|
tester.filmsProvider.selectFilm(mockPredefinedFilms.first);
|
|
await tester.pump();
|
|
expectSelectedFilmName(mockPredefinedFilms.first.name);
|
|
|
|
tester.filmsProvider.selectFilm(mockCustomFilms.first);
|
|
await tester.pump();
|
|
expectSelectedFilmName(mockCustomFilms.first.name);
|
|
|
|
verify(() => storageService.selectedFilmId = mockPredefinedFilms.first.id).called(1);
|
|
verify(() => storageService.selectedFilmId = mockCustomFilms.first.id).called(1);
|
|
},
|
|
);
|
|
|
|
testWidgets(
|
|
'Custom film CRUD',
|
|
(tester) async {
|
|
when(() => storageService.selectedFilmId).thenReturn('');
|
|
when(() => storageService.getCustomFilms()).thenAnswer((_) => Future.value({}));
|
|
await pumpTestWidget(tester, IAPProductStatus.purchased);
|
|
expectPredefinedFilmsCount(mockPredefinedFilms.length);
|
|
expectCustomFilmsCount(0);
|
|
expectFilmsInUseCount(mockPredefinedFilms.length + 0 + 1);
|
|
expectSelectedFilmName('');
|
|
|
|
await tester.filmsProvider.addCustomFilm(mockCustomFilms.first);
|
|
await tester.filmsProvider.toggleFilm(mockCustomFilms.first, true);
|
|
tester.filmsProvider.selectFilm(mockCustomFilms.first);
|
|
await tester.pump();
|
|
expectPredefinedFilmsCount(mockPredefinedFilms.length);
|
|
expectCustomFilmsCount(1);
|
|
expectFilmsInUseCount(mockPredefinedFilms.length + 1 + 1);
|
|
expectSelectedFilmName(mockCustomFilms.first.name);
|
|
verify(() => storageService.addFilm(mockCustomFilms.first)).called(1);
|
|
verify(() => storageService.toggleFilm(mockCustomFilms.first, true)).called(1);
|
|
verify(() => storageService.selectedFilmId = mockCustomFilms.first.id).called(1);
|
|
|
|
const editedFilmName = 'Edited custom film 2x';
|
|
final editedFilm = mockCustomFilms.first.copyWith(name: editedFilmName);
|
|
await tester.filmsProvider.updateCustomFilm(editedFilm);
|
|
await tester.pump();
|
|
expectSelectedFilmName(editedFilm.name);
|
|
verify(() => storageService.updateFilm(editedFilm)).called(1);
|
|
|
|
await tester.filmsProvider.deleteCustomFilm(editedFilm);
|
|
await tester.pump();
|
|
expectPredefinedFilmsCount(mockPredefinedFilms.length);
|
|
expectCustomFilmsCount(0);
|
|
expectFilmsInUseCount(mockPredefinedFilms.length + 0 + 1);
|
|
expectSelectedFilmName('');
|
|
verify(() => storageService.deleteFilm(editedFilm)).called(1);
|
|
verify(() => storageService.selectedFilmId = '').called(1);
|
|
},
|
|
);
|
|
}
|
|
|
|
extension on WidgetTester {
|
|
FilmsProviderState get filmsProvider {
|
|
final BuildContext context = element(find.byType(_Application));
|
|
return FilmsProvider.of(context);
|
|
}
|
|
}
|
|
|
|
class _Application extends StatelessWidget {
|
|
const _Application();
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return const MaterialApp(
|
|
home: Scaffold(
|
|
body: Center(
|
|
child: Column(
|
|
children: [
|
|
_PredefinedFilmsCount(),
|
|
_CustomFilmsCount(),
|
|
_FilmsInUseCount(),
|
|
_SelectedFilm(),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
class _PredefinedFilmsCount extends StatelessWidget {
|
|
static String text(int count) => "Predefined films count: $count";
|
|
|
|
const _PredefinedFilmsCount();
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Text(text(Films.predefinedFilmsOf(context).length));
|
|
}
|
|
}
|
|
|
|
class _CustomFilmsCount extends StatelessWidget {
|
|
static String text(int count) => "Custom films count: $count";
|
|
|
|
const _CustomFilmsCount();
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Text(text(Films.customFilmsOf(context).length));
|
|
}
|
|
}
|
|
|
|
class _FilmsInUseCount extends StatelessWidget {
|
|
static String text(int count) => "Films in use count: $count";
|
|
|
|
const _FilmsInUseCount();
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Text(text(Films.inUseOf(context).length));
|
|
}
|
|
}
|
|
|
|
class _SelectedFilm extends StatelessWidget {
|
|
static String text(String name) => "Selected film: $name}";
|
|
|
|
const _SelectedFilm();
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Text(text(Films.selectedOf(context).name));
|
|
}
|
|
}
|
|
|
|
const mockPredefinedFilms = [
|
|
FilmExponential(id: '1', name: 'Mock film 2x', iso: 400, exponent: 1.34),
|
|
FilmExponential(id: '2', name: 'Mock film 3x', iso: 800, exponent: 1.34),
|
|
FilmExponential(id: '3', name: 'Mock film 4x', iso: 1200, exponent: 1.34),
|
|
];
|
|
|
|
const mockCustomFilms = [
|
|
FilmExponential(id: '1abc', name: 'Mock custom film 2x', iso: 400, exponent: 1.34),
|
|
FilmExponential(id: '2abc', name: 'Mock custom film 3x', iso: 800, exponent: 1.34),
|
|
];
|
|
|
|
extension on List<Film> {
|
|
Map<String, ({T value, bool isUsed})> toFilmsMap<T extends Film>() =>
|
|
Map.fromEntries(map((e) => MapEntry(e.id, (value: e as T, isUsed: true))));
|
|
}
|