mirror of
https://github.com/stablyai/orca.git
synced 2026-10-01 08:01:56 +00:00
test(composer): cover the forced source reset behaviourally, not by source text
The boundaries suite pinned the project switch by matching the literal `handleRepoChange(nextRepoId, ...)` call, which the setup-choice refactor renamed. The invariant it protected — returning from a folder target to a repo with the same id must force the repo-scoped reset past handleRepoChange's same-id early return — now runs against the real handleRepoChange, so a rename cannot break it and a dropped flag cannot pass it.
This commit is contained in:
@@ -5,6 +5,7 @@ import type { ExecutionHostId } from '../../../../shared/execution-host'
|
||||
import type { Project, ProjectHostSetup } from '../../../../shared/project-types'
|
||||
import type { Repo } from '../../../../shared/repo-types'
|
||||
import { useProjectTargetActions } from './project-target-actions'
|
||||
import { useTargetChangeActions } from './target-change-actions'
|
||||
|
||||
const PROJECT_ID = 'github:stablyai/orca'
|
||||
|
||||
@@ -114,3 +115,98 @@ describe('composer project switch with several ready setups (STA-6080)', () => {
|
||||
expect(spies.setRepoId).not.toHaveBeenCalled()
|
||||
})
|
||||
})
|
||||
|
||||
/**
|
||||
* The folder branch of the composer leaves `repoId` on the group's source repo, so switching back to
|
||||
* a project whose setup uses that same repo id hits `handleRepoChange`'s same-id early return and
|
||||
* would keep the folder's source state. `forceResetStartFrom: isProjectGroupTarget` is what forces
|
||||
* the reset through. Exercised against the real `handleRepoChange`, not its source text.
|
||||
*/
|
||||
function renderProjectSwitchFromFolderTarget(isProjectGroupTarget: boolean) {
|
||||
const spies = {
|
||||
setBaseBranch: vi.fn(),
|
||||
setLinkedIssue: vi.fn(),
|
||||
setRepoId: vi.fn(),
|
||||
setSparseEnabled: vi.fn(),
|
||||
setStartFromResetHint: vi.fn()
|
||||
}
|
||||
const noop = vi.fn()
|
||||
const shared = {
|
||||
linkedWorkItem: null,
|
||||
setBranchNameOverride: noop,
|
||||
setBranchNameOverridePreservesNameEdits: noop,
|
||||
setForkPushWarning: noop,
|
||||
setLinkedGitLabIssue: noop,
|
||||
setLinkedGitLabMR: noop,
|
||||
setLinkedPR: noop,
|
||||
setLinkedTaskSourceContext: noop,
|
||||
setLinkedWorkItem: noop,
|
||||
setProjectError: noop,
|
||||
setPushTarget: noop,
|
||||
setReuseEligibleBranch: noop,
|
||||
setReuseSelectedBranch: noop,
|
||||
setSelectedProjectHostSetupOverrideId: noop,
|
||||
setSelectedProjectIdOverride: noop,
|
||||
setSparseDirectories: noop,
|
||||
setSparseSelectedPresetId: noop,
|
||||
...spies
|
||||
}
|
||||
const { result } = renderHook(() => {
|
||||
const { handleRepoChange } = useTargetChangeActions({
|
||||
baseBranch: undefined,
|
||||
branchAutoNameRef: { current: null },
|
||||
decisions: { retargetGitHubPrStartPointSelection: (selection: unknown) => selection },
|
||||
folderSourceRepos: [],
|
||||
hostOptions: [],
|
||||
projectHostSetupOptions: [],
|
||||
// Why: the folder branch already parked the composer on this repo id, so the project switch
|
||||
// resolves to the same value and only the forced reset can clear the folder's state.
|
||||
repoId: 'orca-main',
|
||||
selectedRepoProjectId: PROJECT_ID,
|
||||
setCompareBaseRef: noop,
|
||||
smartGitHubPrStartPointSelectionRef: { current: null },
|
||||
...shared
|
||||
} as unknown as Parameters<typeof useTargetChangeActions>[0])
|
||||
return useProjectTargetActions({
|
||||
actionableHostIds: new Set<ExecutionHostId>(['local']),
|
||||
eligibleRepos: [makeRepo('orca-main', '/checkouts/main')],
|
||||
handleRepoChange,
|
||||
initialProjectGroupAppliedRef: { current: false },
|
||||
isProjectGroupTarget,
|
||||
projectGroups: [],
|
||||
projectHostSetups: [makeSetup('setup-main', 'local', 'orca-main', '/checkouts/main')],
|
||||
projects: [project],
|
||||
repos: [],
|
||||
selectedWorkspaceTarget: { status: 'unavailable', reason: 'project-has-no-ready-setup' },
|
||||
workspaceHostScope: 'all',
|
||||
setSelectedProjectGroupId: noop,
|
||||
...shared
|
||||
} as unknown as Parameters<typeof useProjectTargetActions>[0])
|
||||
})
|
||||
return { handleProjectChange: result.current.handleProjectChange, spies }
|
||||
}
|
||||
|
||||
describe('returning from a folder target to a repo with the same id', () => {
|
||||
it('forces the repo-scoped source reset', () => {
|
||||
const { handleProjectChange, spies } = renderProjectSwitchFromFolderTarget(true)
|
||||
|
||||
handleProjectChange(PROJECT_ID)
|
||||
|
||||
expect(spies.setRepoId).toHaveBeenCalledWith('orca-main')
|
||||
expect(spies.setSparseEnabled).toHaveBeenCalledWith(false)
|
||||
expect(spies.setLinkedIssue).toHaveBeenCalledWith('')
|
||||
expect(spies.setBaseBranch).toHaveBeenCalledWith(undefined)
|
||||
expect(spies.setStartFromResetHint).toHaveBeenCalledWith(null)
|
||||
})
|
||||
|
||||
it('leaves the source state alone when the composer was already on that repo', () => {
|
||||
const { handleProjectChange, spies } = renderProjectSwitchFromFolderTarget(false)
|
||||
|
||||
handleProjectChange(PROJECT_ID)
|
||||
|
||||
expect(spies.setRepoId).toHaveBeenCalledWith('orca-main')
|
||||
expect(spies.setSparseEnabled).not.toHaveBeenCalled()
|
||||
expect(spies.setLinkedIssue).not.toHaveBeenCalled()
|
||||
expect(spies.setBaseBranch).not.toHaveBeenCalled()
|
||||
})
|
||||
})
|
||||
|
||||
@@ -453,15 +453,14 @@ describe('useComposerState host-context boundaries', () => {
|
||||
expect(section).toContain("branchAutoNameRef.current = ''")
|
||||
})
|
||||
|
||||
it('forces repo-scoped source reset when returning from folder target to a repo with the same id', () => {
|
||||
// The caller half — that a project switch passes `forceResetStartFrom: isProjectGroupTarget`, and
|
||||
// that the reset actually runs — is covered behaviourally against the real `handleRepoChange` in
|
||||
// composer-state/project-target-actions.test.ts ("returning from a folder target to a repo with
|
||||
// the same id"), so it survives renaming the local that holds the resolved repo id.
|
||||
it('keeps the same-id early return escapable', () => {
|
||||
const handleRepoChange = COMPOSER_SOURCE.targetChange
|
||||
expect(handleRepoChange).toContain('forceResetStartFrom?: boolean')
|
||||
expect(handleRepoChange).toContain('value === repoId && !options.forceResetStartFrom')
|
||||
|
||||
const handleProjectChange = COMPOSER_SOURCE.projectTarget
|
||||
expect(handleProjectChange).toContain(
|
||||
'handleRepoChange(nextRepoId, { forceResetStartFrom: isProjectGroupTarget })'
|
||||
)
|
||||
})
|
||||
|
||||
it('keeps a Linear branch override when its workspace-scoped issue survives a repo change', () => {
|
||||
|
||||
Reference in New Issue
Block a user