test: fix cli mocks, add pytest config and coverage gaps

- tests/test_cli.py: fix 26 fetch_issues_with_spent_time mocks to return
  3-element tuples (issue, hours, activities) matching the real signature
- pyproject.toml: add [tool.pytest.ini_options] with testpaths and
  pythonpath so bare pytest works
- tests/test_client.py: add pagination test (>100 time entries arriving
  in pages, hours aggregated across all pages)
- tests/test_formatters.py: add structural tests — XLSX full header row
  and grand total row via openpyxl, HTML thead with all columns and
  tbody row count
- add strict xfail trap-tests for known bugs: #58 (naive created_on vs
  aware dedup cutoff TypeError) and #59 (parse_date_range rejects
  datetime range from dynamic+datetime period)

Closes #67
This commit is contained in:
Кокос Артем Николаевич
2026-07-17 10:59:47 +07:00
parent 7ca58f881e
commit 3a3a7bb39c
4 changed files with 218 additions and 26 deletions

View File

@@ -396,6 +396,32 @@ def test_xlsx_has_totals(fake_rows, tmp_path):
assert ws["F2"].number_format == "0.00"
def test_xlsx_has_full_header_row_and_grand_total_row(fake_rows, tmp_path):
"""XLSX содержит полный ряд заголовков колонок и финальную строку общего итога."""
from openpyxl import load_workbook
output = tmp_path / "report.xlsx"
XLSXFormatter().save(fake_rows, str(output))
wb = load_workbook(str(output))
ws = wb.active
headers = [ws.cell(row=1, column=c).value for c in range(1, 8)]
assert headers == [
"Project",
"Version",
"Issue ID",
"Subject",
"Status",
"Hours",
"Spent Time",
]
# Последняя строка — общий итог по всем проектам
assert ws.cell(row=ws.max_row, column=1).value == "Total"
assert ws.cell(row=ws.max_row, column=6).value == 22.5
def test_xlsx_no_time_keeps_columns_empty_and_skips_totals(fake_rows, tmp_path):
"""XLSX с no_time: колонки времени пустые, итогов нет."""
from openpyxl import load_workbook
@@ -456,6 +482,25 @@ def test_html_output_has_doctype_and_charset(fake_rows):
assert '<meta charset="utf-8">' in output
def test_html_has_table_structure_with_all_columns(fake_rows):
"""HTML-отчёт содержит thead со всеми колонками и по строке на каждую задачу."""
output = HTMLFormatter().format(fake_rows)
assert "<thead>" in output
assert "<tbody>" in output
for header in (
"Наименование Проекта",
"Номер версии*",
"Задача",
"Статус Готовность*",
"Затрачено за отчетный период",
):
assert f"<th>{header}</th>" in output
tbody = output.split("<tbody>", 1)[1]
assert tbody.count("<tr>") == len(fake_rows)
# -- Тесты ODT форматтера --