mirror of
https://github.com/Yubico/yubioath-flutter.git
synced 2024-11-22 00:12:09 +03:00
Refactor Key usage in tests.
This commit is contained in:
parent
edfa0402c9
commit
f198b47bbf
@ -1,6 +1,7 @@
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:integration_test/integration_test.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
import 'package:yubico_authenticator/android/keys.dart' as keys;
|
||||
|
||||
import '../test_util.dart';
|
||||
import 'constants.dart';
|
||||
@ -21,18 +22,18 @@ void main() {
|
||||
await tester.startUp({
|
||||
'dlg.beta.enabled': true,
|
||||
});
|
||||
expect(find.byKey(betaDialogKey), findsOneWidget);
|
||||
expect(find.byKey(keys.betaDialogView), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets('does not show welcome dialog', (WidgetTester tester) async {
|
||||
await tester.startUp();
|
||||
expect(find.byKey(betaDialogKey), findsNothing);
|
||||
expect(find.byKey(keys.betaDialogView), findsNothing);
|
||||
});
|
||||
|
||||
testWidgets('updates preferences', (WidgetTester tester) async {
|
||||
await tester.startUp({'dlg.beta.enabled': true});
|
||||
var prefs = await SharedPreferences.getInstance();
|
||||
await tester.tap(find.byKey(gotItBtn));
|
||||
await tester.tap(find.byKey(keys.okButton));
|
||||
await expectLater(prefs.getBool(betaDialogPrefName), equals(false));
|
||||
});
|
||||
});
|
||||
|
@ -1,19 +1,3 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
// widget key names
|
||||
const betaDialogKey = Key('android.beta.dialog');
|
||||
const gotItBtn = Key('android.beta.dialog.btn.got_it');
|
||||
|
||||
const settingsOnNfcTapOptionKey = Key('android.settings.option.on_nfc_tap');
|
||||
const settingsOnNfcTapLaunch = Key('android.settings.on_nfc_tap.launch');
|
||||
const settingsOnNfcTapCopy = Key('android.settings.on_nfc_tap.copy');
|
||||
const settingsOnNfcTapBoth = Key('android.settings.on_nfc_tap.both');
|
||||
const settingsKeyboardLayoutOptionKey = Key('android.settings.option.keyboard_layout');
|
||||
const settingsKeyboardLayoutUS = Key('android.settings.keyboard_layout.US');
|
||||
const settingsKeyboardLayoutDE = Key('android.settings.keyboard_layout.DE');
|
||||
const settingsKeyboardLayoutDECH = Key('android.settings.keyboard_layout.DE-CH');
|
||||
const settingsBypassTouchKey = Key('android.settings.bypass_touch');
|
||||
|
||||
// shared preferences keys
|
||||
const betaDialogPrefName = 'prefBetaDialogShouldBeShown';
|
||||
const prefNfcOpenApp = 'prefNfcOpenApp';
|
||||
|
@ -1,6 +1,7 @@
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:integration_test/integration_test.dart';
|
||||
import 'package:yubico_authenticator/core/state.dart';
|
||||
import 'package:yubico_authenticator/oath/keys.dart' as keys;
|
||||
|
||||
import 'oath_test_util.dart';
|
||||
import 'test_util.dart';
|
||||
@ -27,9 +28,9 @@ void main() {
|
||||
testWidgets('Menu items exist', (WidgetTester tester) async {
|
||||
await tester.startUp(startupParams);
|
||||
await tester.tapDeviceButton();
|
||||
expect(find.byKey(deviceMenuAddAccountKey), findsOneWidget);
|
||||
expect(find.byKey(deviceMenuSetManagePasswordKey), findsOneWidget);
|
||||
expect(find.byKey(deviceMenuResetOathKey), findsOneWidget);
|
||||
expect(find.byKey(keys.addAccountAction), findsOneWidget);
|
||||
expect(find.byKey(keys.setOrManagePasswordAction), findsOneWidget);
|
||||
expect(find.byKey(keys.resetAction), findsOneWidget);
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -1,34 +1,13 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:yubico_authenticator/android/keys.dart' as android_keys;
|
||||
import 'package:yubico_authenticator/core/state.dart';
|
||||
import 'package:yubico_authenticator/oath/keys.dart' as keys;
|
||||
import 'package:yubico_authenticator/oath/views/account_list.dart';
|
||||
import 'package:yubico_authenticator/oath/views/account_view.dart';
|
||||
|
||||
import 'test_util.dart';
|
||||
|
||||
/// when connecting YubiKey with OATH password
|
||||
const passwordValidateEditKey = Key('oath password');
|
||||
const unlockOathBtnKey = Key('oath unlock');
|
||||
|
||||
/// when setting or changing existing YubiKey OATH password
|
||||
const newOathPasswordEntryKey = Key('new oath password');
|
||||
const currentOathPasswordEntryKey = Key('current oath password');
|
||||
const confirmOathPasswordEditKey = Key('confirm oath password');
|
||||
const oathPasswordSaveBntKey = Key('save oath password changes');
|
||||
const oathPasswordRemoveBntKey = Key('remove oath password btn');
|
||||
|
||||
const qrScannerEnterManuallyKey = Key('android.qr_scanner.btn.enter_manually');
|
||||
const deleteAccountBtnKey = Key('oath.dlg.delete_account.btn.delete');
|
||||
const renameAccountBtnSaveKey = Key('oath.dlg.rename_account.btn.save');
|
||||
const renameAccountEditIssuerKey = Key('oath.dlg.rename_account.edit.issuer');
|
||||
const renameAccountEditNameKey = Key('oath.dlg.rename_account.edit.name');
|
||||
|
||||
const deviceMenuAddAccountKey = Key('add oath account');
|
||||
const deviceMenuSetManagePasswordKey = Key('set or manage oath password');
|
||||
const deviceMenuResetOathKey = Key('reset oath app');
|
||||
|
||||
const noAccountsMessagePage = Key('oath.message_page.no_accounts');
|
||||
|
||||
class Account {
|
||||
final String? issuer;
|
||||
final String name;
|
||||
@ -48,14 +27,14 @@ extension OathFunctions on WidgetTester {
|
||||
/// Opens the device menu and taps the "Add account" menu item
|
||||
Future<void> tapAddAccount() async {
|
||||
await tapDeviceButton();
|
||||
await tap(find.byKey(deviceMenuAddAccountKey).hitTestable());
|
||||
await tap(find.byKey(keys.addAccountAction).hitTestable());
|
||||
await longWait();
|
||||
}
|
||||
|
||||
/// Opens the device menu and taps the "Set/Manage password" menu item
|
||||
Future<void> tapSetOrManagePassword() async {
|
||||
await tapDeviceButton();
|
||||
await tap(find.byKey(deviceMenuSetManagePasswordKey));
|
||||
await tap(find.byKey(keys.setOrManagePasswordAction));
|
||||
await longWait();
|
||||
}
|
||||
|
||||
@ -71,31 +50,33 @@ extension OathFunctions on WidgetTester {
|
||||
if (isAndroid) {
|
||||
/// on android a QR Scanner starts
|
||||
/// we want to do a manual addition
|
||||
var manualEntryBtn = find.byKey(qrScannerEnterManuallyKey).hitTestable();
|
||||
var manualEntryBtn =
|
||||
find.byKey(android_keys.manualEntryButton).hitTestable();
|
||||
if (manualEntryBtn.evaluate().isEmpty) {
|
||||
printToConsole('Allow camera permission');
|
||||
await pump(const Duration(seconds: 2));
|
||||
manualEntryBtn = find.byKey(qrScannerEnterManuallyKey).hitTestable();
|
||||
manualEntryBtn =
|
||||
find.byKey(android_keys.manualEntryButton).hitTestable();
|
||||
}
|
||||
|
||||
await tap(manualEntryBtn);
|
||||
await longWait();
|
||||
}
|
||||
|
||||
var issuerText = find.byKey(const Key('issuer')).hitTestable();
|
||||
var issuerText = find.byKey(keys.issuerField).hitTestable();
|
||||
await tap(issuerText);
|
||||
await enterText(issuerText, a.issuer ?? '');
|
||||
await shortWait();
|
||||
var nameText = find.byKey(const Key('name')).hitTestable();
|
||||
var nameText = find.byKey(keys.nameField).hitTestable();
|
||||
await tap(nameText);
|
||||
await enterText(nameText, a.name);
|
||||
await shortWait();
|
||||
var secretText = find.byKey(const Key('secret')).hitTestable();
|
||||
var secretText = find.byKey(keys.secretField).hitTestable();
|
||||
await tap(secretText);
|
||||
await enterText(secretText, a.secret);
|
||||
await shortWait();
|
||||
|
||||
await tap(find.byKey(const Key('save_btn')));
|
||||
await tap(find.byKey(keys.saveButton));
|
||||
|
||||
await longWait();
|
||||
|
||||
@ -118,7 +99,7 @@ extension OathFunctions on WidgetTester {
|
||||
}
|
||||
|
||||
Future<AccountView?> findAccount(Account a, {bool quiet = true}) async {
|
||||
if (find.byKey(noAccountsMessagePage).hitTestable().evaluate().isNotEmpty) {
|
||||
if (find.byKey(keys.noAccountsView).hitTestable().evaluate().isNotEmpty) {
|
||||
/// if there is no OATH account on the YubiKey, the app shows
|
||||
/// No accounts [MessagePage]
|
||||
return null;
|
||||
@ -179,7 +160,7 @@ extension OathFunctions on WidgetTester {
|
||||
await longWait();
|
||||
|
||||
/// TODO check dialog shows correct information about account
|
||||
var deleteButton = find.byKey(deleteAccountBtnKey).hitTestable();
|
||||
var deleteButton = find.byKey(keys.deleteButton).hitTestable();
|
||||
expect(deleteButton, findsOneWidget);
|
||||
await tap(deleteButton);
|
||||
await longWait();
|
||||
@ -221,15 +202,15 @@ extension OathFunctions on WidgetTester {
|
||||
await longWait();
|
||||
|
||||
/// fill new info
|
||||
var issuerTextField = find.byKey(renameAccountEditIssuerKey).hitTestable();
|
||||
var issuerTextField = find.byKey(keys.issuerField).hitTestable();
|
||||
await tap(issuerTextField);
|
||||
await enterText(issuerTextField, newIssuer ?? '');
|
||||
var nameTextField = find.byKey(renameAccountEditNameKey).hitTestable();
|
||||
var nameTextField = find.byKey(keys.nameField).hitTestable();
|
||||
await tap(nameTextField);
|
||||
await enterText(nameTextField, newName);
|
||||
await shortestWait();
|
||||
|
||||
var saveButton = find.byKey(renameAccountBtnSaveKey).hitTestable();
|
||||
var saveButton = find.byKey(keys.saveButton).hitTestable();
|
||||
expect(saveButton, findsOneWidget);
|
||||
await tap(saveButton);
|
||||
await longWait();
|
||||
@ -258,20 +239,20 @@ extension OathFunctions on WidgetTester {
|
||||
|
||||
await longWait();
|
||||
|
||||
var newPasswordEntry = find.byKey(newOathPasswordEntryKey);
|
||||
var newPasswordEntry = find.byKey(keys.newPasswordField);
|
||||
await tap(newPasswordEntry);
|
||||
await enterText(newPasswordEntry, newPassword);
|
||||
await shortWait();
|
||||
var confirmPasswordEntry = find.byKey(confirmOathPasswordEditKey);
|
||||
var confirmPasswordEntry = find.byKey(keys.confirmPasswordField);
|
||||
await tap(confirmPasswordEntry);
|
||||
await enterText(confirmPasswordEntry, newPassword);
|
||||
await shortWait();
|
||||
|
||||
await tap(find.byKey(oathPasswordSaveBntKey));
|
||||
await tap(find.byKey(keys.savePasswordButton));
|
||||
await longWait();
|
||||
|
||||
/// after tapping Save, the dialog is closed and the save button does not exist
|
||||
expect(find.byKey(oathPasswordSaveBntKey).hitTestable(), findsNothing);
|
||||
expect(find.byKey(keys.savePasswordButton).hitTestable(), findsNothing);
|
||||
}
|
||||
|
||||
Future<void> replaceOathPassword(
|
||||
@ -280,35 +261,35 @@ extension OathFunctions on WidgetTester {
|
||||
|
||||
await shortWait();
|
||||
|
||||
var currentPasswordEntry = find.byKey(currentOathPasswordEntryKey);
|
||||
var currentPasswordEntry = find.byKey(keys.currentPasswordField);
|
||||
await tap(currentPasswordEntry);
|
||||
await enterText(currentPasswordEntry, currentPassword);
|
||||
await shortWait();
|
||||
var newPasswordEntry = find.byKey(newOathPasswordEntryKey);
|
||||
var newPasswordEntry = find.byKey(keys.newPasswordField);
|
||||
await tap(newPasswordEntry);
|
||||
await enterText(newPasswordEntry, newPassword);
|
||||
await shortWait();
|
||||
var confirmPasswordEntry = find.byKey(confirmOathPasswordEditKey);
|
||||
var confirmPasswordEntry = find.byKey(keys.confirmPasswordField);
|
||||
await tap(confirmPasswordEntry);
|
||||
await enterText(confirmPasswordEntry, newPassword);
|
||||
await shortWait();
|
||||
|
||||
await tap(find.byKey(oathPasswordSaveBntKey));
|
||||
await tap(find.byKey(keys.savePasswordButton));
|
||||
await longWait();
|
||||
|
||||
expect(find.byKey(oathPasswordSaveBntKey).hitTestable(), findsNothing);
|
||||
expect(find.byKey(keys.savePasswordButton).hitTestable(), findsNothing);
|
||||
}
|
||||
|
||||
Future<void> unlockOathSession(String newPassword) async {
|
||||
var validatePasswordEntry = find.byKey(passwordValidateEditKey);
|
||||
var validatePasswordEntry = find.byKey(keys.passwordField);
|
||||
await tap(validatePasswordEntry);
|
||||
await enterText(validatePasswordEntry, newPassword);
|
||||
await shortWait();
|
||||
var unlockButton = find.byKey(unlockOathBtnKey);
|
||||
var unlockButton = find.byKey(keys.unlockButton);
|
||||
await tap(unlockButton);
|
||||
await longWait();
|
||||
|
||||
expect(find.byKey(unlockOathBtnKey).hitTestable(), findsNothing);
|
||||
expect(find.byKey(keys.unlockButton).hitTestable(), findsNothing);
|
||||
}
|
||||
|
||||
Future<void> removeOathPassword(String currentPassword) async {
|
||||
@ -316,13 +297,13 @@ extension OathFunctions on WidgetTester {
|
||||
|
||||
await longWait();
|
||||
|
||||
var currentPasswordEntry = find.byKey(currentOathPasswordEntryKey);
|
||||
var currentPasswordEntry = find.byKey(keys.currentPasswordField);
|
||||
await tap(currentPasswordEntry);
|
||||
await enterText(currentPasswordEntry, currentPassword);
|
||||
await shortWait();
|
||||
await tap(find.byKey(oathPasswordRemoveBntKey));
|
||||
await tap(find.byKey(keys.removePasswordButton));
|
||||
await longWait();
|
||||
|
||||
expect(find.byKey(oathPasswordRemoveBntKey).hitTestable(), findsNothing);
|
||||
expect(find.byKey(keys.removePasswordButton).hitTestable(), findsNothing);
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../keys.dart' as keys;
|
||||
import 'qr_scanner_scan_status.dart';
|
||||
import 'qr_scanner_util.dart';
|
||||
|
||||
@ -52,7 +53,7 @@ class QRScannerUI extends StatelessWidget {
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
key: const Key('android.qr_scanner.btn.enter_manually'),
|
||||
key: keys.manualEntryButton,
|
||||
child: const Text('Enter manually',
|
||||
style: TextStyle(color: Colors.white))),
|
||||
],
|
||||
|
@ -6,6 +6,7 @@ import '../../app/state.dart';
|
||||
import '../../core/state.dart';
|
||||
import '../../widgets/list_title.dart';
|
||||
import '../../widgets/responsive_dialog.dart';
|
||||
import '../keys.dart' as keys;
|
||||
|
||||
const String _prefNfcOpenApp = 'prefNfcOpenApp';
|
||||
const String _prefNfcBypassTouch = 'prefNfcBypassTouch';
|
||||
@ -35,11 +36,11 @@ enum _TapAction {
|
||||
Key get key {
|
||||
switch (this) {
|
||||
case _TapAction.launch:
|
||||
return const Key('android.settings.on_nfc_tap.launch');
|
||||
return keys.launchTapAction;
|
||||
case _TapAction.copy:
|
||||
return const Key('android.settings.on_nfc_tap.copy');
|
||||
return keys.copyTapAction;
|
||||
case _TapAction.both:
|
||||
return const Key('android.settings.on_nfc_tap.both');
|
||||
return keys.bothTapAction;
|
||||
}
|
||||
}
|
||||
|
||||
@ -114,7 +115,7 @@ class _AndroidSettingsPageState extends ConsumerState<AndroidSettingsPage> {
|
||||
ListTile(
|
||||
title: const Text('On YubiKey NFC tap'),
|
||||
subtitle: Text(tapAction.description),
|
||||
key: const Key('android.settings.option.on_nfc_tap'),
|
||||
key: keys.nfcTapSetting,
|
||||
onTap: () async {
|
||||
final newTapAction = await _selectTapAction(context, tapAction);
|
||||
newTapAction.save(prefs);
|
||||
@ -124,7 +125,7 @@ class _AndroidSettingsPageState extends ConsumerState<AndroidSettingsPage> {
|
||||
ListTile(
|
||||
title: const Text('Keyboard Layout (for static password)'),
|
||||
subtitle: Text(clipKbdLayout),
|
||||
key: const Key('android.settings.option.keyboard_layout'),
|
||||
key: keys.nfcKeyboardLayoutSetting,
|
||||
enabled: tapAction != _TapAction.launch,
|
||||
onTap: () async {
|
||||
var newValue = await _selectKbdLayout(context, clipKbdLayout);
|
||||
@ -142,7 +143,7 @@ class _AndroidSettingsPageState extends ConsumerState<AndroidSettingsPage> {
|
||||
: const Text(
|
||||
'Accounts that require touch need an additional tap over NFC.'),
|
||||
value: nfcBypassTouch,
|
||||
key: const Key('android.settings.bypass_touch'),
|
||||
key: keys.nfcBypassTouchSetting,
|
||||
onChanged: (value) {
|
||||
prefs.setBool(_prefNfcBypassTouch, value);
|
||||
setState(() {});
|
||||
@ -198,7 +199,7 @@ class _AndroidSettingsPageState extends ConsumerState<AndroidSettingsPage> {
|
||||
(e) => RadioListTile<String>(
|
||||
title: Text(e),
|
||||
value: e,
|
||||
key: Key('android.settings.keyboard_layout.$e'),
|
||||
key: keys.keyboardLayoutOption(e),
|
||||
toggleable: true,
|
||||
groupValue: currentKbdLayout,
|
||||
onChanged: (mode) {
|
||||
|
@ -3,6 +3,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
|
||||
import '../../app/message.dart';
|
||||
import '../../core/state.dart';
|
||||
import '../keys.dart' as keys;
|
||||
|
||||
class BetaDialog {
|
||||
final BuildContext context;
|
||||
@ -32,7 +33,7 @@ class BetaDialog {
|
||||
return WillPopScope(
|
||||
onWillPop: () async => false,
|
||||
child: AlertDialog(
|
||||
key: const Key('android.beta.dialog'),
|
||||
key: keys.betaDialogView,
|
||||
content: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
@ -77,7 +78,7 @@ class BetaDialog {
|
||||
// },
|
||||
// ),
|
||||
TextButton(
|
||||
key: const Key('android.beta.dialog.btn.got_it'),
|
||||
key: keys.okButton,
|
||||
style: TextButton.styleFrom(
|
||||
textStyle: Theme.of(context)
|
||||
.textTheme
|
||||
|
@ -17,6 +17,7 @@ import '../../widgets/choice_filter_chip.dart';
|
||||
import '../../widgets/file_drop_target.dart';
|
||||
import '../../widgets/responsive_dialog.dart';
|
||||
import '../../widgets/utf8_utils.dart';
|
||||
import '../keys.dart' as keys;
|
||||
import '../models.dart';
|
||||
import '../state.dart';
|
||||
import 'utils.dart';
|
||||
@ -230,7 +231,7 @@ class _OathAddAccountPageState extends ConsumerState<OathAddAccountPage> {
|
||||
TextButton(
|
||||
onPressed: isValid ? submit : null,
|
||||
child: Text(AppLocalizations.of(context)!.oath_save,
|
||||
key: const Key('save_btn')),
|
||||
key: keys.saveButton),
|
||||
),
|
||||
],
|
||||
child: FileDropTarget(
|
||||
@ -254,7 +255,7 @@ class _OathAddAccountPageState extends ConsumerState<OathAddAccountPage> {
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
TextField(
|
||||
key: const Key('issuer'),
|
||||
key: keys.issuerField,
|
||||
controller: _issuerController,
|
||||
autofocus: !widget.openQrScanner,
|
||||
enabled: issuerRemaining > 0,
|
||||
@ -279,7 +280,7 @@ class _OathAddAccountPageState extends ConsumerState<OathAddAccountPage> {
|
||||
},
|
||||
),
|
||||
TextField(
|
||||
key: const Key('name'),
|
||||
key: keys.nameField,
|
||||
controller: _accountController,
|
||||
maxLength: max(nameRemaining, 1),
|
||||
buildCounter:
|
||||
@ -305,7 +306,7 @@ class _OathAddAccountPageState extends ConsumerState<OathAddAccountPage> {
|
||||
},
|
||||
),
|
||||
TextField(
|
||||
key: const Key('secret'),
|
||||
key: keys.secretField,
|
||||
controller: _secretController,
|
||||
obscureText: _isObscure,
|
||||
inputFormatters: <TextInputFormatter>[
|
||||
|
@ -9,6 +9,7 @@ import '../../app/state.dart';
|
||||
import '../../widgets/responsive_dialog.dart';
|
||||
import '../models.dart';
|
||||
import '../state.dart';
|
||||
import '../keys.dart' as keys;
|
||||
|
||||
class DeleteAccountDialog extends ConsumerWidget {
|
||||
final DeviceNode device;
|
||||
@ -25,7 +26,7 @@ class DeleteAccountDialog extends ConsumerWidget {
|
||||
title: Text(AppLocalizations.of(context)!.oath_delete_account),
|
||||
actions: [
|
||||
TextButton(
|
||||
key: const Key('oath.dlg.delete_account.btn.delete'),
|
||||
key: keys.deleteButton,
|
||||
onPressed: () async {
|
||||
try {
|
||||
await ref
|
||||
|
@ -7,6 +7,7 @@ import '../../app/models.dart';
|
||||
import '../../widgets/responsive_dialog.dart';
|
||||
import '../models.dart';
|
||||
import '../state.dart';
|
||||
import '../keys.dart' as keys;
|
||||
|
||||
class ManagePasswordDialog extends ConsumerStatefulWidget {
|
||||
final DevicePath path;
|
||||
@ -50,7 +51,7 @@ class _ManagePasswordDialogState extends ConsumerState<ManagePasswordDialog> {
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: isValid ? _submit : null,
|
||||
key: const Key('save oath password changes'),
|
||||
key: keys.savePasswordButton,
|
||||
child: Text(AppLocalizations.of(context)!.oath_save),
|
||||
)
|
||||
],
|
||||
@ -64,7 +65,7 @@ class _ManagePasswordDialogState extends ConsumerState<ManagePasswordDialog> {
|
||||
TextField(
|
||||
autofocus: true,
|
||||
obscureText: true,
|
||||
key: const Key('current oath password'),
|
||||
key: keys.currentPasswordField,
|
||||
decoration: InputDecoration(
|
||||
border: const OutlineInputBorder(),
|
||||
labelText:
|
||||
@ -87,7 +88,7 @@ class _ManagePasswordDialogState extends ConsumerState<ManagePasswordDialog> {
|
||||
runSpacing: 8.0,
|
||||
children: [
|
||||
OutlinedButton(
|
||||
key: const Key('remove oath password btn'),
|
||||
key: keys.removePasswordButton,
|
||||
onPressed: _currentPassword.isNotEmpty
|
||||
? () async {
|
||||
final result = await ref
|
||||
@ -131,7 +132,7 @@ class _ManagePasswordDialogState extends ConsumerState<ManagePasswordDialog> {
|
||||
],
|
||||
Text(AppLocalizations.of(context)!.oath_enter_new_password),
|
||||
TextField(
|
||||
key: const Key('new oath password'),
|
||||
key: keys.newPasswordField,
|
||||
autofocus: !widget.state.hasKey,
|
||||
obscureText: true,
|
||||
decoration: InputDecoration(
|
||||
@ -153,7 +154,7 @@ class _ManagePasswordDialogState extends ConsumerState<ManagePasswordDialog> {
|
||||
},
|
||||
),
|
||||
TextField(
|
||||
key: const Key('confirm oath password'),
|
||||
key: keys.confirmPasswordField,
|
||||
obscureText: true,
|
||||
decoration: InputDecoration(
|
||||
border: const OutlineInputBorder(),
|
||||
|
@ -14,6 +14,7 @@ import '../../app/views/app_page.dart';
|
||||
import '../../app/views/graphics.dart';
|
||||
import '../../app/views/message_page.dart';
|
||||
import '../../widgets/menu_list_tile.dart';
|
||||
import '../keys.dart' as keys;
|
||||
import '../models.dart';
|
||||
import '../state.dart';
|
||||
import 'account_list.dart';
|
||||
@ -55,7 +56,8 @@ class _LockedView extends ConsumerWidget {
|
||||
title: Text(AppLocalizations.of(context)!.oath_authenticator),
|
||||
keyActions: [
|
||||
buildMenuItem(
|
||||
title: Text(AppLocalizations.of(context)!.oath_manage_password),
|
||||
title: Text(AppLocalizations.of(context)!.oath_manage_password,
|
||||
key: keys.setOrManagePasswordAction),
|
||||
leading: const Icon(Icons.password),
|
||||
action: () {
|
||||
showBlurDialog(
|
||||
@ -121,7 +123,7 @@ class _UnlockedViewState extends ConsumerState<_UnlockedView> {
|
||||
if (credentials?.isEmpty == true) {
|
||||
return MessagePage(
|
||||
title: Text(AppLocalizations.of(context)!.oath_authenticator),
|
||||
key: const Key('oath.message_page.no_accounts'),
|
||||
key: keys.noAccountsView,
|
||||
graphic: noAccounts,
|
||||
header: AppLocalizations.of(context)!.oath_no_accounts,
|
||||
keyActions: _buildActions(
|
||||
@ -152,7 +154,7 @@ class _UnlockedViewState extends ConsumerState<_UnlockedView> {
|
||||
child: Builder(builder: (context) {
|
||||
final textTheme = Theme.of(context).textTheme;
|
||||
return TextFormField(
|
||||
key: const Key('search_accounts'),
|
||||
key: keys.searchAccountsField,
|
||||
controller: searchController,
|
||||
focusNode: searchFocus,
|
||||
// Use the default style, but with a smaller font size:
|
||||
@ -195,8 +197,10 @@ class _UnlockedViewState extends ConsumerState<_UnlockedView> {
|
||||
final capacity = widget.oathState.version.isAtLeast(4) ? 32 : null;
|
||||
return [
|
||||
buildMenuItem(
|
||||
title: Text(AppLocalizations.of(context)!.oath_add_account,
|
||||
key: const Key('add oath account'),),
|
||||
title: Text(
|
||||
AppLocalizations.of(context)!.oath_add_account,
|
||||
key: keys.addAccountAction,
|
||||
),
|
||||
leading: const Icon(Icons.person_add_alt_1),
|
||||
trailing: capacity != null ? '$used/$capacity' : null,
|
||||
action: capacity == null || capacity > used
|
||||
@ -214,9 +218,11 @@ class _UnlockedViewState extends ConsumerState<_UnlockedView> {
|
||||
: null,
|
||||
),
|
||||
buildMenuItem(
|
||||
title: Text(widget.oathState.hasKey
|
||||
? AppLocalizations.of(context)!.oath_manage_password
|
||||
: AppLocalizations.of(context)!.oath_set_password, key: const Key('set or manage oath password')),
|
||||
title: Text(
|
||||
widget.oathState.hasKey
|
||||
? AppLocalizations.of(context)!.oath_manage_password
|
||||
: AppLocalizations.of(context)!.oath_set_password,
|
||||
key: keys.setOrManagePasswordAction),
|
||||
leading: const Icon(Icons.password),
|
||||
action: () {
|
||||
showBlurDialog(
|
||||
@ -226,7 +232,8 @@ class _UnlockedViewState extends ConsumerState<_UnlockedView> {
|
||||
);
|
||||
}),
|
||||
buildMenuItem(
|
||||
title: Text(AppLocalizations.of(context)!.oath_reset_oath, key: const Key('reset oath app')),
|
||||
title: Text(AppLocalizations.of(context)!.oath_reset_oath,
|
||||
key: keys.resetAction),
|
||||
leading: const Icon(Icons.delete),
|
||||
action: () {
|
||||
showBlurDialog(
|
||||
@ -287,7 +294,7 @@ class _UnlockFormState extends ConsumerState<_UnlockForm> {
|
||||
),
|
||||
const SizedBox(height: 16.0),
|
||||
TextField(
|
||||
key: const Key('oath password'),
|
||||
key: keys.passwordField,
|
||||
controller: _passwordController,
|
||||
autofocus: true,
|
||||
obscureText: _isObscure,
|
||||
@ -345,7 +352,7 @@ class _UnlockFormState extends ConsumerState<_UnlockForm> {
|
||||
child: Align(
|
||||
alignment: Alignment.centerRight,
|
||||
child: ElevatedButton.icon(
|
||||
key: const Key('oath unlock'),
|
||||
key: keys.unlockButton,
|
||||
label: Text(AppLocalizations.of(context)!.oath_unlock),
|
||||
icon: const Icon(Icons.lock_open),
|
||||
onPressed: _passwordController.text.isNotEmpty ? _submit : null,
|
||||
|
@ -12,6 +12,7 @@ import '../../widgets/responsive_dialog.dart';
|
||||
import '../../widgets/utf8_utils.dart';
|
||||
import '../models.dart';
|
||||
import '../state.dart';
|
||||
import '../keys.dart' as keys;
|
||||
import 'utils.dart';
|
||||
|
||||
final _log = Logger('oath.view.rename_account_dialog');
|
||||
@ -116,7 +117,7 @@ class _RenameAccountDialogState extends ConsumerState<RenameAccountDialog> {
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: didChange && isValid ? _submit : null,
|
||||
key: const Key('oath.dlg.rename_account.btn.save'),
|
||||
key: keys.saveButton,
|
||||
child: Text(AppLocalizations.of(context)!.oath_save),
|
||||
),
|
||||
],
|
||||
@ -134,7 +135,7 @@ class _RenameAccountDialogState extends ConsumerState<RenameAccountDialog> {
|
||||
maxLength: issuerRemaining > 0 ? issuerRemaining : null,
|
||||
buildCounter: buildByteCounterFor(_issuer),
|
||||
inputFormatters: [limitBytesLength(issuerRemaining)],
|
||||
key: const Key('oath.dlg.rename_account.edit.issuer'),
|
||||
key: keys.issuerField,
|
||||
decoration: InputDecoration(
|
||||
border: const OutlineInputBorder(),
|
||||
labelText: AppLocalizations.of(context)!.oath_issuer_optional,
|
||||
@ -153,7 +154,7 @@ class _RenameAccountDialogState extends ConsumerState<RenameAccountDialog> {
|
||||
maxLength: nameRemaining,
|
||||
inputFormatters: [limitBytesLength(nameRemaining)],
|
||||
buildCounter: buildByteCounterFor(_account),
|
||||
key: const Key('oath.dlg.rename_account.edit.name'),
|
||||
key: keys.nameField,
|
||||
decoration: InputDecoration(
|
||||
border: const OutlineInputBorder(),
|
||||
labelText: AppLocalizations.of(context)!.oath_account_name,
|
||||
|
@ -4,6 +4,7 @@ import 'package:flutter_localizations/flutter_localizations.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
import 'package:yubico_authenticator/android/keys.dart' as keys;
|
||||
import 'package:yubico_authenticator/android/views/android_settings_page.dart';
|
||||
import 'package:yubico_authenticator/core/state.dart';
|
||||
|
||||
@ -26,7 +27,7 @@ Widget createMaterialApp({required Widget child}) {
|
||||
|
||||
extension _WidgetTesterHelper on WidgetTester {
|
||||
Future<void> openNfcTapOptionSelection() async {
|
||||
var widget = find.byKey(settingsOnNfcTapOptionKey).hitTestable();
|
||||
var widget = find.byKey(keys.nfcTapSetting).hitTestable();
|
||||
expect(widget, findsOneWidget);
|
||||
await tap(widget);
|
||||
await pumpAndSettle();
|
||||
@ -34,28 +35,28 @@ extension _WidgetTesterHelper on WidgetTester {
|
||||
|
||||
Future<void> selectLaunchOption() async {
|
||||
await openNfcTapOptionSelection();
|
||||
await tap(find.byKey(settingsOnNfcTapLaunch));
|
||||
await tap(find.byKey(keys.launchTapAction));
|
||||
await pumpAndSettle();
|
||||
}
|
||||
|
||||
Future<void> selectCopyOption() async {
|
||||
await openNfcTapOptionSelection();
|
||||
await tap(find.byKey(settingsOnNfcTapCopy));
|
||||
await tap(find.byKey(keys.copyTapAction));
|
||||
await pumpAndSettle();
|
||||
}
|
||||
|
||||
Future<void> selectBothOption() async {
|
||||
await openNfcTapOptionSelection();
|
||||
await tap(find.byKey(settingsOnNfcTapBoth));
|
||||
await tap(find.byKey(keys.bothTapAction));
|
||||
await pumpAndSettle();
|
||||
}
|
||||
|
||||
ListTile keyboardLayoutListTile() =>
|
||||
find.byKey(settingsKeyboardLayoutOptionKey).evaluate().single.widget
|
||||
find.byKey(keys.nfcKeyboardLayoutSetting).evaluate().single.widget
|
||||
as ListTile;
|
||||
|
||||
Future<void> openKeyboardLayoutOptionSelection() async {
|
||||
var widget = find.byKey(settingsKeyboardLayoutOptionKey).hitTestable();
|
||||
var widget = find.byKey(keys.nfcKeyboardLayoutSetting).hitTestable();
|
||||
expect(widget, findsOneWidget);
|
||||
await tap(widget);
|
||||
await pumpAndSettle();
|
||||
@ -63,31 +64,29 @@ extension _WidgetTesterHelper on WidgetTester {
|
||||
|
||||
Future<void> selectKeyboardLayoutUSOption() async {
|
||||
await openKeyboardLayoutOptionSelection();
|
||||
await tap(find.byKey(settingsKeyboardLayoutUS));
|
||||
await tap(find.byKey(keys.keyboardLayoutOption('US')));
|
||||
await pumpAndSettle();
|
||||
}
|
||||
|
||||
Future<void> selectKeyboardLayoutDEOption() async {
|
||||
await openKeyboardLayoutOptionSelection();
|
||||
await tap(find.byKey(settingsKeyboardLayoutDE));
|
||||
await tap(find.byKey(keys.keyboardLayoutOption('DE')));
|
||||
await pumpAndSettle();
|
||||
}
|
||||
|
||||
Future<void> selectKeyboardLayoutDECHOption() async {
|
||||
await openKeyboardLayoutOptionSelection();
|
||||
await tap(find.byKey(settingsKeyboardLayoutDECH));
|
||||
await tap(find.byKey(keys.keyboardLayoutOption('DE-CH')));
|
||||
await pumpAndSettle();
|
||||
}
|
||||
|
||||
Future<void> tapBypassTouch() async {
|
||||
await tap(find.byKey(settingsBypassTouchKey));
|
||||
await tap(find.byKey(keys.nfcBypassTouchSetting));
|
||||
await pumpAndSettle();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void main() {
|
||||
|
||||
var widget = createMaterialApp(child: const AndroidSettingsPage());
|
||||
|
||||
testWidgets('NFC Tap options', (WidgetTester tester) async {
|
||||
|
Loading…
Reference in New Issue
Block a user