Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions src/frontend/web/von_interface/static/js/chatTab.js
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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');
}
Expand Down
71 changes: 71 additions & 0 deletions src/frontend/web/von_interface/static/js/test/chatTab.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import {
__testOnly_showNewSharedMessagesIndicator,
__testOnly_updateScrollToEndButtonVisibility,
__testOnly_reduceThinkingCardDisplayState,
__testOnly_setThinkingState,
__testOnly_normaliseThinkingActivityHistory,
__testOnly_renderThinkingCardBodyHTML,
__testOnly_bindConceptSelectionClicks,
Expand Down Expand Up @@ -2296,6 +2297,76 @@ describe('thinking card toggle accessibility', () => {
});
});

describe('copy diagnostics button visibility on preserved finished card', () => {
beforeEach(() => {
document.body.innerHTML = `
<div id="scrollableField"></div>
<div class="thinking-card-wrapper" id="thinkingCardWrapper" aria-hidden="true">
<div class="thinking-card" role="status" aria-live="polite">
<div class="thinking-card-header" id="loadingIndicator">
<span class="thinking-card-phase loading-indicator-text">Thinking...</span>
<span id="thinkingCardStatusBadge" class="thinking-card-status active" aria-hidden="true">Active</span>
<span class="thinking-card-meta" id="thinkingCardMeta"></span>
<button id="thinkingCardToggleButton" type="button" aria-hidden="true" aria-expanded="true" aria-controls="loadingIndicatorDetail" aria-label="Collapse thinking details" title="Collapse thinking details">
<span class="thinking-card-toggle-icon" aria-hidden="true">⌄</span>
<span class="visually-hidden">Toggle thinking details</span>
</button>
<button id="retryThinkingButton" type="button" aria-hidden="true">Retry</button>
<button id="copyThinkingDiagnosticsButton" type="button" aria-hidden="true">Copy diagnostics</button>
<button id="abortButton" type="button" aria-hidden="true"></button>
</div>
<div class="thinking-card-body" id="loadingIndicatorDetail" aria-live="polite"></div>
</div>
</div>
<button id="sendButton"></button>
<textarea id="promptInput"></textarea>
<input type="checkbox" id="annotationToggle" />
`;
});

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 = `
Expand Down
Loading