Skip to main content
Glama
login.exp23.2 kB
#!/usr/bin/env expect # Exit codes: # 0 - Test passed # 1 - Test failed # Set timeout for command execution set timeout 30 # Colors for output set GREEN "\033\[0;32m" set RED "\033\[0;31m" set YELLOW "\033\[1;33m" set BLUE "\033\[0;34m" set NC "\033\[0m" # Get the gbox binary path # Default to using the built binary in the parent directory set gbox_binary "../gbox" # If the built binary doesn't exist, fall back to system gbox if {![file exists $gbox_binary]} { set gbox_binary "gbox" } puts "${BLUE}Testing gbox login command...${NC}" # Function to check and install Python dependencies proc check_python_deps {} { global GREEN RED YELLOW BLUE NC venv_path venv_python puts "${YELLOW}Checking Python dependencies...${NC}" # Check if python3 is available, try both python3 and python set python_cmd "" if {![catch {exec python3 --version} result]} { set python_cmd "python3" puts "${GREEN}✓ Python3 found: $result${NC}" } elseif {![catch {exec python --version} result]} { set python_cmd "python" puts "${GREEN}✓ Python found: $result${NC}" } else { puts "${RED}✗ Python not found. Please install Python3.${NC}" return 0 } # Get current working directory and construct venv path relative to it set current_dir [pwd] puts "${BLUE}Current working directory: $current_dir${NC}" # Check if we're in CI environment (GitHub Actions) set ci_env [expr {[info exists env::CI] && $env::CI == "true"}] if {$ci_env} { puts "${BLUE}Detected CI environment, using system Python${NC}" set venv_path "" set venv_python $python_cmd } else { # Check if we're in the gbox project root or a subdirectory if {[string match "*gbox*" $current_dir]} { # Find the gbox project root by looking for go.mod or other indicators set venv_path "$current_dir/venv" # If we're in a subdirectory, try to find the project root if {![file exists "$current_dir/go.mod"] && ![file exists "$current_dir/README.md"]} { # We might be in a subdirectory, try parent directories set parent_dir [file dirname $current_dir] if {[file exists "$parent_dir/go.mod"] || [file exists "$parent_dir/README.md"]} { set venv_path "$parent_dir/venv" puts "${BLUE}Found project root at: $parent_dir${NC}" } } } else { # Fallback to current directory set venv_path "$current_dir/venv" } puts "${BLUE}Using virtual environment path: $venv_path${NC}" if {![file exists $venv_path]} { puts "${YELLOW}Virtual environment not found, creating one...${NC}" if {[catch {exec $python_cmd -m venv $venv_path} result]} { puts "${RED}✗ Failed to create virtual environment: $result${NC}" return 0 } puts "${GREEN}✓ Virtual environment created${NC}" } else { puts "${GREEN}✓ Virtual environment already exists${NC}" } set venv_python "$venv_path/bin/python" } # Check if playwright is installed if {[catch {exec $venv_python -c "import playwright; print('playwright installed')"} result]} { if {$ci_env} { puts "${YELLOW}Playwright not found in CI environment, this should have been installed by CI setup${NC}" puts "${RED}✗ Playwright not available in CI environment${NC}" return 0 } else { puts "${YELLOW}Playwright not found in virtual environment, installing...${NC}" # Install playwright in virtual environment if {[catch {exec $venv_python -m pip install playwright==1.55.0} result]} { puts "${RED}✗ Failed to install playwright: $result${NC}" return 0 } puts "${GREEN}✓ Playwright installed successfully${NC}" # Install chromium browser if {[catch {exec $venv_python -m playwright install chromium} result]} { puts "${RED}✗ Failed to install chromium browser: $result${NC}" return 0 } puts "${GREEN}✓ Chromium browser installed successfully${NC}" # Install system dependencies for CI if {[catch {exec $venv_python -m playwright install-deps chromium} result]} { puts "${YELLOW}Warning: Failed to install system dependencies (this may be expected in some environments)${NC}" } else { puts "${GREEN}✓ System dependencies installed successfully${NC}" } } } else { puts "${GREEN}✓ Playwright already installed${NC}" } return 1 } # Test 1: Help command for login puts "\n${YELLOW}Testing help command for login...${NC}" puts "${BLUE}Running Test 1: Help command for login${NC}" if {[catch { spawn $gbox_binary login --help expect { -re "Authenticate with gbox cloud service" { puts "${GREEN}✓ Found help description${NC}" exp_continue } -re "Examples:" { puts "${GREEN}✓ Found examples section${NC}" exp_continue } -re "gbox login" { puts "${GREEN}✓ Found login command example${NC}" exp_continue } timeout { puts "${RED}✗ Timeout waiting for help output${NC}" exit 1 } eof { puts "${GREEN}✓ Help command completed successfully${NC}" } } catch {close} } result]} { puts "${RED}✗ Test failed: $result${NC}" exit 1 } # Test 2: Login command - main flow test puts "\n${YELLOW}Testing login command main flow...${NC}" puts "${BLUE}Running Test 2: Login command main flow${NC}" # Set up variables for the login flow set login_url "" set device_code "" puts "${BLUE}=== Test 2 Phase 1: Starting gbox login command ===${NC}" if {[catch { spawn $gbox_binary login expect { -re "Device code: (\[A-Z0-9\]{4}-\[A-Z0-9\]{4})" { set device_code $expect_out(1,string) puts "${GREEN}✓ Extracted device code: $device_code${NC}" puts "${BLUE}=== Test 2 Phase 2: Device code extracted ===${NC}" exp_continue } -re "Device code: (\[^\\r\\n\]+)" { set device_code $expect_out(1,string) puts "${GREEN}✓ Extracted device code (generic): $device_code${NC}" puts "${BLUE}=== Test 2 Phase 2: Device code extracted (generic) ===${NC}" exp_continue } -re "To authenticate, please visit:" { puts "${GREEN}✓ Found URL prompt${NC}" puts "${BLUE}=== Test 2 Phase 3: URL prompt detected ===${NC}" exp_continue } -re "(https://\[^\\r\\n\]+)" { set login_url $expect_out(1,string) puts "${GREEN}✓ Extracted login URL: $login_url${NC}" puts "${BLUE}=== Test 2 Phase 4: Login URL extracted ===${NC}" # If we have both URL and device code, run playwright automation if {$login_url != "" && $device_code != ""} { puts "${GREEN}✓ Login flow initiated successfully (URL and device code extracted)${NC}" puts "${BLUE}=== Test 2 Phase 5: Starting Playwright automation ===${NC}" puts "${YELLOW}Starting automated login with Playwright...${NC}" # Run playwright automation in background without interrupting the login process puts "${BLUE}=== Test 2 Phase 6: Checking Python dependencies ===${NC}" if {![check_python_deps]} { puts "${RED}✗ Failed to setup Python dependencies${NC}" exit 1 } puts "${GREEN}✓ Python dependencies check completed${NC}" # Create temporary Python script for Playwright automation puts "${BLUE}=== Test 2 Phase 7: Creating Playwright automation script ===${NC}" set temp_script "/tmp/test_login_playwright.py" set fp [open $temp_script w] puts $fp "#!/usr/bin/env python3" puts $fp "import asyncio" puts $fp "import sys" puts $fp "from playwright.async_api import async_playwright" puts $fp "" puts $fp "async def test_login_flow():" puts $fp " async with async_playwright() as p:" puts $fp " browser = await p.chromium.launch(" puts $fp " headless=True," puts $fp " args=\[" puts $fp " '--no-sandbox'," puts $fp " '--disable-setuid-sandbox'," puts $fp " '--disable-dev-shm-usage'," puts $fp " '--disable-accelerated-2d-canvas'," puts $fp " '--no-first-run'," puts $fp " '--no-zygote'," puts $fp " '--disable-gpu'" puts $fp " \]" puts $fp " )" puts $fp " page = await browser.new_page()" puts $fp " " puts $fp " try:" puts $fp " print(f'Navigating to login URL: $login_url')" puts $fp " await page.goto('$login_url', wait_until='networkidle')" puts $fp " print('✓ Successfully navigated to login URL')" puts $fp " " puts $fp " # Wait for page to load and look for Continue button" puts $fp " print('Waiting for page to load...')" puts $fp " await page.wait_for_load_state('networkidle')" puts $fp " " puts $fp " # Try multiple selectors for the Continue button" puts $fp " print('Looking for Continue button...')" puts $fp " continue_button = None" puts $fp " selectors = \[" puts $fp " 'input\[type=\"submit\"\]\[value=\"Continue\"\]'," puts $fp " 'button\[type=\"submit\"\]:has-text(\"Continue\")'," puts $fp " 'input.btn\[type=\"submit\"\]'," puts $fp " 'button:has-text(\"Continue\")'," puts $fp " 'input\[value=\"Continue\"\]'" puts $fp " \]" puts $fp " " puts $fp " for selector in selectors:" puts $fp " try:" puts $fp " print(f'Trying selector: {selector}')" puts $fp " continue_button = await page.wait_for_selector(selector, timeout=5000)" puts $fp " if continue_button:" puts $fp " print(f'✓ Found Continue button with selector: {selector}')" puts $fp " break" puts $fp " except Exception as e:" puts $fp " print(f'Selector {selector} failed: {e}')" puts $fp " continue" puts $fp " " puts $fp " if continue_button:" puts $fp " await continue_button.click()" puts $fp " print('✓ Successfully clicked Continue button')" puts $fp " " puts $fp " # Wait for navigation after clicking Continue" puts $fp " print('Waiting for page navigation...')" puts $fp " await page.wait_for_load_state('networkidle')" puts $fp " " puts $fp " # Check if we're on Google OAuth page" puts $fp " current_url = page.url" puts $fp " print(f'Current URL after Continue: {current_url}')" puts $fp " " puts $fp " if 'accounts.google.com' in current_url:" puts $fp " print('✓ Detected Google OAuth flow - this is expected for GitHub login')" puts $fp " print('✓ GitHub OAuth flow initiated successfully')" puts $fp " return True" puts $fp " " puts $fp " else:" puts $fp " print('✗ Continue button not found')" puts $fp " return False" puts $fp " " puts $fp " # Wait for device code input field (fallback for direct device code flow)" puts $fp " print('Looking for device code input field...')" puts $fp " device_code_input = await page.wait_for_selector(" puts $fp " 'input\[name=\"user-code-0\"\]\[id=\"user-code-0\"\]', " puts $fp " timeout=10000" puts $fp " )" puts $fp " " puts $fp " if device_code_input:" puts $fp " # Enter the device code character by character" puts $fp " device_code = '$device_code'" puts $fp " print(f'Entering device code: {device_code}')" puts $fp " " puts $fp " # Remove hyphens from device code for input" puts $fp " clean_code = device_code.replace('-', '')" puts $fp " print(f'Clean device code: {clean_code}')" puts $fp " " puts $fp " # Enter each character in the corresponding input field" puts $fp " for i in range(len(clean_code)):" puts $fp " input_selector = f'input\[name=\"user-code-{i}\"\]'" puts $fp " print(f'Looking for input field {i}: {input_selector}')" puts $fp " " puts $fp " input_field = await page.wait_for_selector(" puts $fp " input_selector, " puts $fp " timeout=5000" puts $fp " )" puts $fp " " puts $fp " if input_field:" puts $fp " await input_field.clear()" puts $fp " await input_field.fill(clean_code\[i\])" puts $fp " print(f'✓ Entered character {i+1}: {clean_code\[i\]}')" puts $fp " else:" puts $fp " print(f'✗ Could not find input field for character {i+1}')" puts $fp " return False" puts $fp " else:" puts $fp " print('✗ Device code input field not found')" puts $fp " return False" puts $fp " " puts $fp " # Click the submit button after entering device code" puts $fp " print('Looking for submit button...')" puts $fp " submit_button = await page.wait_for_selector(" puts $fp " 'input.btn.btn-sm.btn-primary.m-0\[type=\"submit\"\]', " puts $fp " timeout=10000" puts $fp " )" puts $fp " " puts $fp " if submit_button:" puts $fp " await submit_button.click()" puts $fp " print('✓ Successfully clicked submit button')" puts $fp " else:" puts $fp " print('✗ Submit button not found')" puts $fp " return False" puts $fp " " puts $fp " print('✓ Playwright test completed successfully')" puts $fp " return True" puts $fp " " puts $fp " except Exception as e:" puts $fp " print(f'✗ Playwright test failed: {e}')" puts $fp " return False" puts $fp " finally:" puts $fp " await browser.close()" puts $fp "" puts $fp "if __name__ == '__main__':" puts $fp " result = asyncio.run(test_login_flow())" puts $fp " sys.exit(0 if result else 1)" close $fp puts "${GREEN}✓ Playwright script created at: $temp_script${NC}" # Make the script executable puts "${BLUE}=== Test 2 Phase 8: Making script executable ===${NC}" exec chmod +x $temp_script puts "${GREEN}✓ Script made executable${NC}" # Run the playwright test and wait for completion using virtual environment puts "${BLUE}=== Test 2 Phase 9: Running Playwright automation ===${NC}" # Use the same venv_python that was determined in check_python_deps puts "${BLUE}Using Python executable: $venv_python${NC}" if {[catch { set playwright_result [exec $venv_python $temp_script] puts "${GREEN}✓ Playwright test output: $playwright_result${NC}" set playwright_success 1 } result]} { puts "${RED}✗ Playwright test failed: $result${NC}" set playwright_success 0 } # Clean up the temporary script puts "${BLUE}=== Test 2 Phase 10: Cleaning up temporary files ===${NC}" exec rm -f $temp_script puts "${GREEN}✓ Temporary script cleaned up${NC}" if {$playwright_success} { puts "${GREEN}✓ Playwright automation completed successfully${NC}" puts "${BLUE}=== Test 2 Phase 11: Playwright automation completed ===${NC}" } else { puts "${RED}✗ Playwright automation failed${NC}" puts "${BLUE}=== Test 2 Phase 11: Playwright automation failed ===${NC}" } # Continue with the login process instead of breaking exp_continue } exp_continue } -re "Available organizations:" { puts "${GREEN}✓ Found organization selection prompt${NC}" puts "${BLUE}=== Test 2 Phase 12: Organization selection detected ===${NC}" exp_continue } -re "Select an organization by entering the number:" { puts "${GREEN}✓ Found organization selection input prompt${NC}" puts "${BLUE}=== Test 2 Phase 13: Organization selection input prompt ===${NC}" # Send "1" and Enter to select the first organization send "1\r" puts "${GREEN}✓ Sent organization selection: 1${NC}" puts "${BLUE}=== Test 2 Phase 14: Organization selection sent ===${NC}" exp_continue } -re "Selected organization:" { puts "${GREEN}✓ Organization selection confirmed${NC}" puts "${BLUE}=== Test 2 Phase 15: Organization selection confirmed ===${NC}" exp_continue } -re "Created API key:" { puts "${GREEN}✓ API key created successfully${NC}" puts "${BLUE}=== Test 2 Phase 16: API key created ===${NC}" exp_continue } -re "Login process successfully" { puts "${GREEN}✓ Login process completed successfully${NC}" puts "${BLUE}=== Test 2 Phase 17: Login process completed ===${NC}" exp_continue } -re "Login successful" { puts "${GREEN}✓ Login completed successfully${NC}" puts "${BLUE}=== Test 2 Phase 17: Login successful ===${NC}" exp_continue } -re "Already logged in" { puts "${GREEN}✓ Already logged in (expected in some cases)${NC}" puts "${BLUE}=== Test 2 Phase 17: Already logged in ===${NC}" exp_continue } timeout { puts "${BLUE}=== Test 2 Phase 18: Timeout handling ===${NC}" # If we have both URL and device code, Playwright should have completed if {$login_url != "" && $device_code != ""} { puts "${GREEN}✓ Login flow test completed (URL and device code extracted, Playwright automation completed)${NC}" puts "${BLUE}=== Test 2 Phase 19: Test completed with extracted credentials ===${NC}" } else { puts "${RED}✗ Timeout waiting for login flow${NC}" puts "${BLUE}=== Test 2 Phase 19: Test failed due to timeout ===${NC}" exit 1 } } eof { puts "${GREEN}✓ Login command completed${NC}" puts "${BLUE}=== Test 2 Phase 19: Login command completed normally ===${NC}" } } catch {close} } result]} { puts "${RED}✗ Test failed: $result${NC}" exit 1 } # Test 3: Test login with invalid flags puts "\n${YELLOW}Testing login with invalid flags...${NC}" puts "${BLUE}Running Test 3: Login with invalid flags${NC}" if {[catch { spawn $gbox_binary login --invalid-flag expect { -re "Error:.*unknown flag.*invalid-flag" { puts "${GREEN}✓ Found expected error message for invalid flag${NC}" exp_continue } timeout { puts "${RED}✗ Timeout waiting for error message${NC}" exit 1 } eof { puts "${GREEN}✓ Error message displayed correctly${NC}" } } catch {close} } result]} { puts "${RED}✗ Test failed: $result${NC}" exit 1 } puts "\n${GREEN}All login tests passed!${NC}" exit 0

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/babelcloud/gru-sandbox'

If you have feedback or need assistance with the MCP directory API, please join our Discord server