feat: implement sprint 014 hermes renewal
This commit is contained in:
@@ -7,19 +7,9 @@ describe('SprintSyncService', () => {
|
||||
let service: SprintSyncService;
|
||||
|
||||
const mockPrisma = {
|
||||
project: {
|
||||
findUnique: jest.fn(),
|
||||
},
|
||||
sprint: {
|
||||
findFirst: jest.fn(),
|
||||
create: jest.fn(),
|
||||
update: jest.fn(),
|
||||
},
|
||||
task: {
|
||||
findFirst: jest.fn(),
|
||||
create: jest.fn(),
|
||||
update: jest.fn(),
|
||||
},
|
||||
project: { findUnique: jest.fn(), findMany: jest.fn() },
|
||||
sprint: { findFirst: jest.fn(), create: jest.fn(), update: jest.fn() },
|
||||
task: { findFirst: jest.fn(), create: jest.fn(), update: jest.fn() },
|
||||
};
|
||||
|
||||
const mockGitea = {
|
||||
@@ -39,10 +29,8 @@ describe('SprintSyncService', () => {
|
||||
service = module.get<SprintSyncService>(SprintSyncService);
|
||||
jest.clearAllMocks();
|
||||
|
||||
mockPrisma.project.findUnique.mockResolvedValue({
|
||||
id: 1,
|
||||
repoUrl: 'https://gitea.example.com/hanarang/project-alpha',
|
||||
});
|
||||
mockPrisma.project.findUnique.mockResolvedValue({ id: 1, repoUrl: 'https://gitea.example.com/hanarang/project-alpha' });
|
||||
mockPrisma.project.findMany.mockResolvedValue([{ id: 1, repoUrl: 'https://gitea.example.com/hanarang/project-alpha' }]);
|
||||
mockPrisma.sprint.findFirst.mockResolvedValue(null);
|
||||
mockPrisma.sprint.create.mockResolvedValue({ id: 101, status: 'pending' });
|
||||
mockPrisma.sprint.update.mockResolvedValue({ id: 101, status: 'pending' });
|
||||
@@ -51,54 +39,64 @@ describe('SprintSyncService', () => {
|
||||
mockPrisma.task.update.mockResolvedValue({});
|
||||
|
||||
mockGitea.getRepoTree.mockImplementation(async (_repoName: string, path: string) => {
|
||||
if (path === '.plans/sprints/') return ['.plans/sprints/SPRINT-005.md'];
|
||||
if (path === '.plans/sprints/') return ['.plans/sprints/SPRINT-005.md', '.plans/sprints/HOTFIX-001.md'];
|
||||
if (path === '.plans/qa/') return ['.plans/qa/SPRINT-005-review-darang.md'];
|
||||
if (path === '.qa/') return [];
|
||||
if (path === '.plans/hotfix/') return ['.plans/hotfix/HOTFIX-001.md'];
|
||||
return [];
|
||||
});
|
||||
});
|
||||
|
||||
it('syncProjectSprints: 담당 라인 기준 assignee를 저장한다', async () => {
|
||||
mockGitea.getRawFile.mockResolvedValue(`# SPRINT-005: Infra\n\n## 목표\n테스트\n\n## 태스크\n\n### TASK-019: 인프라 배포\n- **담당:** 이랑이\n- **상태:** pending\n- **설명:** Nginx 프록시 + PM2 + SSL\n\n### TASK-020: QA 자동화\n- **담당:** 다랑이\n- **상태:** pending\n- **설명:** smoke test\n`);
|
||||
it('담당 라인을 읽어 assignee를 저장한다', async () => {
|
||||
mockGitea.getRawFile.mockImplementation(async (_repoName: string, path: string) => {
|
||||
if (path.includes('SPRINT-005.md')) {
|
||||
return `# SPRINT-005: Infra\n\n## 목표\n테스트\n\n## 태스크\n\n### TASK-019: 인프라 배포\n- **담당:** 이랑이\n- **설명:** deploy\n\n### TASK-020: QA 자동화\n- **담당:** darang\n- **설명:** qa\n`;
|
||||
}
|
||||
if (path.includes('review')) return 'passed: true';
|
||||
return '# HOTFIX-001: sample';
|
||||
});
|
||||
|
||||
await service.syncProjectSprints(1);
|
||||
|
||||
expect(mockPrisma.task.create).toHaveBeenNthCalledWith(1, expect.objectContaining({
|
||||
data: expect.objectContaining({
|
||||
taskId: 'TASK-019',
|
||||
assignee: 'erang',
|
||||
}),
|
||||
data: expect.objectContaining({ taskId: 'TASK-019', assignee: 'erang', status: 'done' }),
|
||||
}));
|
||||
expect(mockPrisma.task.create).toHaveBeenNthCalledWith(2, expect.objectContaining({
|
||||
data: expect.objectContaining({
|
||||
taskId: 'TASK-020',
|
||||
assignee: 'darang',
|
||||
}),
|
||||
data: expect.objectContaining({ taskId: 'TASK-020', assignee: 'darang', status: 'done' }),
|
||||
}));
|
||||
});
|
||||
|
||||
it('syncProjectSprints: 기존 task도 assignee를 갱신한다', async () => {
|
||||
mockPrisma.task.findFirst.mockResolvedValue({ id: 501, assignee: 'narang', status: 'pending' });
|
||||
mockGitea.getRawFile.mockResolvedValue(`# SPRINT-005: Infra\n\n## 목표\n테스트\n\n## 태스크\n\n### TASK-019: 인프라 배포\n- **담당:** 하랑이\n- **상태:** pending\n- **설명:** sync\n`);
|
||||
it('기존 task도 assignee를 갱신한다', async () => {
|
||||
mockPrisma.task.findFirst.mockResolvedValue({ id: 500, assignee: 'narang', status: 'pending' });
|
||||
mockGitea.getRawFile.mockImplementation(async (_repoName: string, path: string) => {
|
||||
if (path.includes('SPRINT-005.md')) {
|
||||
return `# SPRINT-005: Infra\n\n## 목표\n테스트\n\n## 태스크\n\n### TASK-019: 인프라 배포\n- **담당:** 하랑이\n`;
|
||||
}
|
||||
if (path.includes('review')) return 'passed: false';
|
||||
return '# HOTFIX-001: sample';
|
||||
});
|
||||
|
||||
await service.syncProjectSprints(1);
|
||||
|
||||
expect(mockPrisma.task.update).toHaveBeenCalledWith(expect.objectContaining({
|
||||
where: { id: 501 },
|
||||
data: expect.objectContaining({
|
||||
assignee: 'harang',
|
||||
}),
|
||||
where: { id: 500 },
|
||||
data: expect.objectContaining({ assignee: 'harang' }),
|
||||
}));
|
||||
});
|
||||
|
||||
it('syncProjectSprints: 담당 라인이 없으면 narang으로 fallback한다', async () => {
|
||||
mockGitea.getRawFile.mockResolvedValue(`# SPRINT-005: Infra\n\n## 목표\n테스트\n\n## 태스크\n\n### TASK-019: 인프라 배포\n- **상태:** pending\n- **설명:** sync\n`);
|
||||
it('담당 라인이 없으면 narang fallback', async () => {
|
||||
mockGitea.getRawFile.mockImplementation(async (_repoName: string, path: string) => {
|
||||
if (path.includes('SPRINT-005.md')) {
|
||||
return `# SPRINT-005: Infra\n\n## 목표\n테스트\n\n## 태스크\n\n### TASK-019: 인프라 배포\n- 설명만 있음\n`;
|
||||
}
|
||||
if (path.includes('review')) return 'FAILED';
|
||||
return '# HOTFIX-001: sample';
|
||||
});
|
||||
|
||||
await service.syncProjectSprints(1);
|
||||
|
||||
expect(mockPrisma.task.create).toHaveBeenCalledWith(expect.objectContaining({
|
||||
data: expect.objectContaining({
|
||||
assignee: 'narang',
|
||||
}),
|
||||
data: expect.objectContaining({ assignee: 'narang', status: 'pending' }),
|
||||
}));
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user