feat: add standalone Playwright recorder tool with Docker-based codegen
- introduce repo-local, ephemeral Playwright codegen workflow - add executable codegen script using official Playwright Docker image - persist generated recordings under recordings/ (git-ignored, .gitkeep) - add minimal Makefile with install and codegen targets - switch project license to MIT - improve README with clear usage, requirements, and design rationale - add MIRRORS file for multi-remote setup - clean up gitignore for generated artifacts and node tooling
This commit is contained in:
13
.gitignore
vendored
13
.gitignore
vendored
@@ -1,3 +1,16 @@
|
|||||||
|
# Playwright recorder outputs (generated artifacts)
|
||||||
|
recordings/*
|
||||||
|
!recordings/.gitkeep
|
||||||
|
|
||||||
|
# Ephemeral workspace used by recorder
|
||||||
|
recordings/.work/
|
||||||
|
|
||||||
|
# Optional: if you later add node/npm files here
|
||||||
|
node_modules/
|
||||||
|
npm-debug.log*
|
||||||
|
pnpm-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
|
||||||
.venv/
|
.venv/
|
||||||
dist/
|
dist/
|
||||||
build/
|
build/
|
||||||
|
|||||||
22
LICENSE
22
LICENSE
@@ -1 +1,21 @@
|
|||||||
All rights reserved by Kevin Veen-Birkenbach
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2026 Kevin Veen-Birkenbach
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
|
|||||||
3
MIRRORS
Normal file
3
MIRRORS
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
git@github.com:kevinveenbirkenbach/playwright-recorder.git
|
||||||
|
ssh://git@code.infinito.nexus:2201/kevinveenbirkenbach/playwright-recorder.git
|
||||||
|
ssh://git@git.veen.world:2201/kevinveenbirkenbach/playwright-recorder.git
|
||||||
21
Makefile
Normal file
21
Makefile
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
.PHONY: help install codegen
|
||||||
|
|
||||||
|
## 📖 Show help
|
||||||
|
help:
|
||||||
|
@echo ""
|
||||||
|
@echo "🎭 playwright-recorder"
|
||||||
|
@echo ""
|
||||||
|
@echo "Targets:"
|
||||||
|
@echo " make install 🔧 Prepare the recorder (chmod +x)"
|
||||||
|
@echo " make codegen 🎥 Record Playwright tests via GUI"
|
||||||
|
@echo " make help 📖 Show this help"
|
||||||
|
@echo ""
|
||||||
|
|
||||||
|
## 🔧 One-time setup
|
||||||
|
install:
|
||||||
|
@chmod +x scripts/codegen.sh
|
||||||
|
@echo "✔ scripts/codegen.sh is now executable"
|
||||||
|
|
||||||
|
## 🎥 Run Playwright Codegen (GUI recording)
|
||||||
|
codegen:
|
||||||
|
bash scripts/codegen.sh
|
||||||
140
README.md
140
README.md
@@ -1,6 +1,138 @@
|
|||||||
# playwright-recorder
|
# 🎭 playwright-recorder
|
||||||
|
|
||||||
Homepage: https://github.com/kevinveenbirkenbach/playwright-recorder
|
> A small, reproducible Playwright **recording / codegen tool**
|
||||||
|
> built around **Docker**, **X11/XWayland**, and **ephemeral workspaces**
|
||||||
|
|
||||||
## Author
|
🔗 Homepage: https://github.com/kevinveenbirkenbach/playwright-recorder
|
||||||
Kevin Veen-Birkenbach <kevin@veen.world>
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ✨ What is this?
|
||||||
|
|
||||||
|
`playwright-recorder` is a **developer tool** for recording Playwright tests via
|
||||||
|
the official Playwright **codegen** feature — without polluting your project:
|
||||||
|
|
||||||
|
- 🎥 **GUI-based recording** (Playwright Inspector)
|
||||||
|
- 🧼 **Always fresh** (no reused state, no lockfile pain)
|
||||||
|
- 🐳 **Runs fully in Docker**
|
||||||
|
- 🗂️ **Repo-local, git-ignored workspace**
|
||||||
|
- 📄 **Only generated tests are persisted**
|
||||||
|
- 🚫 **No `/tmp` usage**
|
||||||
|
|
||||||
|
Perfect for:
|
||||||
|
- recording login flows
|
||||||
|
- capturing UI regressions
|
||||||
|
- generating first test drafts
|
||||||
|
- infra-heavy projects where Playwright does *not* belong in the main repo
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
* `recordings/` is **ignored by git**
|
||||||
|
* `.gitkeep` ensures the folder exists
|
||||||
|
* ephemeral workspace lives in `recordings/.work/` and is auto-cleaned
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🚀 Usage
|
||||||
|
|
||||||
|
### 1️⃣ Requirements
|
||||||
|
|
||||||
|
* Docker
|
||||||
|
* X11 or XWayland (Wayland-only will NOT work)
|
||||||
|
* `xhost`
|
||||||
|
|
||||||
|
On Arch Linux:
|
||||||
|
|
||||||
|
## ⚙️ Installation (one-time)
|
||||||
|
|
||||||
|
Prepare the recorder script:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
make install
|
||||||
|
```
|
||||||
|
|
||||||
|
This makes `scripts/codegen.sh` executable.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🎥 Start recording
|
||||||
|
|
||||||
|
```bash
|
||||||
|
make codegen
|
||||||
|
```
|
||||||
|
|
||||||
|
Or with a start URL:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./scripts/codegen.sh https://example.com/login
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📤 Output
|
||||||
|
|
||||||
|
* 📄 Generated test:
|
||||||
|
|
||||||
|
```text
|
||||||
|
recordings/codegen.spec.ts
|
||||||
|
```
|
||||||
|
|
||||||
|
* 🧼 Ephemeral workspace (auto-deleted):
|
||||||
|
|
||||||
|
```text
|
||||||
|
recordings/.work/
|
||||||
|
```
|
||||||
|
|
||||||
|
Nothing else touches your repo.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ⚙️ Configuration (optional)
|
||||||
|
|
||||||
|
Environment variables:
|
||||||
|
|
||||||
|
| Variable | Default | Description |
|
||||||
|
| -------------------- | ----------------- | ------------------- |
|
||||||
|
| `PLAYWRIGHT_VERSION` | `1.58.1` | Playwright version |
|
||||||
|
| `PLAYWRIGHT_IMAGE` | auto | Docker image tag |
|
||||||
|
| `RECORDINGS_DIR` | `recordings` | Output directory |
|
||||||
|
| `OUTPUT_FILE` | `codegen.spec.ts` | Generated file name |
|
||||||
|
| `TARGET` | `playwright-test` | Codegen target |
|
||||||
|
| `DISPLAY` | `:0` | X11 display |
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
OUTPUT_FILE=login.spec.ts make codegen
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🧠 Design philosophy
|
||||||
|
|
||||||
|
* ❌ Not a test runner
|
||||||
|
* ❌ Not CI tooling
|
||||||
|
* ❌ Not framework glue
|
||||||
|
* ✅ A **focused recording utility**
|
||||||
|
* ✅ One job, done well
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔐 Security note
|
||||||
|
|
||||||
|
`xhost +local:docker` is used **temporarily** to allow GUI access.
|
||||||
|
Access is **revoked automatically** when the script exits.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🧑💻 Author
|
||||||
|
|
||||||
|
Kevin Veen-Birkenbach
|
||||||
|
📧 [kevin@veen.world](mailto:kevin@veen.world)
|
||||||
|
🏡 [www.veen.world](https://www.veen.world)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📜 License
|
||||||
|
|
||||||
|
MIT License – see [LICENSE](LICENSE)
|
||||||
|
|||||||
11
flake.nix
11
flake.nix
@@ -1,11 +0,0 @@
|
|||||||
{
|
|
||||||
description = "playwright-recorder";
|
|
||||||
inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
|
|
||||||
outputs = { self, nixpkgs }:
|
|
||||||
let system = "x86_64-linux"; pkgs = import nixpkgs { inherit system; };
|
|
||||||
in {
|
|
||||||
devShells.${system}.default = pkgs.mkShell {
|
|
||||||
packages = with pkgs; [ python312 python312Packages.pytest python312Packages.ruff ];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
[build-system]
|
|
||||||
requires = ["setuptools>=68", "wheel"]
|
|
||||||
build-backend = "setuptools.build_meta"
|
|
||||||
|
|
||||||
[project]
|
|
||||||
name = "playwright-recorder"
|
|
||||||
version = "0.1.0"
|
|
||||||
description = ""
|
|
||||||
readme = "README.md"
|
|
||||||
requires-python = ">=3.10"
|
|
||||||
authors = [{ name = "Kevin Veen-Birkenbach", email = "kevin@veen.world" }]
|
|
||||||
license = { text = "All rights reserved by Kevin Veen-Birkenbach" }
|
|
||||||
urls = { Homepage = "https://github.com/kevinveenbirkenbach/playwright-recorder" }
|
|
||||||
|
|
||||||
dependencies = []
|
|
||||||
|
|
||||||
[tool.setuptools]
|
|
||||||
package-dir = {"" = "src"}
|
|
||||||
|
|
||||||
[tool.setuptools.packages.find]
|
|
||||||
where = ["src"]
|
|
||||||
0
recordings/.gitkeep
Normal file
0
recordings/.gitkeep
Normal file
122
scripts/codegen.sh
Executable file
122
scripts/codegen.sh
Executable file
@@ -0,0 +1,122 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
# playwright-recorder: Playwright Codegen (fresh, repo-local workspace)
|
||||||
|
#
|
||||||
|
# Purpose:
|
||||||
|
# - ALWAYS start fresh (no dependency on repo state)
|
||||||
|
# - Do NOT use /tmp for recordings/workspace
|
||||||
|
# - Use repo-local ignored workspace: recordings/.work
|
||||||
|
# - Persist generated tests into repo-local ignored dir: recordings/
|
||||||
|
# - Run everything inside the official Playwright container (version pinned)
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
PLAYWRIGHT_VERSION="${PLAYWRIGHT_VERSION:-1.58.1}"
|
||||||
|
PLAYWRIGHT_IMAGE="${PLAYWRIGHT_IMAGE:-mcr.microsoft.com/playwright:v${PLAYWRIGHT_VERSION}-jammy}"
|
||||||
|
|
||||||
|
RECORDINGS_DIR="${RECORDINGS_DIR:-recordings}"
|
||||||
|
OUTPUT_FILE="${OUTPUT_FILE:-codegen.spec.ts}"
|
||||||
|
TARGET="${TARGET:-playwright-test}"
|
||||||
|
|
||||||
|
START_URL="${1:-}"
|
||||||
|
|
||||||
|
die() { echo "ERROR: $*" >&2; exit 1; }
|
||||||
|
warn() { echo "WARNING: $*" >&2; }
|
||||||
|
|
||||||
|
require_cmd() {
|
||||||
|
command -v "$1" >/dev/null 2>&1 || die "Missing command: $1"
|
||||||
|
}
|
||||||
|
|
||||||
|
repo_root() {
|
||||||
|
git rev-parse --show-toplevel 2>/dev/null || pwd
|
||||||
|
}
|
||||||
|
|
||||||
|
require_cmd docker
|
||||||
|
require_cmd xhost
|
||||||
|
|
||||||
|
: "${DISPLAY:=:0}"
|
||||||
|
|
||||||
|
ROOT="$(repo_root)"
|
||||||
|
REC_DIR="${ROOT}/${RECORDINGS_DIR}"
|
||||||
|
WORK_DIR="${REC_DIR}/.work"
|
||||||
|
|
||||||
|
mkdir -p "${REC_DIR}"
|
||||||
|
|
||||||
|
cleanup() {
|
||||||
|
# revoke X11 permission
|
||||||
|
xhost -local:docker >/dev/null 2>&1 || true
|
||||||
|
# remove ephemeral workspace
|
||||||
|
rm -rf "${WORK_DIR}" >/dev/null 2>&1 || true
|
||||||
|
}
|
||||||
|
trap cleanup EXIT
|
||||||
|
|
||||||
|
# X11 socket sanity check (helpful hint only)
|
||||||
|
if [[ "${DISPLAY}" == ":0" && ! -S /tmp/.X11-unix/X0 ]]; then
|
||||||
|
warn "No /tmp/.X11-unix/X0 socket detected."
|
||||||
|
warn "You might be on pure Wayland without XWayland."
|
||||||
|
warn "Playwright codegen requires X11/XWayland (or a nested X server)."
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Always fresh workspace (repo-local, ignored)
|
||||||
|
rm -rf "${WORK_DIR}"
|
||||||
|
mkdir -p "${WORK_DIR}/tests"
|
||||||
|
|
||||||
|
# Minimal ephemeral Playwright project (workspace-local)
|
||||||
|
cat > "${WORK_DIR}/package.json" <<EOF
|
||||||
|
{
|
||||||
|
"name": "playwright-recorder-ephemeral",
|
||||||
|
"private": true,
|
||||||
|
"type": "commonjs",
|
||||||
|
"devDependencies": {
|
||||||
|
"@playwright/test": "${PLAYWRIGHT_VERSION}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
|
||||||
|
cat > "${WORK_DIR}/playwright.config.ts" <<'EOF'
|
||||||
|
import { defineConfig } from '@playwright/test';
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
testDir: './tests',
|
||||||
|
use: {
|
||||||
|
trace: 'on-first-retry',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# X11 access control for Docker (temporary)
|
||||||
|
xhost +local:docker >/dev/null
|
||||||
|
|
||||||
|
echo "Playwright image : ${PLAYWRIGHT_IMAGE}"
|
||||||
|
echo "Repo root : ${ROOT}"
|
||||||
|
echo "Recordings dir : ${REC_DIR}"
|
||||||
|
echo "Workspace dir : ${WORK_DIR}"
|
||||||
|
echo "Output file : ${OUTPUT_FILE}"
|
||||||
|
echo "DISPLAY : ${DISPLAY}"
|
||||||
|
if [[ -n "${START_URL}" ]]; then
|
||||||
|
echo "Start URL : ${START_URL}"
|
||||||
|
fi
|
||||||
|
echo
|
||||||
|
|
||||||
|
INSTALL_CMD="npm install --no-audit --no-fund"
|
||||||
|
|
||||||
|
CODEGEN_CMD="./node_modules/.bin/playwright codegen --target=${TARGET} --output=/recordings/${OUTPUT_FILE}"
|
||||||
|
if [[ -n "${START_URL}" ]]; then
|
||||||
|
CODEGEN_CMD="${CODEGEN_CMD} ${START_URL}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
docker run --rm -it \
|
||||||
|
--ipc=host \
|
||||||
|
--network host \
|
||||||
|
-e "DISPLAY=${DISPLAY}" \
|
||||||
|
-v /tmp/.X11-unix:/tmp/.X11-unix \
|
||||||
|
-v "${WORK_DIR}:/work" \
|
||||||
|
-v "${REC_DIR}:/recordings" \
|
||||||
|
-w /work \
|
||||||
|
"${PLAYWRIGHT_IMAGE}" \
|
||||||
|
bash -lc "${INSTALL_CMD}; ${CODEGEN_CMD}"
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "✔ Codegen finished"
|
||||||
|
echo "✔ Generated file: ${RECORDINGS_DIR}/${OUTPUT_FILE}"
|
||||||
Reference in New Issue
Block a user