mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-06-17 09:41:58 +00:00
Merge pull request #46244 from skyc1e/fix/desktop-explorer-refresh
fix(desktop): keep file tree refresh clickable
This commit is contained in:
parent
423d24780b
commit
9d2ec8d35a
2 changed files with 80 additions and 5 deletions
75
apps/desktop/src/app/right-sidebar/index.test.tsx
Normal file
75
apps/desktop/src/app/right-sidebar/index.test.tsx
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
import { cleanup, fireEvent, render, screen, waitFor } from '@testing-library/react'
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
|
||||
import type { HermesReadDirResult } from '@/global'
|
||||
import { $connection, setCurrentCwd } from '@/store/session'
|
||||
|
||||
import { resetProjectTreeState } from './files/use-project-tree'
|
||||
|
||||
import { RightSidebarPane } from './index'
|
||||
|
||||
const readDir = vi.fn<(path: string) => Promise<HermesReadDirResult>>()
|
||||
const selectPaths = vi.fn()
|
||||
|
||||
function ok(entries: { name: string; path: string; isDirectory: boolean }[]): HermesReadDirResult {
|
||||
return { entries }
|
||||
}
|
||||
|
||||
function installBridge() {
|
||||
;(
|
||||
window as unknown as {
|
||||
hermesDesktop: {
|
||||
readDir: typeof readDir
|
||||
selectPaths: typeof selectPaths
|
||||
}
|
||||
}
|
||||
).hermesDesktop = { readDir, selectPaths }
|
||||
}
|
||||
|
||||
describe('RightSidebarPane', () => {
|
||||
beforeEach(() => {
|
||||
$connection.set(null)
|
||||
resetProjectTreeState()
|
||||
setCurrentCwd('/repo')
|
||||
readDir.mockReset()
|
||||
selectPaths.mockReset()
|
||||
readDir.mockResolvedValue(ok([{ name: 'README.md', path: '/repo/README.md', isDirectory: false }]))
|
||||
selectPaths.mockResolvedValue(['/repo-next'])
|
||||
installBridge()
|
||||
})
|
||||
|
||||
afterEach(() => {
|
||||
cleanup()
|
||||
$connection.set(null)
|
||||
setCurrentCwd('')
|
||||
resetProjectTreeState()
|
||||
delete (window as unknown as { hermesDesktop?: unknown }).hermesDesktop
|
||||
})
|
||||
|
||||
it('refreshes the current tree without opening the folder picker', async () => {
|
||||
const onChangeCwd = vi.fn()
|
||||
|
||||
render(<RightSidebarPane onActivateFile={vi.fn()} onActivateFolder={vi.fn()} onChangeCwd={onChangeCwd} />)
|
||||
|
||||
await waitFor(() => expect(screen.getByRole('button', { name: 'Refresh tree' }).hasAttribute('disabled')).toBe(false))
|
||||
|
||||
readDir.mockClear()
|
||||
|
||||
fireEvent.click(screen.getByRole('button', { name: 'Refresh tree' }))
|
||||
|
||||
await waitFor(() => expect(readDir).toHaveBeenCalledWith('/repo'))
|
||||
expect(selectPaths).not.toHaveBeenCalled()
|
||||
|
||||
fireEvent.click(screen.getByRole('button', { name: 'Open folder' }))
|
||||
|
||||
await waitFor(() =>
|
||||
expect(selectPaths).toHaveBeenCalledWith({
|
||||
defaultPath: '/repo',
|
||||
directories: true,
|
||||
multiple: false,
|
||||
title: 'Change working directory'
|
||||
})
|
||||
)
|
||||
await waitFor(() => expect(onChangeCwd).toHaveBeenCalledWith('/repo-next'))
|
||||
})
|
||||
})
|
||||
|
|
@ -126,12 +126,12 @@ interface FilesystemTabProps extends FileTreeBodyProps {
|
|||
onRefresh: () => void
|
||||
}
|
||||
|
||||
// Sidebar palette + hover-reveal: refresh tracks label hover; collapse-all
|
||||
// stays visible while any folder is expanded.
|
||||
// Sidebar palette + hover-reveal: header actions stay reachable while moving
|
||||
// from the project label to the action buttons.
|
||||
const HEADER_ACTION_CLASS =
|
||||
'text-sidebar-foreground/70 hover:bg-sidebar-accent! hover:text-sidebar-accent-foreground! focus-visible:ring-sidebar-ring'
|
||||
|
||||
const HEADER_ACTION_LABEL_REVEAL = `${HEADER_ACTION_CLASS} pointer-events-none opacity-0 transition-opacity focus-visible:pointer-events-auto focus-visible:opacity-100 peer-focus-visible/project-label:pointer-events-auto peer-focus-visible/project-label:opacity-100 peer-hover/project-label:pointer-events-auto peer-hover/project-label:opacity-100`
|
||||
const HEADER_ACTION_LABEL_REVEAL = `${HEADER_ACTION_CLASS} pointer-events-none opacity-0 transition-opacity focus-visible:pointer-events-auto focus-visible:opacity-100 group-focus-within/project-header:pointer-events-auto group-focus-within/project-header:opacity-100 group-hover/project-header:pointer-events-auto group-hover/project-header:opacity-100`
|
||||
|
||||
function FilesystemTab({
|
||||
canCollapse,
|
||||
|
|
@ -158,7 +158,7 @@ function FilesystemTab({
|
|||
return (
|
||||
<div className="flex min-h-0 flex-1 flex-col">
|
||||
<RightSidebarSectionHeader>
|
||||
<div className="peer/project-label flex min-w-0 flex-1">
|
||||
<div className="flex min-w-0 flex-1">
|
||||
<button
|
||||
className="flex w-full min-w-0 items-center rounded-md text-left hover:text-(--ui-text-secondary)"
|
||||
onClick={() => void onChangeFolder()}
|
||||
|
|
@ -216,7 +216,7 @@ function FilesystemTab({
|
|||
}
|
||||
|
||||
export function RightSidebarSectionHeader({ children }: { children: ReactNode }) {
|
||||
return <div className="flex h-7 shrink-0 items-center px-2.5">{children}</div>
|
||||
return <div className="group/project-header flex h-7 shrink-0 items-center px-2.5">{children}</div>
|
||||
}
|
||||
|
||||
interface FileTreeBodyProps {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue