""" Randomized Wait Utility for Realistic Test Behavior World-class utility to simulate realistic human behavior with randomized waits. Instead of hardcoded waits, uses intelligent random delays based on context. """ import random import time from typing import Optional class RandomizedWait: """Utility class for randomized, realistic waits""" # Wait ranges (in seconds) for different contexts WAIT_RANGES = { # Question answering - varies by question type 'question_answer': { 'rating_scale': (1, 4), # Quick selection: 1-4 seconds 'multiple_choice': (2, 6), # Reading options: 2-6 seconds 'true_false': (1, 3), # Binary choice: 1-3 seconds 'open_ended': (5, 15), # Typing response: 5-15 seconds 'matrix': (3, 8), # Multiple selections: 3-8 seconds 'default': (2, 5) # Default: 2-5 seconds }, # Navigation between questions 'question_navigation': { 'next': (1, 3), # Clicking next: 1-3 seconds 'previous': (1, 2), # Going back: 1-2 seconds 'default': (1, 2) # Default navigation: 1-2 seconds }, # Page/UI loading 'page_load': { 'initial': (2, 4), # Initial page load: 2-4 seconds 'navigation': (1, 3), # Navigation load: 1-3 seconds 'modal': (0.5, 1.5), # Modal appearance: 0.5-1.5 seconds 'default': (1, 2) # Default load: 1-2 seconds }, # Form interactions 'form_interaction': { 'input': (0.5, 1.5), # Text input: 0.5-1.5 seconds 'click': (0.3, 1), # Button click: 0.3-1 second 'select': (1, 2), # Dropdown select: 1-2 seconds 'default': (0.5, 1) # Default: 0.5-1 second }, # Submission and confirmation 'submission': { 'submit': (2, 4), # Submit action: 2-4 seconds 'confirm': (1, 2), # Confirmation: 1-2 seconds 'feedback': (3, 8), # Writing feedback: 3-8 seconds 'default': (1, 3) # Default: 1-3 seconds }, # Error recovery 'error_recovery': { 'retry': (1, 2), # Retry after error: 1-2 seconds 'wait': (2, 4), # Wait for state change: 2-4 seconds 'default': (1, 3) # Default: 1-3 seconds } } @staticmethod def wait_for_question_answer(question_type: str = 'default') -> float: """ Wait after answering a question (realistic thinking time) Args: question_type: Type of question (rating_scale, multiple_choice, etc.) Returns: float: Actual wait time used """ ranges = RandomizedWait.WAIT_RANGES['question_answer'] min_wait, max_wait = ranges.get(question_type, ranges['default']) wait_time = random.uniform(min_wait, max_wait) time.sleep(wait_time) return wait_time @staticmethod def wait_for_navigation(action: str = 'next') -> float: """ Wait after navigation action (page load time) Args: action: Navigation action (next, previous, etc.) Returns: float: Actual wait time used """ ranges = RandomizedWait.WAIT_RANGES['question_navigation'] min_wait, max_wait = ranges.get(action, ranges['default']) wait_time = random.uniform(min_wait, max_wait) time.sleep(wait_time) return wait_time @staticmethod def wait_for_page_load(load_type: str = 'default') -> float: """ Wait for page/UI to load Args: load_type: Type of load (initial, navigation, modal, etc.) Returns: float: Actual wait time used """ ranges = RandomizedWait.WAIT_RANGES['page_load'] min_wait, max_wait = ranges.get(load_type, ranges['default']) wait_time = random.uniform(min_wait, max_wait) time.sleep(wait_time) return wait_time @staticmethod def wait_for_form_interaction(interaction_type: str = 'default') -> float: """ Wait for form interaction (click, input, select) Args: interaction_type: Type of interaction (input, click, select, etc.) Returns: float: Actual wait time used """ ranges = RandomizedWait.WAIT_RANGES['form_interaction'] min_wait, max_wait = ranges.get(interaction_type, ranges['default']) wait_time = random.uniform(min_wait, max_wait) time.sleep(wait_time) return wait_time @staticmethod def wait_for_submission(action: str = 'default') -> float: """ Wait for submission-related actions Args: action: Submission action (submit, confirm, feedback, etc.) Returns: float: Actual wait time used """ ranges = RandomizedWait.WAIT_RANGES['submission'] min_wait, max_wait = ranges.get(action, ranges['default']) wait_time = random.uniform(min_wait, max_wait) time.sleep(wait_time) return wait_time @staticmethod def wait_for_error_recovery(recovery_type: str = 'default') -> float: """ Wait for error recovery Args: recovery_type: Type of recovery (retry, wait, etc.) Returns: float: Actual wait time used """ ranges = RandomizedWait.WAIT_RANGES['error_recovery'] min_wait, max_wait = ranges.get(recovery_type, ranges['default']) wait_time = random.uniform(min_wait, max_wait) time.sleep(wait_time) return wait_time @staticmethod def random_wait(min_seconds: float, max_seconds: float) -> float: """ Generic random wait between min and max seconds Args: min_seconds: Minimum wait time max_seconds: Maximum wait time Returns: float: Actual wait time used """ wait_time = random.uniform(min_seconds, max_seconds) time.sleep(wait_time) return wait_time @staticmethod def smart_wait(context: str, sub_context: Optional[str] = None) -> float: """ Smart wait that automatically selects appropriate wait range based on context Args: context: Main context (question_answer, navigation, page_load, etc.) sub_context: Sub-context (question_type, action_type, etc.) Returns: float: Actual wait time used """ if context not in RandomizedWait.WAIT_RANGES: context = 'page_load' # Default fallback ranges = RandomizedWait.WAIT_RANGES[context] if sub_context and sub_context in ranges: min_wait, max_wait = ranges[sub_context] else: min_wait, max_wait = ranges['default'] wait_time = random.uniform(min_wait, max_wait) time.sleep(wait_time) return wait_time