mirror of
https://github.com/stablyai/orca.git
synced 2026-10-07 16:02:29 +00:00
Fix pinned workspace reveal expanding other hosts (#25836)
This commit is contained in:
@@ -123,6 +123,8 @@ const WorktreeList = React.memo(function WorktreeList({
|
||||
agentSendTargetWorktreeId
|
||||
})
|
||||
const effectiveCollapsedGroups = useEffectiveCollapsedGroups({
|
||||
hostScopedPinnedGroups:
|
||||
filterState.workspaceHostScope !== 'all' || filterState.visibleWorkspaceHostIds !== null,
|
||||
collapsedGroups,
|
||||
agentSendTargetWorktreeId,
|
||||
groupBy,
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
import { describe, expect, it } from 'vitest'
|
||||
import { makeRepo, makeWorktree } from './worktree-list-lineage-card-test-fixtures'
|
||||
import { buildRows } from './worktree-list/grouping/build-rows'
|
||||
import { addHostSectionRows } from './host-section-rows'
|
||||
import { scopePinnedSectionCollapse } from './host-pinned-sections'
|
||||
|
||||
for (const hostId of ['ssh:builder', 'runtime:builder'] as const) {
|
||||
describe(`pinned sections on ${hostId}`, () => {
|
||||
const localRepo = makeRepo()
|
||||
const remoteRepo = { ...localRepo, id: 'remote-repo', executionHostId: hostId }
|
||||
const repoMap = new Map([
|
||||
[localRepo.id, localRepo],
|
||||
[remoteRepo.id, remoteRepo]
|
||||
])
|
||||
const local = {
|
||||
...makeWorktree({
|
||||
id: 'local',
|
||||
instanceId: 'local',
|
||||
displayName: 'Local pin',
|
||||
branch: 'local',
|
||||
sortOrder: 0
|
||||
}),
|
||||
hostId: 'local' as const,
|
||||
isPinned: true
|
||||
}
|
||||
const remote = { ...local, id: 'remote', repoId: remoteRepo.id, hostId }
|
||||
const rows = buildRows('none', [local, remote], repoMap, null, new Set())
|
||||
const sectioned = addHostSectionRows({
|
||||
rows,
|
||||
hostOptions: [
|
||||
{ id: 'local', kind: 'local', label: 'Local', detail: '', health: 'local' },
|
||||
{
|
||||
id: hostId,
|
||||
kind: hostId.startsWith('ssh:') ? 'ssh' : 'runtime',
|
||||
label: 'Remote',
|
||||
detail: '',
|
||||
health: 'available'
|
||||
}
|
||||
],
|
||||
workspaceHostScope: 'all',
|
||||
visibleWorkspaceHostIds: ['local', hostId],
|
||||
defaultHostId: 'local'
|
||||
})
|
||||
|
||||
it('keeps remote pins visible while local pins are collapsed', () => {
|
||||
const result = scopePinnedSectionCollapse({
|
||||
rows: sectioned,
|
||||
collapsedGroups: new Set(['pinned']),
|
||||
defaultHostId: 'local'
|
||||
})
|
||||
expect(result.filter((row) => row.type === 'item').map((row) => row.worktree.id)).toEqual([
|
||||
'remote'
|
||||
])
|
||||
expect(result.filter((row) => row.type === 'header').map((row) => row.collapseKey)).toEqual([
|
||||
'pinned',
|
||||
`pinned:host:${hostId}`
|
||||
])
|
||||
})
|
||||
|
||||
it('keeps local pins visible while remote pins are collapsed', () => {
|
||||
const result = scopePinnedSectionCollapse({
|
||||
rows: sectioned,
|
||||
collapsedGroups: new Set([`pinned:host:${hostId}`]),
|
||||
defaultHostId: 'local'
|
||||
})
|
||||
expect(result.filter((row) => row.type === 'item').map((row) => row.worktree.id)).toEqual([
|
||||
'local'
|
||||
])
|
||||
})
|
||||
|
||||
it('retains remote collapse ownership when it is the only visible host', () => {
|
||||
const remoteRows = buildRows('none', [remote], repoMap, null, new Set())
|
||||
const result = scopePinnedSectionCollapse({
|
||||
rows: remoteRows,
|
||||
collapsedGroups: new Set([`pinned:host:${hostId}`]),
|
||||
defaultHostId: 'local'
|
||||
})
|
||||
expect(result.filter((row) => row.type === 'item')).toEqual([])
|
||||
expect(result.filter((row) => row.type === 'header').map((row) => row.collapseKey)).toEqual([
|
||||
`pinned:host:${hostId}`
|
||||
])
|
||||
})
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
import { getWorktreeExecutionHostId, type ExecutionHostId } from '../../../../shared/execution-host'
|
||||
import type { HostSectionRow } from './host-section-rows'
|
||||
import { PINNED_GROUP_KEY } from './worktree-list/grouping/group-keys'
|
||||
|
||||
export function getHostPinnedGroupKey(hostId: ExecutionHostId): string {
|
||||
return hostId === 'local' ? PINNED_GROUP_KEY : `${PINNED_GROUP_KEY}:host:${hostId}`
|
||||
}
|
||||
|
||||
export function scopePinnedSectionCollapse(args: {
|
||||
rows: readonly HostSectionRow[]
|
||||
collapsedGroups: ReadonlySet<string>
|
||||
defaultHostId: ExecutionHostId
|
||||
}): HostSectionRow[] {
|
||||
return args.rows.flatMap((row): HostSectionRow[] => {
|
||||
if (row.type === 'header' && row.key === PINNED_GROUP_KEY) {
|
||||
const hostId =
|
||||
row.hostId ??
|
||||
(row.hostWorktreeCounts?.size === 1
|
||||
? row.hostWorktreeCounts.keys().next().value
|
||||
: undefined)
|
||||
return [{ ...row, collapseKey: hostId ? getHostPinnedGroupKey(hostId) : row.key }]
|
||||
}
|
||||
if (row.type === 'item' && row.sectionKey === PINNED_GROUP_KEY) {
|
||||
const hostId = getWorktreeExecutionHostId(row.worktree, row.repo, args.defaultHostId)
|
||||
if (args.collapsedGroups.has(getHostPinnedGroupKey(hostId))) {
|
||||
return []
|
||||
}
|
||||
}
|
||||
return [row]
|
||||
})
|
||||
}
|
||||
@@ -16,6 +16,7 @@ export function getPinnedWorktreeDisplayPolicy(
|
||||
|
||||
export type GroupHeaderRow = {
|
||||
type: 'header'
|
||||
collapseKey?: string
|
||||
key: string
|
||||
label: string
|
||||
count: number
|
||||
|
||||
@@ -11,11 +11,14 @@ import { getGroupKeysForWorktree } from '../grouping/worktree-group-keys'
|
||||
import { getFolderWorkspaceRevealGroupKeys } from '../navigation/folder-reveal'
|
||||
import type { FolderWorkspace } from '../../../../../../shared/folder-workspace-types'
|
||||
import type { ExecutionHostId } from '../../../../../../shared/execution-host'
|
||||
import { getWorktreeExecutionHostId } from '../../../../../../shared/execution-host'
|
||||
import { getHostPinnedGroupKey } from '../../host-pinned-sections'
|
||||
import { isPinnedSectionWorktree } from '../../pinned-section-worktrees'
|
||||
import { getWorktreeLineageAncestors } from '../../worktree-lineage-projection'
|
||||
|
||||
// While the agent send picker targets a workspace, force open every section that hides it.
|
||||
export function useEffectiveCollapsedGroups(args: {
|
||||
hostScopedPinnedGroups?: boolean
|
||||
collapsedGroups: Set<string>
|
||||
agentSendTargetWorktreeId: string | null
|
||||
groupBy: WorktreeGroupBy
|
||||
@@ -34,6 +37,7 @@ export function useEffectiveCollapsedGroups(args: {
|
||||
}): Set<string> {
|
||||
const {
|
||||
collapsedGroups,
|
||||
hostScopedPinnedGroups = false,
|
||||
agentSendTargetWorktreeId,
|
||||
groupBy,
|
||||
pinnedDisplayPolicy,
|
||||
@@ -77,7 +81,17 @@ export function useEffectiveCollapsedGroups(args: {
|
||||
pinnedDisplayPolicy === 'single-location' &&
|
||||
isPinnedSectionWorktree(targetWorktree, visibleWorktrees, worktreeLineageById, worktreeMap)
|
||||
) {
|
||||
next.delete(PINNED_GROUP_KEY)
|
||||
next.delete(
|
||||
hostScopedPinnedGroups
|
||||
? getHostPinnedGroupKey(
|
||||
getWorktreeExecutionHostId(
|
||||
targetWorktree,
|
||||
repoMap.get(targetWorktree.repoId),
|
||||
defaultHostId
|
||||
)
|
||||
)
|
||||
: PINNED_GROUP_KEY
|
||||
)
|
||||
} else {
|
||||
for (const groupKey of getGroupKeysForWorktree(
|
||||
groupBy,
|
||||
@@ -104,6 +118,7 @@ export function useEffectiveCollapsedGroups(args: {
|
||||
}, [
|
||||
agentSendTargetWorktreeId,
|
||||
collapsedGroups,
|
||||
hostScopedPinnedGroups,
|
||||
groupBy,
|
||||
pinnedDisplayPolicy,
|
||||
visibleWorktrees,
|
||||
|
||||
@@ -16,6 +16,8 @@ import type { ProjectGroupingModel } from '../grouping/project-grouping'
|
||||
import type { PinnedWorktreeDisplayPolicy, Row, WorktreeGroupBy } from '../grouping/row-types'
|
||||
import { getLogicalRepoOrderRankById } from '../../project-header-drop'
|
||||
import { getEmptyProjectPlaceholderRepoIds } from '../../empty-project-placeholder-repos'
|
||||
import { PINNED_GROUP_KEY } from '../grouping/group-keys'
|
||||
import { scopePinnedSectionCollapse } from '../../host-pinned-sections'
|
||||
import { addHostSectionRows } from '../../host-section-rows'
|
||||
import { orderHostSectionOptions } from '../../host-section-order'
|
||||
import { buildSidebarHostOptions } from '../../sidebar-host-options'
|
||||
@@ -141,6 +143,18 @@ export function useSidebarSectionRows(args: SectionRowsArgs) {
|
||||
[hostOptions]
|
||||
)
|
||||
|
||||
const hostScopedPinnedGroups =
|
||||
args.workspaceHostScope !== 'all' || args.visibleWorkspaceHostIds !== null
|
||||
// Host sections apply pinned collapse after splitting the rows by owner.
|
||||
const rowCollapsedGroups = useMemo(() => {
|
||||
if (!hostScopedPinnedGroups || !effectiveCollapsedGroups.has(PINNED_GROUP_KEY)) {
|
||||
return effectiveCollapsedGroups
|
||||
}
|
||||
const next = new Set(effectiveCollapsedGroups)
|
||||
next.delete(PINNED_GROUP_KEY)
|
||||
return next
|
||||
}, [effectiveCollapsedGroups, hostScopedPinnedGroups])
|
||||
|
||||
const rows: Row[] = useMemo(
|
||||
() =>
|
||||
buildRows(
|
||||
@@ -148,7 +162,7 @@ export function useSidebarSectionRows(args: SectionRowsArgs) {
|
||||
worktrees,
|
||||
repoMap,
|
||||
args.prCache,
|
||||
effectiveCollapsedGroups,
|
||||
rowCollapsedGroups,
|
||||
repoOrder,
|
||||
args.workspaceStatuses,
|
||||
args.projectOrderBy,
|
||||
@@ -172,7 +186,7 @@ export function useSidebarSectionRows(args: SectionRowsArgs) {
|
||||
worktrees,
|
||||
repoMap,
|
||||
args.prCache,
|
||||
effectiveCollapsedGroups,
|
||||
rowCollapsedGroups,
|
||||
defaultHostId,
|
||||
repoOrder,
|
||||
args.workspaceStatuses,
|
||||
@@ -215,29 +229,35 @@ export function useSidebarSectionRows(args: SectionRowsArgs) {
|
||||
},
|
||||
[orderedHostOptions, setWorkspaceHostOrder, workspaceHostOrder]
|
||||
)
|
||||
const sectionRows = useMemo(
|
||||
() =>
|
||||
addHostSectionRows({
|
||||
rows,
|
||||
hostOptions: orderedHostOptions,
|
||||
workspaceHostScope: args.workspaceHostScope,
|
||||
visibleWorkspaceHostIds: args.visibleWorkspaceHostIds,
|
||||
defaultHostId,
|
||||
collapsedHostKeys: effectiveCollapsedGroups,
|
||||
forceCollapseHosts: hostDragActive,
|
||||
// Why: projects/workspaces are the primary sidebar object; host sections are only an explicit host-filter view.
|
||||
preferProjectGrouping: true
|
||||
}),
|
||||
[
|
||||
args.visibleWorkspaceHostIds,
|
||||
args.workspaceHostScope,
|
||||
const sectionRows = useMemo(() => {
|
||||
const sectioned = addHostSectionRows({
|
||||
rows,
|
||||
hostOptions: orderedHostOptions,
|
||||
workspaceHostScope: args.workspaceHostScope,
|
||||
visibleWorkspaceHostIds: args.visibleWorkspaceHostIds,
|
||||
defaultHostId,
|
||||
effectiveCollapsedGroups,
|
||||
hostDragActive,
|
||||
orderedHostOptions,
|
||||
rows
|
||||
]
|
||||
)
|
||||
collapsedHostKeys: effectiveCollapsedGroups,
|
||||
forceCollapseHosts: hostDragActive,
|
||||
// Why: projects/workspaces are the primary sidebar object; host sections are only an explicit host-filter view.
|
||||
preferProjectGrouping: true
|
||||
})
|
||||
return hostScopedPinnedGroups
|
||||
? scopePinnedSectionCollapse({
|
||||
rows: sectioned,
|
||||
collapsedGroups: effectiveCollapsedGroups,
|
||||
defaultHostId
|
||||
})
|
||||
: sectioned
|
||||
}, [
|
||||
args.visibleWorkspaceHostIds,
|
||||
args.workspaceHostScope,
|
||||
defaultHostId,
|
||||
effectiveCollapsedGroups,
|
||||
hostDragActive,
|
||||
hostScopedPinnedGroups,
|
||||
orderedHostOptions,
|
||||
rows
|
||||
])
|
||||
const renderedSidebarRowKeys = useMemo(
|
||||
() => collectRenderedSidebarRowKeys(sectionRows),
|
||||
[sectionRows]
|
||||
|
||||
+9
-1
@@ -10,6 +10,7 @@ import type { WorktreeLineage } from '../../../../../../shared/worktree/lineage-
|
||||
import type { ExecutionHostId } from '../../../../../../shared/execution-host'
|
||||
import { getWorktreeExecutionHostId } from '../../../../../../shared/execution-host'
|
||||
import type { RenderRow } from '../listing/render-row'
|
||||
import { getHostPinnedGroupKey } from '../../host-pinned-sections'
|
||||
import { getWorktreeLineageGroupKey } from '../grouping/group-keys'
|
||||
import type { ProjectGroupingModel } from '../grouping/project-grouping'
|
||||
import type { PinnedWorktreeDisplayPolicy, WorktreeGroupBy } from '../grouping/row-types'
|
||||
@@ -87,7 +88,8 @@ export function expandGroupsForWorktreeReveal(
|
||||
return
|
||||
}
|
||||
const targetRepo = args.repoMap.get(targetWorktree.repoId)
|
||||
const hostGroupKey = `host:${getWorktreeExecutionHostId(targetWorktree, targetRepo, args.defaultHostId)}`
|
||||
const targetHostId = getWorktreeExecutionHostId(targetWorktree, targetRepo, args.defaultHostId)
|
||||
const hostGroupKey = `host:${targetHostId}`
|
||||
if (args.collapsedGroups.has(hostGroupKey)) {
|
||||
args.toggleGroup(hostGroupKey)
|
||||
}
|
||||
@@ -118,6 +120,12 @@ export function expandGroupsForWorktreeReveal(
|
||||
)
|
||||
? getPinnedWorktreeRevealCollapsedGroupKeys({
|
||||
worktree: targetWorktree,
|
||||
groupKey: args.renderRows.some(
|
||||
(row) =>
|
||||
row.type === 'host-header' || (row.type === 'header' && row.collapseKey !== undefined)
|
||||
)
|
||||
? getHostPinnedGroupKey(targetHostId)
|
||||
: undefined,
|
||||
collapsedGroups: args.collapsedGroups,
|
||||
inPinnedSection: true
|
||||
})
|
||||
|
||||
@@ -93,10 +93,12 @@ export function getSidebarRowRevealAncestorKeys(args: {
|
||||
export function getPinnedWorktreeRevealCollapsedGroupKeys({
|
||||
worktree,
|
||||
collapsedGroups,
|
||||
groupKey = PINNED_GROUP_KEY,
|
||||
inPinnedSection = worktree.isPinned
|
||||
}: {
|
||||
worktree: Worktree
|
||||
collapsedGroups: ReadonlySet<string>
|
||||
groupKey?: string
|
||||
inPinnedSection?: boolean
|
||||
}): string[] {
|
||||
if (!inPinnedSection) {
|
||||
@@ -104,8 +106,8 @@ export function getPinnedWorktreeRevealCollapsedGroupKeys({
|
||||
}
|
||||
const keys: string[] = []
|
||||
// Why: the reveal effect already opens this host; re-returning it would toggle it back closed.
|
||||
if (collapsedGroups.has(PINNED_GROUP_KEY)) {
|
||||
keys.push(PINNED_GROUP_KEY)
|
||||
if (collapsedGroups.has(groupKey)) {
|
||||
keys.push(groupKey)
|
||||
}
|
||||
return keys
|
||||
}
|
||||
|
||||
@@ -171,7 +171,8 @@ export function renderWorktreeSectionHeaderRow(args: {
|
||||
projectGroupId: folderBackedProjectGroup.id
|
||||
})
|
||||
: null
|
||||
const isHeaderCollapsed = ctx.collapsedGroups.has(row.key)
|
||||
const collapseKey = row.collapseKey ?? row.key
|
||||
const isHeaderCollapsed = ctx.collapsedGroups.has(collapseKey)
|
||||
// Why: repo/project/status/pinned share compact section chrome; flat "All" stays a simple label.
|
||||
const showHeaderCollapseAffordance =
|
||||
row.count > 0 &&
|
||||
@@ -284,7 +285,7 @@ export function renderWorktreeSectionHeaderRow(args: {
|
||||
if (shouldIgnoreRepoHeaderToggle(event)) {
|
||||
return
|
||||
}
|
||||
ctx.toggleGroupWithScrollAnchor(row.key)
|
||||
ctx.toggleGroupWithScrollAnchor(collapseKey)
|
||||
}}
|
||||
onKeyDown={(e) => {
|
||||
if (shouldIgnoreRepoHeaderToggle(e)) {
|
||||
@@ -292,7 +293,7 @@ export function renderWorktreeSectionHeaderRow(args: {
|
||||
}
|
||||
if (e.key === 'Enter' || e.key === ' ') {
|
||||
e.preventDefault()
|
||||
ctx.toggleGroupWithScrollAnchor(row.key)
|
||||
ctx.toggleGroupWithScrollAnchor(collapseKey)
|
||||
}
|
||||
}}
|
||||
>
|
||||
@@ -350,7 +351,7 @@ export function renderWorktreeSectionHeaderRow(args: {
|
||||
onClick={(event) => {
|
||||
event.preventDefault()
|
||||
event.stopPropagation()
|
||||
ctx.toggleGroupWithScrollAnchor(row.key)
|
||||
ctx.toggleGroupWithScrollAnchor(collapseKey)
|
||||
}}
|
||||
>
|
||||
<ChevronDown
|
||||
|
||||
@@ -0,0 +1,133 @@
|
||||
import { expect, test } from './helpers/orca-app'
|
||||
import { waitForActiveWorktree, waitForSessionReady } from './helpers/store'
|
||||
|
||||
for (const hostId of ['ssh:reveal-builder', 'runtime:reveal-builder'] as const) {
|
||||
for (const collapsedHost of [false, true]) {
|
||||
test(`reveals ${hostId} pinned workspace without expanding local pins (host collapsed: ${collapsedHost})`, async ({
|
||||
orcaPage
|
||||
}, testInfo) => {
|
||||
await orcaPage.emulateMedia({ reducedMotion: 'reduce' })
|
||||
await waitForSessionReady(orcaPage)
|
||||
await waitForActiveWorktree(orcaPage)
|
||||
const ids = await orcaPage.evaluate(
|
||||
async ({ hostId, collapsedHost }) => {
|
||||
const store = window.__store!
|
||||
const state = store.getState()
|
||||
const sourceRepo = state.repos[0]
|
||||
const sourceWorktree = state.worktreesByRepo[sourceRepo.id][0]
|
||||
await state.updateWorktreeMeta(sourceWorktree.id, {
|
||||
isPinned: true,
|
||||
displayName: 'Local pinned workspace'
|
||||
})
|
||||
const local = {
|
||||
...sourceWorktree,
|
||||
hostId: 'local' as const,
|
||||
isPinned: true,
|
||||
displayName: 'Local pinned workspace'
|
||||
}
|
||||
const remoteRepo = {
|
||||
...sourceRepo,
|
||||
id: 'reveal-remote-repo',
|
||||
executionHostId: hostId,
|
||||
connectionId: hostId.startsWith('ssh:') ? 'reveal-builder' : null,
|
||||
displayName: 'Remote project'
|
||||
}
|
||||
const remote = {
|
||||
...sourceWorktree,
|
||||
id: 'reveal-remote-workspace',
|
||||
repoId: remoteRepo.id,
|
||||
hostId,
|
||||
isPinned: true,
|
||||
isMainWorktree: false,
|
||||
displayName: 'Remote pinned workspace'
|
||||
}
|
||||
state.setActiveView('terminal')
|
||||
state.setSidebarOpen(true)
|
||||
await window.api.ui.set({ groupBy: 'none' })
|
||||
state.setShowSleepingWorkspaces(true)
|
||||
state.setHideDefaultBranchWorkspace(false)
|
||||
state.setFilterRepoIds([])
|
||||
const collapsedGroups = [
|
||||
'pinned',
|
||||
`pinned:host:${hostId}`,
|
||||
...(collapsedHost ? [`host:${hostId}`] : [])
|
||||
]
|
||||
await window.api.ui.set({ collapsedGroups })
|
||||
store.setState({
|
||||
groupBy: 'none',
|
||||
repos: [sourceRepo, remoteRepo],
|
||||
worktreesByRepo: { [sourceRepo.id]: [local], [remoteRepo.id]: [remote] },
|
||||
sshTargetLabels: new Map([['reveal-builder', 'Remote builder']]),
|
||||
sshConnectionStates: new Map([
|
||||
[
|
||||
'reveal-builder',
|
||||
{
|
||||
targetId: 'reveal-builder',
|
||||
status: 'connected',
|
||||
error: null,
|
||||
reconnectAttempt: 0
|
||||
}
|
||||
]
|
||||
]),
|
||||
visibleWorkspaceHostIds: ['local', hostId],
|
||||
workspaceHostScope: 'all',
|
||||
activeRepoId: remoteRepo.id,
|
||||
activeWorktreeId: remote.id,
|
||||
activeWorkspaceKey: `worktree:${remote.id}`,
|
||||
activeWorkspaceExecutionHostId: hostId,
|
||||
pendingRevealWorktree: null,
|
||||
collapsedGroups: new Set(collapsedGroups)
|
||||
})
|
||||
return { local: local.id, remote: remote.id }
|
||||
},
|
||||
{ hostId, collapsedHost }
|
||||
)
|
||||
const pins = orcaPage.getByRole('button', { name: /^Pinned/ })
|
||||
const localRow = orcaPage.locator(
|
||||
`[data-worktree-sidebar] [role="option"][data-worktree-id=${JSON.stringify(ids.local)}]`
|
||||
)
|
||||
const remoteRow = orcaPage.locator(
|
||||
`[data-worktree-sidebar] [role="option"][data-worktree-id=${JSON.stringify(ids.remote)}]`
|
||||
)
|
||||
await expect(pins.first()).toHaveAttribute('aria-expanded', 'false')
|
||||
await expect(localRow).toHaveCount(0)
|
||||
await expect(remoteRow).toHaveCount(0)
|
||||
await orcaPage.screenshot({
|
||||
path: testInfo.outputPath('before-reveal.png'),
|
||||
clip: { x: 0, y: 170, width: 280, height: 500 }
|
||||
})
|
||||
await orcaPage.getByRole('button', { name: 'Reveal active workspace' }).click()
|
||||
await expect(remoteRow).toBeVisible()
|
||||
await expect(remoteRow).toHaveAttribute('data-scroll-reveal-highlight', 'true')
|
||||
await orcaPage.screenshot({
|
||||
path: testInfo.outputPath('after-reveal.png'),
|
||||
clip: { x: 0, y: 170, width: 280, height: 500 }
|
||||
})
|
||||
await expect(pins).toHaveCount(2)
|
||||
await expect(pins.first()).toHaveAttribute('aria-expanded', 'false')
|
||||
await expect(pins.last()).toHaveAttribute('aria-expanded', 'true')
|
||||
await expect(localRow).toHaveCount(0)
|
||||
|
||||
await pins.last().click()
|
||||
await expect(remoteRow).toHaveCount(0)
|
||||
await orcaPage.evaluate((localId) => {
|
||||
const store = window.__store!
|
||||
const local = Object.values(store.getState().worktreesByRepo)
|
||||
.flat()
|
||||
.find((worktree) => worktree.id === localId)!
|
||||
store.setState({
|
||||
activeRepoId: local.repoId,
|
||||
activeWorktreeId: localId,
|
||||
activeWorkspaceKey: `worktree:${localId}`,
|
||||
activeWorkspaceExecutionHostId: 'local',
|
||||
pendingRevealWorktree: null
|
||||
})
|
||||
}, ids.local)
|
||||
await orcaPage.getByRole('button', { name: 'Reveal active workspace' }).click()
|
||||
await expect(localRow).toBeVisible()
|
||||
await expect(pins.first()).toHaveAttribute('aria-expanded', 'true')
|
||||
await expect(pins.last()).toHaveAttribute('aria-expanded', 'false')
|
||||
await expect(remoteRow).toHaveCount(0)
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user