Compare commits
8
Commits
ec93e45310
...
4b89c9af07
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4b89c9af07 | ||
|
|
f2b02c3ce2 | ||
|
|
db6f4a3a11 | ||
|
|
3bb92c0536 | ||
|
|
9a75027d57 | ||
|
|
93b7ec2af9 | ||
|
|
5bbf750b63 | ||
|
|
7faf56900f |
@@ -147,7 +147,9 @@ class _AjustesContent extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
const SizedBox(height: 12),
|
// Issue 3 (feedback-pruebas): t4:523/534/541 all draw a 16px gap
|
||||||
|
// between these opaque, stacked settings groups -- not 12.
|
||||||
|
const SizedBox(height: 16, key: ValueKey('ajustes-group-gap-1')),
|
||||||
GrupoAjustes(
|
GrupoAjustes(
|
||||||
titulo: l10n.settingsGroupStationsTitle,
|
titulo: l10n.settingsGroupStationsTitle,
|
||||||
filas: [
|
filas: [
|
||||||
@@ -202,7 +204,7 @@ class _AjustesContent extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
const SizedBox(height: 12),
|
const SizedBox(height: 16, key: ValueKey('ajustes-group-gap-2')),
|
||||||
GrupoAjustes(
|
GrupoAjustes(
|
||||||
titulo: l10n.settingsGroupRecordingsTitle,
|
titulo: l10n.settingsGroupRecordingsTitle,
|
||||||
filas: [
|
filas: [
|
||||||
@@ -250,7 +252,7 @@ class _AjustesContent extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
const SizedBox(height: 12),
|
const SizedBox(height: 16, key: ValueKey('ajustes-group-gap-3')),
|
||||||
GrupoAjustes(
|
GrupoAjustes(
|
||||||
titulo: l10n.settingsGroupApplicationTitle,
|
titulo: l10n.settingsGroupApplicationTitle,
|
||||||
filas: [
|
filas: [
|
||||||
|
|||||||
@@ -225,25 +225,6 @@ class _PantallaAlarmaSonandoState extends State<PantallaAlarmaSonando> {
|
|||||||
tokens: tokens,
|
tokens: tokens,
|
||||||
),
|
),
|
||||||
const SizedBox(height: 22),
|
const SizedBox(height: 22),
|
||||||
// Audit 9.4 (t4 line 419): "Lunes, 3 de agosto" between
|
|
||||||
// the pill and the hero time -- never rendered before.
|
|
||||||
// Purely additive: a new sibling Text, touching neither
|
|
||||||
// the pill above nor the hero time below.
|
|
||||||
Text(
|
|
||||||
fechaLargaConDiaSemana(
|
|
||||||
Localizations.localeOf(context).toString(),
|
|
||||||
DateTime.now(),
|
|
||||||
),
|
|
||||||
textAlign: TextAlign.center,
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 14,
|
|
||||||
fontWeight: FontWeight.w600,
|
|
||||||
color: Theme.of(
|
|
||||||
context,
|
|
||||||
).colorScheme.onSurface.withValues(alpha: 0.6),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(height: 6),
|
|
||||||
FittedBox(
|
FittedBox(
|
||||||
fit: BoxFit.scaleDown,
|
fit: BoxFit.scaleDown,
|
||||||
child: Text(
|
child: Text(
|
||||||
@@ -261,6 +242,28 @@ class _PantallaAlarmaSonandoState extends State<PantallaAlarmaSonando> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 6),
|
const SizedBox(height: 6),
|
||||||
|
// Audit 9.4: the date line goes BELOW the hero time. The
|
||||||
|
// prototype's order is pill (t4:415-416) -> 7:30 at 88px
|
||||||
|
// (t4:417) -> "Lunes, 3 de agosto" at 14px (t4:419). An
|
||||||
|
// earlier pass placed it between the pill and the time
|
||||||
|
// and cited "t4 line 419" for it — that line number is
|
||||||
|
// where the date SITS in the source, which is precisely
|
||||||
|
// why it comes last, not first.
|
||||||
|
Text(
|
||||||
|
fechaLargaConDiaSemana(
|
||||||
|
Localizations.localeOf(context).toString(),
|
||||||
|
DateTime.now(),
|
||||||
|
),
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 14,
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
color: Theme.of(
|
||||||
|
context,
|
||||||
|
).colorScheme.onSurface.withValues(alpha: 0.6),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 6),
|
||||||
Text(
|
Text(
|
||||||
localizedAlarmName(l10n, alarma.nombre),
|
localizedAlarmName(l10n, alarma.nombre),
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
@@ -339,14 +342,18 @@ class _PantallaAlarmaSonandoState extends State<PantallaAlarmaSonando> {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 10),
|
// Issue 3 (feedback-pruebas): t4:427 wraps POSPONER's
|
||||||
|
// eyebrow, the snooze tiles and Stop in a `gap:12` flex
|
||||||
|
// column -- the same 12 on both sides, not the 10/14 pair
|
||||||
|
// this used to carry.
|
||||||
|
const SizedBox(height: 12),
|
||||||
_FilaSnoozeFija(
|
_FilaSnoozeFija(
|
||||||
alarma: alarma,
|
alarma: alarma,
|
||||||
l10n: l10n,
|
l10n: l10n,
|
||||||
tokens: tokens,
|
tokens: tokens,
|
||||||
onPosponer: _posponer,
|
onPosponer: _posponer,
|
||||||
),
|
),
|
||||||
const SizedBox(height: 14),
|
const SizedBox(height: 12),
|
||||||
SizedBox(
|
SizedBox(
|
||||||
width: double.infinity,
|
width: double.infinity,
|
||||||
child: FilledButton.icon(
|
child: FilledButton.icon(
|
||||||
|
|||||||
@@ -174,12 +174,18 @@ class _PantallaFavoritosState extends State<PantallaFavoritos> {
|
|||||||
|
|
||||||
return ReorderableListView(
|
return ReorderableListView(
|
||||||
buildDefaultDragHandles: false,
|
buildDefaultDragHandles: false,
|
||||||
padding: const EdgeInsets.fromLTRB(
|
// Issue 3 (feedback-pruebas): zero horizontal here, matching every
|
||||||
PluriLayout.horizontal,
|
// other root's PluriLayout.pageListPadding convention (Alarmas,
|
||||||
4,
|
// Ajustes, and this screen's OWN empty-state branch above).
|
||||||
PluriLayout.horizontal,
|
// ReorderableListView.padding wraps header/children/footer UNIFORMLY,
|
||||||
PluriLayout.bottomChromeInset,
|
// so a single horizontal value here can never be simultaneously right
|
||||||
),
|
// for PluriRootHeader (self-padded, wants none), the reorderable rows
|
||||||
|
// (want row tier, applied per item below) and the footer CTA (wants
|
||||||
|
// card tier, applied on the footer's own Padding below). The previous
|
||||||
|
// `PluriLayout.horizontal` doubled up on top of PluriRootHeader's own
|
||||||
|
// internal inset, pushing "Favorites" in by 36px instead of the 20px
|
||||||
|
// every other root uses for its title.
|
||||||
|
padding: const EdgeInsets.only(bottom: PluriLayout.bottomChromeInset),
|
||||||
header: Padding(
|
header: Padding(
|
||||||
padding: const EdgeInsets.only(bottom: 12),
|
padding: const EdgeInsets.only(bottom: 12),
|
||||||
child: Column(
|
child: Column(
|
||||||
@@ -224,17 +230,39 @@ class _PantallaFavoritosState extends State<PantallaFavoritos> {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
const SizedBox(height: 12),
|
const SizedBox(height: 12),
|
||||||
_FilaChipsGrupos(
|
// Issue 3 (feedback-pruebas): t4:218 draws this chip strip at
|
||||||
|
// title-tier (20px) horizontal inset, directly on the page
|
||||||
|
// background -- it now needs its OWN inset since the list's
|
||||||
|
// padding no longer supplies one.
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(
|
||||||
|
horizontal: PluriLayout.titleHorizontal,
|
||||||
|
),
|
||||||
|
child: _FilaChipsGrupos(
|
||||||
grupos: gruposVisibles,
|
grupos: gruposVisibles,
|
||||||
favoritos: favoritos,
|
favoritos: favoritos,
|
||||||
seleccionado: seleccionEfectiva,
|
seleccionado: seleccionEfectiva,
|
||||||
onSeleccionar: (id) => setState(() => _grupoSeleccionadoId = id),
|
onSeleccionar:
|
||||||
|
(id) => setState(() => _grupoSeleccionadoId = id),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
footer: Padding(
|
footer: Padding(
|
||||||
padding: const EdgeInsets.only(top: 4),
|
// Issue 3 (feedback-pruebas): card tier (16, matching every other
|
||||||
|
// screen's dashed CTA) now that the list's own padding no longer
|
||||||
|
// supplies it, plus t4:234's 8px gap above the CTA
|
||||||
|
// (PluriLayout.compactGap) instead of the previous unwired literal
|
||||||
|
// 4 -- the ONLY state of this screen with a nonzero top gap before
|
||||||
|
// its own content used a value that matched neither this screen's
|
||||||
|
// own empty-state branch nor the prototype.
|
||||||
|
padding: const EdgeInsets.fromLTRB(
|
||||||
|
PluriLayout.horizontal,
|
||||||
|
PluriLayout.compactGap,
|
||||||
|
PluriLayout.horizontal,
|
||||||
|
0,
|
||||||
|
),
|
||||||
child: _CtaEmisoraPersonalizada(
|
child: _CtaEmisoraPersonalizada(
|
||||||
onTap: _abrirFormularioEmisoraPersonalizada,
|
onTap: _abrirFormularioEmisoraPersonalizada,
|
||||||
),
|
),
|
||||||
@@ -244,8 +272,17 @@ class _PantallaFavoritosState extends State<PantallaFavoritos> {
|
|||||||
_onReorder(filtrados, favoritos, oldIndex, newIndex),
|
_onReorder(filtrados, favoritos, oldIndex, newIndex),
|
||||||
children: [
|
children: [
|
||||||
for (var i = 0; i < filtrados.length; i++)
|
for (var i = 0; i < filtrados.length; i++)
|
||||||
_FilaFavorito(
|
// Issue 3 (feedback-pruebas): row tier (12), not card tier -- the
|
||||||
|
// key moves to this wrapper (ReorderableListView identifies each
|
||||||
|
// child by its own top-level key) since FilaEmisoraPlana rows are
|
||||||
|
// documented (audit 4.3) as flat, background-less rows, the same
|
||||||
|
// tier Buscar's results list already uses for the same widget.
|
||||||
|
Padding(
|
||||||
key: ValueKey(filtrados[i].uuid),
|
key: ValueKey(filtrados[i].uuid),
|
||||||
|
padding: const EdgeInsets.symmetric(
|
||||||
|
horizontal: PluriLayout.rowHorizontal,
|
||||||
|
),
|
||||||
|
child: _FilaFavorito(
|
||||||
index: i,
|
index: i,
|
||||||
emisora: filtrados[i],
|
emisora: filtrados[i],
|
||||||
grupos: gruposVisibles,
|
grupos: gruposVisibles,
|
||||||
@@ -254,6 +291,7 @@ class _PantallaFavoritosState extends State<PantallaFavoritos> {
|
|||||||
orElse: () => gruposVisibles.first,
|
orElse: () => gruposVisibles.first,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -343,7 +381,6 @@ class _FilaChipsGrupos extends StatelessWidget {
|
|||||||
|
|
||||||
class _FilaFavorito extends StatelessWidget {
|
class _FilaFavorito extends StatelessWidget {
|
||||||
const _FilaFavorito({
|
const _FilaFavorito({
|
||||||
super.key,
|
|
||||||
required this.index,
|
required this.index,
|
||||||
required this.emisora,
|
required this.emisora,
|
||||||
required this.grupos,
|
required this.grupos,
|
||||||
|
|||||||
@@ -251,7 +251,12 @@ class _PantallaGrabacionesState extends State<PantallaGrabaciones> {
|
|||||||
padding: PluriLayout.pageContentPadding,
|
padding: PluriLayout.pageContentPadding,
|
||||||
children: [
|
children: [
|
||||||
_BarraDeAlmacenamiento(archivos: archivos),
|
_BarraDeAlmacenamiento(archivos: archivos),
|
||||||
const SizedBox(height: 12),
|
// Issue 3 (feedback-pruebas): t4:617 draws a 16px gap between
|
||||||
|
// the storage card and the rows below it, not 12.
|
||||||
|
const SizedBox(
|
||||||
|
height: 16,
|
||||||
|
key: ValueKey('grabaciones-storage-gap'),
|
||||||
|
),
|
||||||
if (snap.connectionState == ConnectionState.done &&
|
if (snap.connectionState == ConnectionState.done &&
|
||||||
archivos.isEmpty)
|
archivos.isEmpty)
|
||||||
PluriEmptyState(
|
PluriEmptyState(
|
||||||
|
|||||||
@@ -134,7 +134,12 @@ class _PantallaPaisesState extends State<PantallaPaises> {
|
|||||||
),
|
),
|
||||||
if (query.isEmpty) ...[
|
if (query.isEmpty) ...[
|
||||||
_seccionTusIdiomas(context, estado.paises, l10n),
|
_seccionTusIdiomas(context, estado.paises, l10n),
|
||||||
const SizedBox(height: 16),
|
// Issue 3 (feedback-pruebas): t4:260 draws a 14px gap
|
||||||
|
// between "Tus idiomas" and "Todos", not 16.
|
||||||
|
const SizedBox(
|
||||||
|
height: 14,
|
||||||
|
key: ValueKey('paises-seccion-gap'),
|
||||||
|
),
|
||||||
_seccionTodos(context, estado.paises, l10n),
|
_seccionTodos(context, estado.paises, l10n),
|
||||||
] else
|
] else
|
||||||
_seccionTodos(context, paisesFiltrados, l10n),
|
_seccionTodos(context, paisesFiltrados, l10n),
|
||||||
|
|||||||
@@ -306,6 +306,32 @@ void main() {
|
|||||||
expect(find.text('RECORDINGS & MUSIC'), findsOneWidget);
|
expect(find.text('RECORDINGS & MUSIC'), findsOneWidget);
|
||||||
expect(find.text('APPLICATION'), findsOneWidget);
|
expect(find.text('APPLICATION'), findsOneWidget);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
testWidgets(
|
||||||
|
'Issue 3 (feedback-pruebas): the gap between stacked settings groups '
|
||||||
|
'is 16, matching t4:523/534/541 -- not 12',
|
||||||
|
(tester) async {
|
||||||
|
setLargeSurface(tester);
|
||||||
|
_suppressListTileInkAssertion();
|
||||||
|
final estado = await crearEstado();
|
||||||
|
addTearDown(estado.dispose);
|
||||||
|
|
||||||
|
await tester.pumpWidget(buildAjustes(estado));
|
||||||
|
await pumpStable(tester);
|
||||||
|
|
||||||
|
for (final key in [
|
||||||
|
'ajustes-group-gap-1',
|
||||||
|
'ajustes-group-gap-2',
|
||||||
|
'ajustes-group-gap-3',
|
||||||
|
]) {
|
||||||
|
expect(
|
||||||
|
tester.getSize(find.byKey(ValueKey(key))).height,
|
||||||
|
16,
|
||||||
|
reason: 't4:523/534/541 all draw a 16px gap between stacked groups',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -99,8 +99,8 @@ void main() {
|
|||||||
SharedPreferences.setMockInitialValues({});
|
SharedPreferences.setMockInitialValues({});
|
||||||
});
|
});
|
||||||
|
|
||||||
testWidgets('visual fidelity (audit 9.4): the date line renders between the '
|
testWidgets('visual fidelity (audit 9.4): the date line renders BELOW the '
|
||||||
'schedule pill and the hero time (t4:419)', (tester) async {
|
'hero time (t4:415-419: pill, then 7:30, then the date)', (tester) async {
|
||||||
await _montarPantalla(tester);
|
await _montarPantalla(tester);
|
||||||
|
|
||||||
final localeTag =
|
final localeTag =
|
||||||
@@ -111,16 +111,22 @@ void main() {
|
|||||||
|
|
||||||
expect(find.text(esperado), findsOneWidget);
|
expect(find.text(esperado), findsOneWidget);
|
||||||
|
|
||||||
// Order: pill above the date line, date line above the hero time.
|
// Order: pill, then the hero time, then the date line. This test used
|
||||||
|
// to assert date-before-time and cited "t4:419" for it — but 419 is
|
||||||
|
// simply the source line the date occupies, and in the prototype it
|
||||||
|
// comes AFTER the 88px time on line 417. The citation refuted the
|
||||||
|
// assertion it was supporting.
|
||||||
final pillY =
|
final pillY =
|
||||||
tester
|
tester
|
||||||
.getBottomLeft(find.byKey(const ValueKey('ringing-schedule-pill')))
|
.getBottomLeft(find.byKey(const ValueKey('ringing-schedule-pill')))
|
||||||
.dy;
|
.dy;
|
||||||
final dateY = tester.getTopLeft(find.text(esperado)).dy;
|
|
||||||
final timeY =
|
final timeY =
|
||||||
tester.getTopLeft(find.byKey(const ValueKey('ringing-hero-time'))).dy;
|
tester
|
||||||
expect(pillY <= dateY, isTrue);
|
.getBottomLeft(find.byKey(const ValueKey('ringing-hero-time')))
|
||||||
expect(dateY <= timeY, isTrue);
|
.dy;
|
||||||
|
final dateY = tester.getTopLeft(find.text(esperado)).dy;
|
||||||
|
expect(pillY <= timeY, isTrue, reason: 'pill sits above the time');
|
||||||
|
expect(timeY <= dateY, isTrue, reason: 'the date sits below the time');
|
||||||
|
|
||||||
// Regression guard: pumpAndSettle must still complete (purely
|
// Regression guard: pumpAndSettle must still complete (purely
|
||||||
// additive static text, no new animation).
|
// additive static text, no new animation).
|
||||||
@@ -159,4 +165,49 @@ void main() {
|
|||||||
await tester.pumpAndSettle();
|
await tester.pumpAndSettle();
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
testWidgets(
|
||||||
|
'Issue 3 (feedback-pruebas): the gap above the snooze tiles matches the '
|
||||||
|
'gap below them (t4:427 draws a uniform gap:12 flex column) -- the '
|
||||||
|
'previous 10/14 pair matched neither the prototype nor each other',
|
||||||
|
(tester) async {
|
||||||
|
await _montarPantalla(tester);
|
||||||
|
final l10n = AppLocalizations.of(
|
||||||
|
tester.element(find.byType(PantallaAlarmaSonando)),
|
||||||
|
);
|
||||||
|
|
||||||
|
final eyebrowBottom =
|
||||||
|
tester
|
||||||
|
.getBottomLeft(
|
||||||
|
find
|
||||||
|
.ancestor(
|
||||||
|
of: find.byIcon(Icons.snooze_rounded),
|
||||||
|
matching: find.byType(Row),
|
||||||
|
)
|
||||||
|
.first,
|
||||||
|
)
|
||||||
|
.dy;
|
||||||
|
final tileDestacado = find.ancestor(
|
||||||
|
of: find.text(l10n.alarmSnoozeOptionLabel(10)),
|
||||||
|
matching: find.byType(FilledButton),
|
||||||
|
);
|
||||||
|
final tilesTop = tester.getTopLeft(tileDestacado).dy;
|
||||||
|
final tilesBottom = tester.getBottomLeft(tileDestacado).dy;
|
||||||
|
final stopButtonTop =
|
||||||
|
tester
|
||||||
|
.getTopLeft(find.byKey(const ValueKey('ringing-stop-button')))
|
||||||
|
.dy;
|
||||||
|
|
||||||
|
expect(
|
||||||
|
tilesTop - eyebrowBottom,
|
||||||
|
12,
|
||||||
|
reason: 't4:427: gap:12 above the snooze tiles',
|
||||||
|
);
|
||||||
|
expect(
|
||||||
|
stopButtonTop - tilesBottom,
|
||||||
|
12,
|
||||||
|
reason: 't4:427: gap:12 below the snooze tiles, same as above',
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,9 @@ import 'package:pluriwave/l10n/gen/app_localizations.dart';
|
|||||||
import 'package:pluriwave/pantallas/ajustes/pantalla_ajustes_grupos_favoritos.dart';
|
import 'package:pluriwave/pantallas/ajustes/pantalla_ajustes_grupos_favoritos.dart';
|
||||||
import 'package:pluriwave/pantallas/pantalla_favoritos.dart';
|
import 'package:pluriwave/pantallas/pantalla_favoritos.dart';
|
||||||
import 'package:pluriwave/widgets/fila_emisora_plana.dart';
|
import 'package:pluriwave/widgets/fila_emisora_plana.dart';
|
||||||
|
import 'package:pluriwave/widgets/pluri_layout.dart';
|
||||||
import 'package:pluriwave/widgets/pluri_push_scaffold.dart';
|
import 'package:pluriwave/widgets/pluri_push_scaffold.dart';
|
||||||
|
import 'package:pluriwave/widgets/pluri_root_header.dart';
|
||||||
import 'package:pluriwave/widgets/tarjeta_emisora.dart';
|
import 'package:pluriwave/widgets/tarjeta_emisora.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
import 'package:shared_preferences/shared_preferences.dart';
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
@@ -546,6 +548,106 @@ void main() {
|
|||||||
expect(inactivo.backgroundColor, const Color(0xFF102532));
|
expect(inactivo.backgroundColor, const Color(0xFF102532));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
group('Issue 3 (feedback-pruebas): spacing tiers', () {
|
||||||
|
testWidgets('the header title sits at title-tier inset (20px) -- '
|
||||||
|
'ReorderableListView.padding used to double up on top of '
|
||||||
|
"PluriRootHeader's own internal inset", (tester) async {
|
||||||
|
setLargeSurface(tester);
|
||||||
|
_suppressListTileInkAssertion();
|
||||||
|
final estado = await crearEstadoConFavoritos();
|
||||||
|
addTearDown(estado.dispose);
|
||||||
|
final l10n = lookupAppLocalizations(const Locale('en'));
|
||||||
|
|
||||||
|
await tester.pumpWidget(buildScreen(estado));
|
||||||
|
await pumpStable(tester);
|
||||||
|
|
||||||
|
final titulo = find.descendant(
|
||||||
|
of: find.byType(PluriRootHeader),
|
||||||
|
matching: find.text(l10n.favoritesTitle),
|
||||||
|
);
|
||||||
|
expect(
|
||||||
|
tester.getTopLeft(titulo).dx,
|
||||||
|
PluriLayout.titleHorizontal,
|
||||||
|
reason:
|
||||||
|
'PluriRootHeader already supplies its own 20px inset; the '
|
||||||
|
'previous ReorderableListView.padding of 16 doubled up on top '
|
||||||
|
'of it, landing the title at 36px instead of 20px -- the ONE '
|
||||||
|
"root screen whose header didn't match Alarmas/Ajustes",
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
testWidgets(
|
||||||
|
'the header sits at the SAME horizontal position whether the list is '
|
||||||
|
'empty or populated -- two mutually-exclusive states of the same '
|
||||||
|
'header must not read differently',
|
||||||
|
(tester) async {
|
||||||
|
setLargeSurface(tester);
|
||||||
|
final l10n = lookupAppLocalizations(const Locale('en'));
|
||||||
|
|
||||||
|
final vacio = await crearEstadoVacio();
|
||||||
|
addTearDown(vacio.dispose);
|
||||||
|
await tester.pumpWidget(buildScreen(vacio));
|
||||||
|
await pumpStable(tester);
|
||||||
|
final dxVacio =
|
||||||
|
tester
|
||||||
|
.getTopLeft(
|
||||||
|
find.descendant(
|
||||||
|
of: find.byType(PluriRootHeader),
|
||||||
|
matching: find.text(l10n.favoritesTitle),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.dx;
|
||||||
|
|
||||||
|
_suppressListTileInkAssertion();
|
||||||
|
final conFavoritos = await crearEstadoConFavoritos();
|
||||||
|
addTearDown(conFavoritos.dispose);
|
||||||
|
await tester.pumpWidget(buildScreen(conFavoritos));
|
||||||
|
await pumpStable(tester);
|
||||||
|
final dxConFavoritos =
|
||||||
|
tester
|
||||||
|
.getTopLeft(
|
||||||
|
find.descendant(
|
||||||
|
of: find.byType(PluriRootHeader),
|
||||||
|
matching: find.text(l10n.favoritesTitle),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.dx;
|
||||||
|
|
||||||
|
expect(
|
||||||
|
dxConFavoritos,
|
||||||
|
dxVacio,
|
||||||
|
reason:
|
||||||
|
'the empty and populated branches of this screen must render '
|
||||||
|
'the SAME header inset -- they previously did not (0 vs 16 '
|
||||||
|
'extra px of list-level padding)',
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
testWidgets(
|
||||||
|
'each favourite row uses row-tier horizontal inset (12), not the '
|
||||||
|
'card-tier constant a background-less row was never meant to carry',
|
||||||
|
(tester) async {
|
||||||
|
setLargeSurface(tester);
|
||||||
|
_suppressListTileInkAssertion();
|
||||||
|
final estado = await crearEstadoConFavoritos();
|
||||||
|
addTearDown(estado.dispose);
|
||||||
|
|
||||||
|
await tester.pumpWidget(buildScreen(estado));
|
||||||
|
await pumpStable(tester);
|
||||||
|
|
||||||
|
expect(
|
||||||
|
tester.getTopLeft(find.byType(FilaEmisoraPlana).first).dx,
|
||||||
|
PluriLayout.rowHorizontal,
|
||||||
|
reason:
|
||||||
|
'audit 4.3: background-less rows are row tier (12), matching '
|
||||||
|
'the same widget already fixed on Buscar -- not card tier '
|
||||||
|
'(16)',
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void setLargeSurface(WidgetTester tester) {
|
void setLargeSurface(WidgetTester tester) {
|
||||||
|
|||||||
@@ -216,6 +216,35 @@ void main() {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
testWidgets(
|
||||||
|
'Issue 3 (feedback-pruebas): the gap between the storage card and the '
|
||||||
|
'rows below is 16, matching t4:617 -- not 12',
|
||||||
|
(tester) async {
|
||||||
|
final estado = EstadoGrabacion(
|
||||||
|
servicio: _FakeServicioGrabacionConArchivos([
|
||||||
|
fijaA,
|
||||||
|
], maxBytesFijo: 200 * 1024 * 1024),
|
||||||
|
);
|
||||||
|
addTearDown(estado.dispose);
|
||||||
|
|
||||||
|
await tester.pumpWidget(
|
||||||
|
buildScreen(
|
||||||
|
estado: estado,
|
||||||
|
reproductor: _ReproductorGrabacionesFake(const {}),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
await pumpStable(tester);
|
||||||
|
|
||||||
|
expect(
|
||||||
|
tester
|
||||||
|
.getSize(find.byKey(const ValueKey('grabaciones-storage-gap')))
|
||||||
|
.height,
|
||||||
|
16,
|
||||||
|
reason: 't4:617 draws a 16px gap here',
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
testWidgets('15.2-A: 3 recording fixtures render as 3 rows', (tester) async {
|
testWidgets('15.2-A: 3 recording fixtures render as 3 rows', (tester) async {
|
||||||
final estado = EstadoGrabacion(
|
final estado = EstadoGrabacion(
|
||||||
servicio: _FakeServicioGrabacionConArchivos([
|
servicio: _FakeServicioGrabacionConArchivos([
|
||||||
|
|||||||
@@ -262,6 +262,27 @@ void main() {
|
|||||||
|
|
||||||
expect(find.byIcon(Icons.search_rounded), findsOneWidget);
|
expect(find.byIcon(Icons.search_rounded), findsOneWidget);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
testWidgets('Issue 3 (feedback-pruebas): the gap between "Tus idiomas" and '
|
||||||
|
'"Todos" is 14, matching t4:260 -- not 16', (tester) async {
|
||||||
|
final estado = EstadoBusqueda(
|
||||||
|
radio: FakeServicioRadio(
|
||||||
|
paises: const [
|
||||||
|
PaisRadio(nombre: 'Spain', codigoIso: 'ES', numeroEmisoras: 482),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
addTearDown(estado.dispose);
|
||||||
|
|
||||||
|
await tester.pumpWidget(buildScreen(estado));
|
||||||
|
await pumpEstable(tester);
|
||||||
|
|
||||||
|
expect(
|
||||||
|
tester.getSize(find.byKey(const ValueKey('paises-seccion-gap'))).height,
|
||||||
|
14,
|
||||||
|
reason: 't4:260 draws a 14px gap between the two eyebrow sections',
|
||||||
|
);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
testWidgets(
|
testWidgets(
|
||||||
|
|||||||
Reference in New Issue
Block a user