debuts de tests unitaires

This commit is contained in:
Yannick Le Duc
2025-08-27 13:31:55 +02:00
parent dc388bf371
commit 924d2714c7
12 changed files with 6089 additions and 5 deletions

View File

@@ -0,0 +1,10 @@
describe('Basic Test', () => {
it('should work', () => {
expect(1 + 1).toBe(2);
});
it('should handle async operations', async () => {
const result = await Promise.resolve('test');
expect(result).toBe('test');
});
});

View File

@@ -0,0 +1,120 @@
// Tests simples pour les utilitaires de base
describe('Basic Utils', () => {
describe('String utilities', () => {
it('should validate email correctly', () => {
const validateEmail = (email: string): boolean => {
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
return emailRegex.test(email);
};
expect(validateEmail('test@example.com')).toBe(true);
expect(validateEmail('invalid-email')).toBe(false);
expect(validateEmail('')).toBe(false);
});
it('should validate required fields', () => {
const validateRequired = (value: any): boolean => {
return value !== null && value !== undefined && value !== '';
};
expect(validateRequired('test')).toBe(true);
expect(validateRequired('')).toBe(false);
expect(validateRequired(null)).toBe(false);
expect(validateRequired(undefined)).toBe(false);
});
it('should format currency', () => {
const formatCurrency = (amount: number, currency = '€'): string => {
return `${amount} ${currency}`;
};
expect(formatCurrency(100)).toBe('100 €');
expect(formatCurrency(0)).toBe('0 €');
expect(formatCurrency(1234.56)).toBe('1234.56 €');
});
it('should generate slug from title', () => {
const generateSlug = (title: string): string => {
return title
.toLowerCase()
.replace(/[^a-z0-9\s-]/g, '')
.replace(/\s+/g, '-')
.replace(/-+/g, '-')
.trim();
};
expect(generateSlug('Test Campaign')).toBe('test-campaign');
expect(generateSlug('Campagne avec des accents')).toBe('campagne-avec-des-accents');
expect(generateSlug('Campaign with UPPERCASE')).toBe('campaign-with-uppercase');
});
it('should parse spending tiers', () => {
const parseSpendingTiers = (tiers: string): number[] => {
if (!tiers) return [];
return tiers.split(',').map(tier => parseInt(tier.trim())).filter(tier => !isNaN(tier));
};
expect(parseSpendingTiers('10,25,50,100')).toEqual([10, 25, 50, 100]);
expect(parseSpendingTiers('5,10,20')).toEqual([5, 10, 20]);
expect(parseSpendingTiers('100')).toEqual([100]);
expect(parseSpendingTiers('')).toEqual([]);
});
it('should validate spending tiers', () => {
const validateSpendingTiers = (tiers: string): boolean => {
const parsed = tiers.split(',').map(tier => parseInt(tier.trim()));
if (parsed.some(tier => isNaN(tier) || tier <= 0)) return false;
for (let i = 1; i < parsed.length; i++) {
if (parsed[i] <= parsed[i - 1]) return false;
}
return true;
};
expect(validateSpendingTiers('10,25,50,100')).toBe(true);
expect(validateSpendingTiers('5,10,20')).toBe(true);
expect(validateSpendingTiers('50,25,100')).toBe(false); // Not ascending
expect(validateSpendingTiers('10,invalid,50')).toBe(false); // Invalid number
});
it('should sanitize HTML content', () => {
const sanitizeHtml = (html: string): string => {
// Simple sanitization - remove script tags
return html.replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi, '');
};
const dirtyHtml = '<script>alert("xss")</script><p>Hello <strong>World</strong></p>';
const cleanHtml = sanitizeHtml(dirtyHtml);
expect(cleanHtml).not.toContain('<script>');
expect(cleanHtml).toContain('<p>');
expect(cleanHtml).toContain('<strong>');
});
it('should debounce function calls', () => {
jest.useFakeTimers();
const debounce = (func: Function, delay: number) => {
let timeoutId: NodeJS.Timeout;
return (...args: any[]) => {
clearTimeout(timeoutId);
timeoutId = setTimeout(() => func.apply(null, args), delay);
};
};
const mockFn = jest.fn();
const debouncedFn = debounce(mockFn, 300);
debouncedFn();
debouncedFn();
debouncedFn();
expect(mockFn).not.toHaveBeenCalled();
jest.advanceTimersByTime(300);
expect(mockFn).toHaveBeenCalledTimes(1);
jest.useRealTimers();
});
});
});

View File

@@ -0,0 +1,61 @@
import React, { ReactElement } from 'react';
import { render, RenderOptions } from '@testing-library/react';
// Mock data pour les tests
export const mockCampaign = {
id: 'test-campaign-id',
title: 'Test Campaign',
description: 'Test campaign description',
status: 'deposit' as const,
budget_per_user: 100,
spending_tiers: '10,25,50,100',
slug: 'test-campaign',
created_at: '2024-01-01T00:00:00Z',
updated_at: '2024-01-01T00:00:00Z',
};
export const mockParticipant = {
id: 'test-participant-id',
campaign_id: 'test-campaign-id',
first_name: 'John',
last_name: 'Doe',
email: 'john.doe@example.com',
short_id: 'abc123',
created_at: '2024-01-01T00:00:00Z',
};
export const mockProposition = {
id: 'test-proposition-id',
campaign_id: 'test-campaign-id',
title: 'Test Proposition',
description: 'Test proposition description',
author_first_name: 'Jane',
author_last_name: 'Smith',
author_email: 'jane.smith@example.com',
created_at: '2024-01-01T00:00:00Z',
};
export const mockVote = {
id: 'test-vote-id',
campaign_id: 'test-campaign-id',
participant_id: 'test-participant-id',
proposition_id: 'test-proposition-id',
amount: 50,
created_at: '2024-01-01T00:00:00Z',
updated_at: '2024-01-01T00:00:00Z',
};
// Wrapper pour les tests avec providers
const AllTheProviders = ({ children }: { children: React.ReactNode }) => {
return <>{children}</>;
};
// Custom render function avec providers
const customRender = (
ui: ReactElement,
options?: Omit<RenderOptions, 'wrapper'>
) => render(ui, { wrapper: AllTheProviders, ...options });
// Re-export everything
export * from '@testing-library/react';
export { customRender as render };