refactor: период через period.from вместо last_used; дедуп удалён
Удалены last_used, precision, dynamic и дедупликация по created_on/updated_on. Период задаётся одним полем period.from (env FROM_DATE), окно -- от этой даты до сегодня. После успешного --commit/--send начало окна сдвигается на конец отчёта; datetime-границы --date приводятся к полным дням. Схема конфига ломающая: старые ключи игнорируются, миграция описана в документации.
This commit is contained in:
@@ -4,11 +4,14 @@ import tempfile
|
||||
from pathlib import Path
|
||||
from unittest import mock
|
||||
|
||||
import yaml
|
||||
|
||||
from redmine_reporter.yaml_config import (
|
||||
check_file_permissions,
|
||||
ensure_config_dir,
|
||||
expand_filename_template,
|
||||
resolve_env_vars,
|
||||
save_period_to_config,
|
||||
)
|
||||
|
||||
|
||||
@@ -211,120 +214,65 @@ class TestResolveOutputPath:
|
||||
class TestSavePeriodToConfig:
|
||||
"""Tests for save_period_to_config()."""
|
||||
|
||||
def test_creates_last_used_in_empty_config(self, tmp_path):
|
||||
import yaml
|
||||
|
||||
from redmine_reporter.yaml_config import save_period_to_config
|
||||
|
||||
def test_creates_period_from_in_empty_config(self, tmp_path):
|
||||
config_path = tmp_path / "config.yml"
|
||||
save_period_to_config(
|
||||
str(config_path), "2026-06-01", "2026-06-30", "date", True
|
||||
)
|
||||
config_path.write_text("")
|
||||
|
||||
save_period_to_config(str(config_path), "2026-06-01")
|
||||
|
||||
with open(config_path) as fh:
|
||||
data = yaml.safe_load(fh)
|
||||
|
||||
assert data["period"]["last_used"]["from"] == "2026-06-01"
|
||||
assert data["period"]["last_used"]["to"] == "2026-06-30"
|
||||
assert "default_from" not in data["period"]
|
||||
|
||||
def test_overwrites_existing_last_used(self, tmp_path):
|
||||
import yaml
|
||||
|
||||
from redmine_reporter.yaml_config import save_period_to_config
|
||||
assert data["period"]["from"] == "2026-06-01"
|
||||
|
||||
def test_overwrites_existing_period_from(self, tmp_path):
|
||||
config_path = tmp_path / "config.yml"
|
||||
config_path.write_text(
|
||||
"period:\n last_used:\n from: '2026-05-01'\n to: '2026-05-31'\n"
|
||||
)
|
||||
config_path.write_text("period:\n from: '2026-05-01'\n")
|
||||
|
||||
save_period_to_config(
|
||||
str(config_path), "2026-06-01", "2026-06-30", "date", True
|
||||
)
|
||||
save_period_to_config(str(config_path), "2026-06-01")
|
||||
|
||||
with open(config_path) as fh:
|
||||
data = yaml.safe_load(fh)
|
||||
|
||||
assert data["period"]["last_used"]["from"] == "2026-06-01"
|
||||
assert data["period"]["last_used"]["to"] == "2026-06-30"
|
||||
|
||||
def test_dynamic_false_overwrites_defaults(self, tmp_path):
|
||||
import yaml
|
||||
|
||||
from redmine_reporter.yaml_config import save_period_to_config
|
||||
|
||||
config_path = tmp_path / "config.yml"
|
||||
config_path.write_text(
|
||||
"period:\n default_from: '2026-01-01'\n default_to: '2026-01-31'\n"
|
||||
)
|
||||
|
||||
save_period_to_config(
|
||||
str(config_path), "2026-06-01", "2026-06-30", "date", False
|
||||
)
|
||||
|
||||
with open(config_path) as fh:
|
||||
data = yaml.safe_load(fh)
|
||||
|
||||
assert data["period"]["default_from"] == "2026-06-01"
|
||||
assert data["period"]["default_to"] == "2026-06-30"
|
||||
assert data["period"]["last_used"]["from"] == "2026-06-01"
|
||||
assert data["period"]["last_used"]["to"] == "2026-06-30"
|
||||
|
||||
def test_datetime_precision_stores_timestamps(self, tmp_path):
|
||||
import yaml
|
||||
|
||||
from redmine_reporter.yaml_config import save_period_to_config
|
||||
|
||||
config_path = tmp_path / "config.yml"
|
||||
|
||||
save_period_to_config(
|
||||
str(config_path),
|
||||
"2026-06-30T09:00:00",
|
||||
"2026-06-30T12:00:00",
|
||||
"datetime",
|
||||
True,
|
||||
)
|
||||
|
||||
with open(config_path) as fh:
|
||||
data = yaml.safe_load(fh)
|
||||
|
||||
assert data["period"]["last_used"]["from"] == "2026-06-30T09:00:00"
|
||||
assert data["period"]["last_used"]["to"] == "2026-06-30T12:00:00"
|
||||
|
||||
def test_preserves_existing_sections(self, tmp_path):
|
||||
import yaml
|
||||
|
||||
from redmine_reporter.yaml_config import save_period_to_config
|
||||
assert data["period"]["from"] == "2026-06-01"
|
||||
|
||||
def test_preserves_other_sections_and_keys(self, tmp_path):
|
||||
config_path = tmp_path / "config.yml"
|
||||
config_path.write_text(
|
||||
"redmine:\n"
|
||||
" url: https://example.com\n"
|
||||
" author: Test\n"
|
||||
"email:\n"
|
||||
" enabled: true\n"
|
||||
"output:\n"
|
||||
" dir: /tmp\n"
|
||||
)
|
||||
|
||||
save_period_to_config(
|
||||
str(config_path), "2026-06-01", "2026-06-30", "date", True
|
||||
)
|
||||
save_period_to_config(str(config_path), "2026-06-01")
|
||||
|
||||
with open(config_path) as fh:
|
||||
data = yaml.safe_load(fh)
|
||||
|
||||
assert data["redmine"]["url"] == "https://example.com"
|
||||
assert data["redmine"]["author"] == "Test"
|
||||
assert data["output"]["dir"] == "/tmp"
|
||||
assert data["period"]["last_used"]["from"] == "2026-06-01"
|
||||
assert data["redmine"] == {"url": "https://example.com", "author": "Test"}
|
||||
assert data["email"] == {"enabled": True}
|
||||
assert data["output"] == {"dir": "/tmp"}
|
||||
assert data["period"] == {"from": "2026-06-01"}
|
||||
|
||||
def test_sets_permissions_0600(self, tmp_path):
|
||||
from redmine_reporter.yaml_config import save_period_to_config
|
||||
|
||||
config_path = tmp_path / "config.yml"
|
||||
|
||||
save_period_to_config(
|
||||
str(config_path), "2026-06-01", "2026-06-30", "date", True
|
||||
)
|
||||
save_period_to_config(str(config_path), "2026-06-01")
|
||||
|
||||
mode = config_path.stat().st_mode & 0o777
|
||||
assert mode == 0o600
|
||||
|
||||
def test_creates_config_file_and_dir_when_missing(self, tmp_path):
|
||||
config_path = tmp_path / "nested" / "config.yml"
|
||||
assert not config_path.exists()
|
||||
|
||||
save_period_to_config(str(config_path), "2026-06-01")
|
||||
|
||||
assert config_path.exists()
|
||||
with open(config_path) as fh:
|
||||
data = yaml.safe_load(fh)
|
||||
assert data["period"]["from"] == "2026-06-01"
|
||||
|
||||
Reference in New Issue
Block a user