bibimbap/docs/development/screenshot-guide.py

133 lines
4.7 KiB
Python

"""
bibimbap 스크린샷 캡처 스크립트
비인증 페이지 + 인증 후 세부 화면 상태 모두 캡처.
사용법:
# 비인증 페이지만
python3 docs/development/screenshot-guide.py
# 인증 포함 전체 (로그인 계정 필요)
SCREENSHOT_EMAIL=user@example.com SCREENSHOT_PASSWORD=pw \
python3 docs/development/screenshot-guide.py
"""
import os
import sys
from playwright.sync_api import sync_playwright
CHROME = "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"
OUT_DIR = "/tmp/bibimbap-screenshots"
BASE_URL = "http://localhost:8080"
EMAIL = os.environ.get("SCREENSHOT_EMAIL", "")
PASSWORD = os.environ.get("SCREENSHOT_PASSWORD", "")
# 비인증 페이지
ANON_PAGES = [
("/", "01-home-anon.png"),
("/login", "02-login.png"),
("/signup", "03-signup.png"),
("/posts", "04-posts-list.png"),
("/recruit", "05-recruit-list.png"),
("/game/3", "06-game-detail-anon.png"),
("/terms", "07-terms.png"),
]
os.makedirs(OUT_DIR, exist_ok=True)
def capture(page, path, filename, *, full_page=True):
page.goto(f"{BASE_URL}{path}", wait_until="networkidle")
page.screenshot(path=os.path.join(OUT_DIR, filename), full_page=full_page)
print(f"{filename}")
def do_login(page):
"""로그인 폼 제출 후 세션 획득. CSRF 토큰은 폼에서 추출."""
page.goto(f"{BASE_URL}/login", wait_until="networkidle")
page.fill("input[name='email']", EMAIL)
page.fill("input[name='password']", PASSWORD)
page.click("button[type='submit']")
page.wait_for_url(lambda url: "/login" not in url, timeout=8000)
def capture_review_form(page):
"""게임 상세 — 리뷰 작성 폼 노출 상태."""
page.goto(f"{BASE_URL}/game/3", wait_until="networkidle")
# JS가 로그인 상태 확인 후 composer를 보여줄 때까지 대기 (최대 3초)
try:
page.wait_for_function(
"document.getElementById('game-review-composer') && "
"!document.getElementById('game-review-composer').hasAttribute('hidden')",
timeout=5000,
)
except Exception:
# JS가 숨긴 채로 두면 강제 노출 (스크린샷 전용)
page.evaluate(
"document.getElementById('game-review-composer')?.removeAttribute('hidden')"
)
page.screenshot(
path=os.path.join(OUT_DIR, "13-game-review-form.png"), full_page=False
)
print(" ✓ 13-game-review-form.png")
def capture_comment_form(page):
"""게임 상세 — 댓글 작성 폼 노출 상태."""
page.goto(f"{BASE_URL}/game/3", wait_until="networkidle")
try:
page.wait_for_function(
"document.getElementById('game-comment-composer') && "
"!document.getElementById('game-comment-composer').hasAttribute('hidden')",
timeout=5000,
)
except Exception:
page.evaluate(
"document.getElementById('game-comment-composer')?.removeAttribute('hidden')"
)
# 댓글 섹션으로 스크롤
page.evaluate(
"document.getElementById('game-comment-composer')?.scrollIntoView({block:'center'})"
)
page.screenshot(
path=os.path.join(OUT_DIR, "14-game-comment-form.png"), full_page=False
)
print(" ✓ 14-game-comment-form.png")
with sync_playwright() as p:
browser = p.chromium.launch(
executable_path=CHROME,
headless=True,
args=["--no-sandbox"],
)
page = browser.new_page(viewport={"width": 1400, "height": 900})
print("── 비인증 페이지 ──────────────────────────────")
for path, filename in ANON_PAGES:
capture(page, path, filename)
if EMAIL and PASSWORD:
print("\n── 로그인 후 세부 화면 ─────────────────────────")
try:
do_login(page)
print(" ✓ 로그인 성공")
capture(page, "/", "08-home-loggedin.png")
capture(page, "/profile", "09-profile.png")
capture(page, "/posts/new", "10-posts-form.png")
capture(page, "/recruit/new", "11-recruit-form.png")
capture(page, "/game/3", "12-game-detail-loggedin.png")
capture_review_form(page)
capture_comment_form(page)
except Exception as e:
print(f" ✗ 로그인 실패 또는 인증 페이지 캡처 오류: {e}", file=sys.stderr)
else:
print("\n※ SCREENSHOT_EMAIL / SCREENSHOT_PASSWORD 미설정 — 비인증 페이지만 캡처됨")
print(" 전체 캡처: SCREENSHOT_EMAIL=... SCREENSHOT_PASSWORD=... python3 docs/development/screenshot-guide.py")
browser.close()
print(f"\n완료: {OUT_DIR}/")