mirror of
https://github.com/stablyai/orca.git
synced 2026-11-01 17:47:40 +00:00
* fix(ssh): draw every host list through one bounded, searchable host picker A generated ~/.ssh/config can import 13k+ SSH hosts, and several surfaces drew a row per host: Settings > General workspace directory 'Apply to', Notifications > Machines, the sidebar and Agents Hosts submenu, the composer run-target picker, the Add Project host selector and remote step, the skill-install machine pickers, Settings > Servers SSH host picker, repository 'Add to another host' and the automation host field and filter. They now share components/host-picker: boundHostList (pinned hosts plus a ranked, capped match list), HostCombobox for single choice (a Command in a Popover that mounts nothing until opened, replacing Selects that mount every item), and useBoundedHostRows with HostListSearchField and HostListOverflowNote for checklists. A host-list-render ratchet stops new JSX from mapping straight over a host collection. * fix(ssh): host lists keep room for search results, menu search is keyboard-reachable - boundHostList gives pinned hosts and other matches separate limits, and narrows pinned hosts by the query, so a large selection never hides what the user types. - In a dropdown, the host search is a menu item: arrow keys reach it, focus moves into the input, and arrows leave it again. - The Add Project host picker hides its setup actions while searching, so Enter picks the matching host. * fix(ssh): re-picking the current host in a host picker is not a change The Selects these pickers replaced suppressed same-value changes; the skill install form clears its workspace and target on a machine change. * chore(ci): let the shared ratchet runner pick up the host-list render ratchet main now discovers every check-*-ratchet.mjs through run-ratchets.mjs, so the separate workflow step would run it twice. * fix(ssh): host lists rank pinned matches and keep input order; label and scroll fixes - boundHostList ranks pinned and other hosts by the same match order before cutting each to its limit, then keeps input order among equal ranks, so a muted or checked exact match is always reachable and clicking a row never moves it. - The Servers SSH host picker is named by its form label again. - The sidebar Hosts submenu scrolls its host rows instead of running off screen. - The composer's overflow note sits outside the listbox.
38 lines
1.7 KiB
JavaScript
38 lines
1.7 KiB
JavaScript
import { describe, expect, it } from 'vitest'
|
|
|
|
import { countHostCollectionJsxMaps, isScannedPath } from './check-host-list-render-ratchet.mjs'
|
|
|
|
describe('countHostCollectionJsxMaps', () => {
|
|
it('counts JSX drawn straight from a host collection', () => {
|
|
expect(
|
|
countHostCollectionJsxMaps(
|
|
'{hostOptions.map((host) => (\n <SelectItem key={host.id} value={host.id} />\n))}'
|
|
)
|
|
).toBe(1)
|
|
expect(
|
|
countHostCollectionJsxMaps('{props.sshConnections.map((c) => <Row key={c.id} />)}')
|
|
).toBe(1)
|
|
expect(countHostCollectionJsxMaps('{targets.map(t => <li key={t.id} />)}')).toBe(1)
|
|
})
|
|
|
|
it('ignores bounded rows, data maps and comments', () => {
|
|
expect(countHostCollectionJsxMaps('{rows.shown.map((host) => <Row key={host.id} />)}')).toBe(0)
|
|
expect(countHostCollectionJsxMaps('{targetRows.shown.map((t) => <Row key={t.id} />)}')).toBe(0)
|
|
expect(countHostCollectionJsxMaps('new Map(hostOptions.map((host) => [host.id, host]))')).toBe(
|
|
0
|
|
)
|
|
expect(countHostCollectionJsxMaps('hosts.map((host) => ({ id: host.id }))')).toBe(0)
|
|
expect(countHostCollectionJsxMaps('// hosts.map((h) => <Row />)')).toBe(0)
|
|
})
|
|
})
|
|
|
|
describe('isScannedPath', () => {
|
|
it('scans renderer components outside the host-picker primitive', () => {
|
|
expect(isScannedPath('src/renderer/src/components/settings/A.tsx')).toBe(true)
|
|
expect(isScannedPath('src/renderer/src/components/host-picker/HostCombobox.tsx')).toBe(false)
|
|
expect(isScannedPath('src/renderer/src/components/settings/A.test.tsx')).toBe(false)
|
|
expect(isScannedPath('src/renderer/src/components/settings/a.ts')).toBe(false)
|
|
expect(isScannedPath('src/main/a.tsx')).toBe(false)
|
|
})
|
|
})
|