Files
thrillwiki_django_no_react/test_mobile_auth_buttons.py
pac7 499c8c5abf Improve mobile authentication by refining how buttons interact with the modal
Refactor the mobile authentication button handling by removing a global event listener and implementing a direct component interaction method. This ensures the auth modal can be opened correctly from mobile buttons. Additional tests and documentation have been added to verify and explain the functionality.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 495199c6-aa06-48cd-8c40-9cccf398cfcf
Replit-Commit-Checkpoint-Type: intermediate_checkpoint
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/d6d61dac-164d-45dd-929f-7dcdfd771b64/495199c6-aa06-48cd-8c40-9cccf398cfcf/IQPlVNL
2025-09-22 00:15:15 +00:00

317 lines
14 KiB
Python
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env python3
"""
ThrillWiki Mobile Authentication Button Testing
Tests the mobile Sign In and Join buttons functionality
"""
import asyncio
import sys
import os
from playwright.async_api import async_playwright, expect
import time
class MobileAuthTester:
def __init__(self):
self.base_url = "http://localhost:5000"
self.test_results = []
self.issues_found = []
def log_test_result(self, test_name, status, details=""):
"""Log test result and print to console"""
result = {
"test": test_name,
"status": status, # "PASS", "FAIL", "SKIP"
"details": details
}
self.test_results.append(result)
status_emoji = "" if status == "PASS" else "" if status == "FAIL" else "⚠️"
print(f"{status_emoji} {test_name}: {status}")
if details:
print(f" Details: {details}")
if status == "FAIL":
self.issues_found.append(f"{test_name}: {details}")
async def test_mobile_auth_buttons(self):
"""Main test function for mobile authentication buttons"""
print("🚀 Starting ThrillWiki Mobile Authentication Tests\n")
print("=" * 60)
async with async_playwright() as p:
# Launch browser in mobile mode
browser = await p.chromium.launch(headless=False, slow_mo=500)
# Create mobile context (iPhone 12 viewport)
context = await browser.new_context(
viewport={'width': 390, 'height': 844},
user_agent='Mozilla/5.0 (iPhone; CPU iPhone OS 14_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0 Mobile/15E148 Safari/604.1'
)
page = await context.new_page()
try:
# Test 1: Navigate to homepage
await self.test_homepage_navigation(page)
# Test 2: Locate mobile authentication buttons
await self.test_locate_mobile_buttons(page)
# Test 3: Test Sign In button functionality
await self.test_sign_in_button(page)
# Test 4: Test Join button functionality
await self.test_join_button(page)
# Test 5: Test modal close functionality
await self.test_modal_close_functionality(page)
# Test 6: Verify button sizing and touch-friendliness
await self.test_button_sizing_and_touch_friendliness(page)
except Exception as e:
self.log_test_result("OVERALL_TEST", "FAIL", f"Unexpected error: {str(e)}")
finally:
await browser.close()
# Print final results
self.print_final_results()
async def test_homepage_navigation(self, page):
"""Test 1: Navigate to ThrillWiki homepage on mobile"""
try:
print("\n1⃣ Testing homepage navigation...")
await page.goto(self.base_url, wait_until="networkidle")
# Wait for page to fully load
await page.wait_for_selector('header', timeout=10000)
# Check if we're on the homepage
title = await page.title()
if "ThrillWiki" in title:
self.log_test_result("Homepage Navigation", "PASS", f"Successfully loaded: {title}")
else:
self.log_test_result("Homepage Navigation", "FAIL", f"Unexpected title: {title}")
except Exception as e:
self.log_test_result("Homepage Navigation", "FAIL", str(e))
async def test_locate_mobile_buttons(self, page):
"""Test 2: Locate mobile Sign In and Join buttons in header"""
try:
print("\n2⃣ Locating mobile authentication buttons...")
# Check for mobile section (should be visible on mobile viewport)
mobile_section = page.locator('.md\\:hidden')
await expect(mobile_section).to_be_visible()
# Look for Sign In button specifically in mobile section
sign_in_button = page.locator('.md\\:hidden button:has-text("Sign In")')
join_button = page.locator('.md\\:hidden button:has-text("Join")')
# Check if buttons exist and are visible
sign_in_visible = await sign_in_button.is_visible()
join_visible = await join_button.is_visible()
if sign_in_visible and join_visible:
self.log_test_result("Locate Mobile Buttons", "PASS", "Both Sign In and Join buttons found in mobile header")
else:
missing = []
if not sign_in_visible:
missing.append("Sign In")
if not join_visible:
missing.append("Join")
self.log_test_result("Locate Mobile Buttons", "FAIL", f"Missing buttons: {', '.join(missing)}")
except Exception as e:
self.log_test_result("Locate Mobile Buttons", "FAIL", str(e))
async def test_sign_in_button(self, page):
"""Test 3: Test Sign In button functionality"""
try:
print("\n3⃣ Testing Sign In button functionality...")
# Find the Sign In button in mobile section
sign_in_button = page.locator('.md\\:hidden button:has-text("Sign In")')
await expect(sign_in_button).to_be_visible()
# Click the Sign In button
await sign_in_button.click()
# Wait for authentication modal to appear
auth_modal = page.locator('[x-data*="authModal"]')
await expect(auth_modal).to_be_visible(timeout=5000)
# Check if login form is displayed (should show "Sign In" heading)
login_heading = page.locator('h2:has-text("Sign In")')
await expect(login_heading).to_be_visible()
# Check for login form elements
username_field = page.locator('input[type="text"], input[type="email"]').first
password_field = page.locator('input[type="password"]').first
username_visible = await username_field.is_visible()
password_visible = await password_field.is_visible()
if username_visible and password_visible:
self.log_test_result("Sign In Button Functionality", "PASS", "Sign In button opens modal with login form")
else:
self.log_test_result("Sign In Button Functionality", "FAIL", "Login form elements not found in modal")
except Exception as e:
self.log_test_result("Sign In Button Functionality", "FAIL", str(e))
async def test_join_button(self, page):
"""Test 4: Test Join button functionality"""
try:
print("\n4⃣ Testing Join button functionality...")
# First, close any open modal by clicking overlay or escape
try:
overlay = page.locator('.fixed.inset-0.bg-background\\/80')
if await overlay.is_visible():
await overlay.click()
await page.wait_for_timeout(500)
except:
pass
# Find the Join button in mobile section
join_button = page.locator('.md\\:hidden button:has-text("Join")')
await expect(join_button).to_be_visible()
# Click the Join button
await join_button.click()
# Wait for authentication modal to appear
auth_modal = page.locator('[x-data*="authModal"]')
await expect(auth_modal).to_be_visible(timeout=5000)
# Check if registration form is displayed (should show "Create Account" or "Sign Up" heading)
register_heading = page.locator('h2:has-text("Create Account"), h2:has-text("Sign Up")')
await expect(register_heading).to_be_visible()
# Check for registration form elements
first_name_field = page.locator('input[id*="first"], input[placeholder*="first" i]')
email_field = page.locator('input[type="email"]')
first_name_visible = await first_name_field.is_visible()
email_visible = await email_field.is_visible()
if first_name_visible and email_visible:
self.log_test_result("Join Button Functionality", "PASS", "Join button opens modal with registration form")
else:
self.log_test_result("Join Button Functionality", "FAIL", "Registration form elements not found in modal")
except Exception as e:
self.log_test_result("Join Button Functionality", "FAIL", str(e))
async def test_modal_close_functionality(self, page):
"""Test 5: Test modal close functionality"""
try:
print("\n5⃣ Testing modal close functionality...")
# Ensure modal is open (click Join button if needed)
auth_modal = page.locator('[x-data*="authModal"]')
if not await auth_modal.is_visible():
join_button = page.locator('.md\\:hidden button:has-text("Join")')
await join_button.click()
await expect(auth_modal).to_be_visible(timeout=5000)
# Test close button
close_button = page.locator('button:has(i.fa-times), button[aria-label*="close" i]')
if await close_button.is_visible():
await close_button.click()
await expect(auth_modal).to_be_hidden(timeout=3000)
self.log_test_result("Modal Close Button", "PASS", "Close button successfully closes modal")
else:
self.log_test_result("Modal Close Button", "FAIL", "Close button not found")
return
# Test escape key functionality
join_button = page.locator('.md\\:hidden button:has-text("Join")')
await join_button.click()
await expect(auth_modal).to_be_visible(timeout=5000)
await page.keyboard.press('Escape')
await expect(auth_modal).to_be_hidden(timeout=3000)
self.log_test_result("Modal Escape Key", "PASS", "Escape key successfully closes modal")
except Exception as e:
self.log_test_result("Modal Close Functionality", "FAIL", str(e))
async def test_button_sizing_and_touch_friendliness(self, page):
"""Test 6: Verify button sizing and touch-friendliness"""
try:
print("\n6⃣ Testing button sizing and touch-friendliness...")
# Get Sign In and Join buttons
sign_in_button = page.locator('.md\\:hidden button:has-text("Sign In")')
join_button = page.locator('.md\\:hidden button:has-text("Join")')
# Check button dimensions (should be at least 44px for touch-friendliness)
sign_in_box = await sign_in_button.bounding_box()
join_box = await join_button.bounding_box()
touch_friendly_issues = []
# Check Sign In button dimensions
if sign_in_box:
if sign_in_box['height'] < 44:
touch_friendly_issues.append(f"Sign In button height ({sign_in_box['height']}px) below 44px minimum")
if sign_in_box['width'] < 44:
touch_friendly_issues.append(f"Sign In button width ({sign_in_box['width']}px) below 44px minimum")
else:
touch_friendly_issues.append("Could not measure Sign In button dimensions")
# Check Join button dimensions
if join_box:
if join_box['height'] < 44:
touch_friendly_issues.append(f"Join button height ({join_box['height']}px) below 44px minimum")
if join_box['width'] < 44:
touch_friendly_issues.append(f"Join button width ({join_box['width']}px) below 44px minimum")
else:
touch_friendly_issues.append("Could not measure Join button dimensions")
if touch_friendly_issues:
self.log_test_result("Button Touch-Friendliness", "FAIL", "; ".join(touch_friendly_issues))
else:
sign_in_size = f"{sign_in_box['width']:.0f}x{sign_in_box['height']:.0f}px" if sign_in_box else "N/A"
join_size = f"{join_box['width']:.0f}x{join_box['height']:.0f}px" if join_box else "N/A"
self.log_test_result("Button Touch-Friendliness", "PASS",
f"Buttons are touch-friendly - Sign In: {sign_in_size}, Join: {join_size}")
except Exception as e:
self.log_test_result("Button Touch-Friendliness", "FAIL", str(e))
def print_final_results(self):
"""Print comprehensive test results"""
print("\n" + "=" * 60)
print("📊 FINAL TEST RESULTS")
print("=" * 60)
passed = sum(1 for result in self.test_results if result["status"] == "PASS")
failed = sum(1 for result in self.test_results if result["status"] == "FAIL")
total = len(self.test_results)
print(f"\nTotal Tests: {total}")
print(f"✅ Passed: {passed}")
print(f"❌ Failed: {failed}")
print(f"Success Rate: {(passed/total)*100:.1f}%")
if self.issues_found:
print(f"\n🐛 ISSUES FOUND ({len(self.issues_found)}):")
for i, issue in enumerate(self.issues_found, 1):
print(f" {i}. {issue}")
else:
print("\n🎉 No issues found! All mobile authentication functionality is working correctly.")
print("\n" + "=" * 60)
async def main():
"""Main entry point"""
tester = MobileAuthTester()
await tester.test_mobile_auth_buttons()
if __name__ == "__main__":
asyncio.run(main())