|
|
|
|
|
""" |
|
|
E2E Tests for Document Processing Workflow |
|
|
|
|
|
Tests the core document processing functionality: |
|
|
- Data room selection and processing |
|
|
- Document upload and indexing |
|
|
- Search functionality |
|
|
- Error handling for document operations |
|
|
""" |
|
|
|
|
|
import pytest |
|
|
import os |
|
|
from playwright.sync_api import Page, expect |
|
|
from .conftest import StreamlitPageHelpers |
|
|
|
|
|
|
|
|
class TestDocumentProcessing: |
|
|
"""Test document processing and data room functionality""" |
|
|
|
|
|
def test_data_room_selection_interface(self, page: Page, streamlit_helpers: StreamlitPageHelpers, sample_test_data): |
|
|
"""Test that data room selection interface is functional""" |
|
|
streamlit_helpers.wait_for_streamlit_load() |
|
|
|
|
|
|
|
|
sidebar = page.locator("[data-testid='stSidebar']") |
|
|
|
|
|
|
|
|
data_room_elements = sidebar.locator("text=/.*[Dd]ata.*[Rr]oom.*|.*VDR.*|.*[Dd]ocument.*/") |
|
|
expect(data_room_elements.first).to_be_visible() |
|
|
|
|
|
def test_document_processing_workflow(self, page: Page, streamlit_helpers: StreamlitPageHelpers, sample_test_data): |
|
|
"""Test the complete document processing workflow""" |
|
|
streamlit_helpers.wait_for_streamlit_load() |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
processing_elements = page.locator("text=/.*[Pp]rocess.*|.*[Aa]nalyze.*|.*[Bb]uild.*|.*[Ii]ndex.*/") |
|
|
|
|
|
if processing_elements.count() > 0: |
|
|
|
|
|
process_button = page.locator("button:has-text(/.*[Pp]rocess.*|.*[Bb]uild.*|.*[Aa]nalyze.*/)") |
|
|
|
|
|
if process_button.count() > 0: |
|
|
|
|
|
process_button.first.click() |
|
|
|
|
|
|
|
|
|
|
|
processing_indicators = page.locator(".stSpinner, [data-testid='stSpinner'], .stStatus, text=/.*[Pp]rocessing.*|.*[Ll]oading.*/") |
|
|
|
|
|
|
|
|
page.wait_for_timeout(2000) |
|
|
|
|
|
def test_file_upload_interface(self, page: Page, streamlit_helpers: StreamlitPageHelpers): |
|
|
"""Test file upload interface if available""" |
|
|
streamlit_helpers.wait_for_streamlit_load() |
|
|
|
|
|
|
|
|
file_uploaders = page.locator("input[type='file'], [data-testid='stFileUploader']") |
|
|
|
|
|
if file_uploaders.count() > 0: |
|
|
expect(file_uploaders.first).to_be_visible() |
|
|
|
|
|
|
|
|
file_uploader = file_uploaders.first |
|
|
accept_attr = file_uploader.get_attribute("accept") |
|
|
|
|
|
|
|
|
if accept_attr: |
|
|
assert any(fmt in accept_attr for fmt in [".pdf", ".md", ".txt", ".docx"]), \ |
|
|
f"File uploader should accept document formats, got: {accept_attr}" |
|
|
|
|
|
def test_search_functionality(self, page: Page, streamlit_helpers: StreamlitPageHelpers): |
|
|
"""Test document search functionality""" |
|
|
streamlit_helpers.wait_for_streamlit_load() |
|
|
|
|
|
|
|
|
search_elements = page.locator("input[placeholder*='search'], input[aria-label*='search'], text=/.*[Ss]earch.*/") |
|
|
|
|
|
if search_elements.count() > 0: |
|
|
search_input = search_elements.first |
|
|
|
|
|
|
|
|
if search_input.get_attribute("type") != "file": |
|
|
search_input.fill("revenue") |
|
|
|
|
|
|
|
|
search_button = page.locator("button:has-text(/.*[Ss]earch.*|.*[Ff]ind.*/)") |
|
|
if search_button.count() > 0: |
|
|
search_button.first.click() |
|
|
else: |
|
|
|
|
|
search_input.press("Enter") |
|
|
|
|
|
|
|
|
page.wait_for_timeout(2000) |
|
|
|
|
|
def test_document_status_display(self, page: Page, streamlit_helpers: StreamlitPageHelpers): |
|
|
"""Test that document processing status is displayed""" |
|
|
streamlit_helpers.wait_for_streamlit_load() |
|
|
|
|
|
|
|
|
status_elements = page.locator("text=/.*[Ss]tatus.*|.*[Rr]eady.*|.*[Pp]rocessed.*|.*[Dd]ocuments.*found.*/") |
|
|
|
|
|
|
|
|
|
|
|
if status_elements.count() > 0: |
|
|
expect(status_elements.first).to_be_visible() |
|
|
|
|
|
def test_error_handling_invalid_path(self, page: Page, streamlit_helpers: StreamlitPageHelpers): |
|
|
"""Test error handling for invalid data room paths""" |
|
|
streamlit_helpers.wait_for_streamlit_load() |
|
|
|
|
|
|
|
|
path_inputs = page.locator("input[placeholder*='path'], input[aria-label*='path']") |
|
|
|
|
|
if path_inputs.count() > 0: |
|
|
path_input = path_inputs.first |
|
|
|
|
|
|
|
|
path_input.fill("/nonexistent/path/to/documents") |
|
|
|
|
|
|
|
|
submit_buttons = page.locator("button:has-text(/.*[Ss]ubmit.*|.*[Cc]heck.*|.*[Vv]alidate.*|.*[Pp]rocess.*/)") |
|
|
|
|
|
if submit_buttons.count() > 0: |
|
|
submit_buttons.first.click() |
|
|
|
|
|
|
|
|
error_elements = page.locator(".stError, [data-testid='stError'], text=/.*[Ee]rror.*|.*[Nn]ot found.*|.*[Ii]nvalid.*/") |
|
|
|
|
|
|
|
|
page.wait_for_timeout(3000) |
|
|
|
|
|
|
|
|
if error_elements.count() > 0: |
|
|
expect(error_elements.first).to_be_visible() |
|
|
|
|
|
def test_processing_progress_indicators(self, page: Page, streamlit_helpers: StreamlitPageHelpers): |
|
|
"""Test that processing shows appropriate progress indicators""" |
|
|
streamlit_helpers.wait_for_streamlit_load() |
|
|
|
|
|
|
|
|
process_buttons = page.locator("button:has-text(/.*[Pp]rocess.*|.*[Bb]uild.*|.*[Aa]nalyze.*|.*[Ii]ndex.*/)") |
|
|
|
|
|
if process_buttons.count() > 0: |
|
|
|
|
|
process_buttons.first.click() |
|
|
|
|
|
|
|
|
progress_elements = page.locator(".stSpinner, .stProgress, [data-testid='stSpinner'], [data-testid='stProgress']") |
|
|
|
|
|
|
|
|
page.wait_for_timeout(1000) |
|
|
|
|
|
|
|
|
|
|
|
def test_document_metadata_display(self, page: Page, streamlit_helpers: StreamlitPageHelpers): |
|
|
"""Test that document metadata is displayed when available""" |
|
|
streamlit_helpers.wait_for_streamlit_load() |
|
|
|
|
|
|
|
|
metadata_elements = page.locator("text=/.*[Dd]ocument.*[Cc]ount.*|.*[Ff]iles.*found.*|.*[Cc]hunks.*|.*[Ii]ndex.*size.*/") |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
tabs = page.locator("[data-testid='stTabs'] button, .stTabs button") |
|
|
|
|
|
if tabs.count() > 0: |
|
|
for i in range(min(tabs.count(), 3)): |
|
|
tabs.nth(i).click() |
|
|
page.wait_for_timeout(1000) |
|
|
|
|
|
|
|
|
doc_info = page.locator("text=/.*[Dd]ocuments.*|.*[Ff]iles.*|.*[Cc]hunks.*|.*[Pp]rocessed.*/") |
|
|
if doc_info.count() > 0: |
|
|
expect(doc_info.first).to_be_visible() |
|
|
break |
|
|
|
|
|
def test_data_room_switching(self, page: Page, streamlit_helpers: StreamlitPageHelpers): |
|
|
"""Test switching between different data rooms""" |
|
|
streamlit_helpers.wait_for_streamlit_load() |
|
|
|
|
|
|
|
|
data_room_selectors = page.locator("select, [data-testid='stSelectbox']") |
|
|
|
|
|
if data_room_selectors.count() > 0: |
|
|
selector = data_room_selectors.first |
|
|
|
|
|
|
|
|
selector.click() |
|
|
page.wait_for_timeout(500) |
|
|
|
|
|
options = page.locator("[data-value], option") |
|
|
|
|
|
if options.count() > 1: |
|
|
|
|
|
options.nth(1).click() |
|
|
|
|
|
|
|
|
page.wait_for_timeout(2000) |
|
|
|
|
|
|
|
|
status_updates = page.locator("text=/.*[Ll]oading.*|.*[Ss]witching.*|.*[Pp]rocessing.*/") |
|
|
|
|
|
@pytest.mark.slow |
|
|
def test_full_processing_workflow(self, page_slow: Page, streamlit_helpers: StreamlitPageHelpers, sample_test_data): |
|
|
"""Test the complete document processing workflow with real data (slower test)""" |
|
|
page = page_slow |
|
|
streamlit_helpers.wait_for_streamlit_load() |
|
|
|
|
|
|
|
|
|
|
|
vdr_path = sample_test_data["vdr_path"] |
|
|
|
|
|
if vdr_path.exists() and any(vdr_path.iterdir()): |
|
|
|
|
|
path_inputs = page.locator("input[placeholder*='path'], input[aria-label*='path']") |
|
|
|
|
|
if path_inputs.count() > 0: |
|
|
path_input = path_inputs.first |
|
|
path_input.fill(str(vdr_path)) |
|
|
|
|
|
|
|
|
process_buttons = page.locator("button:has-text(/.*[Pp]rocess.*|.*[Bb]uild.*/)") |
|
|
|
|
|
if process_buttons.count() > 0: |
|
|
process_buttons.first.click() |
|
|
|
|
|
|
|
|
|
|
|
try: |
|
|
streamlit_helpers.wait_for_processing(timeout=120000) |
|
|
|
|
|
|
|
|
success_elements = page.locator(".stSuccess, text=/.*[Ss]uccess.*|.*[Cc]omplete.*|.*[Ff]inished.*/") |
|
|
|
|
|
page.wait_for_timeout(2000) |
|
|
|
|
|
|
|
|
status_elements = page.locator("text=/.*documents.*processed.*|.*files.*indexed.*|.*chunks.*created.*/") |
|
|
|
|
|
except Exception as e: |
|
|
|
|
|
print(f"Processing timeout or error: {e}") |
|
|
else: |
|
|
pytest.skip("No test VDR data available for full processing test") |
|
|
|