Adding a baseline of integration tests for our otp app, however with some fixes needed:

1. I haven't figured out how right clicking works in integration tests
	2. How to disting slot 1 and slot 2 logic is not done.
Otherwise these tests should just work.
This commit is contained in:
Joakim Troëng 2024-02-06 10:42:14 +01:00
parent b04720c0f9
commit ea3b684b99
6 changed files with 147 additions and 0 deletions

View File

@ -18,6 +18,7 @@
import 'package:flutter_test/flutter_test.dart';
import 'package:integration_test/integration_test.dart';
import 'package:yubico_authenticator/app/views/keys.dart';
import 'package:yubico_authenticator/otp/keys.dart';
import 'utils/test_util.dart';
@ -29,6 +30,135 @@ void main() {
appTest('OTP menu items exist', (WidgetTester tester) async {
await tester.tap(find.byKey(otpAppDrawer));
await tester.shortWait();
await tester.tap(find.byKey(configureYubiOtp).hitTestable());
await tester.shortWait();
});
appTest('Yubico OTP slot 1', (WidgetTester tester) async {
await tester.tap(find.byKey(otpAppDrawer).hitTestable());
await tester.shortWait();
//verify "Slot 1 is empty"
// we are missing the right click on top of the correct slot
await tester.tap(find.byKey(configureYubiOtp).hitTestable());
await tester.shortWait();
// this generates all the fields and saves yubiotp
await tester.tap(find.byKey(useSerial).hitTestable());
await tester.shortWait();
await tester.tap(find.byKey(generatePrivateId).hitTestable());
await tester.shortWait();
await tester.tap(find.byKey(generateSecretKey).hitTestable());
await tester.shortWait();
await tester.tap(find.byKey(saveButton).hitTestable());
await tester.shortWait();
//verify "Slot 1 is configured"
});
appTest('Challenge-Response slot 1', (WidgetTester tester) async {
await tester.tap(find.byKey(otpAppDrawer).hitTestable());
await tester.shortWait();
// verify "Slot 1 is configured"
// we are missing the right click on top of the correct slot
await tester.tap(find.byKey(configureChalResp).hitTestable());
await tester.shortWait();
// this generates and saves chall-resp
await tester.tap(find.byKey(generateSecretKey).hitTestable());
await tester.shortWait();
await tester.tap(find.byKey(saveButton).hitTestable());
await tester.shortWait();
// verify "Slot 1 is configured"
});
appTest('Static Password slot 2', (WidgetTester tester) async {
await tester.tap(find.byKey(otpAppDrawer).hitTestable());
await tester.shortWait();
// verify "Slot 2 is empty"
// we are missing the right click on top of the correct slot
await tester.tap(find.byKey(configureYubiOtp).hitTestable());
await tester.shortWait();
// this generates and saves static password
await tester.tap(find.byKey(generateSecretKey).hitTestable());
await tester.shortWait();
await tester.tap(find.byKey(saveButton).hitTestable());
await tester.shortWait();
// verify "Slot 2 is configured"
});
appTest('OATH-HOTP slot 2', (WidgetTester tester) async {
await tester.tap(find.byKey(otpAppDrawer).hitTestable());
await tester.shortWait();
// verify "Slot 2 is configured"
// we are missing the right click on top of the correct slot
await tester.tap(find.byKey(configureYubiOtp).hitTestable());
await tester.shortWait();
// this writes and saves oath secret
await tester.enterText(find.byKey(secretField), "asdfasdf");
await tester.shortWait();
await tester.tap(find.byKey(saveButton).hitTestable());
await tester.shortWait();
// verify "Slot 2 is configured"
});
appTest('Swap slots', (WidgetTester tester) async {
await tester.tap(find.byKey(otpAppDrawer).hitTestable());
await tester.shortWait();
// verify "Slot 1 is configured"
// verify "Slot 2 is configured"
// taps swap
await tester.tap(find.byKey(actionsIconButtonKey).hitTestable());
await tester.shortWait();
await tester.tap(find.byKey(swapSlots).hitTestable());
await tester.shortWait();
await tester.tap(find.byKey(swap).hitTestable());
await tester.shortWait();
// verify "Slot 1 is configured"
// verify "Slot 2 is configured"
});
appTest('Delete Credentials', (WidgetTester tester) async {
await tester.tap(find.byKey(otpAppDrawer).hitTestable());
await tester.shortWait();
// verify "Slot 1 is configured"
// verify "Slot 2 is configured"
// we need to right click on slot 1
await tester.tap(find.byKey(deleteAction).hitTestable());
await tester.shortWait();
await tester.tap(find.byKey(deleteButton).hitTestable());
await tester.shortWait();
// we need to right click on slot 2
await tester.tap(find.byKey(deleteAction).hitTestable());
await tester.shortWait();
await tester.tap(find.byKey(deleteButton).hitTestable());
await tester.shortWait();
// verify "Slot 1 is empty"
// verify "Slot 2 is empty"
});
});
}

