import 'package:fintracker_api/fintracker_api.dart'; import 'package:fintracker_app/core/widgets/money_text.dart'; import 'package:fintracker_app/features/home/scope_cards.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_test/flutter_test.dart'; ScopeCardOut _card({ String scope = 'portfolio:1', String name = 'ИИСы', String kind = 'portfolio', String total = '224608.65', String? pnl = '6643.47', String? pnlPct = '0.015', String? day = '-265.68', String? dayPct = '-0.001', String? xirr = '0.0298', String income = '17387.49', String? incomePct = '0.043', }) => ScopeCardOut( scope: scope, name: name, kind: kind, asOf: DateTime(2026, 9, 19), totalRub: total, investedRub: '200000', pnlRub: pnl, pnlPct: pnlPct, dayChangeRub: day, dayChangePct: dayPct, xirr: xirr, incomeYearRub: income, incomeYearPct: incomePct, ); Widget _app(List cards, {double width = 1200}) => ProviderScope( child: MaterialApp( home: MediaQuery( data: MediaQueryData(size: Size(width, 900)), child: Scaffold( body: SingleChildScrollView(child: ScopeCards(cards: cards)), ), ), ), ); void main() { testWidgets('a card shows the name, the value and the four figures', ( tester, ) async { await tester.pumpWidget(_app([_card()])); expect(find.text('ИИСЫ'), findsOneWidget); expect(find.text(MoneyText.format('224608.65', 'RUB')), findsOneWidget); for (final label in [ 'Прибыль', 'За день', 'Доходность', 'Пассивный доход', ]) { expect(find.text(label), findsOneWidget, reason: label); } // the gain carries an explicit plus, the loss its own minus expect(find.text('+${MoneyText.format('6643.47', 'RUB')}'), findsOneWidget); expect(find.text(MoneyText.format('-265.68', 'RUB')), findsOneWidget); expect(find.text('2,98 %'), findsOneWidget); expect( find.textContaining(MoneyText.format('17387.49', 'RUB')), findsOneWidget, ); }); testWidgets('missing figures read as a dash, not as zero', (tester) async { await tester.pumpWidget( _app([ _card( pnl: null, pnlPct: null, day: null, dayPct: null, xirr: null, income: '0', incomePct: null, ), ]), ); expect(find.text('—'), findsNWidgets(4)); }); testWidgets('cards flow into columns by the available width', (tester) async { final cards = [ for (var i = 0; i < 6; i++) _card(scope: 'account:$i', name: 'Счёт $i'), ]; addTearDown(tester.view.reset); Future columns(double width) async { tester.view.physicalSize = Size(width, 900); tester.view.devicePixelRatio = 1; await tester.pumpWidget(_app(cards, width: width)); final xs = { for (final c in cards) tester.getTopLeft(find.text('СЧЁТ ${cards.indexOf(c)}')).dx.round(), }; return xs.length; } expect(await columns(1200), 3); expect(await columns(800), 2); expect(await columns(400), 1); }); }