m3_lightmeter/test/providers/films_provider_test.dart
2024-10-06 20:26:40 +02:00

259 lines
8.5 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 _MockIAPStorageService extends Mock implements IAPStorageService {}
void main() {
TestWidgetsFlutterBinding.ensureInitialized();
late _MockIAPStorageService mockIAPStorageService;
setUpAll(() {
mockIAPStorageService = _MockIAPStorageService();
});
tearDown(() {
reset(mockIAPStorageService);
});
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: mockIAPStorageService,
availableFilms: mockFilms,
child: const _Application(),
),
),
);
}
void expectFilmsCount(int count) {
expect(find.text('Films count: $count'), findsOneWidget);
}
void expectFilmsInUseCount(int count) {
expect(find.text('Films in use count: $count'), findsOneWidget);
}
void expectSelectedFilmName(String name) {
expect(find.text('Selected film: $name'), findsOneWidget);
}
group(
'FilmsProvider dependency on IAPProductStatus',
() {
setUp(() {
when(() => mockIAPStorageService.selectedFilm).thenReturn(mockFilms.first);
when(() => mockIAPStorageService.filmsInUse).thenReturn(mockFilms);
});
testWidgets(
'IAPProductStatus.purchased - show all saved films',
(tester) async {
await pumpTestWidget(tester, IAPProductStatus.purchased);
expectFilmsCount(mockFilms.length + 1);
expectFilmsInUseCount(mockFilms.length + 1);
expectSelectedFilmName(mockFilms.first.name);
},
);
testWidgets(
'IAPProductStatus.purchasable - show only default',
(tester) async {
await pumpTestWidget(tester, IAPProductStatus.purchasable);
expectFilmsCount(mockFilms.length + 1);
expectFilmsInUseCount(1);
expectSelectedFilmName('');
},
);
testWidgets(
'IAPProductStatus.pending - show only default',
(tester) async {
await pumpTestWidget(tester, IAPProductStatus.pending);
expectFilmsCount(mockFilms.length + 1);
expectFilmsInUseCount(1);
expectSelectedFilmName('');
},
);
},
);
group(
'FilmsProvider CRUD',
() {
testWidgets(
'Select films in use',
(tester) async {
when(() => mockIAPStorageService.selectedFilm).thenReturn(const FilmStub());
when(() => mockIAPStorageService.filmsInUse).thenReturn([]);
/// Init
await pumpTestWidget(tester, IAPProductStatus.purchased);
expectFilmsCount(mockFilms.length + 1);
expectFilmsInUseCount(1);
expectSelectedFilmName('');
/// Select all filmsInUse
await tester.tap(find.byKey(_Application.saveFilmsButtonKey(0)));
await tester.pumpAndSettle();
expectFilmsCount(mockFilms.length + 1);
expectFilmsInUseCount(mockFilms.length + 1);
expectSelectedFilmName('');
verify(() => mockIAPStorageService.filmsInUse = mockFilms.skip(0).toList()).called(1);
verifyNever(() => mockIAPStorageService.selectedFilm = const FilmStub());
},
);
testWidgets(
'Select film',
(tester) async {
when(() => mockIAPStorageService.selectedFilm).thenReturn(const FilmStub());
when(() => mockIAPStorageService.filmsInUse).thenReturn(mockFilms);
/// Init
await pumpTestWidget(tester, IAPProductStatus.purchased);
expectFilmsCount(mockFilms.length + 1);
expectFilmsInUseCount(mockFilms.length + 1);
expectSelectedFilmName('');
/// Select all filmsInUse
await tester.tap(find.byKey(_Application.setFilmButtonKey(0)));
await tester.pumpAndSettle();
expectFilmsCount(mockFilms.length + 1);
expectFilmsInUseCount(mockFilms.length + 1);
expectSelectedFilmName(mockFilms.first.name);
verifyNever(() => mockIAPStorageService.filmsInUse = any<List<Film>>());
verify(() => mockIAPStorageService.selectedFilm = mockFilms.first).called(1);
},
);
group(
'Coming from free app',
() {
testWidgets(
'Has selected film',
(tester) async {
when(() => mockIAPStorageService.selectedFilm).thenReturn(mockFilms[2]);
when(() => mockIAPStorageService.filmsInUse).thenReturn([]);
/// Init
await pumpTestWidget(tester, IAPProductStatus.purchased);
expectFilmsInUseCount(1);
expectSelectedFilmName('');
verifyNever(() => mockIAPStorageService.filmsInUse = any<List<Film>>());
verify(() => mockIAPStorageService.selectedFilm = const FilmStub()).called(1);
},
);
testWidgets(
'None film selected',
(tester) async {
when(() => mockIAPStorageService.selectedFilm).thenReturn(const FilmStub());
when(() => mockIAPStorageService.filmsInUse).thenReturn([]);
/// Init
await pumpTestWidget(tester, IAPProductStatus.purchased);
expectFilmsInUseCount(1);
expectSelectedFilmName('');
verifyNever(() => mockIAPStorageService.filmsInUse = any<List<Film>>());
verifyNever(() => mockIAPStorageService.selectedFilm = const FilmStub());
},
);
},
);
testWidgets(
'Discard selected (by filmsInUse list update)',
(tester) async {
when(() => mockIAPStorageService.selectedFilm).thenReturn(mockFilms.first);
when(() => mockIAPStorageService.filmsInUse).thenReturn(mockFilms);
/// Init
await pumpTestWidget(tester, IAPProductStatus.purchased);
expectFilmsCount(mockFilms.length + 1);
expectFilmsInUseCount(mockFilms.length + 1);
expectSelectedFilmName(mockFilms.first.name);
/// Select all filmsInUse except the first one
await tester.tap(find.byKey(_Application.saveFilmsButtonKey(1)));
await tester.pumpAndSettle();
expectFilmsCount(mockFilms.length + 1);
expectFilmsInUseCount((mockFilms.length - 1) + 1);
expectSelectedFilmName('');
verify(() => mockIAPStorageService.filmsInUse = mockFilms.skip(1).toList()).called(1);
verify(() => mockIAPStorageService.selectedFilm = const FilmStub()).called(1);
},
);
},
);
}
class _Application extends StatelessWidget {
const _Application();
static ValueKey saveFilmsButtonKey(int index) => ValueKey('saveFilmsButtonKey$index');
static ValueKey setFilmButtonKey(int index) => ValueKey('setFilmButtonKey$index');
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: Center(
child: Column(
children: [
Text("Films count: ${Films.of(context).length}"),
Text("Films in use count: ${Films.inUseOf(context).length}"),
Text("Selected film: ${Films.selectedOf(context).name}"),
_filmRow(context, 0),
_filmRow(context, 1),
],
),
),
),
);
}
Widget _filmRow(BuildContext context, int index) {
return Row(
children: [
ElevatedButton(
key: saveFilmsButtonKey(index),
onPressed: () {
FilmsProvider.of(context).saveFilms(mockFilms.skip(index).toList());
},
child: const Text("Save filmsInUse"),
),
ElevatedButton(
key: setFilmButtonKey(index),
onPressed: () {
FilmsProvider.of(context).setFilm(mockFilms[index]);
},
child: const Text("Set film"),
),
],
);
}
}
const mockFilms = [
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),
];