mirror of
https://github.com/stablyai/orca.git
synced 2026-10-18 08:03:22 +00:00
test(sidebar): harden #8865 project-group sleep-filter coverage
Add adversarial cases for explicit project filters, multi-member groups, ungrouped neighbors, and buildRows membership/count preservation. Co-authored-by: bbingz <zzb@gxsmjx.com>
This commit is contained in:
@@ -131,4 +131,72 @@ describe('getEmptyProjectPlaceholderRepoIds', () => {
|
||||
}).size
|
||||
).toBe(0)
|
||||
})
|
||||
|
||||
it('still respects explicit project filters for sleep-filtered grouped members', () => {
|
||||
const selected: Repo = { ...repo, id: 'repo-selected', projectGroupId: 'group-1' }
|
||||
const filteredOut: Repo = { ...repo, id: 'repo-hidden', projectGroupId: 'group-1' }
|
||||
const selectedWt: Worktree = { ...worktree, id: 'wt-selected', repoId: selected.id }
|
||||
const hiddenWt: Worktree = { ...worktree, id: 'wt-hidden', repoId: filteredOut.id }
|
||||
|
||||
expect(
|
||||
Array.from(
|
||||
getEmptyProjectPlaceholderRepoIds({
|
||||
groupBy: 'repo',
|
||||
repos: [selected, filteredOut],
|
||||
worktreesByRepo: {
|
||||
[selected.id]: [selectedWt],
|
||||
[filteredOut.id]: [hiddenWt]
|
||||
},
|
||||
// Why: simulate Hide sleeping removing every card while the project
|
||||
// filter still intentionally excludes `filteredOut`.
|
||||
visibleWorktrees: [],
|
||||
filterRepoIds: [selected.id]
|
||||
})
|
||||
)
|
||||
).toEqual([selected.id])
|
||||
})
|
||||
|
||||
it('placeholders only the fully-filtered members of a multi-project group', () => {
|
||||
const sleeping: Repo = { ...repo, id: 'repo-sleeping', projectGroupId: 'group-1' }
|
||||
const awake: Repo = { ...repo, id: 'repo-awake', projectGroupId: 'group-1' }
|
||||
const sleepingWt: Worktree = { ...worktree, id: 'wt-sleeping', repoId: sleeping.id }
|
||||
const awakeWt: Worktree = { ...worktree, id: 'wt-awake', repoId: awake.id }
|
||||
|
||||
expect(
|
||||
Array.from(
|
||||
getEmptyProjectPlaceholderRepoIds({
|
||||
groupBy: 'repo',
|
||||
repos: [sleeping, awake],
|
||||
worktreesByRepo: {
|
||||
[sleeping.id]: [sleepingWt],
|
||||
[awake.id]: [awakeWt]
|
||||
},
|
||||
visibleWorktrees: [awakeWt],
|
||||
filterRepoIds: []
|
||||
})
|
||||
)
|
||||
).toEqual([sleeping.id])
|
||||
})
|
||||
|
||||
it('does not placeholder ungrouped neighbors of a filtered grouped member', () => {
|
||||
const grouped: Repo = { ...repo, id: 'repo-grouped', projectGroupId: 'group-1' }
|
||||
const ungrouped: Repo = { ...repo, id: 'repo-ungrouped' }
|
||||
const groupedWt: Worktree = { ...worktree, id: 'wt-grouped', repoId: grouped.id }
|
||||
const ungroupedWt: Worktree = { ...worktree, id: 'wt-ungrouped', repoId: ungrouped.id }
|
||||
|
||||
expect(
|
||||
Array.from(
|
||||
getEmptyProjectPlaceholderRepoIds({
|
||||
groupBy: 'repo',
|
||||
repos: [grouped, ungrouped],
|
||||
worktreesByRepo: {
|
||||
[grouped.id]: [groupedWt],
|
||||
[ungrouped.id]: [ungroupedWt]
|
||||
},
|
||||
visibleWorktrees: [],
|
||||
filterRepoIds: []
|
||||
})
|
||||
)
|
||||
).toEqual([grouped.id])
|
||||
})
|
||||
})
|
||||
|
||||
@@ -1933,6 +1933,73 @@ describe('project groups', () => {
|
||||
expect(rows[0]).toMatchObject({ label: 'Platform' })
|
||||
})
|
||||
|
||||
it('keeps sleep-filtered Project Group members as empty project headers', () => {
|
||||
// Why: #8865 — Hide sleeping removes workspace cards; membership placeholders
|
||||
// must still project the grouped project header so the group count stays honest.
|
||||
const group: ProjectGroup = {
|
||||
id: 'group-1',
|
||||
name: 'Platform',
|
||||
parentPath: '/platform',
|
||||
parentGroupId: null,
|
||||
createdFrom: 'folder-scan',
|
||||
tabOrder: 0,
|
||||
isCollapsed: false,
|
||||
color: null,
|
||||
createdAt: 1,
|
||||
updatedAt: 1
|
||||
}
|
||||
const sleepingRepo: Repo = {
|
||||
...repo,
|
||||
id: 'repo-sleeping',
|
||||
displayName: 'sleeping-project',
|
||||
projectGroupId: group.id
|
||||
}
|
||||
const awakeRepo: Repo = {
|
||||
...repo,
|
||||
id: 'repo-awake',
|
||||
displayName: 'awake-project',
|
||||
projectGroupId: group.id
|
||||
}
|
||||
const awakeWorktree: Worktree = {
|
||||
...worktree,
|
||||
id: 'wt-awake',
|
||||
repoId: awakeRepo.id,
|
||||
path: '/tmp/awake'
|
||||
}
|
||||
|
||||
const rows = buildRows(
|
||||
'repo',
|
||||
[awakeWorktree],
|
||||
new Map([
|
||||
[sleepingRepo.id, sleepingRepo],
|
||||
[awakeRepo.id, awakeRepo]
|
||||
]),
|
||||
null,
|
||||
new Set(),
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
{},
|
||||
new Map([[awakeWorktree.id, awakeWorktree]]),
|
||||
false,
|
||||
undefined,
|
||||
[group],
|
||||
new Set([sleepingRepo.id])
|
||||
)
|
||||
|
||||
expect(rows[0]).toMatchObject({
|
||||
type: 'header',
|
||||
key: 'project-group:group-1',
|
||||
count: 2
|
||||
})
|
||||
// Why: empty/placeholder projects sort after projects with visible activity.
|
||||
expect(rows.filter((row) => row.type === 'header').map((row) => row.key)).toEqual([
|
||||
'project-group:group-1',
|
||||
`repo:${awakeRepo.id}`,
|
||||
`repo:${sleepingRepo.id}`
|
||||
])
|
||||
})
|
||||
|
||||
it('renders ungrouped repos as top-level repo rows when Project Groups exist', () => {
|
||||
const group: ProjectGroup = {
|
||||
id: 'group-1',
|
||||
|
||||
Reference in New Issue
Block a user