fixed unit tests

This commit is contained in:
Vadim 2025-09-05 22:18:15 +02:00
parent 88702942d3
commit 7b81c99a4d
4 changed files with 181 additions and 40 deletions

View file

@ -15,6 +15,7 @@ class _MockGeolocationService extends Mock implements GeolocationService {}
class MockIAPProviders extends StatefulWidget { class MockIAPProviders extends StatefulWidget {
final TogglableMap<EquipmentProfile> equipmentProfiles; final TogglableMap<EquipmentProfile> equipmentProfiles;
final TogglableMap<PinholeEquipmentProfile> pinholeEquipmentProfiles;
final String selectedEquipmentProfileId; final String selectedEquipmentProfileId;
final TogglableMap<Film> predefinedFilms; final TogglableMap<Film> predefinedFilms;
final TogglableMap<FilmExponential> customFilms; final TogglableMap<FilmExponential> customFilms;
@ -23,6 +24,7 @@ class MockIAPProviders extends StatefulWidget {
MockIAPProviders({ MockIAPProviders({
TogglableMap<EquipmentProfile>? equipmentProfiles, TogglableMap<EquipmentProfile>? equipmentProfiles,
TogglableMap<PinholeEquipmentProfile>? pinholeEquipmentProfiles,
this.selectedEquipmentProfileId = '', this.selectedEquipmentProfileId = '',
TogglableMap<Film>? predefinedFilms, TogglableMap<Film>? predefinedFilms,
TogglableMap<FilmExponential>? customFilms, TogglableMap<FilmExponential>? customFilms,
@ -30,6 +32,7 @@ class MockIAPProviders extends StatefulWidget {
required this.child, required this.child,
super.key, super.key,
}) : equipmentProfiles = equipmentProfiles ?? mockEquipmentProfiles.toTogglableMap(), }) : equipmentProfiles = equipmentProfiles ?? mockEquipmentProfiles.toTogglableMap(),
pinholeEquipmentProfiles = pinholeEquipmentProfiles ?? mockPinholeEquipmentProfiles.toTogglableMap(),
predefinedFilms = predefinedFilms ?? mockFilms.toTogglableMap(), predefinedFilms = predefinedFilms ?? mockFilms.toTogglableMap(),
customFilms = customFilms ?? mockFilms.toTogglableMap(), customFilms = customFilms ?? mockFilms.toTogglableMap(),
selectedFilmId = selectedFilmId ?? const FilmStub().id; selectedFilmId = selectedFilmId ?? const FilmStub().id;
@ -46,15 +49,20 @@ class _MockIAPProvidersState extends State<MockIAPProviders> {
void initState() { void initState() {
super.initState(); super.initState();
registerFallbackValue(defaultEquipmentProfile); registerFallbackValue(defaultEquipmentProfile);
registerFallbackValue(mockPinholeEquipmentProfiles.first);
registerFallbackValue(defaultCustomPhotos.first); registerFallbackValue(defaultCustomPhotos.first);
registerFallbackValue(ApertureValue.values.first); registerFallbackValue(ApertureValue.values.first);
registerFallbackValue(ShutterSpeedValue.values.first); registerFallbackValue(ShutterSpeedValue.values.first);
mockIapStorageService = _MockIapStorageService(); mockIapStorageService = _MockIapStorageService();
when(() => mockIapStorageService.init()).thenAnswer((_) async {}); when(() => mockIapStorageService.init()).thenAnswer((_) async {});
when(() => mockIapStorageService.getEquipmentProfiles()).thenAnswer((_) => Future.value(widget.equipmentProfiles));
when(() => mockIapStorageService.selectedEquipmentProfileId).thenReturn(widget.selectedEquipmentProfileId); when(() => mockIapStorageService.selectedEquipmentProfileId).thenReturn(widget.selectedEquipmentProfileId);
when(() => mockIapStorageService.getEquipmentProfiles()).thenAnswer((_) => Future.value(widget.equipmentProfiles));
when(() => mockIapStorageService.getPinholeEquipmentProfiles())
.thenAnswer((_) => Future.value(widget.pinholeEquipmentProfiles));
when(() => mockIapStorageService.addEquipmentProfile(any<EquipmentProfile>())).thenAnswer((_) async {}); when(() => mockIapStorageService.addEquipmentProfile(any<EquipmentProfile>())).thenAnswer((_) async {});
when(() => mockIapStorageService.addPinholeEquipmentProfile(any<PinholeEquipmentProfile>()))
.thenAnswer((_) async {});
when( when(
() => mockIapStorageService.updateEquipmentProfile( () => mockIapStorageService.updateEquipmentProfile(
id: any<String>(named: 'id'), id: any<String>(named: 'id'),
@ -62,7 +70,14 @@ class _MockIAPProvidersState extends State<MockIAPProviders> {
isUsed: any<bool>(named: 'isUsed'), isUsed: any<bool>(named: 'isUsed'),
), ),
).thenAnswer((_) async {}); ).thenAnswer((_) async {});
when(
() => mockIapStorageService.updatePinholeEquipmentProfile(
id: any<String>(named: 'id'),
name: any<String>(named: 'name'),
),
).thenAnswer((_) async {});
when(() => mockIapStorageService.deleteEquipmentProfile(any<String>())).thenAnswer((_) async {}); when(() => mockIapStorageService.deleteEquipmentProfile(any<String>())).thenAnswer((_) async {});
when(() => mockIapStorageService.deletePinholeEquipmentProfile(any<String>())).thenAnswer((_) async {});
when(() => mockIapStorageService.getPredefinedFilms()).thenAnswer((_) => Future.value(widget.predefinedFilms)); when(() => mockIapStorageService.getPredefinedFilms()).thenAnswer((_) => Future.value(widget.predefinedFilms));
when(() => mockIapStorageService.getCustomFilms()).thenAnswer((_) => Future.value(widget.customFilms)); when(() => mockIapStorageService.getCustomFilms()).thenAnswer((_) => Future.value(widget.customFilms));
@ -175,6 +190,31 @@ final mockEquipmentProfiles = [
), ),
]; ];
final mockPinholeEquipmentProfiles = [
PinholeEquipmentProfile(
id: '3',
name: 'Pinhole Camera f/64',
aperture: 64.0,
isoValues: [
IsoValue.values[1],
IsoValue.values[2],
IsoValue.values[3],
],
ndValues: const [NdValue(0)],
),
PinholeEquipmentProfile(
id: '4',
name: 'Pinhole Camera f/128',
aperture: 128.0,
isoValues: [
IsoValue.values[1],
IsoValue.values[2],
IsoValue.values[3],
],
ndValues: const [NdValue(0)],
),
];
const mockFilms = [ const mockFilms = [
_FilmMultiplying(id: '1', name: 'Mock film 1', iso: 100, reciprocityMultiplier: 2), _FilmMultiplying(id: '1', name: 'Mock film 1', iso: 100, reciprocityMultiplier: 2),
_FilmMultiplying(id: '2', name: 'Mock film 2', iso: 400, reciprocityMultiplier: 2), _FilmMultiplying(id: '2', name: 'Mock film 2', iso: 400, reciprocityMultiplier: 2),

View file

@ -16,7 +16,7 @@ void main() {
}); });
setUp(() { setUp(() {
registerFallbackValue(_customProfiles.first); registerFallbackValue(_mockEquipmentProfiles.first);
when(() => storageService.addEquipmentProfile(any<EquipmentProfile>())).thenAnswer((_) async {}); when(() => storageService.addEquipmentProfile(any<EquipmentProfile>())).thenAnswer((_) async {});
when( when(
() => storageService.updateEquipmentProfile( () => storageService.updateEquipmentProfile(
@ -26,7 +26,10 @@ void main() {
), ),
).thenAnswer((_) async {}); ).thenAnswer((_) async {});
when(() => storageService.deleteEquipmentProfile(any<String>())).thenAnswer((_) async {}); when(() => storageService.deleteEquipmentProfile(any<String>())).thenAnswer((_) async {});
when(() => storageService.getEquipmentProfiles()).thenAnswer((_) => Future.value(_customProfiles.toTogglableMap())); when(() => storageService.getEquipmentProfiles())
.thenAnswer((_) => Future.value(_mockEquipmentProfiles.toTogglableMap()));
when(() => storageService.getPinholeEquipmentProfiles())
.thenAnswer((_) => Future.value(_mockPinholeEquipmentProfiles.toTogglableMap()));
}); });
tearDown(() { tearDown(() {
@ -62,17 +65,15 @@ void main() {
'EquipmentProfilesProvider dependency on IAPProductStatus', 'EquipmentProfilesProvider dependency on IAPProductStatus',
() { () {
setUp(() { setUp(() {
when(() => storageService.selectedEquipmentProfileId).thenReturn(_customProfiles.first.id); when(() => storageService.selectedEquipmentProfileId).thenReturn(_mockProfiles.first.id);
when(() => storageService.getEquipmentProfiles())
.thenAnswer((_) => Future.value(_customProfiles.toTogglableMap()));
}); });
testWidgets( testWidgets(
'Pro - show all saved profiles', 'Pro - show all saved profiles',
(tester) async { (tester) async {
await pumpTestWidget(tester, true); await pumpTestWidget(tester, true);
expectEquipmentProfilesCount(_customProfiles.length + 1); expectEquipmentProfilesCount(_mockProfiles.length + 1);
expectSelectedEquipmentProfileName(_customProfiles.first.name); expectSelectedEquipmentProfileName(_mockProfiles.first.name);
}, },
); );
@ -90,19 +91,19 @@ void main() {
testWidgets( testWidgets(
'toggleProfile', 'toggleProfile',
(tester) async { (tester) async {
when(() => storageService.selectedEquipmentProfileId).thenReturn(_customProfiles.first.id); when(() => storageService.selectedEquipmentProfileId).thenReturn(_mockEquipmentProfiles.first.id);
await pumpTestWidget(tester, true); await pumpTestWidget(tester, true);
expectEquipmentProfilesCount(_customProfiles.length + 1); expectEquipmentProfilesCount(_mockProfiles.length + 1);
expectEquipmentProfilesInUseCount(_customProfiles.length + 1); expectEquipmentProfilesInUseCount(_mockProfiles.length + 1);
expectSelectedEquipmentProfileName(_customProfiles.first.name); expectSelectedEquipmentProfileName(_mockEquipmentProfiles.first.name);
await tester.equipmentProfilesProvider.toggleProfile(_customProfiles.first, false); await tester.equipmentProfilesProvider.toggleProfile(_mockEquipmentProfiles.first.id, false);
await tester.pump(); await tester.pump();
expectEquipmentProfilesCount(_customProfiles.length + 1); expectEquipmentProfilesCount(_mockProfiles.length + 1);
expectEquipmentProfilesInUseCount(_customProfiles.length + 1 - 1); expectEquipmentProfilesInUseCount(_mockProfiles.length + 1 - 1);
expectSelectedEquipmentProfileName(''); expectSelectedEquipmentProfileName('');
verify(() => storageService.updateEquipmentProfile(id: _customProfiles.first.id, isUsed: false)).called(1); verify(() => storageService.updateEquipmentProfile(id: _mockEquipmentProfiles.first.id, isUsed: false)).called(1);
verify(() => storageService.selectedEquipmentProfileId = '').called(1); verify(() => storageService.selectedEquipmentProfileId = '').called(1);
}, },
); );
@ -111,6 +112,7 @@ void main() {
'EquipmentProfilesProvider CRUD', 'EquipmentProfilesProvider CRUD',
(tester) async { (tester) async {
when(() => storageService.getEquipmentProfiles()).thenAnswer((_) async => {}); when(() => storageService.getEquipmentProfiles()).thenAnswer((_) async => {});
when(() => storageService.getPinholeEquipmentProfiles()).thenAnswer((_) async => {});
when(() => storageService.selectedEquipmentProfileId).thenReturn(''); when(() => storageService.selectedEquipmentProfileId).thenReturn('');
await pumpTestWidget(tester, true); await pumpTestWidget(tester, true);
@ -118,44 +120,45 @@ void main() {
expectSelectedEquipmentProfileName(''); expectSelectedEquipmentProfileName('');
/// Add first profile and verify /// Add first profile and verify
await tester.equipmentProfilesProvider.addProfile(_customProfiles.first); await tester.equipmentProfilesProvider.addProfile(_mockEquipmentProfiles.first);
await tester.pump(); await tester.pump();
expectEquipmentProfilesCount(2); expectEquipmentProfilesCount(2);
expectSelectedEquipmentProfileName(''); expectSelectedEquipmentProfileName('');
verify(() => storageService.addEquipmentProfile(any<EquipmentProfile>())).called(1); verify(() => storageService.addEquipmentProfile(any<EquipmentProfile>())).called(1);
/// Add the other profiles and select the 1st one /// Add the other profiles and select the 1st one
for (final profile in _customProfiles.skip(1)) { for (final profile in _mockEquipmentProfiles.skip(1)) {
await tester.equipmentProfilesProvider.addProfile(profile); await tester.equipmentProfilesProvider.addProfile(profile);
} }
tester.equipmentProfilesProvider.selectProfile(_customProfiles.first); tester.equipmentProfilesProvider.selectProfile(_mockEquipmentProfiles.first.id);
await tester.pump(); await tester.pump();
expectEquipmentProfilesCount(1 + _customProfiles.length); expectEquipmentProfilesCount(1 + _mockEquipmentProfiles.length);
expectSelectedEquipmentProfileName(_customProfiles.first.name); expectSelectedEquipmentProfileName(_mockEquipmentProfiles.first.name);
/// Edit the selected profile /// Edit the selected profile
final updatedName = "${_customProfiles.first} updated"; final updatedName = "${_mockEquipmentProfiles.first} updated";
await tester.equipmentProfilesProvider.updateProfile(_customProfiles.first.copyWith(name: updatedName)); await tester.equipmentProfilesProvider.updateProfile(_mockEquipmentProfiles.first.copyWith(name: updatedName));
await tester.pump(); await tester.pump();
expectEquipmentProfilesCount(1 + _customProfiles.length); expectEquipmentProfilesCount(1 + _mockEquipmentProfiles.length);
expectSelectedEquipmentProfileName(updatedName); expectSelectedEquipmentProfileName(updatedName);
verify(() => storageService.updateEquipmentProfile(id: _customProfiles.first.id, name: updatedName)).called(1); verify(() => storageService.updateEquipmentProfile(id: _mockEquipmentProfiles.first.id, name: updatedName))
.called(1);
/// Delete a non-selected profile /// Delete a non-selected profile
await tester.equipmentProfilesProvider.deleteProfile(_customProfiles.last); await tester.equipmentProfilesProvider.deleteProfile(_mockEquipmentProfiles.last);
await tester.pump(); await tester.pump();
expectEquipmentProfilesCount(1 + _customProfiles.length - 1); expectEquipmentProfilesCount(1 + _mockEquipmentProfiles.length - 1);
expectSelectedEquipmentProfileName(updatedName); expectSelectedEquipmentProfileName(updatedName);
verifyNever(() => storageService.selectedEquipmentProfileId = ''); verifyNever(() => storageService.selectedEquipmentProfileId = '');
verify(() => storageService.deleteEquipmentProfile(_customProfiles.last.id)).called(1); verify(() => storageService.deleteEquipmentProfile(_mockEquipmentProfiles.last.id)).called(1);
/// Delete the selected profile /// Delete the selected profile
await tester.equipmentProfilesProvider.deleteProfile(_customProfiles.first); await tester.equipmentProfilesProvider.deleteProfile(_mockEquipmentProfiles.first);
await tester.pump(); await tester.pump();
expectEquipmentProfilesCount(1 + _customProfiles.length - 2); expectEquipmentProfilesCount(1 + _mockEquipmentProfiles.length - 2);
expectSelectedEquipmentProfileName(''); expectSelectedEquipmentProfileName('');
verify(() => storageService.selectedEquipmentProfileId = '').called(1); verify(() => storageService.selectedEquipmentProfileId = '').called(1);
verify(() => storageService.deleteEquipmentProfile(_customProfiles.first.id)).called(1); verify(() => storageService.deleteEquipmentProfile(_mockEquipmentProfiles.first.id)).called(1);
}, },
); );
} }
@ -221,7 +224,9 @@ class _SelectedEquipmentProfile extends StatelessWidget {
} }
} }
final List<EquipmentProfile> _customProfiles = [ final List<IEquipmentProfile> _mockProfiles = [..._mockEquipmentProfiles, ..._mockPinholeEquipmentProfiles];
final List<EquipmentProfile> _mockEquipmentProfiles = [
const EquipmentProfile( const EquipmentProfile(
id: '1', id: '1',
name: 'Test 1', name: 'Test 1',
@ -291,3 +296,42 @@ final List<EquipmentProfile> _customProfiles = [
], ],
), ),
]; ];
final _mockPinholeEquipmentProfiles = [
const PinholeEquipmentProfile(
id: '3',
name: 'Pinhole Camera f/64',
aperture: 64.0,
isoValues: [
IsoValue(100, StopType.full),
IsoValue(200, StopType.full),
IsoValue(400, StopType.full),
IsoValue(800, StopType.full),
],
ndValues: [
NdValue(0),
NdValue(2),
NdValue(4),
],
),
const PinholeEquipmentProfile(
id: '4',
name: 'Pinhole Camera f/128',
aperture: 128.0,
isoValues: [
IsoValue(50, StopType.full),
IsoValue(100, StopType.full),
IsoValue(200, StopType.full),
IsoValue(400, StopType.full),
IsoValue(800, StopType.full),
IsoValue(1600, StopType.full),
],
ndValues: [
NdValue(0),
NdValue(1),
NdValue(2),
NdValue(4),
NdValue(8),
],
),
];

View file

@ -19,7 +19,10 @@ void main() {
setUpAll(() { setUpAll(() {
storageService = _MockEquipmentProfilesStorageService(); storageService = _MockEquipmentProfilesStorageService();
when(() => storageService.getEquipmentProfiles()).thenAnswer((_) async => _mockEquipmentProfiles.toTogglableMap()); when(() => storageService.getEquipmentProfiles())
.thenAnswer((_) async => _mockEquipmentProfiles.toList().toTogglableMap());
when(() => storageService.getPinholeEquipmentProfiles())
.thenAnswer((_) async => _mockPinholeEquipmentProfiles.toList().toTogglableMap());
when(() => storageService.selectedEquipmentProfileId).thenReturn(''); when(() => storageService.selectedEquipmentProfileId).thenReturn('');
}); });
@ -48,7 +51,7 @@ void main() {
expectReadingValueContainerText(S.current.equipmentProfile); expectReadingValueContainerText(S.current.equipmentProfile);
await tester.openAnimatedPicker<EquipmentProfilePicker>(); await tester.openAnimatedPicker<EquipmentProfilePicker>();
expect(find.byIcon(Icons.camera_alt_outlined), findsOneWidget); expect(find.byIcon(Icons.camera_alt_outlined), findsOneWidget);
expectDialogPickerText<EquipmentProfile>(S.current.equipmentProfile); expectDialogPickerText<IEquipmentProfile>(S.current.equipmentProfile);
}, },
); );
@ -62,7 +65,7 @@ void main() {
await pumpApplication(tester); await pumpApplication(tester);
expectReadingValueContainerText(S.current.none); expectReadingValueContainerText(S.current.none);
await tester.openAnimatedPicker<EquipmentProfilePicker>(); await tester.openAnimatedPicker<EquipmentProfilePicker>();
expectRadioListTile<EquipmentProfile>(S.current.none, isSelected: true); expectRadioListTile<IEquipmentProfile>(S.current.none, isSelected: true);
}, },
); );
@ -73,7 +76,18 @@ void main() {
await pumpApplication(tester); await pumpApplication(tester);
expectReadingValueContainerText(_mockEquipmentProfiles.first.name); expectReadingValueContainerText(_mockEquipmentProfiles.first.name);
await tester.openAnimatedPicker<EquipmentProfilePicker>(); await tester.openAnimatedPicker<EquipmentProfilePicker>();
expectRadioListTile<EquipmentProfile>(_mockEquipmentProfiles.first.name, isSelected: true); expectRadioListTile<IEquipmentProfile>(_mockEquipmentProfiles.first.name, isSelected: true);
},
);
testWidgets(
'Pinhole Camera f/64',
(tester) async {
when(() => storageService.selectedEquipmentProfileId).thenReturn(_mockPinholeEquipmentProfiles.first.id);
await pumpApplication(tester);
expectReadingValueContainerText(_mockPinholeEquipmentProfiles.first.name);
await tester.openAnimatedPicker<EquipmentProfilePicker>();
expectRadioListTile<IEquipmentProfile>(_mockPinholeEquipmentProfiles.first.name, isSelected: true);
}, },
); );
}, },
@ -84,10 +98,13 @@ void main() {
(tester) async { (tester) async {
when(() => storageService.getEquipmentProfiles()) when(() => storageService.getEquipmentProfiles())
.thenAnswer((_) async => _mockEquipmentProfiles.skip(1).toList().toTogglableMap()); .thenAnswer((_) async => _mockEquipmentProfiles.skip(1).toList().toTogglableMap());
when(() => storageService.getPinholeEquipmentProfiles())
.thenAnswer((_) async => _mockPinholeEquipmentProfiles.skip(1).toList().toTogglableMap());
await pumpApplication(tester); await pumpApplication(tester);
await tester.openAnimatedPicker<EquipmentProfilePicker>(); await tester.openAnimatedPicker<EquipmentProfilePicker>();
expectRadioListTile<EquipmentProfile>(S.current.none, isSelected: true); expectRadioListTile<IEquipmentProfile>(S.current.none, isSelected: true);
expectRadioListTile<EquipmentProfile>(_mockEquipmentProfiles[1].name); expectRadioListTile<IEquipmentProfile>(_mockEquipmentProfiles[1].name);
expectRadioListTile<IEquipmentProfile>(_mockPinholeEquipmentProfiles[1].name);
}, },
); );
} }
@ -126,3 +143,42 @@ final _mockEquipmentProfiles = [
isoValues: IsoValue.values, isoValues: IsoValue.values,
), ),
]; ];
final _mockPinholeEquipmentProfiles = [
const PinholeEquipmentProfile(
id: '3',
name: 'Pinhole Camera f/64',
aperture: 64.0,
isoValues: [
IsoValue(100, StopType.full),
IsoValue(200, StopType.full),
IsoValue(400, StopType.full),
IsoValue(800, StopType.full),
],
ndValues: [
NdValue(0),
NdValue(2),
NdValue(4),
],
),
const PinholeEquipmentProfile(
id: '4',
name: 'Pinhole Camera f/128',
aperture: 128.0,
isoValues: [
IsoValue(50, StopType.full),
IsoValue(100, StopType.full),
IsoValue(200, StopType.full),
IsoValue(400, StopType.full),
IsoValue(800, StopType.full),
IsoValue(1600, StopType.full),
],
ndValues: [
NdValue(0),
NdValue(1),
NdValue(2),
NdValue(4),
NdValue(8),
],
),
];

