fix(ecualizador): header switch, banner radius, preset chips, glow thumb

Audit 11.1 (t4:566): the master enable switch moves to
PluriPushScaffold's header actions -- was the body's first
SwitchListTile row. Its realtime/pending explainer subtitle stays
behind as a plain caption so no information is lost.

Audit 11.2 (t4:571): explainer banner radius is 16 (a local one-off,
matching neither of the 3 named tokens), not radiusSm's 14.

Audit 11.3 (t4:574-577): preset chips are solid brand-teal with dark
text when active, listSurface + a faint border when not -- was
Material's own ChoiceChip theming (primaryContainer/grey).

Audit 11.5 (t4:585): band sliders use a new 20x20 _GlowSliderThumbShape
(brand-teal blurred glow + solid thumb), replacing the Material
default round thumb.

Audit 11.7 (t4:584): the dB label is brand teal at 90% alpha, not
liveGreen -- a leftover wrong colour family 11.6's slider-only fix
never touched.

Updated 2 pre-existing tests (pantalla_ajustes_ecualizador_test.dart,
pantalla_ajustes_test.dart) to locate the enable switch by key instead
of by the "Enable equalizer" text it no longer renders next to.
This commit is contained in:
2026-07-30 16:14:11 +02:00
parent b5b9829faa
commit 533896b9fa
5 changed files with 222 additions and 29 deletions
@@ -9,6 +9,7 @@ import 'package:pluriwave/modelos/dispositivo_audio.dart';
import 'package:pluriwave/modelos/emisora.dart';
import 'package:pluriwave/modelos/preset_ecualizador.dart';
import 'package:pluriwave/pantallas/ajustes/pantalla_ajustes_ecualizador.dart';
import 'package:pluriwave/tema/pluriwave_tokens.dart';
import 'package:pluriwave/widgets/ecualizador_widget.dart';
import 'package:pluriwave/widgets/pluri_glass_surface.dart';
import 'package:pluriwave/widgets/pluri_push_scaffold.dart';
@@ -119,9 +120,8 @@ void main() {
expect((appBar.title as Text).data, equals('Equalizer'));
});
testWidgets('moved control still responds: enable switch toggles activo', (
tester,
) async {
testWidgets('moved control still responds: enable switch toggles activo '
'(audit 11.1: now in the header, t4 line 566)', (tester) async {
_suppressListTileInkAssertion();
final estado = await crearEstado();
addTearDown(estado.dispose);
@@ -130,7 +130,7 @@ void main() {
await tester.pumpAndSettle();
final before = estado.ecualizador.activo;
await tester.tap(find.text('Enable equalizer'));
await tester.tap(find.byKey(const ValueKey('eq-master-switch')));
await tester.pumpAndSettle();
expect(estado.ecualizador.activo, equals(!before));
@@ -447,6 +447,74 @@ void main() {
},
);
testWidgets(
'visual fidelity (audit 11.1): the master switch is a header action, '
'not the body\'s first row (t4 line 566)',
(tester) async {
_suppressListTileInkAssertion();
final estado = await crearEstado();
addTearDown(estado.dispose);
await tester.pumpWidget(buildScreen(estado));
await tester.pumpAndSettle();
expect(
find.descendant(
of: find.byType(AppBar),
matching: find.byKey(const ValueKey('eq-master-switch')),
),
findsOneWidget,
reason: 'the master switch lives in the AppBar, not the body',
);
expect(
find.descendant(
of: find.byType(ListView),
matching: find.byKey(const ValueKey('eq-master-switch')),
),
findsNothing,
);
},
);
testWidgets(
'visual fidelity (audit 11.2): the explainer banner radius is 16, '
'not radiusSm\'s 14 (t4 line 571)',
(tester) async {
_suppressListTileInkAssertion();
final estado = await crearEstado();
addTearDown(estado.dispose);
await tester.pumpWidget(buildScreen(estado));
await tester.pumpAndSettle();
final banner = tester.widget<Container>(
find.byKey(const Key('eq-base-explainer-banner')),
);
final decoration = banner.decoration as BoxDecoration;
expect(
(decoration.borderRadius as BorderRadius).topLeft,
const Radius.circular(16),
);
},
);
testWidgets('visual fidelity (audit 11.3): the active preset chip is solid '
'brand teal with dark text (t4 lines 574-577)', (tester) async {
_suppressListTileInkAssertion();
final estado = await crearEstado();
addTearDown(estado.dispose);
await tester.pumpWidget(buildScreen(estado));
await tester.pumpAndSettle();
final chip = tester.widget<ChoiceChip>(
find.widgetWithText(ChoiceChip, 'Flat'),
);
expect(chip.selected, isTrue);
expect(chip.selectedColor, PluriWaveTokens.brand);
expect(chip.labelStyle?.color, const Color(0xFF062126));
});
testWidgets(
'Guardar como preset with a whitespace-only name shows the same validation message',
(tester) async {
+3 -2
View File
@@ -162,9 +162,10 @@ void main() {
await pumpStable(tester);
// Pushed, not index-switched: exactly one PluriPushScaffold now exists,
// and its moved control (the enable switch) is reachable.
// and its moved control (the enable switch, audit 11.1 -- now a
// header action, t4 line 566) is reachable.
expect(find.byType(PluriPushScaffold), findsOneWidget);
expect(find.text('Enable equalizer'), findsOneWidget);
expect(find.byKey(const ValueKey('eq-master-switch')), findsOneWidget);
});
testWidgets('tapping the Orden de listas row pushes its detail screen', (
+26
View File
@@ -136,4 +136,30 @@ void main() {
'EQ bands with brand teal #21D4D9 (t4 line 585)',
);
});
testWidgets(
'visual fidelity (audit 11.5): the thumb is a 20x20 custom glow shape, '
'not the Material default (t4 line 585)',
(tester) async {
await tester.pumpWidget(buildWidget());
final tema = SliderTheme.of(tester.element(find.byType(Slider).first));
final size = tema.thumbShape?.getPreferredSize(true, false);
expect(
size,
const Size(20, 20),
reason: 't4 line 585: a 20x20 thumb with a 14px brand-teal glow',
);
},
);
testWidgets('visual fidelity (audit 11.7): the dB label is brand teal, not '
'liveGreen (t4 line 584)', (tester) async {
await tester.pumpWidget(buildWidget());
final label = tester.widget<Text>(find.text('0.0dB').first);
expect(label.style?.color, PluriWaveTokens.brand.withValues(alpha: 0.9));
expect(label.style?.color, isNot(PluriWaveTokens.dark.liveGreen));
});
}