View File

@ -20,6 +20,8 @@ const _prefix = 'otp.keys';
const _keyAction = '$_prefix.actions';
const _slotAction = '$_prefix.slot.actions';
/// const getOtpSlotKey = '$_prefix.pick_otp_slot';
// Key actions
const swapSlots = Key('$_keyAction.swap_slots');
@ -32,7 +34,12 @@ const deleteAction = Key('$_slotAction.delete');
const saveButton = Key('$_prefix.save');
const deleteButton = Key('$_prefix.delete');
const swap = Key('$_prefix.swap');
const secretField = Key('$_prefix.secret');
const publicIdField = Key('$_prefix.public_id');
const privateIdField = Key('$_prefix.private_id');
const useSerial = Key('$_prefix.use_serial');
const generatePrivateId = Key('$_prefix.generate_private_id');
const generateSecretKey = Key('$_prefix.generate_secret_key');

View File

@ -31,6 +31,7 @@ import '../../widgets/app_input_decoration.dart';
import '../../widgets/app_text_field.dart';
import '../../widgets/responsive_dialog.dart';
import '../keys.dart' as keys;
import '../keys.dart';
import '../models.dart';
import '../state.dart';
import 'overwrite_confirm_dialog.dart';
@ -141,6 +142,7 @@ class _ConfigureChalrespDialogState
: null,
prefixIcon: const Icon(Icons.key_outlined),
suffixIcon: IconButton(
key: generateSecretKey,
icon: const Icon(Icons.refresh),
onPressed: () {
setState(() {

View File

@ -29,6 +29,7 @@ import '../../widgets/app_text_field.dart';
import '../../widgets/choice_filter_chip.dart';
import '../../widgets/responsive_dialog.dart';
import '../keys.dart' as keys;
import '../keys.dart';
import '../models.dart';
import '../state.dart';
import 'overwrite_confirm_dialog.dart';
@ -160,6 +161,7 @@ class _ConfigureStaticDialogState extends ConsumerState<ConfigureStaticDialog> {
: null,
prefixIcon: const Icon(Icons.key_outlined),
suffixIcon: IconButton(
key: generateSecretKey,
tooltip: l10n.s_generate_random,
icon: const Icon(Icons.refresh),
onPressed: () async {

View File

@ -34,6 +34,7 @@ import '../../widgets/app_text_field.dart';
import '../../widgets/choice_filter_chip.dart';
import '../../widgets/responsive_dialog.dart';
import '../keys.dart' as keys;
import '../keys.dart';
import '../models.dart';
import '../state.dart';
import 'overwrite_confirm_dialog.dart';
@ -215,6 +216,7 @@ class _ConfigureYubiOtpDialogState
: null,
prefixIcon: const Icon(Icons.public_outlined),
suffixIcon: IconButton(
key: useSerial,
tooltip: l10n.s_use_serial,
icon: const Icon(Icons.auto_awesome_outlined),
onPressed: (info?.serial != null)
@ -250,6 +252,7 @@ class _ConfigureYubiOtpDialogState
: null,
prefixIcon: const Icon(Icons.key_outlined),
suffixIcon: IconButton(
key: generatePrivateId,
tooltip: l10n.s_generate_random,
icon: const Icon(Icons.refresh),
onPressed: () {
@ -286,6 +289,7 @@ class _ConfigureYubiOtpDialogState
: null,
prefixIcon: const Icon(Icons.key_outlined),
suffixIcon: IconButton(
key: generateSecretKey,
tooltip: l10n.s_generate_random,
icon: const Icon(Icons.refresh),
onPressed: () {

View File

@ -22,6 +22,7 @@ import '../../app/message.dart';
import '../../app/models.dart';
import '../../app/state.dart';
import '../../widgets/responsive_dialog.dart';
import '../keys.dart';
import '../state.dart';
class SwapSlotsDialog extends ConsumerWidget {
@ -35,6 +36,7 @@ class SwapSlotsDialog extends ConsumerWidget {
title: Text(l10n.s_swap_slots),
actions: [
TextButton(
key: swap,
onPressed: () async {
await ref.read(otpStateProvider(devicePath).notifier).swapSlots();
await ref.read(withContextProvider)((context) async {