| name | browser |
| description | Browser automation skill for testing SugarCRM Enterprise (v12-25). Use for simulating user interactions: clicking buttons, filling forms, navigating modules, creating records, and verifying functionality. Requires Playwright and Chromium browser installed.
|
Browser Automation Skill
Control a Chromium browser to test SugarCRM Enterprise (versions 12-25) by simulating user interactions.
When This Skill MUST Be Used
Invoke this skill for ANY task involving:
- Testing SugarCRM functionality
- Automating browser interactions with web applications
- UI testing, form submissions, navigation flows
- Screenshot capture of web pages
- Data extraction from web pages
Prerequisites
1. Install Playwright
pip install playwright
playwright install chromium
2. Set Environment Variables
export SUGARCRM_URL="https://your-instance.sugarcrm.com"
export SUGARCRM_USERNAME="your-username"
export SUGARCRM_PASSWORD="your-password"
Optionally create ~/.config/opencode/skills/browser/.env:
SUGARCRM_URL=https://your-instance.sugarcrm.com
SUGARCRM_USERNAME=admin
SUGARCRM_PASSWORD=your-password
3. Verify Installation
python -c "from playwright.sync_api import sync_playwright; print('OK')"
Core Actions
Launch Browser
from scripts.launcher import launch
browser, page = launch(headless=False)
browser, page = launch(headless=True)
Navigate to URL
page.goto("https://example.com")
import os
page.goto(os.environ.get("SUGARCRM_URL"))
Click Element
page.click("#save-button")
page.click("text=Save")
page.click("text=Create New")
Fill Input Field
page.fill("#first_name", "John")
page.fill("label:has-text('First Name')", "John")
page.type("#email", "john@example.com", delay=100)
Select Dropdown
page.select_option("#industry", "Technology")
page.select_option("#status", label="Active")
Wait for Element
page.wait_for_selector(".record-list")
page.wait_for_selector("text=Lead created successfully")
page.wait_for_load_state("networkidle")
page.wait_for_url("**/Accounts/**")
Screenshot
page.screenshot(path="screenshot.png", full_page=True)
page.screenshot(path="screenshot.png")
page.locator(".record-panel").screenshot(path="panel.png")
Extract Content
name = page.locator(".record-name").inner_text()
url = page.locator("a.documentation").get_attribute("href")
content = page.content()
title = page.evaluate("document.title")
Execute JavaScript
result = page.evaluate("""(arg) => {
return document.querySelector('.count').innerText;
}""")
Close Browser
browser.close()
SugarCRM-Specific Helpers
Located in scripts/crm_helpers.py:
Login to SugarCRM
from scripts.crm_helpers import login
page = login(browser)
Logout from SugarCRM
from scripts.crm_helpers import logout
logout(page)
Open Module
from scripts.crm_helpers import open_module
open_module(page, "Accounts")
open_module(page, "Contacts")
open_module(page, "Leads")
open_module(page, "Opportunities")
Create Record
from scripts.crm_helpers import create_record
create_record(page, "Accounts", {
"name": "Acme Corp",
"phone": "+1234567890",
"industry": "Technology",
"website": "https://acme.com"
})
Search
from scripts.crm_helpers import search
results = search(page, "Acme")
Handle Notifications
from scripts.crm_helpers import handle_notifications
handle_notifications(page)
Wait for Module Load
from scripts.crm_helpers import wait_for_module_load
wait_for_module_load(page, "Accounts")
Common Workflows
Workflow 1: Login and Create Lead
from scripts.launcher import launch
from scripts.crm_helpers import login, open_module, create_record
browser, page = launch(headless=False)
login(page)
open_module(page, "Leads")
create_record(page, "Leads", {
"first_name": "John",
"last_name": "Doe",
"email1": "john.doe@example.com",
"phone_work": "+1234567890",
"account_name": "Acme Corp"
})
browser.close()
Workflow 2: Update Existing Record
from scripts.launcher import launch
from scripts.crm_helpers import login, search, handle_notifications
browser, page = launch(headless=False)
login(page)
page.fill("input.search-input", "Acme Corp")
page.click("button.search-button")
page.wait_for_selector("text=Acme Corp")
page.click("tr[data-id] >> text=Acme Corp")
page.click("button.edit-button")
page.fill("#phone_office", "+9876543210")
page.click("button.save")
handle_notifications(page)
browser.close()
Workflow 3: Export Data
from scripts.launcher import launch
from scripts.crm_helpers import login, open_module
browser, page = launch(headless=False)
login(page)
open_module(page, "Accounts")
page.click("input.select-all")
page.click("button.export")
browser.close()
Error Handling
Retry Failed Actions
from playwright.sync_api import expect
for _ in range(3):
try:
page.click("button.save")
break
except Exception:
page.wait_for_timeout(1000)
Handle Popups
page.on("dialog", lambda dialog: dialog.accept())
with page.context.expect_page() as new_page_info:
page.click("a.new-window")
new_page = new_page_info.value
Handle Navigation Errors
try:
page.goto(url, timeout=30000)
except Exception as e:
print(f"Navigation failed: {e}")
page.screenshot(path="error.png")
Troubleshooting
Browser Won't Launch
playwright install-deps chromium
playwright install
Login Fails
- Verify environment variables are set:
echo $SUGARCRM_URL
- Check URL is correct (includes https://)
- Verify credentials work manually first
Element Not Found
- Use
page.screenshot() to see current state
- Check if element is in iframe (use
page.frame())
- Wait longer with
page.wait_for_timeout(2000)
- Inspect page HTML:
print(page.content())
Slow Performance
- Use headless mode:
launch(headless=True)
- Disable screenshots during tests
- Use CSS selectors instead of text selectors
Best Practices
- Always close browser - Call
browser.close() in finally block
- Use explicit waits - Avoid
sleep(), use wait_for_selector()
- Take screenshots on failure - Helps debug issues
- Use unique selectors - Prefer data attributes or IDs
- Handle notifications - Call
handle_notifications() after actions
- Log actions - Print steps for debugging
Environment Variables
| Variable | Required | Description |
|---|
SUGARCRM_URL | Yes | SugarCRM instance URL |
SUGARCRM_USERNAME | Yes | Login username |
SUGARCRM_PASSWORD | Yes | Login password |
File Structure
~/.config/opencode/skills/browser/
├── SKILL.md # This file
├── .env.example # Environment template
└── scripts/
├── __init__.py
├── launcher.py # Browser launch entry point
├── browser.py # Core Playwright actions
└── crm_helpers.py # SugarCRM helpers