mirror of
https://github.com/Yubico/yubioath-flutter.git
synced 2024-11-25 05:52:40 +03:00
update OTP integration tests
This commit is contained in:
parent
b49ac0bb4e
commit
4f186bb2fc
@ -2,16 +2,33 @@
|
||||
tags:
|
||||
# Tests which we want to run on desktop
|
||||
desktop:
|
||||
timeout: none
|
||||
|
||||
# Tests which we want to run on Android
|
||||
android:
|
||||
timeout: none
|
||||
|
||||
# Tests consuming quiet a lot of time
|
||||
slow:
|
||||
timeout: none
|
||||
|
||||
# Minimal tests
|
||||
# quick verification that the framework is working
|
||||
minimal:
|
||||
timeout: none
|
||||
|
||||
# OATH tests
|
||||
oath:
|
||||
timeout: none
|
||||
|
||||
# OTP tests
|
||||
otp:
|
||||
timeout: none
|
||||
|
||||
# PIV tests
|
||||
piv:
|
||||
timeout: none
|
||||
|
||||
# Management tests
|
||||
management:
|
||||
timeout: none
|
@ -14,6 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
@Tags(['desktop', 'management'])
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:integration_test/integration_test.dart';
|
||||
|
@ -14,12 +14,14 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
@Tags(['android', 'desktop', 'oath'])
|
||||
@Tags(['desktop', 'otp'])
|
||||
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 'package:yubico_authenticator/otp/models.dart';
|
||||
|
||||
import 'utils/otp_test_util.dart';
|
||||
import 'utils/test_util.dart';
|
||||
|
||||
void main() {
|
||||
@ -27,21 +29,12 @@ void main() {
|
||||
binding.framePolicy = LiveTestWidgetsFlutterBindingFramePolicy.fullyLive;
|
||||
|
||||
group('OTP UI tests', () {
|
||||
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.openSlotMenu(SlotId.one);
|
||||
|
||||
await tester.tap(find.byKey(configureYubiOtp).hitTestable());
|
||||
await tester.shortWait();
|
||||
@ -65,7 +58,7 @@ void main() {
|
||||
|
||||
// verify "Slot 1 is configured"
|
||||
|
||||
// we are missing the right click on top of the correct slot
|
||||
await tester.openSlotMenu(SlotId.one);
|
||||
|
||||
await tester.tap(find.byKey(configureChalResp).hitTestable());
|
||||
await tester.shortWait();
|
||||
@ -85,9 +78,9 @@ void main() {
|
||||
|
||||
// verify "Slot 2 is empty"
|
||||
|
||||
// we are missing the right click on top of the correct slot
|
||||
await tester.openSlotMenu(SlotId.two);
|
||||
|
||||
await tester.tap(find.byKey(configureYubiOtp).hitTestable());
|
||||
await tester.tap(find.byKey(configureStatic).hitTestable());
|
||||
await tester.shortWait();
|
||||
|
||||
// this generates and saves static password
|
||||
@ -105,9 +98,9 @@ void main() {
|
||||
|
||||
// verify "Slot 2 is configured"
|
||||
|
||||
// we are missing the right click on top of the correct slot
|
||||
await tester.openSlotMenu(SlotId.two);
|
||||
|
||||
await tester.tap(find.byKey(configureYubiOtp).hitTestable());
|
||||
await tester.tap(find.byKey(configureHotp).hitTestable());
|
||||
await tester.shortWait();
|
||||
|
||||
// this writes and saves oath secret
|
||||
@ -127,17 +120,14 @@ void main() {
|
||||
// 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.tapSwapSlotsButton();
|
||||
await tester.tap(find.byKey(swapButton).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();
|
||||
@ -145,15 +135,24 @@ void main() {
|
||||
// verify "Slot 1 is configured"
|
||||
// verify "Slot 2 is configured"
|
||||
|
||||
// we need to right click on slot 1
|
||||
await tester.openSlotMenu(SlotId.one);
|
||||
await tester.tap(find.byKey(deleteAction).hitTestable());
|
||||
await tester.shortWait();
|
||||
await tester.longWait();
|
||||
await tester.tap(find.byKey(deleteButton).hitTestable());
|
||||
await tester.shortWait();
|
||||
|
||||
// wait for any toasts to be gone
|
||||
await tester.pump(const Duration(seconds: 3));
|
||||
var closeFinder = find.byKey(closeButton);
|
||||
if (closeFinder.evaluate().isNotEmpty) {
|
||||
// close the view
|
||||
await tester.tap(closeFinder);
|
||||
await tester.shortWait();
|
||||
}
|
||||
|
||||
// we need to right click on slot 2
|
||||
await tester.openSlotMenu(SlotId.two);
|
||||
await tester.tap(find.byKey(deleteAction).hitTestable());
|
||||
await tester.shortWait();
|
||||
await tester.longWait();
|
||||
await tester.tap(find.byKey(deleteButton).hitTestable());
|
||||
await tester.shortWait();
|
||||
|
||||
|
@ -14,6 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
@Tags(['desktop', 'piv'])
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:integration_test/integration_test.dart';
|
||||
|
49
integration_test/utils/otp_test_util.dart
Normal file
49
integration_test/utils/otp_test_util.dart
Normal file
@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright (C) 2024 Yubico.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:yubico_authenticator/app/views/keys.dart';
|
||||
import 'package:yubico_authenticator/otp/keys.dart';
|
||||
import 'package:yubico_authenticator/otp/models.dart';
|
||||
|
||||
import 'test_util.dart';
|
||||
|
||||
extension OathFunctions on WidgetTester {
|
||||
/// Opens the menu of specific OTP Slot, either by tapping the button or
|
||||
/// by tapping the list item
|
||||
Future<void> openSlotMenu(SlotId slotId) async {
|
||||
final menuButtonFinder = find.byKey(getOpenMenuButtonKey(slotId));
|
||||
if (menuButtonFinder.evaluate().isNotEmpty) {
|
||||
await tap(menuButtonFinder);
|
||||
} else {
|
||||
await tap(find.byKey(getAppListItemKey(slotId)));
|
||||
}
|
||||
await longWait();
|
||||
}
|
||||
|
||||
/// tap the Swap Slots button - either first open the action menu,
|
||||
/// or try to find the button on visible screen
|
||||
Future<void> tapSwapSlotsButton() async {
|
||||
final actionButtonFinder = find.byKey(actionsIconButtonKey);
|
||||
if (actionButtonFinder.evaluate().isNotEmpty) {
|
||||
await tap(actionButtonFinder);
|
||||
await shortWait();
|
||||
}
|
||||
|
||||
await tap(find.byKey(swapSlots).hitTestable());
|
||||
await longWait();
|
||||
}
|
||||
}
|
@ -16,6 +16,8 @@
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'models.dart';
|
||||
|
||||
const _prefix = 'otp.keys';
|
||||
const _keyAction = '$_prefix.actions';
|
||||
const _slotAction = '$_prefix.slot.actions';
|
||||
@ -34,7 +36,7 @@ const deleteAction = Key('$_slotAction.delete');
|
||||
|
||||
const saveButton = Key('$_prefix.save');
|
||||
const deleteButton = Key('$_prefix.delete');
|
||||
const swap = Key('$_prefix.swap');
|
||||
const swapButton = Key('$_prefix.swap');
|
||||
|
||||
const secretField = Key('$_prefix.secret');
|
||||
const publicIdField = Key('$_prefix.public_id');
|
||||
@ -42,4 +44,10 @@ 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');
|
||||
const generateSecretKey = Key('$_prefix.generate_secret_key');
|
||||
|
||||
Key getOpenMenuButtonKey(SlotId slotId) =>
|
||||
Key('$_prefix.open_slot_menu_slot_${slotId.name}');
|
||||
|
||||
Key getAppListItemKey(SlotId slotId) =>
|
||||
Key('$_prefix.app_list_item_slot_${slotId.name}');
|
||||
|
@ -32,6 +32,7 @@ import '../../core/state.dart';
|
||||
import '../../management/models.dart';
|
||||
import '../../widgets/list_title.dart';
|
||||
import '../features.dart' as features;
|
||||
import '../keys.dart';
|
||||
import '../models.dart';
|
||||
import '../state.dart';
|
||||
import 'actions.dart';
|
||||
@ -197,6 +198,7 @@ class _SlotListItem extends ConsumerWidget {
|
||||
final hasFeature = ref.watch(featureProvider);
|
||||
|
||||
return AppListItem(
|
||||
key: getAppListItemKey(slot),
|
||||
otpSlot,
|
||||
selected: selected,
|
||||
leading: CircleAvatar(
|
||||
@ -209,6 +211,7 @@ class _SlotListItem extends ConsumerWidget {
|
||||
trailing: expanded
|
||||
? null
|
||||
: OutlinedButton(
|
||||
key: getOpenMenuButtonKey(slot),
|
||||
onPressed: Actions.handler(context, OpenIntent(otpSlot)),
|
||||
child: const Icon(Icons.more_horiz),
|
||||
),
|
||||
|
@ -36,7 +36,7 @@ class SwapSlotsDialog extends ConsumerWidget {
|
||||
title: Text(l10n.s_swap_slots),
|
||||
actions: [
|
||||
TextButton(
|
||||
key: swap,
|
||||
key: swapButton,
|
||||
onPressed: () async {
|
||||
await ref.read(otpStateProvider(devicePath).notifier).swapSlots();
|
||||
await ref.read(withContextProvider)((context) async {
|
||||
|
Loading…
Reference in New Issue
Block a user