fix(#5501): clear pending retry state on render invalidation (Codex gate)
Codex re-gate SILENT: a retry whose fetch is invalidated mid-flight (e.g. a profile switch) left the button stuck as an inert 'Retrying…' with no request in flight — the stale catch returns before _showSessionListLoadError and the .finally() bails when the skeleton removed the old button. _invalidateSessionListRenders() now clears the pending retry markers (retrying, _retryFailedFocus) so the next repaint shows an actionable idle Retry. Regression test added (fails without the fix); test harness extracts _invalidateSessionListRenders + declares its render-gen globals. Co-authored-by: rodboev <rodboev@users.noreply.github.com>
This commit is contained in:
1 parent
9be4048c72
commit
f6cc48b834
2 files changed
+51
No files matched your search
@@ -4251,6 +4251,17 @@ function _invalidateSessionListRenders(){
|
||||
_renderSessionListGen++;
|
||||
_pendingSessionListPayload = null;
|
||||
_renderSessionListQueuedRequest = null;
|
||||
// A retry whose fetch is invalidated here (e.g. a profile switch mid-retry)
|
||||
// would otherwise leave the error note stuck as an inert "Retrying…" button
|
||||
// with no request in flight — the stale fetch returns before
|
||||
// _showSessionListLoadError and the .finally() bails when the old button was
|
||||
// removed. Clear the pending retry markers so the next repaint shows an
|
||||
// actionable idle Retry again.
|
||||
if(_sessionListLoadError && (_sessionListLoadError.retrying || _sessionListLoadError._retryFailedFocus)){
|
||||
_sessionListLoadError = {..._sessionListLoadError};
|
||||
delete _sessionListLoadError.retrying;
|
||||
delete _sessionListLoadError._retryFailedFocus;
|
||||
}
|
||||
}
|
||||
if(typeof window!=='undefined') window._invalidateSessionListRenders = _invalidateSessionListRenders;
|
||||
|
||||
|
||||
@@ -39,6 +39,7 @@ def _build_node_script(extra_js):
|
||||
src = SESSIONS_JS.read_text(encoding="utf-8")
|
||||
show_error_fn = _extract_function(src, "_showSessionListLoadError")
|
||||
retry_note_fn = _extract_function(src, "_renderSessionListLoadErrorNote")
|
||||
invalidate_fn = _extract_function(src, "_invalidateSessionListRenders")
|
||||
return f"""
|
||||
class FakeClassList {{
|
||||
constructor(node) {{
|
||||
@@ -146,6 +147,9 @@ global.document = {{ createElement: (tag) => new FakeElement(tag) }};
|
||||
global.$ = (id) => id === 'sessionList' ? list : null;
|
||||
global._allSessions = [];
|
||||
global._sessionListLoadError = null;
|
||||
global._renderSessionListGen = 0;
|
||||
global._pendingSessionListPayload = null;
|
||||
global._renderSessionListQueuedRequest = null;
|
||||
global._sessionListFromCacheCalls = [];
|
||||
global.renderSessionListCalls = [];
|
||||
global.renderSessionListFromCache = () => {{
|
||||
@@ -184,6 +188,7 @@ global.renderSessionList = (opts) => {{
|
||||
}};
|
||||
{show_error_fn}
|
||||
{retry_note_fn}
|
||||
{invalidate_fn}
|
||||
{extra_js}
|
||||
"""
|
||||
|
||||
@@ -579,3 +584,38 @@ def test_session_list_error_note_has_live_region_and_pending_uses_aria_disabled(
|
||||
assert "Retrying..." not in note_fn
|
||||
# keyboard focus restored on a failed retry
|
||||
assert "_retryFailedFocus" in note_fn
|
||||
|
||||
|
||||
def test_retry_pending_state_cleared_on_render_invalidation():
|
||||
"""#5505 gate (Codex SILENT): a retry whose fetch is invalidated mid-flight
|
||||
(e.g. a profile switch) must not leave the button stuck as an inert
|
||||
'Retrying…' with no request in flight. _invalidateSessionListRenders() clears
|
||||
the pending retry markers so the next repaint shows an actionable idle Retry."""
|
||||
if NODE is None:
|
||||
pytest.skip("node not on PATH")
|
||||
|
||||
script = _render_script(
|
||||
"""
|
||||
_showSessionListLoadError(new Error('backend busy'));
|
||||
global._sessionListLoadError = {...global._sessionListLoadError, retrying: true, _retryFailedFocus: true};
|
||||
_invalidateSessionListRenders();
|
||||
global.renderSessionListFromCache();
|
||||
const note = list.children[0];
|
||||
const retry = findButton(note);
|
||||
console.log(JSON.stringify({
|
||||
retryingCleared: !global._sessionListLoadError.retrying,
|
||||
focusFlagCleared: !global._sessionListLoadError._retryFailedFocus,
|
||||
text: retry.textContent,
|
||||
ariaDisabled: retry.getAttribute('aria-disabled'),
|
||||
clickable: typeof retry.onclick === 'function',
|
||||
}));
|
||||
"""
|
||||
)
|
||||
body = _run_node(script)
|
||||
assert body == {
|
||||
"retryingCleared": True,
|
||||
"focusFlagCleared": True,
|
||||
"text": "Retry",
|
||||
"ariaDisabled": None,
|
||||
"clickable": True,
|
||||
}
|
||||
Reference in new issue
Block a user