diff --git a/.gitignore b/.gitignore index 588c8ba..3047e59 100644 --- a/.gitignore +++ b/.gitignore @@ -67,7 +67,6 @@ instance/ # Scrapy stuff: .scrapy -.git # Sphinx documentation docs/_build/ diff --git a/Makefile b/Makefile index 696be00..2be5042 100644 --- a/Makefile +++ b/Makefile @@ -22,10 +22,10 @@ shell: $(IMAGE_NAME) /bin/bash test: - poetry run pytest tests/unit --reruns 1 + $(DOCKER_RUN) poetry run pytest tests/unit --reruns 1 test-with-xdist: - poetry run pytest tests/unit --reruns 1 -n auto + $(DOCKER_RUN) poetry run pytest tests/unit --reruns 1 -n auto lint: $(DOCKER_RUN) poetry run ruff check . diff --git a/README.md b/README.md index ae2f338..7ef7c19 100644 --- a/README.md +++ b/README.md @@ -96,19 +96,22 @@ No need for custom marker definitions. Perfect for smarter filtering, reporting, ![ScreenRecording2025-06-29at1 06 02AM-ezgif com-video-to-gif-converter](https://github.com/user-attachments/assets/af40622f-f548-44a5-982b-344c74a65e13) -#### 🔍 Universal Test Search + Smart Link Navigation +#### 🔍 Universal Test Search + Smart Traceability -Whether you're trying to trace coverage or track unlinked test cases — this search has your back! +Whether you're tracing coverage, investigating failures, or tracking unlinked test cases — this search has your back! Just start typing, and the dashboard will instantly filter tests by: -✅ Test name +✅ Test names -✅ Linked issue/documentation IDs (like JIRA, Testmo, Notion, etc.) +✅ Linked issue or documentation IDs (JIRA, Testmo, Notion, etc.) -✅ Custom URLs or keywords present in the links +✅ Custom URLs or keywords present in linked references + +✅ Error messages and trace snippets to quickly group related failures + +new_search -![ScreenRecording2025-06-21at3 10 06PM-ezgif com-video-to-gif-converter](https://github.com/user-attachments/assets/f81c9a81-f98d-4151-ad7a-c1184cd199eb) #### 📸 Screenshot Support: View screenshots directly in the report to understand failures faster. diff --git a/docs/Features/search.rst b/docs/Features/search.rst index 0320246..4827b3a 100644 --- a/docs/Features/search.rst +++ b/docs/Features/search.rst @@ -1,21 +1,28 @@ -Universal Test Search + Smart Link Navigation -============================================= +# Universal Test Search + Smart Traceability -The `pytest-html-plus` report comes with a powerful search bar at the top of the page, helping you find the test cases you care about in real-time. +The `pytest-html-plus` report includes a powerful search bar that instantly filters tests as you type, helping you quickly locate failures, trace coverage, and navigate linked references. -Search and Navigate: ---------------------- +## Search and Navigate -Just start typing, and the dashboard will instantly filter and display tests based on: +Simply start typing, and the dashboard will filter tests in real time based on: -✅ **Test name** +✅ **Test names** -✅ **Linked external IDs** — such as JIRA, Testmo, Notion, or any quoted references you attach (e.g. `JIRA-123`, `DOC-456`, etc.) +✅ **Linked external IDs** — such as JIRA, Testmo, Notion, or any quoted references you attach (for example `JIRA-123`, `DOC-456`, etc.) -✅ **Custom URLs or keywords** — any meaningful text or link in the associated references will be indexed. +✅ **Custom URLs or keywords** — any meaningful text or link in associated references will be indexed + +✅ **Error messages and trace snippets** — quickly find tests sharing similar failures, assertion messages, or exception types .. tip:: - This smart search helps you **trace coverage**, **group tests by external references**, or **isolate unlinked cases** with ease. -For example, if you tag tests with a JIRA ID or Notion doc, typing that ID in the search bar will instantly filter all associated test cases for traceability. +This smart search helps you **trace coverage**, **group tests by external references**, and **identify related failures** with ease. + +## Examples + +* Search `JIRA-123` to display all tests linked to that issue. +* Search `TimeoutError` to locate tests failing due to timeouts. +* Search `NoSuchElementException` to identify Selenium or Playwright locator failures. +* Search `expected 200` to find API assertions with matching error messages. +This makes it easy to investigate patterns, correlate failures, and navigate large reports efficiently. diff --git a/pyproject.toml b/pyproject.toml index cfb9477..ce98ace 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "pytest-html-plus" -version = "1.0.1" +version = "1.1.0" description = "Generate Actionable, automatic screenshots, unified Mobile friendly Pytest HTML report in less than 3 seconds — no hooks, merge plugins, no config, xdist-ready." readme = "README.md" authors = ["reporterplus"] @@ -84,7 +84,8 @@ ignore = [ "W293", # blank line whitespace — let black handle ] exclude = [ - "pytest_html_plus/generate_html_report.py" + "pytest_html_plus/generate_html_report.py", + ".git" ] [tool.ruff.lint] diff --git a/pytest_html_plus/generate_html_report.py b/pytest_html_plus/generate_html_report.py index 677d1fb..01ef786 100644 --- a/pytest_html_plus/generate_html_report.py +++ b/pytest_html_plus/generate_html_report.py @@ -4,7 +4,7 @@ import os import shutil from datetime import datetime, timezone - +from html import escape from pytest_html_plus.compute_filter_counts import compute_filter_count from pytest_html_plus.utils import extract_error_block, extract_trace_block @@ -614,7 +614,8 @@ def generate_html_report(self): document.querySelectorAll('.test-card').forEach(card => {{ const name = card.getAttribute('data-name') || ''; const link = card.getAttribute('data-link') || ''; - const isVisible = name.toLowerCase().includes(filter) || link.toLowerCase().includes(filter); + const error = card.getAttribute('data-error') || ''; + const isVisible = name.toLowerCase().includes(filter) || link.toLowerCase().includes(filter) || error.toLowerCase().includes(filter); card.style.display = isVisible ? '' : 'none'; }}); }}); @@ -750,7 +751,7 @@ def generate_html_report(self): @@ -873,6 +874,8 @@ def generate_html_report(self): """ attempts_html += "" + + search_error = "" if test.get("error"): full_error = test["error"] @@ -891,6 +894,11 @@ def generate_html_report(self):
Error: {self.generate_copy_button(error_content, "error")}
{error_content}
""" + search_error = ( + error_content.replace("\n", " ") + .replace("\r", " ") + )[:1000] + flaky_badge = "" if test.get("flaky"): @@ -928,7 +936,7 @@ def generate_html_report(self): ) html += f""" -
+
diff --git a/tests/unit/test_error_block.py b/tests/unit/test_error_block.py index 25272e1..ec0cd04 100644 --- a/tests/unit/test_error_block.py +++ b/tests/unit/test_error_block.py @@ -1,3 +1,5 @@ +import pytest + from pytest_html_plus.utils import extract_error_block @@ -7,12 +9,14 @@ def test_error_block_basic(): assert extract_error_block(error) == expected +@pytest.mark.jira("https://acme.atlassian.net/browse/QA-123") def test_error_block_spaces_and_blank_lines(): error = "\n\n E TypeError\n\n \nE IndexError\n" expected = "E TypeError\nE IndexError" assert extract_error_block(error) == expected +@pytest.mark.link("https://acme.atlassian.net/browse/PAY-456") def test_error_block_no_E_lines(): error = "line 1\nline 2" expected = "line 1\nline 2"