b2f6cb1977
- login-form-nonce replaces form-nonce (Login plugin 3.x) - task value is login.login not login - login success check uses form presence, not status code (/post returns 200 unauthenticated) - entry discovery searches by title, handles .en.md suffix - cleanup uses docker exec to remove files owned by www-data Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
125 lines
5.7 KiB
Bash
Executable File
125 lines
5.7 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# End-to-end test: logs in, submits the post form, verifies entry is created on disk.
|
|
# Requires GRAV_TEST_USER and GRAV_TEST_PASS (set in .env or environment).
|
|
# Cleans up the test entry after the test.
|
|
set -euo pipefail
|
|
|
|
BASE_URL="${GRAV_BASE_URL:-http://localhost:8081}"
|
|
USER="${GRAV_TEST_USER:-}"
|
|
PASS="${GRAV_TEST_PASS:-}"
|
|
TRACKER="user/pages/01.tracker"
|
|
COOKIE_JAR="$(mktemp /tmp/grav-test-cookies.XXXXXX)"
|
|
PASS_COUNT=0
|
|
FAIL_COUNT=0
|
|
TEST_SLUG=""
|
|
|
|
cleanup() {
|
|
rm -f "$COOKIE_JAR"
|
|
if [ -n "$TEST_SLUG" ] && [ -d "$TRACKER/$TEST_SLUG" ]; then
|
|
# Entry files are created by www-data inside Docker; use docker exec to remove
|
|
if docker exec intotheeast_grav rm -rf "/var/www/html/$TRACKER/$TEST_SLUG" 2>/dev/null; then
|
|
echo " [cleanup] Removed test entry: $TEST_SLUG"
|
|
else
|
|
rm -rf "$TRACKER/$TEST_SLUG" 2>/dev/null || \
|
|
echo " [cleanup] Warning: could not remove $TEST_SLUG (permission denied — remove manually)"
|
|
fi
|
|
fi
|
|
}
|
|
trap cleanup EXIT
|
|
|
|
ok() { echo " ✓ $1"; PASS_COUNT=$((PASS_COUNT+1)); }
|
|
fail() { echo " ✗ $1"; FAIL_COUNT=$((FAIL_COUNT+1)); }
|
|
die() { echo ""; echo "FATAL: $1"; exit 1; }
|
|
|
|
echo ""
|
|
echo "Post form integration test — $BASE_URL"
|
|
echo "────────────────────────────────────────"
|
|
|
|
[ -n "$USER" ] || die "GRAV_TEST_USER not set. Add it to .env"
|
|
[ -n "$PASS" ] || die "GRAV_TEST_PASS not set. Add it to .env"
|
|
|
|
# ── Step 1: get login page + nonce ───────────────────────────────────────────
|
|
LOGIN_HTML=$(curl -sf -c "$COOKIE_JAR" -b "$COOKIE_JAR" "$BASE_URL/login") \
|
|
|| die "Could not reach $BASE_URL/login"
|
|
|
|
LOGIN_NONCE=$(echo "$LOGIN_HTML" | grep -o 'name="login-form-nonce" value="[^"]*"' | head -1 | sed 's/.*value="\([^"]*\)".*/\1/')
|
|
[ -n "$LOGIN_NONCE" ] || die "Could not extract login form nonce — is the site running?"
|
|
|
|
# ── Step 2: log in ───────────────────────────────────────────────────────────
|
|
LOGIN_STATUS=$(curl -sf -o /dev/null -w "%{http_code}" \
|
|
-c "$COOKIE_JAR" -b "$COOKIE_JAR" \
|
|
-L \
|
|
-d "username=${USER}&password=${PASS}&login-form-nonce=${LOGIN_NONCE}&task=login.login" \
|
|
"$BASE_URL/login")
|
|
|
|
# After login, fetch /post and verify we see the post form (not the login form)
|
|
# /post returns 200 for both auth and unauth users — check for form-nonce to confirm login
|
|
POST_CHECK_HTML=$(curl -sf -c "$COOKIE_JAR" -b "$COOKIE_JAR" "$BASE_URL/post") \
|
|
|| die "Could not reach $BASE_URL/post"
|
|
|
|
POST_STATUS=$(echo "$POST_CHECK_HTML" | grep -c 'name="form-nonce"' || true)
|
|
[ "$POST_STATUS" -gt 0 ] && ok "Login succeeded and /post is accessible" \
|
|
|| die "Login failed (post form not visible) — check GRAV_TEST_USER / GRAV_TEST_PASS"
|
|
|
|
# ── Step 3: extract post form nonce from already-fetched HTML ────────────────
|
|
POST_HTML="$POST_CHECK_HTML"
|
|
|
|
POST_NONCE=$(echo "$POST_HTML" | grep -o 'name="form-nonce" value="[^"]*"' | head -1 | sed 's/.*value="\([^"]*\)".*/\1/')
|
|
[ -n "$POST_NONCE" ] || die "Could not extract post form nonce"
|
|
ok "Post form loaded and nonce extracted"
|
|
|
|
# ── Step 4: submit test entry ────────────────────────────────────────────────
|
|
TEST_TITLE="Automated Test Entry"
|
|
TEST_DATE=$(date "+%Y-%m-%d %H:%M")
|
|
TEST_SLUG_EXPECTED=$(date "+%Y-%m-%d-%H%M")-automated-test-entry
|
|
|
|
SUBMIT_BODY=$(curl -sf \
|
|
-c "$COOKIE_JAR" -b "$COOKIE_JAR" \
|
|
-d "data[title]=${TEST_TITLE}" \
|
|
-d "data[date]=${TEST_DATE}" \
|
|
-d "data[content]=This+is+an+automated+test+entry.+Safe+to+delete." \
|
|
-d "data[location_city]=Test+City" \
|
|
-d "data[location_country]=Test+Country" \
|
|
-d "form-nonce=${POST_NONCE}" \
|
|
-d "task=process" \
|
|
"$BASE_URL/post")
|
|
|
|
ok "Form submitted"
|
|
|
|
# ── Step 5: verify entry exists on disk ─────────────────────────────────────
|
|
sleep 1 # give Grav a moment to write the file
|
|
|
|
# Find an entry containing the test title — search all .md and .en.md files
|
|
# add-page-by-form may produce date-based slugs in various formats
|
|
ENTRY_FILE=$(grep -rl "$TEST_TITLE" "$TRACKER" --include="*.md" 2>/dev/null | head -1)
|
|
|
|
if [ -n "$ENTRY_FILE" ]; then
|
|
TEST_SLUG=$(basename "$(dirname "$ENTRY_FILE")")
|
|
ok "Entry created on disk: $TEST_SLUG"
|
|
|
|
# Verify file name is entry.md or entry.en.md (template-named file)
|
|
ENTRY_BASENAME=$(basename "$ENTRY_FILE")
|
|
if [ "$ENTRY_BASENAME" = "entry.md" ] || [ "$ENTRY_BASENAME" = "entry.en.md" ]; then
|
|
ok "Entry file exists: $ENTRY_BASENAME"
|
|
else
|
|
fail "Entry file has unexpected name: $ENTRY_BASENAME (expected entry.md or entry.en.md)"
|
|
fi
|
|
|
|
# Verify the title is in the frontmatter
|
|
if grep -q "$TEST_TITLE" "$ENTRY_FILE"; then
|
|
ok "Title appears in entry frontmatter"
|
|
else
|
|
fail "Title not found in $ENTRY_BASENAME — frontmatter may be malformed"
|
|
fi
|
|
else
|
|
fail "No entry created on disk — form processing failed silently"
|
|
echo " Searched $TRACKER for files containing: $TEST_TITLE"
|
|
fi
|
|
|
|
# ── Result ───────────────────────────────────────────────────────────────────
|
|
echo "────────────────────────────────────────"
|
|
echo " $PASS_COUNT passed, $FAIL_COUNT failed"
|
|
echo ""
|
|
|
|
[ $FAIL_COUNT -eq 0 ]
|