Spaces:
Sleeping
Sleeping
| """ | |
| 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) | |