#!/usr/bin/env python3
"""Regression for the live-test bugs (Phase 8 follow-up):
BUG A Tectonic was invoked with `--synctex 0` -> the `0` is consumed as the
INPUT and the real .tex becomes an "unexpected argument", so the PDF
never compiles. Fix: minimal `tectonic --outdir
--keep-logs `.
BUG B content.js stripChrome() read textContent off a DETACHED clone, joining
adjacent elements with NO whitespace -> Frankenstein tokens like
"engineergreater hyderabad" / "managerzamp". Fix: insert separators.
BUG C A jobs LIST / search / recommendations page (title "Top job picks for
you") produced junk keywords and a 0% resume. Fix: detect + fail loudly.
Deterministic, ASCII-only, no network, no LaTeX engine required.
"""
import os
import re
import sys
ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.insert(0, ROOT)
_ok = True
def check(name, cond, detail=""):
global _ok
status = "PASS" if cond else "FAIL"
if not cond:
_ok = False
print(f" [{status}] {name}" + (f" {detail}" if detail else ""))
return cond
def read(rel):
with open(os.path.join(ROOT, rel), encoding="utf-8") as f:
return f.read()
print("=" * 70)
print("Phase 8 follow-up: extraction + LaTeX-compile bug fixes")
print("=" * 70)
# ── BUG A: Tectonic command line ─────────────────────────────────────────────
print("[A] Tectonic invocation is well-formed (no --synctex value trap)")
from src.latex_resume import _engine_commands
cmds = _engine_commands("tectonic", "/tmp/out/resume.tex", "/tmp/out")
cmd = cmds[0]
check("engine is tectonic", cmd[0] == "tectonic", " ".join(cmd))
check("no --synctex flag", "--synctex" not in cmd)
check("no bare numeric positional ('0')", "0" not in cmd)
check("input .tex is the final positional",
cmd[-1] == "/tmp/out/resume.tex", cmd[-1])
check("--outdir points at the out dir",
"--outdir" in cmd and cmd[cmd.index("--outdir") + 1] == "/tmp/out")
# ── BUG B: stripChrome inserts whitespace separators ─────────────────────────
print("[B] content.js stripChrome separates tokens (no concatenation)")
content = read("extension/content.js")
check("inserts a separator text node between elements",
"createTextNode(' \\n')" in content)
check("reads textContent after inserting separators",
"clone.textContent" in content)
# ── BUG C: non-job / listing-page detection ──────────────────────────────────
print("[C] content.js rejects jobs-list / recommendation pages")
check("NON_JOB_TITLES table present", "NON_JOB_TITLES" in content)
check("'top job picks for you' is blacklisted",
"top job picks for you" in content.lower())
check("looksLikeListingJunk() exists", "looksLikeListingJunk" in content)
check("flags repeated 'easy apply' rows", "easy apply" in content.lower())
check("sets extraction_reason='not_a_job_posting'",
"not_a_job_posting" in content)
check("raises the min-JD-length gate to 80",
"length < 80" in content)
print("[C] popup.js surfaces the not-a-posting reason")
popup = read("extension/popup/popup.js")
check("popup handles not_a_job_posting", "not_a_job_posting" in popup)
# ── Realistic LaTeX injection coverage (no compile needed) ────────────────────
print("[D] Realistic PM LaTeX + JD -> honest keyword coverage")
from src.latex_resume import optimize_latex_resume
SAMPLE_LATEX = r"""
\documentclass{article}
\begin{document}
\section*{Summary}
Product Manager with experience shipping B2B SaaS products, partnering with
engineering and design, and running discovery with customers.
\section*{Experience}
\textbf{Senior Product Manager} \\ Acme SaaS (2021--2024)
\begin{itemize}
\item Owned the product roadmap for a B2B analytics platform.
\item Ran A/B tests and user research to prioritize the backlog.
\item Partnered with engineering on go-to-market for two launches.
\end{itemize}
\end{document}
"""
JD = (
"We are hiring a Product Manager for our B2B SaaS platform. You will own the "
"product roadmap, define product strategy, run user research and discovery, "
"prioritize the backlog, partner with engineering and design, lead "
"go-to-market, run A/B testing and experimentation, define KPIs and metrics, "
"and work with stakeholders. Experience with agile, data analysis, SQL, "
"machine learning and generative AI product features is a plus. Strong "
"stakeholder management and roadmapping skills required."
)
report = optimize_latex_resume(
SAMPLE_LATEX, JD, maximum_ats_mode=True, confirmed_terms=[],
blocked_terms=[], compile_pdf=False, out_dir=None, job_title="pm",
)
pct = int(report.get("pct", 0) or 0)
injected = report.get("injected", [])
gated = report.get("gated", {}) or {}
blocked_injected = [t for t in injected
if "blocked" in str(gated.get(t, "")).lower()]
print(f" coverage pct = {pct}% injected = {len(injected)} terms")
check("coverage >= 85% on a well-matched PM JD (path can reach 90%+)",
pct >= 85, f"{pct}%")
check("no blocked/fabrication term injected", not blocked_injected,
str(blocked_injected))
for fab in ("cissp", "pmp", "cuda", "12+ years"):
blob = (report.get("tex", "") or "").lower()
check(f"no fabrication term in output: '{fab}'", fab not in blob)
# ── Guaranteed PDF fallback + multi-engine resilience ────────────────────────
print("[E] Guaranteed PDF fallback + multi-engine resilience")
import tempfile
import shutil as _sh
from src.latex_resume import render_text_to_pdf, latex_engines_available
_tmp = tempfile.mkdtemp()
_fb = os.path.join(_tmp, "fb.pdf")
_out = render_text_to_pdf(
"Jane Doe\nProduct Manager\n\nEXPERIENCE\nOwned the product roadmap.", _fb)
check("render_text_to_pdf() produces a non-empty PDF (no LaTeX engine needed)",
bool(_out) and os.path.exists(_fb) and os.path.getsize(_fb) > 0,
f"{os.path.getsize(_fb) if os.path.exists(_fb) else 0} bytes")
_sh.rmtree(_tmp, ignore_errors=True)
check("latex_engines_available() returns a list (multi-engine fallback)",
isinstance(latex_engines_available(), list))
api = read("api_server.py")
check("both LaTeX branches add a pdf_fallback flag", api.count("pdf_fallback") >= 4,
f"count={api.count('pdf_fallback')}")
check("API fallback uses render_text_to_pdf", "render_text_to_pdf" in api)
# ── Panel <-> popup run sync ─────────────────────────────────────────────────
print("[F] Side-panel <-> popup run-state sync")
check("popup reflects a 'running' change from another surface",
"entry.status === 'running'" in popup)
check("popup surfaces the pdf_fallback note", "pdf_fallback" in popup)
print("-" * 70)
print("PASS - extraction junk-guard + tectonic fix + PDF fallback + sync verified"
if _ok else "FAIL - see above")
sys.exit(0 if _ok else 1)