Refactor Key usage in tests.

This commit is contained in:
Dain Nilsson 2022-09-12 12:58:17 +02:00
parent edfa0402c9
commit f198b47bbf
No known key found for this signature in database
GPG Key ID: F04367096FBA95E8
13 changed files with 99 additions and 119 deletions

View File

@ -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));
});
});

View File

@ -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';

View File

@ -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);
});
});

View File

@ -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);
}
}

View File

@ -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))),
],

View File

@ -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) {

View File

@ -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

View File

@ -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>[

View File

@ -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

View File

@ -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(),

View File

@ -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,

View File

@ -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,

View File

@ -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 {