Skip to content

Commit 6376f64

Browse files
Overwrite remote with local content
0 parents  commit 6376f64

File tree

14 files changed

+1497
-0
lines changed

14 files changed

+1497
-0
lines changed

.github/workflows/ci.yml

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
name: Python CI
2+
3+
on:
4+
push:
5+
branches: [main]
6+
pull_request:
7+
branches: [main]
8+
9+
env:
10+
PYTHONPATH: .
11+
MCP_SERVER_URL: wss://mcp.openai.com/v1
12+
13+
jobs:
14+
test:
15+
runs-on: ubuntu-latest
16+
17+
steps:
18+
- name: Checkout code
19+
uses: actions/checkout@v2
20+
21+
- name: Set up Python
22+
uses: actions/setup-python@v2
23+
with:
24+
python-version: '3.9'
25+
26+
- name: Cache pip
27+
uses: actions/cache@v2
28+
with:
29+
path: ~/.cache/pip
30+
key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}
31+
restore-keys: |
32+
${{ runner.os }}-pip-
33+
34+
35+
- name: Install dependencies
36+
run: |
37+
python -m venv venv
38+
source venv/bin/activate || .\venv\Scripts\Activate.ps1
39+
pip install -r requirements.txt
40+
playwright install
41+
42+
43+
- name: Run tests
44+
run: |
45+
source venv/bin/activate || .\venv\Scripts\Activate.ps1
46+
pytest -v --maxfail=1 --disable-warnings --html=report.html --self-contained-html
47+
48+
- name: Upload HTML Report
49+
uses: actions/upload-artifact@v3
50+
with:
51+
name: pytest-report
52+
path: report.html

.gitignore

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
venv/
2+
__pycache__/
3+
*.pyc
4+
.playwright/
5+
test-results/
6+
.DS_Store
7+
Thumbs.db
8+
commands.txt
9+
pom.xml

README.md

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
## 🔗 Playwright + MCP Integration
2+
3+
This repository demonstrates how to connect **Playwright-based Python UI tests** to **MCP (Model Context Protocol)** for intelligent testing flows.
4+
5+
### Features
6+
- ✅ Browser automation with Playwright
7+
- 🤖 AI-aware testing using MCP SDK
8+
- 🧩 Configurable YAML for connecting to custom MCP servers
9+
- 💡 Extendable design for adaptive and self-healing test logic
10+
11+
*NOTE: pom.xml is for local-use only*
12+
13+
#### Legacy Java Artifacts (pom.xml)
14+
This project is primarily a **Python / Playwright / MCP** framework. The file `pom.xml` was retained for local reference/legacy compatibility, but **is not committed** to this repository.
15+
To keep it locally without committing:
16+
1. Add `pom.xml` to `.gitignore` (already included).
17+
2. If `pom.xml` was previously tracked, run:
18+
```bash
19+
git rm --cached pom.xml
20+
git commit -m "Remove pom.xml from Git and ignore it"
21+
22+
Run locally:
23+
```powershell
24+
python -m venv venv
25+
.\venv\Scripts\Activate.ps1
26+
pip install -r requirements.txt
27+
pytest -v

docs/setup.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# Setup Guide
2+
3+
## Prerequisites
4+
5+
- Python 3.9+
6+
- Git
7+
- PowerShell
8+
9+
## Run locally
10+
11+
```powershell
12+
python -m venv venv
13+
.\venv\Scripts\Activate.ps1
14+
pip install -r requirements.txt
15+
playwright install
16+
pytest -v
17+
```

playwright-python-mcp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Subproject commit d60ec02b39f54fe40dfe4e9c867012a24cae9e44

playwright_mcp/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# Playwright MCP package

playwright_mcp/browser.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
from playwright.sync_api import sync_playwright
2+
3+
def launch_and_get_title(url: str = "https://example.com") -> str:
4+
"""Launch Chromium headless, navigate to URL, return title."""
5+
with sync_playwright() as p:
6+
browser = p.chromium.launch(headless=True)
7+
page = browser.new_page()
8+
page.goto(url)
9+
title = page.title()
10+
browser.close()
11+
return title
12+
13+
if __name__ == "__main__":
14+
print("Title:", launch_and_get_title())

playwright_mcp/mcp_adapter.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# playwright_mcp/mcp_adapter.py
2+
3+
import asyncio
4+
from playwright.sync_api import sync_playwright
5+
from playwright_mcp.mcp_client import MCPClient
6+
7+
async def run_mcp_test_flow():
8+
"""Run Playwright test with MCP reasoning support."""
9+
# Connect to a local MCP server or model endpoint
10+
mcp = MCPClient("wss://mcp.openai.com/v1") # Example placeholder
11+
await mcp.connect()
12+
13+
from playwright.sync_api import sync_playwright
14+
with sync_playwright() as p:
15+
browser = p.chromium.launch(headless=True)
16+
page = browser.new_page()
17+
page.goto("https://example.com")
18+
title = page.title()
19+
20+
print(f"[Playwright] Page title: {title}")
21+
22+
# Send the title as context to MCP
23+
response = await mcp.send_context({"title": title})
24+
print(f"[MCP] Response: {response}")
25+
26+
browser.close()
27+
28+
await mcp.close()
29+
30+
if __name__ == "__main__":
31+
asyncio.run(run_mcp_test_flow())

playwright_mcp/mcp_client.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# playwright_mcp/mcp_client.py
2+
3+
from mcp import Client, connect_websocket
4+
import asyncio
5+
import json
6+
7+
class MCPClient:
8+
def __init__(self, server_url: str):
9+
self.server_url = server_url
10+
self.client = None
11+
12+
async def connect(self):
13+
print(f"[MCP] Connecting to {self.server_url}...")
14+
self.client = await connect_websocket(self.server_url)
15+
print("[MCP] Connected.")
16+
17+
async def send_context(self, context_data: dict):
18+
"""Send context (like page title or state) to MCP model for reasoning."""
19+
if not self.client:
20+
raise RuntimeError("MCP client not connected.")
21+
response = await self.client.query({"context": context_data})
22+
return response
23+
24+
async def close(self):
25+
if self.client:
26+
await self.client.close()

0 commit comments

Comments
 (0)