359 lines
14 KiB
Rust
359 lines
14 KiB
Rust
//! Authentication Flow Tests
|
|
//!
|
|
//! Tests for user authentication functionality:
|
|
//! - User registration at /register
|
|
//! - Login and logout functionality
|
|
//! - Cart migration during login
|
|
//! - Session management
|
|
//! - GitEa OAuth integration (conditional)
|
|
|
|
use crate::utils::*;
|
|
use crate::environment::*;
|
|
use tokio_test;
|
|
|
|
/// Test user registration flow
|
|
#[tokio::test]
|
|
#[serial_test::serial]
|
|
async fn test_user_registration_flow() -> Result<(), Box<dyn std::error::Error>> {
|
|
let environment = TestFixtures::setup_test_environment().await?;
|
|
let mut helper = UXTestHelper::new(&environment);
|
|
|
|
log::info!("Testing user registration flow");
|
|
|
|
// Get test persona
|
|
let persona = helper.data_manager.get_persona(&UserRole::Consumer).unwrap();
|
|
|
|
// Navigate to registration page
|
|
helper.browser.navigate_to("/register").await?;
|
|
helper.assert_page_loaded("Register").await?;
|
|
|
|
// Verify registration form elements exist
|
|
assert!(helper.browser.element_exists("input[name='email'], input[type='email']").await);
|
|
assert!(helper.browser.element_exists("input[name='password'], input[type='password']").await);
|
|
assert!(helper.browser.element_exists("input[name='name'], input[name='full_name']").await);
|
|
|
|
helper.take_screenshot("registration_form").await?;
|
|
|
|
// Fill registration form
|
|
helper.browser.type_text("input[name='email'], input[type='email']", &persona.email).await?;
|
|
helper.browser.type_text("input[name='password'], input[type='password']", &persona.password).await?;
|
|
helper.browser.type_text("input[name='name'], input[name='full_name']", &persona.name).await?;
|
|
|
|
// Fill additional fields if they exist
|
|
if helper.browser.element_exists("input[name='confirm_password']").await {
|
|
helper.browser.type_text("input[name='confirm_password']", &persona.password).await?;
|
|
}
|
|
|
|
helper.take_screenshot("registration_form_filled").await?;
|
|
|
|
// Submit registration
|
|
helper.browser.click("button[type='submit'], .register-btn, .signup-btn").await?;
|
|
|
|
// Wait for success response or redirect
|
|
helper.browser.wait_for_element(".success, .dashboard, .registration-success, .alert-success").await?;
|
|
|
|
helper.take_screenshot("registration_success").await?;
|
|
|
|
// Verify user is now authenticated (should be on dashboard or logged in)
|
|
if helper.browser.get_current_url().await?.contains("dashboard") {
|
|
helper.assert_user_is_authenticated().await?;
|
|
}
|
|
|
|
log::info!("User registration flow test completed successfully");
|
|
Ok(())
|
|
}
|
|
|
|
/// Test user login flow
|
|
#[tokio::test]
|
|
#[serial_test::serial]
|
|
async fn test_user_login_flow() -> Result<(), Box<dyn std::error::Error>> {
|
|
let environment = TestFixtures::setup_test_environment().await?;
|
|
let mut helper = UXTestHelper::new(&environment);
|
|
|
|
log::info!("Testing user login flow");
|
|
|
|
// Get test persona (should already exist from registration or test data)
|
|
let persona = helper.data_manager.get_persona(&UserRole::Consumer).unwrap();
|
|
|
|
// Navigate to login page
|
|
helper.browser.navigate_to("/login").await?;
|
|
helper.assert_page_loaded("Login").await?;
|
|
|
|
// Verify login form elements exist
|
|
assert!(helper.browser.element_exists("input[name='email'], input[type='email']").await);
|
|
assert!(helper.browser.element_exists("input[name='password'], input[type='password']").await);
|
|
assert!(helper.browser.element_exists("button[type='submit'], .login-btn").await);
|
|
|
|
helper.take_screenshot("login_form").await?;
|
|
|
|
// Test login with valid credentials
|
|
helper.login_as(persona).await?;
|
|
|
|
// Verify successful login
|
|
helper.assert_user_is_authenticated().await?;
|
|
|
|
// Verify redirect to dashboard or appropriate page
|
|
let current_url = helper.browser.get_current_url().await?;
|
|
assert!(current_url.contains("dashboard") || current_url.contains("marketplace"));
|
|
|
|
helper.take_screenshot("login_success").await?;
|
|
|
|
log::info!("User login flow test completed successfully");
|
|
Ok(())
|
|
}
|
|
|
|
/// Test user logout flow
|
|
#[tokio::test]
|
|
#[serial_test::serial]
|
|
async fn test_user_logout_flow() -> Result<(), Box<dyn std::error::Error>> {
|
|
let environment = TestFixtures::setup_test_environment().await?;
|
|
let mut helper = UXTestHelper::new(&environment);
|
|
|
|
log::info!("Testing user logout flow");
|
|
|
|
// First login
|
|
let persona = helper.data_manager.get_persona(&UserRole::Consumer).unwrap();
|
|
helper.login_as(persona).await?;
|
|
helper.assert_user_is_authenticated().await?;
|
|
|
|
// Test logout
|
|
helper.logout().await?;
|
|
|
|
// Verify logout success
|
|
let current_url = helper.browser.get_current_url().await?;
|
|
assert!(!current_url.contains("dashboard"));
|
|
|
|
// Verify user menu/authentication indicators are gone
|
|
assert!(!helper.browser.element_exists(".user-menu, .logout-btn").await);
|
|
|
|
// Try to access protected page and verify redirect
|
|
helper.browser.navigate_to("/dashboard").await?;
|
|
|
|
// Should redirect to login or show unauthorized
|
|
let final_url = helper.browser.get_current_url().await?;
|
|
assert!(final_url.contains("login") || final_url.contains("unauthorized") || !final_url.contains("dashboard"));
|
|
|
|
helper.take_screenshot("logout_success").await?;
|
|
|
|
log::info!("User logout flow test completed successfully");
|
|
Ok(())
|
|
}
|
|
|
|
/// Test cart migration during login
|
|
#[tokio::test]
|
|
#[serial_test::serial]
|
|
async fn test_cart_migration_during_login() -> Result<(), Box<dyn std::error::Error>> {
|
|
let environment = TestFixtures::setup_test_environment().await?;
|
|
let mut helper = UXTestHelper::new(&environment);
|
|
|
|
log::info!("Testing cart migration during login");
|
|
|
|
// Step 1: Add items to cart as anonymous user
|
|
helper.browser.navigate_to("/marketplace").await?;
|
|
|
|
// Try to add item to anonymous cart
|
|
if helper.browser.element_exists(".add-to-cart, .product-card").await {
|
|
helper.browser.click(".add-to-cart, .product-card .btn").await?;
|
|
helper.browser.wait_for_element(".cart-updated, .notification").await.ok();
|
|
}
|
|
|
|
// Navigate to anonymous cart and verify items
|
|
helper.navigate_to_cart().await?;
|
|
let anonymous_cart_items = helper.browser.find_elements(".cart-item, .product-item").await.unwrap_or_default().len();
|
|
|
|
helper.take_screenshot("anonymous_cart_with_items").await?;
|
|
|
|
// Step 2: Login and verify cart migration
|
|
let persona = helper.data_manager.get_persona(&UserRole::Consumer).unwrap();
|
|
helper.login_as(persona).await?;
|
|
|
|
// Navigate to authenticated user cart
|
|
helper.navigate_to_cart().await?;
|
|
|
|
// Verify cart items were migrated
|
|
let authenticated_cart_items = helper.browser.find_elements(".cart-item, .product-item").await.unwrap_or_default().len();
|
|
|
|
// Cart should have same or more items (if user already had items)
|
|
assert!(authenticated_cart_items >= anonymous_cart_items,
|
|
"Cart migration failed: anonymous had {}, authenticated has {}",
|
|
anonymous_cart_items, authenticated_cart_items);
|
|
|
|
helper.take_screenshot("authenticated_cart_after_migration").await?;
|
|
|
|
log::info!("Cart migration during login test completed successfully");
|
|
Ok(())
|
|
}
|
|
|
|
/// Test session management and persistence
|
|
#[tokio::test]
|
|
#[serial_test::serial]
|
|
async fn test_session_management() -> Result<(), Box<dyn std::error::Error>> {
|
|
let environment = TestFixtures::setup_test_environment().await?;
|
|
let mut helper = UXTestHelper::new(&environment);
|
|
|
|
log::info!("Testing session management and persistence");
|
|
|
|
// Login
|
|
let persona = helper.data_manager.get_persona(&UserRole::Consumer).unwrap();
|
|
helper.login_as(persona).await?;
|
|
helper.assert_user_is_authenticated().await?;
|
|
|
|
// Navigate to different pages and verify session persists
|
|
let test_pages = vec![
|
|
"/dashboard",
|
|
"/dashboard/wallet",
|
|
"/marketplace",
|
|
"/dashboard/settings",
|
|
];
|
|
|
|
for page in test_pages {
|
|
helper.browser.navigate_to(page).await?;
|
|
|
|
// Verify still authenticated on each page
|
|
if page.contains("dashboard") {
|
|
// For dashboard pages, check for dashboard elements
|
|
helper.browser.wait_for_element(".dashboard, .user-content").await.ok();
|
|
}
|
|
|
|
// Check that we're not redirected to login
|
|
let current_url = helper.browser.get_current_url().await?;
|
|
assert!(!current_url.contains("login"), "Session expired on page {}", page);
|
|
|
|
helper.take_screenshot(&format!("session_check_{}", page.replace("/", "_"))).await?;
|
|
}
|
|
|
|
// Test API authentication status
|
|
let auth_status = helper.api_client.validate_auth_status().await?;
|
|
assert!(auth_status.authenticated, "API reports user not authenticated");
|
|
assert_eq!(auth_status.user_email, Some(persona.email.clone()));
|
|
|
|
log::info!("Session management test completed successfully");
|
|
Ok(())
|
|
}
|
|
|
|
/// Test login error handling
|
|
#[tokio::test]
|
|
#[serial_test::serial]
|
|
async fn test_login_error_handling() -> Result<(), Box<dyn std::error::Error>> {
|
|
let environment = TestFixtures::setup_test_environment().await?;
|
|
let mut helper = UXTestHelper::new(&environment);
|
|
|
|
log::info!("Testing login error handling");
|
|
|
|
// Navigate to login page
|
|
helper.browser.navigate_to("/login").await?;
|
|
|
|
// Test invalid credentials
|
|
helper.browser.type_text("input[name='email'], input[type='email']", "invalid@example.com").await?;
|
|
helper.browser.type_text("input[name='password'], input[type='password']", "wrongpassword").await?;
|
|
|
|
helper.take_screenshot("login_invalid_credentials").await?;
|
|
|
|
// Submit login
|
|
helper.browser.click("button[type='submit'], .login-btn").await?;
|
|
|
|
// Should show error message
|
|
helper.browser.wait_for_element(".error, .alert-danger, .login-error").await?;
|
|
|
|
// Verify error message is displayed
|
|
assert!(helper.browser.element_exists(".error, .alert-danger, .login-error").await);
|
|
|
|
// Verify user is not authenticated
|
|
assert!(!helper.browser.element_exists(".user-menu, .dashboard-link").await);
|
|
|
|
helper.take_screenshot("login_error_displayed").await?;
|
|
|
|
// Test empty form submission
|
|
helper.browser.navigate_to("/login").await?;
|
|
helper.browser.click("button[type='submit'], .login-btn").await?;
|
|
|
|
// Should show validation errors
|
|
helper.browser.wait_for_element(".validation-error, .required-field").await.ok();
|
|
helper.take_screenshot("login_validation_errors").await?;
|
|
|
|
log::info!("Login error handling test completed successfully");
|
|
Ok(())
|
|
}
|
|
|
|
/// Test GitEa OAuth integration (conditional on environment)
|
|
#[tokio::test]
|
|
#[serial_test::serial]
|
|
async fn test_gitea_oauth_integration() -> Result<(), Box<dyn std::error::Error>> {
|
|
let environment = TestFixtures::setup_test_environment().await?;
|
|
let mut helper = UXTestHelper::new(&environment).await?;
|
|
|
|
log::info!("Testing GitEa OAuth integration");
|
|
|
|
// Check if GitEa OAuth is enabled
|
|
if std::env::var("GITEA_CLIENT_ID").is_ok() {
|
|
// Navigate to login page
|
|
helper.browser.navigate_to("/login").await?;
|
|
|
|
// Look for GitEa OAuth button
|
|
if helper.browser.element_exists(".oauth-gitea, .gitea-login, a[href*='auth/gitea']").await {
|
|
helper.take_screenshot("login_with_gitea_option").await?;
|
|
|
|
// Click GitEa OAuth (don't complete the flow in tests)
|
|
// Just verify the redirect starts
|
|
helper.browser.click(".oauth-gitea, .gitea-login, a[href*='auth/gitea']").await?;
|
|
|
|
// Should redirect to GitEa or show OAuth flow
|
|
let current_url = helper.browser.get_current_url().await?;
|
|
assert!(current_url.contains("gitea") || current_url.contains("oauth") || current_url.contains("auth"));
|
|
|
|
helper.take_screenshot("gitea_oauth_redirect").await?;
|
|
|
|
log::info!("GitEa OAuth integration verified");
|
|
} else {
|
|
log::info!("GitEa OAuth button not found - may not be enabled");
|
|
}
|
|
} else {
|
|
log::info!("GitEa OAuth not configured - skipping integration test");
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
|
|
/// Test registration validation
|
|
#[tokio::test]
|
|
#[serial_test::serial]
|
|
async fn test_registration_validation() -> Result<(), Box<dyn std::error::Error>> {
|
|
let environment = TestFixtures::setup_test_environment().await?;
|
|
let mut helper = UXTestHelper::new(&environment).await?;
|
|
|
|
log::info!("Testing registration validation");
|
|
|
|
// Navigate to registration page
|
|
helper.browser.navigate_to("/register").await?;
|
|
|
|
// Test empty form submission
|
|
helper.browser.click("button[type='submit'], .register-btn").await?;
|
|
|
|
// Should show validation errors
|
|
helper.browser.wait_for_element(".validation-error, .required-field, .error").await.ok();
|
|
helper.take_screenshot("registration_validation_errors").await?;
|
|
|
|
// Test invalid email format
|
|
helper.browser.type_text("input[name='email'], input[type='email']", "invalid-email").await?;
|
|
helper.browser.type_text("input[name='password'], input[type='password']", "short").await?;
|
|
helper.browser.click("button[type='submit'], .register-btn").await?;
|
|
|
|
// Should show format validation errors
|
|
helper.browser.wait_for_element(".validation-error, .email-error").await.ok();
|
|
helper.take_screenshot("registration_format_errors").await?;
|
|
|
|
// Test duplicate email (if validation exists)
|
|
let existing_persona = helper.data_manager.get_persona(&UserRole::Consumer).unwrap();
|
|
helper.browser.navigate_to("/register").await?;
|
|
helper.browser.type_text("input[name='email'], input[type='email']", &existing_persona.email).await?;
|
|
helper.browser.type_text("input[name='password'], input[type='password']", "validpassword123").await?;
|
|
helper.browser.type_text("input[name='name'], input[name='full_name']", "Test User").await?;
|
|
helper.browser.click("button[type='submit'], .register-btn").await?;
|
|
|
|
// May show duplicate email error
|
|
helper.browser.wait_for_element(".error, .duplicate-email").await.ok();
|
|
helper.take_screenshot("registration_duplicate_email").await?;
|
|
|
|
log::info!("Registration validation test completed successfully");
|
|
Ok(())
|
|
} |