mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-06-23 10:42:00 +00:00
fix(desktop): filter undefined entries in AttachmentList to prevent refText crash on session switch (#49624)
* fix(desktop): filter undefined entries in AttachmentList to prevent refText crash on session switch When switching sessions, the attachments array can contain stale/undefined entries from the previous session's state. Accessing attachment.refText on an undefined entry throws TypeError, breaking session switching entirely. Fix: add .filter(Boolean) before .map() to skip undefined/null entries. Fixes #49614 * fix(desktop): update I18nConfigClient usage in attachment test The i18n config API changed from getLocale/saveLocale to getConfig/saveConfig. Update the test fixture to match.
This commit is contained in:
parent
c768c4b71c
commit
bef1d3e4ff
2 changed files with 70 additions and 1 deletions
69
apps/desktop/src/app/chat/composer/attachments.test.tsx
Normal file
69
apps/desktop/src/app/chat/composer/attachments.test.tsx
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
import { cleanup, render, screen } from '@testing-library/react'
|
||||
import { afterEach, describe, expect, it } from 'vitest'
|
||||
|
||||
import { I18nProvider } from '@/i18n/context'
|
||||
|
||||
import { AttachmentList } from './attachments'
|
||||
import type { ComposerAttachment } from '@/store/composer'
|
||||
|
||||
function makeAttachment(id: string, label = 'test.pdf'): ComposerAttachment {
|
||||
return { id, kind: 'file', label }
|
||||
}
|
||||
|
||||
function renderWithI18n(ui: React.ReactNode) {
|
||||
return render(
|
||||
<I18nProvider configClient={{ getConfig: async () => ({}), saveConfig: async () => ({ ok: true }) }}>
|
||||
{ui}
|
||||
</I18nProvider>
|
||||
)
|
||||
}
|
||||
|
||||
describe('AttachmentList', () => {
|
||||
afterEach(() => {
|
||||
cleanup()
|
||||
})
|
||||
|
||||
it('renders valid attachments', () => {
|
||||
const attachments = [makeAttachment('a', 'doc.pdf'), makeAttachment('b', 'img.png')]
|
||||
renderWithI18n(<AttachmentList attachments={attachments} />)
|
||||
expect(screen.getByText('doc.pdf')).toBeDefined()
|
||||
expect(screen.getByText('img.png')).toBeDefined()
|
||||
})
|
||||
|
||||
it('renders empty list without error', () => {
|
||||
renderWithI18n(<AttachmentList attachments={[]} />)
|
||||
const container = screen.getByTestId?.('composer-attachments') ?? document.querySelector('[data-slot="composer-attachments"]')
|
||||
expect(container).toBeDefined()
|
||||
})
|
||||
|
||||
it('does not crash when attachments array contains undefined entries', () => {
|
||||
// Repro: session switch can leave stale/undefined entries in the
|
||||
// attachments array, causing a TypeError at attachment.refText.
|
||||
const attachments = [
|
||||
makeAttachment('a', 'good.pdf'),
|
||||
undefined as unknown as ComposerAttachment,
|
||||
makeAttachment('b', 'also-good.png')
|
||||
]
|
||||
|
||||
expect(() => {
|
||||
renderWithI18n(<AttachmentList attachments={attachments} />)
|
||||
}).not.toThrow()
|
||||
|
||||
// Only valid attachments should render
|
||||
expect(screen.getByText('good.pdf')).toBeDefined()
|
||||
expect(screen.getByText('also-good.png')).toBeDefined()
|
||||
})
|
||||
|
||||
it('does not crash when attachments array contains null entries', () => {
|
||||
const attachments = [
|
||||
null as unknown as ComposerAttachment,
|
||||
makeAttachment('a', 'valid.txt')
|
||||
]
|
||||
|
||||
expect(() => {
|
||||
renderWithI18n(<AttachmentList attachments={attachments} />)
|
||||
}).not.toThrow()
|
||||
|
||||
expect(screen.getByText('valid.txt')).toBeDefined()
|
||||
})
|
||||
})
|
||||
|
|
@ -20,7 +20,7 @@ export function AttachmentList({
|
|||
}) {
|
||||
return (
|
||||
<div className="flex max-w-full flex-wrap gap-1.5 px-1 pt-1" data-slot="composer-attachments">
|
||||
{attachments.map(attachment => (
|
||||
{attachments.filter(Boolean).map(attachment => (
|
||||
<AttachmentPill attachment={attachment} key={attachment.id} onRemove={onRemove} />
|
||||
))}
|
||||
</div>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue