Files
ignis_app/test/remote_and_group_widget_test.dart

216 lines
6.3 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:ignis_app/models/ignis_group.dart';
import 'package:ignis_app/providers/providers.dart';
import 'package:ignis_app/screens/remote_screen.dart';
import 'package:ignis_app/services/settings_service.dart';
import 'package:ignis_app/widgets/group_card.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'test_support.dart';
void main() {
TestWidgetsFlutterBinding.ensureInitialized();
testWidgets('remote screen shows api keys menu for admin only', (
tester,
) async {
final adminApi = FakeIgnisApi(
authData: {'is_admin': true, 'name': 'owner'},
groupsData: <Object>[],
);
final adminContainer = await _pumpRemoteScreen(
tester,
api: adminApi,
settingsService: await _seedSettingsService(),
);
await adminContainer.read(authInfoProvider.notifier).load();
await tester.pump();
await tester.tap(find.byIcon(Icons.more_vert));
await tester.pumpAndSettle();
expect(find.text('API-ключи'), findsOneWidget);
await tester.tapAt(const Offset(10, 10));
await tester.pumpAndSettle();
final guestApi = FakeIgnisApi(
authData: {'is_admin': false, 'name': 'guest'},
groupsData: <Object>[],
);
final guestContainer = await _pumpRemoteScreen(
tester,
api: guestApi,
settingsService: await _seedSettingsService(),
);
await guestContainer.read(authInfoProvider.notifier).load();
await tester.pump();
await tester.tap(find.byIcon(Icons.more_vert));
await tester.pumpAndSettle();
expect(find.text('API-ключи'), findsNothing);
});
testWidgets('remote screen deletes group after confirmation', (tester) async {
final api = FakeIgnisApi(
authData: {'is_admin': true, 'name': 'owner'},
groupsData: {
'kitchen': {
'name': 'Kitchen',
'macs': ['AA:BB'],
},
},
);
final container = await _pumpRemoteScreen(
tester,
api: api,
settingsService: await _seedSettingsService(),
);
await container.read(groupsProvider.notifier).refresh();
await tester.pump(const Duration(milliseconds: 300));
expect(find.text('Kitchen'), findsOneWidget);
await tester.drag(find.text('Kitchen'), const Offset(-500, 0));
await tester.pumpAndSettle();
expect(find.text('Удалить группу?'), findsOneWidget);
await tester.tap(find.text('Удалить'));
await tester.pumpAndSettle();
expect(api.deletedGroupId, 'kitchen');
expect(find.text('Kitchen'), findsNothing);
});
testWidgets('group card toggles power and creates 4 hour timer', (
tester,
) async {
final api = FakeIgnisApi(tasksData: {'tasks': <Object>[]});
await pumpTestApp(
tester,
api: api,
child: Scaffold(
body: GroupCard(
group: const IgnisGroup(
id: 'hall',
name: 'Hall',
state: IgnisGroupState(isOn: true, brightness: 50),
),
),
),
);
await tester.tap(find.byIcon(Icons.timer));
await tester.pumpAndSettle();
expect(api.controlledGroupId, 'hall');
expect(api.controlGroupParams, containsPair('state', true));
expect(api.scheduledOnceParams, containsPair('target_id', 'hall'));
expect(api.scheduledOnceParams, containsPair('hours_from_now', 4));
await tester.tap(find.byType(Switch));
await tester.pumpAndSettle();
expect(api.controlGroupParams, containsPair('state', false));
});
testWidgets('group card loads scenes and applies selected scene', (
tester,
) async {
final api = FakeIgnisApi(scenesData: {'party': 'Party'});
await pumpTestApp(
tester,
api: api,
child: Scaffold(
body: GroupCard(
group: const IgnisGroup(
id: 'hall',
name: 'Hall',
state: IgnisGroupState(isOn: true),
),
),
),
);
await tester.tap(find.text('Сцена'));
await tester.pump();
await tester.pump(const Duration(milliseconds: 100));
expect(find.text('Party'), findsOneWidget);
await tester.tap(find.text('Party'));
await tester.pumpAndSettle();
expect(api.controlledGroupId, 'hall');
expect(api.controlGroupParams, containsPair('scene', 'party'));
});
testWidgets('group card shows retry when scenes fail to load', (
tester,
) async {
final api = FakeIgnisApi(scenesData: {'party': 'Party'});
api.scenesError = DioException(
requestOptions: RequestOptions(path: '/devices/scenes'),
type: DioExceptionType.connectionError,
message: 'No route to host',
);
await pumpTestApp(
tester,
api: api,
child: Scaffold(
body: GroupCard(
group: const IgnisGroup(
id: 'hall',
name: 'Hall',
state: IgnisGroupState(isOn: true),
),
),
),
);
await tester.tap(find.text('Сцена'));
await tester.pump();
await tester.pump(const Duration(milliseconds: 100));
expect(find.text('Не удалось загрузить сцены'), findsOneWidget);
api.scenesError = null;
await tester.tap(find.text('Повторить'));
await tester.pumpAndSettle();
expect(find.text('Party'), findsOneWidget);
});
}
Future<ProviderContainer> _pumpRemoteScreen(
WidgetTester tester, {
required FakeIgnisApi api,
required SettingsService settingsService,
}) async {
final container = createTestContainer(api, settingsService: settingsService);
await container.read(currentHomeProvider.notifier).load();
await tester.pumpWidget(
UncontrolledProviderScope(
container: container,
child: const MaterialApp(home: RemoteScreen()),
),
);
await tester.pump();
await tester.pump(const Duration(milliseconds: 100));
return container;
}
Future<SettingsService> _seedSettingsService() async {
SharedPreferences.setMockInitialValues({
'ignis_homes':
'[{"id":"home-1","name":"Home 1","url":"https://one.example","geofenceEnabled":false}]',
'ignis_current_home_id': 'home-1',
});
final settingsService = SettingsService(
credentialsStorage: InMemoryCredentialsStorage(),
);
await settingsService.setHomeApiKey('home-1', 'key-1');
return settingsService;
}