#!/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())