Files
pluriwave/test/widgets/ecualizador_widget_test.dart
FreeTLab 533896b9fa 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.
2026-07-30 16:14:11 +02:00

166 lines
5.5 KiB
Dart

import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:pluriwave/l10n/gen/app_localizations.dart';
import 'package:pluriwave/modelos/preset_ecualizador.dart';
import 'package:pluriwave/tema/pluriwave_tokens.dart';
import 'package:pluriwave/widgets/ecualizador_widget.dart';
/// WU13 task 13.1 — first-class regression guard (design ADR-5, spec
/// `eq-custom-presets` "Five-Band Equalizer"): the equalizer widget must
/// always render exactly 5 vertical sliders. Band count is device-reported
/// via `just_audio`'s `AndroidEqualizer` (spike, Engram id 2498), not
/// app-chosen — any future change rendering 7 sliders is rejected on sight.
///
/// **Correction found at apply time**: `tasks.md`'s WU13 Verify command
/// names this file as if it already existed ("Modified tests:
/// ecualizador_widget_test.dart"). No such file existed before this commit
/// (`ecualizador_widget.dart` had zero test coverage) — created new instead.
void main() {
Widget buildWidget({
PresetEcualizador? preset,
bool habilitado = true,
void Function(PresetEcualizador)? onCambio,
}) {
return MaterialApp(
locale: const Locale('en'),
localizationsDelegates: AppLocalizations.localizationsDelegates,
supportedLocales: AppLocalizations.supportedLocales,
home: Scaffold(
body: EcualizadorWidget(
preset: preset ?? PresetEcualizador.flat,
habilitado: habilitado,
onCambio: onCambio ?? (_) {},
),
),
);
}
testWidgets('renders exactly 5 vertical sliders, one per band', (
tester,
) async {
await tester.pumpWidget(buildWidget());
expect(find.byType(Slider), findsNWidgets(5));
});
testWidgets('renders exactly 5 sliders regardless of the preset selected', (
tester,
) async {
// Regression guard restated: a future change proposing 7 sliders (the
// rejected mockup band count) must fail this test regardless of which
// fixed preset is active.
await tester.pumpWidget(buildWidget(preset: PresetEcualizador.jazz));
expect(find.byType(Slider), findsNWidgets(5));
});
testWidgets('dragging a slider reports the updated band back via onCambio', (
tester,
) async {
PresetEcualizador? reportado;
await tester.pumpWidget(buildWidget(onCambio: (p) => reportado = p));
final slider = tester.widget<Slider>(find.byType(Slider).first);
slider.onChanged?.call(6.0);
await tester.pump();
expect(reportado, isNotNull);
expect(reportado!.bandas.length, 5);
expect(reportado!.bandas.first, 6.0);
});
testWidgets(
'habilitado: false disables every slider (greyed, non-interactive)',
(tester) async {
await tester.pumpWidget(buildWidget(habilitado: false));
final sliders = tester.widgetList<Slider>(find.byType(Slider));
expect(sliders, hasLength(5));
for (final slider in sliders) {
expect(slider.onChanged, isNull);
}
},
);
testWidgets('habilitado: true (default) keeps every slider interactive', (
tester,
) async {
await tester.pumpWidget(buildWidget());
final sliders = tester.widgetList<Slider>(find.byType(Slider));
expect(sliders, hasLength(5));
for (final slider in sliders) {
expect(slider.onChanged, isNotNull);
}
});
// Visual-fidelity guards (audit id 2521, items 11.4 and 11.6). These two
// values drifted silently once already: the whole point of the fidelity
// pass was that behavioural tests ("renders 5 sliders") never noticed the
// sliders were 46% too short and painted in the wrong colour family.
testWidgets('each band column is 280 tall, as the prototype draws it', (
tester,
) async {
await tester.pumpWidget(buildWidget());
final columnas = tester.widgetList<SizedBox>(
find.descendant(
of: find.byType(EcualizadorWidget),
matching: find.byType(SizedBox),
),
);
expect(
columnas.where((c) => c.height == 280),
hasLength(5),
reason:
'prototype t4 line 581 sizes the band column at 280; 152 left the '
'sliders 46% short',
);
});
testWidgets('band fill uses the brand teal, not the LIVE-badge green', (
tester,
) async {
await tester.pumpWidget(buildWidget());
final tema = SliderTheme.of(tester.element(find.byType(Slider).first));
expect(tema.activeTrackColor, PluriWaveTokens.brand);
expect(tema.thumbColor, PluriWaveTokens.brand);
expect(
tema.activeTrackColor,
isNot(PluriWaveTokens.dark.liveGreen),
reason:
'liveGreen (#7EE4C2) is the LIVE badge colour; the prototype fills '
'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));
});
}