Files
pluriwave/test/servicios/musica_local_auto_test.dart
T
FreeTLab 725169cd31 feat(auto): page local-music folders instead of truncating at 50 [size:exception]
Folders over the 50-item cap now show a "Mas..." item that reveals
the next page on tap, instead of silently dropping the rest. Paging
slices the cheap raw list before building any MediaItem, so items
beyond the requested page are never resolved (art, title) -- proven
by a call-count test. Also swaps the raw SAF content:// URI shown in
settings for a parsed, human-readable folder name with a localized
fallback across all 13 locales.

servicio_audio.dart is untouched; this stays entirely within the
local-music tree/dispatch layer.
2026-07-19 22:14:05 +02:00

126 lines
3.8 KiB
Dart

import 'package:flutter_test/flutter_test.dart';
import 'package:pluriwave/servicios/musica_local_auto.dart';
void main() {
group('esArchivoAudio', () {
test('acepta cualquier MIME audio/*, en cualquier capitalización', () {
expect(esArchivoAudio('audio/mpeg', 'cancion.mp3'), isTrue);
expect(esArchivoAudio('audio/flac', 'cancion.flac'), isTrue);
expect(esArchivoAudio('AUDIO/OGG', 'cancion.ogg'), isTrue);
});
test(
'rechaza MIME no-audio aunque el nombre tenga una extensión de '
'audio (defensa contra un MIME nativo incorrecto)',
() {
expect(esArchivoAudio('video/mp4', 'cancion.mp3'), isFalse);
expect(
esArchivoAudio('application/octet-stream', 'cancion.mp3'),
isFalse,
);
expect(esArchivoAudio('text/plain', 'notas.mp3'), isFalse);
},
);
test('rechaza MIME null, vacío o en blanco', () {
expect(esArchivoAudio(null, 'cancion.mp3'), isFalse);
expect(esArchivoAudio('', 'cancion.mp3'), isFalse);
expect(esArchivoAudio(' ', 'cancion.mp3'), isFalse);
});
test(
'rechaza nombre null, vacío o en blanco aunque el MIME sea audio '
'válido',
() {
expect(esArchivoAudio('audio/mpeg', null), isFalse);
expect(esArchivoAudio('audio/mpeg', ''), isFalse);
expect(esArchivoAudio('audio/mpeg', ' '), isFalse);
},
);
});
group('nombreCarpetaDesdeUri', () {
const generico = 'Carpeta seleccionada';
test('almacenamiento interno: toma el segmento tras el último ":"', () {
expect(
nombreCarpetaDesdeUri(
'content://com.android.externalstorage.documents/tree/'
'primary%3AMusic%2FMyFolder',
nombreGenerico: generico,
),
'MyFolder',
);
});
test('tarjeta SD: toma el segmento tras el último ":"', () {
expect(
nombreCarpetaDesdeUri(
'content://com.android.externalstorage.documents/tree/'
'1A2B-3C4D%3AMusic',
nombreGenerico: generico,
),
'Music',
);
});
test(
'carpeta anidada con "/": toma el segmento tras la última "/"',
() {
expect(
nombreCarpetaDesdeUri(
'content://com.android.externalstorage.documents/tree/'
'primary%3AMusic%2FAlbum%2FDeep',
nombreGenerico: generico,
),
'Deep',
);
},
);
test(
'raíz de almacenamiento con tail vacío tras ":" cae al genérico',
() {
final resultado = nombreCarpetaDesdeUri(
'content://com.android.externalstorage.documents/tree/primary%3A',
nombreGenerico: generico,
);
expect(resultado, generico);
},
);
test('URI no parseable o de forma inesperada cae al genérico', () {
for (final uri in [
'',
'not a uri \$\$\$ ///',
'content://com.android.externalstorage.documents/tree/',
]) {
final resultado = nombreCarpetaDesdeUri(uri, nombreGenerico: generico);
expect(resultado, generico);
}
});
test(
'nunca devuelve la URI cruda ni una cadena vacía, para ningún caso '
'de esta suite',
() {
final casos = [
'content://com.android.externalstorage.documents/tree/'
'primary%3AMusic%2FMyFolder',
'content://com.android.externalstorage.documents/tree/'
'1A2B-3C4D%3AMusic',
'content://com.android.externalstorage.documents/tree/primary%3A',
'',
'garbage',
];
for (final uri in casos) {
final resultado = nombreCarpetaDesdeUri(uri, nombreGenerico: generico);
expect(resultado, isNotEmpty);
expect(resultado, isNot(equals(uri)));
expect(resultado, isNot(contains('content://')));
}
},
);
});
}