ENHANCEMENT_USAGE.md•5.82 kB
# Firefox MCP Server Enhancement Usage Guide
## New Functions Added
### 1. `send_key` - Keyboard Event Simulation
Send keyboard events to the page or a specific element.
**Parameters:**
- `key` (required): Key to press (e.g., "ArrowLeft", "Enter", "a", "A")
- `selector` (optional): CSS selector to focus before sending key
- `modifiers` (optional): Array of modifier keys ["Shift", "Control", "Alt", "Meta"]
- `repeat` (optional): Number of times to press the key (default: 1)
- `tabId` (optional): Tab ID (uses active tab if not provided)
**Examples:**
```javascript
// Move slider left using arrow key
await mcp.send_key({
selector: ".slider-forward",
key: "ArrowLeft",
repeat: 5
});
// Submit form with Enter key
await mcp.send_key({
selector: "input[type='text']",
key: "Enter"
});
// Copy text with Ctrl+C
await mcp.send_key({
key: "c",
modifiers: ["Control"]
});
// Navigate with Tab key
await mcp.send_key({
key: "Tab",
repeat: 3
});
```
### 2. `drag` - Mouse Drag Operations
Perform drag operations for sliders, drag-and-drop interfaces, and other draggable elements.
**Parameters:**
- Source (one required):
- `selector`: CSS selector of element to drag from
- `fromCoordinates`: Starting coordinates {x, y}
- Destination (one required):
- `toSelector`: CSS selector of element to drag to
- `toCoordinates`: Ending coordinates {x, y}
- `offsetX`/`offsetY`: Offset from start position
- Options:
- `duration`: Total duration in ms (default: 0)
- `steps`: Number of intermediate mousemove events (default: 1)
- `tabId`: Tab ID (uses active tab if not provided)
**Examples:**
```javascript
// Drag slider to specific position
await mcp.drag({
selector: ".slider-forward",
offsetX: -100, // Move 100px left
duration: 500, // Smooth animation over 500ms
steps: 10 // 10 intermediate positions
});
// Drag from element to coordinates
await mcp.drag({
selector: ".draggable-item",
toCoordinates: { x: 400, y: 300 }
});
// Drag between two elements
await mcp.drag({
selector: ".source-element",
toSelector: ".target-element",
duration: 1000,
steps: 20
});
// Precise coordinate-based drag
await mcp.drag({
fromCoordinates: { x: 100, y: 200 },
toCoordinates: { x: 300, y: 200 }
});
```
## Testing HTML Range Sliders
### Method 1: Using Keyboard Navigation
```javascript
// Focus the slider and move it left
await mcp.send_key({
selector: "input[type='range'].slider-forward",
key: "ArrowLeft",
repeat: 10 // Move 10 steps left
});
// Move slider right
await mcp.send_key({
selector: "input[type='range'].slider-forward",
key: "ArrowRight",
repeat: 5
});
// Jump to extremes
await mcp.send_key({
selector: "input[type='range']",
key: "Home" // Move to minimum
});
await mcp.send_key({
selector: "input[type='range']",
key: "End" // Move to maximum
});
```
### Method 2: Using Drag Operations
```javascript
// Get slider position first
const sliderInfo = await mcp.execute_script({
script: `
const slider = document.querySelector('.slider-forward');
const rect = slider.getBoundingClientRect();
return {
x: rect.x,
y: rect.y + rect.height / 2,
width: rect.width,
currentValue: slider.value
};
`
});
// Drag to 25% position
await mcp.drag({
selector: ".slider-forward",
offsetX: -sliderInfo.width * 0.25,
duration: 300,
steps: 5
});
// Drag to specific value (e.g., 75%)
const targetX = sliderInfo.width * 0.75 - sliderInfo.width * 0.5;
await mcp.drag({
selector: ".slider-forward",
offsetX: targetX,
duration: 500,
steps: 10
});
```
## Complete Test Example: Shield Officer Controls
```javascript
// Launch Firefox
await mcp.launch_firefox_multi({ headless: false });
// Create tab and navigate
await mcp.create_tab({
tabId: "game-tab",
url: "http://localhost:4000/stellar-bonds"
});
// Click quick game button
await mcp.click({
selector: "button:has-text('Quick Game')",
tabId: "game-tab"
});
// Wait for shield controls to load
await mcp.wait_for_element({
selector: ".slider-forward",
tabId: "game-tab"
});
// Test forward shield with keyboard
await mcp.send_key({
selector: ".slider-forward",
key: "ArrowLeft",
repeat: 10,
tabId: "game-tab"
});
// Wait a bit to see the effect
await new Promise(resolve => setTimeout(resolve, 1000));
// Test aft shield with drag
await mcp.drag({
selector: ".slider-aft",
offsetX: 150, // Move right
duration: 1000,
steps: 20,
tabId: "game-tab"
});
// Take screenshot to verify
await mcp.screenshot({
path: "shield-test.png",
tabId: "game-tab"
});
```
## Implementation Notes
1. **Playwright Integration**: Both functions use Playwright's native APIs:
- `send_key` uses `page.keyboard.press()`
- `drag` uses `page.mouse` methods
2. **Event Accuracy**: The implementation ensures proper event sequences:
- Keyboard: focus → keydown → keyup
- Mouse: mousemove → mousedown → mousemove(s) → mouseup
3. **Framework Compatibility**: Works with:
- React/Vue/Angular event handlers
- Phoenix LiveView
- Vanilla JavaScript
4. **Error Handling**: Graceful handling of:
- Element not found
- Invalid parameters
- Timing issues
## Troubleshooting
### Sliders Not Responding to Keyboard
- Ensure the slider is focused first
- Some sliders may require specific key names (e.g., "Left" vs "ArrowLeft")
- Try adding a small delay between key presses
### Drag Not Working
- Verify element is visible and not covered
- Ensure coordinates are within viewport
- Try increasing duration/steps for smoother animation
- Some frameworks may require specific event properties
### LiveView Specific Issues
- LiveView may batch events - try adding delays
- Ensure WebSocket connection is established
- Check browser console for LiveView errors