Extract settings and harden geofence automation

This commit is contained in:
Artem Kokos
2026-05-15 10:18:46 +07:00
parent 1963488479
commit d796537917
21 changed files with 1392 additions and 278 deletions

View File

@@ -85,6 +85,7 @@ void main() {
expect(calls.single.method, 'armGeofence');
expect(calls.single.arguments, <String, Object?>{
'homeId': 'home-1',
'homeName': 'Home 1',
'baseUrl': 'https://one.example',
'apiKey': 'secret-key',
'latitude': 55.75,

View File

@@ -0,0 +1,65 @@
import 'package:flutter_test/flutter_test.dart';
import 'package:ignis_app/features/settings/models/geofence_system_state.dart';
import 'package:ignis_app/features/settings/providers/settings_providers.dart';
import 'package:ignis_app/providers/providers.dart';
import 'package:ignis_app/services/settings_service.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'test_support.dart';
void main() {
TestWidgetsFlutterBinding.ensureInitialized();
test(
'geofence system status provider inspects current home prerequisites',
() async {
SharedPreferences.setMockInitialValues({
'ignis_homes':
'[{"id":"home-1","name":"Дом","url":"https://one.example","latitude":55.75,"longitude":37.61,"geofenceEnabled":true}]',
'ignis_current_home_id': 'home-1',
});
final settingsService = SettingsService(
credentialsStorage: InMemoryCredentialsStorage(),
);
await settingsService.setHomeApiKey('home-1', 'key-1');
final fakeService = _RecordingGeofenceSystemStatusService(
const GeofenceSystemState(GeofenceSystemIssue.ready),
);
final container = createTestContainer(
FakeIgnisApi(),
settingsService: settingsService,
extraOverrides: [
geofenceSystemStatusServiceProvider.overrideWithValue(fakeService),
],
);
await container.read(currentHomeProvider.notifier).load();
final state = await container.read(geofenceSystemStatusProvider.future);
expect(state.issue, GeofenceSystemIssue.ready);
expect(fakeService.lastHasActiveHome, isTrue);
expect(fakeService.lastHasCoordinates, isTrue);
},
);
}
class _RecordingGeofenceSystemStatusService
implements GeofenceSystemStatusService {
final GeofenceSystemState result;
_RecordingGeofenceSystemStatusService(this.result);
bool? lastHasActiveHome;
bool? lastHasCoordinates;
@override
Future<GeofenceSystemState> inspect({
required bool hasActiveHome,
required bool hasCoordinates,
}) async {
lastHasActiveHome = hasActiveHome;
lastHasCoordinates = hasCoordinates;
return result;
}
}

View File

@@ -1,6 +1,7 @@
import 'dart:convert';
import 'package:flutter_test/flutter_test.dart';
import 'package:ignis_app/features/settings/models/app_theme_preset.dart';
import 'package:ignis_app/models/home_config.dart';
import 'package:ignis_app/services/credentials_storage.dart';
import 'package:ignis_app/services/settings_service.dart';
@@ -79,4 +80,18 @@ void main() {
jsonDecode(prefs.getString('ignis_homes')!) as List<dynamic>;
expect(storedHomes.single, isNot(contains('apiKey')));
});
test('stores and restores app theme preset', () async {
SharedPreferences.setMockInitialValues({});
final service = SettingsService(
credentialsStorage: InMemoryCredentialsStorage(),
);
expect(await service.getAppThemePreset(), AppThemePreset.fallback);
await service.setAppThemePreset(AppThemePreset.graphite);
expect(await service.getAppThemePreset(), AppThemePreset.graphite);
});
}

View File

@@ -0,0 +1,34 @@
import 'package:flutter_test/flutter_test.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:ignis_app/features/settings/models/app_theme_preset.dart';
import 'package:ignis_app/features/settings/providers/settings_providers.dart';
import 'package:ignis_app/features/shared/providers/core_providers.dart';
import 'package:ignis_app/services/settings_service.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'test_support.dart';
void main() {
TestWidgetsFlutterBinding.ensureInitialized();
test('app theme notifier updates state and persists selection', () async {
SharedPreferences.setMockInitialValues({});
final settingsService = SettingsService(
credentialsStorage: InMemoryCredentialsStorage(),
);
final container = ProviderContainer(
overrides: [
settingsServiceProvider.overrideWithValue(settingsService),
initialAppThemePresetProvider.overrideWithValue(AppThemePreset.ember),
],
);
addTearDown(container.dispose);
await container
.read(appThemeProvider.notifier)
.setTheme(AppThemePreset.graphite);
expect(container.read(appThemeProvider), AppThemePreset.graphite);
expect(await settingsService.getAppThemePreset(), AppThemePreset.graphite);
});
}

View File

@@ -2,6 +2,8 @@ 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/features/settings/models/app_theme_preset.dart';
import 'package:ignis_app/features/settings/providers/settings_providers.dart';
import 'package:ignis_app/providers/providers.dart';
import 'package:ignis_app/services/api_client.dart';
import 'package:ignis_app/services/credentials_storage.dart';
@@ -336,14 +338,18 @@ ProviderContainer createTestContainer(
FakeIgnisApi api, {
SettingsService? settingsService,
bool remotePollingEnabled = true,
AppThemePreset initialThemePreset = AppThemePreset.fallback,
List extraOverrides = const [],
}) {
final overrides = [
apiProvider.overrideWithValue(api),
remotePollingEnabledProvider.overrideWithValue(remotePollingEnabled),
initialAppThemePresetProvider.overrideWithValue(initialThemePreset),
];
if (settingsService != null) {
overrides.add(settingsServiceProvider.overrideWithValue(settingsService));
}
overrides.addAll(extraOverrides.cast());
final container = ProviderContainer(overrides: overrides);
addTearDown(container.dispose);
@@ -356,11 +362,15 @@ Future<ProviderContainer> pumpTestApp(
FakeIgnisApi? api,
SettingsService? settingsService,
bool remotePollingEnabled = true,
AppThemePreset initialThemePreset = AppThemePreset.fallback,
List extraOverrides = const [],
}) async {
final container = createTestContainer(
api ?? FakeIgnisApi(),
settingsService: settingsService,
remotePollingEnabled: remotePollingEnabled,
initialThemePreset: initialThemePreset,
extraOverrides: extraOverrides,
);
await tester.pumpWidget(