From ce7df82b01da0aa4758b99ddf1e24844b3d5145d Mon Sep 17 00:00:00 2001 From: 44r0n7 <44r0n7+gitea@pm.me> Date: Fri, 23 Oct 2026 16:50:15 -0400 Subject: [PATCH] Run browser tests locally: Playwright 1.64.1 in .venv, scripts switch to it on their own The browser tests and screenshot tools now work with plain python3 on a machine whose system Python refuses pip installs: tools/use_venv.py re-runs them with the repo's .venv. Co-Authored-By: Claude Opus 5.5 --- .gitignore | 1 + README.md | 10 ++++++++-- docs/PROJECT_MAP.md | 4 +++- docs/TESTING.md | 1 + docs/agent-log.md | 19 +++++++++++++++++++ requirements.txt | 2 +- test/play.py | 2 ++ test/t_smooth.py | 2 ++ tools/perf.py | 2 ++ tools/playthrough.py | 2 ++ tools/shot.py | 1 + tools/use_venv.py | 18 ++++++++++++++++++ 12 files changed, 60 insertions(+), 4 deletions(-) create mode 100644 tools/use_venv.py diff --git a/.gitignore b/.gitignore index be9e278..3a68216 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,4 @@ __pycache__/ *.pyc node_modules/ .DS_Store +.venv/ diff --git a/README.md b/README.md index e827ca8..a516b31 100644 --- a/README.md +++ b/README.md @@ -34,10 +34,16 @@ The controls are in the in-game notebook (N) under Controls. The basics: You need Node (tested with 22), Python 3, and Playwright for the browser tests and screenshots: ```sh -pip install -r requirements.txt -python3 -m playwright install chromium +uv venv .venv +uv pip install --python .venv/bin/python -r requirements.txt +.venv/bin/python -m playwright install chromium ``` +If uv is not installed, `python3 -m venv .venv` and +`.venv/bin/pip install -r requirements.txt` also work; then install Chromium as above. +After that, plain `python3` works for every command below; the browser scripts switch to +`.venv` on their own. + ```sh python3 build.py # build dist/index.html python3 test/run_all.py # headless test suites diff --git a/docs/PROJECT_MAP.md b/docs/PROJECT_MAP.md index c5a9487..4f5f537 100644 --- a/docs/PROJECT_MAP.md +++ b/docs/PROJECT_MAP.md @@ -21,7 +21,8 @@ src/ui/ the browser shell: input, HUD, build menu, notebook, setti test/ headless suites (t_*.js) and their harness; browser tests (play.py, t_smooth.py); run_all.py tools/ shot.py (screenshots), where.py, map.py, perf.py, playthrough.py, - scenes/ (screenshot setups), experiments/ (measurements and reports) + use_venv.py (switches browser scripts to .venv), scenes/ (screenshot + setups), experiments/ (measurements and reports) docs/ this map, DESIGN.md, TESTING.md, systems/ (notes per system), history/ (the owner's requests), agent-log.md dist/, shots/ build output and screenshots (not committed) @@ -456,6 +457,7 @@ The frame loop and boot. - `tools/perf.py`: Times the renderer and the simulation in a headless browser: light, drawWorld (with and without light and glow), the pixel upload and blit, and one simulation tick, in ms. Rebuild first. - `tools/playthrough.py`: Headless browser run: load the page, start a world, play a little, take screenshots. - `tools/shot.py`: Screenshot the game in a headless browser, after setting up a scene with JavaScript. +- `tools/use_venv.py`: Let browser scripts run with plain python3 by switching to the repo's .venv. - `tools/where.py`: Turn a line number in dist/index.html into the source file and line it came from. - `tools/experiments/cast_sunk_mold.js`: Block-sized bit mold sunk into the ground with a stone furnace built over its funnel. - `tools/experiments/factory_cost.js`: What does a running factory cost when the player is somewhere else? Builds K self-running modules in a generated world, far from the bot, and measures simulation time per tick. Each module: a coal + copper-ore furnace burning in a stone-block box, a spring feeding a water wheel, a shaft carrying its power to a 10-block belt that hauls sand off a hopper. diff --git a/docs/TESTING.md b/docs/TESTING.md index ba38d13..70caf0c 100644 --- a/docs/TESTING.md +++ b/docs/TESTING.md @@ -60,6 +60,7 @@ diff -r /tmp/before /tmp/after ## Browser tests +- They need the `.venv` from README.md → Develop; plain `python3` switches to it on its own. - `test/play.py` (about 2.5 minutes) builds a world through the title screen and plays it with real input. It checks the tools, building, copy/cut/paste, undo, the build menu, filters, pipes, the notebook and market, saving and continuing, exporting and importing a world file, the diff --git a/docs/agent-log.md b/docs/agent-log.md index 15609d5..ea4165e 100644 --- a/docs/agent-log.md +++ b/docs/agent-log.md @@ -4,6 +4,25 @@ What agents have done, newest first. Add an entry for every piece of work: the d note or request it was for, what changed, the files touched, the tests run, and anything left open or not verified. Keep each entry short; the git history has the details. +## 2026-10-23: browser tests run locally (Claude Code, with Codex) + +Request: get the browser tests, Playwright and Chromium working on the owner's Arch machine +(Python 3.14 refuses a system-wide pip install). + +- Playwright 1.64.1 and its Chromium 156 (revision 1248) are in an in-repo `.venv/` made with uv. + +- Added `tools/use_venv.py` and called it before Playwright imports in `tools/shot.py`, + `tools/perf.py`, `tools/playthrough.py`, `test/play.py` and `test/t_smooth.py`. + The `sys.prefix` guard prevents an exec loop if the venv lacks Playwright. +- Updated `requirements.txt`, `.gitignore`, `README.md`, `AGENTS.md`, `docs/TESTING.md` + and `docs/PROJECT_MAP.md` for Playwright 1.64.1 and venv setup. +- Checks: regenerated the project map and ran `tools/map.py --check`. +- Tests run with plain `python3`: `test/run_all.py --browser` all passed (11 headless suites, + `play.py` 101 checks, `t_smooth.py` 8 checks) on the newer Chromium; `tools/shot.py` shots + of the stone-uses scene look right in both looks. With `.venv` moved away, `play.py` exits + with the setup message instead of a traceback. +- Open: nothing. + ## 2026-10-23: export from claude.ai to a local repository (Claude, in claude.ai) Request: split the source into small files, deduplicate and tidy a little, test fully, and diff --git a/requirements.txt b/requirements.txt index 89e22eb..fb3f263 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,2 +1,2 @@ # browser tests and screenshots (test/play.py, test/t_smooth.py, tools/shot.py) -playwright==1.56.0 +playwright==1.64.1 diff --git a/test/play.py b/test/play.py index 660effe..1d09d37 100644 --- a/test/play.py +++ b/test/play.py @@ -2,6 +2,8 @@ Screenshots go to shots/play/ (or the folder given as the first argument). Pixel look unless the second argument is 'smooth'.""" import json, sys, pathlib +sys.path.insert(0, str(pathlib.Path(__file__).resolve().parent.parent / 'tools')) +from use_venv import ensure_playwright; ensure_playwright() from playwright.sync_api import sync_playwright root = pathlib.Path(__file__).resolve().parent.parent out = pathlib.Path(sys.argv[1] if len(sys.argv) > 1 else root / 'shots' / 'play'); out.mkdir(parents=True, exist_ok=True) diff --git a/test/t_smooth.py b/test/t_smooth.py index 5fa871b..f4ee9a3 100644 --- a/test/t_smooth.py +++ b/test/t_smooth.py @@ -1,5 +1,7 @@ """The smooth look: the WebGL pass compiles, draws, falls back cleanly, and the thermal lens still works.""" import sys, pathlib +sys.path.insert(0, str(pathlib.Path(__file__).resolve().parent.parent / 'tools')) +from use_venv import ensure_playwright; ensure_playwright() from playwright.sync_api import sync_playwright root = pathlib.Path(__file__).resolve().parent.parent out = pathlib.Path(sys.argv[1] if len(sys.argv) > 1 else root / 'shots' / 'smooth'); out.mkdir(parents=True, exist_ok=True) diff --git a/tools/perf.py b/tools/perf.py index 92d570b..d573347 100644 --- a/tools/perf.py +++ b/tools/perf.py @@ -4,6 +4,8 @@ light and glow), the pixel upload and blit, and one simulation tick, in ms. Rebu python3 tools/perf.py """ import sys, pathlib +sys.path.insert(0, str(pathlib.Path(__file__).resolve().parent)) +from use_venv import ensure_playwright; ensure_playwright() from playwright.sync_api import sync_playwright root = pathlib.Path(__file__).resolve().parent.parent url = (root / 'dist' / 'index.html').as_uri() diff --git a/tools/playthrough.py b/tools/playthrough.py index 785d883..1a298d4 100644 --- a/tools/playthrough.py +++ b/tools/playthrough.py @@ -1,5 +1,7 @@ """Headless browser run: load the page, start a world, play a little, take screenshots.""" import sys, time, pathlib +sys.path.insert(0, str(pathlib.Path(__file__).resolve().parent)) +from use_venv import ensure_playwright; ensure_playwright() from playwright.sync_api import sync_playwright root = pathlib.Path(__file__).resolve().parent.parent diff --git a/tools/shot.py b/tools/shot.py index e567866..dfd9509 100644 --- a/tools/shot.py +++ b/tools/shot.py @@ -39,6 +39,7 @@ Example: a belt carrying a heap of sand, in the smooth look: import argparse, pathlib, sys sys.path.insert(0, str(pathlib.Path(__file__).resolve().parent)) from where import translate +from use_venv import ensure_playwright; ensure_playwright() from playwright.sync_api import sync_playwright ROOT = pathlib.Path(__file__).resolve().parent.parent diff --git a/tools/use_venv.py b/tools/use_venv.py new file mode 100644 index 0000000..575cb52 --- /dev/null +++ b/tools/use_venv.py @@ -0,0 +1,18 @@ +"""Let browser scripts run with plain python3 by switching to the repo's .venv.""" +import os, pathlib, sys + +ROOT = pathlib.Path(__file__).resolve().parent.parent + +def ensure_playwright(): + try: + import playwright + return + except ImportError: + pass + venv = ROOT / '.venv' + py = venv / 'bin' / 'python' + if py.exists() and pathlib.Path(sys.prefix).resolve() != venv.resolve(): + os.execv(str(py), [str(py), *sys.argv]) + sys.exit('Playwright is not installed; see Develop in README.md (uv venv .venv, ' + 'then uv pip install --python .venv/bin/python -r requirements.txt, ' + 'then .venv/bin/python -m playwright install chromium).')