mirror of
https://github.com/twonlyapp/twonly-app.git
synced 2026-09-01 16:04:08 +00:00
Some checks are pending
Flutter analyze & test / flutter_analyze_and_test (push) Waiting to run
151 lines
5.1 KiB
Dart
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);
|
|
});
|
|
});
|
|
});
|
|
}
|