test(JiraSync): further refine test coverage for synchronization and change detection scenarios
This commit is contained in:
309
src/services/task-management/__tests__/daily.test.ts
Normal file
309
src/services/task-management/__tests__/daily.test.ts
Normal file
@@ -0,0 +1,309 @@
|
||||
/**
|
||||
* Tests unitaires pour DailyService
|
||||
*/
|
||||
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
import { describe, it, expect, beforeEach, vi } from 'vitest';
|
||||
import { DailyService } from '../daily';
|
||||
import { prisma } from '@/services/core/database';
|
||||
import {
|
||||
getPreviousWorkday,
|
||||
normalizeDate,
|
||||
getToday,
|
||||
getYesterday,
|
||||
} from '@/lib/date-utils';
|
||||
|
||||
// Mock de prisma
|
||||
vi.mock('@/services/core/database', () => ({
|
||||
prisma: {
|
||||
dailyCheckbox: {
|
||||
findMany: vi.fn(),
|
||||
findUnique: vi.fn(),
|
||||
create: vi.fn(),
|
||||
update: vi.fn(),
|
||||
delete: vi.fn(),
|
||||
aggregate: vi.fn(),
|
||||
},
|
||||
},
|
||||
}));
|
||||
|
||||
// Mock de date-utils
|
||||
vi.mock('@/lib/date-utils', () => ({
|
||||
getPreviousWorkday: vi.fn(),
|
||||
normalizeDate: vi.fn(),
|
||||
formatDateForAPI: vi.fn(),
|
||||
getToday: vi.fn(),
|
||||
getYesterday: vi.fn(),
|
||||
}));
|
||||
|
||||
describe('DailyService', () => {
|
||||
let service: DailyService;
|
||||
const mockUserId = 'user-123';
|
||||
const mockDate = new Date('2024-01-15');
|
||||
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
service = new DailyService();
|
||||
vi.mocked(normalizeDate).mockImplementation((date) => date);
|
||||
vi.mocked(getPreviousWorkday).mockReturnValue(new Date('2024-01-14'));
|
||||
vi.mocked(getToday).mockReturnValue(mockDate);
|
||||
vi.mocked(getYesterday).mockReturnValue(new Date('2024-01-14'));
|
||||
});
|
||||
|
||||
describe('getDailyView', () => {
|
||||
it('devrait récupérer la vue daily pour une date', async () => {
|
||||
const yesterdayCheckboxes: any[] = [];
|
||||
const todayCheckboxes: any[] = [];
|
||||
|
||||
vi.mocked(prisma.dailyCheckbox.findMany)
|
||||
.mockResolvedValueOnce(yesterdayCheckboxes)
|
||||
.mockResolvedValueOnce(todayCheckboxes);
|
||||
|
||||
const view = await service.getDailyView(mockDate, mockUserId);
|
||||
|
||||
expect(view.date).toEqual(mockDate);
|
||||
expect(view.yesterday).toEqual(yesterdayCheckboxes);
|
||||
expect(view.today).toEqual(todayCheckboxes);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getCheckboxesByDate', () => {
|
||||
it('devrait récupérer les checkboxes pour une date', async () => {
|
||||
const mockCheckboxes = [
|
||||
{
|
||||
id: 'checkbox-1',
|
||||
date: mockDate,
|
||||
text: 'Checkbox 1',
|
||||
isChecked: false,
|
||||
type: 'task',
|
||||
order: 0,
|
||||
taskId: null,
|
||||
userId: mockUserId,
|
||||
task: null,
|
||||
user: { id: mockUserId },
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
},
|
||||
];
|
||||
|
||||
vi.mocked(prisma.dailyCheckbox.findMany).mockResolvedValue(
|
||||
mockCheckboxes as any
|
||||
);
|
||||
|
||||
const checkboxes = await service.getCheckboxesByDate(
|
||||
mockDate,
|
||||
mockUserId
|
||||
);
|
||||
|
||||
expect(checkboxes).toBeDefined();
|
||||
expect(prisma.dailyCheckbox.findMany).toHaveBeenCalledWith({
|
||||
where: {
|
||||
date: mockDate,
|
||||
userId: mockUserId,
|
||||
},
|
||||
include: {
|
||||
task: {
|
||||
include: {
|
||||
taskTags: {
|
||||
include: {
|
||||
tag: true,
|
||||
},
|
||||
},
|
||||
primaryTag: true,
|
||||
},
|
||||
},
|
||||
user: true,
|
||||
},
|
||||
orderBy: { order: 'asc' },
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('addCheckbox', () => {
|
||||
it('devrait ajouter une checkbox', async () => {
|
||||
const mockCheckbox = {
|
||||
id: 'checkbox-1',
|
||||
date: mockDate,
|
||||
text: 'New checkbox',
|
||||
isChecked: false,
|
||||
type: 'task',
|
||||
order: 0,
|
||||
taskId: null,
|
||||
userId: mockUserId,
|
||||
task: null,
|
||||
user: { id: mockUserId },
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
};
|
||||
|
||||
vi.mocked(prisma.dailyCheckbox.aggregate).mockResolvedValue({
|
||||
_max: { order: null },
|
||||
} as any);
|
||||
vi.mocked(prisma.dailyCheckbox.create).mockResolvedValue(
|
||||
mockCheckbox as any
|
||||
);
|
||||
|
||||
const checkbox = await service.addCheckbox({
|
||||
date: mockDate,
|
||||
text: 'New checkbox',
|
||||
userId: mockUserId,
|
||||
});
|
||||
|
||||
expect(checkbox).toBeDefined();
|
||||
expect(prisma.dailyCheckbox.create).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("devrait utiliser l'ordre spécifié", async () => {
|
||||
const mockCheckbox = {
|
||||
id: 'checkbox-1',
|
||||
date: mockDate,
|
||||
text: 'New checkbox',
|
||||
isChecked: false,
|
||||
type: 'task',
|
||||
order: 5,
|
||||
taskId: null,
|
||||
userId: mockUserId,
|
||||
task: null,
|
||||
user: { id: mockUserId },
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
};
|
||||
|
||||
vi.mocked(prisma.dailyCheckbox.create).mockResolvedValue(
|
||||
mockCheckbox as any
|
||||
);
|
||||
|
||||
await service.addCheckbox({
|
||||
date: mockDate,
|
||||
text: 'New checkbox',
|
||||
userId: mockUserId,
|
||||
order: 5,
|
||||
});
|
||||
|
||||
expect(prisma.dailyCheckbox.create).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
data: expect.objectContaining({
|
||||
order: 5,
|
||||
}),
|
||||
})
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('updateCheckbox', () => {
|
||||
it('devrait mettre à jour une checkbox', async () => {
|
||||
const mockCheckbox = {
|
||||
id: 'checkbox-1',
|
||||
date: mockDate,
|
||||
text: 'Updated checkbox',
|
||||
isChecked: true,
|
||||
type: 'task',
|
||||
order: 0,
|
||||
taskId: null,
|
||||
userId: mockUserId,
|
||||
task: null,
|
||||
user: { id: mockUserId },
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
};
|
||||
|
||||
vi.mocked(prisma.dailyCheckbox.update).mockResolvedValue(
|
||||
mockCheckbox as any
|
||||
);
|
||||
|
||||
const checkbox = await service.updateCheckbox('checkbox-1', {
|
||||
text: 'Updated checkbox',
|
||||
isChecked: true,
|
||||
});
|
||||
|
||||
expect(checkbox).toBeDefined();
|
||||
expect(prisma.dailyCheckbox.update).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('toggleCheckbox', () => {
|
||||
it("devrait toggle l'état d'une checkbox", async () => {
|
||||
const existingCheckbox = {
|
||||
id: 'checkbox-1',
|
||||
isChecked: false,
|
||||
};
|
||||
|
||||
const updatedCheckbox = {
|
||||
id: 'checkbox-1',
|
||||
date: mockDate,
|
||||
text: 'Checkbox',
|
||||
isChecked: true,
|
||||
type: 'task',
|
||||
order: 0,
|
||||
taskId: null,
|
||||
userId: mockUserId,
|
||||
task: null,
|
||||
user: { id: mockUserId },
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
};
|
||||
|
||||
vi.mocked(prisma.dailyCheckbox.findUnique).mockResolvedValue(
|
||||
existingCheckbox as any
|
||||
);
|
||||
vi.mocked(prisma.dailyCheckbox.update).mockResolvedValue(
|
||||
updatedCheckbox as any
|
||||
);
|
||||
|
||||
const checkbox = await service.toggleCheckbox('checkbox-1');
|
||||
|
||||
expect(checkbox.isChecked).toBe(true);
|
||||
expect(prisma.dailyCheckbox.update).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
data: expect.objectContaining({
|
||||
isChecked: true,
|
||||
}),
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
it("devrait lancer une erreur si la checkbox n'existe pas", async () => {
|
||||
vi.mocked(prisma.dailyCheckbox.findUnique).mockResolvedValue(null);
|
||||
|
||||
await expect(service.toggleCheckbox('non-existent')).rejects.toThrow(
|
||||
'non trouvée'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('deleteCheckbox', () => {
|
||||
it('devrait supprimer une checkbox', async () => {
|
||||
const existingCheckbox = {
|
||||
id: 'checkbox-1',
|
||||
date: mockDate,
|
||||
text: 'Checkbox',
|
||||
isChecked: false,
|
||||
type: 'task',
|
||||
order: 0,
|
||||
taskId: null,
|
||||
userId: mockUserId,
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
};
|
||||
|
||||
vi.mocked(prisma.dailyCheckbox.findUnique).mockResolvedValue(
|
||||
existingCheckbox as any
|
||||
);
|
||||
vi.mocked(prisma.dailyCheckbox.delete).mockResolvedValue({} as any);
|
||||
|
||||
await service.deleteCheckbox('checkbox-1');
|
||||
|
||||
expect(prisma.dailyCheckbox.delete).toHaveBeenCalledWith({
|
||||
where: { id: 'checkbox-1' },
|
||||
});
|
||||
});
|
||||
|
||||
it("devrait lancer une erreur si la checkbox n'existe pas", async () => {
|
||||
vi.mocked(prisma.dailyCheckbox.findUnique).mockResolvedValue(null);
|
||||
|
||||
await expect(service.deleteCheckbox('non-existent')).rejects.toThrow(
|
||||
'non trouvée'
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
286
src/services/task-management/__tests__/tags.test.ts
Normal file
286
src/services/task-management/__tests__/tags.test.ts
Normal file
@@ -0,0 +1,286 @@
|
||||
/**
|
||||
* Tests unitaires pour tagsService
|
||||
*/
|
||||
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
import { describe, it, expect, beforeEach, vi } from 'vitest';
|
||||
import { tagsService } from '../tags';
|
||||
import { prisma } from '@/services/core/database';
|
||||
|
||||
// Mock de prisma
|
||||
vi.mock('@/services/core/database', () => ({
|
||||
prisma: {
|
||||
tag: {
|
||||
findMany: vi.fn(),
|
||||
findFirst: vi.fn(),
|
||||
create: vi.fn(),
|
||||
update: vi.fn(),
|
||||
delete: vi.fn(),
|
||||
},
|
||||
taskTag: {
|
||||
deleteMany: vi.fn(),
|
||||
},
|
||||
},
|
||||
}));
|
||||
|
||||
describe('tagsService', () => {
|
||||
const mockUserId = 'user-123';
|
||||
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
|
||||
describe('getTags', () => {
|
||||
it('devrait récupérer tous les tags avec leur usage', async () => {
|
||||
const mockTags = [
|
||||
{
|
||||
id: 'tag-1',
|
||||
name: 'Tag 1',
|
||||
color: '#ff0000',
|
||||
isPinned: false,
|
||||
_count: { taskTags: 5 },
|
||||
},
|
||||
{
|
||||
id: 'tag-2',
|
||||
name: 'Tag 2',
|
||||
color: '#00ff00',
|
||||
isPinned: true,
|
||||
_count: { taskTags: 2 },
|
||||
},
|
||||
];
|
||||
|
||||
vi.mocked(prisma.tag.findMany).mockResolvedValue(mockTags as any);
|
||||
|
||||
const tags = await tagsService.getTags(mockUserId);
|
||||
|
||||
expect(tags).toHaveLength(2);
|
||||
expect(tags[0]).toEqual({
|
||||
id: 'tag-1',
|
||||
name: 'Tag 1',
|
||||
color: '#ff0000',
|
||||
isPinned: false,
|
||||
usage: 5,
|
||||
});
|
||||
expect(prisma.tag.findMany).toHaveBeenCalledWith({
|
||||
where: { ownerId: mockUserId },
|
||||
include: {
|
||||
_count: {
|
||||
select: {
|
||||
taskTags: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
orderBy: { name: 'asc' },
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('getTagById', () => {
|
||||
it('devrait récupérer un tag par son ID', async () => {
|
||||
const mockTag = {
|
||||
id: 'tag-1',
|
||||
name: 'Tag 1',
|
||||
color: '#ff0000',
|
||||
isPinned: false,
|
||||
};
|
||||
|
||||
vi.mocked(prisma.tag.findFirst).mockResolvedValue(mockTag as any);
|
||||
|
||||
const tag = await tagsService.getTagById('tag-1', mockUserId);
|
||||
|
||||
expect(tag).toEqual(mockTag);
|
||||
expect(prisma.tag.findFirst).toHaveBeenCalledWith({
|
||||
where: {
|
||||
id: 'tag-1',
|
||||
ownerId: mockUserId,
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it("devrait retourner null si le tag n'existe pas", async () => {
|
||||
vi.mocked(prisma.tag.findFirst).mockResolvedValue(null);
|
||||
|
||||
const tag = await tagsService.getTagById('non-existent', mockUserId);
|
||||
|
||||
expect(tag).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
describe('getTagByName', () => {
|
||||
it('devrait récupérer un tag par son nom', async () => {
|
||||
const mockTag = {
|
||||
id: 'tag-1',
|
||||
name: 'Tag 1',
|
||||
color: '#ff0000',
|
||||
isPinned: false,
|
||||
};
|
||||
|
||||
vi.mocked(prisma.tag.findFirst).mockResolvedValue(mockTag as any);
|
||||
|
||||
const tag = await tagsService.getTagByName('Tag 1', mockUserId);
|
||||
|
||||
expect(tag).toEqual(mockTag);
|
||||
expect(prisma.tag.findFirst).toHaveBeenCalledWith({
|
||||
where: {
|
||||
name: {
|
||||
equals: 'Tag 1',
|
||||
},
|
||||
ownerId: mockUserId,
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('createTag', () => {
|
||||
it('devrait créer un nouveau tag', async () => {
|
||||
const mockTag = {
|
||||
id: 'tag-1',
|
||||
name: 'New Tag',
|
||||
color: '#ff0000',
|
||||
isPinned: false,
|
||||
};
|
||||
|
||||
vi.mocked(prisma.tag.findFirst).mockResolvedValue(null); // Pas de tag existant
|
||||
vi.mocked(prisma.tag.create).mockResolvedValue(mockTag as any);
|
||||
|
||||
const tag = await tagsService.createTag({
|
||||
name: 'New Tag',
|
||||
color: '#ff0000',
|
||||
userId: mockUserId,
|
||||
});
|
||||
|
||||
expect(tag).toEqual(mockTag);
|
||||
expect(prisma.tag.create).toHaveBeenCalledWith({
|
||||
data: {
|
||||
name: 'New Tag',
|
||||
color: '#ff0000',
|
||||
isPinned: false,
|
||||
ownerId: mockUserId,
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('devrait lancer une erreur si le tag existe déjà', async () => {
|
||||
const existingTag = {
|
||||
id: 'tag-1',
|
||||
name: 'Existing Tag',
|
||||
color: '#ff0000',
|
||||
isPinned: false,
|
||||
};
|
||||
|
||||
vi.mocked(prisma.tag.findFirst).mockResolvedValue(existingTag as any);
|
||||
|
||||
await expect(
|
||||
tagsService.createTag({
|
||||
name: 'Existing Tag',
|
||||
color: '#ff0000',
|
||||
userId: mockUserId,
|
||||
})
|
||||
).rejects.toThrow('existe déjà');
|
||||
});
|
||||
|
||||
it('devrait trimmer le nom du tag', async () => {
|
||||
const mockTag = {
|
||||
id: 'tag-1',
|
||||
name: 'Trimmed Tag',
|
||||
color: '#ff0000',
|
||||
isPinned: false,
|
||||
};
|
||||
|
||||
vi.mocked(prisma.tag.findFirst).mockResolvedValue(null);
|
||||
vi.mocked(prisma.tag.create).mockResolvedValue(mockTag as any);
|
||||
|
||||
await tagsService.createTag({
|
||||
name: ' Trimmed Tag ',
|
||||
color: '#ff0000',
|
||||
userId: mockUserId,
|
||||
});
|
||||
|
||||
expect(prisma.tag.create).toHaveBeenCalledWith({
|
||||
data: {
|
||||
name: 'Trimmed Tag',
|
||||
color: '#ff0000',
|
||||
isPinned: false,
|
||||
ownerId: mockUserId,
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('updateTag', () => {
|
||||
it('devrait mettre à jour un tag', async () => {
|
||||
const mockTag = {
|
||||
id: 'tag-1',
|
||||
name: 'Updated Tag',
|
||||
color: '#00ff00',
|
||||
isPinned: true,
|
||||
};
|
||||
|
||||
vi.mocked(prisma.tag.findFirst).mockResolvedValue({
|
||||
id: 'tag-1',
|
||||
name: 'Old Tag',
|
||||
color: '#ff0000',
|
||||
isPinned: false,
|
||||
} as any);
|
||||
vi.mocked(prisma.tag.update).mockResolvedValue(mockTag as any);
|
||||
|
||||
const tag = await tagsService.updateTag('tag-1', mockUserId, {
|
||||
name: 'Updated Tag',
|
||||
color: '#00ff00',
|
||||
isPinned: true,
|
||||
});
|
||||
|
||||
expect(tag).toEqual(mockTag);
|
||||
expect(prisma.tag.update).toHaveBeenCalledWith({
|
||||
where: { id: 'tag-1' },
|
||||
data: {
|
||||
name: 'Updated Tag',
|
||||
color: '#00ff00',
|
||||
isPinned: true,
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it("devrait lancer une erreur si le tag n'existe pas", async () => {
|
||||
vi.mocked(prisma.tag.findFirst).mockResolvedValue(null);
|
||||
|
||||
await expect(
|
||||
tagsService.updateTag('non-existent', mockUserId, {
|
||||
name: 'Updated Tag',
|
||||
})
|
||||
).rejects.toThrow('non trouvé');
|
||||
});
|
||||
});
|
||||
|
||||
describe('deleteTag', () => {
|
||||
it('devrait supprimer un tag', async () => {
|
||||
vi.mocked(prisma.tag.findFirst).mockResolvedValue({
|
||||
id: 'tag-1',
|
||||
name: 'Tag to delete',
|
||||
color: '#ff0000',
|
||||
isPinned: false,
|
||||
} as any);
|
||||
vi.mocked(prisma.taskTag.deleteMany).mockResolvedValue({
|
||||
count: 0,
|
||||
} as any);
|
||||
vi.mocked(prisma.tag.delete).mockResolvedValue({} as any);
|
||||
|
||||
await tagsService.deleteTag('tag-1', mockUserId);
|
||||
|
||||
expect(prisma.taskTag.deleteMany).toHaveBeenCalledWith({
|
||||
where: { tagId: 'tag-1' },
|
||||
});
|
||||
expect(prisma.tag.delete).toHaveBeenCalledWith({
|
||||
where: { id: 'tag-1' },
|
||||
});
|
||||
});
|
||||
|
||||
it("devrait lancer une erreur si le tag n'existe pas", async () => {
|
||||
vi.mocked(prisma.tag.findFirst).mockResolvedValue(null);
|
||||
|
||||
await expect(
|
||||
tagsService.deleteTag('non-existent', mockUserId)
|
||||
).rejects.toThrow('non trouvé');
|
||||
});
|
||||
});
|
||||
});
|
||||
436
src/services/task-management/__tests__/tasks.test.ts
Normal file
436
src/services/task-management/__tests__/tasks.test.ts
Normal file
@@ -0,0 +1,436 @@
|
||||
/**
|
||||
* Tests unitaires pour TasksService
|
||||
*/
|
||||
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
import { describe, it, expect, beforeEach, vi } from 'vitest';
|
||||
import { TasksService } from '../tasks';
|
||||
import { prisma } from '@/services/core/database';
|
||||
import { tagsService } from '../tags';
|
||||
import { getReadonlyFieldsForTask } from '../readonly-fields';
|
||||
import { getToday } from '@/lib/date-utils';
|
||||
|
||||
// Mock de prisma
|
||||
vi.mock('@/services/core/database', () => ({
|
||||
prisma: {
|
||||
task: {
|
||||
findMany: vi.fn(),
|
||||
findFirst: vi.fn(),
|
||||
findUnique: vi.fn(),
|
||||
create: vi.fn(),
|
||||
update: vi.fn(),
|
||||
delete: vi.fn(),
|
||||
aggregate: vi.fn(),
|
||||
},
|
||||
taskTag: {
|
||||
createMany: vi.fn(),
|
||||
deleteMany: vi.fn(),
|
||||
findMany: vi.fn(),
|
||||
},
|
||||
dailyCheckbox: {
|
||||
findMany: vi.fn(),
|
||||
},
|
||||
},
|
||||
}));
|
||||
|
||||
// Mock de tagsService
|
||||
vi.mock('../tags', () => ({
|
||||
tagsService: {
|
||||
ensureTagsExist: vi.fn(),
|
||||
},
|
||||
}));
|
||||
|
||||
// Mock de readonly-fields
|
||||
vi.mock('../readonly-fields', () => ({
|
||||
getReadonlyFieldsForTask: vi.fn(),
|
||||
}));
|
||||
|
||||
// Mock de date-utils
|
||||
vi.mock('@/lib/date-utils', () => ({
|
||||
getToday: vi.fn(),
|
||||
}));
|
||||
|
||||
describe('TasksService', () => {
|
||||
let service: TasksService;
|
||||
const mockUserId = 'user-123';
|
||||
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
service = new TasksService();
|
||||
vi.mocked(getToday).mockReturnValue(new Date('2024-01-15'));
|
||||
});
|
||||
|
||||
describe('getTasks', () => {
|
||||
it('devrait récupérer toutes les tâches pour un utilisateur', async () => {
|
||||
const mockTasks = [
|
||||
{
|
||||
id: 'task-1',
|
||||
title: 'Task 1',
|
||||
description: null,
|
||||
status: 'todo',
|
||||
priority: 'medium',
|
||||
source: 'manual',
|
||||
sourceId: 'manual-123',
|
||||
ownerId: mockUserId,
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
dueDate: null,
|
||||
completedAt: null,
|
||||
primaryTagId: null,
|
||||
jiraProject: null,
|
||||
jiraKey: null,
|
||||
jiraType: null,
|
||||
tfsProject: null,
|
||||
tfsPullRequestId: null,
|
||||
tfsRepository: null,
|
||||
tfsSourceBranch: null,
|
||||
tfsTargetBranch: null,
|
||||
assignee: null,
|
||||
taskTags: [],
|
||||
primaryTag: null,
|
||||
_count: { dailyCheckboxes: 0 },
|
||||
},
|
||||
];
|
||||
|
||||
vi.mocked(prisma.task.findMany).mockResolvedValue(mockTasks as any);
|
||||
vi.mocked(getReadonlyFieldsForTask).mockReturnValue([]);
|
||||
|
||||
const tasks = await service.getTasks(mockUserId);
|
||||
|
||||
expect(tasks).toHaveLength(1);
|
||||
expect(prisma.task.findMany).toHaveBeenCalledWith({
|
||||
where: { ownerId: mockUserId },
|
||||
include: {
|
||||
taskTags: {
|
||||
include: {
|
||||
tag: true,
|
||||
},
|
||||
},
|
||||
primaryTag: true,
|
||||
_count: {
|
||||
select: {
|
||||
dailyCheckboxes: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
take: undefined,
|
||||
skip: 0,
|
||||
orderBy: [
|
||||
{ completedAt: 'desc' },
|
||||
{ dueDate: 'asc' },
|
||||
{ createdAt: 'desc' },
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
it('devrait filtrer par statut', async () => {
|
||||
vi.mocked(prisma.task.findMany).mockResolvedValue([]);
|
||||
|
||||
await service.getTasks(mockUserId, { status: ['todo', 'in_progress'] });
|
||||
|
||||
expect(prisma.task.findMany).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
where: expect.objectContaining({
|
||||
status: { in: ['todo', 'in_progress'] },
|
||||
}),
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
it('devrait rechercher dans le titre et la description', async () => {
|
||||
vi.mocked(prisma.task.findMany).mockResolvedValue([]);
|
||||
|
||||
await service.getTasks(mockUserId, { search: 'test' });
|
||||
|
||||
expect(prisma.task.findMany).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
where: expect.objectContaining({
|
||||
OR: [
|
||||
{ title: { contains: 'test' } },
|
||||
{ description: { contains: 'test' } },
|
||||
],
|
||||
}),
|
||||
})
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('createTask', () => {
|
||||
it('devrait créer une nouvelle tâche', async () => {
|
||||
const mockTask = {
|
||||
id: 'task-1',
|
||||
title: 'New Task',
|
||||
description: 'Description',
|
||||
status: 'todo',
|
||||
priority: 'medium',
|
||||
ownerId: mockUserId,
|
||||
source: 'manual',
|
||||
sourceId: 'manual-123',
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
dueDate: null,
|
||||
completedAt: null,
|
||||
primaryTagId: null,
|
||||
jiraProject: null,
|
||||
jiraKey: null,
|
||||
jiraType: null,
|
||||
tfsProject: null,
|
||||
tfsPullRequestId: null,
|
||||
tfsRepository: null,
|
||||
tfsSourceBranch: null,
|
||||
tfsTargetBranch: null,
|
||||
assignee: null,
|
||||
taskTags: [],
|
||||
primaryTag: null,
|
||||
};
|
||||
|
||||
vi.mocked(prisma.task.create).mockResolvedValue(mockTask as any);
|
||||
vi.mocked(prisma.task.findUnique).mockResolvedValue(mockTask as any);
|
||||
vi.mocked(tagsService.ensureTagsExist).mockResolvedValue([]);
|
||||
vi.mocked(getReadonlyFieldsForTask).mockReturnValue([]);
|
||||
|
||||
const task = await service.createTask({
|
||||
title: 'New Task',
|
||||
description: 'Description',
|
||||
ownerId: mockUserId,
|
||||
});
|
||||
|
||||
expect(task).toBeDefined();
|
||||
expect(prisma.task.create).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('devrait définir completedAt si le statut est done', async () => {
|
||||
const mockTask = {
|
||||
id: 'task-1',
|
||||
title: 'Done Task',
|
||||
description: null,
|
||||
status: 'done',
|
||||
priority: 'medium',
|
||||
ownerId: mockUserId,
|
||||
source: 'manual',
|
||||
sourceId: 'manual-123',
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
dueDate: null,
|
||||
completedAt: new Date('2024-01-15'),
|
||||
primaryTagId: null,
|
||||
jiraProject: null,
|
||||
jiraKey: null,
|
||||
jiraType: null,
|
||||
tfsProject: null,
|
||||
tfsPullRequestId: null,
|
||||
tfsRepository: null,
|
||||
tfsSourceBranch: null,
|
||||
tfsTargetBranch: null,
|
||||
assignee: null,
|
||||
taskTags: [],
|
||||
primaryTag: null,
|
||||
};
|
||||
|
||||
vi.mocked(prisma.task.create).mockResolvedValue(mockTask as any);
|
||||
vi.mocked(prisma.task.findUnique).mockResolvedValue(mockTask as any);
|
||||
vi.mocked(tagsService.ensureTagsExist).mockResolvedValue([]);
|
||||
vi.mocked(getReadonlyFieldsForTask).mockReturnValue([]);
|
||||
|
||||
await service.createTask({
|
||||
title: 'Done Task',
|
||||
status: 'done',
|
||||
ownerId: mockUserId,
|
||||
});
|
||||
|
||||
expect(prisma.task.create).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
data: expect.objectContaining({
|
||||
completedAt: expect.any(Date),
|
||||
}),
|
||||
})
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('updateTask', () => {
|
||||
it('devrait mettre à jour une tâche', async () => {
|
||||
const mockTask = {
|
||||
id: 'task-1',
|
||||
title: 'Updated Task',
|
||||
description: null,
|
||||
status: 'in_progress',
|
||||
priority: 'medium',
|
||||
ownerId: mockUserId,
|
||||
source: 'manual',
|
||||
sourceId: 'manual-123',
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
dueDate: null,
|
||||
completedAt: null,
|
||||
primaryTagId: null,
|
||||
jiraProject: null,
|
||||
jiraKey: null,
|
||||
jiraType: null,
|
||||
tfsProject: null,
|
||||
tfsPullRequestId: null,
|
||||
tfsRepository: null,
|
||||
tfsSourceBranch: null,
|
||||
tfsTargetBranch: null,
|
||||
assignee: null,
|
||||
taskTags: [],
|
||||
primaryTag: null,
|
||||
};
|
||||
|
||||
vi.mocked(prisma.task.findFirst).mockResolvedValue(mockTask as any);
|
||||
vi.mocked(prisma.task.update).mockResolvedValue(mockTask as any);
|
||||
vi.mocked(prisma.task.findUnique).mockResolvedValue(mockTask as any);
|
||||
vi.mocked(getReadonlyFieldsForTask).mockReturnValue([]);
|
||||
|
||||
const task = await service.updateTask(mockUserId, 'task-1', {
|
||||
title: 'Updated Task',
|
||||
status: 'in_progress',
|
||||
});
|
||||
|
||||
expect(task).toBeDefined();
|
||||
expect(prisma.task.update).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('devrait définir completedAt quand le statut passe à done', async () => {
|
||||
const mockTask = {
|
||||
id: 'task-1',
|
||||
title: 'Task',
|
||||
description: null,
|
||||
status: 'todo',
|
||||
priority: 'medium',
|
||||
ownerId: mockUserId,
|
||||
source: 'manual',
|
||||
sourceId: 'manual-123',
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
dueDate: null,
|
||||
completedAt: null,
|
||||
primaryTagId: null,
|
||||
jiraProject: null,
|
||||
jiraKey: null,
|
||||
jiraType: null,
|
||||
tfsProject: null,
|
||||
tfsPullRequestId: null,
|
||||
tfsRepository: null,
|
||||
tfsSourceBranch: null,
|
||||
tfsTargetBranch: null,
|
||||
assignee: null,
|
||||
taskTags: [],
|
||||
primaryTag: null,
|
||||
};
|
||||
|
||||
vi.mocked(prisma.task.findFirst).mockResolvedValue(mockTask as any);
|
||||
vi.mocked(prisma.task.update).mockResolvedValue({
|
||||
...mockTask,
|
||||
status: 'done',
|
||||
completedAt: new Date('2024-01-15'),
|
||||
} as any);
|
||||
vi.mocked(prisma.task.findUnique).mockResolvedValue({
|
||||
...mockTask,
|
||||
status: 'done',
|
||||
completedAt: new Date('2024-01-15'),
|
||||
} as any);
|
||||
vi.mocked(getReadonlyFieldsForTask).mockReturnValue([]);
|
||||
|
||||
await service.updateTask(mockUserId, 'task-1', {
|
||||
status: 'done',
|
||||
});
|
||||
|
||||
expect(prisma.task.update).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
data: expect.objectContaining({
|
||||
completedAt: expect.any(Date),
|
||||
}),
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
it("devrait lancer une erreur si la tâche n'existe pas", async () => {
|
||||
vi.mocked(prisma.task.findFirst).mockResolvedValue(null);
|
||||
|
||||
await expect(
|
||||
service.updateTask(mockUserId, 'non-existent', {
|
||||
title: 'Updated',
|
||||
})
|
||||
).rejects.toThrow('introuvable');
|
||||
});
|
||||
});
|
||||
|
||||
describe('deleteTask', () => {
|
||||
it('devrait supprimer une tâche', async () => {
|
||||
const mockTask = {
|
||||
id: 'task-1',
|
||||
title: 'Task to delete',
|
||||
ownerId: mockUserId,
|
||||
};
|
||||
|
||||
vi.mocked(prisma.task.findFirst).mockResolvedValue(mockTask as any);
|
||||
vi.mocked(prisma.task.delete).mockResolvedValue({} as any);
|
||||
|
||||
await service.deleteTask(mockUserId, 'task-1');
|
||||
|
||||
expect(prisma.task.delete).toHaveBeenCalledWith({
|
||||
where: { id: 'task-1' },
|
||||
});
|
||||
});
|
||||
|
||||
it("devrait lancer une erreur si la tâche n'existe pas", async () => {
|
||||
vi.mocked(prisma.task.findFirst).mockResolvedValue(null);
|
||||
|
||||
await expect(
|
||||
service.deleteTask(mockUserId, 'non-existent')
|
||||
).rejects.toThrow('introuvable');
|
||||
});
|
||||
});
|
||||
|
||||
describe('updateTaskStatus', () => {
|
||||
it("devrait mettre à jour le statut d'une tâche", async () => {
|
||||
const mockTask = {
|
||||
id: 'task-1',
|
||||
title: 'Task',
|
||||
description: null,
|
||||
status: 'todo',
|
||||
priority: 'medium',
|
||||
ownerId: mockUserId,
|
||||
source: 'manual',
|
||||
sourceId: 'manual-123',
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
dueDate: null,
|
||||
completedAt: null,
|
||||
primaryTagId: null,
|
||||
jiraProject: null,
|
||||
jiraKey: null,
|
||||
jiraType: null,
|
||||
tfsProject: null,
|
||||
tfsPullRequestId: null,
|
||||
tfsRepository: null,
|
||||
tfsSourceBranch: null,
|
||||
tfsTargetBranch: null,
|
||||
assignee: null,
|
||||
taskTags: [],
|
||||
primaryTag: null,
|
||||
};
|
||||
|
||||
vi.mocked(prisma.task.findFirst).mockResolvedValue(mockTask as any);
|
||||
vi.mocked(prisma.task.update).mockResolvedValue({
|
||||
...mockTask,
|
||||
status: 'in_progress',
|
||||
} as any);
|
||||
vi.mocked(prisma.task.findUnique).mockResolvedValue({
|
||||
...mockTask,
|
||||
status: 'in_progress',
|
||||
} as any);
|
||||
vi.mocked(getReadonlyFieldsForTask).mockReturnValue([]);
|
||||
|
||||
const task = await service.updateTaskStatus(
|
||||
mockUserId,
|
||||
'task-1',
|
||||
'in_progress'
|
||||
);
|
||||
|
||||
expect(task).toBeDefined();
|
||||
expect(prisma.task.update).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user