test(JiraSync): improve test coverage for synchronization scenarios and enhance assertions for change detection
This commit is contained in:
345
src/services/__tests__/notes.test.ts
Normal file
345
src/services/__tests__/notes.test.ts
Normal file
@@ -0,0 +1,345 @@
|
||||
/**
|
||||
* Tests unitaires pour NotesService
|
||||
*/
|
||||
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
import { describe, it, expect, beforeEach, vi } from 'vitest';
|
||||
import { NotesService } from '../notes';
|
||||
import { prisma } from '@/services/core/database';
|
||||
import { tagsService } from '../task-management/tags';
|
||||
|
||||
// Mock de prisma
|
||||
vi.mock('@/services/core/database', () => ({
|
||||
prisma: {
|
||||
note: {
|
||||
findMany: vi.fn(),
|
||||
findFirst: vi.fn(),
|
||||
findUnique: vi.fn(),
|
||||
create: vi.fn(),
|
||||
update: vi.fn(),
|
||||
delete: vi.fn(),
|
||||
count: vi.fn(),
|
||||
},
|
||||
noteTag: {
|
||||
createMany: vi.fn(),
|
||||
deleteMany: vi.fn(),
|
||||
findMany: vi.fn(),
|
||||
},
|
||||
},
|
||||
}));
|
||||
|
||||
// Mock de tagsService
|
||||
vi.mock('../task-management/tags', () => ({
|
||||
tagsService: {
|
||||
ensureTagsExist: vi.fn(),
|
||||
},
|
||||
}));
|
||||
|
||||
describe('NotesService', () => {
|
||||
let service: NotesService;
|
||||
const mockUserId = 'user-123';
|
||||
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
service = new NotesService();
|
||||
});
|
||||
|
||||
describe('getNotes', () => {
|
||||
it('devrait récupérer toutes les notes pour un utilisateur', async () => {
|
||||
const mockNotes = [
|
||||
{
|
||||
id: 'note-1',
|
||||
title: 'Note 1',
|
||||
content: 'Content 1',
|
||||
userId: mockUserId,
|
||||
taskId: null,
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
noteTags: [],
|
||||
task: null,
|
||||
},
|
||||
];
|
||||
|
||||
vi.mocked(prisma.note.findMany).mockResolvedValue(mockNotes as any);
|
||||
|
||||
const notes = await service.getNotes(mockUserId);
|
||||
|
||||
expect(notes).toHaveLength(1);
|
||||
expect(prisma.note.findMany).toHaveBeenCalledWith({
|
||||
where: { userId: mockUserId },
|
||||
include: {
|
||||
noteTags: {
|
||||
include: {
|
||||
tag: true,
|
||||
},
|
||||
},
|
||||
task: {
|
||||
include: {
|
||||
taskTags: {
|
||||
include: {
|
||||
tag: true,
|
||||
},
|
||||
},
|
||||
primaryTag: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
orderBy: { updatedAt: 'desc' },
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('getNoteById', () => {
|
||||
it('devrait récupérer une note par son ID', async () => {
|
||||
const mockNote = {
|
||||
id: 'note-1',
|
||||
title: 'Note 1',
|
||||
content: 'Content 1',
|
||||
userId: mockUserId,
|
||||
taskId: null,
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
noteTags: [],
|
||||
task: null,
|
||||
};
|
||||
|
||||
vi.mocked(prisma.note.findFirst).mockResolvedValue(mockNote as any);
|
||||
|
||||
const note = await service.getNoteById('note-1', mockUserId);
|
||||
|
||||
expect(note).toBeDefined();
|
||||
expect(note?.id).toBe('note-1');
|
||||
expect(prisma.note.findFirst).toHaveBeenCalledWith({
|
||||
where: {
|
||||
id: 'note-1',
|
||||
userId: mockUserId,
|
||||
},
|
||||
include: {
|
||||
noteTags: {
|
||||
include: {
|
||||
tag: true,
|
||||
},
|
||||
},
|
||||
task: {
|
||||
include: {
|
||||
taskTags: {
|
||||
include: {
|
||||
tag: true,
|
||||
},
|
||||
},
|
||||
primaryTag: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it("devrait retourner null si la note n'existe pas", async () => {
|
||||
vi.mocked(prisma.note.findFirst).mockResolvedValue(null);
|
||||
|
||||
const note = await service.getNoteById('non-existent', mockUserId);
|
||||
|
||||
expect(note).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
describe('createNote', () => {
|
||||
it('devrait créer une nouvelle note', async () => {
|
||||
const mockNote = {
|
||||
id: 'note-1',
|
||||
title: 'New Note',
|
||||
content: 'Content',
|
||||
userId: mockUserId,
|
||||
taskId: null,
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
noteTags: [],
|
||||
task: null,
|
||||
};
|
||||
|
||||
vi.mocked(prisma.note.create).mockResolvedValue(mockNote as any);
|
||||
vi.mocked(prisma.note.findUnique).mockResolvedValue(mockNote as any);
|
||||
vi.mocked(tagsService.ensureTagsExist).mockResolvedValue([]);
|
||||
|
||||
const note = await service.createNote({
|
||||
title: 'New Note',
|
||||
content: 'Content',
|
||||
userId: mockUserId,
|
||||
});
|
||||
|
||||
expect(note).toBeDefined();
|
||||
expect(prisma.note.create).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('devrait créer une note avec des tags', async () => {
|
||||
const mockNote = {
|
||||
id: 'note-1',
|
||||
title: 'New Note',
|
||||
content: 'Content',
|
||||
userId: mockUserId,
|
||||
taskId: null,
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
noteTags: [],
|
||||
task: null,
|
||||
};
|
||||
|
||||
const mockTags = [
|
||||
{ id: 'tag-1', name: 'Tag 1', color: '#ff0000', isPinned: false },
|
||||
];
|
||||
|
||||
vi.mocked(prisma.note.create).mockResolvedValue(mockNote as any);
|
||||
vi.mocked(prisma.note.findUnique).mockResolvedValue({
|
||||
...mockNote,
|
||||
noteTags: [{ tag: mockTags[0] }],
|
||||
} as any);
|
||||
vi.mocked(tagsService.ensureTagsExist).mockResolvedValue(mockTags as any);
|
||||
vi.mocked(prisma.noteTag.createMany).mockResolvedValue({
|
||||
count: 1,
|
||||
} as any);
|
||||
|
||||
await service.createNote({
|
||||
title: 'New Note',
|
||||
content: 'Content',
|
||||
userId: mockUserId,
|
||||
tags: ['Tag 1'],
|
||||
});
|
||||
|
||||
expect(tagsService.ensureTagsExist).toHaveBeenCalledWith(
|
||||
['Tag 1'],
|
||||
mockUserId
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('updateNote', () => {
|
||||
it('devrait mettre à jour une note', async () => {
|
||||
const mockNote = {
|
||||
id: 'note-1',
|
||||
title: 'Updated Note',
|
||||
content: 'Updated Content',
|
||||
userId: mockUserId,
|
||||
taskId: null,
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
noteTags: [],
|
||||
task: null,
|
||||
};
|
||||
|
||||
vi.mocked(prisma.note.findFirst).mockResolvedValue({
|
||||
id: 'note-1',
|
||||
userId: mockUserId,
|
||||
} as any);
|
||||
vi.mocked(prisma.note.update).mockResolvedValue(mockNote as any);
|
||||
vi.mocked(prisma.note.findUnique).mockResolvedValue({
|
||||
...mockNote,
|
||||
noteTags: [],
|
||||
} as any);
|
||||
vi.mocked(prisma.noteTag.deleteMany).mockResolvedValue({
|
||||
count: 0,
|
||||
} as any);
|
||||
vi.mocked(tagsService.ensureTagsExist).mockResolvedValue([]);
|
||||
|
||||
const note = await service.updateNote('note-1', mockUserId, {
|
||||
title: 'Updated Note',
|
||||
content: 'Updated Content',
|
||||
});
|
||||
|
||||
expect(note).toBeDefined();
|
||||
expect(prisma.note.update).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("devrait lancer une erreur si la note n'existe pas", async () => {
|
||||
vi.mocked(prisma.note.findFirst).mockResolvedValue(null);
|
||||
|
||||
await expect(
|
||||
service.updateNote('non-existent', mockUserId, {
|
||||
title: 'Updated',
|
||||
})
|
||||
).rejects.toThrow();
|
||||
});
|
||||
});
|
||||
|
||||
describe('deleteNote', () => {
|
||||
it('devrait supprimer une note', async () => {
|
||||
vi.mocked(prisma.note.findFirst).mockResolvedValue({
|
||||
id: 'note-1',
|
||||
userId: mockUserId,
|
||||
} as any);
|
||||
vi.mocked(prisma.note.delete).mockResolvedValue({} as any);
|
||||
|
||||
await service.deleteNote('note-1', mockUserId);
|
||||
|
||||
expect(prisma.note.delete).toHaveBeenCalledWith({
|
||||
where: { id: 'note-1' },
|
||||
});
|
||||
});
|
||||
|
||||
it("devrait lancer une erreur si la note n'existe pas", async () => {
|
||||
vi.mocked(prisma.note.findFirst).mockResolvedValue(null);
|
||||
|
||||
await expect(
|
||||
service.deleteNote('non-existent', mockUserId)
|
||||
).rejects.toThrow();
|
||||
});
|
||||
});
|
||||
|
||||
describe('searchNotes', () => {
|
||||
it('devrait rechercher dans les notes', async () => {
|
||||
const mockNotes = [
|
||||
{
|
||||
id: 'note-1',
|
||||
title: 'Test Note',
|
||||
content: 'Content',
|
||||
userId: mockUserId,
|
||||
taskId: null,
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
noteTags: [],
|
||||
task: null,
|
||||
},
|
||||
];
|
||||
|
||||
vi.mocked(prisma.note.findMany).mockResolvedValue(mockNotes as any);
|
||||
|
||||
const notes = await service.searchNotes(mockUserId, 'Test');
|
||||
|
||||
expect(notes).toHaveLength(1);
|
||||
expect(prisma.note.findMany).toHaveBeenCalledWith({
|
||||
where: {
|
||||
userId: mockUserId,
|
||||
OR: [
|
||||
{ title: { contains: 'Test' } },
|
||||
{ content: { contains: 'Test' } },
|
||||
],
|
||||
},
|
||||
orderBy: { updatedAt: 'desc' },
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('getNotesStats', () => {
|
||||
it('devrait retourner les statistiques des notes', async () => {
|
||||
const mockNotes = [
|
||||
{
|
||||
id: 'note-1',
|
||||
content: 'This is a test note with words',
|
||||
updatedAt: new Date(),
|
||||
},
|
||||
{
|
||||
id: 'note-2',
|
||||
content: 'Another note',
|
||||
updatedAt: new Date(),
|
||||
},
|
||||
];
|
||||
|
||||
vi.mocked(prisma.note.findMany).mockResolvedValue(mockNotes as any);
|
||||
|
||||
const stats = await service.getNotesStats(mockUserId);
|
||||
|
||||
expect(stats.totalNotes).toBeGreaterThanOrEqual(0);
|
||||
expect(stats.totalWords).toBeGreaterThanOrEqual(0);
|
||||
expect(stats.lastUpdated).toBeDefined();
|
||||
});
|
||||
});
|
||||
});
|
||||
276
src/services/__tests__/users.test.ts
Normal file
276
src/services/__tests__/users.test.ts
Normal file
@@ -0,0 +1,276 @@
|
||||
/**
|
||||
* Tests unitaires pour usersService
|
||||
*/
|
||||
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
import { describe, it, expect, beforeEach, vi } from 'vitest';
|
||||
import { usersService } from '../users';
|
||||
import { prisma } from '../core/database';
|
||||
import bcrypt from 'bcryptjs';
|
||||
|
||||
// Mock de prisma
|
||||
vi.mock('../core/database', () => ({
|
||||
prisma: {
|
||||
user: {
|
||||
create: vi.fn(),
|
||||
findUnique: vi.fn(),
|
||||
update: vi.fn(),
|
||||
},
|
||||
},
|
||||
}));
|
||||
|
||||
// Mock de bcrypt
|
||||
vi.mock('bcryptjs', () => ({
|
||||
default: {
|
||||
hash: vi.fn(),
|
||||
compare: vi.fn(),
|
||||
},
|
||||
}));
|
||||
|
||||
describe('usersService', () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
|
||||
describe('createUser', () => {
|
||||
it('devrait créer un nouvel utilisateur', async () => {
|
||||
const mockUser = {
|
||||
id: 'user-1',
|
||||
email: 'test@example.com',
|
||||
name: 'Test User',
|
||||
firstName: 'Test',
|
||||
lastName: 'User',
|
||||
avatar: null,
|
||||
role: 'user',
|
||||
isActive: true,
|
||||
lastLoginAt: null,
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
};
|
||||
|
||||
vi.mocked(bcrypt.hash).mockResolvedValue('hashedPassword' as any);
|
||||
vi.mocked(prisma.user.create).mockResolvedValue(mockUser as any);
|
||||
|
||||
const user = await usersService.createUser({
|
||||
email: 'test@example.com',
|
||||
name: 'Test User',
|
||||
firstName: 'Test',
|
||||
lastName: 'User',
|
||||
password: 'password123',
|
||||
});
|
||||
|
||||
expect(user).toEqual(mockUser);
|
||||
expect(bcrypt.hash).toHaveBeenCalledWith('password123', 12);
|
||||
expect(prisma.user.create).toHaveBeenCalledWith({
|
||||
data: {
|
||||
email: 'test@example.com',
|
||||
name: 'Test User',
|
||||
firstName: 'Test',
|
||||
lastName: 'User',
|
||||
avatar: undefined,
|
||||
role: 'user',
|
||||
password: 'hashedPassword',
|
||||
},
|
||||
select: expect.any(Object),
|
||||
});
|
||||
});
|
||||
|
||||
it('devrait utiliser le rôle par défaut si non spécifié', async () => {
|
||||
const mockUser = {
|
||||
id: 'user-1',
|
||||
email: 'test@example.com',
|
||||
name: null,
|
||||
firstName: null,
|
||||
lastName: null,
|
||||
avatar: null,
|
||||
role: 'user',
|
||||
isActive: true,
|
||||
lastLoginAt: null,
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
};
|
||||
|
||||
vi.mocked(bcrypt.hash).mockResolvedValue('hashedPassword' as any);
|
||||
vi.mocked(prisma.user.create).mockResolvedValue(mockUser as any);
|
||||
|
||||
await usersService.createUser({
|
||||
email: 'test@example.com',
|
||||
password: 'password123',
|
||||
});
|
||||
|
||||
expect(prisma.user.create).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
data: expect.objectContaining({
|
||||
role: 'user',
|
||||
}),
|
||||
})
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getUserByEmail', () => {
|
||||
it('devrait récupérer un utilisateur par email', async () => {
|
||||
const mockUser = {
|
||||
id: 'user-1',
|
||||
email: 'test@example.com',
|
||||
name: 'Test User',
|
||||
firstName: 'Test',
|
||||
lastName: 'User',
|
||||
avatar: null,
|
||||
role: 'user',
|
||||
isActive: true,
|
||||
lastLoginAt: null,
|
||||
password: 'hashedPassword',
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
};
|
||||
|
||||
vi.mocked(prisma.user.findUnique).mockResolvedValue(mockUser as any);
|
||||
|
||||
const user = await usersService.getUserByEmail('test@example.com');
|
||||
|
||||
expect(user).toEqual(mockUser);
|
||||
expect(prisma.user.findUnique).toHaveBeenCalledWith({
|
||||
where: { email: 'test@example.com' },
|
||||
select: expect.any(Object),
|
||||
});
|
||||
});
|
||||
|
||||
it("devrait retourner null si l'utilisateur n'existe pas", async () => {
|
||||
vi.mocked(prisma.user.findUnique).mockResolvedValue(null);
|
||||
|
||||
const user = await usersService.getUserByEmail('nonexistent@example.com');
|
||||
|
||||
expect(user).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
describe('getUserById', () => {
|
||||
it('devrait récupérer un utilisateur par ID', async () => {
|
||||
const mockUser = {
|
||||
id: 'user-1',
|
||||
email: 'test@example.com',
|
||||
name: 'Test User',
|
||||
firstName: 'Test',
|
||||
lastName: 'User',
|
||||
avatar: null,
|
||||
role: 'user',
|
||||
isActive: true,
|
||||
lastLoginAt: null,
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
};
|
||||
|
||||
vi.mocked(prisma.user.findUnique).mockResolvedValue(mockUser as any);
|
||||
|
||||
const user = await usersService.getUserById('user-1');
|
||||
|
||||
expect(user).toEqual(mockUser);
|
||||
expect(prisma.user.findUnique).toHaveBeenCalledWith({
|
||||
where: { id: 'user-1' },
|
||||
select: expect.any(Object),
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('verifyPassword', () => {
|
||||
it('devrait vérifier un mot de passe correct', async () => {
|
||||
vi.mocked(bcrypt.compare).mockResolvedValue(true as any);
|
||||
|
||||
const isValid = await usersService.verifyPassword(
|
||||
'password123',
|
||||
'hashedPassword'
|
||||
);
|
||||
|
||||
expect(isValid).toBe(true);
|
||||
expect(bcrypt.compare).toHaveBeenCalledWith(
|
||||
'password123',
|
||||
'hashedPassword'
|
||||
);
|
||||
});
|
||||
|
||||
it('devrait retourner false pour un mot de passe incorrect', async () => {
|
||||
vi.mocked(bcrypt.compare).mockResolvedValue(false as any);
|
||||
|
||||
const isValid = await usersService.verifyPassword(
|
||||
'wrongPassword',
|
||||
'hashedPassword'
|
||||
);
|
||||
|
||||
expect(isValid).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('emailExists', () => {
|
||||
it("devrait retourner true si l'email existe", async () => {
|
||||
vi.mocked(prisma.user.findUnique).mockResolvedValue({
|
||||
id: 'user-1',
|
||||
email: 'test@example.com',
|
||||
} as any);
|
||||
|
||||
const exists = await usersService.emailExists('test@example.com');
|
||||
|
||||
expect(exists).toBe(true);
|
||||
});
|
||||
|
||||
it("devrait retourner false si l'email n'existe pas", async () => {
|
||||
vi.mocked(prisma.user.findUnique).mockResolvedValue(null);
|
||||
|
||||
const exists = await usersService.emailExists('nonexistent@example.com');
|
||||
|
||||
expect(exists).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('updateLastLogin', () => {
|
||||
it('devrait mettre à jour la date de dernière connexion', async () => {
|
||||
vi.mocked(prisma.user.update).mockResolvedValue({} as any);
|
||||
|
||||
await usersService.updateLastLogin('user-1');
|
||||
|
||||
expect(prisma.user.update).toHaveBeenCalledWith({
|
||||
where: { id: 'user-1' },
|
||||
data: {
|
||||
lastLoginAt: expect.any(Date),
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('updateUser', () => {
|
||||
it('devrait mettre à jour un utilisateur', async () => {
|
||||
const mockUser = {
|
||||
id: 'user-1',
|
||||
email: 'test@example.com',
|
||||
name: 'Updated Name',
|
||||
firstName: 'Updated',
|
||||
lastName: 'Name',
|
||||
avatar: null,
|
||||
role: 'user',
|
||||
isActive: true,
|
||||
lastLoginAt: null,
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
};
|
||||
|
||||
vi.mocked(prisma.user.update).mockResolvedValue(mockUser as any);
|
||||
|
||||
const user = await usersService.updateUser('user-1', {
|
||||
name: 'Updated Name',
|
||||
firstName: 'Updated',
|
||||
lastName: 'Name',
|
||||
});
|
||||
|
||||
expect(user).toEqual(mockUser);
|
||||
expect(prisma.user.update).toHaveBeenCalledWith({
|
||||
where: { id: 'user-1' },
|
||||
data: {
|
||||
name: 'Updated Name',
|
||||
firstName: 'Updated',
|
||||
lastName: 'Name',
|
||||
},
|
||||
select: expect.any(Object),
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user