Add browser Python editor with Pyodide, user auth, and workspace API
- FastAPI serves static UI, file CRUD under code/ and read-only lib/ - Pyodide worker runs Python and Jedi completions in the browser - SQLite accounts: login/register, session cookies, superuser user management - Optional EDITOR_API_KEY, AUTH_* env vars, .env.example - Pipenv, pytest, Selenium smoke test, README Made-with: Cursor
This commit is contained in:
101
tests/test_browser.py
Normal file
101
tests/test_browser.py
Normal file
@@ -0,0 +1,101 @@
|
||||
import importlib
|
||||
import socket
|
||||
import subprocess
|
||||
import sys
|
||||
import time
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
|
||||
def _is_port_open(port: int) -> bool:
|
||||
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
|
||||
sock.settimeout(0.3)
|
||||
return sock.connect_ex(("127.0.0.1", port)) == 0
|
||||
|
||||
|
||||
@pytest.mark.integration
|
||||
def test_browser_create_file_not_forced_into_new(tmp_path):
|
||||
playwright = pytest.importorskip("playwright.sync_api")
|
||||
sync_playwright = playwright.sync_playwright
|
||||
|
||||
editor_dir = Path(__file__).resolve().parents[1]
|
||||
port = 8123
|
||||
env = dict(
|
||||
**__import__("os").environ,
|
||||
WORKSPACE_ROOT=str(tmp_path),
|
||||
AUTH_ENABLED="false",
|
||||
AUTH_DATABASE_PATH=str(tmp_path / "playwright_auth.db"),
|
||||
)
|
||||
|
||||
server = subprocess.Popen(
|
||||
[
|
||||
sys.executable,
|
||||
"-m",
|
||||
"uvicorn",
|
||||
"app:app",
|
||||
"--app-dir",
|
||||
"src",
|
||||
"--host",
|
||||
"127.0.0.1",
|
||||
"--port",
|
||||
str(port),
|
||||
],
|
||||
cwd=str(editor_dir),
|
||||
env=env,
|
||||
stdout=subprocess.DEVNULL,
|
||||
stderr=subprocess.DEVNULL,
|
||||
)
|
||||
try:
|
||||
for _ in range(50):
|
||||
if _is_port_open(port):
|
||||
break
|
||||
time.sleep(0.1)
|
||||
else:
|
||||
pytest.fail("Server did not start in time")
|
||||
|
||||
with sync_playwright() as p:
|
||||
try:
|
||||
browser = p.chromium.launch()
|
||||
except Exception as exc: # pragma: no cover
|
||||
pytest.skip(f"Playwright browser not installed: {exc}")
|
||||
|
||||
page = browser.new_page()
|
||||
page.goto(f"http://127.0.0.1:{port}/editor", wait_until="networkidle")
|
||||
page.click("#new-file-btn")
|
||||
page.fill("#new-filename", "browser-test.txt")
|
||||
page.click("#create-file-btn")
|
||||
page.wait_for_timeout(500)
|
||||
browser.close()
|
||||
|
||||
assert (tmp_path / "code" / "browser-test.txt").exists()
|
||||
assert not (tmp_path / "new" / "browser-test.txt").exists()
|
||||
finally:
|
||||
server.terminate()
|
||||
try:
|
||||
server.wait(timeout=3)
|
||||
except subprocess.TimeoutExpired:
|
||||
server.kill()
|
||||
|
||||
|
||||
def test_new_file_uses_api_file_route(tmp_path, monkeypatch):
|
||||
import editor_app.config as config
|
||||
import editor_app.db.session as db_sess
|
||||
import editor_app.main as main
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
monkeypatch.setenv("WORKSPACE_ROOT", str(tmp_path))
|
||||
monkeypatch.setenv("AUTH_ENABLED", "false")
|
||||
monkeypatch.setenv("AUTH_DATABASE_PATH", str(tmp_path / "auth_route.db"))
|
||||
config.WORKSPACE_ROOT = tmp_path
|
||||
db_sess.reset_engine()
|
||||
importlib.reload(main)
|
||||
client = TestClient(main.app)
|
||||
|
||||
response = client.post(
|
||||
"/api/file/code/routing-check.txt",
|
||||
json={"content": "ok"},
|
||||
)
|
||||
assert response.status_code == 200
|
||||
assert (tmp_path / "code" / "routing-check.txt").exists()
|
||||
assert not (tmp_path / "new" / "routing-check.txt").exists()
|
||||
Reference in New Issue
Block a user