Initial working version
This commit is contained in:
commit
ec1c5958ce
33 changed files with 4547 additions and 0 deletions
8
tests/__init__.py
Normal file
8
tests/__init__.py
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
"""
|
||||
Tests package initialization - adds the project root to the Python path
|
||||
"""
|
||||
import os
|
||||
import sys
|
||||
|
||||
# Add the parent directory to Python's path so 'src' module can be found
|
||||
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
|
||||
88
tests/test_auth.py
Normal file
88
tests/test_auth.py
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
"""
|
||||
Test script to verify the new Twitch API authentication
|
||||
"""
|
||||
import os
|
||||
import sys
|
||||
import logging
|
||||
from dotenv import load_dotenv
|
||||
|
||||
load_dotenv()
|
||||
|
||||
# Configure logging
|
||||
logging.basicConfig(level=logging.INFO, format='%(asctime)s [%(levelname)s] %(message)s')
|
||||
logger = logging.getLogger('auth-test')
|
||||
|
||||
def test_twitch_auth():
|
||||
"""Test the Twitch authentication with client credentials flow"""
|
||||
# Check for required libraries
|
||||
try:
|
||||
import requests
|
||||
except ImportError:
|
||||
logger.error("The 'requests' library is required. Install it with: pip install requests")
|
||||
return False
|
||||
|
||||
try:
|
||||
from src.core.auth import TwitchAuth
|
||||
except ImportError:
|
||||
logger.error("Failed to import TwitchAuth from src.core.auth")
|
||||
return False
|
||||
|
||||
# Get credentials from environment variables
|
||||
client_id = os.environ.get("TWITCH_CLIENT_ID")
|
||||
client_secret = os.environ.get("TWITCH_CLIENT_SECRET")
|
||||
|
||||
if not client_id or not client_secret:
|
||||
logger.error("TWITCH_CLIENT_ID and TWITCH_CLIENT_SECRET environment variables must be set")
|
||||
logger.info("You can get these from https://dev.twitch.tv/console/apps")
|
||||
return False
|
||||
|
||||
# Try to get a token using the TwitchAuth class
|
||||
logger.info("Attempting to get Twitch OAuth token...")
|
||||
|
||||
try:
|
||||
auth = TwitchAuth(client_id, client_secret)
|
||||
oauth_token = auth.get_oauth_token()
|
||||
|
||||
if not oauth_token or not auth.access_token:
|
||||
logger.error("Failed to get token using TwitchAuth")
|
||||
return False
|
||||
|
||||
logger.info("Successfully obtained access token!")
|
||||
if auth.token_expiry:
|
||||
expiry_hours = (auth.token_expiry - time.time()) / 3600
|
||||
logger.info(f"Token expires in: {expiry_hours:.1f} hours")
|
||||
|
||||
# Validate the token by making a simple API call
|
||||
logger.info("Validating token with a simple API call...")
|
||||
|
||||
headers = {
|
||||
'Client-ID': client_id,
|
||||
'Authorization': f"Bearer {auth.access_token}"
|
||||
}
|
||||
|
||||
# Get top games as a test
|
||||
response = requests.get('https://api.twitch.tv/helix/games/top', headers=headers)
|
||||
|
||||
if response.status_code == 200:
|
||||
games = response.json().get('data', [])
|
||||
logger.info(f"API call successful! Retrieved {len(games)} top games.")
|
||||
if games:
|
||||
logger.info(f"Top game: {games[0]['name']}")
|
||||
return True
|
||||
else:
|
||||
logger.error(f"API call failed: {response.status_code} - {response.text}")
|
||||
return False
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Error during authentication: {e}")
|
||||
return False
|
||||
|
||||
if __name__ == "__main__":
|
||||
import time
|
||||
print("Testing Twitch API authentication...")
|
||||
if test_twitch_auth():
|
||||
print("Authentication test PASSED!")
|
||||
sys.exit(0)
|
||||
else:
|
||||
print("Authentication test FAILED!")
|
||||
sys.exit(1)
|
||||
34
tests/test_controller.py
Normal file
34
tests/test_controller.py
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
import traceback
|
||||
import sys
|
||||
import os
|
||||
|
||||
print("Starting controller test...")
|
||||
|
||||
try:
|
||||
import sdl2
|
||||
print("SDL2 imported successfully")
|
||||
except ImportError as e:
|
||||
print(f"Failed to import SDL2: {e}")
|
||||
sys.exit(1)
|
||||
|
||||
try:
|
||||
from src.game.input.gamepad import VirtualController
|
||||
print("Controller support module imported successfully")
|
||||
except Exception as e:
|
||||
print(f"Failed to import controller support module: {e}")
|
||||
traceback.print_exc()
|
||||
sys.exit(1)
|
||||
|
||||
try:
|
||||
print("Creating VirtualController...")
|
||||
controller = VirtualController()
|
||||
print("VirtualController created successfully")
|
||||
|
||||
print(f"Controller available: {controller.is_available()}")
|
||||
print(f"Physical controller available: {controller.is_physical_controller_available()}")
|
||||
|
||||
print("Test completed successfully!")
|
||||
except Exception as e:
|
||||
print(f"Error during testing: {e}")
|
||||
traceback.print_exc()
|
||||
sys.exit(1)
|
||||
37
tests/test_controller_redirect.py
Normal file
37
tests/test_controller_redirect.py
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
import time
|
||||
import traceback
|
||||
import sys
|
||||
|
||||
print("Starting controller redirection test...")
|
||||
|
||||
try:
|
||||
from src.game.input.gamepad import VirtualController
|
||||
print("Controller support module imported successfully")
|
||||
|
||||
controller = VirtualController()
|
||||
print(f"Controller available: {controller.is_available()}")
|
||||
print(f"Physical controller available: {controller.is_physical_controller_available()}")
|
||||
|
||||
if controller.is_physical_controller_available():
|
||||
print("Testing controller redirection...")
|
||||
|
||||
# Start redirection
|
||||
success = controller.start_controller_redirection()
|
||||
print(f"Redirection started: {success}")
|
||||
|
||||
if success:
|
||||
# Let it run for a few seconds
|
||||
print("Redirection active for 5 seconds. Try using your physical controller...")
|
||||
for i in range(5, 0, -1):
|
||||
print(f"{i}...")
|
||||
time.sleep(1)
|
||||
|
||||
# Stop redirection
|
||||
controller.stop_controller_redirection()
|
||||
print("Redirection stopped")
|
||||
|
||||
print("Test completed successfully!")
|
||||
except Exception as e:
|
||||
print(f"Error during testing: {e}")
|
||||
traceback.print_exc()
|
||||
sys.exit(1)
|
||||
50
tests/test_game_controls.py
Normal file
50
tests/test_game_controls.py
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
import time
|
||||
import traceback
|
||||
import sys
|
||||
|
||||
print("Starting game control test...")
|
||||
|
||||
try:
|
||||
from src.game.input.gamepad import VirtualController
|
||||
print("Controller support module imported successfully")
|
||||
|
||||
controller = VirtualController()
|
||||
print(f"Controller available: {controller.is_available()}")
|
||||
|
||||
if controller.is_available():
|
||||
print("Testing basic controller actions...")
|
||||
|
||||
# Test some basic controller actions
|
||||
print("Pressing A button")
|
||||
controller.press_a()
|
||||
time.sleep(0.5)
|
||||
|
||||
print("Pressing B button")
|
||||
controller.press_b()
|
||||
time.sleep(0.5)
|
||||
|
||||
print("Moving left stick up")
|
||||
controller.move_left_stick_up()
|
||||
time.sleep(0.5)
|
||||
|
||||
print("Moving right stick right")
|
||||
controller.move_right_stick_right()
|
||||
time.sleep(0.5)
|
||||
|
||||
print("Pressing left trigger")
|
||||
controller.press_left_trigger()
|
||||
time.sleep(0.5)
|
||||
|
||||
print("Pressing D-pad up")
|
||||
controller.press_dpad_up()
|
||||
time.sleep(0.5)
|
||||
|
||||
# Reset controller at the end
|
||||
controller.reset()
|
||||
print("Controller reset")
|
||||
|
||||
print("Test completed successfully!")
|
||||
except Exception as e:
|
||||
print(f"Error during testing: {e}")
|
||||
traceback.print_exc()
|
||||
sys.exit(1)
|
||||
162
tests/test_token_cache.py
Normal file
162
tests/test_token_cache.py
Normal file
|
|
@ -0,0 +1,162 @@
|
|||
"""
|
||||
Test script to verify token caching functionality
|
||||
"""
|
||||
import os
|
||||
import sys
|
||||
import logging
|
||||
import time
|
||||
import json
|
||||
from dotenv import load_dotenv
|
||||
|
||||
# Add the parent directory to Python's path so 'src' module can be found
|
||||
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
|
||||
|
||||
# Load environment variables from .env file
|
||||
load_dotenv()
|
||||
|
||||
# Configure logging
|
||||
logging.basicConfig(level=logging.INFO, format='%(asctime)s [%(levelname)s] %(message)s')
|
||||
logger = logging.getLogger('token-cache-test')
|
||||
|
||||
def test_token_cache(cache_file: str = "test_token_cache.json") -> bool:
|
||||
"""Test the token caching functionality"""
|
||||
try:
|
||||
import requests
|
||||
except ImportError:
|
||||
logger.error("The 'requests' library is required. Install it with: pip install requests")
|
||||
return False
|
||||
|
||||
# Import the bot class
|
||||
from src.core.twitch import TwitchBot
|
||||
from src.core.auth import TwitchAuth
|
||||
|
||||
# Get credentials from environment variables
|
||||
client_id = os.environ.get("TWITCH_CLIENT_ID")
|
||||
client_secret = os.environ.get("TWITCH_CLIENT_SECRET")
|
||||
username = os.environ.get("TWITCH_USERNAME")
|
||||
channel = os.environ.get("TWITCH_CHANNEL")
|
||||
|
||||
if not all([client_id, client_secret, username, channel]):
|
||||
logger.error("Missing required environment variables")
|
||||
logger.info("Please set TWITCH_CLIENT_ID, TWITCH_CLIENT_SECRET, TWITCH_USERNAME, and TWITCH_CHANNEL")
|
||||
return False
|
||||
|
||||
# Remove the cache file if it exists (to start fresh)
|
||||
if os.path.exists(cache_file):
|
||||
logger.info(f"Removing existing cache file: {cache_file}")
|
||||
os.remove(cache_file)
|
||||
|
||||
# Use mock tokens for testing
|
||||
mock_access_token = "mock_access_token_for_testing"
|
||||
mock_refresh_token = "mock_refresh_token_for_testing"
|
||||
mock_expires_in = 14400 # 4 hours
|
||||
|
||||
# Create a bot instance with the test cache file
|
||||
logger.info("Creating bot instance...")
|
||||
bot = TwitchBot(
|
||||
username=username,
|
||||
client_id=client_id,
|
||||
client_secret=client_secret,
|
||||
channel=channel,
|
||||
access_token=mock_access_token,
|
||||
refresh_token=mock_refresh_token,
|
||||
token_cache_file=cache_file
|
||||
)
|
||||
|
||||
# First call should use the provided token and save it
|
||||
logger.info("First call to get_oauth_token (should use the provided token)...")
|
||||
oauth_token1 = bot.get_oauth_token()
|
||||
|
||||
# Verify the cache file was created
|
||||
if not os.path.exists(cache_file):
|
||||
logger.error(f"Cache file was not created: {cache_file}")
|
||||
return False
|
||||
|
||||
# Load and display cache file
|
||||
with open(cache_file, 'r') as f:
|
||||
cache_data = json.load(f)
|
||||
|
||||
logger.info(f"Cache file created with {len(cache_data)} entries")
|
||||
logger.info(f"Token expires at: {time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(cache_data['expires_at']))}")
|
||||
|
||||
# Save the token for comparison
|
||||
token1 = bot.access_token
|
||||
|
||||
# Create a new bot instance to test loading from cache
|
||||
logger.info("Creating a second bot instance (should load token from cache)...")
|
||||
bot2 = TwitchBot(
|
||||
username=username,
|
||||
client_id=client_id,
|
||||
client_secret=client_secret,
|
||||
channel=channel,
|
||||
token_cache_file=cache_file
|
||||
)
|
||||
|
||||
# Second call should use the cached token
|
||||
logger.info("Second call to get_oauth_token (should use cached token)...")
|
||||
oauth_token2 = bot2.get_oauth_token()
|
||||
token2 = bot2.access_token
|
||||
|
||||
# Compare tokens
|
||||
if token1 == token2:
|
||||
logger.info("SUCCESS: Both instances used the same token")
|
||||
else:
|
||||
logger.error("FAILURE: Different tokens were used")
|
||||
return False
|
||||
|
||||
# Simulate token expiration by modifying the cache file
|
||||
logger.info("Simulating token expiration...")
|
||||
with open(cache_file, 'r') as f:
|
||||
cache_data = json.load(f)
|
||||
|
||||
# Set expiry to now minus 10 minutes
|
||||
cache_data['expires_at'] = time.time() - 600
|
||||
|
||||
with open(cache_file, 'w') as f:
|
||||
json.dump(cache_data, f)
|
||||
|
||||
# Create a third bot instance with the "expired" token
|
||||
# Since we don't want to trigger a real OAuth flow in tests,
|
||||
# we'll provide a new mock token to use
|
||||
logger.info("Creating a third bot instance with expired token cache...")
|
||||
mock_new_token = "mock_new_token_after_expiration"
|
||||
mock_new_refresh = "mock_new_refresh_after_expiration"
|
||||
|
||||
bot3 = TwitchBot(
|
||||
username=username,
|
||||
client_id=client_id,
|
||||
client_secret=client_secret,
|
||||
channel=channel,
|
||||
access_token=mock_new_token,
|
||||
refresh_token=mock_new_refresh,
|
||||
token_cache_file=cache_file
|
||||
)
|
||||
|
||||
# Third call should use the new token since the cached one is expired
|
||||
logger.info("Third call to get_oauth_token (should use the new mock token due to expiration)...")
|
||||
oauth_token3 = bot3.get_oauth_token()
|
||||
token3 = bot3.access_token
|
||||
|
||||
# Compare tokens - they should be different
|
||||
if token1 != token3:
|
||||
logger.info("SUCCESS: Token was refreshed after expiration")
|
||||
else:
|
||||
logger.error("FAILURE: Expired token was not refreshed")
|
||||
return False
|
||||
|
||||
# Clean up
|
||||
if os.path.exists(cache_file):
|
||||
os.remove(cache_file)
|
||||
logger.info(f"Removed test cache file: {cache_file}")
|
||||
|
||||
logger.info("All token cache tests passed!")
|
||||
return True
|
||||
|
||||
if __name__ == "__main__":
|
||||
print("Testing token caching functionality...")
|
||||
if test_token_cache():
|
||||
print("All token cache tests PASSED!")
|
||||
sys.exit(0)
|
||||
else:
|
||||
print("Token cache tests FAILED!")
|
||||
sys.exit(1)
|
||||
Loading…
Add table
Add a link
Reference in a new issue