docs: refresh operator runbook and creatives copy after prod cutover
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
100
scripts/smoke_operator_login.py
Normal file
100
scripts/smoke_operator_login.py
Normal file
@@ -0,0 +1,100 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Login as marketing@ on app.4ventures.es and smoke dashboard routes."""
|
||||
from __future__ import annotations
|
||||
|
||||
import re
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
from playwright.sync_api import sync_playwright
|
||||
|
||||
ROOT = Path("/Users/4ventures/4ventures-client-portal")
|
||||
SHOT = ROOT / "scripts/dokploy-shots"
|
||||
SHOT.mkdir(parents=True, exist_ok=True)
|
||||
APP = "https://app.4ventures.es"
|
||||
CREDS = ROOT / ".ops" / "marketing-credentials.txt"
|
||||
|
||||
|
||||
def load_creds() -> tuple[str, str]:
|
||||
email = "marketing@4ventures.es"
|
||||
password = ""
|
||||
for line in CREDS.read_text(encoding="utf-8").splitlines():
|
||||
if line.startswith("email="):
|
||||
email = line.split("=", 1)[1].strip()
|
||||
if line.startswith("password="):
|
||||
password = line.split("=", 1)[1].strip()
|
||||
if not password:
|
||||
raise SystemExit("missing password in .ops/marketing-credentials.txt")
|
||||
return email, password
|
||||
|
||||
|
||||
def main() -> int:
|
||||
email, password = load_creds()
|
||||
with sync_playwright() as p:
|
||||
browser = p.chromium.launch(headless=True)
|
||||
page = browser.new_page(viewport={"width": 1400, "height": 1100})
|
||||
page.goto(f"{APP}/login", wait_until="networkidle", timeout=90000)
|
||||
page.wait_for_timeout(1000)
|
||||
page.screenshot(path=str(SHOT / "app_login.png"), full_page=True)
|
||||
|
||||
# Fill login form
|
||||
email_inp = page.locator('input[type="email"], input[name="email"], input[placeholder*="mail" i]')
|
||||
pass_inp = page.locator('input[type="password"]')
|
||||
print("email_inputs", email_inp.count(), "pass_inputs", pass_inp.count(), flush=True)
|
||||
if not email_inp.count() or not pass_inp.count():
|
||||
print("LOGIN_FORM_MISSING", flush=True)
|
||||
print(page.inner_text("body")[:500].replace("\n", " | "), flush=True)
|
||||
browser.close()
|
||||
return 2
|
||||
email_inp.first.fill(email)
|
||||
pass_inp.first.fill(password)
|
||||
submit = page.locator('button[type="submit"], button').filter(has_text=re.compile(r"Entrar|Login|Iniciar|Acceder|Sign", re.I))
|
||||
if submit.count():
|
||||
submit.first.click()
|
||||
else:
|
||||
page.locator('button[type="submit"]').first.click()
|
||||
page.wait_for_timeout(4000)
|
||||
page.screenshot(path=str(SHOT / "app_after_login.png"), full_page=True)
|
||||
print("url", page.url, flush=True)
|
||||
body = page.inner_text("body")
|
||||
bad = bool(re.search(r"invalid|incorrect|error|credencial", body, re.I)) and "/login" in page.url
|
||||
print("still_login", "/login" in page.url, "errorish", bad, flush=True)
|
||||
print("title_snip", " | ".join([ln.strip() for ln in body.splitlines() if ln.strip()][:12]), flush=True)
|
||||
|
||||
if "/login" in page.url:
|
||||
browser.close()
|
||||
print("LOGIN_FAILED", flush=True)
|
||||
return 3
|
||||
|
||||
# Smoke routes
|
||||
results = {}
|
||||
for path in ("/dashboard", "/dashboard/agencia", "/dashboard/creatives", "/dashboard/kpis"):
|
||||
page.goto(f"{APP}{path}", wait_until="networkidle", timeout=60000)
|
||||
page.wait_for_timeout(1200)
|
||||
code_ish = page.url
|
||||
txt = page.inner_text("body")[:300].replace("\n", " | ")
|
||||
results[path] = {"url": code_ish, "snip": txt}
|
||||
safe = path.strip("/").replace("/", "_") or "root"
|
||||
page.screenshot(path=str(SHOT / f"app_{safe}.png"), full_page=True)
|
||||
print(path, "->", code_ish, flush=True)
|
||||
print(" ", txt[:180], flush=True)
|
||||
|
||||
# API with cookies from context
|
||||
cookies = page.context.cookies()
|
||||
cookie_header = "; ".join(f"{c['name']}={c['value']}" for c in cookies if "app.4ventures.es" in c.get("domain", "") or c.get("domain", "").endswith("4ventures.es"))
|
||||
print("cookies", len(cookies), flush=True)
|
||||
|
||||
browser.close()
|
||||
|
||||
# Outside: health still ok
|
||||
import urllib.request
|
||||
|
||||
with urllib.request.urlopen("https://app.4ventures.es/api/health", timeout=12) as r:
|
||||
print("health", r.read().decode()[:180], flush=True)
|
||||
|
||||
print("SUCCESS_LOGIN", flush=True)
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
Reference in New Issue
Block a user