You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
167 lines
5.3 KiB
167 lines
5.3 KiB
import 'dart:async';
|
|
import 'package:flutter_test/flutter_test.dart';
|
|
import 'package:app_boilerplate/ui/relay_management/relay_management_controller.dart';
|
|
import 'package:app_boilerplate/data/nostr/nostr_service.dart';
|
|
import 'package:app_boilerplate/data/nostr/models/nostr_relay.dart';
|
|
import 'package:app_boilerplate/data/sync/sync_engine.dart';
|
|
import 'package:app_boilerplate/data/local/local_storage_service.dart';
|
|
import 'package:path/path.dart' as path;
|
|
import 'package:sqflite_common_ffi/sqflite_ffi.dart';
|
|
import 'dart:io';
|
|
|
|
void main() {
|
|
// Initialize Flutter bindings and sqflite for testing
|
|
TestWidgetsFlutterBinding.ensureInitialized();
|
|
sqfliteFfiInit();
|
|
databaseFactory = databaseFactoryFfi;
|
|
|
|
late NostrService nostrService;
|
|
late SyncEngine syncEngine;
|
|
late LocalStorageService localStorage;
|
|
late Directory testDir;
|
|
late String testDbPath;
|
|
late Directory testCacheDir;
|
|
late RelayManagementController controller;
|
|
|
|
setUp(() async {
|
|
// Create temporary directory for testing
|
|
testDir = await Directory.systemTemp.createTemp('relay_test_');
|
|
testDbPath = path.join(testDir.path, 'test_local_storage.db');
|
|
testCacheDir = Directory(path.join(testDir.path, 'image_cache'));
|
|
|
|
// Initialize local storage
|
|
localStorage = LocalStorageService(
|
|
testDbPath: testDbPath,
|
|
testCacheDir: testCacheDir,
|
|
);
|
|
await localStorage.initialize();
|
|
|
|
// Create services
|
|
nostrService = NostrService();
|
|
syncEngine = SyncEngine(
|
|
localStorage: localStorage,
|
|
nostrService: nostrService,
|
|
);
|
|
|
|
// Create controller
|
|
controller = RelayManagementController(
|
|
nostrService: nostrService,
|
|
syncEngine: syncEngine,
|
|
);
|
|
});
|
|
|
|
tearDown(() async {
|
|
controller.dispose();
|
|
syncEngine.dispose();
|
|
nostrService.dispose();
|
|
await localStorage.close();
|
|
try {
|
|
if (await testDir.exists()) {
|
|
await testDir.delete(recursive: true);
|
|
}
|
|
} catch (_) {
|
|
// Ignore cleanup errors
|
|
}
|
|
});
|
|
|
|
group('RelayManagementController', () {
|
|
test('initial state - empty relay list', () {
|
|
expect(controller.relays, isEmpty);
|
|
expect(controller.isSyncing, isFalse);
|
|
expect(controller.error, isNull);
|
|
expect(controller.isCheckingHealth, isFalse);
|
|
});
|
|
|
|
test('addRelay - success', () {
|
|
final url = 'wss://relay.example.com';
|
|
final result = controller.addRelay(url);
|
|
|
|
expect(result, isTrue);
|
|
expect(controller.relays.length, equals(1));
|
|
expect(controller.relays[0].url, equals(url));
|
|
expect(controller.error, isNull);
|
|
});
|
|
|
|
test('addRelay - invalid URL format', () {
|
|
final result = controller.addRelay('invalid-url');
|
|
|
|
expect(result, isFalse);
|
|
expect(controller.relays, isEmpty);
|
|
expect(controller.error, isNotNull);
|
|
expect(controller.error, contains('Invalid relay URL'));
|
|
});
|
|
|
|
test('addRelay - duplicate relay', () {
|
|
final url = 'wss://relay.example.com';
|
|
controller.addRelay(url);
|
|
final result = controller.addRelay(url);
|
|
|
|
expect(result, isTrue); // Still returns true, but doesn't add duplicate
|
|
expect(controller.relays.length, equals(1));
|
|
});
|
|
|
|
test('removeRelay - success', () {
|
|
final url = 'wss://relay.example.com';
|
|
controller.addRelay(url);
|
|
expect(controller.relays.length, equals(1));
|
|
|
|
controller.removeRelay(url);
|
|
expect(controller.relays, isEmpty);
|
|
expect(controller.error, isNull);
|
|
});
|
|
|
|
test('removeRelay - non-existent relay', () {
|
|
controller.removeRelay('wss://nonexistent.com');
|
|
expect(controller.relays, isEmpty);
|
|
expect(controller.error, isNull);
|
|
});
|
|
|
|
test('clearError - clears error message', () {
|
|
controller.addRelay('invalid-url');
|
|
expect(controller.error, isNotNull);
|
|
|
|
controller.clearError();
|
|
expect(controller.error, isNull);
|
|
});
|
|
|
|
test('checkRelayHealth - attempts to connect to relays', () async {
|
|
// Add a relay (but don't connect to real relay in tests)
|
|
controller.addRelay('wss://relay.example.com');
|
|
expect(controller.relays.length, equals(1));
|
|
expect(controller.relays[0].isConnected, isFalse);
|
|
|
|
// Health check will attempt to connect (will fail in test environment, but that's OK)
|
|
// The method should complete without throwing - it handles connection failures gracefully
|
|
// Use runZoned to catch any unhandled exceptions that might escape
|
|
await runZonedGuarded(
|
|
() async {
|
|
await controller.checkRelayHealth();
|
|
},
|
|
(error, stack) {
|
|
// Swallow any unhandled errors - connection failures are expected
|
|
},
|
|
);
|
|
|
|
// Verify the health check completed
|
|
expect(controller.isCheckingHealth, isFalse);
|
|
// Relay should still be in the list (even if disconnected)
|
|
expect(controller.relays.length, equals(1));
|
|
});
|
|
|
|
test('triggerManualSync - without sync engine', () async {
|
|
final controllerWithoutSync = RelayManagementController(
|
|
nostrService: nostrService,
|
|
syncEngine: null,
|
|
);
|
|
|
|
final result = await controllerWithoutSync.triggerManualSync();
|
|
expect(result, isFalse);
|
|
expect(controllerWithoutSync.error, isNotNull);
|
|
expect(controllerWithoutSync.error, contains('Sync engine not configured'));
|
|
|
|
controllerWithoutSync.dispose();
|
|
});
|
|
});
|
|
}
|
|
|