140 lines
4.9 KiB
Dart
140 lines
4.9 KiB
Dart
import 'package:flutter/cupertino.dart';
|
|
import 'package:flutter_test/flutter_test.dart';
|
|
import 'package:please_pay_me/app/app.dart';
|
|
import 'package:please_pay_me/core/config/app_config.dart';
|
|
import 'package:please_pay_me/core/storage/session_storage.dart';
|
|
import 'package:please_pay_me/data/demo/demo_backend.dart';
|
|
import 'package:please_pay_me/features/auth/session_controller.dart';
|
|
import 'package:please_pay_me/theme/theme.dart';
|
|
|
|
import 'support/test_setup.dart';
|
|
|
|
void main() {
|
|
setUpAll(setUpTestEnvironment);
|
|
|
|
SessionController demoSession({bool seeded = true}) {
|
|
return SessionController(
|
|
config: AppConfig.demo,
|
|
storage: InMemorySessionStorage(),
|
|
demoBackend: seeded ? DemoBackend() : DemoBackend.empty(),
|
|
);
|
|
}
|
|
|
|
/// Skeletons pulse forever, so `pumpAndSettle` would time out.
|
|
Future<void> settle(WidgetTester tester) async {
|
|
await tester.pump();
|
|
await tester.pump(const Duration(milliseconds: 400));
|
|
}
|
|
|
|
testWidgets('restoring session shows the branded splash', (tester) async {
|
|
final session = demoSession();
|
|
|
|
await tester.pumpWidget(PleasePayMeApp(session: session));
|
|
await tester.pump();
|
|
|
|
expect(find.text('Дожить до ЗП'), findsOneWidget);
|
|
expect(find.text('Бюджет от зарплаты до зарплаты'), findsOneWidget);
|
|
expect(find.byType(CupertinoActivityIndicator), findsOneWidget);
|
|
});
|
|
|
|
testWidgets('signed-out app shows the login screen', (tester) async {
|
|
final session = demoSession();
|
|
await session.restore();
|
|
|
|
await tester.pumpWidget(PleasePayMeApp(session: session));
|
|
await settle(tester);
|
|
|
|
expect(find.text('Дожить до ЗП'), findsOneWidget);
|
|
expect(find.text('Войти через Яндекс'), findsOneWidget);
|
|
});
|
|
|
|
testWidgets('demo session opens the overview with the current envelope',
|
|
(tester) async {
|
|
final session = demoSession()..startDemo();
|
|
|
|
await tester.pumpWidget(PleasePayMeApp(session: session));
|
|
await settle(tester);
|
|
|
|
expect(find.text('Обзор'), findsWidgets);
|
|
expect(find.text('До аванса'), findsOneWidget);
|
|
expect(find.text('Остаток бюджета'), findsOneWidget);
|
|
|
|
await tester.drag(find.byType(CustomScrollView).first, const Offset(0, -500));
|
|
await settle(tester);
|
|
|
|
// Grouped headers are uppercased by `AppSectionHeader`, as in iOS Settings.
|
|
expect(find.text('БЛИЖАЙШАЯ ВЫПЛАТА'), findsOneWidget);
|
|
expect(tester.takeException(), isNull);
|
|
});
|
|
|
|
testWidgets('tabs switch between the main sections', (tester) async {
|
|
final session = demoSession()..startDemo();
|
|
|
|
await tester.pumpWidget(PleasePayMeApp(session: session));
|
|
await settle(tester);
|
|
|
|
for (final tab in ['Журнал', 'Бюджеты', 'Работа', 'Профиль']) {
|
|
await tester.tap(find.text(tab).last);
|
|
await settle(tester);
|
|
expect(tester.takeException(), isNull, reason: 'tab $tab failed to render');
|
|
}
|
|
|
|
expect(find.text('Демо'), findsOneWidget);
|
|
});
|
|
|
|
testWidgets('profile theme switcher applies dark appearance', (tester) async {
|
|
final session = demoSession()..startDemo();
|
|
final theme = ThemeController(store: MemoryThemeStore());
|
|
|
|
await tester.pumpWidget(PleasePayMeApp(session: session, theme: theme));
|
|
await settle(tester);
|
|
|
|
await tester.tap(find.text('Профиль').last);
|
|
await settle(tester);
|
|
|
|
expect(find.text('Системная'), findsOneWidget);
|
|
expect(find.text('Светлая'), findsOneWidget);
|
|
|
|
await tester.tap(find.text('Тёмная'));
|
|
await settle(tester);
|
|
|
|
expect(theme.preference, ThemePreference.dark);
|
|
expect(theme.resolve(Brightness.light), Brightness.dark);
|
|
});
|
|
|
|
testWidgets('empty demo backend renders the empty states', (tester) async {
|
|
final session = demoSession(seeded: false)..startDemo();
|
|
|
|
await tester.pumpWidget(PleasePayMeApp(session: session));
|
|
await settle(tester);
|
|
|
|
expect(find.text('Бюджета пока нет'), findsOneWidget);
|
|
expect(find.text('Создать бюджет'), findsOneWidget);
|
|
});
|
|
|
|
testWidgets('recording an expense updates the remaining amount', (tester) async {
|
|
final session = demoSession()..startDemo();
|
|
|
|
await tester.pumpWidget(PleasePayMeApp(session: session));
|
|
await settle(tester);
|
|
|
|
await tester.tap(find.text('Добавить трату'));
|
|
await settle(tester);
|
|
expect(find.text('Новая трата'), findsOneWidget);
|
|
|
|
await tester.enterText(find.byType(CupertinoTextField).first, '1000');
|
|
await settle(tester);
|
|
|
|
await tester.tap(find.text('Записать трату'));
|
|
await tester.pump();
|
|
await tester.pump(const Duration(milliseconds: 500));
|
|
|
|
expect(find.text('Новая трата'), findsNothing);
|
|
expect(find.text('Трата записана'), findsOneWidget);
|
|
|
|
// Let the toast auto-dismiss so no timers outlive the test.
|
|
await tester.pump(const Duration(seconds: 3));
|
|
expect(tester.takeException(), isNull);
|
|
});
|
|
}
|