"""End-to-end tests for the Video Analyzer application using Playwright.""" from __future__ import annotations import subprocess import time from typing import Generator import pytest from playwright.sync_api import Page, expect @pytest.fixture(scope="module") def app_url() -> Generator[str, None, None]: """Start the Gradio app and return its URL.""" # Start the app in background process = subprocess.Popen( ["python", "app.py"], stdout=subprocess.PIPE, stderr=subprocess.PIPE, ) # Wait for app to start time.sleep(10) yield "http://127.0.0.1:7860" # Cleanup process.terminate() process.wait() class TestUnifiedChatbotUI: """E2E tests for the unified chatbot Video Analyzer UI.""" def test_homepage_loads(self, page: Page, app_url: str): """Test that the homepage loads correctly.""" page.goto(app_url) # Check title is visible expect(page.locator("text=Video Analyzer")).to_be_visible() def test_app_subtitle_visible(self, page: Page, app_url: str): """Test that the app subtitle is visible.""" page.goto(app_url) # Check subtitle expect(page.locator("text=Analyze YouTube videos")).to_be_visible() def test_login_button_visible(self, page: Page, app_url: str): """Test that the login button is visible.""" page.goto(app_url) # Look for login button (HuggingFace sign in) login_button = page.locator("button:has-text('Sign in')") expect(login_button).to_be_visible() def test_chatbot_visible(self, page: Page, app_url: str): """Test that the chatbot component is visible.""" page.goto(app_url) # Check for chatbot container chatbot = page.locator("[data-testid='chatbot']") expect(chatbot).to_be_visible() def test_welcome_message_displayed(self, page: Page, app_url: str): """Test that welcome message is shown on load.""" page.goto(app_url) # Wait for page to load page.wait_for_timeout(2000) # Check for welcome message content expect(page.locator("text=Welcome to Video Analyzer")).to_be_visible() def test_message_input_exists(self, page: Page, app_url: str): """Test that the message input field exists.""" page.goto(app_url) # Check for text input with placeholder msg_input = page.locator("textarea[placeholder*='YouTube URL']") expect(msg_input).to_be_visible() def test_send_button_exists(self, page: Page, app_url: str): """Test that the Send button exists.""" page.goto(app_url) # Check for Send button send_btn = page.locator("button:has-text('Send')") expect(send_btn).to_be_visible() def test_clear_chat_button_exists(self, page: Page, app_url: str): """Test that the Clear Chat button exists.""" page.goto(app_url) # Check for Clear Chat button clear_btn = page.locator("button:has-text('Clear Chat')") expect(clear_btn).to_be_visible() def test_knowledge_base_status_visible(self, page: Page, app_url: str): """Test that knowledge base status is displayed.""" page.goto(app_url) # Wait for status to load page.wait_for_timeout(2000) # Check for knowledge base empty message expect(page.locator("text=Knowledge base is empty")).to_be_visible() def test_can_type_in_message_input(self, page: Page, app_url: str): """Test that user can type in the message input.""" page.goto(app_url) # Find and fill the message input msg_input = page.locator("textarea[placeholder*='YouTube URL']") msg_input.fill("https://youtube.com/watch?v=test123") # Verify the input has the text expect(msg_input).to_have_value("https://youtube.com/watch?v=test123") def test_send_button_is_primary(self, page: Page, app_url: str): """Test that Send button has primary styling.""" page.goto(app_url) # Check for primary variant button send_btn = page.locator("button:has-text('Send')").first expect(send_btn).to_be_visible() def test_login_prompt_for_unauthenticated_users(self, page: Page, app_url: str): """Test that unauthenticated users see login prompt in welcome.""" page.goto(app_url) # Wait for welcome message page.wait_for_timeout(2000) # Check for sign in prompt expect(page.locator("text=sign in with HuggingFace")).to_be_visible() def test_clear_chat_works(self, page: Page, app_url: str): """Test that Clear Chat button clears the chatbot.""" page.goto(app_url) # Wait for welcome message to appear page.wait_for_timeout(2000) expect(page.locator("text=Welcome to Video Analyzer")).to_be_visible() # Click clear chat clear_btn = page.locator("button:has-text('Clear Chat')") clear_btn.click() # Wait a moment for clear to process page.wait_for_timeout(500) # Welcome message should be gone (chat cleared) expect(page.locator("text=Welcome to Video Analyzer")).not_to_be_visible() def test_responsive_layout(self, page: Page, app_url: str): """Test that the layout is responsive.""" page.goto(app_url) # Set mobile viewport page.set_viewport_size({"width": 375, "height": 667}) # UI elements should still be visible expect(page.locator("text=Video Analyzer")).to_be_visible() expect(page.locator("button:has-text('Send')")).to_be_visible() def test_chatbot_has_height(self, page: Page, app_url: str): """Test that chatbot has appropriate height.""" page.goto(app_url) # Get chatbot element chatbot = page.locator("[data-testid='chatbot']") box = chatbot.bounding_box() # Should have significant height (500px configured) assert box is not None assert box["height"] >= 400 # Allow some flexibility def test_theme_applied(self, page: Page, app_url: str): """Test that Soft theme is applied (lighter colors).""" page.goto(app_url) # The Soft theme should be applied - check body has gradio styling body = page.locator("body") expect(body).to_be_visible()