/**
* @vitest-environment happy-dom
*/
import { describe, it, expect, beforeEach } from 'vitest';
import { render } from '@testing-library/react';
import React from 'react';
import { Stats } from '../../../components/parts/Stats.js';
import type { Statistics } from '../../../types.js';
import { Window } from 'happy-dom';
describe('Stats', () => {
beforeEach(() => {
// Setup happy-dom
const window = new Window();
globalThis.window = window as any;
globalThis.document = window.document as any;
});
const mockStats: Statistics = {
localCount: 10,
remoteCount: 8,
worktreeCount: 3,
changesCount: 2,
lastUpdated: new Date('2025-01-25T12:00:00Z'),
};
it('should render all statistics', () => {
const { getByText } = render();
expect(getByText(/Local:/)).toBeDefined();
expect(getByText(/10/)).toBeDefined();
expect(getByText(/Remote:/)).toBeDefined();
expect(getByText(/8/)).toBeDefined();
expect(getByText(/Worktrees:/)).toBeDefined();
expect(getByText(/3/)).toBeDefined();
expect(getByText(/Changes:/)).toBeDefined();
expect(getByText(/2/)).toBeDefined();
});
it('should render with zero counts', () => {
const zeroStats: Statistics = {
localCount: 0,
remoteCount: 0,
worktreeCount: 0,
changesCount: 0,
lastUpdated: new Date(),
};
const { getByText, getAllByText } = render();
expect(getByText(/Local:/)).toBeDefined();
const zeros = getAllByText(/0/);
expect(zeros.length).toBe(4); // All 4 counts are 0
});
it('should render in a horizontal layout', () => {
const { container } = render();
// Verify component renders without error
expect(container).toBeDefined();
});
it('should accept custom separator', () => {
const { getAllByText } = render();
const separators = getAllByText(/\|/);
expect(separators.length).toBeGreaterThan(0);
});
it('should handle large numbers', () => {
const largeStats: Statistics = {
localCount: 999,
remoteCount: 888,
worktreeCount: 777,
changesCount: 666,
lastUpdated: new Date(),
};
const { getByText } = render();
expect(getByText(/999/)).toBeDefined();
expect(getByText(/888/)).toBeDefined();
expect(getByText(/777/)).toBeDefined();
expect(getByText(/666/)).toBeDefined();
});
it('should display lastUpdated when provided', () => {
const now = new Date();
const lastUpdated = new Date(now.getTime() - 5000); // 5 seconds ago
const { getByText } = render();
expect(getByText(/Updated:/)).toBeDefined();
expect(getByText(/ago/)).toBeDefined();
});
it('should not display lastUpdated when null', () => {
const { queryByText } = render();
expect(queryByText(/Updated:/)).toBeNull();
});
it('should not display lastUpdated when not provided', () => {
const { queryByText } = render();
expect(queryByText(/Updated:/)).toBeNull();
});
it('should format relative time correctly (seconds)', () => {
const now = new Date();
const lastUpdated = new Date(now.getTime() - 30000); // 30 seconds ago
const { getByText } = render();
expect(getByText(/30s ago/)).toBeDefined();
});
it('should format relative time correctly (minutes)', () => {
const now = new Date();
const lastUpdated = new Date(now.getTime() - 120000); // 2 minutes ago
const { getByText } = render();
expect(getByText(/2m ago/)).toBeDefined();
});
it('should format relative time correctly (hours)', () => {
const now = new Date();
const lastUpdated = new Date(now.getTime() - 7200000); // 2 hours ago
const { getByText } = render();
expect(getByText(/2h ago/)).toBeDefined();
});
});