diff --git a/src/frontend/web/von_interface/static/js/chatTab.js b/src/frontend/web/von_interface/static/js/chatTab.js index 7be8e3b..96c0ed0 100644 --- a/src/frontend/web/von_interface/static/js/chatTab.js +++ b/src/frontend/web/von_interface/static/js/chatTab.js @@ -1600,6 +1600,10 @@ export function __testOnly_syncThinkingCanonicalHistoriesFromProgress(request, p return syncThinkingCanonicalHistoriesFromProgress(request, progress); } +export function __testOnly_setThinkingState(isThinking, request, options) { + return setThinkingState(isThinking, request, options); +} + function updateThinkingCardStatusBadge(progress) { const badgeEl = document.getElementById('thinkingCardStatusBadge'); if (!badgeEl) { @@ -19020,8 +19024,8 @@ function setThinkingState(isThinking, request = activeChatRequest, options = {}) retryButton.setAttribute('aria-hidden', isThinking ? 'false' : 'true'); } if (copyDiagnosticsButton) { - copyDiagnosticsButton.setAttribute('aria-hidden', isThinking ? 'false' : 'true'); - if (!isThinking) { + copyDiagnosticsButton.setAttribute('aria-hidden', (isThinking || preserveFinishedCard) ? 'false' : 'true'); + if (!isThinking && !preserveFinishedCard) { copyDiagnosticsButton.textContent = 'Copy diagnostics'; copyDiagnosticsButton.classList.remove('success-feedback', 'error-feedback'); } diff --git a/src/frontend/web/von_interface/static/js/test/chatTab.test.js b/src/frontend/web/von_interface/static/js/test/chatTab.test.js index 5f83195..f5f7666 100644 --- a/src/frontend/web/von_interface/static/js/test/chatTab.test.js +++ b/src/frontend/web/von_interface/static/js/test/chatTab.test.js @@ -36,6 +36,7 @@ import { __testOnly_showNewSharedMessagesIndicator, __testOnly_updateScrollToEndButtonVisibility, __testOnly_reduceThinkingCardDisplayState, + __testOnly_setThinkingState, __testOnly_normaliseThinkingActivityHistory, __testOnly_renderThinkingCardBodyHTML, __testOnly_bindConceptSelectionClicks, @@ -2296,6 +2297,76 @@ describe('thinking card toggle accessibility', () => { }); }); +describe('copy diagnostics button visibility on preserved finished card', () => { + beforeEach(() => { + document.body.innerHTML = ` +
+ + + + + `; + }); + + afterEach(() => { + jest.restoreAllMocks(); + }); + + test('copy diagnostics button remains visible on preserved finished card (JVNAUTOSCI-1431)', () => { + const copyBtn = document.getElementById('copyThinkingDiagnosticsButton'); + const toggleBtn = document.getElementById('thinkingCardToggleButton'); + + // While thinking — both visible + __testOnly_setThinkingState(true, {}); + expect(copyBtn.getAttribute('aria-hidden')).toBe('false'); + expect(toggleBtn.getAttribute('aria-hidden')).toBe('false'); + + // Finished with preserveFinishedCard — both should stay visible + __testOnly_setThinkingState(false, {}, { preserveFinishedCard: true }); + expect(copyBtn.getAttribute('aria-hidden')).toBe('false'); + expect(toggleBtn.getAttribute('aria-hidden')).toBe('false'); + + // Finished without preserveFinishedCard — both should hide + __testOnly_setThinkingState(false, {}); + expect(copyBtn.getAttribute('aria-hidden')).toBe('true'); + expect(toggleBtn.getAttribute('aria-hidden')).toBe('true'); + }); + + test('copy diagnostics button resets text only when fully dismissed', () => { + const copyBtn = document.getElementById('copyThinkingDiagnosticsButton'); + + // Simulate a successful copy feedback state + copyBtn.textContent = 'Copied!'; + copyBtn.classList.add('success-feedback'); + + // Preserved finished card should keep the feedback text + __testOnly_setThinkingState(false, {}, { preserveFinishedCard: true }); + expect(copyBtn.textContent).toBe('Copied!'); + expect(copyBtn.classList.contains('success-feedback')).toBe(true); + + // Full dismissal should reset + __testOnly_setThinkingState(false, {}); + expect(copyBtn.textContent).toBe('Copy diagnostics'); + expect(copyBtn.classList.contains('success-feedback')).toBe(false); + }); +}); + describe('chat abort behaviour', () => { beforeEach(() => { document.body.innerHTML = `