n8n-nodes-playwright-test-executor
v1.0.5
Published
n8n Playwright node for executing AI-generated test specifications
Maintainers
Keywords
Readme
n8n-nodes-playwright-test-executor
This is an n8n community node for AI-powered browser test automation using Playwright. It lets you execute AI-generated test specifications in your n8n workflows.
n8n is a fair-code licensed workflow automation platform.
Installation Operations Use Cases Compatibility Resources
Installation
Follow the installation guide in the n8n community nodes documentation.
Install via n8n UI:
- Go to Settings → Community Nodes
- Click Install
- Enter:
n8n-nodes-playwright-test-executor
Or install via command line:
npm install n8n-nodes-playwright-test-executorNote: By default the package runs browsers locally and will attempt to download browser binaries (~1GB) on first use. If you are running n8n in a container and don't want to install browsers inside it, use Remote Execution Mode instead (see below).
Operations
This node supports the following operations:
Standard Operations
- Navigate: Go to a specified URL
- Take Screenshot: Capture a screenshot of a webpage
- Get Text: Extract text from an element using CSS selector
- Click Element: Click on an element using CSS selector
- Fill Form: Fill a form field using CSS selector
AI-Powered Operation
- Execute Test Specification: Execute AI-generated test cases in JSON format
Use Cases
AI-Powered Test Automation
This node is designed to work with AI models (like Gemini, GPT-4, Claude) to create automated testing workflows:
HTML Content → AI Model → Test Specification → Playwright Execution → ResultsExample Workflow:
- HTTP Request node: Fetch HTML from target website
- AI Agent node (Gemini/OpenAI): Analyze HTML and generate test cases
- Playwright node: Execute test specification
- Code node: Format results
- Slack/Email node: Send test report
Test Specification Format
The "Execute Test Specification" operation accepts JSON with the following structure:
[
{
"test_name": "Verify homepage loads correctly",
"steps": [
{
"action": "load_page",
"description": "Navigate to homepage"
},
{
"action": "assert_element_present",
"selector": "h1",
"description": "Check main heading exists"
},
{
"action": "assert_text_present",
"text": "Welcome",
"description": "Verify welcome message"
}
],
"expected_result": "Homepage loads with heading and welcome message"
}
]Supported Actions
Navigation Actions
| Action | Parameters | Description | Example |
|--------|-----------|-------------|---------|
| load_page | - | Navigate to base URL | {"action": "load_page"} |
| go_back | - | Navigate back in history | {"action": "go_back"} |
| go_forward | - | Navigate forward in history | {"action": "go_forward"} |
| reload_page | - | Reload current page | {"action": "reload_page"} |
Element Interaction Actions
| Action | Parameters | Description | Example |
|--------|-----------|-------------|---------|
| click | selector or link | Click element or link text | {"action": "click", "selector": "#button"} |
| fill_input | selector, value | Type text into input field | {"action": "fill_input", "selector": "#email", "value": "[email protected]"} |
| select_option | selector, value | Select dropdown option | {"action": "select_option", "selector": "#country", "value": "USA"} |
| check_checkbox | selector | Check a checkbox | {"action": "check_checkbox", "selector": "#agree"} |
| uncheck_checkbox | selector | Uncheck a checkbox | {"action": "uncheck_checkbox", "selector": "#agree"} |
| hover | selector | Hover mouse over element | {"action": "hover", "selector": ".menu"} |
| press_key | key | Press keyboard key | {"action": "press_key", "key": "Enter"} |
| submit_form | - | Submit a form | {"action": "submit_form"} |
| scroll_to_element | selector | Scroll element into view | {"action": "scroll_to_element", "selector": "#footer"} |
Assertion Actions
| Action | Parameters | Description | Example |
|--------|-----------|-------------|---------|
| assert_element_present | selector | Verify element exists | {"action": "assert_element_present", "selector": "h1"} |
| assert_element_not_present | selector | Verify element does not exist | {"action": "assert_element_not_present", "selector": ".error"} |
| assert_element_visible | selector | Verify element is visible | {"action": "assert_element_visible", "selector": ".modal"} |
| assert_text_present | text | Verify text exists on page | {"action": "assert_text_present", "text": "Welcome"} |
| assert_url_contains | text | Verify URL contains text | {"action": "assert_url_contains", "text": "/dashboard"} |
| assert_page_title | text | Verify page title contains text | {"action": "assert_page_title", "text": "Dashboard"} |
| assert_element_count | selector, count | Verify number of matching elements | {"action": "assert_element_count", "selector": ".item", "count": 5} |
| assert_attribute | selector, attribute, value | Verify element attribute value | {"action": "assert_attribute", "selector": "#link", "attribute": "href", "value": "/home"} |
Wait Actions
| Action | Parameters | Description | Example |
|--------|-----------|-------------|---------|
| wait_for_element | selector, timeout (optional) | Wait for element to appear | {"action": "wait_for_element", "selector": ".loading", "timeout": 5000} |
Utility Actions
| Action | Parameters | Description | Example |
|--------|-----------|-------------|---------|
| take_screenshot | - | Take screenshot (returns base64) | {"action": "take_screenshot"} |
| upload_file | selector, file_path | Upload file to input | {"action": "upload_file", "selector": "#upload", "file_path": "/path/file.pdf"} |
| clear_input | selector | Clear text from input field | {"action": "clear_input", "selector": "#search"} |
| wait | timeout | Wait for specified milliseconds | {"action": "wait", "timeout": 2000} |
| execute_script | script | Execute JavaScript code | {"action": "execute_script", "script": "return document.title"} |
| set_viewport | width, height | Set browser viewport size | {"action": "set_viewport", "width": 1920, "height": 1080} |
Advanced Interaction Actions
| Action | Parameters | Description | Example |
|--------|-----------|-------------|---------|
| double_click | selector | Double-click element | {"action": "double_click", "selector": ".item"} |
| right_click | selector | Right-click element | {"action": "right_click", "selector": ".menu-item"} |
| drag_and_drop | source_selector, target_selector | Drag element to target | {"action": "drag_and_drop", "source_selector": "#item1", "target_selector": "#drop-zone"} |
| focus | selector | Focus on element | {"action": "focus", "selector": "#input"} |
| blur | selector | Remove focus from element | {"action": "blur", "selector": "#input"} |
Dialog Actions
| Action | Parameters | Description | Example |
|--------|-----------|-------------|---------|
| accept_dialog | - | Accept next browser alert/confirm | {"action": "accept_dialog"} |
| dismiss_dialog | - | Dismiss next browser alert/confirm | {"action": "dismiss_dialog"} |
Frame Actions
| Action | Parameters | Description | Example |
|--------|-----------|-------------|---------|
| switch_to_iframe | selector | Switch context to iframe | {"action": "switch_to_iframe", "selector": "#my-iframe"} |
| switch_to_main | - | Switch back to main frame | {"action": "switch_to_main"} |
Cookie Actions
| Action | Parameters | Description | Example |
|--------|-----------|-------------|---------|
| set_cookie | name, value, domain, path | Set browser cookie | {"action": "set_cookie", "name": "session", "value": "abc123"} |
| get_cookie | name | Get cookie value | {"action": "get_cookie", "name": "session"} |
| clear_cookies | - | Clear all cookies | {"action": "clear_cookies"} |
Extended Assertions
| Action | Parameters | Description | Example |
|--------|-----------|-------------|---------|
| assert_element_enabled | selector | Verify element is enabled | {"action": "assert_element_enabled", "selector": "#submit"} |
| assert_element_disabled | selector | Verify element is disabled | {"action": "assert_element_disabled", "selector": "#submit"} |
| assert_checkbox_checked | selector | Verify checkbox is checked | {"action": "assert_checkbox_checked", "selector": "#agree"} |
| assert_checkbox_unchecked | selector | Verify checkbox is unchecked | {"action": "assert_checkbox_unchecked", "selector": "#agree"} |
Data Extraction Actions
| Action | Parameters | Description | Example |
|--------|-----------|-------------|---------|
| get_text | selector | Extract text from element | {"action": "get_text", "selector": ".result"} |
| get_attribute | selector, attribute | Extract element attribute | {"action": "get_attribute", "selector": "#link", "attribute": "href"} |
Browser Options
- Choose between Chromium, Firefox, or WebKit
- Configure headless mode (default: true)
- Adjust operation speed with slow motion option
Execution Mode
| Mode | Description | |------|-------------| | Local | Launches a browser process on the same machine as n8n. Requires browser binaries to be installed (~1GB). | | Remote | Connects to a Playwright server running in a separate container or machine via WebSocket. No browser binaries needed on the n8n host. |
Remote Execution Setup
Run a Playwright server in a separate container:
# docker-compose.yml
services:
n8n:
image: n8nio/n8n
# ...
playwright-server:
image: mcr.microsoft.com/playwright:v1.49.0-noble
command: npx playwright run-server --port 3000 --host 0.0.0.0
ports:
- "3000:3000"Then in the n8n node:
- Set Execution Mode to
Remote - Set Remote WebSocket URL to
ws://playwright-server:3000
This is the recommended approach when running n8n in Docker, as it keeps browser dependencies isolated in a dedicated container.
Results Format
The node returns detailed execution results:
{
"summary": {
"total": 5,
"passed": 4,
"failed": 1
},
"results": [
{
"test_name": "Verify homepage loads correctly",
"status": "passed",
"errors": [],
"details": [...]
}
]
}Compatibility
- Requires n8n version 1.0.0 or later
- Tested with Playwright version 1.49.0
- Supports Windows, macOS, and Linux
System Requirements
- Node.js 18.10 or later
- Approximately 1GB disk space for browser binaries
- Additional system dependencies may be required for browser automation
Example AI Prompt for Test Generation
Use this prompt with your AI model to generate compatible test specifications:
Analyze the provided HTML and generate test cases in JSON format.
SUPPORTED ACTIONS:
Navigation: load_page, go_back, go_forward, reload_page
Interaction: click, fill_input, select_option, check_checkbox, uncheck_checkbox, hover, press_key, submit_form, scroll_to_element, double_click, right_click, drag_and_drop, focus, blur
Assertions: assert_element_present, assert_element_not_present, assert_element_visible, assert_text_present, assert_url_contains, assert_page_title, assert_element_count, assert_attribute, assert_element_enabled, assert_element_disabled, assert_checkbox_checked, assert_checkbox_unchecked
Wait: wait_for_element, wait
Utility: take_screenshot, upload_file, clear_input, execute_script, set_viewport
Dialog: accept_dialog, dismiss_dialog
Frame: switch_to_iframe, switch_to_main
Cookie: set_cookie, get_cookie, clear_cookies
Data Extraction: get_text, get_attribute
Format:
[
{
"test_name": "Test description",
"steps": [
{
"action": "action_name",
"selector": "CSS selector (if applicable)",
"text": "Text to verify (if applicable)",
"value": "Value to input (if applicable)",
"key": "Key to press (if applicable)",
"attribute": "Attribute name (if applicable)",
"count": "Expected count (if applicable)",
"timeout": "Timeout in ms (if applicable)",
"description": "Step description"
}
],
"expected_result": "Expected outcome"
}
]
Example:
[
{
"test_name": "Login test",
"steps": [
{"action": "load_page"},
{"action": "fill_input", "selector": "#username", "value": "testuser"},
{"action": "fill_input", "selector": "#password", "value": "password123"},
{"action": "click", "selector": "#login-button"},
{"action": "wait_for_element", "selector": ".dashboard", "timeout": 5000},
{"action": "assert_url_contains", "text": "/dashboard"},
{"action": "assert_element_visible", "selector": ".welcome-message"}
],
"expected_result": "User successfully logs in and sees dashboard"
}
]Resources
Troubleshooting
Browser executable not found (local mode)
If browsers are not installed correctly:
- Clean the installation:
rm -rf ~/.cache/ms-playwright
# or for Windows:
rmdir /s /q %USERPROFILE%\AppData\Local\ms-playwright- Reinstall the package through n8n's Community Nodes interface
Running in Docker (recommended: use Remote mode)
If you are running n8n in Docker and don't want to install browsers inside the container, switch to Remote Execution Mode and run a separate playwright-server container (see Remote Execution Setup above).
Remote connection refused
- Make sure the Playwright server container is running and reachable from the n8n container
- Check that the WebSocket URL matches the container name and port (e.g.
ws://playwright-server:3000) - Ensure both containers are on the same Docker network
License
Author
Modified from the original n8n-nodes-playwright by Mohamed Toema
Built for AI-powered test automation 🤖🎯
