use crate::otp::OTP;
use std::time::{SystemTime, UNIX_EPOCH};
#[tokio::test]
async fn test_hotp_generation() {
let key = "1234567890";
let counter = 1;
let digits = 6;
let otp = OTP::new(key, Some(digits), None)
.hotp(counter)
.await
.unwrap();
assert_eq!(otp.len(), digits as usize);
assert!(otp.chars().all(|c| c.is_ascii_digit()));
}
#[tokio::test]
async fn test_hotp_invalid_digits() {
let key = "1234567890";
let counter = 1;
let result = OTP::new(key, Some(9), None).hotp(counter).await;
assert!(result.is_err());
assert_eq!(
result.unwrap_err().to_string(),
"Digits must be between 1 and 8"
);
let result = OTP::new(key, Some(0), None).hotp(counter).await;
assert!(result.is_err());
assert_eq!(
result.unwrap_err().to_string(),
"Digits must be between 1 and 8"
);
}
#[tokio::test]
async fn test_totp_generation() {
let secret = "1234567890";
let digits = 6;
let otp = OTP::new(secret, Some(digits), None).totp().await.unwrap();
assert_eq!(otp.len(), digits as usize);
assert!(otp.chars().all(|c| c.is_ascii_digit()));
}
#[tokio::test]
async fn test_totp_different_time_windows() {
let secret = "1234567890";
let seconds = 30;
let digits = 6;
let otp1 = OTP::new(secret, Some(digits), Some(seconds))
.totp()
.await
.unwrap();
let now = SystemTime::now()
.duration_since(UNIX_EPOCH)
.unwrap()
.as_secs();
let counter1 = now / seconds as u64;
let counter2 = counter1 + 1;
let otp2 = OTP::new(secret, Some(digits), Some(seconds))
.hotp(counter2)
.await
.unwrap();
assert_ne!(otp1, otp2);
}
#[tokio::test]
async fn test_totp_verification() {
let secret = "1234567890";
let otp = OTP::new(secret, None, None);
let totp = otp.totp().await.unwrap();
let is_valid = otp.verify(&totp, None).await.unwrap();
assert!(is_valid);
}
#[tokio::test]
async fn test_totp_invalid_verification() {
let secret = "1234567890";
let invalid_totp = "000000";
let is_valid = OTP::new(secret, None, None)
.verify(invalid_totp, None)
.await
.unwrap();
assert!(!is_valid);
}
#[tokio::test]
async fn test_totp_window_verification() {
let secret = "1234567890";
let otp = OTP::new(secret, None, None);
let totp = otp.totp().await.unwrap();
let is_valid = otp.verify(&totp, Some(1)).await.unwrap();
assert!(is_valid);
}
#[tokio::test]
async fn test_qr_code_generation() {
let secret = "1234567890";
let issuer = "my-site.com";
let account = "account";
let url = OTP::new(secret, None, None).url(issuer, account).unwrap();
assert!(url.contains("otpauth://totp"));
assert!(url.contains(issuer));
assert!(url.contains(account));
}