feat(app): новый визуальный язык, верхняя навигация, портфели, создание счетов и ручные события
Тема и общие виджеты (AssetIcon, ServiceMark, HelpTip, глоссарий), верхняя панель TopNav и вкладки Аналитики вместо NavSidebar, иконки PWA. Экраны: портфели, создание брокерского счёта, ручное событие, правка инструмента, Обзор карточками по скоупам и таблица активов, пересчёт метрик с опросом /metrics/status. design-system.md обновлён.
This commit is contained in:
@@ -0,0 +1,109 @@
|
||||
import 'package:fintracker_api/fintracker_api.dart';
|
||||
import 'package:fintracker_app/features/portfolio/instrument_edit_dialog.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
InstrumentOut _instrument() => InstrumentOut(
|
||||
id: 1,
|
||||
assetClass: 'share',
|
||||
isin: 'RU0008958863',
|
||||
figi: null,
|
||||
ticker: 'MSNG',
|
||||
board: 'TQBR',
|
||||
exchange: null,
|
||||
name: 'Мосэнерго',
|
||||
issuer: null,
|
||||
currency: 'RUB',
|
||||
lot: 1,
|
||||
nominal: null,
|
||||
nominalCurrency: null,
|
||||
maturityDate: null,
|
||||
sector: null,
|
||||
country: null,
|
||||
isActive: true,
|
||||
);
|
||||
|
||||
Future<InstrumentPatch?> _open(
|
||||
WidgetTester tester,
|
||||
Future<void> Function() interact,
|
||||
) async {
|
||||
InstrumentPatch? result;
|
||||
var closed = false;
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
home: Builder(
|
||||
builder: (context) => Scaffold(
|
||||
body: TextButton(
|
||||
onPressed: () async {
|
||||
result = await showDialog<InstrumentPatch>(
|
||||
context: context,
|
||||
builder: (_) => InstrumentEditDialog(instrument: _instrument()),
|
||||
);
|
||||
closed = true;
|
||||
},
|
||||
child: const Text('open'),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
await tester.tap(find.text('open'));
|
||||
await tester.pumpAndSettle();
|
||||
await interact();
|
||||
await tester.pumpAndSettle();
|
||||
expect(closed, isTrue);
|
||||
return result;
|
||||
}
|
||||
|
||||
void main() {
|
||||
testWidgets('only the changed lot goes into the patch', (tester) async {
|
||||
final patch = await _open(tester, () async {
|
||||
await tester.enterText(find.widgetWithText(TextFormField, '1'), '1000');
|
||||
await tester.tap(find.text('Сохранить'));
|
||||
});
|
||||
|
||||
expect(patch, isNotNull);
|
||||
expect(patch!.lot, 1000);
|
||||
expect(patch.name, isNull);
|
||||
expect(patch.board, isNull);
|
||||
expect(patch.assetClass, isNull);
|
||||
});
|
||||
|
||||
testWidgets('saving without changes closes with nothing to send', (
|
||||
tester,
|
||||
) async {
|
||||
final patch = await _open(tester, () async {
|
||||
await tester.tap(find.text('Сохранить'));
|
||||
});
|
||||
|
||||
expect(patch, isNull);
|
||||
});
|
||||
|
||||
testWidgets('a lot below 1 is refused and the dialog stays open', (
|
||||
tester,
|
||||
) async {
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
home: Builder(
|
||||
builder: (context) => Scaffold(
|
||||
body: TextButton(
|
||||
onPressed: () => showDialog<InstrumentPatch>(
|
||||
context: context,
|
||||
builder: (_) => InstrumentEditDialog(instrument: _instrument()),
|
||||
),
|
||||
child: const Text('open'),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
await tester.tap(find.text('open'));
|
||||
await tester.pumpAndSettle();
|
||||
await tester.enterText(find.widgetWithText(TextFormField, '1'), '0');
|
||||
await tester.tap(find.text('Сохранить'));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(find.text('Целое число не меньше 1'), findsOneWidget);
|
||||
expect(find.text('Сохранить'), findsOneWidget);
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user