394 lines
15 KiB
Python
394 lines
15 KiB
Python
"""
|
|
End-to-end tests for real user scenarios
|
|
"""
|
|
|
|
import pytest
|
|
import asyncio
|
|
import time
|
|
from datetime import datetime
|
|
from selenium.webdriver.common.by import By
|
|
from selenium.webdriver.support.ui import WebDriverWait
|
|
from selenium.webdriver.support import expected_conditions as EC
|
|
|
|
|
|
@pytest.mark.e2e
|
|
class TestUserOnboarding:
|
|
"""Test complete user onboarding flow"""
|
|
|
|
def test_new_user_registration_and_first_job(self, browser, base_url):
|
|
"""Test new user registering and creating their first job"""
|
|
# 1. Navigate to application
|
|
browser.get(f"{base_url}/")
|
|
|
|
# 2. Click register button
|
|
register_btn = browser.find_element(By.ID, "register-btn")
|
|
register_btn.click()
|
|
|
|
# 3. Fill registration form
|
|
browser.find_element(By.ID, "email").send_keys("test@example.com")
|
|
browser.find_element(By.ID, "password").send_keys("SecurePass123!")
|
|
browser.find_element(By.ID, "confirm-password").send_keys("SecurePass123!")
|
|
browser.find_element(By.ID, "organization").send_keys("Test Org")
|
|
|
|
# 4. Submit registration
|
|
browser.find_element(By.ID, "submit-register").click()
|
|
|
|
# 5. Verify email confirmation page
|
|
WebDriverWait(browser, 10).until(
|
|
EC.presence_of_element_located((By.ID, "confirmation-message"))
|
|
)
|
|
assert "Check your email" in browser.page_source
|
|
|
|
# 6. Simulate email confirmation (via API)
|
|
# In real test, would parse email and click confirmation link
|
|
|
|
# 7. Login after confirmation
|
|
browser.get(f"{base_url}/login")
|
|
browser.find_element(By.ID, "email").send_keys("test@example.com")
|
|
browser.find_element(By.ID, "password").send_keys("SecurePass123!")
|
|
browser.find_element(By.ID, "login-btn").click()
|
|
|
|
# 8. Verify dashboard
|
|
WebDriverWait(browser, 10).until(
|
|
EC.presence_of_element_located((By.ID, "dashboard"))
|
|
)
|
|
assert "Welcome" in browser.page_source
|
|
|
|
# 9. Create first job
|
|
browser.find_element(By.ID, "create-job-btn").click()
|
|
browser.find_element(By.ID, "job-type").send_keys("AI Inference")
|
|
browser.find_element(By.ID, "model-select").send_keys("GPT-4")
|
|
browser.find_element(By.ID, "prompt-input").send_keys("Write a poem about AI")
|
|
|
|
# 10. Submit job
|
|
browser.find_element(By.ID, "submit-job").click()
|
|
|
|
# 11. Verify job created
|
|
WebDriverWait(browser, 10).until(
|
|
EC.presence_of_element_located((By.CLASS_NAME, "job-card"))
|
|
)
|
|
assert "AI Inference" in browser.page_source
|
|
|
|
|
|
@pytest.mark.e2e
|
|
class TestMinerWorkflow:
|
|
"""Test miner registration and job execution"""
|
|
|
|
def test_miner_setup_and_job_execution(self, browser, base_url):
|
|
"""Test miner setting up and executing jobs"""
|
|
# 1. Navigate to miner portal
|
|
browser.get(f"{base_url}/miner")
|
|
|
|
# 2. Register as miner
|
|
browser.find_element(By.ID, "miner-register").click()
|
|
browser.find_element(By.ID, "miner-id").send_keys("miner-test-123")
|
|
browser.find_element(By.ID, "endpoint").send_keys("http://localhost:9000")
|
|
browser.find_element(By.ID, "gpu-memory").send_keys("16")
|
|
browser.find_element(By.ID, "cpu-cores").send_keys("8")
|
|
|
|
# Select capabilities
|
|
browser.find_element(By.ID, "cap-ai").click()
|
|
browser.find_element(By.ID, "cap-image").click()
|
|
|
|
browser.find_element(By.ID, "submit-miner").click()
|
|
|
|
# 3. Verify miner registered
|
|
WebDriverWait(browser, 10).until(
|
|
EC.presence_of_element_located((By.ID, "miner-dashboard"))
|
|
)
|
|
assert "Miner Dashboard" in browser.page_source
|
|
|
|
# 4. Start miner daemon (simulated)
|
|
browser.find_element(By.ID, "start-miner").click()
|
|
|
|
# 5. Wait for job assignment
|
|
time.sleep(2) # Simulate waiting
|
|
|
|
# 6. Accept job
|
|
WebDriverWait(browser, 10).until(
|
|
EC.presence_of_element_located((By.CLASS_NAME, "job-assignment"))
|
|
)
|
|
browser.find_element(By.ID, "accept-job").click()
|
|
|
|
# 7. Execute job (simulated)
|
|
browser.find_element(By.ID, "execute-job").click()
|
|
|
|
# 8. Submit results
|
|
browser.find_element(By.ID, "result-input").send_keys("Generated poem about AI...")
|
|
browser.find_element(By.ID, "submit-result").click()
|
|
|
|
# 9. Verify job completed
|
|
WebDriverWait(browser, 10).until(
|
|
EC.presence_of_element_located((By.CLASS_NAME, "completion-status"))
|
|
)
|
|
assert "Completed" in browser.page_source
|
|
|
|
# 10. Check earnings
|
|
browser.find_element(By.ID, "earnings-tab").click()
|
|
assert browser.find_element(By.ID, "total-earnings").text != "0"
|
|
|
|
|
|
@pytest.mark.e2e
|
|
class TestWalletOperations:
|
|
"""Test wallet creation and operations"""
|
|
|
|
def test_wallet_creation_and_transactions(self, browser, base_url):
|
|
"""Test creating wallet and performing transactions"""
|
|
# 1. Login and navigate to wallet
|
|
browser.get(f"{base_url}/login")
|
|
browser.find_element(By.ID, "email").send_keys("wallet@example.com")
|
|
browser.find_element(By.ID, "password").send_keys("WalletPass123!")
|
|
browser.find_element(By.ID, "login-btn").click()
|
|
|
|
# 2. Go to wallet section
|
|
browser.find_element(By.ID, "wallet-link").click()
|
|
|
|
# 3. Create new wallet
|
|
browser.find_element(By.ID, "create-wallet").click()
|
|
browser.find_element(By.ID, "wallet-name").send_keys("My Test Wallet")
|
|
browser.find_element(By.ID, "create-wallet-btn").click()
|
|
|
|
# 4. Secure wallet (backup phrase)
|
|
WebDriverWait(browser, 10).until(
|
|
EC.presence_of_element_located((By.ID, "backup-phrase"))
|
|
)
|
|
phrase = browser.find_element(By.ID, "backup-phrase").text
|
|
assert len(phrase.split()) == 12 # 12-word mnemonic
|
|
|
|
# 5. Confirm backup
|
|
browser.find_element(By.ID, "confirm-backup").click()
|
|
|
|
# 6. View wallet address
|
|
address = browser.find_element(By.ID, "wallet-address").text
|
|
assert address.startswith("0x")
|
|
|
|
# 7. Fund wallet (testnet faucet)
|
|
browser.find_element(By.ID, "fund-wallet").click()
|
|
browser.find_element(By.ID, "request-funds").click()
|
|
|
|
# 8. Wait for funding
|
|
time.sleep(3)
|
|
|
|
# 9. Check balance
|
|
balance = browser.find_element(By.ID, "wallet-balance").text
|
|
assert float(balance) > 0
|
|
|
|
# 10. Send transaction
|
|
browser.find_element(By.ID, "send-btn").click()
|
|
browser.find_element(By.ID, "recipient").send_keys("0x1234567890abcdef")
|
|
browser.find_element(By.ID, "amount").send_keys("1.0")
|
|
browser.find_element(By.ID, "send-tx").click()
|
|
|
|
# 11. Confirm transaction
|
|
browser.find_element(By.ID, "confirm-send").click()
|
|
|
|
# 12. Verify transaction sent
|
|
WebDriverWait(browser, 10).until(
|
|
EC.presence_of_element_located((By.CLASS_NAME, "tx-success"))
|
|
)
|
|
assert "Transaction sent" in browser.page_source
|
|
|
|
|
|
@pytest.mark.e2e
|
|
class TestMarketplaceInteraction:
|
|
"""Test marketplace interactions"""
|
|
|
|
def test_service_provider_workflow(self, browser, base_url):
|
|
"""Test service provider listing and managing services"""
|
|
# 1. Login as provider
|
|
browser.get(f"{base_url}/login")
|
|
browser.find_element(By.ID, "email").send_keys("provider@example.com")
|
|
browser.find_element(By.ID, "password").send_keys("ProviderPass123!")
|
|
browser.find_element(By.ID, "login-btn").click()
|
|
|
|
# 2. Go to marketplace
|
|
browser.find_element(By.ID, "marketplace-link").click()
|
|
|
|
# 3. List new service
|
|
browser.find_element(By.ID, "list-service").click()
|
|
browser.find_element(By.ID, "service-name").send_keys("Premium AI Inference")
|
|
browser.find_element(By.ID, "service-desc").send_keys("High-performance AI inference with GPU acceleration")
|
|
|
|
# Set pricing
|
|
browser.find_element(By.ID, "price-per-token").send_keys("0.0001")
|
|
browser.find_element(By.ID, "price-per-minute").send_keys("0.05")
|
|
|
|
# Set capabilities
|
|
browser.find_element(By.ID, "capability-text").click()
|
|
browser.find_element(By.ID, "capability-image").click()
|
|
browser.find_element(By.ID, "capability-video").click()
|
|
|
|
browser.find_element(By.ID, "submit-service").click()
|
|
|
|
# 4. Verify service listed
|
|
WebDriverWait(browser, 10).until(
|
|
EC.presence_of_element_located((By.CLASS_NAME, "service-card"))
|
|
)
|
|
assert "Premium AI Inference" in browser.page_source
|
|
|
|
# 5. Receive booking notification
|
|
time.sleep(2) # Simulate booking
|
|
|
|
# 6. View bookings
|
|
browser.find_element(By.ID, "bookings-tab").click()
|
|
bookings = browser.find_elements(By.CLASS_NAME, "booking-item")
|
|
assert len(bookings) > 0
|
|
|
|
# 7. Accept booking
|
|
browser.find_element(By.ID, "accept-booking").click()
|
|
|
|
# 8. Mark as completed
|
|
browser.find_element(By.ID, "complete-booking").click()
|
|
browser.find_element(By.ID, "completion-notes").send_keys("Job completed successfully")
|
|
browser.find_element(By.ID, "submit-completion").click()
|
|
|
|
# 9. Receive payment
|
|
WebDriverWait(browser, 10).until(
|
|
EC.presence_of_element_located((By.ID, "payment-received"))
|
|
)
|
|
assert "Payment received" in browser.page_source
|
|
|
|
|
|
@pytest.mark.e2e
|
|
class TestMultiTenantScenario:
|
|
"""Test multi-tenant scenarios"""
|
|
|
|
def test_tenant_isolation(self, browser, base_url):
|
|
"""Test that tenant data is properly isolated"""
|
|
# 1. Login as Tenant A
|
|
browser.get(f"{base_url}/login")
|
|
browser.find_element(By.ID, "email").send_keys("tenant-a@example.com")
|
|
browser.find_element(By.ID, "password").send_keys("TenantAPass123!")
|
|
browser.find_element(By.ID, "login-btn").click()
|
|
|
|
# 2. Create jobs for Tenant A
|
|
for i in range(3):
|
|
browser.find_element(By.ID, "create-job").click()
|
|
browser.find_element(By.ID, "job-name").send_keys(f"Tenant A Job {i}")
|
|
browser.find_element(By.ID, "submit-job").click()
|
|
time.sleep(0.5)
|
|
|
|
# 3. Verify Tenant A sees only their jobs
|
|
jobs = browser.find_elements(By.CLASS_NAME, "job-item")
|
|
assert len(jobs) == 3
|
|
for job in jobs:
|
|
assert "Tenant A Job" in job.text
|
|
|
|
# 4. Logout
|
|
browser.find_element(By.ID, "logout").click()
|
|
|
|
# 5. Login as Tenant B
|
|
browser.find_element(By.ID, "email").send_keys("tenant-b@example.com")
|
|
browser.find_element(By.ID, "password").send_keys("TenantBPass123!")
|
|
browser.find_element(By.ID, "login-btn").click()
|
|
|
|
# 6. Verify Tenant B cannot see Tenant A's jobs
|
|
jobs = browser.find_elements(By.CLASS_NAME, "job-item")
|
|
assert len(jobs) == 0
|
|
|
|
# 7. Create job for Tenant B
|
|
browser.find_element(By.ID, "create-job").click()
|
|
browser.find_element(By.ID, "job-name").send_keys("Tenant B Job")
|
|
browser.find_element(By.ID, "submit-job").click()
|
|
|
|
# 8. Verify Tenant B sees only their job
|
|
jobs = browser.find_elements(By.CLASS_NAME, "job-item")
|
|
assert len(jobs) == 1
|
|
assert "Tenant B Job" in jobs[0].text
|
|
|
|
|
|
@pytest.mark.e2e
|
|
class TestErrorHandling:
|
|
"""Test error handling in user flows"""
|
|
|
|
def test_network_error_handling(self, browser, base_url):
|
|
"""Test handling of network errors"""
|
|
# 1. Start a job
|
|
browser.get(f"{base_url}/login")
|
|
browser.find_element(By.ID, "email").send_keys("user@example.com")
|
|
browser.find_element(By.ID, "password").send_keys("UserPass123!")
|
|
browser.find_element(By.ID, "login-btn").click()
|
|
|
|
browser.find_element(By.ID, "create-job").click()
|
|
browser.find_element(By.ID, "job-name").send_keys("Test Job")
|
|
browser.find_element(By.ID, "submit-job").click()
|
|
|
|
# 2. Simulate network error (disconnect network)
|
|
# In real test, would use network simulation tool
|
|
|
|
# 3. Try to update job
|
|
browser.find_element(By.ID, "edit-job").click()
|
|
browser.find_element(By.ID, "job-name").clear()
|
|
browser.find_element(By.ID, "job-name").send_keys("Updated Job")
|
|
browser.find_element(By.ID, "save-job").click()
|
|
|
|
# 4. Verify error message
|
|
WebDriverWait(browser, 10).until(
|
|
EC.presence_of_element_located((By.ID, "error-message"))
|
|
)
|
|
assert "Network error" in browser.page_source
|
|
|
|
# 5. Verify retry option
|
|
assert browser.find_element(By.ID, "retry-btn").is_displayed()
|
|
|
|
# 6. Retry after network restored
|
|
browser.find_element(By.ID, "retry-btn").click()
|
|
|
|
# 7. Verify success
|
|
WebDriverWait(browser, 10).until(
|
|
EC.presence_of_element_located((By.ID, "success-message"))
|
|
)
|
|
assert "Updated successfully" in browser.page_source
|
|
|
|
|
|
@pytest.mark.e2e
|
|
class TestMobileResponsiveness:
|
|
"""Test mobile responsiveness"""
|
|
|
|
def test_mobile_workflow(self, mobile_browser, base_url):
|
|
"""Test complete workflow on mobile device"""
|
|
# 1. Open on mobile
|
|
mobile_browser.get(f"{base_url}")
|
|
|
|
# 2. Verify mobile layout
|
|
assert mobile_browser.find_element(By.ID, "mobile-menu").is_displayed()
|
|
|
|
# 3. Navigate using mobile menu
|
|
mobile_browser.find_element(By.ID, "mobile-menu").click()
|
|
mobile_browser.find_element(By.ID, "mobile-jobs").click()
|
|
|
|
# 4. Create job on mobile
|
|
mobile_browser.find_element(By.ID, "mobile-create-job").click()
|
|
mobile_browser.find_element(By.ID, "job-type-mobile").send_keys("AI Inference")
|
|
mobile_browser.find_element(By.ID, "prompt-mobile").send_keys("Mobile test prompt")
|
|
mobile_browser.find_element(By.ID, "submit-mobile").click()
|
|
|
|
# 5. Verify job created
|
|
WebDriverWait(mobile_browser, 10).until(
|
|
EC.presence_of_element_located((By.CLASS_NAME, "mobile-job-card"))
|
|
)
|
|
|
|
# 6. Check mobile wallet
|
|
mobile_browser.find_element(By.ID, "mobile-menu").click()
|
|
mobile_browser.find_element(By.ID, "mobile-wallet").click()
|
|
|
|
# 7. Verify wallet balance displayed
|
|
assert mobile_browser.find_element(By.ID, "mobile-balance").is_displayed()
|
|
|
|
# 8. Send payment on mobile
|
|
mobile_browser.find_element(By.ID, "mobile-send").click()
|
|
mobile_browser.find_element(By.ID, "recipient-mobile").send_keys("0x123456")
|
|
mobile_browser.find_element(By.ID, "amount-mobile").send_keys("1.0")
|
|
mobile_browser.find_element(By.ID, "send-mobile").click()
|
|
|
|
# 9. Confirm with mobile PIN
|
|
mobile_browser.find_element(By.ID, "pin-1").click()
|
|
mobile_browser.find_element(By.ID, "pin-2").click()
|
|
mobile_browser.find_element(By.ID, "pin-3").click()
|
|
mobile_browser.find_element(By.ID, "pin-4").click()
|
|
|
|
# 10. Verify success
|
|
WebDriverWait(mobile_browser, 10).until(
|
|
EC.presence_of_element_located((By.ID, "mobile-success"))
|
|
)
|