Re-pushed by rodboev fixing both bounce findings (parent streaming-state isolation + nested-fork batch-select) plus a select-handler selector fix. On current master (0 behind); sessions.js byte-identical to PR head. Co-authored-by: Rod Boev <rod.boev@gmail.com>
87 lines
3.7 KiB
Python
87 lines
3.7 KiB
Python
"""Structural regressions for sidebar session inline rename (#1153).
|
|
|
|
The first Enter after double-click rename could appear to revert because the
|
|
frontend cleared `_renamingSid` before `/api/session/rename` completed. That
|
|
let normal session-list refreshes re-render stale cached data and destroy the
|
|
input while the save was still in flight.
|
|
"""
|
|
|
|
import pathlib
|
|
|
|
|
|
REPO = pathlib.Path(__file__).parent.parent
|
|
SESSIONS_JS = (REPO / "static" / "sessions.js").read_text(encoding="utf-8")
|
|
|
|
|
|
def _session_rename_block():
|
|
start = SESSIONS_JS.find("function _buildSessionRenameStarter(")
|
|
assert start >= 0, "shared session rename helper not found"
|
|
end = SESSIONS_JS.find("function _appendSessionCopyLinkAction(", start)
|
|
assert end > start, "session inline rename block end marker not found"
|
|
return SESSIONS_JS[start:end]
|
|
|
|
|
|
def test_session_rename_finish_is_idempotent():
|
|
block = _session_rename_block()
|
|
assert "let finishDone=false;" in block, (
|
|
"session rename finish() must track completion so Enter, blur, Escape, "
|
|
"and delayed pointer paths cannot complete twice"
|
|
)
|
|
guard_pos = block.find("if(finishDone) return;")
|
|
set_pos = block.find("finishDone=true;")
|
|
assert guard_pos >= 0 and set_pos > guard_pos, (
|
|
"session rename finish() must return early after the first completion"
|
|
)
|
|
|
|
|
|
def test_session_rename_guard_releases_after_save_path_completes():
|
|
block = _session_rename_block()
|
|
assert block.count("_renamingSid=null;") == 1, (
|
|
"_renamingSid must be cleared from one release helper only, not at the "
|
|
"top of finish() before the async rename save settles"
|
|
)
|
|
release_pos = block.find("const releaseRename=()=>{")
|
|
clear_pos = block.find("_renamingSid=null;")
|
|
assert release_pos >= 0 and clear_pos > release_pos, (
|
|
"_renamingSid should be cleared inside releaseRename(), after the "
|
|
"selected finish path has completed"
|
|
)
|
|
api_pos = block.find("await api('/api/session/rename'")
|
|
finally_pos = block.find("finally{")
|
|
release_call_pos = block.find("releaseRename();", finally_pos)
|
|
assert api_pos >= 0 and finally_pos > api_pos and release_call_pos > finally_pos, (
|
|
"save path must await /api/session/rename before releaseRename() clears "
|
|
"the render guard"
|
|
)
|
|
|
|
|
|
def test_session_rename_success_updates_cache_and_active_session_title():
|
|
block = _session_rename_block()
|
|
assert "_allSessions.find(item=>item&&item.session_id===session.session_id)" in block
|
|
assert "target.display_title=nextTitle;" in block
|
|
assert "target._state_db_title=nextTitle;" in block
|
|
assert "if(S.session&&S.session.session_id===session.session_id){applyLocalTitle(S.session, nextTitle);syncTopbar();}" in block, (
|
|
"successful session rename must keep cached and active titles coherent"
|
|
)
|
|
|
|
|
|
def test_session_rename_failure_restores_state_and_surfaces_error():
|
|
block = _session_rename_block()
|
|
catch_pos = block.find("}catch(err){")
|
|
assert catch_pos >= 0, "session rename save path must handle API failures"
|
|
catch_block = block[catch_pos:block.find("}finally{", catch_pos)]
|
|
assert "applyTitle(oldTitle,false);" in catch_block, (
|
|
"failed session rename must restore the cached/active title instead of "
|
|
"silently appearing successful"
|
|
)
|
|
assert "setStatus(msg);" in catch_block
|
|
assert "showToast(msg,3000,'error')" in catch_block
|
|
|
|
|
|
def test_session_rename_blur_commits_current_title():
|
|
block = _session_rename_block()
|
|
assert "inp.onblur=()=>{ if(_renamingSid===session.session_id) finish(true); };" in block, (
|
|
"blur should commit the edited title so rename matches the long-standing "
|
|
"top-level session behavior"
|
|
)
|