Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 5c0e19d08f | |||
| cf9aa5bf88 | |||
| a739a3fc5c | |||
| 5079e85eb5 | |||
| 5e9da6dc63 |
10
CHANGELOG.md
10
CHANGELOG.md
@@ -1,3 +1,13 @@
|
|||||||
|
## [1.1.1] - 2026-02-05
|
||||||
|
|
||||||
|
* Fix permission issues by running Playwright Docker containers with the host UID/GID, preventing root-owned files during codegen and replay.
|
||||||
|
|
||||||
|
|
||||||
|
## [1.1.0] - 2026-02-05
|
||||||
|
|
||||||
|
* 🎬 Enable replay of recorded Playwright tests in headless mode
|
||||||
|
|
||||||
|
|
||||||
## [1.0.0] - 2026-02-05
|
## [1.0.0] - 2026-02-05
|
||||||
|
|
||||||
* Official Release 🥳
|
* Official Release 🥳
|
||||||
|
|||||||
6
Makefile
6
Makefile
@@ -19,3 +19,9 @@ install:
|
|||||||
## 🎥 Run Playwright Codegen (GUI recording)
|
## 🎥 Run Playwright Codegen (GUI recording)
|
||||||
codegen:
|
codegen:
|
||||||
bash scripts/codegen.sh
|
bash scripts/codegen.sh
|
||||||
|
|
||||||
|
.PHONY: replay
|
||||||
|
|
||||||
|
## ▶ Replay recorded Playwright tests (headless)
|
||||||
|
replay:
|
||||||
|
bash scripts/replay.sh
|
||||||
|
|||||||
30
README.md
30
README.md
@@ -37,12 +37,18 @@ Perfect for:
|
|||||||
|
|
||||||
### 1️⃣ Requirements
|
### 1️⃣ Requirements
|
||||||
|
|
||||||
* Docker
|
- Docker
|
||||||
* X11 or XWayland (Wayland-only will NOT work)
|
- X11 or XWayland (Wayland-only will NOT work)
|
||||||
* `xhost`
|
- `xhost`
|
||||||
|
|
||||||
On Arch Linux:
|
On Arch Linux:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo pacman -S --needed xorg-xhost
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## ⚙️ Installation (one-time)
|
## ⚙️ Installation (one-time)
|
||||||
|
|
||||||
Prepare the recorder script:
|
Prepare the recorder script:
|
||||||
@@ -69,6 +75,24 @@ Or with a start URL:
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## ▶ Replay recorded tests (headless)
|
||||||
|
|
||||||
|
Run all recorded tests:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
make replay
|
||||||
|
```
|
||||||
|
|
||||||
|
Run a specific test file:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./scripts/replay.sh recordings/login.spec.ts
|
||||||
|
```
|
||||||
|
|
||||||
|
Replay runs **headless**, without X11, and does **not** require `xhost`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## 📤 Output
|
## 📤 Output
|
||||||
|
|
||||||
* 📄 Generated test:
|
* 📄 Generated test:
|
||||||
|
|||||||
@@ -37,6 +37,10 @@ require_cmd xhost
|
|||||||
|
|
||||||
: "${DISPLAY:=:0}"
|
: "${DISPLAY:=:0}"
|
||||||
|
|
||||||
|
# Run containers as the current host user to avoid root-owned files in bind mounts.
|
||||||
|
USER_ID="$(id -u)"
|
||||||
|
GROUP_ID="$(id -g)"
|
||||||
|
|
||||||
ROOT="$(repo_root)"
|
ROOT="$(repo_root)"
|
||||||
REC_DIR="${ROOT}/${RECORDINGS_DIR}"
|
REC_DIR="${ROOT}/${RECORDINGS_DIR}"
|
||||||
WORK_DIR="${REC_DIR}/.work"
|
WORK_DIR="${REC_DIR}/.work"
|
||||||
@@ -107,6 +111,8 @@ if [[ -n "${START_URL}" ]]; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
docker run --rm -it \
|
docker run --rm -it \
|
||||||
|
--user "${USER_ID}:${GROUP_ID}" \
|
||||||
|
-e HOME=/tmp \
|
||||||
--ipc=host \
|
--ipc=host \
|
||||||
--network host \
|
--network host \
|
||||||
-e "DISPLAY=${DISPLAY}" \
|
-e "DISPLAY=${DISPLAY}" \
|
||||||
|
|||||||
118
scripts/replay.sh
Normal file
118
scripts/replay.sh
Normal file
@@ -0,0 +1,118 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
# playwright-recorder: Replay Playwright tests (headless)
|
||||||
|
#
|
||||||
|
# Purpose:
|
||||||
|
# - Replay previously generated Playwright tests
|
||||||
|
# - Run fully headless
|
||||||
|
# - Use Docker + official Playwright image
|
||||||
|
# - No GUI, no X11, no xhost
|
||||||
|
#
|
||||||
|
# Usage:
|
||||||
|
# ./scripts/replay.sh
|
||||||
|
# ./scripts/replay.sh recordings/login.spec.ts
|
||||||
|
#
|
||||||
|
# Optional env vars:
|
||||||
|
# PLAYWRIGHT_VERSION=1.58.1
|
||||||
|
# PLAYWRIGHT_IMAGE=mcr.microsoft.com/playwright:v1.58.1-jammy
|
||||||
|
# RECORDINGS_DIR=recordings
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
PLAYWRIGHT_VERSION="${PLAYWRIGHT_VERSION:-1.58.1}"
|
||||||
|
PLAYWRIGHT_IMAGE="${PLAYWRIGHT_IMAGE:-mcr.microsoft.com/playwright:v${PLAYWRIGHT_VERSION}-jammy}"
|
||||||
|
|
||||||
|
RECORDINGS_DIR="${RECORDINGS_DIR:-recordings}"
|
||||||
|
TEST_FILE="${1:-}"
|
||||||
|
|
||||||
|
die() { echo "ERROR: $*" >&2; exit 1; }
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
# Run containers as the current host user to avoid root-owned files in bind mounts.
|
||||||
|
USER_ID="$(id -u)"
|
||||||
|
GROUP_ID="$(id -g)"
|
||||||
|
|
||||||
|
ROOT="$(repo_root)"
|
||||||
|
REC_DIR="${ROOT}/${RECORDINGS_DIR}"
|
||||||
|
|
||||||
|
[[ -d "${REC_DIR}" ]] || die "Recordings dir not found: ${REC_DIR}"
|
||||||
|
|
||||||
|
# Build ephemeral workspace
|
||||||
|
WORK_DIR="${REC_DIR}/.replay-work"
|
||||||
|
|
||||||
|
# Robust cleanup: handle possible permission issues from previous runs.
|
||||||
|
if [[ -e "${WORK_DIR}" ]]; then
|
||||||
|
chmod -R u+rwX "${WORK_DIR}" 2>/dev/null || true
|
||||||
|
rm -rf "${WORK_DIR}" 2>/dev/null || true
|
||||||
|
fi
|
||||||
|
|
||||||
|
mkdir -p "${WORK_DIR}/tests"
|
||||||
|
|
||||||
|
cleanup() {
|
||||||
|
rm -rf "${WORK_DIR}" >/dev/null 2>&1 || true
|
||||||
|
}
|
||||||
|
trap cleanup EXIT
|
||||||
|
|
||||||
|
# Copy recorded tests into workspace
|
||||||
|
if [[ -n "${TEST_FILE}" ]]; then
|
||||||
|
[[ -f "${ROOT}/${TEST_FILE}" ]] || die "Test file not found: ${TEST_FILE}"
|
||||||
|
cp "${ROOT}/${TEST_FILE}" "${WORK_DIR}/tests/"
|
||||||
|
else
|
||||||
|
shopt -s nullglob
|
||||||
|
cp "${REC_DIR}"/*.spec.ts "${WORK_DIR}/tests/" || die "No *.spec.ts found in ${REC_DIR}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Minimal Playwright project
|
||||||
|
cat > "${WORK_DIR}/package.json" <<EOF
|
||||||
|
{
|
||||||
|
"name": "playwright-replay",
|
||||||
|
"private": true,
|
||||||
|
"type": "commonjs",
|
||||||
|
"devDependencies": {
|
||||||
|
"@playwright/test": "${PLAYWRIGHT_VERSION}"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"test": "playwright test"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
|
||||||
|
cat > "${WORK_DIR}/playwright.config.ts" <<'EOF'
|
||||||
|
import { defineConfig } from '@playwright/test';
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
testDir: './tests',
|
||||||
|
use: {
|
||||||
|
headless: true,
|
||||||
|
trace: 'retain-on-failure',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
EOF
|
||||||
|
|
||||||
|
echo "▶ Replaying Playwright tests"
|
||||||
|
echo "Image : ${PLAYWRIGHT_IMAGE}"
|
||||||
|
echo "Workspace : ${WORK_DIR}"
|
||||||
|
echo "Tests : ${TEST_FILE:-all recordings}"
|
||||||
|
echo
|
||||||
|
|
||||||
|
docker run --rm \
|
||||||
|
--network host \
|
||||||
|
--user "${USER_ID}:${GROUP_ID}" \
|
||||||
|
-e HOME=/tmp \
|
||||||
|
-v "${WORK_DIR}:/work" \
|
||||||
|
-w /work \
|
||||||
|
"${PLAYWRIGHT_IMAGE}" \
|
||||||
|
bash -lc "npm install --no-audit --no-fund && npx playwright test"
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "✔ Replay finished"
|
||||||
Reference in New Issue
Block a user