import 'package:audio_service/audio_service.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:pluriwave/servicios/navegacion_auto.dart'; /// Android Auto entitlement gating (android-auto-media spec "Free-Tier /// Reduced Root Browse" + "Free-Tier Browse Never Leaks Real Content", /// design.md ADR-4). All pure — no handler instantiation needed /// (`PluriWaveAudioHandler` cannot be constructed in a unit test). void main() { group('raiz(premium:) — root keeps its labels for every tier', () { test('premium: identical to today\'s tree (regression guard)', () { final constructor = ConstructorArbolAuto(); final premiumConLocal = constructor.raiz( incluirMusicaLocal: true, premium: true, ); final premiumSinLocal = constructor.raiz( incluirMusicaLocal: false, premium: true, ); expect(premiumConLocal.map((m) => m.id), [ ConstructorArbolAuto.idFavoritos, ConstructorArbolAuto.idTodas, ConstructorArbolAuto.idMisEmisoras, ConstructorArbolAuto.idMusicaLocal, ]); expect(premiumConLocal.every((m) => m.playable == false), isTrue); expect(premiumConLocal.every((m) => m.displaySubtitle == null), isTrue); expect(premiumSinLocal.map((m) => m.id), [ ConstructorArbolAuto.idFavoritos, ConstructorArbolAuto.idTodas, ConstructorArbolAuto.idMisEmisoras, ]); }); test('free: same folder ids/titles, non-blank, never playable', () { final constructor = ConstructorArbolAuto(); final libre = constructor.raiz(incluirMusicaLocal: true, premium: false); expect(libre, isNotEmpty); expect(libre.map((m) => m.id), [ ConstructorArbolAuto.idFavoritos, ConstructorArbolAuto.idTodas, ConstructorArbolAuto.idMisEmisoras, ConstructorArbolAuto.idMusicaLocal, ]); expect(libre.every((m) => m.playable == false), isTrue); }); }); test( 'itemPremiumBloqueado(): id fijo, no reproducible, etiqueta premium', () { final item = ConstructorArbolAuto().itemPremiumBloqueado(); expect(item.id, 'premium:info'); expect(item.playable, isFalse); expect(item.title, isNotEmpty); }, ); group('respuestaBloqueadaPorEntitlement — backstop de navegacion', () { test('root nunca es bloqueada (root siempre resuelve via raiz)', () { final respuesta = respuestaBloqueadaPorEntitlement( parentMediaId: AudioService.browsableRootId, premium: false, ); expect(respuesta, isNull); }); test('cualquier id no-root, en free, retorna SOLO el item bloqueado', () { for (final id in [ ConstructorArbolAuto.idFavoritos, ConstructorArbolAuto.idTodas, ConstructorArbolAuto.idMisEmisoras, ConstructorArbolAuto.idMusicaLocal, ConstructorArbolAuto.idEcualizador, // Stale/deep-linked id from before a downgrade — the backstop must // not special-case known ids (Spec "Stale folder id bypass // attempt"). 'emisora:algun-uuid-viejo', 'grupo:algo', ]) { final respuesta = respuestaBloqueadaPorEntitlement( parentMediaId: id, premium: false, ); expect(respuesta, hasLength(1)); expect(respuesta!.single.id, 'premium:info'); } }); test('cualquier id no-root, en premium, no es bloqueada', () { final respuesta = respuestaBloqueadaPorEntitlement( parentMediaId: ConstructorArbolAuto.idFavoritos, premium: true, ); expect(respuesta, isNull); }); }); }