/**
* 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
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);
});
});
});