update tests, make them pass on Neo with delays

This commit is contained in:
Adam Velebil 2022-09-13 17:13:06 +02:00
parent ea522834cf
commit eb1f67e4fb
No known key found for this signature in database
GPG Key ID: AC6D6B9D715FC084
5 changed files with 69 additions and 32 deletions

View File

@ -1,13 +1,14 @@
import 'package:flutter_test/flutter_test.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:yubico_authenticator/android/init.dart';
import 'package:yubico_authenticator/android/keys.dart' as android_keys;
import 'package:yubico_authenticator/android/qr_scanner/qr_scanner_view.dart';
import 'package:yubico_authenticator/app/views/device_avatar.dart';
import 'package:yubico_authenticator/app/views/keys.dart' as app_keys;
import '../test_util.dart';
import 'constants.dart';
// track the first start and use longer delay
bool _firstStart = true;
const int _firstStartDelaySec = 5;
void _setShowBetaDialogPref(bool value) async {
SharedPreferences.setMockInitialValues({betaDialogPrefName: value});
}
@ -19,17 +20,31 @@ Future<void> startUp(WidgetTester tester,
var betaDlgEnabled = startUpParams['dlg.beta.enabled'] ?? false;
_setShowBetaDialogPref(betaDlgEnabled);
if (_firstStart) {
tester.printToConsole('First app start: Connect YubiKey and approve USB Connection');
}
await tester.pumpWidget(await initialize());
await tester.pumpWidget(
await initialize(),
_firstStart
? const Duration(seconds: _firstStartDelaySec)
: const Duration(milliseconds: 500));
// wait for a YubiKey connection
await tester.waitForFinder(find.descendant(
of: tester.findDeviceButton(),
matching: find.byWidgetPredicate((widget) =>
widget is DeviceAvatar && widget.key != app_keys.noDeviceAvatar)));
if (_firstStart) {
_firstStart = false;
}
await tester.pump(const Duration(milliseconds: 500));
}
Future<void> grantCameraPermissions(WidgetTester tester) async {
await tester.waitForFinder(find.byType(QrScannerView));
await tester.longWait();
/// on android a QR Scanner starts
/// we want to do a manual addition
var manualEntryBtn = find.byKey(android_keys.manualEntryButton).hitTestable();
if (manualEntryBtn.evaluate().isEmpty) {
tester.testLog(false, 'Allow camera permission');
manualEntryBtn = await tester.waitForFinder(manualEntryBtn);
}
await tester.tap(manualEntryBtn);
await tester.longWait();
}

View File

@ -1,11 +1,11 @@
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 'android/util.dart';
import 'test_util.dart';
class Account {
@ -48,19 +48,7 @@ extension OathFunctions on WidgetTester {
await tapAddAccount();
if (isAndroid) {
/// on android a QR Scanner starts
/// we want to do a manual addition
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(android_keys.manualEntryButton).hitTestable();
}
await tap(manualEntryBtn);
await longWait();
await grantCameraPermissions(this);
}
var issuerText = find.byKey(keys.issuerField).hitTestable();
@ -78,7 +66,9 @@ extension OathFunctions on WidgetTester {
await tap(find.byKey(keys.saveButton));
await longWait();
/// TODO:
/// the following pump is because of NEO keys
await pump(const Duration(seconds: 1));
accountView = await findAccount(a);
expect(accountView, isNotNull);
@ -154,12 +144,16 @@ extension OathFunctions on WidgetTester {
}
await openAccountDialog(a);
/// click the delete IconButton in the account dialog
var deleteIconButton = find.byIcon(Icons.delete_outline).hitTestable();
expect(deleteIconButton, findsOneWidget);
await tap(deleteIconButton);
await longWait();
/// TODO check dialog shows correct information about account
/// click the delete Button in the delete dialog
var deleteButton = find.byKey(keys.deleteButton).hitTestable();
expect(deleteButton, findsOneWidget);
await tap(deleteButton);
@ -249,7 +243,10 @@ extension OathFunctions on WidgetTester {
await shortWait();
await tap(find.byKey(keys.savePasswordButton));
await longWait();
/// TODO:
/// the following pause is because of NEO keys
await pump(const Duration(seconds: 1));
/// after tapping Save, the dialog is closed and the save button does not exist
expect(find.byKey(keys.savePasswordButton).hitTestable(), findsNothing);

View File

@ -1,5 +1,6 @@
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:yubico_authenticator/app/views/device_button.dart';
import 'package:yubico_authenticator/app/views/keys.dart' as app_keys;
import 'package:yubico_authenticator/core/state.dart';
@ -36,6 +37,26 @@ extension AppWidgetTester on WidgetTester {
await pump(const Duration(seconds: veryLongWaitS));
}
/// waits up to [timeOutSec] seconds evaluating whether [Finder] f is
/// visible
Future<Finder> waitForFinder(Finder f, [int timeOutSec = 20]) async {
int delayMs = 500;
int elapsedTime = 0;
var evaluated = f.evaluate();
while (evaluated.isEmpty && elapsedTime < timeOutSec * 1000) {
await pump(Duration(milliseconds: delayMs));
elapsedTime += delayMs;
evaluated = f.evaluate();
}
if (evaluated.isEmpty) {
testLog(false, 'Failed to find ${f.description} in $timeOutSec seconds.');
}
return f;
}
Finder findDeviceButton() {
return find.byType(DeviceButton).hitTestable();
}
@ -119,6 +140,7 @@ extension AppWidgetTester on WidgetTester {
}
}
@isTest
void appTest(
String description,
WidgetTesterCallback callback, {

View File

@ -6,6 +6,7 @@ import '../../widgets/custom_icons.dart';
import '../models.dart';
import '../state.dart';
import 'device_images.dart';
import 'keys.dart';
class DeviceAvatar extends StatelessWidget {
final Widget child;
@ -57,6 +58,7 @@ class DeviceAvatar extends StatelessWidget {
} else {
return DeviceAvatar(
radius: radius,
key: noDeviceAvatar,
child: const Icon(Icons.usb),
);
}

View File

@ -2,4 +2,5 @@
import 'package:flutter/material.dart';
const _prefix = 'app.keys';
const deviceInfoListTile = Key('$_prefix.device_info_list_tile');
const deviceInfoListTile = Key('$_prefix.device_info_list_tile');
const noDeviceAvatar = Key('$_prefix.no_device_avatar');