From ebdde7df013cb78e9ece9305f2fb0bc008b2c781 Mon Sep 17 00:00:00 2001 From: freetlab Date: Tue, 28 Jul 2026 23:21:34 +0200 Subject: [PATCH] fix(grabaciones): wire the recordings library into Settings navigation WU15 shipped PantallaGrabaciones (the recordings library: storage bar, recording rows, the "..." Rename/Share/Delete menu) fully tested but reachable from nowhere in the app - a gap flagged in WU15's own apply-progress notes, not fixed there since it needed a design decision rather than a guess. Coordinator ruling applied: the approved mockup's "Ajustes > Grabaciones" screen depicts the library, not the folder/size settings form. So the GRABACIONES Y MUSICA group's "Grabaciones" row in pantalla_ajustes.dart now opens PantallaGrabaciones instead of PantallaAjustesGrabaciones. The settings form is not dropped - it stays reachable, now from within the library via a settings icon in its PluriPushScaffold actions, matching the existing pantalla_ajustes_timer_sueno.dart "Add" action precedent for a real capability living in the header. One new ARB key (en/es only, per precedent): recordingsLibrarySettingsTooltip. Tests: 604 -> 605 (one scenario re-targeted in pantalla_ajustes_test.dart, one new scenario in pantalla_grabaciones_test.dart, which needed the same ListTile-ink-assertion suppression helper WU3a/WU3b established since it now pushes a ListTile-bearing settings screen). flutter analyze unchanged at 1 pre-existing info. Recorded in tasks.md as WU15b - not part of the original 18-unit plan, added here to close the gap WU15 flagged. --- lib/l10n/app_en.arb | 1 + lib/l10n/app_es.arb | 1 + lib/l10n/gen/app_localizations.dart | 6 +++ lib/l10n/gen/app_localizations_ar.dart | 3 ++ lib/l10n/gen/app_localizations_bn.dart | 3 ++ lib/l10n/gen/app_localizations_de.dart | 3 ++ lib/l10n/gen/app_localizations_en.dart | 3 ++ lib/l10n/gen/app_localizations_es.dart | 3 ++ lib/l10n/gen/app_localizations_fr.dart | 3 ++ lib/l10n/gen/app_localizations_hi.dart | 3 ++ lib/l10n/gen/app_localizations_id.dart | 3 ++ lib/l10n/gen/app_localizations_it.dart | 3 ++ lib/l10n/gen/app_localizations_ja.dart | 3 ++ lib/l10n/gen/app_localizations_pt.dart | 3 ++ lib/l10n/gen/app_localizations_ru.dart | 3 ++ lib/l10n/gen/app_localizations_zh.dart | 3 ++ lib/pantallas/pantalla_ajustes.dart | 9 +++- lib/pantallas/pantalla_grabaciones.dart | 12 +++++ openspec/changes/rediseno-funcional/tasks.md | 44 +++++++++++++++- test/pantallas/pantalla_ajustes_test.dart | 35 +++++++------ test/pantallas/pantalla_grabaciones_test.dart | 50 +++++++++++++++++++ 21 files changed, 180 insertions(+), 17 deletions(-) diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index da9378c..a97ee57 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -231,6 +231,7 @@ "recordingRenameEmptyError": "Enter a name", "recordingDeleteConfirmTitle": "Delete recording?", "recordingDeleteConfirmMessage": "This can't be undone.", + "recordingsLibrarySettingsTooltip": "Recording settings", "stationOrderTitle": "Station order", "stationOrderByName": "By name", "stationOrderByQuality": "By quality", diff --git a/lib/l10n/app_es.arb b/lib/l10n/app_es.arb index bbc77da..011593b 100644 --- a/lib/l10n/app_es.arb +++ b/lib/l10n/app_es.arb @@ -231,6 +231,7 @@ "recordingRenameEmptyError": "Ingresá un nombre", "recordingDeleteConfirmTitle": "¿Eliminar grabación?", "recordingDeleteConfirmMessage": "Esta acción no se puede deshacer.", + "recordingsLibrarySettingsTooltip": "Ajustes de grabación", "stationOrderTitle": "Orden de emisoras", "stationOrderByName": "Por nombre", "stationOrderByQuality": "Por calidad", diff --git a/lib/l10n/gen/app_localizations.dart b/lib/l10n/gen/app_localizations.dart index 4480e62..4800560 100644 --- a/lib/l10n/gen/app_localizations.dart +++ b/lib/l10n/gen/app_localizations.dart @@ -868,6 +868,12 @@ abstract class AppLocalizations { /// **'Esta acción no se puede deshacer.'** String get recordingDeleteConfirmMessage; + /// No description provided for @recordingsLibrarySettingsTooltip. + /// + /// In es, this message translates to: + /// **'Ajustes de grabación'** + String get recordingsLibrarySettingsTooltip; + /// No description provided for @stationOrderTitle. /// /// In es, this message translates to: diff --git a/lib/l10n/gen/app_localizations_ar.dart b/lib/l10n/gen/app_localizations_ar.dart index daf0c48..ed03cdd 100644 --- a/lib/l10n/gen/app_localizations_ar.dart +++ b/lib/l10n/gen/app_localizations_ar.dart @@ -435,6 +435,9 @@ class AppLocalizationsAr extends AppLocalizations { String get recordingDeleteConfirmMessage => 'Esta acción no se puede deshacer.'; + @override + String get recordingsLibrarySettingsTooltip => 'Ajustes de grabación'; + @override String get stationOrderTitle => 'ترتيب المحطات'; diff --git a/lib/l10n/gen/app_localizations_bn.dart b/lib/l10n/gen/app_localizations_bn.dart index 7a855b1..2d5f303 100644 --- a/lib/l10n/gen/app_localizations_bn.dart +++ b/lib/l10n/gen/app_localizations_bn.dart @@ -438,6 +438,9 @@ class AppLocalizationsBn extends AppLocalizations { String get recordingDeleteConfirmMessage => 'Esta acción no se puede deshacer.'; + @override + String get recordingsLibrarySettingsTooltip => 'Ajustes de grabación'; + @override String get stationOrderTitle => 'স্টেশনের ক্রম'; diff --git a/lib/l10n/gen/app_localizations_de.dart b/lib/l10n/gen/app_localizations_de.dart index db5c075..81d31ab 100644 --- a/lib/l10n/gen/app_localizations_de.dart +++ b/lib/l10n/gen/app_localizations_de.dart @@ -441,6 +441,9 @@ class AppLocalizationsDe extends AppLocalizations { String get recordingDeleteConfirmMessage => 'Esta acción no se puede deshacer.'; + @override + String get recordingsLibrarySettingsTooltip => 'Ajustes de grabación'; + @override String get stationOrderTitle => 'Senderreihenfolge'; diff --git a/lib/l10n/gen/app_localizations_en.dart b/lib/l10n/gen/app_localizations_en.dart index 3086c42..46c72ef 100644 --- a/lib/l10n/gen/app_localizations_en.dart +++ b/lib/l10n/gen/app_localizations_en.dart @@ -435,6 +435,9 @@ class AppLocalizationsEn extends AppLocalizations { @override String get recordingDeleteConfirmMessage => 'This can\'t be undone.'; + @override + String get recordingsLibrarySettingsTooltip => 'Recording settings'; + @override String get stationOrderTitle => 'Station order'; diff --git a/lib/l10n/gen/app_localizations_es.dart b/lib/l10n/gen/app_localizations_es.dart index a61c695..5a3fc6a 100644 --- a/lib/l10n/gen/app_localizations_es.dart +++ b/lib/l10n/gen/app_localizations_es.dart @@ -439,6 +439,9 @@ class AppLocalizationsEs extends AppLocalizations { String get recordingDeleteConfirmMessage => 'Esta acción no se puede deshacer.'; + @override + String get recordingsLibrarySettingsTooltip => 'Ajustes de grabación'; + @override String get stationOrderTitle => 'Orden de emisoras'; diff --git a/lib/l10n/gen/app_localizations_fr.dart b/lib/l10n/gen/app_localizations_fr.dart index 8e27f30..7731edb 100644 --- a/lib/l10n/gen/app_localizations_fr.dart +++ b/lib/l10n/gen/app_localizations_fr.dart @@ -443,6 +443,9 @@ class AppLocalizationsFr extends AppLocalizations { String get recordingDeleteConfirmMessage => 'Esta acción no se puede deshacer.'; + @override + String get recordingsLibrarySettingsTooltip => 'Ajustes de grabación'; + @override String get stationOrderTitle => 'Ordre des stations'; diff --git a/lib/l10n/gen/app_localizations_hi.dart b/lib/l10n/gen/app_localizations_hi.dart index 7a19429..1c4cdce 100644 --- a/lib/l10n/gen/app_localizations_hi.dart +++ b/lib/l10n/gen/app_localizations_hi.dart @@ -436,6 +436,9 @@ class AppLocalizationsHi extends AppLocalizations { String get recordingDeleteConfirmMessage => 'Esta acción no se puede deshacer.'; + @override + String get recordingsLibrarySettingsTooltip => 'Ajustes de grabación'; + @override String get stationOrderTitle => 'स्टेशन क्रम'; diff --git a/lib/l10n/gen/app_localizations_id.dart b/lib/l10n/gen/app_localizations_id.dart index de8a8aa..f2dea3a 100644 --- a/lib/l10n/gen/app_localizations_id.dart +++ b/lib/l10n/gen/app_localizations_id.dart @@ -437,6 +437,9 @@ class AppLocalizationsId extends AppLocalizations { String get recordingDeleteConfirmMessage => 'Esta acción no se puede deshacer.'; + @override + String get recordingsLibrarySettingsTooltip => 'Ajustes de grabación'; + @override String get stationOrderTitle => 'Urutan stasiun'; diff --git a/lib/l10n/gen/app_localizations_it.dart b/lib/l10n/gen/app_localizations_it.dart index 6c13278..88474da 100644 --- a/lib/l10n/gen/app_localizations_it.dart +++ b/lib/l10n/gen/app_localizations_it.dart @@ -439,6 +439,9 @@ class AppLocalizationsIt extends AppLocalizations { String get recordingDeleteConfirmMessage => 'Esta acción no se puede deshacer.'; + @override + String get recordingsLibrarySettingsTooltip => 'Ajustes de grabación'; + @override String get stationOrderTitle => 'Ordine emittenti'; diff --git a/lib/l10n/gen/app_localizations_ja.dart b/lib/l10n/gen/app_localizations_ja.dart index 2213b52..ff9f164 100644 --- a/lib/l10n/gen/app_localizations_ja.dart +++ b/lib/l10n/gen/app_localizations_ja.dart @@ -426,6 +426,9 @@ class AppLocalizationsJa extends AppLocalizations { String get recordingDeleteConfirmMessage => 'Esta acción no se puede deshacer.'; + @override + String get recordingsLibrarySettingsTooltip => 'Ajustes de grabación'; + @override String get stationOrderTitle => '局の並び順'; diff --git a/lib/l10n/gen/app_localizations_pt.dart b/lib/l10n/gen/app_localizations_pt.dart index 5da15e7..beaf3d6 100644 --- a/lib/l10n/gen/app_localizations_pt.dart +++ b/lib/l10n/gen/app_localizations_pt.dart @@ -438,6 +438,9 @@ class AppLocalizationsPt extends AppLocalizations { String get recordingDeleteConfirmMessage => 'Esta acción no se puede deshacer.'; + @override + String get recordingsLibrarySettingsTooltip => 'Ajustes de grabación'; + @override String get stationOrderTitle => 'Ordem das estações'; diff --git a/lib/l10n/gen/app_localizations_ru.dart b/lib/l10n/gen/app_localizations_ru.dart index 5ab6d3a..fe4580a 100644 --- a/lib/l10n/gen/app_localizations_ru.dart +++ b/lib/l10n/gen/app_localizations_ru.dart @@ -439,6 +439,9 @@ class AppLocalizationsRu extends AppLocalizations { String get recordingDeleteConfirmMessage => 'Esta acción no se puede deshacer.'; + @override + String get recordingsLibrarySettingsTooltip => 'Ajustes de grabación'; + @override String get stationOrderTitle => 'Порядок станций'; diff --git a/lib/l10n/gen/app_localizations_zh.dart b/lib/l10n/gen/app_localizations_zh.dart index 3740ad8..d74ff6d 100644 --- a/lib/l10n/gen/app_localizations_zh.dart +++ b/lib/l10n/gen/app_localizations_zh.dart @@ -424,6 +424,9 @@ class AppLocalizationsZh extends AppLocalizations { String get recordingDeleteConfirmMessage => 'Esta acción no se puede deshacer.'; + @override + String get recordingsLibrarySettingsTooltip => 'Ajustes de grabación'; + @override String get stationOrderTitle => '电台排序'; diff --git a/lib/pantallas/pantalla_ajustes.dart b/lib/pantallas/pantalla_ajustes.dart index 7cea685..3d22f72 100644 --- a/lib/pantallas/pantalla_ajustes.dart +++ b/lib/pantallas/pantalla_ajustes.dart @@ -9,7 +9,6 @@ import 'ajustes/pantalla_ajustes_backup.dart'; import 'ajustes/pantalla_ajustes_ecualizador.dart'; import 'ajustes/pantalla_ajustes_emisora_preferida.dart'; import 'ajustes/pantalla_ajustes_emisoras_personalizadas.dart'; -import 'ajustes/pantalla_ajustes_grabaciones.dart'; import 'ajustes/pantalla_ajustes_grupos_favoritos.dart'; import 'ajustes/pantalla_ajustes_idioma.dart'; import 'ajustes/pantalla_ajustes_info.dart'; @@ -18,6 +17,7 @@ import 'ajustes/pantalla_ajustes_orden_listas.dart'; import 'ajustes/pantalla_ajustes_salida_audio.dart'; import 'ajustes/pantalla_ajustes_timer_sueno.dart'; import 'ajustes/widgets/fila_ajuste.dart'; +import 'pantalla_grabaciones.dart'; class PantallaAjustes extends StatelessWidget { const PantallaAjustes({super.key}); @@ -142,10 +142,15 @@ class _AjustesContent extends StatelessWidget { FilaAjuste( icon: Icons.radio_button_checked_rounded, titulo: l10n.recordingsSectionTitle, + // WU15b: this row opens the recordings LIBRARY + // (PantallaGrabaciones), matching the approved mockup's + // "Ajustes > Grabaciones" screen. The folder/size settings + // form (PantallaAjustesGrabaciones) is still reachable, but + // now from within the library via its own settings action. onTap: () => PluriPushScaffold.push( context, - (_) => const PantallaAjustesGrabaciones(), + (_) => const PantallaGrabaciones(), ), ), FilaAjuste( diff --git a/lib/pantallas/pantalla_grabaciones.dart b/lib/pantallas/pantalla_grabaciones.dart index 3db720b..d274a57 100644 --- a/lib/pantallas/pantalla_grabaciones.dart +++ b/lib/pantallas/pantalla_grabaciones.dart @@ -13,6 +13,7 @@ import '../widgets/pluri_icon.dart'; import '../widgets/pluri_layout.dart'; import '../widgets/pluri_premium_widgets.dart'; import '../widgets/pluri_push_scaffold.dart'; +import 'ajustes/pantalla_ajustes_grabaciones.dart'; /// Inline-preview playback + duration lookup for a single recording file at /// a time (WU15, recordings-library spec — "Row playback starts and @@ -228,6 +229,17 @@ class _PantallaGrabacionesState extends State { return PluriPushScaffold( title: l10n.recordingsLibraryTitle, + actions: [ + IconButton( + icon: const Icon(Icons.settings_outlined), + tooltip: l10n.recordingsLibrarySettingsTooltip, + onPressed: + () => PluriPushScaffold.push( + context, + (_) => const PantallaAjustesGrabaciones(), + ), + ), + ], body: FutureBuilder>( future: _grabaciones, builder: (context, snap) { diff --git a/openspec/changes/rediseno-funcional/tasks.md b/openspec/changes/rediseno-funcional/tasks.md index 867860b..f7198e3 100644 --- a/openspec/changes/rediseno-funcional/tasks.md +++ b/openspec/changes/rediseno-funcional/tasks.md @@ -13,6 +13,9 @@ > needs. Tables and checklists are used throughout to keep it scannable despite the length. > **WU12 does not exist** — the native EQ band-count spike was resolved before planning closed (Engram id 2498, "keep > 5 bands"). Numbering skips 11→13 on purpose; this is not a gap. +> **WU15b was added mid-apply, not planned upfront** — WU15 shipped `PantallaGrabaciones` (the recordings library) +> fully tested but reachable from nowhere in the app. WU15b (below, after WU15's section) is the coordinator-ruled fix +> that wires it into Settings navigation. It is small and does not change the 18-commit delivery model's shape. > Strict TDD is ON. Runner: `flutter test`. `flutter analyze` and a **scoped** `dart format` gate every commit. > **`flutter build` is never run.** > @@ -51,6 +54,7 @@ | 13 | `feat(eq): restyle equalizer screen and add custom presets` | 3a | 400-550 | Medium-High | Monitor | | 14 | `feat(reproductor): restructure full player with tool-tray and EQ sheet` | 13 | 450-600 | Medium-High | Monitor | | 15 | `feat(grabaciones): add recordings library screen` | 3b | ~~300-400~~ → **REALIZED: 1,767** (1,767+ / 0-, 22 files) | Medium | Monitor§ | +| 15b | `fix(grabaciones): wire the recordings library into Settings navigation` | 15 | 60-100 | Low | No | | 16 | `feat(connectivity): restyle offline and reconnect banners` | 1 | 150-250 | Low | No | | 17 | `feat(bienvenida): add monetization-free welcome screen` | 1 | 150-200 | Low | No | | 18 | `feat(i18n): add redesign strings and translate Escuchar rename to 11 locales` | all | ~0 eng. / 400-600 data | Medium (data volume, low logic risk) | No | @@ -640,7 +644,45 @@ and no task asks it to gain a "view library" link. WU15's own **Verify** command `pantalla_ajustes_grabaciones_test.dart` — confirming this screen is not meant to touch WU3b's file in this work unit. Not invented here; needs a design decision, not a guess. -## WU16 — Connectivity states +## WU15b — Wire the recordings library into Settings navigation + +**Not in the original plan — added to close the WU15 gap noted above.** WU15 built `PantallaGrabaciones` (the +recordings library) fully tested and committed, but left it unreachable from the app: `rg "PantallaGrabaciones" lib/` +found only its own declaration. This work unit exists solely to fix that. + +**Commit**: `fix(grabaciones): wire the recordings library into Settings navigation` +**Depends on**: WU15 +**Spec refs**: `recordings-library` — Browsable Recordings List (reachability); `app-navigation-shell` — Push-Chrome +on Second-Level Screens (the settings form stays a pushed screen, now one level deeper) +**Verify**: `flutter test test/pantallas/pantalla_ajustes_test.dart test/pantallas/pantalla_grabaciones_test.dart test/pantallas/ajustes/pantalla_ajustes_grabaciones_test.dart && flutter analyze && dart format --set-exit-if-changed $(git diff --cached --name-only --diff-filter=ACM HEAD -- '*.dart')` +**Modified tests**: `pantalla_ajustes_test.dart` (one scenario re-targeted), `pantalla_grabaciones_test.dart` (one new +scenario) + +**Coordinator ruling applied.** The approved mockup's screen 12 ("Ajustes › Grabaciones") depicts the recordings +**library**, not the settings form — so the `GRABACIONES Y MÚSICA` group's "Grabaciones" row now opens +`PantallaGrabaciones` (the library) instead of `PantallaAjustesGrabaciones` (the folder/size-limit settings form). +The settings form is not dropped: it stays reachable, but now from **within** the library, via a settings icon in its +`PluriPushScaffold.actions` (matching the existing `pantalla_ajustes_timer_sueno.dart` "Add" action precedent for a +real capability living in the header, not decorative chrome). + +- [x] 15b.1 RED — re-targeted `pantalla_ajustes_test.dart`'s "tapping the Grabaciones row" scenario: it now asserts + landing on `PantallaGrabaciones` (`find.text('My recordings')`), not the settings form (`find.text('Change + path')` asserted absent). +- [x] 15b.2 RED — added a new scenario to `pantalla_grabaciones_test.dart`: tapping the library's settings icon + pushes a second `PluriPushScaffold` showing the settings form (`find.text('Change path')`). +- [x] 15b.3 GREEN — `pantalla_ajustes.dart`: the "Grabaciones" `FilaAjuste.onTap` now pushes `PantallaGrabaciones`; + removed the now-unused `PantallaAjustesGrabaciones` import from this file. +- [x] 15b.4 GREEN — `pantalla_grabaciones.dart`: added `actions: [IconButton(Icons.settings_outlined, ...)]` to its + `PluriPushScaffold`, pushing `PantallaAjustesGrabaciones`. One new ARB key (en/es only, matching precedent): + `recordingsLibrarySettingsTooltip`. +- [x] 15b.5 REFACTOR — confirmed the new test needed the same `_suppressListTileInkAssertion()` helper WU3a/WU3b + established (WU3b Discovery 9: any pushed screen whose `PluriGlassSurface` body contains a tappable `ListTile` + needs it) — added to `pantalla_grabaciones_test.dart`, scoped to only the one new scenario that mounts + `PantallaAjustesGrabaciones`. +- [x] 15b.6 Verify — scoped suite green: 605/605 (up from 604), 2 skipped (unchanged, both pre-existing WU15 + documented skips). `flutter analyze`: 1 issue, identical to baseline. Literal-encoding scan: zero hits. + + **Commit**: `feat(connectivity): restyle offline and reconnect banners` **Depends on**: WU1 diff --git a/test/pantallas/pantalla_ajustes_test.dart b/test/pantallas/pantalla_ajustes_test.dart index 3fb0271..bd1239e 100644 --- a/test/pantallas/pantalla_ajustes_test.dart +++ b/test/pantallas/pantalla_ajustes_test.dart @@ -246,23 +246,30 @@ void main() { }, ); - testWidgets('tapping the Grabaciones row pushes its detail screen', ( - tester, - ) async { - setLargeSurface(tester); - _suppressListTileInkAssertion(); - final estado = await crearEstado(); - addTearDown(estado.dispose); + testWidgets( + 'tapping the Grabaciones row pushes the recordings LIBRARY, not the ' + 'folder/size settings form (WU15b — the approved mockup screen ' + '"Ajustes > Grabaciones" depicts the library)', + (tester) async { + setLargeSurface(tester); + _suppressListTileInkAssertion(); + final estado = await crearEstado(); + addTearDown(estado.dispose); - await tester.pumpWidget(buildAjustes(estado)); - await pumpStable(tester); + await tester.pumpWidget(buildAjustes(estado)); + await pumpStable(tester); - await tester.tap(find.text('Recordings')); - await pumpStable(tester); + await tester.tap(find.text('Recordings')); + await pumpStable(tester); - expect(find.byType(PluriPushScaffold), findsOneWidget); - expect(find.text('Change path'), findsOneWidget); - }); + expect(find.byType(PluriPushScaffold), findsOneWidget); + expect(find.text('My recordings'), findsOneWidget); + // The folder/size settings form is reachable FROM the library now, + // not directly from the Settings root row — see + // pantalla_grabaciones_test.dart for that entry point. + expect(find.text('Change path'), findsNothing); + }, + ); testWidgets('tapping the Info row pushes its detail screen', ( tester, diff --git a/test/pantallas/pantalla_grabaciones_test.dart b/test/pantallas/pantalla_grabaciones_test.dart index 57c2d73..36d4fb4 100644 --- a/test/pantallas/pantalla_grabaciones_test.dart +++ b/test/pantallas/pantalla_grabaciones_test.dart @@ -24,6 +24,26 @@ import 'package:shared_preferences/shared_preferences.dart'; /// the real `share_plus` call, since this suite does not mock that channel /// either (see `pantalla_ajustes_backup_test.dart`'s note on the same /// constraint). +/// +/// Pre-existing project constraint (see `pantalla_ajustes_test.dart`): +/// PluriGlassSurface paints a background over ListTile's ink layer, which +/// Flutter flags as a warning-level assertion, not a correctness bug. Only +/// needed by the WU15b settings-affordance test below, which pushes +/// PantallaAjustesGrabaciones (a ListTile-with-onTap screen) — this file's +/// other scenarios never mount that screen. +void _suppressListTileInkAssertion() { + final original = FlutterError.onError; + FlutterError.onError = (details) { + if (details.exceptionAsString().contains( + 'ListTile background color or ink splashes may be invisible', + )) { + return; + } + original?.call(details); + }; + addTearDown(() => FlutterError.onError = original); +} + void main() { setUp(() { SharedPreferences.setMockInitialValues({}); @@ -95,6 +115,36 @@ void main() { expect(find.text('My recordings'), findsOneWidget); }); + testWidgets( + 'WU15b: tapping the settings icon pushes the folder/size settings ' + 'screen (PantallaAjustesGrabaciones stays reachable, now from within ' + 'the library instead of directly from the Settings root row)', + (tester) async { + _suppressListTileInkAssertion(); + final estado = EstadoGrabacion( + servicio: _FakeServicioGrabacionConArchivos( + const [], + maxBytesFijo: 200 * 1024 * 1024, + ), + ); + addTearDown(estado.dispose); + + await tester.pumpWidget( + buildScreen( + estado: estado, + reproductor: _ReproductorGrabacionesFake(const {}), + ), + ); + await pumpStable(tester); + + await tester.tap(find.byIcon(Icons.settings_outlined)); + await pumpStable(tester); + + expect(find.byType(PluriPushScaffold), findsNWidgets(2)); + expect(find.text('Change path'), findsOneWidget); + }, + ); + testWidgets('15.1: storage bar reflects 84 of 200 MB used', (tester) async { final estado = EstadoGrabacion( servicio: _FakeServicioGrabacionConArchivos([