/** * Tests for Docker Section JavaScript */ import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest'; import { JSDOM } from 'jsdom'; // Mock fetch global.fetch = vi.fn(); const createTestDom = () => { const dom = new JSDOM(`
0
0
0
0
`); global.window = dom.window; global.document = dom.window.document; global.localStorage = { getItem: vi.fn(), setItem: vi.fn(), removeItem: vi.fn(), }; }; // Import docker section after DOM setup const dockerSection = { hosts: [], stats: {}, formatRelativeTime(dateStr) { if (!dateStr) return 'N/A'; const date = new Date(dateStr); const now = new Date(); const diffMs = now - date; const diffMins = Math.floor(diffMs / 60000); const diffHours = Math.floor(diffMins / 60); const diffDays = Math.floor(diffHours / 24); if (diffMins < 1) return 'À l\'instant'; if (diffMins < 60) return `Il y a ${diffMins}min`; if (diffHours < 24) return `Il y a ${diffHours}h`; return `Il y a ${diffDays}j`; }, formatBytes(bytes) { if (!bytes) return '0 B'; const k = 1024; const sizes = ['B', 'KB', 'MB', 'GB', 'TB']; const i = Math.floor(Math.log(bytes) / Math.log(k)); return parseFloat((bytes / Math.pow(k, i)).toFixed(1)) + ' ' + sizes[i]; }, renderHostCard(host) { const statusColor = host.docker_status === 'online' ? 'green' : host.docker_status === 'offline' ? 'red' : 'yellow'; return `

${host.host_name}

