riazmo's picture
Upload app.py
c886cf8 verified
"""
UI Regression Testing Tool v2.1 - Enhanced Transparency
Full visibility into what's being compared and how.
"""
import gradio as gr
import os
import sys
from datetime import datetime
from pathlib import Path
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
from workflow import run_workflow
from utils.report_generator import generate_transparency_report
LOG_FILE = "app.log"
def clear_logs():
with open(LOG_FILE, "w") as f:
f.write(f"===== Session: {datetime.now()} =====\n\n")
def get_logs():
try:
with open(LOG_FILE, "r") as f:
return f.read()
except:
return "Logs will appear here..."
def run_full_analysis(figma_key, figma_id, url, hf_token, progress=gr.Progress()):
"""Run analysis with full transparency reporting."""
clear_logs()
print(f"\n{'='*60}")
print(f"πŸš€ UI REGRESSION TEST v2.1 (Enhanced Transparency)")
print(f"{'='*60}")
print(f"⏰ {datetime.now()}")
print(f"🌐 Website: {url}")
print(f"πŸ“ Figma: {figma_id}")
print(f"πŸ€— HF Token: {'βœ… Provided' if hf_token else '❌ Not provided'}")
print(f"{'='*60}\n")
if not figma_key or not figma_id or not url:
return (
"❌ Missing required fields:\n- Figma API Key\n- Figma File ID\n- Website URL",
"", "", "", "", None, None, None, None, None, None, get_logs()
)
execution_id = f"exec_{datetime.now().strftime('%Y%m%d_%H%M%S')}"
thread_id = f"thread_{execution_id}"
try:
progress(0.1, desc="🎨 Extracting from Figma...")
print("Starting workflow...")
state = run_workflow(figma_id, figma_key, url, execution_id, thread_id, hf_token)
if not state or not state.values:
return (
"❌ Workflow failed to return results",
"", "", "", "", None, None, None, None, None, None, get_logs()
)
values = state.values
if "failed" in values.get("status", ""):
error = values.get("error_message", "Unknown error")
return (
f"❌ Workflow Failed:\n{error}",
"", "", "", "", None, None, None, None, None, None, get_logs()
)
progress(0.8, desc="πŸ“Š Generating transparency report...")
# Generate detailed transparency report
report = generate_transparency_report(values, execution_id)
# Extract data
overall_score = values.get("overall_score", 0)
viewport_scores = values.get("similarity_scores", {})
element_diffs = values.get("element_differences", [])
ai_analysis = values.get("ai_analysis", {})
figma_sum = values.get("figma_element_summary", {})
website_sum = values.get("website_element_summary", {})
# Status summary
score_emoji = "🟒" if overall_score >= 90 else "🟑" if overall_score >= 70 else "πŸ”΄"
status = f"## {score_emoji} Overall Similarity: {overall_score:.1f}%\n\n"
status += "### Viewport Scores\n"
for vp in ["desktop", "mobile"]:
if vp in viewport_scores:
sc = viewport_scores[vp]
e = "βœ…" if sc >= 90 else "⚠️" if sc >= 70 else "❌"
status += f"- {e} **{vp.capitalize()}**: {sc:.1f}%\n"
else:
status += f"- ❌ **{vp.capitalize()}**: NOT PROCESSED\n"
status += f"\n**Total Differences:** {len(element_diffs)}\n"
# AI summary
ai_summary = "## πŸ€– AI Analysis\n\n"
ai_summary += f"**Mode:** {'AI-Enhanced' if ai_analysis.get('ai_enhanced') else 'Rule-based'}\n\n"
ai_summary += ai_analysis.get("summary", "Analysis complete.") + "\n\n"
issues = ai_analysis.get("priority_issues", [])
if issues:
ai_summary += "### Priority Issues\n"
for i, issue in enumerate(issues, 1):
ai_summary += f"{i}. {issue}\n"
# All differences
all_diffs = f"## πŸ” All Differences ({len(element_diffs)})\n\n"
by_cat = {}
for d in element_diffs:
cat = d.get("category", "other")
by_cat.setdefault(cat, []).append(d)
for cat in sorted(by_cat.keys()):
diffs = by_cat[cat]
emoji = {"size": "πŸ“", "color": "🎨", "typography": "✏️",
"missing": "❌", "border": "πŸ”²"}.get(cat, "β€’")
all_diffs += f"### {emoji} {cat.upper()} ({len(diffs)})\n\n"
for d in diffs:
sev = "πŸ”΄" if d.get("severity") == "high" else "🟑"
elem = d.get("element_name", "?")
desc = d.get("description", "")
vp = d.get("viewport", "")
f_val = d.get("figma_value", "")
w_val = d.get("website_value", "")
all_diffs += f"- {sev} **{elem}** [{vp}]: {desc}\n"
if f_val and w_val:
all_diffs += f" - Figma: `{f_val}` β†’ Website: `{w_val}`\n"
# Get images
figma_shots = values.get("figma_screenshots", {})
website_shots = values.get("website_screenshots", {})
comparison_imgs = values.get("comparison_images", {})
progress(1.0, desc="βœ… Complete!")
return (
status,
ai_summary,
all_diffs,
report.get("workflow_log", ""),
report.get("viewport_status", "") + "\n" + report.get("ai_status", ""),
figma_shots.get("desktop"),
website_shots.get("desktop"),
comparison_imgs.get("desktop"),
figma_shots.get("mobile"),
website_shots.get("mobile"),
comparison_imgs.get("mobile"),
get_logs()
)
except Exception as e:
import traceback
print(f"❌ Error: {e}")
traceback.print_exc()
return (
f"❌ Error: {str(e)}",
"", "", "", "", None, None, None, None, None, None, get_logs()
)
def create_interface():
with gr.Blocks(title="UI Regression v2.1") as demo:
gr.Markdown("""
# 🎨 UI Regression Testing v2.1
*Element-level comparison with full transparency*
""")
with gr.Row():
with gr.Column(scale=1):
gr.Markdown("### βš™οΈ Configuration")
figma_key = gr.Textbox(label="Figma API Key *", type="password")
figma_id = gr.Textbox(label="Figma File ID *")
website_url = gr.Textbox(label="Website URL *")
hf_token = gr.Textbox(label="HF Token (Optional)", type="password")
btn = gr.Button("πŸš€ Run Analysis", variant="primary", size="lg")
gr.Markdown("""
**Figma Requirements:**
- Frame with "Desktop" in name (~1440px)
- Frame with "Mobile" in name (~375px)
""")
with gr.Column(scale=2):
status_box = gr.Markdown("*Run analysis to see results*")
with gr.Tabs():
with gr.TabItem("πŸ€– AI Insights"):
ai_box = gr.Markdown()
with gr.TabItem("πŸ” All Differences"):
diff_box = gr.Markdown()
with gr.TabItem("πŸ“‹ Workflow Log"):
workflow_box = gr.Markdown()
with gr.TabItem("πŸ”§ Debug Info"):
debug_box = gr.Markdown()
gr.Markdown("### πŸ–₯️ Desktop")
with gr.Row():
figma_desktop = gr.Image(label="Figma", height=250)
website_desktop = gr.Image(label="Website", height=250)
comparison_desktop = gr.Image(label="Diff", height=350)
gr.Markdown("### πŸ“± Mobile")
with gr.Row():
figma_mobile = gr.Image(label="Figma", height=350)
website_mobile = gr.Image(label="Website", height=350)
comparison_mobile = gr.Image(label="Diff", height=450)
with gr.Accordion("πŸ“œ Logs", open=False):
log_box = gr.Code(language="python", lines=15)
btn.click(
run_full_analysis,
inputs=[figma_key, figma_id, website_url, hf_token],
outputs=[
status_box, ai_box, diff_box, workflow_box, debug_box,
figma_desktop, website_desktop, comparison_desktop,
figma_mobile, website_mobile, comparison_mobile, log_box
]
)
return demo
if __name__ == "__main__":
Path(LOG_FILE).parent.mkdir(parents=True, exist_ok=True)
with open(LOG_FILE, "w") as f:
f.write(f"===== Startup: {datetime.now()} =====\n\n")
print(f"πŸš€ UI Regression v2.1 - {datetime.now()}")
demo = create_interface()
demo.launch(server_name="0.0.0.0", server_port=7860)