feat: appove and go

This commit is contained in:
thanhnv
2026-07-19 09:37:16 +07:00
parent 13fae3e6c3
commit 709b6cccd6
24 changed files with 1245 additions and 70 deletions
+35
View File
@@ -312,6 +312,41 @@ test('KeyResultsService.updateProgress non-existent KR throws NotFoundException'
}
});
test('KeyResultsService.updateProgress rolls back progress when status recalculation fails', async () => {
const prisma = new PrismaService();
await prisma.$connect();
const service = new KeyResultsService(prisma);
const testable = service as unknown as {
recalculateObjectiveStatus: (objectiveId: number) => Promise<void>;
};
const recalculateObjectiveStatus = testable.recalculateObjectiveStatus.bind(service);
let beforeProgress = 0;
try {
const before = await prisma.keyResult.findUniqueOrThrow({ where: { id: 1 } });
beforeProgress = before.progress;
testable.recalculateObjectiveStatus = async () => {
throw new Error('forced status recalculation failure');
};
await assert.rejects(
() => service.updateProgress(1, { progress: 99, comment: 'must roll back' }, employeeUser),
/forced status recalculation failure/,
);
const after = await prisma.keyResult.findUniqueOrThrow({ where: { id: 1 } });
assert.equal(after.progress, beforeProgress);
const leakedHistory = await prisma.progressUpdate.findMany({
where: { keyResultId: 1, progress: 99, comment: 'must roll back' },
});
assert.equal(leakedHistory.length, 0);
} finally {
testable.recalculateObjectiveStatus = recalculateObjectiveStatus;
await prisma.keyResult.update({ where: { id: 1 }, data: { progress: beforeProgress } });
await prisma.progressUpdate.deleteMany({ where: { keyResultId: 1, comment: 'must roll back' } });
await prisma.$disconnect();
}
});
// ─── Status recalculation (full NOT_STARTED → IN_PROGRESS → COMPLETED cycle) ─
test('KeyResultsService status recalculation: NOT_STARTED → IN_PROGRESS → COMPLETED → IN_PROGRESS', async () => {