From 7d3f648d2cd691e491caad04e35ecf70a38e7f4d Mon Sep 17 00:00:00 2001 From: Andrey Epifancev Date: Thu, 15 Oct 2026 10:56:51 +0400 Subject: [PATCH] =?UTF-8?q?fix:=20=D1=84=D0=B8=D0=BD=D0=B0=D0=BB=D1=8C?= =?UTF-8?q?=D0=BD=D0=BE=D0=B5=20=D1=80=D0=B5=D0=B2=D1=8C=D1=8E=20=E2=80=94?= =?UTF-8?q?=20M-1/T3.1=20=D0=B0=D1=82=D0=BE=D0=BC=D0=B0=D1=80=D0=BD=D0=B0?= =?UTF-8?q?=D1=8F=20=D0=BF=D0=BE=D0=B4=D0=BC=D0=B5=D0=BD=D0=B0=20agent=5Fu?= =?UTF-8?q?pdate,=20T1.1/T1.2=20open=5Fdb,=20T2.3,=20T4.1=20(#32)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 5.5 --- src/jira_hub/api.py | 8 +++++--- tests/test_cli.py | 7 +++---- tests/test_commands.py | 8 ++++++++ tests/test_release.py | 10 +++++++++- tests/test_settings.py | 7 +++---- 5 files changed, 28 insertions(+), 12 deletions(-) diff --git a/src/jira_hub/api.py b/src/jira_hub/api.py index 2a20aae..3580f59 100644 --- a/src/jira_hub/api.py +++ b/src/jira_hub/api.py @@ -77,15 +77,17 @@ class Hub: def note_agent_update(self, body): """update_state и launcher_version из claim: хранятся в памяти, агент шлёт их в каждом claim (R-3). Значение неверного типа игнорируется — claim из-за него не отвергается; сам claim отмечается (reported).""" - self.agent_update["reported"] = True + new = dict(self.agent_update) + new["reported"] = True us = body.get("update_state") if us is None or isinstance(us, dict): if us is not None and isinstance(us.get("error"), str): us = {**us, "error": us["error"][:500]} - self.agent_update["update_state"] = us + new["update_state"] = us lv = body.get("launcher_version") if lv is None or (isinstance(lv, int) and not isinstance(lv, bool)): - self.agent_update["launcher_version"] = lv + new["launcher_version"] = lv + self.agent_update = new def make_backup(self, label): conn = self.conn() diff --git a/tests/test_cli.py b/tests/test_cli.py index b7c6c42..8ea8b83 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -2,19 +2,19 @@ import json import os from pathlib import Path -from jira_hub import cli, db, paths, release, settings +from jira_hub import cli, paths, release, settings FIXTURE = Path(__file__).parent / "fixtures" / "config.example.json" -def test_init_import_tokens(tmp_path, monkeypatch, capsys): +def test_init_import_tokens(tmp_path, monkeypatch, capsys, open_db): monkeypatch.setenv("JIRA_HUB_HOME", str(tmp_path / "home")) assert cli.main(["init", "--config", str(FIXTURE)]) == 0 out = capsys.readouterr().out assert "transitions_map" in out and "агентский токен" in out assert cli.main(["init", "--config", str(FIXTURE)]) == 1 assert "уже инициализирован" in capsys.readouterr().err - conn = db.connect(paths.db_path()) + conn = open_db(paths.db_path()) assert settings.get(conn, "board_id") == 4216 (tmp_path / "pkg").mkdir() (tmp_path / "pkg" / "tasks.csv").write_text("Код,Статус по факту,Вид работы\nAURORA-1,В работе,UI\n", encoding="utf-8") @@ -23,7 +23,6 @@ def test_init_import_tokens(tmp_path, monkeypatch, capsys): assert rep["notes"] == 1 and rep["missing_keys"] == ["AURORA-1"] assert cli.main(["tokens"]) == 0 assert settings.tokens(conn)["client"] in capsys.readouterr().out - conn.close() def test_agent_publish(tmp_path, monkeypatch, capsys): diff --git a/tests/test_commands.py b/tests/test_commands.py index c310ee3..62e15ef 100644 --- a/tests/test_commands.py +++ b/tests/test_commands.py @@ -162,6 +162,14 @@ def test_ensure_fields_text_compare_ignores_crlf(conn, mirror_value, param, expe assert ok is expected +def test_ensure_fields_summary_difference_is_detected(conn): + """T4.1 #32: CRLF в summary игнорируется, но реальное расхождение текста — False.""" + conn.execute("UPDATE issue SET summary = ? WHERE key = 'A-1'", ("x\r\ny",)) + ok, _ = commands.check_confirmed(conn, {"type": "ensure_fields", + "params": {"key": "A-1", "summary": "x\nz"}}, LT) + assert ok is False + + @pytest.mark.parametrize("ctype, name, value, msg", [ ("ensure_fields", "duedate", True, "duedate — строка"), ("ensure_fields", "labels_add", "AWPCA", "labels_add — список строк"), diff --git a/tests/test_release.py b/tests/test_release.py index 4cf2c6a..5b5345d 100644 --- a/tests/test_release.py +++ b/tests/test_release.py @@ -186,6 +186,8 @@ def test_restore_failure_is_logged_not_raised(tmp_path, monkeypatch, caplog): """Review Focus 2: и возврат agent.py.prev не удался — PublishError с текстом, причина возврата в логе.""" rd = tmp_path / "release" release.publish(rd, agent_file(tmp_path, 8)) + before = _listing(rd) + new_src = agent_file(tmp_path, 9) _fail_replace_into(monkeypatch, "manifest.json") real = release.os.replace @@ -196,8 +198,14 @@ def test_restore_failure_is_logged_not_raised(tmp_path, monkeypatch, caplog): monkeypatch.setattr(release.os, "replace", fake) with pytest.raises(release.PublishError, match="не удалось записать публикацию"): - release.publish(rd, agent_file(tmp_path, 9)) + release.publish(rd, new_src) assert "прежняя публикация не восстановлена" in caplog.text + monkeypatch.undo() + after = _listing(rd) # задокументированное состояние: новый agent.py, старый agent.py.prev, старый манифест + assert sorted(after) == ["agent.py", "agent.py.prev", "manifest.json"] + assert after["agent.py"] == new_src.read_bytes() + assert after["agent.py.prev"] == before["agent.py"] + assert after["manifest.json"] == before["manifest.json"] @pytest.mark.parametrize("manifest", [ diff --git a/tests/test_settings.py b/tests/test_settings.py index 10f0276..4926338 100644 --- a/tests/test_settings.py +++ b/tests/test_settings.py @@ -3,7 +3,7 @@ from pathlib import Path import pytest -from jira_hub import db, settings +from jira_hub import settings FIXTURE = Path(__file__).parent / "fixtures" / "config.example.json" @@ -53,8 +53,8 @@ def test_init_from_config(conn): settings.init_from_config(conn, cfg, force=True) -def test_relay_dir_default_and_validation(tmp_path): - conn = db.connect(tmp_path / "hub.sqlite") +def test_relay_dir_default_and_validation(tmp_path, open_db): + conn = open_db(tmp_path / "hub.sqlite") settings.ensure_defaults(conn) assert settings.get(conn, "relay_dir") is None settings.validate("relay_dir", None) @@ -63,4 +63,3 @@ def test_relay_dir_default_and_validation(tmp_path): with pytest.raises(ValueError): settings.validate("relay_dir", bad) assert "relay_dir" not in settings.AGENT_KEYS - conn.close()