yubioath-flutter/integration_test/oath_test.dart
2023-12-04 15:28:07 +01:00

331 lines
12 KiB
Dart

/*
* Copyright (C) 2023 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 'dart:convert';
import 'dart:math';
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/core/state.dart';
import 'package:yubico_authenticator/oath/keys.dart' as keys;
import 'package:yubico_authenticator/oath/models.dart';
import 'package:yubico_authenticator/oath/views/account_list.dart';
import 'utils/oath_test_util.dart';
import 'utils/test_util.dart';
String randomPadded() {
return randomNum(999).toString().padLeft(3, '0');
}
randomNum(int i) {}
String generateRandomIssuer() {
return 'i${randomPadded()}';
}
String generateRandomName() {
return 'n${randomPadded()}';
}
void main() {
var binding = IntegrationTestWidgetsFlutterBinding.ensureInitialized();
binding.framePolicy = LiveTestWidgetsFlutterBindingFramePolicy.fullyLive;
group('OATH UI tests', () {
appTest('Menu items exist', (WidgetTester tester) async {
await tester.tapActionIconButton();
await tester.shortWait();
expect(find.byKey(keys.addAccountAction), findsOneWidget);
expect(find.byKey(keys.setOrManagePasswordAction), findsOneWidget);
expect(find.byKey(keys.resetAction), findsOneWidget);
// close dialog
await tester.tapTopLeftCorner();
await tester.longWait();
});
});
group('Account creation', () {
appTest('Initial reset OATH', (WidgetTester tester) async {
/// reset OATH application
var oathDrawerButton = find.byKey(oathAppDrawer).hitTestable();
await tester.tap(oathDrawerButton);
await tester.longWait();
await tester.resetOATH();
await tester.longWait();
});
appTest('Create 32 Accounts', (WidgetTester tester) async {
var oathDrawerButton = find.byKey(oathAppDrawer).hitTestable();
await tester.tap(oathDrawerButton);
await tester.longWait();
for (var i = 0; i < 32; i += 1) {
// just now merely 32 accounts
var testAccount = Account(
issuer: 'MaxAccount_issuer_$i',
name: 'MaxAccount_name_$i',
secret: 'abbaabba',
);
await tester.addAccount(testAccount);
await tester.shortWait();
expect(
find.descendant(
of: find.byType(AccountList),
matching: find.textContaining(testAccount.name)),
findsOneWidget);
await tester.shortWait();
}
// TODO: verify one more addAccount() is not possible
await tester.resetOATH();
await tester.shortWait();
});
// appTest('Create weird character-accounts and check byte count',
// (WidgetTester tester) async {});
group('TOTP account tests', () {
appTest('TOTP: sha-1', (WidgetTester tester) async {
var oathDrawerButton = find.byKey(oathAppDrawer).hitTestable();
await tester.tap(oathDrawerButton);
await tester.longWait();
const testAccount = Account(
issuer: 'i_totp_sha1',
name: 'n__totp_sha1',
secret: 'abbaabba',
touch: false,
oathType: OathType.totp,
hashAlgorithm: HashAlgorithm.sha1);
await tester.addAccount(testAccount);
expect(
find.descendant(
of: find.byType(AccountList),
matching: find.textContaining(testAccount.name)),
findsOneWidget);
await tester.shortWait();
});
appTest('TOTP: sha-256', (WidgetTester tester) async {
var oathDrawerButton = find.byKey(oathAppDrawer).hitTestable();
await tester.tap(oathDrawerButton);
await tester.longWait();
const testAccount = Account(
issuer: 'i_totp_sha256',
name: 'n__totp_sha256',
secret: 'abbaabba',
touch: false,
oathType: OathType.totp,
hashAlgorithm: HashAlgorithm.sha256);
await tester.addAccount(testAccount);
expect(
find.descendant(
of: find.byType(AccountList),
matching: find.textContaining(testAccount.name)),
findsOneWidget);
await tester.shortWait();
});
appTest('TOTP: sha-512', (WidgetTester tester) async {
var oathDrawerButton = find.byKey(oathAppDrawer).hitTestable();
await tester.tap(oathDrawerButton);
await tester.longWait();
const testAccount = Account(
issuer: 'i_totp_sha512',
name: 'n__totp_sha512',
secret: 'abbaabba',
touch: false,
oathType: OathType.totp,
hashAlgorithm: HashAlgorithm.sha512);
await tester.addAccount(testAccount);
expect(
find.descendant(
of: find.byType(AccountList),
matching: find.textContaining(testAccount.name)),
findsOneWidget);
await tester.shortWait();
});
// appTest('TOTP: period-20',
// (WidgetTester tester) async {});
// appTest('TOTP: period-45',
// (WidgetTester tester) async {});
// appTest('TOTP: period-60',
// (WidgetTester tester) async {});
// appTest('TOTP: digits-8',
// (WidgetTester tester) async {});
appTest('TOTP: touch', (WidgetTester tester) async {
var oathDrawerButton = find.byKey(oathAppDrawer).hitTestable();
await tester.tap(oathDrawerButton);
await tester.longWait();
const testAccount = Account(
issuer: 'i_totp_touch',
name: 'n_totp_touch',
secret: 'abbaabba',
touch: true,
oathType: OathType.totp,
hashAlgorithm: HashAlgorithm.sha1);
await tester.addAccount(testAccount);
expect(
find.descendant(
of: find.byType(AccountList),
matching: find.textContaining(testAccount.name)),
findsOneWidget);
await tester.shortWait();
});
});
// group('HOTP account tests', () {
appTest('HOTP: sha-1', (WidgetTester tester) async {
var oathDrawerButton = find.byKey(oathAppDrawer).hitTestable();
await tester.tap(oathDrawerButton);
await tester.longWait();
const testAccount = Account(
issuer: 'i_hotp_sha1',
name: 'n__hotp_sha1',
secret: 'abbaabba',
touch: false,
oathType: OathType.hotp,
hashAlgorithm: HashAlgorithm.sha1);
await tester.addAccount(testAccount);
expect(
find.descendant(
of: find.byType(AccountList),
matching: find.textContaining(testAccount.name)),
findsOneWidget);
await tester.shortWait();
});
appTest('HOTP: sha-256', (WidgetTester tester) async {
var oathDrawerButton = find.byKey(oathAppDrawer).hitTestable();
await tester.tap(oathDrawerButton);
await tester.longWait();
const testAccount = Account(
issuer: 'i_hotp_sha256',
name: 'n__hotp_sha256',
secret: 'abbaabba',
touch: false,
oathType: OathType.hotp,
hashAlgorithm: HashAlgorithm.sha256);
await tester.addAccount(testAccount);
expect(
find.descendant(
of: find.byType(AccountList),
matching: find.textContaining(testAccount.name)),
findsOneWidget);
await tester.shortWait();
});
appTest('HOTP: sha-512', (WidgetTester tester) async {
var oathDrawerButton = find.byKey(oathAppDrawer).hitTestable();
await tester.tap(oathDrawerButton);
await tester.longWait();
const testAccount = Account(
issuer: 'i_hotp_sha512',
name: 'n__hotp_sha512',
secret: 'abbaabba',
touch: false,
oathType: OathType.hotp,
hashAlgorithm: HashAlgorithm.sha512);
await tester.addAccount(testAccount);
expect(
find.descendant(
of: find.byType(AccountList),
matching: find.textContaining(testAccount.name)),
findsOneWidget);
await tester.shortWait();
});
// appTest('TOTP: digits-8',
// (WidgetTester tester) async {});
appTest('HOTP: touch', (WidgetTester tester) async {
var oathDrawerButton = find.byKey(oathAppDrawer).hitTestable();
await tester.tap(oathDrawerButton);
await tester.longWait();
const testAccount = Account(
issuer: 'i_hotp_touch',
name: 'n_hotp_touch',
secret: 'abbaabba',
touch: true,
oathType: OathType.hotp,
hashAlgorithm: HashAlgorithm.sha1);
await tester.addAccount(testAccount);
expect(
find.descendant(
of: find.byType(AccountList),
matching: find.textContaining(testAccount.name)),
findsOneWidget);
await tester.shortWait();
});
// group('QR Code scanning', () {});
appTest('Final reset OATH', (WidgetTester tester) async {
/// reset OATH application
var oathDrawerButton = find.byKey(oathAppDrawer).hitTestable();
await tester.tap(oathDrawerButton);
await tester.longWait();
await tester.resetOATH();
await tester.longWait();
});
/// adds an account, renames, verifies
appTest('Rename OATH account', (WidgetTester tester) async {
var testAccount =
const Account(issuer: 'IssuerToRename', name: 'NameToRename');
/// delete account if it exists
await tester.deleteAccount(testAccount);
await tester.deleteAccount(
const Account(issuer: 'RenamedIssuer', name: 'RenamedName'));
await tester.addAccount(testAccount);
await tester.renameAccount(testAccount, 'RenamedIssuer', 'RenamedName');
});
});
group('Password tests', () {
// NOTE: that the password groups should be run as whole
// NOTE: cannot restart the app on Android to be able to unlock: skip
group('Desktop password tests', skip: isAndroid, () {
var firstPassword = 'firstPassword';
var secondPassword = 'secondPassword';
var thirdPassword = 'thirdPassword';
appTest('Reset OATH', (WidgetTester tester) async {
await tester.resetOATH();
});
appTest('Set first OATH password', (WidgetTester tester) async {
// Sets a password for OATH
await tester.setOathPassword(firstPassword);
});
appTest('Set second OATH password', (WidgetTester tester) async {
// Without removing the first, change to a second password
await tester.unlockOathSession(firstPassword);
await tester.replaceOathPassword(firstPassword, secondPassword);
});
appTest('Set third OATH password', (WidgetTester tester) async {
// Without removing the second, set a third password
await tester.unlockOathSession(secondPassword);
await tester.replaceOathPassword(secondPassword, thirdPassword);
});
appTest('Remove OATH password', (WidgetTester tester) async {
// restarts the app, unlocks with password, removes password req.
await tester.unlockOathSession(thirdPassword);
await tester.removeOathPassword(thirdPassword);
});
});
});
}