${host.docker_status}
${host.containers_running}/${host.containers_total} containers
`; }, renderHostsGrid() { const grid = document.getElementById('docker-hosts-grid'); if (!grid) return; if (this.hosts.length === 0) { grid.innerHTML = '
Aucun host Docker
'; return; } grid.innerHTML = this.hosts.map(host => this.renderHostCard(host)).join(''); }, updateStatsDisplay() { const el = (id, value) => { const elem = document.getElementById(id); if (elem) elem.textContent = value; }; el('docker-stat-hosts', this.stats.enabled_hosts || 0); el('docker-stat-containers', this.stats.running_containers || 0); el('docker-stat-images', this.stats.total_images || 0); el('docker-stat-alerts', this.stats.open_alerts || 0); }, filterHosts(query) { const cards = document.querySelectorAll('#docker-hosts-grid > div[data-host-id]'); const lowerQuery = query.toLowerCase(); cards.forEach(card => { const hostId = card.dataset.hostId; const host = this.hosts.find(h => h.host_id === hostId); if (host) { const matches = host.host_name.toLowerCase().includes(lowerQuery) || host.host_ip.toLowerCase().includes(lowerQuery); card.style.display = matches ? '' : 'none'; } }); } }; describe('Docker Section', () => { beforeEach(() => { createTestDom(); vi.clearAllMocks(); dockerSection.hosts = []; dockerSection.stats = {}; }); afterEach(() => { // Cleanup between tests if (global.document) { global.document.body.innerHTML = ''; } }); describe('formatRelativeTime', () => { it('returns N/A for null input', () => { expect(dockerSection.formatRelativeTime(null)).toBe('N/A'); }); it('returns "À l\'instant" for recent times', () => { const now = new Date().toISOString(); expect(dockerSection.formatRelativeTime(now)).toBe('À l\'instant'); }); it('returns minutes for times less than an hour ago', () => { const thirtyMinsAgo = new Date(Date.now() - 30 * 60 * 1000).toISOString(); expect(dockerSection.formatRelativeTime(thirtyMinsAgo)).toBe('Il y a 30min'); }); it('returns hours for times less than a day ago', () => { const fiveHoursAgo = new Date(Date.now() - 5 * 60 * 60 * 1000).toISOString(); expect(dockerSection.formatRelativeTime(fiveHoursAgo)).toBe('Il y a 5h'); }); it('returns days for older times', () => { const twoDaysAgo = new Date(Date.now() - 2 * 24 * 60 * 60 * 1000).toISOString(); expect(dockerSection.formatRelativeTime(twoDaysAgo)).toBe('Il y a 2j'); }); }); describe('formatBytes', () => { it('returns "0 B" for falsy input', () => { expect(dockerSection.formatBytes(0)).toBe('0 B'); expect(dockerSection.formatBytes(null)).toBe('0 B'); expect(dockerSection.formatBytes(undefined)).toBe('0 B'); }); it('formats bytes correctly', () => { expect(dockerSection.formatBytes(500)).toBe('500 B'); }); it('formats kilobytes correctly', () => { expect(dockerSection.formatBytes(1024)).toBe('1 KB'); expect(dockerSection.formatBytes(2048)).toBe('2 KB'); }); it('formats megabytes correctly', () => { expect(dockerSection.formatBytes(1024 * 1024)).toBe('1 MB'); expect(dockerSection.formatBytes(150 * 1024 * 1024)).toBe('150 MB'); }); it('formats gigabytes correctly', () => { expect(dockerSection.formatBytes(1024 * 1024 * 1024)).toBe('1 GB'); expect(dockerSection.formatBytes(2.5 * 1024 * 1024 * 1024)).toBe('2.5 GB'); }); }); describe('renderHostsGrid', () => { it('shows empty message when no hosts', () => { dockerSection.hosts = []; dockerSection.renderHostsGrid(); const grid = document.getElementById('docker-hosts-grid'); expect(grid.innerHTML).toContain('Aucun host Docker'); }); it('renders host cards for each host', () => { dockerSection.hosts = [ { host_id: 'h1', host_name: 'server1', host_ip: '192.168.1.10', docker_status: 'online', containers_total: 5, containers_running: 3 }, { host_id: 'h2', host_name: 'server2', host_ip: '192.168.1.11', docker_status: 'offline', containers_total: 2, containers_running: 0 } ]; dockerSection.renderHostsGrid(); const grid = document.getElementById('docker-hosts-grid'); expect(grid.querySelectorAll('[data-host-id]').length).toBe(2); }); }); describe('renderHostCard', () => { it('includes host name', () => { const host = { host_id: 'h1', host_name: 'myserver', host_ip: '192.168.1.10', docker_status: 'online', containers_total: 5, containers_running: 3 }; const html = dockerSection.renderHostCard(host); expect(html).toContain('myserver'); }); it('shows green status for online hosts', () => { const host = { host_id: 'h1', host_name: 'myserver', host_ip: '192.168.1.10', docker_status: 'online', containers_total: 5, containers_running: 3 }; const html = dockerSection.renderHostCard(host); expect(html).toContain('status-green'); }); it('shows red status for offline hosts', () => { const host = { host_id: 'h1', host_name: 'myserver', host_ip: '192.168.1.10', docker_status: 'offline', containers_total: 5, containers_running: 0 }; const html = dockerSection.renderHostCard(host); expect(html).toContain('status-red'); }); it('shows container counts', () => { const host = { host_id: 'h1', host_name: 'myserver', host_ip: '192.168.1.10', docker_status: 'online', containers_total: 10, containers_running: 7 }; const html = dockerSection.renderHostCard(host); expect(html).toContain('7/10 containers'); }); }); describe('updateStatsDisplay', () => { it('updates stat elements with values', () => { dockerSection.stats = { enabled_hosts: 5, running_containers: 25, total_images: 100, open_alerts: 3 }; dockerSection.updateStatsDisplay(); expect(document.getElementById('docker-stat-hosts').textContent).toBe('5'); expect(document.getElementById('docker-stat-containers').textContent).toBe('25'); expect(document.getElementById('docker-stat-images').textContent).toBe('100'); expect(document.getElementById('docker-stat-alerts').textContent).toBe('3'); }); it('shows 0 for missing stats', () => { dockerSection.stats = {}; dockerSection.updateStatsDisplay(); expect(document.getElementById('docker-stat-hosts').textContent).toBe('0'); expect(document.getElementById('docker-stat-containers').textContent).toBe('0'); }); }); describe('filterHosts', () => { beforeEach(() => { dockerSection.hosts = [ { host_id: 'h1', host_name: 'production-server', host_ip: '192.168.1.10', docker_status: 'online', containers_total: 5, containers_running: 3 }, { host_id: 'h2', host_name: 'staging-server', host_ip: '192.168.1.11', docker_status: 'online', containers_total: 2, containers_running: 2 }, { host_id: 'h3', host_name: 'dev-server', host_ip: '10.0.0.5', docker_status: 'offline', containers_total: 1, containers_running: 0 } ]; dockerSection.renderHostsGrid(); }); it('filters hosts by name', () => { dockerSection.filterHosts('production'); const cards = document.querySelectorAll('#docker-hosts-grid > div[data-host-id]'); const visibleCards = Array.from(cards).filter(c => c.style.display !== 'none'); expect(visibleCards.length).toBe(1); }); it('filters hosts by IP', () => { dockerSection.filterHosts('10.0.0'); const cards = document.querySelectorAll('#docker-hosts-grid > div[data-host-id]'); const visibleCards = Array.from(cards).filter(c => c.style.display !== 'none'); expect(visibleCards.length).toBe(1); }); it('shows all hosts with empty query', () => { dockerSection.filterHosts(''); const cards = document.querySelectorAll('#docker-hosts-grid > div[data-host-id]'); const visibleCards = Array.from(cards).filter(c => c.style.display !== 'none'); expect(visibleCards.length).toBe(3); }); it('is case insensitive', () => { dockerSection.filterHosts('STAGING'); const cards = document.querySelectorAll('#docker-hosts-grid > div[data-host-id]'); const visibleCards = Array.from(cards).filter(c => c.style.display !== 'none'); expect(visibleCards.length).toBe(1); }); }); });