gateway/tool_test01ui.py
2025-06-02 23:12:24 +02:00

926 lines
No EOL
34 KiB
Python

"""
UI Test Procedure for PowerOn Frontend
Tests CRUD operations, user registration, authentication, and access control
"""
import os
import sys
import json
import logging
from datetime import datetime
from typing import Dict, List, Any
import requests
from dataclasses import dataclass
from enum import Enum
import time
# Configure logging
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s',
handlers=[
logging.FileHandler('ui_test_report.log'),
logging.StreamHandler(sys.stdout)
]
)
logger = logging.getLogger(__name__)
# Test configuration
BASE_URL = "http://localhost:8080" # Adjust based on your frontend URL
API_URL = "http://localhost:8000" # Adjust based on your backend URL
class UserRole(Enum):
SYSADMIN = "sysadmin"
ADMIN = "admin"
USER = "user"
@dataclass
class TestResult:
test_name: str
success: bool
message: str
details: Dict[str, Any] = None
@dataclass
class TestReport:
timestamp: str
total_tests: int
passed_tests: int
failed_tests: int
results: List[TestResult]
bugs_found: List[Dict[str, str]]
required_adaptations: List[Dict[str, str]]
class UITestSuite:
def __init__(self):
self.session = requests.Session()
self.test_results = []
self.bugs_found = []
self.required_adaptations = []
self.current_user = None
self.current_role = None
def run_all_tests(self):
"""Run all test categories"""
logger.info("Starting UI Test Suite")
# Test user registration and authentication
self.test_user_registration()
self.test_user_authentication()
# Test CRUD operations for each module
self.test_files_module()
self.test_mandates_module()
self.test_prompts_module()
self.test_users_module()
# Generate and save report
self.generate_report()
def test_user_registration(self):
"""Test user registration for different roles"""
logger.info("Testing User Registration")
test_users = [
{"username": "test_sysadmin", "password": "Test123!", "role": UserRole.SYSADMIN},
{"username": "test_admin", "password": "Test123!", "role": UserRole.ADMIN},
{"username": "test_user", "password": "Test123!", "role": UserRole.USER}
]
for user in test_users:
try:
# Create userData object matching User model
user_data = {
"username": user["username"],
"email": f"{user['username']}@test.com",
"fullName": f"Test {user['role'].value}",
"language": "en",
"enabled": True,
"privilege": user["role"].value,
"authenticationAuthority": "local",
"mandateId": None, # Will be set by the backend
"connections": []
}
response = self.session.post(
f"{API_URL}/api/local/register",
json={
"userData": user_data,
"password": user["password"]
},
headers={
"X-CSRF-Token": "test-csrf-token",
"Content-Type": "application/json"
}
)
if response.status_code == 200:
logger.info(f"Successfully registered {user['role'].value} user")
self.test_results.append(TestResult(
f"Register {user['role'].value}",
True,
f"Successfully registered {user['role'].value} user"
))
else:
error_msg = f"Failed to register {user['role'].value} user: {response.status_code}"
if response.text:
error_msg += f" - {response.text}"
logger.error(error_msg)
self.test_results.append(TestResult(
f"Register {user['role'].value}",
False,
error_msg,
{"status_code": response.status_code, "response": response.text}
))
except Exception as e:
error_msg = f"Exception during registration: {str(e)}"
logger.error(error_msg)
self.test_results.append(TestResult(
f"Register {user['role'].value}",
False,
error_msg
))
def test_user_authentication(self):
"""Test login and logout for different roles"""
logger.info("Testing User Authentication")
test_users = [
{"username": "test_sysadmin", "password": "Test123!", "role": UserRole.SYSADMIN},
{"username": "test_admin", "password": "Test123!", "role": UserRole.ADMIN},
{"username": "test_user", "password": "Test123!", "role": UserRole.USER}
]
for user in test_users:
# Test login
try:
response = self.session.post(
f"{API_URL}/api/local/login",
data={
"username": user["username"],
"password": user["password"]
},
headers={
"X-CSRF-Token": "test-csrf-token" # Add CSRF token
}
)
if response.status_code == 200:
self.test_results.append(TestResult(
f"Login {user['role'].value}",
True,
f"Successfully logged in as {user['role'].value}"
))
# Test logout
logout_response = self.session.post(f"{API_URL}/api/security/local/logout")
if logout_response.status_code == 200:
self.test_results.append(TestResult(
f"Logout {user['role'].value}",
True,
f"Successfully logged out as {user['role'].value}"
))
else:
self.test_results.append(TestResult(
f"Logout {user['role'].value}",
False,
f"Failed to logout as {user['role'].value}"
))
else:
self.test_results.append(TestResult(
f"Login {user['role'].value}",
False,
f"Failed to login as {user['role'].value}"
))
except Exception as e:
self.test_results.append(TestResult(
f"Login {user['role'].value}",
False,
f"Exception during login: {str(e)}"
))
def test_files_module(self):
"""Test CRUD operations for files module"""
logger.info("Testing Files Module")
# Test for each role
for role in UserRole:
self.current_role = role
self._login_as_role(role)
# Test view files
self._test_view_files()
# Test create file
self._test_create_file()
# Test modify file
self._test_modify_file()
# Test delete file
self._test_delete_file()
self._logout()
def test_mandates_module(self):
"""Test CRUD operations for mandates module"""
logger.info("Testing Mandates Module")
for role in UserRole:
self.current_role = role
self._login_as_role(role)
# Test view mandates
self._test_view_mandates()
# Test create mandate
self._test_create_mandate()
# Test modify mandate
self._test_modify_mandate()
# Test delete mandate
self._test_delete_mandate()
self._logout()
def test_prompts_module(self):
"""Test CRUD operations for prompts module"""
logger.info("Testing Prompts Module")
for role in UserRole:
self.current_role = role
self._login_as_role(role)
# Test view prompts
self._test_view_prompts()
# Test create prompt
self._test_create_prompt()
# Test modify prompt
self._test_modify_prompt()
# Test delete prompt
self._test_delete_prompt()
self._logout()
def test_users_module(self):
"""Test CRUD operations for users module"""
logger.info("Testing Users Module")
for role in UserRole:
self.current_role = role
self._login_as_role(role)
# Test view users
self._test_view_users()
# Test create user
self._test_create_user()
# Test modify user
self._test_modify_user()
# Test delete user
self._test_delete_user()
self._logout()
def _login_as_role(self, role: UserRole):
"""Helper method to login as a specific role"""
username = f"test_{role.value}"
max_retries = 3
retry_delay = 12 # 12 seconds delay between retries (to stay under 5 per minute)
for attempt in range(max_retries):
try:
# Always wait before attempting login
if attempt == 0:
logger.info(f"Waiting {retry_delay}s before first login attempt for {role.value}")
else:
logger.info(f"Rate limit reached, waiting {retry_delay}s before retry {attempt + 1} for {role.value} login")
time.sleep(retry_delay)
response = self.session.post(
f"{API_URL}/api/local/login",
data={
"username": username,
"password": "Test123!"
},
headers={
"X-CSRF-Token": "test-csrf-token"
}
)
if response.status_code == 200:
self.current_user = response.json()
logger.info(f"Successfully logged in as {role.value}")
return
elif response.status_code == 429:
logger.info(f"Rate limit reached for {role.value} login: {response.text}")
if attempt < max_retries - 1:
continue
else:
logger.error(f"Max retries reached for {role.value} login after rate limits")
raise Exception(f"Max retries reached for {role.value} login after rate limits")
else:
error_msg = f"Failed to login as {role.value}: {response.status_code}"
if response.text:
error_msg += f" - {response.text}"
logger.error(error_msg)
raise Exception(error_msg)
except Exception as e:
if attempt == max_retries - 1:
logger.error(f"Login error for {role.value} after {max_retries} attempts: {str(e)}")
raise
continue
def _logout(self):
"""Helper method to logout"""
self.session.post(f"{API_URL}/api/security/local/logout")
self.current_user = None
def _test_view_files(self):
"""Test viewing files"""
try:
response = self.session.get(f"{API_URL}/api/files")
if response.status_code == 200:
self.test_results.append(TestResult(
f"View Files as {self.current_role.value}",
True,
"Successfully viewed files"
))
else:
self.test_results.append(TestResult(
f"View Files as {self.current_role.value}",
False,
f"Failed to view files: {response.status_code}"
))
except Exception as e:
self.test_results.append(TestResult(
f"View Files as {self.current_role.value}",
False,
f"Exception viewing files: {str(e)}"
))
def _test_create_file(self):
"""Test creating a file"""
try:
# Create a test file
test_file = {
"name": f"test_file_{self.current_role.value}",
"content": "Test content",
"type": "text/plain"
}
response = self.session.post(
f"{API_URL}/api/files",
json=test_file
)
if response.status_code == 200:
self.test_results.append(TestResult(
f"Create File as {self.current_role.value}",
True,
"Successfully created file"
))
else:
self.test_results.append(TestResult(
f"Create File as {self.current_role.value}",
False,
f"Failed to create file: {response.status_code}"
))
except Exception as e:
self.test_results.append(TestResult(
f"Create File as {self.current_role.value}",
False,
f"Exception creating file: {str(e)}"
))
def _test_modify_file(self):
"""Test modifying a file"""
try:
# First get a file to modify
files_response = self.session.get(f"{API_URL}/api/files")
if files_response.status_code == 200 and files_response.json():
file_id = files_response.json()[0]["id"]
# Modify the file
update_data = {
"name": f"modified_file_{self.current_role.value}",
"content": "Modified content"
}
response = self.session.put(
f"{API_URL}/api/files/{file_id}",
json=update_data
)
if response.status_code == 200:
self.test_results.append(TestResult(
f"Modify File as {self.current_role.value}",
True,
"Successfully modified file"
))
else:
self.test_results.append(TestResult(
f"Modify File as {self.current_role.value}",
False,
f"Failed to modify file: {response.status_code}"
))
else:
self.test_results.append(TestResult(
f"Modify File as {self.current_role.value}",
False,
"No files available to modify"
))
except Exception as e:
self.test_results.append(TestResult(
f"Modify File as {self.current_role.value}",
False,
f"Exception modifying file: {str(e)}"
))
def _test_delete_file(self):
"""Test deleting a file"""
try:
# First get a file to delete
files_response = self.session.get(f"{API_URL}/api/files")
if files_response.status_code == 200 and files_response.json():
file_id = files_response.json()[0]["id"]
response = self.session.delete(f"{API_URL}/api/files/{file_id}")
if response.status_code == 200:
self.test_results.append(TestResult(
f"Delete File as {self.current_role.value}",
True,
"Successfully deleted file"
))
else:
self.test_results.append(TestResult(
f"Delete File as {self.current_role.value}",
False,
f"Failed to delete file: {response.status_code}"
))
else:
self.test_results.append(TestResult(
f"Delete File as {self.current_role.value}",
False,
"No files available to delete"
))
except Exception as e:
self.test_results.append(TestResult(
f"Delete File as {self.current_role.value}",
False,
f"Exception deleting file: {str(e)}"
))
def _test_view_mandates(self):
"""Test viewing mandates"""
try:
response = self.session.get(f"{API_URL}/api/mandates")
if response.status_code == 200:
self.test_results.append(TestResult(
f"View Mandates as {self.current_role.value}",
True,
"Successfully viewed mandates"
))
else:
self.test_results.append(TestResult(
f"View Mandates as {self.current_role.value}",
False,
f"Failed to view mandates: {response.status_code}"
))
except Exception as e:
self.test_results.append(TestResult(
f"View Mandates as {self.current_role.value}",
False,
f"Exception viewing mandates: {str(e)}"
))
def _test_create_mandate(self):
"""Test creating a mandate"""
try:
test_mandate = {
"name": f"test_mandate_{self.current_role.value}",
"description": "Test mandate",
"enabled": True
}
response = self.session.post(
f"{API_URL}/api/mandates",
json=test_mandate
)
if response.status_code == 200:
self.test_results.append(TestResult(
f"Create Mandate as {self.current_role.value}",
True,
"Successfully created mandate"
))
else:
self.test_results.append(TestResult(
f"Create Mandate as {self.current_role.value}",
False,
f"Failed to create mandate: {response.status_code}"
))
except Exception as e:
self.test_results.append(TestResult(
f"Create Mandate as {self.current_role.value}",
False,
f"Exception creating mandate: {str(e)}"
))
def _test_modify_mandate(self):
"""Test modifying a mandate"""
try:
# First get a mandate to modify
mandates_response = self.session.get(f"{API_URL}/api/mandates")
if mandates_response.status_code == 200 and mandates_response.json():
mandate_id = mandates_response.json()[0]["id"]
update_data = {
"name": f"modified_mandate_{self.current_role.value}",
"description": "Modified mandate"
}
response = self.session.put(
f"{API_URL}/api/mandates/{mandate_id}",
json=update_data
)
if response.status_code == 200:
self.test_results.append(TestResult(
f"Modify Mandate as {self.current_role.value}",
True,
"Successfully modified mandate"
))
else:
self.test_results.append(TestResult(
f"Modify Mandate as {self.current_role.value}",
False,
f"Failed to modify mandate: {response.status_code}"
))
else:
self.test_results.append(TestResult(
f"Modify Mandate as {self.current_role.value}",
False,
"No mandates available to modify"
))
except Exception as e:
self.test_results.append(TestResult(
f"Modify Mandate as {self.current_role.value}",
False,
f"Exception modifying mandate: {str(e)}"
))
def _test_delete_mandate(self):
"""Test deleting a mandate"""
try:
# First get a mandate to delete
mandates_response = self.session.get(f"{API_URL}/api/mandates")
if mandates_response.status_code == 200 and mandates_response.json():
mandate_id = mandates_response.json()[0]["id"]
response = self.session.delete(f"{API_URL}/api/mandates/{mandate_id}")
if response.status_code == 200:
self.test_results.append(TestResult(
f"Delete Mandate as {self.current_role.value}",
True,
"Successfully deleted mandate"
))
else:
self.test_results.append(TestResult(
f"Delete Mandate as {self.current_role.value}",
False,
f"Failed to delete mandate: {response.status_code}"
))
else:
self.test_results.append(TestResult(
f"Delete Mandate as {self.current_role.value}",
False,
"No mandates available to delete"
))
except Exception as e:
self.test_results.append(TestResult(
f"Delete Mandate as {self.current_role.value}",
False,
f"Exception deleting mandate: {str(e)}"
))
def _test_view_prompts(self):
"""Test viewing prompts"""
try:
response = self.session.get(f"{API_URL}/api/prompts")
if response.status_code == 200:
self.test_results.append(TestResult(
f"View Prompts as {self.current_role.value}",
True,
"Successfully viewed prompts"
))
else:
self.test_results.append(TestResult(
f"View Prompts as {self.current_role.value}",
False,
f"Failed to view prompts: {response.status_code}"
))
except Exception as e:
self.test_results.append(TestResult(
f"View Prompts as {self.current_role.value}",
False,
f"Exception viewing prompts: {str(e)}"
))
def _test_create_prompt(self):
"""Test creating a prompt"""
try:
test_prompt = {
"name": f"test_prompt_{self.current_role.value}",
"content": "Test prompt content",
"category": "test"
}
response = self.session.post(
f"{API_URL}/api/prompts",
json=test_prompt
)
if response.status_code == 200:
self.test_results.append(TestResult(
f"Create Prompt as {self.current_role.value}",
True,
"Successfully created prompt"
))
else:
self.test_results.append(TestResult(
f"Create Prompt as {self.current_role.value}",
False,
f"Failed to create prompt: {response.status_code}"
))
except Exception as e:
self.test_results.append(TestResult(
f"Create Prompt as {self.current_role.value}",
False,
f"Exception creating prompt: {str(e)}"
))
def _test_modify_prompt(self):
"""Test modifying a prompt"""
try:
# First get a prompt to modify
prompts_response = self.session.get(f"{API_URL}/api/prompts")
if prompts_response.status_code == 200 and prompts_response.json():
prompt_id = prompts_response.json()[0]["id"]
update_data = {
"name": f"modified_prompt_{self.current_role.value}",
"content": "Modified prompt content"
}
response = self.session.put(
f"{API_URL}/api/prompts/{prompt_id}",
json=update_data
)
if response.status_code == 200:
self.test_results.append(TestResult(
f"Modify Prompt as {self.current_role.value}",
True,
"Successfully modified prompt"
))
else:
self.test_results.append(TestResult(
f"Modify Prompt as {self.current_role.value}",
False,
f"Failed to modify prompt: {response.status_code}"
))
else:
self.test_results.append(TestResult(
f"Modify Prompt as {self.current_role.value}",
False,
"No prompts available to modify"
))
except Exception as e:
self.test_results.append(TestResult(
f"Modify Prompt as {self.current_role.value}",
False,
f"Exception modifying prompt: {str(e)}"
))
def _test_delete_prompt(self):
"""Test deleting a prompt"""
try:
# First get a prompt to delete
prompts_response = self.session.get(f"{API_URL}/api/prompts")
if prompts_response.status_code == 200 and prompts_response.json():
prompt_id = prompts_response.json()[0]["id"]
response = self.session.delete(f"{API_URL}/api/prompts/{prompt_id}")
if response.status_code == 200:
self.test_results.append(TestResult(
f"Delete Prompt as {self.current_role.value}",
True,
"Successfully deleted prompt"
))
else:
self.test_results.append(TestResult(
f"Delete Prompt as {self.current_role.value}",
False,
f"Failed to delete prompt: {response.status_code}"
))
else:
self.test_results.append(TestResult(
f"Delete Prompt as {self.current_role.value}",
False,
"No prompts available to delete"
))
except Exception as e:
self.test_results.append(TestResult(
f"Delete Prompt as {self.current_role.value}",
False,
f"Exception deleting prompt: {str(e)}"
))
def _test_view_users(self):
"""Test viewing users"""
try:
response = self.session.get(f"{API_URL}/api/users")
if response.status_code == 200:
self.test_results.append(TestResult(
f"View Users as {self.current_role.value}",
True,
"Successfully viewed users"
))
else:
self.test_results.append(TestResult(
f"View Users as {self.current_role.value}",
False,
f"Failed to view users: {response.status_code}"
))
except Exception as e:
self.test_results.append(TestResult(
f"View Users as {self.current_role.value}",
False,
f"Exception viewing users: {str(e)}"
))
def _test_create_user(self):
"""Test creating a user"""
try:
test_user = {
"username": f"new_user_{self.current_role.value}",
"password": "Test123!",
"email": f"new_user_{self.current_role.value}@test.com",
"privilege": "user"
}
response = self.session.post(
f"{API_URL}/api/users",
json=test_user
)
if response.status_code == 200:
self.test_results.append(TestResult(
f"Create User as {self.current_role.value}",
True,
"Successfully created user"
))
else:
self.test_results.append(TestResult(
f"Create User as {self.current_role.value}",
False,
f"Failed to create user: {response.status_code}"
))
except Exception as e:
self.test_results.append(TestResult(
f"Create User as {self.current_role.value}",
False,
f"Exception creating user: {str(e)}"
))
def _test_modify_user(self):
"""Test modifying a user"""
try:
# First get a user to modify
users_response = self.session.get(f"{API_URL}/api/users")
if users_response.status_code == 200 and users_response.json():
user_id = users_response.json()[0]["id"]
update_data = {
"username": f"modified_user_{self.current_role.value}",
"email": f"modified_user_{self.current_role.value}@test.com"
}
response = self.session.put(
f"{API_URL}/api/users/{user_id}",
json=update_data
)
if response.status_code == 200:
self.test_results.append(TestResult(
f"Modify User as {self.current_role.value}",
True,
"Successfully modified user"
))
else:
self.test_results.append(TestResult(
f"Modify User as {self.current_role.value}",
False,
f"Failed to modify user: {response.status_code}"
))
else:
self.test_results.append(TestResult(
f"Modify User as {self.current_role.value}",
False,
"No users available to modify"
))
except Exception as e:
self.test_results.append(TestResult(
f"Modify User as {self.current_role.value}",
False,
f"Exception modifying user: {str(e)}"
))
def _test_delete_user(self):
"""Test deleting a user"""
try:
# First get a user to delete
users_response = self.session.get(f"{API_URL}/api/users")
if users_response.status_code == 200 and users_response.json():
user_id = users_response.json()[0]["id"]
response = self.session.delete(f"{API_URL}/api/users/{user_id}")
if response.status_code == 200:
self.test_results.append(TestResult(
f"Delete User as {self.current_role.value}",
True,
"Successfully deleted user"
))
else:
self.test_results.append(TestResult(
f"Delete User as {self.current_role.value}",
False,
f"Failed to delete user: {response.status_code}"
))
else:
self.test_results.append(TestResult(
f"Delete User as {self.current_role.value}",
False,
"No users available to delete"
))
except Exception as e:
self.test_results.append(TestResult(
f"Delete User as {self.current_role.value}",
False,
f"Exception deleting user: {str(e)}"
))
def generate_report(self):
"""Generate test report"""
# Convert TestResult objects to dictionaries
serialized_results = [
{
"test_name": r.test_name,
"success": r.success,
"message": r.message,
"details": r.details
}
for r in self.test_results
]
report = {
"timestamp": datetime.now().isoformat(),
"total_tests": len(self.test_results),
"passed_tests": sum(1 for r in self.test_results if r.success),
"failed_tests": sum(1 for r in self.test_results if not r.success),
"results": serialized_results,
"bugs_found": self.bugs_found,
"required_adaptations": self.required_adaptations
}
# Save report to file
with open('ui_test_report.json', 'w') as f:
json.dump(report, f, indent=2)
# Print summary
logger.info(f"""
Test Report Summary:
-------------------
Total Tests: {report['total_tests']}
Passed: {report['passed_tests']}
Failed: {report['failed_tests']}
Bugs Found: {len(report['bugs_found'])}
Required Adaptations: {len(report['required_adaptations'])}
""")
if __name__ == "__main__":
test_suite = UITestSuite()
test_suite.run_all_tests()