Files
cowork-local/tools/check_cowork_screen.py
T
Nam Pham Dinh ThanhandClaude Opus 5 63b0af27e9 Cowork: composer spans the screen, files panel keeps one heading
Read the wireframe as a tree this time instead of a flat list of its text, and
the difference was structural rather than cosmetic.

The drawing nests it: a toolbar row, then a body row holding the transcript and
the files column side by side, then the composer as its OWN full-width row under
both, then the status line. The app had the composer inside the chat column, so
it stopped at the files panel's edge — the input narrowed by ~220px the moment a
deliverable appeared. It is now a sibling of the splitter, spanning 1474 of 1490
px with the panel open.

The panel also carried two headings: a "Files" label, and under it the section's
own "TỆP ĐẦU RA (n)". The drawing has one — "TỆP ĐẦU RA (3) ›" — so the section
header moves onto that row with the collapse chevron at its right, and the label
steps out of the layout.

The check for that needed two attempts. Asking whether the "Files" label is
visible passes either way: unparented, it reports invisible whether or not the
code hides it. It now counts the headings the panel actually shows.

23/23 checkers pass.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-18 15:56:42 +09:00

141 lines
5.3 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""Workspace ▸ Cowork against its wireframe (section 5).
The drawing heads the screen with the THREAD's title — "Gom số liệu doanh thu",
not the word "Cowork" — with the model beside it, Skills and Cuộc trò chuyện mới
on the right, and a caps TỆP ĐẦU RA (n) panel down the side.
"""
from __future__ import annotations
import os
import sys
sys.stdout.reconfigure(encoding="utf-8", errors="replace")
from pathlib import Path
REPO = Path(__file__).resolve().parent.parent
sys.path.insert(0, str(REPO.parent))
sys.path.insert(0, str(Path(__file__).resolve().parent))
os.environ.setdefault("QT_QPA_PLATFORM", "offscreen")
from capture_screens import ( # noqa: E402
_apply_theme, _freeze_schedulers, _isolate_home, _load_fonts)
def main() -> int:
sandbox = _isolate_home()
from PySide6.QtWidgets import QApplication
app = QApplication([])
_load_fonts()
_freeze_schedulers()
_apply_theme(app)
from cowork_local.config import CONFIG_DIR
assert str(sandbox) in str(CONFIG_DIR), f"isolation failed: {CONFIG_DIR}"
from seed_demo_data import seed
seed()
from cowork_local.app import MainWindow
from cowork_local.config import AppConfig
from cowork_local.core.history import list_conversations, load_conversation
from cowork_local.i18n import set_language, tr
from cowork_local.state import AppContext
set_language("vi")
win = MainWindow(AppContext(AppConfig.load()), user_name="local")
win.resize(1920, 1000)
win.show()
app.processEvents()
win._goto(win._ROW_WORKSPACE, win.workspace._cowork_tab_idx)
app.processEvents()
c = win.cowork
fails = []
# a new thread has no title yet, so the screen name stands in
print(f"chua mo thread: tieu de={c._title_lbl.text()!r}")
if not c._title_lbl.text().strip():
fails.append("tieu de trong khi chua mo thread")
convs = list_conversations()
if not convs:
fails.append("khong co hoi thoai de kiem")
else:
conv = load_conversation(Path(convs[0]["path"]))
c.load_conversation(conv)
app.processEvents()
want = conv.get("title", "")
print(f"sau khi mo thread: tieu de={c._title_lbl.text()!r} (thread={want!r})")
if want and c._title_lbl.text() != want:
fails.append(f"tieu de khong theo thread: {c._title_lbl.text()!r} != {want!r}")
if c._title_lbl.text() == tr("cowork.title") and want:
fails.append("tieu de van la ten man hinh")
# the files panel is a caps section carrying its own count
head = c.output_section.header.text()
print(f"pane tep dau ra: {head!r}")
body = head.lstrip("▾▸ ").split(" (")[0]
if body != body.upper():
fails.append(f"tieu de pane chua viet hoa: {head!r}")
if "(" not in head:
fails.append("tieu de pane khong kem so luong")
# toolbar keeps both actions the drawing shows
for name, btn in (("Skills", c.skills_btn), ("chat moi", c._new_btn)):
if not btn.isVisible():
fails.append(f"thieu nut {name} tren thanh cong cu")
print(f"nut tren thanh cong cu: {c.skills_btn.text()!r}, {c._new_btn.text()!r}")
# one heading on the files panel, with the chevron at its right — the
# drawing has "TỆP ĐẦU RA (3) ›" and nothing above it
from PySide6.QtCore import QPoint as _QP
hdr_w = c.output_section.header
chev = c._io_collapse_btn
same_row = abs(hdr_w.mapTo(c, _QP(0, 0)).y() - chev.mapTo(c, _QP(0, 0)).y()) <= 8
chev_right = chev.mapTo(c, _QP(0, 0)).x() > hdr_w.mapTo(c, _QP(0, 0)).x()
# Count what the panel actually shows as headings. Asking whether the old
# label is visible proved nothing: unparented, it reports invisible whether
# or not the code hides it.
from PySide6.QtWidgets import QLabel
heads = [l.text() for l in c._io_widget.findChildren(QLabel)
if l.isVisible() and l.text().strip()]
print(f"tieu de hien trong pane: {heads} | "
f"chevron cung hang={same_row} ben phai={chev_right}")
if heads:
fails.append(f"pane co tieu de thua ngoai '{hdr_w.text()}': {heads}")
if not (same_row and chev_right):
fails.append("chevron thu gon khong nam cuoi hang tieu de pane")
# the composer spans the screen, under BOTH columns — inside the chat
# column it stopped at the files panel's edge and shrank when files arrived
from PySide6.QtCore import QPoint
c._set_io_collapsed(False)
app.processEvents()
split = c.center_split
files_pane = split.widget(1)
comp_right = c.composer.mapTo(c, QPoint(c.composer.width(), 0)).x()
files_left = files_pane.mapTo(c, QPoint(0, 0)).x()
below = c.composer.mapTo(c, QPoint(0, 0)).y() > split.mapTo(c, QPoint(0, 0)).y()
spans = comp_right > files_left
print(f"o nhap: rong {c.composer.width()} / man {c.width()} | "
f"duoi splitter={below} | trai qua duoi pane tep={spans}")
if not below:
fails.append("o nhap khong nam duoi hang than")
if not spans:
fails.append("o nhap dung lai o mep pane tep, khong trai het man")
print()
for f in fails:
print("FAIL " + f)
print("PASS man Cowork khop ban ve" if not fails else f"{len(fails)} problem(s)")
sys.stdout.flush()
os._exit(1 if fails else 0)
if __name__ == "__main__":
raise SystemExit(main())