Files
OnBudget/test/features/analytics/analytics_screen_test.dart
T
SandersandClaude Opus 4.8 4f99b80169 Replace account_bindings with per-app default account; build analytics charts
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>
2026-07-18 00:09:12 +03:00

104 lines
4.2 KiB
Dart

import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.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/analytics/domain/month_math.dart';
import 'package:new_budget/src/features/analytics/presentation/screens/analytics_screen.dart';
import 'package:new_budget/src/features/home/presentation/state/selected_category_filter.dart';
import 'package:new_budget/src/features/settings/application/settings_controller.dart';
import 'package:new_budget/src/features/settings/domain/entities/settings.dart';
import 'package:new_budget/src/features/user/application/active_user_controller.dart';
import 'package:new_budget/src/features/user/domain/entities/user.dart';
// ─── Fakes ───────────────────────────────────────────────────────────────────
const _userId = 'test-uid';
class FakeActiveUserController extends ActiveUserController {
@override
Future<User?> build() async =>
User(id: _userId, name: 'Test', createdAt: DateTime(2024));
}
class FakeSettingsController extends SettingsController {
FakeSettingsController({required this.habitEnabled});
final bool habitEnabled;
@override
Future<Settings> build(String userId) async => Settings(
userId: _userId,
baseCurrency: 'RUB',
themeMode: AppThemeMode.system,
locale: 'ru',
firstDayOfMonth: 1,
habitTrackingEnabled: habitEnabled,
);
}
Widget _buildScreen({required bool habitEnabled}) => ProviderScope(
overrides: [
activeUserControllerProvider
.overrideWith(() => FakeActiveUserController()),
settingsControllerProvider(_userId)
.overrideWith(() => FakeSettingsController(
habitEnabled: habitEnabled,
)),
],
child: MaterialApp(
theme: AppTheme.light(),
localizationsDelegates: AppLocalizations.localizationsDelegates,
supportedLocales: AppLocalizations.supportedLocales,
home: const AnalyticsScreen(),
),
);
ProviderContainer _container(WidgetTester tester) =>
ProviderScope.containerOf(tester.element(find.byType(AnalyticsScreen)));
// ─── Tests ───────────────────────────────────────────────────────────────────
void main() {
setUpAll(() {
GoogleFonts.config.allowRuntimeFetching = false;
});
testWidgets('хабит-карточка видна при включённом трекинге', (tester) async {
await tester.pumpWidget(_buildScreen(habitEnabled: true));
await tester.pump(); // future-провайдеры разрешаются
await tester.pump();
expect(find.text('Habit analysis'), findsOneWidget);
});
testWidgets('хабит-карточка скрыта при выключенном трекинге',
(tester) async {
await tester.pumpWidget(_buildScreen(habitEnabled: false));
await tester.pump();
await tester.pump();
expect(find.text('Habit analysis'), findsNothing);
});
testWidgets('шаг месяца в AppBar двигает общий selectedMonthProvider',
(tester) async {
await tester.pumpWidget(_buildScreen(habitEnabled: false));
await tester.pump();
await tester.pump();
final container = _container(tester);
final initial = container.read(selectedMonthProvider);
await tester.tap(find.byIcon(Icons.chevron_left));
await tester.pump();
expect(container.read(selectedMonthProvider), previousMonth(initial));
// На прошлом месяце появляется шаг вперёд — возвращаемся.
await tester.tap(find.byIcon(Icons.chevron_right));
await tester.pump();
expect(container.read(selectedMonthProvider), initial);
});
}