Files
OnBudget/test/app/router/inbox_tab_test.dart
T
SandersandClaude Opus 4.8 fdc5c14852 Move Inbox to a dedicated bottom-nav tab gated by parsing toggle
Replace the Inbox badge button in MonthHeader with a bottom-nav tab
(hidden when notification parsing is disabled). Redirect /inbox → /home
when parsing is off, register the Inbox shell branch unconditionally,
and add a settings action to the Inbox screen. Move the parsing tile to
the top of the profile screen so settings stay reachable when the tab
is hidden. Add tests for the nav tab visibility and inbox routing, plus
a release-install PowerShell helper that preserves app data.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-19 16:45:21 +03:00

110 lines
4.4 KiB
Dart

import 'package:drift/native.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:intl/date_symbol_data_local.dart';
import 'package:new_budget/src/app/app.dart';
import 'package:new_budget/src/app/router/app_router.dart';
import 'package:new_budget/src/app/router/app_routes.dart';
import 'package:new_budget/src/core/database/app_database.dart';
import 'package:new_budget/src/core/providers/database_provider.dart';
import 'package:new_budget/src/features/notification_parsing/application/notification_ingest_worker.dart';
import 'package:new_budget/src/features/notification_parsing/application/parsing_settings_controller.dart';
import 'package:new_budget/src/features/notification_parsing/application/parsing_worker.dart';
import 'package:new_budget/src/features/notification_parsing/presentation/screens/inbox_screen.dart';
// Воркеры парсинга — no-op: реальные подписываются на connectivity_plus и
// нативный notification-listener канал, которых под `flutter test` нет.
class _FakeParsingWorker extends ParsingWorker {
@override
void build(String userId) {}
}
class _FakeIngestWorker extends NotificationIngestWorker {
@override
void build(String userId) {}
}
void main() {
setUpAll(() {
GoogleFonts.config.allowRuntimeFetching = false;
});
testWidgets(
'вкладка Inbox видна только при включённом парсинге, /inbox редиректит',
(tester) async {
await initializeDateFormatting('ru');
final db = AppDatabase.forTesting(NativeDatabase.memory());
addTearDown(db.close);
// Реальная in-memory БД: активный пользователь + выключенный парсинг.
await db.usersDao
.insertUser(UsersTableCompanion.insert(id: 'u1', name: 'Тест'));
await db.settingsDao.setPreference('active_user_id', 'u1');
await db.settingsDao.setPreference('parsing_enabled', 'false');
final container = ProviderContainer(
overrides: [
appDatabaseProvider.overrideWithValue(db),
parsingWorkerProvider.overrideWith2((_) => _FakeParsingWorker()),
notificationIngestWorkerProvider
.overrideWith2((_) => _FakeIngestWorker()),
],
);
addTearDown(container.dispose);
await tester.pumpWidget(
UncontrolledProviderScope(
container: container,
child: const NewBudgetApp(),
),
);
// Пара кадров: активный пользователь и настройки парсинга грузятся из БД.
await tester.pump();
await tester.pump();
await tester.pump();
// ignore: avoid_print
for (final t in tester.allWidgets.whereType<Text>()) {
// ignore: avoid_print
print('TEXT: ${t.data}');
}
// Парсинг выключен → вкладки Inbox нет, остальные на месте.
expect(find.text('Inbox'), findsNothing);
expect(find.text('Home'), findsOneWidget);
// Deep-link на /inbox при выключенном парсинге уводит на /home.
final router = container.read(appRouterProvider);
router.go(AppRoutes.inbox);
await tester.pump();
await tester.pump();
expect(router.state.matchedLocation, AppRoutes.home);
expect(find.byType(InboxScreen), findsNothing);
// Включаем парсинг — вкладка появляется без пересоздания роутера.
await container
.read(parsingSettingsControllerProvider.notifier)
.setEnabled(true);
await tester.pump();
expect(find.text('Inbox'), findsOneWidget);
// Теперь /inbox доступен.
await tester.tap(find.text('Inbox'));
await tester.pump();
await tester.pump();
expect(router.state.matchedLocation, AppRoutes.inbox);
expect(find.byType(InboxScreen), findsOneWidget);
// Выключаем парсинг, находясь НА вкладке Inbox: redirect возвращает
// на /home (refreshListenable дёргается слушателем настроек).
await container
.read(parsingSettingsControllerProvider.notifier)
.setEnabled(false);
await tester.pump();
await tester.pump();
expect(router.state.matchedLocation, AppRoutes.home);
expect(find.text('Inbox'), findsNothing);
});
}