fix(wizard): «Завершить подключение» не закрывало окно
_finish первой же строкой вызывал EventLogService.log_event — метода с таким именем у сервиса нет, есть log(category, message, details, level). AttributeError уходил в обработчик Tk, а под pythonw консоли нет, поэтому для владельца кнопка просто не работала: окно оставалось открытым, on_complete не вызывался, аккаунт не попадал в маршрутизацию. Вызов приведён к настоящему API. Журналирование и обратный вызов обёрнуты так, чтобы сбой в них не запирал пользователя в мастере, — закрытие окна не должно зависеть от побочных действий. Воспроизведено и проверено исполнением: до правки winfo_exists=1 и on_complete не вызван, после — окно уничтожено, результат передан. Тесты: 252 passed в venv Hermes. Единственный сбой (test_oauth_lifecycle::test_f_copy_before_open_browser, TclError) и FAILED релизного гейта воспроизводятся на чистом main и к этой правке отношения не имеют. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
c75fb35082
commit
7090c8ae6f
2 changed files with 86 additions and 14 deletions
|
|
@ -1449,19 +1449,28 @@ class AddAccountWizard(HubModal):
|
|||
).pack(side="right", padx=10, pady=10)
|
||||
|
||||
def _finish(self):
|
||||
EventLogService.get().log_event(
|
||||
event_type="ACCOUNT_CONNECTED",
|
||||
title=f"Подключен аккаунт {self.selected_provider}",
|
||||
detail=f"Слот: {self.target_slot} ({self.discovered_identity})",
|
||||
provider=self.selected_provider,
|
||||
profile_id=self.target_slot,
|
||||
)
|
||||
if self.on_complete:
|
||||
self.on_complete(
|
||||
{
|
||||
"provider": self.selected_provider,
|
||||
"profile_id": self.target_slot,
|
||||
"identity": self.discovered_identity,
|
||||
}
|
||||
# Ни журналирование, ни обратный вызов не должны мешать закрытию окна:
|
||||
# исключение здесь оставляло мастер открытым без единого признака ошибки.
|
||||
try:
|
||||
EventLogService.get().log(
|
||||
"account",
|
||||
f"Подключен аккаунт {self.selected_provider}: {self.discovered_identity}",
|
||||
details=f"Слот: {self.target_slot}",
|
||||
level="success",
|
||||
)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
if self.on_complete:
|
||||
try:
|
||||
self.on_complete(
|
||||
{
|
||||
"provider": self.selected_provider,
|
||||
"profile_id": self.target_slot,
|
||||
"identity": self.discovered_identity,
|
||||
}
|
||||
)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
self.destroy()
|
||||
|
|
|
|||
63
tests/test_ui_wizard_finish.py
Normal file
63
tests/test_ui_wizard_finish.py
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
"""Мастер подключения обязан закрываться по кнопке «Завершить».
|
||||
|
||||
Дефект, ради которого написан файл: `_finish` вызывал
|
||||
`EventLogService.log_event` — метода, которого у сервиса нет. Под `pythonw`
|
||||
консоли нет, трейсбек Tk уходил в никуда, и для пользователя кнопка
|
||||
«Завершить подключение» просто не работала: окно оставалось открытым,
|
||||
аккаунт в маршрутизацию не попадал.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import pytest
|
||||
|
||||
pytest.importorskip("customtkinter")
|
||||
|
||||
import customtkinter as ctk
|
||||
|
||||
from antigravity_provider.router.ui.add_account_wizard import AddAccountWizard
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def root():
|
||||
app = ctk.CTk()
|
||||
app.withdraw()
|
||||
yield app
|
||||
try:
|
||||
app.destroy()
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
|
||||
def _wizard(root, on_complete=None):
|
||||
w = AddAccountWizard(root, on_complete=on_complete)
|
||||
w.withdraw()
|
||||
w.selected_provider = "antigravity"
|
||||
w.target_slot = "ag-w2"
|
||||
w.discovered_identity = "user@example.com"
|
||||
return w
|
||||
|
||||
|
||||
def test_finish_closes_wizard_and_reports_result(root):
|
||||
seen = []
|
||||
w = _wizard(root, on_complete=seen.append)
|
||||
|
||||
w._finish()
|
||||
|
||||
assert w.winfo_exists() == 0, "окно мастера осталось открытым после «Завершить»"
|
||||
assert seen == [
|
||||
{"provider": "antigravity", "profile_id": "ag-w2", "identity": "user@example.com"}
|
||||
]
|
||||
|
||||
|
||||
def test_finish_closes_even_if_callback_raises(root):
|
||||
"""Сбой в обработчике владельца не должен запирать пользователя в мастере."""
|
||||
|
||||
def boom(_result):
|
||||
raise RuntimeError("обновление данных упало")
|
||||
|
||||
w = _wizard(root, on_complete=boom)
|
||||
|
||||
w._finish()
|
||||
|
||||
assert w.winfo_exists() == 0
|
||||
Loading…
Reference in a new issue