View file

@ -13,7 +13,7 @@ class _MockEquipmentProfilesStorageService extends Mock implements IapStorageSer
void main() { void main() {
TestWidgetsFlutterBinding.ensureInitialized(); TestWidgetsFlutterBinding.ensureInitialized();
final storageService = _MockEquipmentProfilesStorageService(); final storageService = _MockEquipmentProfilesStorageService();
final onDidChangeDependencies = MockValueChanged<EquipmentProfile>(); final onDidChangeDependencies = MockValueChanged<IEquipmentProfile>();
setUp(() { setUp(() {
registerFallbackValue(_customProfiles.first); registerFallbackValue(_customProfiles.first);
@ -26,6 +26,7 @@ void main() {
).thenAnswer((_) async {}); ).thenAnswer((_) async {});
when(() => storageService.deleteEquipmentProfile(any<String>())).thenAnswer((_) async {}); when(() => storageService.deleteEquipmentProfile(any<String>())).thenAnswer((_) async {});
when(() => storageService.getEquipmentProfiles()).thenAnswer((_) => Future.value(_customProfiles.toTogglableMap())); when(() => storageService.getEquipmentProfiles()).thenAnswer((_) => Future.value(_customProfiles.toTogglableMap()));
when(() => storageService.getPinholeEquipmentProfiles()).thenAnswer((_) => Future.value({}));
}); });
tearDown(() { tearDown(() {
@ -56,7 +57,7 @@ void main() {
when(() => storageService.selectedEquipmentProfileId).thenReturn(''); when(() => storageService.selectedEquipmentProfileId).thenReturn('');
await pumpTestWidget(tester); await pumpTestWidget(tester);
tester.equipmentProfilesProvider.selectProfile(_customProfiles[0]); tester.equipmentProfilesProvider.selectProfile(_customProfiles[0].id);
await tester.pump(); await tester.pump();
verify(() => onDidChangeDependencies.onChanged(_customProfiles[0])).called(1); verify(() => onDidChangeDependencies.onChanged(_customProfiles[0])).called(1);
}, },