Dependence milestone

This commit is contained in:
2026-05-30 08:32:08 +02:00
parent fb0e853122
commit 16a39ca5e7
12 changed files with 217 additions and 9 deletions
@@ -36,6 +36,7 @@ const makeMilestone = (overrides: Partial<MilestoneEntity> = {}): MilestoneEntit
endDate: '',
dueDate: '',
issueIds: [],
dependsOnIds: [],
...overrides,
});
@@ -501,6 +502,87 @@ describe('MilestoneDetail', () => {
});
});
describe('dependencies', () => {
beforeEach(() => {
milestonesStore.seed([
makeMilestone({ id: 1, name: 'Sprint 1', dependsOnIds: [] }),
makeMilestone({ id: 2, name: 'Sprint 2', dependsOnIds: [] }),
makeMilestone({ id: 3, name: 'Sprint 3', dependsOnIds: [] }),
]);
(component as any).milestone = makeMilestone({ id: 1, name: 'Sprint 1', dependsOnIds: [] });
});
it('hasDependencies returns false when dependsOnIds is empty', () => {
expect((component as any).hasDependencies).toBe(false);
});
it('hasDependencies returns true when dependsOnIds is non-empty', () => {
(component as any).milestone.dependsOnIds = [2];
expect((component as any).hasDependencies).toBe(true);
});
it('dependencyIds returns the dependsOnIds array', () => {
(component as any).milestone.dependsOnIds = [2, 3];
expect((component as any).dependencyIds).toEqual([2, 3]);
});
it('availableCandidates excludes the current milestone', () => {
const candidates: MilestoneEntity[] = (component as any).availableCandidates;
expect(candidates.some((m: MilestoneEntity) => m.id === 1)).toBe(false);
});
it('availableCandidates excludes already-added dependencies', () => {
(component as any).milestone.dependsOnIds = [2];
const candidates: MilestoneEntity[] = (component as any).availableCandidates;
expect(candidates.some((m: MilestoneEntity) => m.id === 2)).toBe(false);
expect(candidates.some((m: MilestoneEntity) => m.id === 3)).toBe(true);
});
it('resolveDependency returns the milestone with the given id', () => {
expect((component as any).resolveDependency(2)?.name).toBe('Sprint 2');
});
it('resolveDependency returns undefined for unknown id', () => {
expect((component as any).resolveDependency(999)).toBeUndefined();
});
it('openAddDependency shows the form and resets selection', () => {
(component as any).selectedCandidateMilestoneId = 2;
(component as any).openAddDependency();
expect((component as any).showAddDependency).toBe(true);
expect((component as any).selectedCandidateMilestoneId).toBeNull();
});
it('cancelAddDependency hides the form and resets selection', () => {
(component as any).showAddDependency = true;
(component as any).selectedCandidateMilestoneId = 2;
(component as any).cancelAddDependency();
expect((component as any).showAddDependency).toBe(false);
expect((component as any).selectedCandidateMilestoneId).toBeNull();
});
it('confirmAddDependency does nothing when no candidate is selected', async () => {
(component as any).selectedCandidateMilestoneId = null;
await (component as any).confirmAddDependency();
expect((component as any).milestone.dependsOnIds).toHaveLength(0);
});
it('confirmAddDependency adds the id and saves', async () => {
(component as any).selectedCandidateMilestoneId = 2;
await (component as any).confirmAddDependency();
expect((component as any).milestone.dependsOnIds).toContain(2);
expect((component as any).showAddDependency).toBe(false);
expect((component as any).selectedCandidateMilestoneId).toBeNull();
});
it('removeDependency removes the id and saves', async () => {
(component as any).milestone.dependsOnIds = [2, 3];
await (component as any).removeDependency(2);
expect((component as any).milestone.dependsOnIds).not.toContain(2);
expect((component as any).milestone.dependsOnIds).toContain(3);
});
});
describe('deleteMilestone', () => {
it('removes the milestone and navigates to /milestones', async () => {
const spy = vi.spyOn(router, 'navigate').mockResolvedValue(true);