258 lines
9.8 KiB
Python
258 lines
9.8 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Test script for REAL-TIME form discovery capabilities.
|
|
|
|
This script tests the enhanced form filling system that:
|
|
1. NEVER uses cached selectors
|
|
2. Always uses real-time MCP tools for discovery
|
|
3. Gets fresh selectors on every request
|
|
4. Uses chrome_get_interactive_elements and chrome_get_content_web_form
|
|
"""
|
|
|
|
import asyncio
|
|
import logging
|
|
import sys
|
|
import os
|
|
|
|
# Add the current directory to the path so we can import our modules
|
|
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
|
|
|
|
from mcp_chrome_client import MCPChromeClient
|
|
|
|
# Set up logging
|
|
logging.basicConfig(
|
|
level=logging.INFO,
|
|
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
|
|
)
|
|
logger = logging.getLogger(__name__)
|
|
|
|
async def test_realtime_discovery():
|
|
"""Test the real-time form discovery capabilities"""
|
|
|
|
# Initialize MCP Chrome client
|
|
client = MCPChromeClient(
|
|
server_type="http",
|
|
server_url="http://127.0.0.1:12306/mcp"
|
|
)
|
|
|
|
try:
|
|
# Connect to MCP server
|
|
logger.info("Connecting to MCP server...")
|
|
await client.connect()
|
|
logger.info("Connected successfully!")
|
|
|
|
# Test 1: Navigate to Google (fresh page)
|
|
logger.info("=== Test 1: Navigate to Google ===")
|
|
result = await client._navigate_mcp("https://www.google.com")
|
|
logger.info(f"Navigation result: {result}")
|
|
await asyncio.sleep(3) # Wait for page to load
|
|
|
|
# Test 2: Real-time discovery for search field (NO CACHE)
|
|
logger.info("=== Test 2: Real-time discovery for search field ===")
|
|
discovery_result = await client._discover_form_fields_dynamically("search", "python programming")
|
|
logger.info(f"Real-time discovery result: {discovery_result}")
|
|
|
|
# Test 3: Fill field using ONLY real-time discovery
|
|
logger.info("=== Test 3: Fill field using ONLY real-time discovery ===")
|
|
fill_result = await client.fill_field_by_name("search", "machine learning")
|
|
logger.info(f"Real-time fill result: {fill_result}")
|
|
|
|
# Test 4: Direct MCP element search
|
|
logger.info("=== Test 4: Direct MCP element search ===")
|
|
direct_result = await client._direct_mcp_element_search("search", "artificial intelligence")
|
|
logger.info(f"Direct search result: {direct_result}")
|
|
|
|
# Test 5: Navigate to different site and test real-time discovery
|
|
logger.info("=== Test 5: Test real-time discovery on GitHub ===")
|
|
result = await client._navigate_mcp("https://www.github.com")
|
|
logger.info(f"GitHub navigation result: {result}")
|
|
await asyncio.sleep(3)
|
|
|
|
# Real-time discovery on GitHub
|
|
github_discovery = await client._discover_form_fields_dynamically("search", "python")
|
|
logger.info(f"GitHub real-time discovery: {github_discovery}")
|
|
|
|
# Test 6: Test very flexible matching
|
|
logger.info("=== Test 6: Test very flexible matching ===")
|
|
flexible_result = await client._direct_mcp_element_search("query", "test search")
|
|
logger.info(f"Flexible matching result: {flexible_result}")
|
|
|
|
# Test 7: Test common selectors generation
|
|
logger.info("=== Test 7: Test common selectors generation ===")
|
|
common_selectors = client._generate_common_selectors("search")
|
|
logger.info(f"Generated common selectors: {common_selectors[:10]}") # Show first 10
|
|
|
|
# Test 8: Navigate to a form-heavy site
|
|
logger.info("=== Test 8: Test on form-heavy site ===")
|
|
result = await client._navigate_mcp("https://httpbin.org/forms/post")
|
|
logger.info(f"Form site navigation result: {result}")
|
|
await asyncio.sleep(3)
|
|
|
|
# Test real-time discovery on form fields
|
|
form_fields = ["email", "password", "comment"]
|
|
for field in form_fields:
|
|
logger.info(f"Testing real-time discovery for field: {field}")
|
|
field_result = await client._discover_form_fields_dynamically(field, f"test_{field}")
|
|
logger.info(f"Field '{field}' discovery: {field_result}")
|
|
|
|
logger.info("=== All real-time discovery tests completed! ===")
|
|
|
|
except Exception as e:
|
|
logger.error(f"Test failed with error: {e}")
|
|
import traceback
|
|
traceback.print_exc()
|
|
|
|
finally:
|
|
# Disconnect from MCP server
|
|
try:
|
|
await client.disconnect()
|
|
logger.info("Disconnected from MCP server")
|
|
except Exception as e:
|
|
logger.error(f"Error disconnecting: {e}")
|
|
|
|
async def test_mcp_tools_directly():
|
|
"""Test MCP tools directly to verify real-time capabilities"""
|
|
logger.info("=== Testing MCP tools directly ===")
|
|
|
|
client = MCPChromeClient(server_type="http", server_url="http://127.0.0.1:12306/mcp")
|
|
|
|
try:
|
|
await client.connect()
|
|
|
|
# Navigate to Google
|
|
await client._navigate_mcp("https://www.google.com")
|
|
await asyncio.sleep(3)
|
|
|
|
# Test chrome_get_interactive_elements directly
|
|
logger.info("Testing chrome_get_interactive_elements...")
|
|
interactive_result = await client._call_mcp_tool("chrome_get_interactive_elements", {
|
|
"types": ["input", "textarea", "select"]
|
|
})
|
|
|
|
if interactive_result and "elements" in interactive_result:
|
|
elements = interactive_result["elements"]
|
|
logger.info(f"Found {len(elements)} interactive elements")
|
|
|
|
for i, element in enumerate(elements[:5]): # Show first 5
|
|
attrs = element.get("attributes", {})
|
|
logger.info(f"Element {i+1}: {element.get('tagName')} - name: {attrs.get('name')}, id: {attrs.get('id')}, type: {attrs.get('type')}")
|
|
|
|
# Test chrome_get_content_web_form directly
|
|
logger.info("Testing chrome_get_content_web_form...")
|
|
form_result = await client._call_mcp_tool("chrome_get_content_web_form", {})
|
|
|
|
if form_result:
|
|
logger.info(f"Form content result: {str(form_result)[:200]}...") # Show first 200 chars
|
|
|
|
# Test chrome_get_web_content for all inputs
|
|
logger.info("Testing chrome_get_web_content for all inputs...")
|
|
content_result = await client._call_mcp_tool("chrome_get_web_content", {
|
|
"selector": "input, textarea, select",
|
|
"textOnly": False
|
|
})
|
|
|
|
if content_result:
|
|
logger.info(f"Web content result: {str(content_result)[:200]}...") # Show first 200 chars
|
|
|
|
except Exception as e:
|
|
logger.error(f"Direct MCP tool test failed: {e}")
|
|
import traceback
|
|
traceback.print_exc()
|
|
|
|
finally:
|
|
try:
|
|
await client.disconnect()
|
|
except Exception:
|
|
pass
|
|
|
|
async def test_field_matching_algorithms():
|
|
"""Test the field matching algorithms"""
|
|
logger.info("=== Testing field matching algorithms ===")
|
|
|
|
client = MCPChromeClient(server_type="http", server_url="http://127.0.0.1:12306/mcp")
|
|
|
|
# Test elements (simulated)
|
|
test_elements = [
|
|
{
|
|
"tagName": "input",
|
|
"attributes": {
|
|
"name": "q",
|
|
"type": "search",
|
|
"placeholder": "Search Google or type a URL",
|
|
"aria-label": "Search"
|
|
}
|
|
},
|
|
{
|
|
"tagName": "input",
|
|
"attributes": {
|
|
"name": "email",
|
|
"type": "email",
|
|
"placeholder": "Enter your email address"
|
|
}
|
|
},
|
|
{
|
|
"tagName": "input",
|
|
"attributes": {
|
|
"name": "user_password",
|
|
"type": "password",
|
|
"placeholder": "Password"
|
|
}
|
|
},
|
|
{
|
|
"tagName": "textarea",
|
|
"attributes": {
|
|
"name": "message",
|
|
"placeholder": "Type your message here",
|
|
"aria-label": "Message"
|
|
}
|
|
}
|
|
]
|
|
|
|
test_field_names = [
|
|
"search", "query", "q",
|
|
"email", "mail", "e-mail",
|
|
"password", "pass", "user password",
|
|
"message", "comment", "text"
|
|
]
|
|
|
|
logger.info("Testing standard field matching...")
|
|
for field_name in test_field_names:
|
|
logger.info(f"\nTesting field name: '{field_name}'")
|
|
for i, element in enumerate(test_elements):
|
|
is_match = client._is_field_match(element, field_name.lower())
|
|
selector = client._extract_best_selector(element)
|
|
logger.info(f" Element {i+1} ({element['tagName']}): Match={is_match}, Selector={selector}")
|
|
|
|
logger.info("\nTesting very flexible matching...")
|
|
for field_name in test_field_names:
|
|
logger.info(f"\nTesting flexible field name: '{field_name}'")
|
|
for i, element in enumerate(test_elements):
|
|
is_match = client._is_very_flexible_match(element, field_name.lower())
|
|
logger.info(f" Element {i+1} ({element['tagName']}): Flexible Match={is_match}")
|
|
|
|
def main():
|
|
"""Main function to run the tests"""
|
|
logger.info("Starting REAL-TIME form discovery tests...")
|
|
|
|
# Check if MCP server is likely running
|
|
import socket
|
|
try:
|
|
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
|
sock.settimeout(1)
|
|
result = sock.connect_ex(('127.0.0.1', 12306))
|
|
sock.close()
|
|
if result != 0:
|
|
logger.warning("MCP server doesn't appear to be running on port 12306")
|
|
logger.warning("Please start the MCP server before running this test")
|
|
return
|
|
except Exception as e:
|
|
logger.warning(f"Could not check MCP server status: {e}")
|
|
|
|
# Run the tests
|
|
asyncio.run(test_field_matching_algorithms())
|
|
asyncio.run(test_mcp_tools_directly())
|
|
asyncio.run(test_realtime_discovery())
|
|
|
|
if __name__ == "__main__":
|
|
main()
|