## Summary epic r04 - begin refactor ## Change Type - [x] Cowork feature - [ ] Bug fix - [ ] Core AI contribution - [ ] Test / hardening - [ ] Performance - [ ] Documentation ## Related Work Cowork Task: Core Repo: http://34.143.229.138/gitea-admin/fsg-ai-core-assets Core AI Issue: Core Task: Related PR: ## Scope What is intentionally included? What is intentionally NOT included? ## Validation - [ ] Unit tests - [ ] Integration tests - [ ] Manual verification - [ ] Regression check Commands / evidence: ## Security Impact Permission / credential / network / customer data impact: ## Compatibility - [ ] No breaking change - [ ] Breaking change documented ## Reviewer Notes Anything Cowork reviewers should pay attention to. --------- Co-authored-by: Anh Tran Nguyen Minh <anhtnm1@fpt.com> Co-authored-by: Huong Le Thi Thien <huongltt35@fpt.com> Co-authored-by: Nam Pham Dinh Thanh <nampdt@fpt.com> Co-authored-by: Vu Dam Tuan <vudt15@fpt.com> Co-authored-by: Hiep Ha Van <hiephv3@fpt.com> Co-authored-by: Lam Hoang Van <lamhv7@fpt.com> Reviewed-on: #7 Co-authored-by: Duy Le Huu <duylh19@fpt.com>
This commit was merged in pull request #7.
This commit is contained in:
@@ -0,0 +1,19 @@
|
||||
"""Dựng Qt ở chế độ offscreen cho test giao diện.
|
||||
|
||||
Offscreen là bắt buộc, không phải cho nhanh: máy dev là máy làm việc thật của
|
||||
người dùng. Test bật cửa sổ lên là nó nhảy ra trước mặt, che thứ đang mở.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
|
||||
import pytest
|
||||
|
||||
os.environ.setdefault("QT_QPA_PLATFORM", "offscreen")
|
||||
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def qapp():
|
||||
from PySide6.QtWidgets import QApplication
|
||||
app = QApplication.instance() or QApplication([])
|
||||
yield app
|
||||
@@ -0,0 +1,149 @@
|
||||
"""Đặc tả hành vi SettingsDialog TRƯỚC khi tách — R08-T07.
|
||||
|
||||
Không phải test tính năng mới. Đây là lưới an toàn: chốt lại dialog hiện
|
||||
đang làm gì, để khi bóc 727 dòng thành các widget con còn biết mình có làm
|
||||
lệch đi chỗ nào không. Bài nào ở đây đỏ sau khi tách nghĩa là tách sai.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import pytest
|
||||
|
||||
|
||||
class _Config:
|
||||
"""Đủ dùng cho SettingsDialog, không hơn — xem danh sách ctx.* nó chạm."""
|
||||
|
||||
def __init__(self):
|
||||
self.data = {
|
||||
"active_provider": "openai_compat",
|
||||
"language": "vi",
|
||||
"theme": "dark",
|
||||
"providers": {
|
||||
"openai_compat": {"base_url": "https://api.openai.com/v1",
|
||||
"api_key": "khoa-cu", "model": "gpt-4o"},
|
||||
"ollama": {"base_url": "http://localhost:11434",
|
||||
"api_key": "ollama", "model": "qwen2.5-coder"},
|
||||
},
|
||||
"tray": {"minimize_on_close": True, "notify_on_done": False},
|
||||
"agent_security": {
|
||||
"enabled": True, "cowork_confirm_commands": False,
|
||||
"block_network": True, "command_ai_check": False,
|
||||
"resource_limit_cpu_percent": 55,
|
||||
"resource_limit_memory_mb": 1024,
|
||||
"resource_limit_disk_mb": 2048,
|
||||
},
|
||||
"attachments": {"max_tokens": 32000, "max_files": 7},
|
||||
"structure": {"max_nodes": 300, "max_edges": 600},
|
||||
"routing": {"switch_mode": "auto", "policy": "cost",
|
||||
"min_score_gain": 0.05, "confirm_timeout_sec": 90,
|
||||
"reassess_interval_hours": 12,
|
||||
"per_provider_concurrency": 3,
|
||||
"judge_model": "gpt-4o-mini"},
|
||||
}
|
||||
self._data = self.data
|
||||
self._agent_security = self.data["agent_security"]
|
||||
|
||||
language = property(lambda self: self.data["language"])
|
||||
theme = property(lambda self: self.data["theme"])
|
||||
active_provider = property(lambda self: self.data["active_provider"])
|
||||
agent_security = property(lambda self: self.data["agent_security"])
|
||||
routing = property(lambda self: self.data["routing"])
|
||||
|
||||
|
||||
class _Ctx:
|
||||
def __init__(self):
|
||||
self.config = _Config()
|
||||
self.routing = None
|
||||
self.saves = 0
|
||||
|
||||
def save(self):
|
||||
self.saves += 1
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def dialog(qapp):
|
||||
from cowork_local.ui.settings_dialog import SettingsDialog
|
||||
ctx = _Ctx()
|
||||
dlg = SettingsDialog(ctx)
|
||||
yield dlg, ctx
|
||||
dlg.deleteLater()
|
||||
|
||||
|
||||
# ---- dialog gồm những mục nào -------------------------------------------
|
||||
|
||||
def test_co_dung_nam_muc(dialog):
|
||||
"""Năm mục thật trên màn hình. Plan R08-T07 ghi bốn widget và có một cái
|
||||
tên `connector`, nhưng UI connector đã dời khỏi Settings từ trước (xem
|
||||
ghi chú ở settings_dialog.py:180) — nên con số thật là năm, không bốn."""
|
||||
dlg, _ = dialog
|
||||
labels = [dlg.section_list.item(i).text()
|
||||
for i in range(dlg.section_list.count())]
|
||||
assert len(labels) == 5, labels
|
||||
assert dlg.section_stack.count() == 5
|
||||
|
||||
|
||||
def test_moi_muc_deu_bam_duoc(dialog):
|
||||
dlg, _ = dialog
|
||||
for i in range(dlg.section_list.count()):
|
||||
dlg.section_list.setCurrentRow(i)
|
||||
assert dlg.section_stack.currentIndex() == i
|
||||
|
||||
|
||||
# ---- nạp giá trị từ config ----------------------------------------------
|
||||
|
||||
def test_nap_dung_gia_tri_dang_co(dialog):
|
||||
dlg, ctx = dialog
|
||||
assert dlg.language_combo.currentData() == "vi"
|
||||
assert dlg.theme_combo.currentData() == "dark"
|
||||
assert dlg.provider_combo.currentData() == "openai_compat"
|
||||
assert dlg.prov_base.text() == "https://api.openai.com/v1"
|
||||
assert dlg.tray_chk.isChecked() is True
|
||||
assert dlg.notify_chk.isChecked() is False
|
||||
assert dlg.routing_mode.currentData() == "auto"
|
||||
assert dlg.routing_policy.currentData() == "cost"
|
||||
assert dlg.routing_timeout.value() == 90
|
||||
assert dlg.attach_files.value() == 7
|
||||
assert dlg.struct_nodes.value() == 300
|
||||
assert dlg.sandbox_cpu.value() == 55
|
||||
|
||||
|
||||
def test_khoa_api_khong_hien_ro(dialog):
|
||||
"""QLineEdit.Password — khoá không được đọc được bằng mắt qua vai."""
|
||||
from PySide6.QtWidgets import QLineEdit
|
||||
dlg, _ = dialog
|
||||
assert dlg.prov_key.echoMode() == QLineEdit.Password
|
||||
|
||||
|
||||
# ---- lưu ghi ra đúng chỗ -------------------------------------------------
|
||||
|
||||
def test_luu_ghi_dung_moi_o(dialog):
|
||||
dlg, ctx = dialog
|
||||
dlg.language_combo.setCurrentIndex(
|
||||
dlg.language_combo.findData("en") if dlg.language_combo.findData("en") >= 0 else 0)
|
||||
dlg.tray_chk.setChecked(False)
|
||||
dlg.routing_timeout.setValue(120)
|
||||
dlg.attach_files.setValue(3)
|
||||
dlg.sandbox_cpu.setValue(80)
|
||||
|
||||
dlg._save()
|
||||
d = ctx.config.data
|
||||
|
||||
assert d["tray"]["minimize_on_close"] is False
|
||||
assert d["routing"]["confirm_timeout_sec"] == 120
|
||||
assert d["attachments"]["max_files"] == 3
|
||||
assert d["agent_security"]["resource_limit_cpu_percent"] == 80
|
||||
assert ctx.saves == 1
|
||||
|
||||
|
||||
def test_luu_doi_min_gain_tu_phan_tram_sang_phan_le(dialog):
|
||||
"""Ô nhập là %, config lưu số thập phân. Đây là chỗ dễ tách sai nhất."""
|
||||
dlg, ctx = dialog
|
||||
dlg.routing_min_gain.setValue(25)
|
||||
dlg._save()
|
||||
assert ctx.config.data["routing"]["min_score_gain"] == 0.25
|
||||
|
||||
|
||||
def test_luu_xoa_cache_de_app_doc_lai_ngay(dialog):
|
||||
dlg, ctx = dialog
|
||||
dlg._save()
|
||||
assert ctx.config._data is None
|
||||
assert ctx.config._agent_security is None
|
||||
Reference in New Issue
Block a user