mirror of https://github.com/immich-app/immich.git
fix: getAspectRatio fallback to db width and height (#24131)
fix: getExif fallback to db width and height Co-authored-by: shenlong-tanwen <139912620+shalong-tanwen@users.noreply.github.com>feat/sync-adjustment-time
parent
0498f6cb9d
commit
c860809aa1
@ -0,0 +1,165 @@
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:immich_mobile/domain/models/exif.model.dart';
|
||||
import 'package:immich_mobile/domain/services/asset.service.dart';
|
||||
import 'package:mocktail/mocktail.dart';
|
||||
|
||||
import '../../infrastructure/repository.mock.dart';
|
||||
import '../../test_utils.dart';
|
||||
|
||||
void main() {
|
||||
late AssetService sut;
|
||||
late MockRemoteAssetRepository mockRemoteAssetRepository;
|
||||
late MockDriftLocalAssetRepository mockLocalAssetRepository;
|
||||
|
||||
setUp(() {
|
||||
mockRemoteAssetRepository = MockRemoteAssetRepository();
|
||||
mockLocalAssetRepository = MockDriftLocalAssetRepository();
|
||||
sut = AssetService(
|
||||
remoteAssetRepository: mockRemoteAssetRepository,
|
||||
localAssetRepository: mockLocalAssetRepository,
|
||||
);
|
||||
});
|
||||
|
||||
group('getAspectRatio', () {
|
||||
test('flips dimensions on Android for 90° and 270° orientations', () async {
|
||||
debugDefaultTargetPlatformOverride = TargetPlatform.android;
|
||||
addTearDown(() => debugDefaultTargetPlatformOverride = null);
|
||||
|
||||
for (final orientation in [90, 270]) {
|
||||
final localAsset = TestUtils.createLocalAsset(
|
||||
id: 'local-$orientation',
|
||||
width: 1920,
|
||||
height: 1080,
|
||||
orientation: orientation,
|
||||
);
|
||||
|
||||
final result = await sut.getAspectRatio(localAsset);
|
||||
|
||||
expect(result, 1080 / 1920, reason: 'Orientation $orientation should flip on Android');
|
||||
}
|
||||
});
|
||||
|
||||
test('does not flip dimensions on iOS regardless of orientation', () async {
|
||||
debugDefaultTargetPlatformOverride = TargetPlatform.iOS;
|
||||
addTearDown(() => debugDefaultTargetPlatformOverride = null);
|
||||
|
||||
for (final orientation in [0, 90, 270]) {
|
||||
final localAsset = TestUtils.createLocalAsset(
|
||||
id: 'local-$orientation',
|
||||
width: 1920,
|
||||
height: 1080,
|
||||
orientation: orientation,
|
||||
);
|
||||
|
||||
final result = await sut.getAspectRatio(localAsset);
|
||||
|
||||
expect(result, 1920 / 1080, reason: 'iOS should never flip dimensions');
|
||||
}
|
||||
});
|
||||
|
||||
test('fetches dimensions from remote repository when missing from asset', () async {
|
||||
final remoteAsset = TestUtils.createRemoteAsset(id: 'remote-1', width: null, height: null);
|
||||
|
||||
final exif = const ExifInfo(orientation: '1');
|
||||
|
||||
final fetchedAsset = TestUtils.createRemoteAsset(id: 'remote-1', width: 1920, height: 1080);
|
||||
|
||||
when(() => mockRemoteAssetRepository.getExif('remote-1')).thenAnswer((_) async => exif);
|
||||
when(() => mockRemoteAssetRepository.get('remote-1')).thenAnswer((_) async => fetchedAsset);
|
||||
|
||||
final result = await sut.getAspectRatio(remoteAsset);
|
||||
|
||||
expect(result, 1920 / 1080);
|
||||
verify(() => mockRemoteAssetRepository.get('remote-1')).called(1);
|
||||
});
|
||||
|
||||
test('fetches dimensions from local repository when missing from local asset', () async {
|
||||
final localAsset = TestUtils.createLocalAsset(id: 'local-1', width: null, height: null, orientation: 0);
|
||||
|
||||
final fetchedAsset = TestUtils.createLocalAsset(id: 'local-1', width: 1920, height: 1080, orientation: 0);
|
||||
|
||||
when(() => mockLocalAssetRepository.get('local-1')).thenAnswer((_) async => fetchedAsset);
|
||||
|
||||
final result = await sut.getAspectRatio(localAsset);
|
||||
|
||||
expect(result, 1920 / 1080);
|
||||
verify(() => mockLocalAssetRepository.get('local-1')).called(1);
|
||||
});
|
||||
|
||||
test('returns 1.0 when dimensions are still unavailable after fetching', () async {
|
||||
final remoteAsset = TestUtils.createRemoteAsset(id: 'remote-1', width: null, height: null);
|
||||
|
||||
final exif = const ExifInfo(orientation: '1');
|
||||
|
||||
when(() => mockRemoteAssetRepository.getExif('remote-1')).thenAnswer((_) async => exif);
|
||||
when(() => mockRemoteAssetRepository.get('remote-1')).thenAnswer((_) async => null);
|
||||
|
||||
final result = await sut.getAspectRatio(remoteAsset);
|
||||
|
||||
expect(result, 1.0);
|
||||
});
|
||||
|
||||
test('returns 1.0 when height is zero', () async {
|
||||
final remoteAsset = TestUtils.createRemoteAsset(id: 'remote-1', width: 1920, height: 0);
|
||||
|
||||
final exif = const ExifInfo(orientation: '1');
|
||||
|
||||
when(() => mockRemoteAssetRepository.getExif('remote-1')).thenAnswer((_) async => exif);
|
||||
|
||||
final result = await sut.getAspectRatio(remoteAsset);
|
||||
|
||||
expect(result, 1.0);
|
||||
});
|
||||
|
||||
test('handles local asset with remoteId and uses exif from remote', () async {
|
||||
final localAsset = TestUtils.createLocalAsset(
|
||||
id: 'local-1',
|
||||
remoteId: 'remote-1',
|
||||
width: 1920,
|
||||
height: 1080,
|
||||
orientation: 0,
|
||||
);
|
||||
|
||||
final exif = const ExifInfo(orientation: '6');
|
||||
|
||||
when(() => mockRemoteAssetRepository.getExif('remote-1')).thenAnswer((_) async => exif);
|
||||
|
||||
final result = await sut.getAspectRatio(localAsset);
|
||||
|
||||
expect(result, 1080 / 1920);
|
||||
});
|
||||
|
||||
test('handles various flipped EXIF orientations correctly', () async {
|
||||
final flippedOrientations = ['5', '6', '7', '8', '90', '-90'];
|
||||
|
||||
for (final orientation in flippedOrientations) {
|
||||
final remoteAsset = TestUtils.createRemoteAsset(id: 'remote-$orientation', width: 1920, height: 1080);
|
||||
|
||||
final exif = ExifInfo(orientation: orientation);
|
||||
|
||||
when(() => mockRemoteAssetRepository.getExif('remote-$orientation')).thenAnswer((_) async => exif);
|
||||
|
||||
final result = await sut.getAspectRatio(remoteAsset);
|
||||
|
||||
expect(result, 1080 / 1920, reason: 'Orientation $orientation should flip dimensions');
|
||||
}
|
||||
});
|
||||
|
||||
test('handles various non-flipped EXIF orientations correctly', () async {
|
||||
final nonFlippedOrientations = ['1', '2', '3', '4'];
|
||||
|
||||
for (final orientation in nonFlippedOrientations) {
|
||||
final remoteAsset = TestUtils.createRemoteAsset(id: 'remote-$orientation', width: 1920, height: 1080);
|
||||
|
||||
final exif = ExifInfo(orientation: orientation);
|
||||
|
||||
when(() => mockRemoteAssetRepository.getExif('remote-$orientation')).thenAnswer((_) async => exif);
|
||||
|
||||
final result = await sut.getAspectRatio(remoteAsset);
|
||||
|
||||
expect(result, 1920 / 1080, reason: 'Orientation $orientation should NOT flip dimensions');
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
Loading…
Reference in New Issue