Milestone et Epic pour les tache commentaire
Signed-off-by: Gato <cedric@goutailler-olivier.fr>
This commit is contained in:
@@ -4,6 +4,7 @@ import { RouterTestingModule } from '@angular/router/testing';
|
||||
import { afterEach, vi } from 'vitest';
|
||||
import { IssueComments } from './issue-comments';
|
||||
import { IssueEntity, IssuesStore } from '../issues.store';
|
||||
import { MilestoneEntity, MilestonesStore } from '../../milestones/milestones.store';
|
||||
|
||||
const makeIssue = (overrides: Partial<IssueEntity> = {}): IssueEntity => ({
|
||||
id: 1,
|
||||
@@ -81,16 +82,60 @@ class FakeIssuesStore {
|
||||
}
|
||||
}
|
||||
|
||||
const makeMilestone = (overrides: Partial<MilestoneEntity> = {}): MilestoneEntity => ({
|
||||
id: 1,
|
||||
name: 'Sprint 1',
|
||||
description: '',
|
||||
startDate: '',
|
||||
endDate: '',
|
||||
dueDate: '',
|
||||
issueIds: [],
|
||||
dependsOnIds: [],
|
||||
...overrides,
|
||||
});
|
||||
|
||||
class FakeMilestonesStore {
|
||||
private _data = signal<MilestoneEntity[]>([]);
|
||||
|
||||
readonly milestones = this._data.asReadonly();
|
||||
readonly loading = signal(false);
|
||||
readonly loaded = signal(true);
|
||||
|
||||
getById(id: number): MilestoneEntity | undefined {
|
||||
return this._data().find((m) => m.id === id);
|
||||
}
|
||||
|
||||
load(): Promise<void> {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
upsert(milestone: MilestoneEntity): Promise<MilestoneEntity> {
|
||||
this._data.update((list) => {
|
||||
const idx = list.findIndex((m) => m.id === milestone.id);
|
||||
if (idx === -1) return [...list, milestone];
|
||||
const copy = [...list];
|
||||
copy[idx] = milestone;
|
||||
return copy;
|
||||
});
|
||||
return Promise.resolve(milestone);
|
||||
}
|
||||
}
|
||||
|
||||
describe('IssueComments', () => {
|
||||
let component: IssueComments;
|
||||
let fixture: ComponentFixture<IssueComments>;
|
||||
let store: FakeIssuesStore;
|
||||
let milestonesStore: FakeMilestonesStore;
|
||||
|
||||
beforeEach(async () => {
|
||||
store = new FakeIssuesStore();
|
||||
milestonesStore = new FakeMilestonesStore();
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [IssueComments, RouterTestingModule],
|
||||
providers: [{ provide: IssuesStore, useValue: store }],
|
||||
providers: [
|
||||
{ provide: IssuesStore, useValue: store },
|
||||
{ provide: MilestonesStore, useValue: milestonesStore },
|
||||
],
|
||||
}).compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(IssueComments);
|
||||
@@ -394,6 +439,46 @@ describe('IssueComments', () => {
|
||||
|
||||
expect(store.issues().filter((i) => i.type === 'Task').length).toBe(0);
|
||||
});
|
||||
|
||||
it('inherits the epic from the parent issue', async () => {
|
||||
await store.upsert(makeIssue({ id: 1, epic: 'Mon Epic', comments: store.getById(1)!.comments }));
|
||||
const commentId = store.getById(1)!.comments[0].id;
|
||||
(component as any).newTaskName = 'Tâche avec epic';
|
||||
await (component as any).createTaskForComment(commentId);
|
||||
|
||||
const task = store.issues().find((i) => i.type === 'Task');
|
||||
expect(task?.epic).toBe('Mon Epic');
|
||||
});
|
||||
|
||||
it('does not set epic when parent issue has none', async () => {
|
||||
const commentId = store.getById(1)!.comments[0].id;
|
||||
(component as any).newTaskName = 'Tâche sans epic';
|
||||
await (component as any).createTaskForComment(commentId);
|
||||
|
||||
const task = store.issues().find((i) => i.type === 'Task');
|
||||
expect(task?.epic).toBe('');
|
||||
});
|
||||
|
||||
it('adds the new task to the same milestone as the parent issue', async () => {
|
||||
await milestonesStore.upsert(makeMilestone({ id: 10, name: 'Release 1', issueIds: [1] }));
|
||||
const commentId = store.getById(1)!.comments[0].id;
|
||||
(component as any).newTaskName = 'Tâche dans milestone';
|
||||
await (component as any).createTaskForComment(commentId);
|
||||
|
||||
const task = store.issues().find((i) => i.type === 'Task')!;
|
||||
expect(milestonesStore.getById(10)!.issueIds).toContain(task.id);
|
||||
});
|
||||
|
||||
it('does not modify any milestone when parent issue is not in one', async () => {
|
||||
await milestonesStore.upsert(makeMilestone({ id: 10, name: 'Release 1', issueIds: [99] }));
|
||||
const commentId = store.getById(1)!.comments[0].id;
|
||||
(component as any).newTaskName = 'Tâche hors milestone';
|
||||
await (component as any).createTaskForComment(commentId);
|
||||
|
||||
expect(milestonesStore.getById(10)!.issueIds).not.toContain(
|
||||
store.issues().find((i) => i.type === 'Task')!.id,
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('linkIssueToComment', () => {
|
||||
|
||||
@@ -6,6 +6,7 @@ import { marked } from 'marked';
|
||||
import { handleImagePaste, insertAtSelection } from '../paste-image.util';
|
||||
import { IssueComment, IssueEntity, IssuesStore } from '../issues.store';
|
||||
import { StatusEntity, StatusesStore } from '../../settings/statuses/statuses.store';
|
||||
import { MilestonesStore } from '../../milestones/milestones.store';
|
||||
|
||||
@Component({
|
||||
selector: 'app-issue-comments',
|
||||
@@ -15,6 +16,7 @@ import { StatusEntity, StatusesStore } from '../../settings/statuses/statuses.st
|
||||
})
|
||||
export class IssueComments {
|
||||
private readonly issuesStore = inject(IssuesStore);
|
||||
private readonly milestonesStore = inject(MilestonesStore);
|
||||
private readonly sanitizer = inject(DomSanitizer);
|
||||
private readonly statusesStore = inject(StatusesStore);
|
||||
|
||||
@@ -169,7 +171,7 @@ export class IssueComments {
|
||||
type: 'Task',
|
||||
name,
|
||||
assignee: '',
|
||||
epic: '',
|
||||
epic: issue.epic,
|
||||
startDate: '',
|
||||
startDateMode: 'forced',
|
||||
endDate: '',
|
||||
@@ -189,6 +191,12 @@ export class IssueComments {
|
||||
return { ...c, linkedIssueIds: [...c.linkedIssueIds, created.id] };
|
||||
});
|
||||
await this.issuesStore.upsert({ ...issue, comments: updatedComments });
|
||||
|
||||
const milestone = this.milestonesStore.milestones().find((m) => m.issueIds.includes(issue.id));
|
||||
if (milestone) {
|
||||
await this.milestonesStore.upsert({ ...milestone, issueIds: [...milestone.issueIds, created.id] });
|
||||
}
|
||||
|
||||
this.creatingTaskForCommentId = null;
|
||||
this.newTaskName = '';
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user