Three things that said one thing and did another
All three shipped in the last two commits, and all three are the same kind of mistake: an interface that looks right and is not. The folder settings page could not be scrolled. `.main` is a flex column with `min-height: 0`, so a `.page` dropped straight into it overflows the viewport with nothing to scroll -- Save and Back end up below the bottom of the window, reachable by zooming out or by dragging the prompt textarea up out of the way. Every other page of this shape already wraps its content in `.admin-scroll`; this one did not. The two class names that scroll are one rule in admin.css precisely so this is a wrapper somebody forgot rather than a value they got wrong, and now it is noted. The project directory was a text box, on the one screen that asks for an absolute path on another machine. It is the same button-and-hidden-field the new-chat screen uses, wired by `[data-dir-field]` in ui.js -- scoped to that attribute so this and the composer's own handler cannot both answer one click and open two dialogs. The composer keeps its own because it does more: it follows the selected profile's default directory until somebody picks their own, which only means something while a chat is being created. With no connection chosen it says so rather than opening onto nothing, and Clear is always there, because browsing somewhere and changing your mind before saving needs a way back to "no opinion" as much as clearing a saved one does. And "New chat" did not follow the Chat/Agent switch. The button sits above the scroll area rather than inside the tree the switch swaps, so it went on saying "New chat" over a list of agent chats. It moves to its own partial and arrives out of band, the way the chat title already does. Renaming it to something neutral would have hidden the bug rather than fixed it, and would have cost the `?kind=agent` preselection the label is there to explain. The tests that existed asserted a page load, which re-renders the button anyway -- which is exactly why nobody saw it. The new ones assert the fragment. The directory field was driven under a DOM stub first. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -290,6 +290,58 @@ def test_the_settings_page_renders_what_is_stored(client: TestClient, db, regist
|
||||
assert f'hx-patch="/api/folders/{folder.id}"' in page
|
||||
|
||||
|
||||
def test_the_settings_page_can_be_scrolled(client: TestClient, db, registered):
|
||||
"""`.main` is a flex column with `min-height: 0`, so a `.page` dropped
|
||||
straight into it overflows the viewport with nothing to scroll and Save ends
|
||||
up below the bottom of the window. Every other page of this shape wraps its
|
||||
content in the scrolling container; this one did not."""
|
||||
folder = _folder(db, "Errands")
|
||||
page = client.get(f"/folders/{folder.id}").text
|
||||
assert 'class="admin-scroll"' in page
|
||||
assert page.index('class="admin-scroll"') < page.index('class="page"')
|
||||
|
||||
|
||||
def test_the_project_directory_is_chosen_rather_than_typed(
|
||||
client: TestClient, db, registered
|
||||
):
|
||||
"""The same control the new-chat screen uses, and for the reason it gives
|
||||
there: a path on another machine is something you would rather find than
|
||||
spell."""
|
||||
_add_connection(db)
|
||||
settings_store.update(db, {"enabled": True}, key=settings_store.AGENTS)
|
||||
db.add(
|
||||
SshProfile(
|
||||
owner_id=db.scalars(select(User).order_by(User.created_at)).first().id,
|
||||
name="Box",
|
||||
host="example.test",
|
||||
username="root",
|
||||
host_key="ssh-ed25519 AAAA",
|
||||
)
|
||||
)
|
||||
db.commit()
|
||||
folder = _folder(db, "Errands", project_dir="/srv/project")
|
||||
|
||||
page = client.get(f"/folders/{folder.id}").text
|
||||
assert "data-dir-field" in page
|
||||
assert "data-dir-browse" in page
|
||||
# The hidden field is what the form actually submits, so it must carry the
|
||||
# stored value -- the button beside it only shows it.
|
||||
assert 'name="project_dir"' in page
|
||||
assert 'value="/srv/project"' in page
|
||||
assert 'type="hidden"' in page
|
||||
|
||||
|
||||
def test_the_directory_can_still_be_cleared(client: TestClient, db, registered):
|
||||
"""A hidden input always submits, so an empty one means "no opinion" rather
|
||||
than "leave it alone" -- which is the whole reason `update_folder` reads the
|
||||
raw form."""
|
||||
_add_connection(db)
|
||||
folder = _folder(db, "Errands", project_dir="/srv/project")
|
||||
client.patch(f"/api/folders/{folder.id}", data={"project_dir": ""})
|
||||
db.refresh(folder)
|
||||
assert folder.project_dir == ""
|
||||
|
||||
|
||||
def test_the_settings_page_refuses_someone_elses_folder(client: TestClient, db, registered):
|
||||
other = User(name="Sam", email="sam@shire.test", password_hash="x")
|
||||
db.add(other)
|
||||
|
||||
Reference in New Issue
Block a user