mirror-immich/mobile/test/services/view_intent_service_test.dart

120 lines
4.2 KiB
Dart

import 'dart:io';
import 'package:flutter_test/flutter_test.dart';
import 'package:immich_mobile/platform/view_intent_api.g.dart';
import 'package:immich_mobile/services/view_intent.service.dart';
import 'package:mocktail/mocktail.dart';
class MockViewIntentHostApi extends Mock implements ViewIntentHostApi {}
void main() {
late MockViewIntentHostApi hostApi;
late ViewIntentService service;
late Directory tempRoot;
late Directory cacheDir;
final attachment = ViewIntentPayload(
path: '/tmp/file.jpg',
mimeType: 'image/jpeg',
localAssetId: '42',
);
setUp(() {
hostApi = MockViewIntentHostApi();
tempRoot = Directory.systemTemp.createTempSync('view-intent-root');
cacheDir = Directory('${tempRoot.path}/cache')..createSync();
service = ViewIntentService(hostApi, temporaryDirectory: () async => cacheDir);
});
tearDown(() async {
clearInteractions(hostApi);
if (await tempRoot.exists()) {
await tempRoot.delete(recursive: true);
}
});
test('consumeViewIntent returns null when no attachment', () async {
when(() => hostApi.consumeViewIntent()).thenAnswer((_) async => null);
final result = await service.consumeViewIntent();
expect(result, isNull);
verify(() => hostApi.consumeViewIntent()).called(1);
});
test('consumeViewIntent returns attachment when present', () async {
when(() => hostApi.consumeViewIntent()).thenAnswer((_) async => attachment);
final result = await service.consumeViewIntent();
expect(result, attachment);
verify(() => hostApi.consumeViewIntent()).called(1);
});
test('consumeViewIntent swallows host api errors', () async {
when(() => hostApi.consumeViewIntent()).thenThrow(Exception('boom'));
final result = await service.consumeViewIntent();
expect(result, isNull);
verify(() => hostApi.consumeViewIntent()).called(1);
});
test('setManagedTempFilePath cleans previous managed temp file', () async {
final firstFile = File('${cacheDir.path}/view_intent_first.jpg')..writeAsStringSync('first');
final secondFile = File('${cacheDir.path}/view_intent_second.jpg')..writeAsStringSync('second');
await service.setManagedTempFilePath(firstFile.path);
await service.setManagedTempFilePath(secondFile.path);
expect(await firstFile.exists(), isFalse);
expect(await secondFile.exists(), isTrue);
await service.cleanupManagedTempFile();
expect(await secondFile.exists(), isFalse);
});
test('cleanupTempFile defers deletion while an upload is active', () async {
final tempFile = File('${cacheDir.path}/view_intent_in_flight.jpg')..writeAsStringSync('bytes');
service.markUploadActive(tempFile.path);
await service.cleanupTempFile(tempFile.path);
expect(await tempFile.exists(), isTrue, reason: 'active uploads block cleanup');
await service.markUploadInactive(tempFile.path);
expect(await tempFile.exists(), isFalse);
});
test('cleanupTempFile ignores non-managed paths', () async {
final nonManagedFile = File('${tempRoot.path}/plain_file.jpg')..writeAsStringSync('content');
await service.cleanupTempFile(nonManagedFile.path);
expect(await nonManagedFile.exists(), isTrue);
});
test('cleanupStaleTempFiles removes view-intent temp files and keeps unrelated files', () async {
final firstFile = File('${cacheDir.path}/view_intent_first.jpg')..writeAsStringSync('first');
final secondFile = File('${cacheDir.path}/view_intent_second.jpg')..writeAsStringSync('second');
final unrelatedFile = File('${cacheDir.path}/plain_file.jpg')..writeAsStringSync('plain');
await service.cleanupStaleTempFiles();
expect(await firstFile.exists(), isFalse);
expect(await secondFile.exists(), isFalse);
expect(await unrelatedFile.exists(), isTrue);
});
test('cleanupStaleTempFiles skips paths with active uploads', () async {
final stale = File('${cacheDir.path}/view_intent_stale.jpg')..writeAsStringSync('stale');
final active = File('${cacheDir.path}/view_intent_active.jpg')..writeAsStringSync('active');
service.markUploadActive(active.path);
await service.cleanupStaleTempFiles();
expect(await stale.exists(), isFalse);
expect(await active.exists(), isTrue);
});
}