Mở app lên là hai mục đã hiện sẵn dù người dùng chưa bấm chọn project nào.
Cổng này có hai mặt và cả hai đều hở:
1. refresh() mặc định row_to_select = 0, nên lúc mở app (_current_id rỗng)
danh sách tự chọn hộ project đầu tiên -> _update_tab_visibility(True).
Cùng đường đó còn làm app nhảy sang project khác ngay sau khi xoá project
đang mở. Đổi mặc định thành -1; có keep khớp thì vẫn giữ đúng dòng cũ.
2. NavRailMixin._rebuild_nav dựng hàng bị cổng đóng ở dạng mờ kèm tooltip
("shown instead of hidden") nên chúng vẫn nằm trên menu trái. Nay bỏ hẳn
hàng cho tới khi chọn project.
Mặt 1 làm selected_project_id() trả rỗng, khiến bộ chọn project trên rail rơi
về mục 0 và chỉ vào project đầu danh sách trong khi cổng vẫn đóng — hai chỗ
nói hai đằng. Thêm mục "Chọn project…" (khoá app.nav.pick_project, khác
no_project: đã có project, chỉ chưa chọn) để rail nói đúng trạng thái.
tools/check_nav.py và một bài trong test_startup_landing.py đang chốt thiết
kế cũ; cập nhật để chốt hành vi mới. Bài startup giữ nguyên từng assert, chỉ
đổi cách mở cổng từ cửa sau setTabVisible sang chọn project thật.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
142 lines
5.3 KiB
Python
142 lines
5.3 KiB
Python
"""Cổng project: Cowork và GraphRAG chỉ hiện khi đã chọn một project cụ thể.
|
|
|
|
Cổng có hai mặt và trước đây chỉ mặt thứ nhất làm đúng:
|
|
|
|
* **Sub-tab trong màn Workspace** — ``_update_tab_visibility`` vốn đã ẩn/hiện
|
|
đúng. Chỗ hỏng nằm ở ``refresh()``: nó mặc định ``row_to_select = 0`` nên lúc
|
|
mở app (chưa ai bấm gì) danh sách tự chọn hộ project đầu tiên, mở cổng cho một
|
|
project người dùng chưa hề chọn.
|
|
* **Hàng trên menu trái** — ``NavRailMixin._rebuild_nav`` từng dựng hàng ở dạng
|
|
mờ kèm tooltip thay vì bỏ đi ("shown instead of hidden"), nên người dùng vẫn
|
|
thấy Cowork/GraphRAG trên menu dù cổng đang đóng.
|
|
|
|
Các bài dưới đây chốt cả hai mặt, ở cả ba trạng thái: chưa chọn → ẩn, chọn rồi →
|
|
hiện, bỏ chọn → ẩn lại.
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
import pytest
|
|
|
|
pytest.importorskip("PySide6", reason="cần PySide6 để dựng cửa sổ thật")
|
|
|
|
|
|
@pytest.fixture
|
|
def win(qapp, tmp_path):
|
|
"""MainWindow thật — cần cả cửa sổ vì phải kiểm cả menu trái.
|
|
|
|
Đọc project từ ``~/.cowork_local`` như bản cài thật (``core/projects.py``
|
|
gắn ``PROJECTS_DIR`` vào đó) nên các bài này KHÔNG tạo/xoá project nào.
|
|
Bài nào cần cổng MỞ thì gọi thẳng ``_update_tab_visibility(True)`` thay vì
|
|
tạo project trên đĩa của người chạy test.
|
|
"""
|
|
from cowork_local.presentation.shell.bootstrap import build_config, build_context
|
|
from cowork_local.presentation.shell.main_window import MainWindow
|
|
|
|
config_path = tmp_path / "config.json"
|
|
build_config(config_path)
|
|
window = MainWindow(build_context(config_path))
|
|
yield window
|
|
window.close()
|
|
|
|
|
|
def _cong(ws):
|
|
"""Hai sub-tab nằm sau cổng project, bỏ qua bản dựng không có chúng."""
|
|
return [(ten, idx) for ten, idx in
|
|
(("Cowork", ws._cowork_tab_idx), ("GraphRAG", ws._graphrag_tab_idx))
|
|
if idx >= 0]
|
|
|
|
|
|
def _hang_menu(win):
|
|
"""Nhãn của mọi hàng đang có trên cột menu trái."""
|
|
return [win.nav.topLevelItem(i).text(0) for i in range(win.nav.topLevelItemCount())]
|
|
|
|
|
|
# ---- mặt 1: không tự chọn hộ project ------------------------------------
|
|
|
|
def test_mo_app_len_chua_chon_thi_khong_tu_chon_ho(win):
|
|
"""Đây là nguyên nhân gốc: ``refresh()`` từng mặc định chọn dòng 0."""
|
|
ws = win.workspace
|
|
|
|
assert ws._current_id == ""
|
|
assert ws.project_list.currentRow() == -1
|
|
|
|
|
|
def test_chua_chon_project_thi_hai_sub_tab_deu_an(win):
|
|
ws = win.workspace
|
|
|
|
for ten, idx in _cong(ws):
|
|
assert ws.tabs.isTabVisible(idx) is False, f"{ten} hiện khi chưa chọn project"
|
|
assert ws.subtab_available(idx) is False, f"{ten} vẫn mở cổng"
|
|
|
|
|
|
def test_chua_chon_project_thi_dung_o_tab_project(win):
|
|
"""Ẩn hai tab kia mà lại đứng ở một tab đã ẩn thì màn hình trống trơn."""
|
|
ws = win.workspace
|
|
|
|
assert ws.current_subtab() == ws._project_tab_idx
|
|
|
|
|
|
def test_refresh_giu_nguyen_project_dang_chon(win):
|
|
"""Sửa cổng không được làm mất lựa chọn hiện có: ``keep`` vẫn phải thắng."""
|
|
ws = win.workspace
|
|
if ws.project_list.count() == 0:
|
|
pytest.skip("máy chạy test chưa có project nào để chọn")
|
|
|
|
ws.project_list.setCurrentRow(0)
|
|
dang_chon = ws._current_id
|
|
|
|
ws.refresh()
|
|
|
|
assert ws._current_id == dang_chon
|
|
assert ws.project_list.currentRow() >= 0
|
|
|
|
|
|
# ---- mặt 2: menu trái bỏ hẳn hàng, không hiện dạng mờ -------------------
|
|
|
|
def test_chua_chon_project_thi_menu_trai_khong_co_hai_hang(win):
|
|
"""Đây là thứ người dùng nhìn thấy — trước đây hai hàng vẫn nằm đó, chỉ mờ."""
|
|
nhan = _hang_menu(win)
|
|
|
|
assert "Cowork" not in nhan, f"Cowork vẫn trên menu: {nhan}"
|
|
assert "GraphRAG" not in nhan, f"GraphRAG vẫn trên menu: {nhan}"
|
|
|
|
|
|
def test_mo_cong_thi_hai_hang_quay_lai_menu_trai(win):
|
|
"""Bỏ hàng phải đảo ngược được, nếu không thì chọn project xong vẫn kẹt."""
|
|
ws = win.workspace
|
|
ws._current_id = "gia-lap"
|
|
ws._update_tab_visibility(True)
|
|
|
|
nhan = _hang_menu(win)
|
|
assert "Cowork" in nhan, f"Cowork không quay lại: {nhan}"
|
|
assert "GraphRAG" in nhan, f"GraphRAG không quay lại: {nhan}"
|
|
|
|
|
|
def test_mo_cong_thi_hai_sub_tab_cung_hien_lai(win):
|
|
ws = win.workspace
|
|
ws._current_id = "gia-lap"
|
|
ws._update_tab_visibility(True)
|
|
|
|
for ten, idx in _cong(ws):
|
|
assert ws.tabs.isTabVisible(idx) is True, f"{ten} vẫn ẩn khi cổng đã mở"
|
|
|
|
|
|
def test_dong_cong_lai_thi_hai_hang_bien_mat(win):
|
|
"""Cổng phải đóng lại được, không chỉ mở một chiều."""
|
|
ws = win.workspace
|
|
ws._current_id = "gia-lap"
|
|
ws._update_tab_visibility(True)
|
|
ws._current_id = ""
|
|
ws._update_tab_visibility(False)
|
|
|
|
nhan = _hang_menu(win)
|
|
assert "Cowork" not in nhan and "GraphRAG" not in nhan, nhan
|
|
|
|
|
|
def test_cac_hang_khac_khong_bi_anh_huong(win):
|
|
"""Chỉ hai hàng sau cổng bị bỏ — phần còn lại của menu giữ nguyên."""
|
|
nhan = _hang_menu(win)
|
|
|
|
for bat_buoc in ("Project", "Co4E"):
|
|
assert bat_buoc in nhan, f"{bat_buoc} biến mất khỏi menu: {nhan}"
|