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:
@@ -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 форматтера --
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user