test(favorites): cover sqlite migrations
Build & Deploy Pluriwave / Build APK + AAB release (push) Successful in 1m39s
Build & Deploy Pluriwave / Análisis de código (push) Successful in 24s

This commit is contained in:
2026-05-22 17:20:40 +02:00
parent f6a9ba0086
commit b6e66e75ce
5 changed files with 172 additions and 8 deletions
+36 -7
View File
@@ -8,12 +8,24 @@ import '../modelos/grupo_favoritos.dart';
/// Servicio de persistencia de emisoras favoritas con SQLite.
///
/// - Inicializaci?n lazy: la BD se abre en el primer acceso.
/// - Migration-ready: versi?n 3 a?ade agrupaciones de favoritos.
/// - Inicialización lazy: la BD se abre en el primer acceso.
/// - Migration-ready: versión 3 añade agrupaciones de favoritos.
class ServicioFavoritos {
static const _dbName = 'pluriwave.db';
static const _dbVersion = 3;
ServicioFavoritos({
DatabaseFactory? databaseFactory,
Future<String> Function()? databasePathProvider,
String? databaseName,
}) : _databaseFactory = databaseFactory,
_databasePathProvider = databasePathProvider ?? getDatabasesPath,
_databaseName = databaseName ?? _dbName;
final DatabaseFactory? _databaseFactory;
final Future<String> Function() _databasePathProvider;
final String _databaseName;
Database? _db;
Future<Database> get _database async {
@@ -21,10 +33,27 @@ class ServicioFavoritos {
return _db!;
}
Future<void> cerrar() async {
await _db?.close();
_db = null;
}
Future<Database> _initDb() async {
final dbPath = await getDatabasesPath();
final dbPath = await _databasePathProvider();
await Directory(dbPath).create(recursive: true);
final path = join(dbPath, _dbName);
final path = join(dbPath, _databaseName);
final factory = _databaseFactory;
if (factory != null) {
return factory.openDatabase(
path,
options: OpenDatabaseOptions(
version: _dbVersion,
onCreate: _onCreate,
onUpgrade: _onUpgrade,
onOpen: _asegurarEsquema,
),
);
}
return openDatabase(
path,
version: _dbVersion,
@@ -79,8 +108,8 @@ class ServicioFavoritos {
}
}
// Migraci?n defensiva: algunas instalaciones antiguas pueden venir de
// esquemas intermedios. No asumimos qu? columna existe: la verificamos.
// Migración defensiva: algunas instalaciones antiguas pueden venir de
// esquemas intermedios. No asumimos qué columna existe: la verificamos.
await addColumn('favicon', 'TEXT');
await addColumn('pais', 'TEXT');
await addColumn('codigo_pais', 'TEXT');
@@ -279,7 +308,7 @@ class ServicioFavoritos {
String _normalizarNombreGrupo(String nombre) {
final normalizado = nombre.trim().replaceAll(RegExp(r'\s+'), ' ');
if (normalizado.isEmpty) {
throw ArgumentError('El nombre del grupo no puede estar vac?o');
throw ArgumentError('El nombre del grupo no puede estar vacío');
}
if (normalizado.length > 28) {
throw ArgumentError('El nombre del grupo no puede superar 28 caracteres');