Files
sure/mobile/test/widgets/sure_icon_test.dart
ghost 4eca3b5b6b feat(mobile): add SureIcon (Lucide) primitive and migrate dashboard icons (#2346)
Introduce a SureIcon design-system primitive that renders bundled Lucide SVGs via flutter_svg (already a dependency — no new dep), mirroring the web `icon` helper / DS::FilledIcon: tokenized size (SureIconSize xs–2xl = 12–32), color inherited from the ambient IconTheme by default, and accessibility that distinguishes decorative icons (excluded from the semantics tree) from meaningful ones (semanticLabel). A SureIcons registry keeps call sites typo-safe and limited to bundled assets.

Migrate the dashboard surface off Material Icons.* onto SureIcon — 24 call sites across net_worth_card, account_card, and dashboard_screen (account-type glyphs, asset/liability trend icons, sync/empty/error states, refresh, collapsible section headers, expand chevrons). Bundle the 17 Lucide SVGs the surface needs under assets/icons/lucide/ with the ISC license. The swipe Undo control and the rest of the app's icons follow in later slices.

Part of #2235.

Signed-off-by: Juan José Mata <juanjo.mata@gmail.com>
Co-authored-by: Juan José Mata <juanjo.mata@gmail.com>
2026-06-16 09:49:14 +02:00

68 lines
2.0 KiB
Dart

import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:sure_mobile/widgets/sure_icon.dart';
void main() {
SvgPicture svg(WidgetTester tester) =>
tester.widget<SvgPicture>(find.byType(SvgPicture));
testWidgets('renders the named Lucide asset at the requested size',
(tester) async {
await tester.pumpWidget(
const MaterialApp(
home: SureIcon(SureIcons.wallet, size: SureIconSize.lg),
),
);
expect(svg(tester).width, SureIconSize.lg);
expect(svg(tester).height, SureIconSize.lg);
});
testWidgets('paints at its size inside a larger tight-constrained parent',
(tester) async {
await tester.pumpWidget(
const MaterialApp(
home: Center(
child: SizedBox(
width: 48,
height: 48,
child: SureIcon(SureIcons.landmark, size: SureIconSize.lg),
),
),
),
);
// The glyph must stay 24 (not stretch to the 48 container) — regression for
// the account-card icon rendering at 2x.
expect(tester.getSize(find.byType(SvgPicture)), const Size(24, 24));
});
testWidgets('falls back to the ambient IconTheme size when size is null',
(tester) async {
await tester.pumpWidget(
const MaterialApp(
home: IconTheme(
data: IconThemeData(size: 30),
child: SureIcon(SureIcons.refresh),
),
),
);
expect(svg(tester).width, 30);
expect(svg(tester).height, 30);
});
testWidgets('a meaningful icon exposes its label; a decorative one does not',
(tester) async {
await tester.pumpWidget(
const MaterialApp(
home: SureIcon(SureIcons.refresh, semanticLabel: 'Refresh'),
),
);
expect(find.bySemanticsLabel('Refresh'), findsOneWidget);
await tester.pumpWidget(
const MaterialApp(home: SureIcon(SureIcons.wallet)),
);
expect(find.bySemanticsLabel('wallet'), findsNothing);
});
}