amélioration tests
This commit is contained in:
144
src/__tests__/components/Footer.test.tsx
Normal file
144
src/__tests__/components/Footer.test.tsx
Normal file
@@ -0,0 +1,144 @@
|
||||
import React from 'react';
|
||||
import { render, screen } from '@testing-library/react';
|
||||
import '@testing-library/jest-dom';
|
||||
import Footer from '../../components/Footer';
|
||||
|
||||
// Mock des dépendances
|
||||
jest.mock('@/lib/project.config', () => ({
|
||||
PROJECT_CONFIG: {
|
||||
repository: {
|
||||
url: 'https://github.com/example/repo'
|
||||
}
|
||||
}
|
||||
}));
|
||||
|
||||
jest.mock('@/lib/services', () => ({
|
||||
settingsService: {
|
||||
getStringValue: jest.fn().mockResolvedValue('Développé avec ❤️ pour faciliter la démocratie participative - [Logiciel libre et open source](GITURL) et transparent pour tous')
|
||||
}
|
||||
}));
|
||||
|
||||
describe('Footer', () => {
|
||||
beforeEach(() => {
|
||||
// Mock des variables d'environnement
|
||||
process.env.NEXT_PUBLIC_SUPABASE_URL = 'https://test.supabase.co';
|
||||
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY = 'test-key';
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
it('should render footer with basic content', async () => {
|
||||
render(<Footer />);
|
||||
|
||||
// Attendre que le contenu se charge
|
||||
await screen.findByText(/Développé avec ❤️/);
|
||||
expect(screen.getByText(/Développé avec ❤️/)).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should render footer with home variant', async () => {
|
||||
render(<Footer variant="home" />);
|
||||
|
||||
await screen.findByText(/Développé avec ❤️/);
|
||||
const footer = screen.getByText(/Développé avec ❤️/).closest('div');
|
||||
expect(footer).toHaveClass('text-center', 'mt-16', 'pb-8');
|
||||
});
|
||||
|
||||
it('should render footer with public variant (default)', async () => {
|
||||
render(<Footer variant="public" />);
|
||||
|
||||
await screen.findByText(/Développé avec ❤️/);
|
||||
const footer = screen.getByText(/Développé avec ❤️/).closest('div');
|
||||
expect(footer).toHaveClass('text-center', 'mt-16', 'pb-20');
|
||||
});
|
||||
|
||||
it('should apply custom className', async () => {
|
||||
render(<Footer className="custom-class" />);
|
||||
|
||||
await screen.findByText(/Développé avec ❤️/);
|
||||
const footer = screen.getByText(/Développé avec ❤️/).closest('div');
|
||||
expect(footer).toHaveClass('custom-class');
|
||||
});
|
||||
|
||||
it('should handle Supabase not configured', async () => {
|
||||
// Simuler Supabase non configuré
|
||||
process.env.NEXT_PUBLIC_SUPABASE_URL = 'https://placeholder.supabase.co';
|
||||
|
||||
render(<Footer />);
|
||||
|
||||
await screen.findByText(/Développé avec ❤️/);
|
||||
expect(screen.getByText(/Développé avec ❤️/)).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should handle Supabase error gracefully', async () => {
|
||||
// Simuler une erreur Supabase
|
||||
const { settingsService } = require('@/lib/services');
|
||||
settingsService.getStringValue.mockRejectedValueOnce(new Error('Supabase error'));
|
||||
|
||||
render(<Footer />);
|
||||
|
||||
await screen.findByText(/Développé avec ❤️/);
|
||||
expect(screen.getByText(/Développé avec ❤️/)).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should render links when footer message contains markdown links', async () => {
|
||||
const { settingsService } = require('@/lib/services');
|
||||
settingsService.getStringValue.mockResolvedValueOnce('Check our [repository](GITURL) for more info');
|
||||
|
||||
render(<Footer />);
|
||||
|
||||
await screen.findByText(/Check our/);
|
||||
const link = screen.getByRole('link', { name: /repository/i });
|
||||
expect(link).toHaveAttribute('href', 'https://github.com/example/repo');
|
||||
expect(link).toHaveAttribute('target', '_blank');
|
||||
expect(link).toHaveAttribute('rel', 'noopener noreferrer');
|
||||
});
|
||||
|
||||
it('should handle multiple links in footer message', async () => {
|
||||
const { settingsService } = require('@/lib/services');
|
||||
settingsService.getStringValue.mockResolvedValueOnce('Check our [docs](GITURL) and [code](GITURL)');
|
||||
|
||||
render(<Footer />);
|
||||
|
||||
await screen.findByText(/Check our/);
|
||||
const links = screen.getAllByRole('link');
|
||||
expect(links).toHaveLength(2);
|
||||
links.forEach(link => {
|
||||
expect(link).toHaveAttribute('href', 'https://github.com/example/repo');
|
||||
});
|
||||
});
|
||||
|
||||
it('should handle footer message without links', async () => {
|
||||
const { settingsService } = require('@/lib/services');
|
||||
settingsService.getStringValue.mockResolvedValueOnce('Simple footer message without links');
|
||||
|
||||
render(<Footer />);
|
||||
|
||||
await screen.findByText(/Simple footer message/);
|
||||
expect(screen.getByText(/Simple footer message/)).toBeInTheDocument();
|
||||
expect(screen.queryByRole('link')).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should handle special characters in footer message', async () => {
|
||||
const { settingsService } = require('@/lib/services');
|
||||
settingsService.getStringValue.mockResolvedValueOnce('Footer with special chars: @#$%^&*()');
|
||||
|
||||
render(<Footer />);
|
||||
|
||||
await screen.findByText(/Footer with special chars/);
|
||||
expect(screen.getByText(/Footer with special chars/)).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should handle HTML in footer message safely', async () => {
|
||||
const { settingsService } = require('@/lib/services');
|
||||
settingsService.getStringValue.mockResolvedValueOnce('Footer with <script>alert("xss")</script> content');
|
||||
|
||||
render(<Footer />);
|
||||
|
||||
await screen.findByText(/Footer with/);
|
||||
expect(screen.getByText(/Footer with/)).toBeInTheDocument();
|
||||
// HTML should not be interpreted
|
||||
expect(screen.queryByText('xss')).not.toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
103
src/__tests__/components/Navigation.test.tsx
Normal file
103
src/__tests__/components/Navigation.test.tsx
Normal file
@@ -0,0 +1,103 @@
|
||||
import React from 'react';
|
||||
import { render, screen } from '@testing-library/react';
|
||||
import '@testing-library/jest-dom';
|
||||
import Navigation from '../../components/Navigation';
|
||||
|
||||
describe('Navigation', () => {
|
||||
it('should render navigation with basic content', () => {
|
||||
render(<Navigation />);
|
||||
|
||||
expect(screen.getByText(/Mes Budgets Participatifs - Admin/)).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should contain navigation links', () => {
|
||||
render(<Navigation />);
|
||||
|
||||
const links = screen.getAllByRole('link');
|
||||
expect(links.length).toBeGreaterThan(0);
|
||||
});
|
||||
|
||||
it('should have proper link structure', () => {
|
||||
render(<Navigation />);
|
||||
|
||||
const links = screen.getAllByRole('link');
|
||||
links.forEach(link => {
|
||||
expect(link).toHaveAttribute('href');
|
||||
});
|
||||
});
|
||||
|
||||
it('should show back button when showBackButton is true', () => {
|
||||
render(<Navigation showBackButton={true} />);
|
||||
|
||||
expect(screen.getByText(/Retour/)).toBeInTheDocument();
|
||||
expect(screen.getByRole('link', { name: /Retour/ })).toHaveAttribute('href', '/');
|
||||
});
|
||||
|
||||
it('should not show back button by default', () => {
|
||||
render(<Navigation />);
|
||||
|
||||
expect(screen.queryByText(/Retour/)).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should use custom back URL when provided', () => {
|
||||
render(<Navigation showBackButton={true} backUrl="/custom-back" />);
|
||||
|
||||
expect(screen.getByRole('link', { name: /Retour/ })).toHaveAttribute('href', '/custom-back');
|
||||
});
|
||||
|
||||
it('should contain settings link', () => {
|
||||
render(<Navigation />);
|
||||
|
||||
const settingsLink = screen.getByRole('link', { name: /Paramètres/ });
|
||||
expect(settingsLink).toHaveAttribute('href', '/admin/settings');
|
||||
});
|
||||
|
||||
it('should contain signout link', () => {
|
||||
render(<Navigation />);
|
||||
|
||||
const signoutLink = screen.getByRole('link', { name: /Déconnexion/ });
|
||||
expect(signoutLink).toHaveAttribute('href', '/api/auth/signout');
|
||||
});
|
||||
|
||||
it('should have proper link structure', () => {
|
||||
render(<Navigation />);
|
||||
|
||||
const links = screen.getAllByRole('link');
|
||||
expect(links.length).toBeGreaterThan(0);
|
||||
});
|
||||
|
||||
it('should have proper card structure', () => {
|
||||
render(<Navigation />);
|
||||
|
||||
const card = screen.getByText(/Mes Budgets Participatifs - Admin/).closest('[class*="card"]');
|
||||
expect(card).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should have proper layout structure', () => {
|
||||
render(<Navigation />);
|
||||
|
||||
const title = screen.getByText(/Mes Budgets Participatifs - Admin/);
|
||||
expect(title).toHaveClass('text-xl', 'font-semibold');
|
||||
});
|
||||
|
||||
it('should handle navigation without custom props', () => {
|
||||
render(<Navigation />);
|
||||
|
||||
// Should render with default content
|
||||
expect(screen.getByText(/Mes Budgets Participatifs - Admin/)).toBeInTheDocument();
|
||||
expect(screen.getByRole('link', { name: /Paramètres/ })).toBeInTheDocument();
|
||||
expect(screen.getByRole('link', { name: /Déconnexion/ })).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should have proper icon structure', () => {
|
||||
render(<Navigation showBackButton={true} />);
|
||||
|
||||
// Vérifier que les icônes sont présentes (Lucide React icons)
|
||||
const backButton = screen.getByRole('link', { name: /Retour/ });
|
||||
const settingsButton = screen.getByRole('link', { name: /Paramètres/ });
|
||||
|
||||
// Les icônes sont des éléments SVG dans les liens
|
||||
expect(backButton.querySelector('svg')).toBeInTheDocument();
|
||||
expect(settingsButton.querySelector('svg')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user