Files
bambuddy/frontend/src/__tests__/components/PrinterQueueWidget.test.tsx
T
AneoPsy b477fbf46d Refactors date and file formatting utilities
refactor(utils): consolidate date and file size formatting

Extracts formatting logic into dedicated utility functions to improve
code maintainability and consistency across components.

Changes:
- Consolidate date formatting functions (formatRelativeTime, etc.)
- Consolidate file size formatting into single formatFileSize utility
- Fix file size calculation errors
- Update UI components to use new utilities
- Change "ASAP" to "Waiting" for unscheduled queue items

Tests:
- Add comprehensive unit tests for date utilities
- Add unit tests for file size formatting
2026-02-17 01:15:33 -10:00

131 lines
3.5 KiB
TypeScript

/**
* Tests for the PrinterQueueWidget component.
*
* This is a compact widget that shows "Next in queue" with the first pending
* item's name and a "+N" badge if there are more items. Returns null when empty.
*/
import { describe, it, expect, beforeEach } from 'vitest';
import { screen, waitFor } from '@testing-library/react';
import { render } from '../utils';
import { PrinterQueueWidget } from '../../components/PrinterQueueWidget';
import { http, HttpResponse } from 'msw';
import { server } from '../mocks/server';
const mockQueueItems = [
{
id: 1,
printer_id: 1,
archive_id: 1,
position: 1,
status: 'pending',
archive_name: 'First Print',
printer_name: 'X1 Carbon',
print_time_seconds: 3600,
scheduled_time: null,
},
{
id: 2,
printer_id: 1,
archive_id: 2,
position: 2,
status: 'pending',
archive_name: 'Second Print',
printer_name: 'X1 Carbon',
print_time_seconds: 7200,
scheduled_time: null,
},
];
describe('PrinterQueueWidget', () => {
beforeEach(() => {
server.use(
http.get('/api/v1/queue/', ({ request }) => {
const url = new URL(request.url);
const printerId = url.searchParams.get('printer_id');
if (printerId === '1') {
return HttpResponse.json(mockQueueItems);
}
return HttpResponse.json([]);
})
);
});
describe('rendering', () => {
it('shows next in queue label', async () => {
render(<PrinterQueueWidget printerId={1} />);
await waitFor(() => {
expect(screen.getByText('Next in queue')).toBeInTheDocument();
});
});
it('shows first pending item name', async () => {
render(<PrinterQueueWidget printerId={1} />);
await waitFor(() => {
expect(screen.getByText('First Print')).toBeInTheDocument();
});
});
it('shows additional items badge when multiple pending', async () => {
render(<PrinterQueueWidget printerId={1} />);
await waitFor(() => {
// Shows "+1" badge since there are 2 items
expect(screen.getByText('+1')).toBeInTheDocument();
});
});
it('shows Waiting for unscheduled items', async () => {
render(<PrinterQueueWidget printerId={1} />);
await waitFor(() => {
expect(screen.getByText('Waiting')).toBeInTheDocument();
});
});
});
describe('empty state', () => {
it('renders nothing when no pending items', async () => {
const { container } = render(<PrinterQueueWidget printerId={999} />);
// Wait for query to resolve
await waitFor(() => {
// Widget returns null when empty, so container should have no visible widget
expect(container.querySelector('a[href="/queue"]')).not.toBeInTheDocument();
});
});
});
describe('single item', () => {
it('does not show badge when only one item', async () => {
server.use(
http.get('/api/v1/queue/', () => {
return HttpResponse.json([mockQueueItems[0]]);
})
);
render(<PrinterQueueWidget printerId={1} />);
await waitFor(() => {
expect(screen.getByText('First Print')).toBeInTheDocument();
});
// Should not have a "+N" badge
expect(screen.queryByText(/^\+\d+$/)).not.toBeInTheDocument();
});
});
describe('link behavior', () => {
it('links to queue page', async () => {
render(<PrinterQueueWidget printerId={1} />);
await waitFor(() => {
const link = screen.getByRole('link');
expect(link).toHaveAttribute('href', '/queue');
});
});
});
});