//! Shopping Workflow Tests //! //! Tests for complete shopping experience: //! - Buy Now functionality //! - Add to Cart workflow //! - Checkout process //! - Order confirmation //! - Cart management (add, remove, edit quantities) use crate::utils::*; use crate::environment::*; use tokio_test; /// Test Buy Now complete workflow #[tokio::test] #[serial_test::serial] async fn test_buy_now_complete_workflow() -> Result<(), Box> { let environment = TestFixtures::setup_test_environment().await?; let mut helper = UXTestHelper::new(&environment); log::info!("Testing Buy Now complete workflow"); // Login as consumer let persona = helper.data_manager.get_persona(&UserRole::Consumer).unwrap(); helper.login_as(persona).await?; // Navigate to marketplace helper.browser.navigate_to("/marketplace").await?; // Look for products with Buy Now option if helper.browser.element_exists(".product-card, .product-item").await { // Get initial wallet balance let initial_balance = helper.api_client.get_wallet_balance().await.ok(); // Click on first product to get details helper.browser.click(".product-card, .product-item").await?; helper.browser.wait_for_element(".product-details, .buy-now").await.ok(); helper.take_screenshot("product_page_buy_now").await?; // Click Buy Now button if helper.browser.element_exists(".buy-now, button[data-action='buy-now']").await { helper.browser.click(".buy-now, button[data-action='buy-now']").await?; // Complete checkout flow let order_id = helper.complete_checkout_flow().await?; // Verify order confirmation assert!(!order_id.is_empty()); helper.assert_element_contains_text(".order-confirmation, .success", "success").await.ok(); // Check if wallet balance was deducted (if we got initial balance) if let Some(initial) = initial_balance { let final_balance = helper.api_client.get_wallet_balance().await?; assert!(final_balance.balance <= initial.balance, "Wallet balance should be deducted"); } helper.take_screenshot("buy_now_success").await?; } } log::info!("Buy Now complete workflow test completed successfully"); Ok(()) } /// Test Add to Cart workflow #[tokio::test] #[serial_test::serial] async fn test_add_to_cart_workflow() -> Result<(), Box> { let environment = TestFixtures::setup_test_environment().await?; let mut helper = UXTestHelper::new(&environment); log::info!("Testing Add to Cart workflow"); // Login as consumer let persona = helper.data_manager.get_persona(&UserRole::Consumer).unwrap(); helper.login_as(persona).await?; // Navigate to marketplace helper.browser.navigate_to("/marketplace").await?; // Initial cart should be empty or have known state helper.navigate_to_cart().await?; let initial_cart_items = helper.browser.find_elements(".cart-item, .product-item").await.unwrap_or_default().len(); // Go back to marketplace and add items helper.browser.navigate_to("/marketplace").await?; // Add first product to cart if helper.browser.element_exists(".add-to-cart, .product-card").await { helper.browser.click(".add-to-cart, .product-card .btn:not(.buy-now)").await?; // Wait for cart update notification helper.browser.wait_for_element(".cart-updated, .notification, .alert-success").await.ok(); helper.take_screenshot("item_added_to_cart").await?; // Verify cart badge updated if helper.browser.element_exists(".cart-badge, .cart-count").await { let badge_text = helper.browser.get_text(".cart-badge, .cart-count").await?; let cart_count = badge_text.parse::().unwrap_or(0); assert!(cart_count > initial_cart_items, "Cart count should increase"); } } // Navigate to cart and verify item helper.navigate_to_cart().await?; let final_cart_items = helper.browser.find_elements(".cart-item, .product-item").await.unwrap_or_default().len(); assert!(final_cart_items > initial_cart_items, "Cart should have more items"); helper.take_screenshot("cart_with_added_items").await?; log::info!("Add to Cart workflow test completed successfully"); Ok(()) } /// Test cart management (edit quantities, remove items) #[tokio::test] #[serial_test::serial] async fn test_cart_management() -> Result<(), Box> { let environment = TestFixtures::setup_test_environment().await?; let mut helper = UXTestHelper::new(&environment); log::info!("Testing cart management"); // Login as consumer let persona = helper.data_manager.get_persona(&UserRole::Consumer).unwrap(); helper.login_as(persona).await?; // Add items to cart first helper.browser.navigate_to("/marketplace").await?; // Add multiple items if possible let add_to_cart_buttons = helper.browser.find_elements(".add-to-cart, .product-card .btn").await.unwrap_or_default(); for (i, button) in add_to_cart_buttons.iter().take(2).enumerate() { button.click().await.ok(); helper.wait(std::time::Duration::from_millis(500)).await; log::info!("Added item {} to cart", i + 1); } // Navigate to cart helper.navigate_to_cart().await?; // Test quantity editing (if available) if helper.browser.element_exists(".quantity-input, input[name='quantity']").await { helper.browser.type_text(".quantity-input, input[name='quantity']", "3").await?; // Click update quantity button if exists if helper.browser.element_exists(".update-quantity, .quantity-update").await { helper.browser.click(".update-quantity, .quantity-update").await?; helper.browser.wait_for_element(".cart-updated, .notification").await.ok(); } helper.take_screenshot("cart_quantity_updated").await?; } // Test increase/decrease quantity buttons if helper.browser.element_exists(".quantity-increase, .btn-plus").await { helper.browser.click(".quantity-increase, .btn-plus").await?; helper.wait(std::time::Duration::from_millis(500)).await; helper.take_screenshot("cart_quantity_increased").await?; } if helper.browser.element_exists(".quantity-decrease, .btn-minus").await { helper.browser.click(".quantity-decrease, .btn-minus").await?; helper.wait(std::time::Duration::from_millis(500)).await; helper.take_screenshot("cart_quantity_decreased").await?; } // Test remove item from cart let initial_items = helper.browser.find_elements(".cart-item, .product-item").await.unwrap_or_default().len(); if helper.browser.element_exists(".remove-item, .delete-item, .btn-remove").await { helper.browser.click(".remove-item, .delete-item, .btn-remove").await?; // Wait for item removal helper.browser.wait_for_element(".item-removed, .notification").await.ok(); // Verify item count decreased let final_items = helper.browser.find_elements(".cart-item, .product-item").await.unwrap_or_default().len(); assert!(final_items < initial_items, "Cart items should decrease after removal"); helper.take_screenshot("cart_item_removed").await?; } // Test clear cart functionality if helper.browser.element_exists(".clear-cart, .empty-cart").await { helper.browser.click(".clear-cart, .empty-cart").await?; // Handle confirmation if present if helper.browser.element_exists(".confirm-clear, .confirm-yes").await { helper.browser.click(".confirm-clear, .confirm-yes").await?; } // Verify cart is empty helper.browser.wait_for_element(".cart-empty, .empty-state").await.ok(); helper.take_screenshot("cart_cleared").await?; } log::info!("Cart management test completed successfully"); Ok(()) } /// Test complete checkout process #[tokio::test] #[serial_test::serial] async fn test_complete_checkout_process() -> Result<(), Box> { let environment = TestFixtures::setup_test_environment().await?; let mut helper = UXTestHelper::new(&environment); log::info!("Testing complete checkout process"); // Login as consumer let persona = helper.data_manager.get_persona(&UserRole::Consumer).unwrap(); helper.login_as(persona).await?; // Add items to cart helper.browser.navigate_to("/marketplace").await?; 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 cart helper.navigate_to_cart().await?; helper.take_screenshot("cart_before_checkout").await?; // Get initial wallet balance for verification let initial_balance = helper.api_client.get_wallet_balance().await.ok(); // Proceed to checkout if helper.browser.element_exists(".checkout-btn, .proceed-checkout").await { helper.browser.click(".checkout-btn, .proceed-checkout").await?; // Wait for checkout page/modal helper.browser.wait_for_element(".checkout, .checkout-form, .payment-form").await?; helper.take_screenshot("checkout_page").await?; // Fill checkout form if required if helper.browser.element_exists("input[name='billing_address']").await { helper.browser.type_text("input[name='billing_address']", "123 Test Street").await?; } if helper.browser.element_exists("input[name='city']").await { helper.browser.type_text("input[name='city']", "Test City").await?; } // Confirm purchase if helper.browser.element_exists(".confirm-purchase, .place-order").await { helper.browser.click(".confirm-purchase, .place-order").await?; // Wait for order processing helper.browser.wait_for_element(".processing, .order-confirmation, .success").await?; helper.take_screenshot("order_processing").await?; // Wait for final confirmation helper.browser.wait_for_element(".order-success, .purchase-complete").await?; // Verify order details are displayed if helper.browser.element_exists(".order-id, .order-number").await { let order_id = helper.browser.get_text(".order-id, .order-number").await?; assert!(!order_id.is_empty(), "Order ID should be displayed"); log::info!("Order completed with ID: {}", order_id); } helper.take_screenshot("checkout_success").await?; // Verify wallet balance was deducted if let Some(initial) = initial_balance { let final_balance = helper.api_client.get_wallet_balance().await?; assert!(final_balance.balance < initial.balance, "Wallet balance should be deducted"); log::info!("Wallet balance: {} -> {}", initial.balance, final_balance.balance); } } } log::info!("Complete checkout process test completed successfully"); Ok(()) } /// Test checkout with insufficient funds #[tokio::test] #[serial_test::serial] async fn test_checkout_insufficient_funds() -> Result<(), Box> { let environment = TestFixtures::setup_test_environment().await?; let mut helper = UXTestHelper::new(&environment).await?; log::info!("Testing checkout with insufficient funds"); // Login as consumer let persona = helper.data_manager.get_persona(&UserRole::Consumer).unwrap(); helper.login_as(persona).await?; // Check current wallet balance let balance = helper.api_client.get_wallet_balance().await?; // If balance is sufficient, we can't test insufficient funds scenario easily // This test would need a way to set balance to insufficient amount log::info!("Current balance: {} {}", balance.balance, balance.currency); // Add expensive item to cart (if available) or multiple items helper.browser.navigate_to("/marketplace").await?; // Add items to cart until we might exceed balance let products = helper.browser.find_elements(".product-card, .add-to-cart").await.unwrap_or_default(); for product in products.iter().take(5) { product.click().await.ok(); helper.wait(std::time::Duration::from_millis(300)).await; } // Navigate to cart and try checkout helper.navigate_to_cart().await?; if helper.browser.element_exists(".checkout-btn").await { helper.browser.click(".checkout-btn").await?; // Look for insufficient funds error helper.browser.wait_for_element(".insufficient-funds, .payment-error, .error").await.ok(); if helper.browser.element_exists(".insufficient-funds, .payment-error").await { helper.take_screenshot("insufficient_funds_error").await?; log::info!("Insufficient funds error properly displayed"); } else { log::info!("No insufficient funds scenario encountered"); } } Ok(()) } /// Test order history and tracking #[tokio::test] #[serial_test::serial] async fn test_order_history_and_tracking() -> Result<(), Box> { let environment = TestFixtures::setup_test_environment().await?; let mut helper = UXTestHelper::new(&environment).await?; log::info!("Testing order history and tracking"); // Login as consumer let persona = helper.data_manager.get_persona(&UserRole::Consumer).unwrap(); helper.login_as(persona).await?; // Navigate to order history helper.navigate_to_dashboard_section("orders").await?; // Verify orders page elements assert!(helper.browser.element_exists(".orders, .order-history, .order-list").await); helper.take_screenshot("order_history_page").await?; // Check if orders exist if helper.browser.element_exists(".order-item, .order-row").await { // Click on first order for details helper.browser.click(".order-item, .order-row").await?; // Wait for order details helper.browser.wait_for_element(".order-details, .order-info").await.ok(); helper.take_screenshot("order_details_page").await?; // Verify order details elements let expected_elements = vec![ ".order-id, .order-number", ".order-date, .purchase-date", ".order-status, .status", ".order-total, .total-amount", ]; for element in expected_elements { if helper.browser.element_exists(element).await { log::info!("Found order detail element: {}", element); } } // Test invoice download if available if helper.browser.element_exists(".download-invoice, .invoice-link").await { helper.browser.click(".download-invoice, .invoice-link").await?; helper.take_screenshot("invoice_download").await?; } } else { log::info!("No orders found in history - this is expected for new test environment"); } log::info!("Order history and tracking test completed successfully"); Ok(()) } /// Test different product categories checkout #[tokio::test] #[serial_test::serial] async fn test_different_product_categories_checkout() -> Result<(), Box> { let environment = TestFixtures::setup_test_environment().await?; let mut helper = UXTestHelper::new(&environment).await?; log::info!("Testing different product categories checkout"); // Login as consumer let persona = helper.data_manager.get_persona(&UserRole::Consumer).unwrap(); helper.login_as(persona).await?; // Test different marketplace categories let categories = vec![ "/marketplace/compute", "/marketplace/applications", "/marketplace/services", ]; for category_url in categories { log::info!("Testing checkout for category: {}", category_url); helper.browser.navigate_to(category_url).await?; // Look for products in this category if helper.browser.element_exists(".product-card, .service-item, .app-item").await { // Try to add item to cart helper.browser.click(".add-to-cart, .buy-now").await.ok(); // Handle any category-specific checkout flows match category_url { "/marketplace/compute" => { // VM/Compute might have configuration options if helper.browser.element_exists(".vm-config, .compute-options").await { helper.take_screenshot("compute_configuration").await?; } } "/marketplace/applications" => { // Apps might have deployment options if helper.browser.element_exists(".app-config, .deployment-options").await { helper.take_screenshot("app_configuration").await?; } } "/marketplace/services" => { // Services might have booking/scheduling if helper.browser.element_exists(".service-booking, .schedule-options").await { helper.take_screenshot("service_booking").await?; } } _ => {} } helper.wait(std::time::Duration::from_millis(500)).await; } } log::info!("Different product categories checkout test completed successfully"); Ok(()) }