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>
164 lines
7.2 KiB
Python
164 lines
7.2 KiB
Python
"""Màn hình app mở lên lần đầu.
|
|
|
|
Trước đây `MainWindow.__init__` gọi `_goto(ROW_WORKSPACE, current_subtab())` rồi
|
|
ngay sau đó `_restore_sessions()` lại `_show_cowork_tab()` để mở lại hội thoại
|
|
lần trước. Kết quả: thứ người dùng thấy khi bật app là cuộc trò chuyện cũ, không
|
|
phải danh sách project — và dòng landing ở trên trông như đang quyết định điều đó
|
|
trong khi thực ra bị ghi đè vài chục dòng sau.
|
|
|
|
Giờ landing được chốt SAU restore: hội thoại cũ vẫn được nạp lại (đó là mục đích
|
|
của restore — phục hồi sau khi thoát đột ngột), nhưng khung nhìn đầu tiên là
|
|
"Tất cả project…".
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
import pytest
|
|
|
|
pytest.importorskip("PySide6", reason="cần PySide6 để dựng cửa sổ thật")
|
|
|
|
|
|
@pytest.fixture
|
|
def window(qapp, tmp_path):
|
|
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)
|
|
win = MainWindow(build_context(config_path))
|
|
yield win
|
|
win.close()
|
|
|
|
|
|
def test_mo_app_len_thi_dung_o_man_workspace(window):
|
|
"""Vẫn là màn Workspace, không phải Dashboard/Lịch/Giám sát."""
|
|
assert window.pages.currentIndex() == window._ROW_WORKSPACE
|
|
|
|
|
|
def test_mo_app_len_thi_o_khung_tat_ca_project(window):
|
|
"""Đúng khung mà link "Tất cả project…" ở thanh menu mở ra.
|
|
|
|
Trừ khi cổng project đang giữ nó đóng: chưa có project nào thì sub-tab
|
|
Cowork bị ẩn, và màn hình đúng cho người dùng đó là màn quản lý project.
|
|
Ép mở bằng cửa sau sẽ để nội dung ở Cowork trong khi cổng nói là Project.
|
|
"""
|
|
ws = window.workspace
|
|
if ws.subtab_available(ws._cowork_tab_idx):
|
|
assert ws.current_subtab() == ws._cowork_tab_idx
|
|
assert ws._history_opened is True
|
|
else:
|
|
assert ws.current_subtab() == ws._project_tab_idx
|
|
|
|
|
|
def test_bang_lich_su_khong_bi_an_di(window):
|
|
"""Danh sách phải nhìn thấy được — mở đúng tab mà bảng vẫn gập là vô nghĩa.
|
|
|
|
Dùng ``isHidden()`` chứ không ``isVisible()``: test không gọi ``show()`` trên
|
|
cửa sổ (bật cửa sổ thật lên sẽ nhảy ra trước mặt người đang làm việc), mà
|
|
``isVisible()`` của widget con chỉ True khi đã có tổ tiên được hiện.
|
|
``isHidden()`` phản ánh đúng thứ ta quan tâm: có ai gọi ``setVisible(False)``
|
|
lên nó hay không.
|
|
"""
|
|
ws = window.workspace
|
|
if not ws.subtab_available(ws._cowork_tab_idx):
|
|
pytest.skip("cổng project đang đóng — bảng lịch sử không thuộc màn này")
|
|
assert ws._sidebar.isHidden() is False
|
|
|
|
|
|
# ---- vệt sáng thanh menu phải khớp nội dung ------------------------------
|
|
#
|
|
# Bug: mở app lên ở khung "Tất cả project…" thì bấm "Project" trên thanh menu
|
|
# KHÔNG có tác dụng; phải bấm sang mục khác rồi bấm về mới được.
|
|
#
|
|
# Nguyên nhân: landing gọi thẳng ``workspace.show_history_pane()``, đổi nội dung
|
|
# sang sub-tab Cowork nhưng bỏ qua ``_goto`` — chỗ duy nhất dời vệt sáng. Vệt
|
|
# sáng ở lại "Project", mà QTreeWidget không phát ``currentItemChanged`` khi bấm
|
|
# lại đúng dòng đang chọn, nên cú bấm rơi vào hư không.
|
|
|
|
def _hang_dang_chon(window):
|
|
"""(page, sub) mà thanh menu đang tô sáng, hoặc None."""
|
|
from PySide6.QtCore import Qt
|
|
|
|
for tree in (window.nav, window.nav_bottom):
|
|
item = tree.currentItem()
|
|
if item is not None:
|
|
data = item.data(0, Qt.UserRole) or {}
|
|
return data.get("page"), data.get("sub")
|
|
return None
|
|
|
|
|
|
def test_vet_sang_thanh_menu_khop_voi_noi_dung_dang_hien(window):
|
|
"""Không khớp là cú bấm đầu tiên vào đúng mục đó sẽ rơi vào hư không."""
|
|
dang_chon = _hang_dang_chon(window)
|
|
|
|
assert dang_chon is not None, "thanh menu không tô sáng dòng nào"
|
|
page, sub = dang_chon
|
|
assert page == window._ROW_WORKSPACE
|
|
# Bat bien that su quan trong: vet sang KHOP noi dung. Man hinh ha canh la
|
|
# cai nao thi tuy cong project, nhung hai thu nay khong bao gio duoc lech.
|
|
assert sub == window.workspace.current_subtab(), (
|
|
f"nội dung ở sub-tab {window.workspace.current_subtab()} "
|
|
f"nhưng thanh menu đang sáng ở {sub}")
|
|
|
|
|
|
def test_bam_project_tren_thanh_menu_an_ngay_lan_dau(window):
|
|
"""Tái hiện đúng thao tác của người dùng: mở app xong bấm ngay "Project"."""
|
|
from PySide6.QtCore import Qt
|
|
|
|
project_sub = window.workspace._project_tab_idx
|
|
muc_project = None
|
|
for i in range(window.nav.topLevelItemCount()):
|
|
it = window.nav.topLevelItem(i)
|
|
data = it.data(0, Qt.UserRole) or {}
|
|
if data.get("page") == window._ROW_WORKSPACE and data.get("sub") == project_sub:
|
|
muc_project = it
|
|
break
|
|
if muc_project is None:
|
|
pytest.skip("thanh menu chưa dựng mục con cho sub-tab Project")
|
|
|
|
if window.workspace.current_subtab() == project_sub:
|
|
pytest.skip("cổng project đang đóng — app đã hạ cánh sẵn ở màn Project")
|
|
|
|
assert window.nav.currentItem() is not muc_project, (
|
|
"mục Project đang được tô sáng sẵn dù nội dung ở Cowork — "
|
|
"bấm vào nó sẽ không phát tín hiệu nào")
|
|
|
|
window.nav.setCurrentItem(muc_project)
|
|
|
|
assert window.workspace.current_subtab() == project_sub
|
|
|
|
|
|
def test_khi_cong_project_MO_thi_ha_canh_o_cowork_va_vet_sang_theo(window):
|
|
"""Nhánh của người dùng ĐÃ chọn một project — nhánh mà bug được báo.
|
|
|
|
Trước đây bài này mở cổng bằng cửa sau ``setTabVisible(True)`` vì môi trường
|
|
test không có project nào (``core/projects.py`` ghi vào ``~/.cowork_local``
|
|
thật, nên test không tạo project). Cửa sau đó hết tác dụng từ khi cổng được
|
|
điều khiển bằng ``_current_id``: ``refresh()``/``goto_all_projects()`` đóng
|
|
lại ngay. Giờ mở cổng bằng đúng đường thật — chọn một project — và bỏ qua
|
|
bài này trên máy chưa có project nào.
|
|
"""
|
|
from PySide6.QtCore import Qt
|
|
|
|
ws = window.workspace
|
|
if ws._cowork_tab_idx < 0:
|
|
pytest.skip("bản dựng này không có sub-tab Cowork")
|
|
if ws.project_list.count() == 0:
|
|
pytest.skip("máy chạy test chưa có project nào — cổng không mở được")
|
|
|
|
ws.project_list.setCurrentRow(0)
|
|
try:
|
|
window.goto_all_projects()
|
|
|
|
assert ws.current_subtab() == ws._cowork_tab_idx
|
|
assert ws._history_opened is True
|
|
|
|
item = window.nav.currentItem()
|
|
assert item is not None, "thanh menu không tô sáng dòng nào"
|
|
data = item.data(0, Qt.UserRole) or {}
|
|
assert data.get("sub") == ws._cowork_tab_idx, (
|
|
f"nội dung ở Cowork ({ws._cowork_tab_idx}) "
|
|
f"nhưng thanh menu sáng ở {data.get('sub')}")
|
|
finally:
|
|
ws.project_list.setCurrentRow(-1) # đóng cổng lại đúng đường thật
|
|
window.goto_all_projects()
|