151 lines
5.3 KiB
TypeScript
151 lines
5.3 KiB
TypeScript
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
import { screen, fireEvent, waitFor } from '@testing-library/react';
|
|
import '@testing-library/jest-dom';
|
|
import SleepButton from '../../src/components/tracker/SleepButton';
|
|
import { useSleepSession } from '../../src/hooks/useSleepSession';
|
|
import { renderWithProviders } from '../test-utils';
|
|
|
|
vi.mock('../../src/hooks/useSleepSession', () => ({
|
|
useSleepSession: vi.fn(),
|
|
}));
|
|
|
|
describe('SleepButton', () => {
|
|
beforeEach(() => {
|
|
vi.clearAllMocks();
|
|
});
|
|
|
|
it('renders "Start Sleep" when no active session', async () => {
|
|
vi.mocked(useSleepSession).mockReturnValue({
|
|
activeSession: null,
|
|
isCreating: false,
|
|
isEnding: false,
|
|
} as any);
|
|
|
|
renderWithProviders(<SleepButton time="2024-01-01T12:00" />);
|
|
expect(screen.getByRole('button', { name: /Start Sleep/i })).toBeInTheDocument();
|
|
});
|
|
|
|
it('renders "Stop Sleep" when session is active', async () => {
|
|
vi.mocked(useSleepSession).mockReturnValue({
|
|
activeSession: { id: 1, start_time: '2024-01-01T12:00' },
|
|
isCreating: false,
|
|
isEnding: false,
|
|
} as any);
|
|
|
|
renderWithProviders(<SleepButton time="2024-01-01T12:00" />);
|
|
expect(screen.getByRole('button', { name: /Stop Sleep/i })).toBeInTheDocument();
|
|
});
|
|
|
|
it('calls createSession when no active session and button is clicked', async () => {
|
|
const createSessionMock = vi.fn();
|
|
vi.mocked(useSleepSession).mockReturnValue({
|
|
activeSession: null,
|
|
isCreating: false,
|
|
isEnding: false,
|
|
createSession: createSessionMock,
|
|
} as any);
|
|
|
|
renderWithProviders(<SleepButton time="2024-01-01T12:00" />);
|
|
const button = screen.getByRole('button', { name: /Start Sleep/i });
|
|
fireEvent.click(button);
|
|
|
|
await waitFor(() => expect(createSessionMock).toHaveBeenCalledWith({ start_time: '2024-01-01T12:00' }));
|
|
});
|
|
|
|
it('calls endSession when session is active and button is clicked', async () => {
|
|
const endSessionMock = vi.fn();
|
|
vi.mocked(useSleepSession).mockReturnValue({
|
|
activeSession: { id: 1, start_time: '2024-01-01T12:00' },
|
|
isCreating: false,
|
|
isEnding: false,
|
|
endSession: endSessionMock,
|
|
} as any);
|
|
|
|
renderWithProviders(<SleepButton time="2024-01-01T14:00" />);
|
|
const button = screen.getByRole('button', { name: /Stop Sleep/i });
|
|
fireEvent.click(button);
|
|
|
|
await waitFor(() => expect(endSessionMock).toHaveBeenCalledWith({ sessionId: 1, endTime: '2024-01-01T14:00' }));
|
|
});
|
|
|
|
it('handles endSession error gracefully', async () => {
|
|
const consoleSpy = vi.spyOn(console, 'error').mockImplementation(() => {});
|
|
const endSessionMock = vi.fn().mockRejectedValue(new Error('Failed to stop'));
|
|
vi.mocked(useSleepSession).mockReturnValue({
|
|
activeSession: { id: 1, start_time: '2024-01-01T12:00' },
|
|
isCreating: false,
|
|
isEnding: false,
|
|
endSession: endSessionMock,
|
|
} as any);
|
|
|
|
renderWithProviders(<SleepButton time="2024-01-01T14:00" />);
|
|
const button = screen.getByRole('button', { name: /Stop Sleep/i });
|
|
fireEvent.click(button);
|
|
|
|
await waitFor(() => expect(consoleSpy).toHaveBeenCalledWith('Failed to update sleep session:', 'Failed to stop'));
|
|
consoleSpy.mockRestore();
|
|
});
|
|
|
|
it('handles createSession error gracefully', async () => {
|
|
const consoleSpy = vi.spyOn(console, 'error').mockImplementation(() => {});
|
|
const createSessionMock = vi.fn().mockRejectedValue(new Error('Failed to start'));
|
|
vi.mocked(useSleepSession).mockReturnValue({
|
|
activeSession: null,
|
|
isCreating: false,
|
|
isEnding: false,
|
|
createSession: createSessionMock,
|
|
} as any);
|
|
|
|
renderWithProviders(<SleepButton time="2024-01-01T14:00" />);
|
|
const button = screen.getByRole('button', { name: /Start Sleep/i });
|
|
fireEvent.click(button);
|
|
|
|
await waitFor(() => expect(consoleSpy).toHaveBeenCalledWith('Failed to update sleep session:', 'Failed to start'));
|
|
consoleSpy.mockRestore();
|
|
});
|
|
|
|
it('shows alert when time is invalid', async () => {
|
|
const alertSpy = vi.spyOn(window, 'alert').mockImplementation(() => {});
|
|
vi.mocked(useSleepSession).mockReturnValue({
|
|
activeSession: null,
|
|
isCreating: false,
|
|
isEnding: false,
|
|
} as any);
|
|
|
|
renderWithProviders(<SleepButton time="" />);
|
|
const button = screen.getByRole('button', { name: /Start Sleep/i });
|
|
fireEvent.click(button);
|
|
|
|
expect(alertSpy).toHaveBeenCalledWith('Please select a valid time.');
|
|
alertSpy.mockRestore();
|
|
});
|
|
|
|
it('renders "Processing..." and disables button when isCreating is true', async () => {
|
|
vi.mocked(useSleepSession).mockReturnValue({
|
|
activeSession: null,
|
|
isCreating: true,
|
|
isEnding: false,
|
|
} as any);
|
|
|
|
renderWithProviders(<SleepButton time="2024-01-01T12:00" />);
|
|
const button = screen.getByRole('button');
|
|
|
|
expect(button).toBeDisabled();
|
|
expect(screen.getByText(/Processing.../i)).toBeInTheDocument();
|
|
});
|
|
|
|
it('renders "Processing..." and disables button when isEnding is true', async () => {
|
|
vi.mocked(useSleepSession).mockReturnValue({
|
|
activeSession: { id: 1, start_time: '2024-01-01T12:00' },
|
|
isCreating: false,
|
|
isEnding: true,
|
|
} as any);
|
|
|
|
renderWithProviders(<SleepButton time="2024-01-01T14:00" />);
|
|
const button = screen.getByRole('button');
|
|
|
|
expect(button).toBeDisabled();
|
|
expect(screen.getByText(/Processing.../i)).toBeInTheDocument();
|
|
});
|
|
});
|