test: expand client-side coverage and fix lifecycle issues

This commit is contained in:
Artem Kokos
2026-05-01 10:12:33 +07:00
parent 2fa89f6be0
commit 8f0753c1e2
10 changed files with 1116 additions and 43 deletions

View File

@@ -0,0 +1,154 @@
import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:ignis_app/screens/api_keys_screen.dart';
import 'package:ignis_app/screens/group_edit_screen.dart';
import 'package:ignis_app/screens/home_edit_screen.dart';
import 'package:ignis_app/screens/schedules_screen.dart';
import 'package:ignis_app/services/settings_service.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'test_support.dart';
void main() {
TestWidgetsFlutterBinding.ensureInitialized();
testWidgets('schedules screen retries after initial load error', (
tester,
) async {
final api = FakeIgnisApi();
api.tasksError = DioException(
requestOptions: RequestOptions(path: '/schedules/tasks'),
type: DioExceptionType.connectionError,
message: 'No route to host',
);
await pumpTestApp(tester, child: const SchedulesScreen(), api: api);
await tester.pumpAndSettle();
expect(find.text('Не удалось загрузить расписания'), findsOneWidget);
api.tasksError = null;
api.tasksData = {
'tasks': [
{
'id': 'job-1',
'target_id': 'kitchen',
'state': false,
'hour': '7',
'minute': '30',
'day_of_week': '1,2,3',
'type': 'cron',
},
],
};
await tester.tap(find.text('Повторить'));
await tester.pumpAndSettle();
expect(find.text('Выключить группу kitchen'), findsOneWidget);
});
testWidgets('api keys screen retries after initial load error', (
tester,
) async {
final api = FakeIgnisApi();
api.apiKeysError = DioException(
requestOptions: RequestOptions(path: '/api-keys'),
type: DioExceptionType.connectionError,
message: 'No route to host',
);
await pumpTestApp(tester, child: const ApiKeysScreen(), api: api);
await tester.pumpAndSettle();
expect(find.text('Не удалось загрузить API-ключи'), findsOneWidget);
api.apiKeysError = null;
api.apiKeysData = {
'keys': [
{'name': 'Guest', 'key': 'secret', 'is_active': true},
],
};
await tester.tap(find.text('Повторить'));
await tester.pumpAndSettle();
expect(find.text('Guest'), findsOneWidget);
});
testWidgets('group edit screen shows snackbar when rescan fails', (
tester,
) async {
final api = FakeIgnisApi(devicesData: {'devices': <Object>[]});
api.rescanNetworkError = DioException(
requestOptions: RequestOptions(path: '/devices/rescan'),
type: DioExceptionType.connectionError,
message: 'No route to host',
);
await pumpTestApp(tester, child: const GroupEditScreen(), api: api);
await tester.pumpAndSettle();
await tester.tap(find.byTooltip('Пересканировать сеть'));
await tester.pumpAndSettle();
expect(find.textContaining('Ошибка сканирования'), findsOneWidget);
});
testWidgets('home edit screen shows save error when credentials fail', (
tester,
) async {
SharedPreferences.setMockInitialValues({});
final settingsService = SettingsService(
credentialsStorage: InMemoryCredentialsStorage(),
);
final api = FakeIgnisApi();
api.authError = DioException(
requestOptions: RequestOptions(path: '/auth/me'),
type: DioExceptionType.badResponse,
response: Response(
requestOptions: RequestOptions(path: '/auth/me'),
statusCode: 403,
),
);
await pumpTestApp(
tester,
api: api,
settingsService: settingsService,
child: Builder(
builder: (context) => Scaffold(
body: Center(
child: ElevatedButton(
onPressed: () => Navigator.of(
context,
).push(MaterialPageRoute(builder: (_) => const HomeEditScreen())),
child: const Text('open'),
),
),
),
),
);
await tester.tap(find.text('open'));
await tester.pumpAndSettle();
await tester.enterText(
find.widgetWithText(TextFormField, 'Название'),
'Дом',
);
await tester.enterText(
find.widgetWithText(TextFormField, 'Адрес сервера'),
'ignis.akokos.ru',
);
await tester.enterText(
find.widgetWithText(TextFormField, 'API Key'),
'wrong-key',
);
final saveButton = find.widgetWithText(ElevatedButton, 'ДОБАВИТЬ');
await tester.ensureVisible(saveButton);
await tester.tap(saveButton);
await tester.pumpAndSettle();
expect(find.textContaining('Не удалось сохранить дом'), findsOneWidget);
expect(await settingsService.getHomes(), isEmpty);
});
}