feat(ui): add premium PluriWave redesign
Build & Deploy Pluriwave / Análisis de código (push) Failing after 21s
Build & Deploy Pluriwave / Build APK + AAB release (push) Has been skipped

This commit is contained in:
2026-05-20 18:42:22 +02:00
parent f95a8290ae
commit c707fc9911
30 changed files with 2218 additions and 954 deletions
@@ -0,0 +1,51 @@
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:pluriwave/tema/pluriwave_theme.dart';
import 'package:pluriwave/tema/pluriwave_tokens.dart';
import 'package:pluriwave/widgets/pluri_glass_surface.dart';
import 'package:pluriwave/widgets/pluri_icon.dart';
import 'package:pluriwave/widgets/pluri_wave_scaffold.dart';
void main() {
test('PluriWaveTokens.dark mantiene valores base esperados', () {
expect(PluriWaveTokens.dark.deepViolet, const Color(0xFF24123D));
expect(PluriWaveTokens.dark.radiusMd, 16);
expect(PluriWaveTokens.dark.spacingMd, 16);
});
testWidgets('PluriIcon expone semantics label', (tester) async {
await tester.pumpWidget(
MaterialApp(
theme: PluriWaveTheme.dark(),
home: const Scaffold(
body: PluriIcon(
glyph: PluriIconGlyph.search,
variant: PluriIconVariant.activeGlow,
semanticLabel: 'Buscar emisoras',
),
),
),
);
expect(find.bySemanticsLabel('Buscar emisoras'), findsOneWidget);
});
testWidgets('PluriGlassSurface y PluriWaveScaffold se instancian', (tester) async {
await tester.pumpWidget(
MaterialApp(
theme: PluriWaveTheme.dark(),
home: const PluriWaveScaffold(
body: Center(
child: PluriGlassSurface(
child: Text('ok'),
),
),
),
),
);
expect(find.byType(PluriWaveScaffold), findsOneWidget);
expect(find.byType(PluriGlassSurface), findsOneWidget);
expect(find.text('ok'), findsOneWidget);
});
}
@@ -0,0 +1,48 @@
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:pluriwave/servicios/servicio_audio.dart';
import 'package:pluriwave/widgets/visualizador_audio.dart';
void main() {
group('VisualizadorAudio lifecycle', () {
testWidgets('ignora eventos de estado después de dispose', (tester) async {
final controller = StreamController<EstadoReproduccion>.broadcast();
await tester.pumpWidget(
MaterialApp(
home: Scaffold(
body: VisualizadorAudio(estadoStream: controller.stream),
),
),
);
await tester.pumpWidget(const SizedBox.shrink());
controller.add(EstadoReproduccion.reproduciendo);
await tester.pump();
expect(tester.takeException(), isNull);
await controller.close();
});
testWidgets('ignora eventos de estado después de dispose en indicador', (tester) async {
final controller = StreamController<EstadoReproduccion>.broadcast();
await tester.pumpWidget(
MaterialApp(
home: Scaffold(
body: IndicadorReproduccion(estadoStream: controller.stream),
),
),
);
await tester.pumpWidget(const SizedBox.shrink());
controller.add(EstadoReproduccion.reproduciendo);
await tester.pump();
expect(tester.takeException(), isNull);
await controller.close();
});
});
}