Complete testing system: pyproject.toml (pytest markers), test.sh orchestrator with auto app start/stop and colorful summary, pre-push hook, Gitea Actions workflow. New QA tests: API health (7 endpoints), responsive (3 viewports), log monitoring (ERROR/ORA-/Traceback detection), real GoMag sync, PL/SQL package validation, smoke prod (read-only). Converted test_app_basic.py and test_integration.py to pytest. Added pytestmark to all existing tests (unit/e2e/oracle). E2E conftest upgraded: console error collector, screenshot on failure, auto-detect live app on :5003. Usage: ./test.sh ci (30s) | ./test.sh full (2-3min) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
84 lines
3.1 KiB
Python
84 lines
3.1 KiB
Python
"""E2E: Mappings page with sortable headers, grouping, multi-CODMAT modal."""
|
|
import pytest
|
|
from playwright.sync_api import Page, expect
|
|
|
|
pytestmark = pytest.mark.e2e
|
|
|
|
|
|
@pytest.fixture(autouse=True)
|
|
def navigate_to_mappings(page: Page, app_url: str):
|
|
page.goto(f"{app_url}/mappings")
|
|
page.wait_for_load_state("networkidle")
|
|
|
|
|
|
def test_mappings_page_loads(page: Page):
|
|
"""Verify mappings page renders."""
|
|
expect(page.locator("h4")).to_contain_text("Mapari SKU")
|
|
|
|
|
|
def test_sortable_headers_present(page: Page):
|
|
"""R7: Verify sortable column headers with sort icons."""
|
|
sortable_ths = page.locator("th.sortable")
|
|
count = sortable_ths.count()
|
|
assert count >= 5, f"Expected at least 5 sortable columns, got {count}"
|
|
|
|
sort_icons = page.locator(".sort-icon")
|
|
assert sort_icons.count() >= 5, f"Expected at least 5 sort-icon spans, got {sort_icons.count()}"
|
|
|
|
|
|
def test_product_name_column_exists(page: Page):
|
|
"""R4: Verify 'Produs Web' column exists in header."""
|
|
headers = page.locator("thead th")
|
|
texts = headers.all_text_contents()
|
|
assert any("Produs Web" in t for t in texts), f"'Produs Web' column not found in headers: {texts}"
|
|
|
|
|
|
def test_um_column_exists(page: Page):
|
|
"""R12: Verify 'UM' column exists in header."""
|
|
headers = page.locator("thead th")
|
|
texts = headers.all_text_contents()
|
|
assert any("UM" in t for t in texts), f"'UM' column not found in headers: {texts}"
|
|
|
|
|
|
def test_show_inactive_toggle_exists(page: Page):
|
|
"""R5: Verify 'Arata inactive' toggle is present."""
|
|
toggle = page.locator("#showInactive")
|
|
expect(toggle).to_be_visible()
|
|
label = page.locator("label[for='showInactive']")
|
|
expect(label).to_contain_text("Arata inactive")
|
|
|
|
|
|
def test_sort_click_changes_icon(page: Page):
|
|
"""R7: Clicking a sortable header should display a sort direction arrow."""
|
|
sku_header = page.locator("th.sortable", has_text="SKU")
|
|
sku_header.click()
|
|
page.wait_for_timeout(500)
|
|
|
|
icon = page.locator(".sort-icon[data-col='sku']")
|
|
text = icon.text_content()
|
|
assert text in ("↑", "↓"), f"Expected sort arrow (↑ or ↓), got '{text}'"
|
|
|
|
|
|
def test_add_modal_multi_codmat(page: Page):
|
|
"""R11: Verify the add mapping modal supports multiple CODMAT lines."""
|
|
page.locator("button", has_text="Adauga Mapare").click()
|
|
page.wait_for_timeout(500)
|
|
|
|
codmat_lines = page.locator(".codmat-line")
|
|
assert codmat_lines.count() >= 1, "Expected at least one CODMAT line in modal"
|
|
|
|
page.locator("button", has_text="Adauga CODMAT").click()
|
|
page.wait_for_timeout(300)
|
|
assert codmat_lines.count() >= 2, "Expected a second CODMAT line after clicking Adauga CODMAT"
|
|
|
|
# Second line must have a remove button
|
|
remove_btns = page.locator(".codmat-line:nth-child(2) button.btn-outline-danger")
|
|
assert remove_btns.count() >= 1, "Second CODMAT line is missing remove button"
|
|
|
|
|
|
def test_search_input_exists(page: Page):
|
|
"""Verify search input is present with the correct placeholder."""
|
|
search = page.locator("#searchInput")
|
|
expect(search).to_be_visible()
|
|
expect(search).to_have_attribute("placeholder", "Cauta SKU, CODMAT sau denumire...")
|