Keep stored home API keys hidden on edit

This commit is contained in:
Artem Kokos
2026-05-16 11:22:02 +07:00
parent 83d946558b
commit 894ba91095
3 changed files with 100 additions and 27 deletions

View File

@@ -82,25 +82,25 @@ void main() {
expect(api.createdGroupMacs, ['AA:BB']);
});
testWidgets('group edit screen shows backend rescan summary', (
tester,
) async {
final api = FakeIgnisApi(
devicesData: {
'devices': [
{'mac': 'AA:BB', 'name': 'Лампа 1'},
],
},
groupsData: <Object>[],
)..rescanNetworkData = {
'status': 'ok',
'found': 3,
'added': 1,
'updated': 2,
'removed_offline': 1,
'pending_removal': 0,
'online': 3,
};
testWidgets('group edit screen shows backend rescan summary', (tester) async {
final api =
FakeIgnisApi(
devicesData: {
'devices': [
{'mac': 'AA:BB', 'name': 'Лампа 1'},
],
},
groupsData: <Object>[],
)
..rescanNetworkData = {
'status': 'ok',
'found': 3,
'added': 1,
'updated': 2,
'removed_offline': 1,
'pending_removal': 0,
'online': 3,
};
await pumpTestApp(tester, child: const GroupEditScreen(), api: api);
await tester.pumpAndSettle();
@@ -109,7 +109,9 @@ void main() {
await tester.pumpAndSettle();
expect(
find.text('Сканирование завершено: найдено 3, новых 1, обновлено 2, убрано 1'),
find.text(
'Сканирование завершено: найдено 3, новых 1, обновлено 2, убрано 1',
),
findsOneWidget,
);
expect(api.rescanCalls, 1);
@@ -228,4 +230,57 @@ void main() {
);
expect(savedApiKey, 'secret-key');
});
testWidgets('home edit screen keeps stored api key hidden on edit', (
tester,
) async {
SharedPreferences.setMockInitialValues({});
final settingsService = SettingsService(
credentialsStorage: InMemoryCredentialsStorage(),
);
final existingHome = HomeConfig(
id: 'home-1',
name: 'Квартира',
url: 'https://ignis.akokos.ru',
);
await settingsService.upsertHome(existingHome, apiKey: 'stored-secret');
final api = FakeIgnisApi(authData: {'is_admin': true, 'name': 'owner'});
await pumpTestApp(
tester,
api: api,
settingsService: settingsService,
child: HomeEditScreen(home: existingHome),
);
await tester.pumpAndSettle();
final keyField = tester.widget<EditableText>(
find.byWidgetPredicate(
(widget) => widget is EditableText && widget.obscureText,
),
);
expect(keyField.controller.text, isEmpty);
expect(
find.text('Сохранённый ключ хранится отдельно и не показывается в поле'),
findsOneWidget,
);
await tester.enterText(
find.widgetWithText(TextFormField, 'Адрес сервера'),
'ignis.example.com',
);
await tester.pump();
await tester.tap(find.widgetWithText(ElevatedButton, 'СОХРАНИТЬ'));
await tester.pumpAndSettle();
expect(api.validateCredentialsCalls, 1);
expect(api.validatedBaseUrl, 'https://ignis.example.com');
expect(api.validatedApiKey, 'stored-secret');
expect(
await settingsService.getHomeApiKey(existingHome.id),
'stored-secret',
);
});
}

View File

@@ -73,6 +73,9 @@ class FakeIgnisApi extends IgnisApi {
String? deletedGroupId;
Map<String, dynamic>? scheduledOnceParams;
Map<String, dynamic>? scheduledCronParams;
String? validatedBaseUrl;
String? validatedApiKey;
int validateCredentialsCalls = 0;
int rescanCalls = 0;
FakeIgnisApi({
@@ -99,6 +102,9 @@ class FakeIgnisApi extends IgnisApi {
@override
Future<void> validateCredentials(String baseUrl, String apiKey) async {
validateCredentialsCalls += 1;
validatedBaseUrl = baseUrl;
validatedApiKey = apiKey;
final error = authError;
if (error != null) throw error;
}