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)
|
).pack(side="right", padx=10, pady=10)
|
||||||
|
|
||||||
def _finish(self):
|
def _finish(self):
|
||||||
EventLogService.get().log_event(
|
# Ни журналирование, ни обратный вызов не должны мешать закрытию окна:
|
||||||
event_type="ACCOUNT_CONNECTED",
|
# исключение здесь оставляло мастер открытым без единого признака ошибки.
|
||||||
title=f"Подключен аккаунт {self.selected_provider}",
|
try:
|
||||||
detail=f"Слот: {self.target_slot} ({self.discovered_identity})",
|
EventLogService.get().log(
|
||||||
provider=self.selected_provider,
|
"account",
|
||||||
profile_id=self.target_slot,
|
f"Подключен аккаунт {self.selected_provider}: {self.discovered_identity}",
|
||||||
)
|
details=f"Слот: {self.target_slot}",
|
||||||
if self.on_complete:
|
level="success",
|
||||||
self.on_complete(
|
|
||||||
{
|
|
||||||
"provider": self.selected_provider,
|
|
||||||
"profile_id": self.target_slot,
|
|
||||||
"identity": self.discovered_identity,
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
|
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()
|
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