twonly-app/test/services/cloud_backup_test.dart
otsmr 96f8bc39d0
Some checks are pending
Flutter analyze & test / flutter_analyze_and_test (push) Waiting to run
start with cloud backup
2026-07-19 20:24:14 +02:00

151 lines
5.1 KiB
Dart

import 'dart:async';
import 'dart:io';
import 'package:drift/drift.dart' show Value;
import 'package:flutter/services.dart';
import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:twonly/core/bridge.dart' as bridge;
import 'package:twonly/core/frb_generated.dart';
import 'package:twonly/globals.dart';
import 'package:twonly/locator.dart';
import 'package:twonly/src/database/tables/mediafiles.table.dart';
import 'package:twonly/src/database/twonly.db.dart';
import 'package:twonly/src/services/api/api.service.dart';
import 'package:twonly/src/services/mediafiles/mediafile.service.dart';
import 'package:twonly/src/services/memories/memories_cloud.service.dart';
import 'package:twonly/src/services/user.service.dart';
import 'package:twonly/src/utils/log.dart';
import '../mocks/platform_channels.dart';
import '../mocks/test_client.dart';
void main() {
group('Memories Cloud Backup Integration', () {
late TestClient client;
late Directory tempDir;
setUpAll(() async {
TestWidgetsFlutterBinding.ensureInitialized();
TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger
.setMockMethodCallHandler(
const MethodChannel('dev.fluttercommunity.plus/package_info'),
(call) async {
return {
'appName': 'twonly',
'packageName': 'eu.twonly.app',
'version': '1.0.0',
'buildNumber': '100',
};
},
);
Log.init();
setupPlatformChannelMocks();
HttpOverrides.global = RealHttpOverrides();
final dylibPath =
'${Directory.current.path}/rust/target/debug/librust_lib_twonly.dylib';
if (File(dylibPath).existsSync()) {
await RustLib.init(externalLibrary: ExternalLibrary.open(dylibPath));
} else {
await RustLib.init();
}
tempDir = Directory.systemTemp.createTempSync(
'twonly_cloud_backup_test_',
);
AppEnvironment.initTesting(
customCacheDir: tempDir.path,
customSupportDir: tempDir.path,
);
await bridge.initializeTwonlyFlutter(
config: bridge.InitConfig(
databaseDir: tempDir.path,
dataDir: tempDir.path,
),
);
if (locator.isRegistered<TwonlyDB>()) {
await locator.unregister<TwonlyDB>();
}
if (locator.isRegistered<UserService>()) {
await locator.unregister<UserService>();
}
if (locator.isRegistered<ApiService>()) {
await locator.unregister<ApiService>();
}
locator
..registerFactory<TwonlyDB>(() {
final db = Zone.current[#twonlyDB] as TwonlyDB?;
if (db != null) return db;
throw StateError('No TwonlyDB in active Zone.');
})
..registerFactory<UserService>(() {
final us = Zone.current[#userService] as UserService?;
if (us != null) return us;
throw StateError('No UserService in active Zone.');
})
..registerFactory<ApiService>(() {
final api = Zone.current[#apiService] as ApiService?;
if (api != null) return api;
throw StateError('No ApiService in active Zone.');
});
client = TestClient(777);
await client.init();
});
tearDownAll(() async {
try {
if (tempDir.existsSync()) {
tempDir.deleteSync(recursive: true);
}
} catch (_) {}
});
test('Full Backup Lifecycle', () async {
await client.run(() async {
// 1. Create a dummy media file
final mediaId = 'test_media_${DateTime.now().millisecondsSinceEpoch}';
await twonlyDB.mediaFilesDao.insertOrUpdateMedia(
MediaFilesCompanion(
mediaId: Value(mediaId),
createdAt: Value(DateTime.now()),
stored: const Value(true),
hasThumbnail: const Value(true),
cloudState: const Value(CloudState.none),
type: const Value(MediaType.image),
),
);
final mediaFile = await twonlyDB.mediaFilesDao.getMediaFileById(
mediaId,
);
expect(mediaFile, isNotNull);
expect(mediaFile!.cloudState, CloudState.none);
// Mock original and thumbnail files
final mediaService = MediaFileService(mediaFile);
final originalFile = mediaService.originalPath;
final thumbnailFile = mediaService.thumbnailPath;
await originalFile.create(recursive: true);
await originalFile.writeAsBytes([1, 2, 3, 4, 5]);
await thumbnailFile.create(recursive: true);
await thumbnailFile.writeAsBytes([1, 2, 3]);
// 2. Trigger checkUploads (which performs S3 POST upload and confirmation)
await memoriesCloudService.checkUploads();
// 3. Verify that the media has cloudState == uploaded
final finalMedia = await twonlyDB.mediaFilesDao.getMediaFileById(
mediaId,
);
expect(finalMedia, isNotNull);
expect(finalMedia!.cloudState, CloudState.uploaded);
});
});
});
}