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.
126 lines
3.8 KiB
Dart
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://')));
|
|
}
|
|
},
|
|
);
|
|
});
|
|
}
|