Notification parsing: - Drop the account_bindings table/DAO/repo/entity/controller/screen; account resolution now goes senderToAccount rule -> source_apps.defaultAccountId (trusted) -> global default (untrusted -> Inbox), via v1->v2 migration. - Add defaultAccountId to source_apps; per-app settings consolidated into source_app_detail_screen (/settings/parsing/apps/:pkg). - Inbox auto-learns an app default on first Confirm/CreateRule; account picker on the card instead of a disabled button; parse_error_labels extracted. Analytics: - Replace placeholder screen with fl_chart cards (chart_card, chart_theme, month_stepper, month_math domain helper); slim down habit_analysis_screen. Android: add launcher icon (adaptive foreground + colors.xml) and app_name. Tests: migration_v2, analytics (screen/month_math), AI retry, inbox visibility; update resolver/gate/inbox suites for the new resolution path. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
85 lines
2.8 KiB
Dart
85 lines
2.8 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:flutter_test/flutter_test.dart';
|
|
import 'package:google_fonts/google_fonts.dart';
|
|
import 'package:new_budget/l10n/app_localizations.dart';
|
|
import 'package:new_budget/src/app/theme/app_theme.dart';
|
|
import 'package:new_budget/src/core/database/converters/enum_converters.dart';
|
|
import 'package:new_budget/src/features/accounts/domain/entities/account.dart';
|
|
import 'package:new_budget/src/features/home/presentation/widgets/tx_row.dart';
|
|
import 'package:new_budget/src/features/transactions/domain/entities/transaction.dart';
|
|
|
|
Transaction _tx({
|
|
String? extraInfo,
|
|
SpendingObligation? obligation,
|
|
SpendingImpulse? impulse,
|
|
}) =>
|
|
Transaction(
|
|
id: 't',
|
|
userId: 'u',
|
|
accountId: 'a',
|
|
type: TransactionType.expense,
|
|
amount: 100,
|
|
// Сегодняшняя дата → подзаголовок не дёргает DateFormat с локалью.
|
|
date: DateTime.now(),
|
|
merchant: 'Кофейня',
|
|
extraInfo: extraInfo,
|
|
obligation: obligation,
|
|
impulse: impulse,
|
|
createdAt: DateTime(2026, 6, 1),
|
|
);
|
|
|
|
Widget _wrap(Transaction tx, {required bool habitTrackingEnabled}) =>
|
|
MaterialApp(
|
|
locale: const Locale('en'),
|
|
theme: AppTheme.light(),
|
|
localizationsDelegates: AppLocalizations.localizationsDelegates,
|
|
supportedLocales: AppLocalizations.supportedLocales,
|
|
home: Scaffold(
|
|
body: TxRow(
|
|
tx: tx,
|
|
category: null,
|
|
accountById: const <String, Account>{},
|
|
habitTrackingEnabled: habitTrackingEnabled,
|
|
),
|
|
),
|
|
);
|
|
|
|
void main() {
|
|
setUpAll(() {
|
|
GoogleFonts.config.allowRuntimeFetching = false;
|
|
});
|
|
|
|
testWidgets('флаг выключен → показывается extraInfo, нет ярлыков',
|
|
(tester) async {
|
|
await tester.pumpWidget(
|
|
_wrap(_tx(extraInfo: 'комментарий'), habitTrackingEnabled: false),
|
|
);
|
|
|
|
expect(find.text('комментарий'), findsOneWidget);
|
|
expect(find.text('not marked'), findsNothing);
|
|
});
|
|
|
|
testWidgets('флаг включён → extraInfo скрыт, показаны ярлыки',
|
|
(tester) async {
|
|
await tester.pumpWidget(
|
|
_wrap(
|
|
_tx(extraInfo: 'комментарий', obligation: SpendingObligation.required),
|
|
habitTrackingEnabled: true,
|
|
),
|
|
);
|
|
|
|
expect(find.text('комментарий'), findsNothing);
|
|
expect(find.text('Required'), findsOneWidget);
|
|
});
|
|
|
|
testWidgets('флаг включён, оценок нет → "not marked" вместо extraInfo',
|
|
(tester) async {
|
|
await tester.pumpWidget(
|
|
_wrap(_tx(extraInfo: 'комментарий'), habitTrackingEnabled: true),
|
|
);
|
|
|
|
expect(find.text('комментарий'), findsNothing);
|
|
expect(find.text('not marked'), findsOneWidget);
|
|
});
|
|
}
|