""" 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()