test: rewrite AutodraftSettings tests for three-state button group UI
The component was redesigned from a switch + radio buttons to Off/Next Pick/All Picks buttons with a separate queue-only Switch toggle. Updated 17 stale tests and added 5 new tests covering the queue-only toggle and the All Picks/Off button interactions. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
40e343d80f
commit
df28ab723d
1 changed files with 184 additions and 190 deletions
|
|
@ -25,239 +25,142 @@ describe('AutodraftSettings Component', () => {
|
|||
});
|
||||
|
||||
describe('Rendering', () => {
|
||||
it('should render the autodraft switch', () => {
|
||||
it('should render three autodraft state buttons', () => {
|
||||
render(<AutodraftSettings {...defaultProps} />);
|
||||
|
||||
expect(screen.getByText('Autodraft')).toBeInTheDocument();
|
||||
expect(screen.getByRole('switch')).toBeInTheDocument();
|
||||
|
||||
expect(screen.getByRole('button', { name: 'Off' })).toBeInTheDocument();
|
||||
expect(screen.getByRole('button', { name: 'Next Pick' })).toBeInTheDocument();
|
||||
expect(screen.getByRole('button', { name: 'All Picks' })).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should not show mode options when autodraft is disabled', () => {
|
||||
it('should not show the queue-only toggle when autodraft is Off', () => {
|
||||
render(<AutodraftSettings {...defaultProps} isEnabled={false} />);
|
||||
|
||||
expect(screen.queryByText('Next Pick')).not.toBeInTheDocument();
|
||||
expect(screen.queryByText('While On')).not.toBeInTheDocument();
|
||||
|
||||
expect(screen.queryByRole('switch')).not.toBeInTheDocument();
|
||||
expect(screen.queryByText('Only autodraft from queue')).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should show mode options when autodraft is enabled', () => {
|
||||
it('should show the queue-only toggle when autodraft is active', () => {
|
||||
render(<AutodraftSettings {...defaultProps} isEnabled={true} />);
|
||||
|
||||
expect(screen.getByText('Next Pick')).toBeInTheDocument();
|
||||
expect(screen.getByText('While On')).toBeInTheDocument();
|
||||
|
||||
expect(screen.getByRole('switch')).toBeInTheDocument();
|
||||
expect(screen.getByText('Only autodraft from queue')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should show disabled message when it is user turn', () => {
|
||||
it('should show disabled message when it is the user\'s turn', () => {
|
||||
render(<AutodraftSettings {...defaultProps} isMyTurn={true} />);
|
||||
|
||||
|
||||
expect(screen.getByText(/Autodraft settings are disabled during your pick/i)).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should mark Off as active when isEnabled=false', () => {
|
||||
render(<AutodraftSettings {...defaultProps} isEnabled={false} />);
|
||||
|
||||
const offButton = screen.getByRole('button', { name: 'Off' });
|
||||
expect(offButton.className).toContain('bg-electric');
|
||||
});
|
||||
|
||||
it('should mark Next Pick as active when isEnabled=true and mode=next_pick', () => {
|
||||
render(<AutodraftSettings {...defaultProps} isEnabled={true} mode="next_pick" />);
|
||||
|
||||
const nextPickButton = screen.getByRole('button', { name: 'Next Pick' });
|
||||
expect(nextPickButton.className).toContain('bg-electric');
|
||||
});
|
||||
|
||||
it('should mark All Picks as active when isEnabled=true and mode=while_on', () => {
|
||||
render(<AutodraftSettings {...defaultProps} isEnabled={true} mode="while_on" />);
|
||||
|
||||
const allPicksButton = screen.getByRole('button', { name: 'All Picks' });
|
||||
expect(allPicksButton.className).toContain('bg-electric');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Switch Toggle', () => {
|
||||
it('should enable autodraft when switch is toggled on', async () => {
|
||||
describe('Button Group Interaction', () => {
|
||||
it('should switch to Next Pick when that button is clicked', async () => {
|
||||
const onUpdate = vi.fn();
|
||||
render(<AutodraftSettings {...defaultProps} onUpdate={onUpdate} />);
|
||||
|
||||
const switchElement = screen.getByRole('switch');
|
||||
fireEvent.click(switchElement);
|
||||
render(<AutodraftSettings {...defaultProps} isEnabled={false} onUpdate={onUpdate} />);
|
||||
|
||||
fireEvent.click(screen.getByRole('button', { name: 'Next Pick' }));
|
||||
|
||||
await waitFor(() => {
|
||||
expect(global.fetch).toHaveBeenCalledWith(
|
||||
'/api/autodraft/update',
|
||||
expect.objectContaining({
|
||||
method: 'POST',
|
||||
})
|
||||
expect.objectContaining({ method: 'POST' })
|
||||
);
|
||||
});
|
||||
|
||||
await waitFor(() => {
|
||||
expect(onUpdate).toHaveBeenCalledWith(true, 'next_pick');
|
||||
expect(onUpdate).toHaveBeenCalledWith(true, 'next_pick', false);
|
||||
});
|
||||
});
|
||||
|
||||
it('should disable autodraft when switch is toggled off', async () => {
|
||||
it('should switch to All Picks when that button is clicked', async () => {
|
||||
const onUpdate = vi.fn();
|
||||
render(<AutodraftSettings {...defaultProps} isEnabled={false} onUpdate={onUpdate} />);
|
||||
|
||||
fireEvent.click(screen.getByRole('button', { name: 'All Picks' }));
|
||||
|
||||
await waitFor(() => {
|
||||
expect(onUpdate).toHaveBeenCalledWith(true, 'while_on', false);
|
||||
});
|
||||
});
|
||||
|
||||
it('should switch to Off when that button is clicked from an active state', async () => {
|
||||
const onUpdate = vi.fn();
|
||||
render(<AutodraftSettings {...defaultProps} isEnabled={true} onUpdate={onUpdate} />);
|
||||
|
||||
const switchElement = screen.getByRole('switch');
|
||||
fireEvent.click(switchElement);
|
||||
|
||||
fireEvent.click(screen.getByRole('button', { name: 'Off' }));
|
||||
|
||||
await waitFor(() => {
|
||||
expect(global.fetch).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
await waitFor(() => {
|
||||
expect(onUpdate).toHaveBeenCalledWith(false, 'next_pick');
|
||||
expect(onUpdate).toHaveBeenCalledWith(false, 'next_pick', false);
|
||||
});
|
||||
});
|
||||
|
||||
it('should be disabled when it is user turn', () => {
|
||||
it('should disable all buttons when it is the user\'s turn', () => {
|
||||
render(<AutodraftSettings {...defaultProps} isMyTurn={true} />);
|
||||
|
||||
const switchElement = screen.getByRole('switch');
|
||||
expect(switchElement).toBeDisabled();
|
||||
|
||||
expect(screen.getByRole('button', { name: 'Off' })).toBeDisabled();
|
||||
expect(screen.getByRole('button', { name: 'Next Pick' })).toBeDisabled();
|
||||
expect(screen.getByRole('button', { name: 'All Picks' })).toBeDisabled();
|
||||
});
|
||||
|
||||
it('should handle API errors gracefully', async () => {
|
||||
it('should not fire API call when a button is clicked during user\'s turn', () => {
|
||||
render(<AutodraftSettings {...defaultProps} isMyTurn={true} />);
|
||||
|
||||
fireEvent.click(screen.getByRole('button', { name: 'Next Pick' }));
|
||||
|
||||
expect(global.fetch).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should handle API errors by reverting state', async () => {
|
||||
const consoleSpy = vi.spyOn(console, 'error').mockImplementation(() => {});
|
||||
(global.fetch as any).mockResolvedValueOnce({
|
||||
ok: false,
|
||||
json: async () => ({ error: 'Server error' }),
|
||||
});
|
||||
|
||||
render(<AutodraftSettings {...defaultProps} />);
|
||||
|
||||
const switchElement = screen.getByRole('switch');
|
||||
fireEvent.click(switchElement);
|
||||
render(<AutodraftSettings {...defaultProps} isEnabled={false} />);
|
||||
|
||||
fireEvent.click(screen.getByRole('button', { name: 'Next Pick' }));
|
||||
|
||||
await waitFor(() => {
|
||||
expect(consoleSpy).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
// Switch should revert to original state
|
||||
expect(switchElement).not.toBeChecked();
|
||||
// Off button should still be active (reverted)
|
||||
const offButton = screen.getByRole('button', { name: 'Off' });
|
||||
expect(offButton.className).toContain('bg-electric');
|
||||
|
||||
consoleSpy.mockRestore();
|
||||
});
|
||||
});
|
||||
|
||||
describe('Mode Selection', () => {
|
||||
it('should select next_pick mode by default', () => {
|
||||
render(<AutodraftSettings {...defaultProps} isEnabled={true} mode="next_pick" />);
|
||||
|
||||
const nextPickRadio = screen.getByRole('radio', { name: /next pick/i });
|
||||
expect(nextPickRadio).toBeChecked();
|
||||
});
|
||||
|
||||
it('should select while_on mode when specified', () => {
|
||||
render(<AutodraftSettings {...defaultProps} isEnabled={true} mode="while_on" />);
|
||||
|
||||
const whileOnRadio = screen.getByRole('radio', { name: /while on/i });
|
||||
expect(whileOnRadio).toBeChecked();
|
||||
});
|
||||
|
||||
it('should change mode when radio button is clicked', async () => {
|
||||
const onUpdate = vi.fn();
|
||||
render(<AutodraftSettings {...defaultProps} isEnabled={true} mode="next_pick" onUpdate={onUpdate} />);
|
||||
|
||||
const whileOnRadio = screen.getByRole('radio', { name: /while on/i });
|
||||
fireEvent.click(whileOnRadio);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(global.fetch).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
await waitFor(() => {
|
||||
expect(onUpdate).toHaveBeenCalledWith(true, 'while_on');
|
||||
});
|
||||
});
|
||||
|
||||
it('should disable mode selection when it is user turn', () => {
|
||||
render(<AutodraftSettings {...defaultProps} isEnabled={true} isMyTurn={true} />);
|
||||
|
||||
const nextPickRadio = screen.getByRole('radio', { name: /next pick/i });
|
||||
const whileOnRadio = screen.getByRole('radio', { name: /while on/i });
|
||||
|
||||
expect(nextPickRadio).toBeDisabled();
|
||||
expect(whileOnRadio).toBeDisabled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('API Integration', () => {
|
||||
it('should send correct data when enabling autodraft', async () => {
|
||||
render(<AutodraftSettings {...defaultProps} />);
|
||||
|
||||
const switchElement = screen.getByRole('switch');
|
||||
fireEvent.click(switchElement);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(global.fetch).toHaveBeenCalledWith(
|
||||
'/api/autodraft/update',
|
||||
expect.objectContaining({
|
||||
method: 'POST',
|
||||
body: expect.any(FormData),
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
const fetchCall = (global.fetch as any).mock.calls[0];
|
||||
const formData = fetchCall[1].body as FormData;
|
||||
|
||||
expect(formData.get('seasonId')).toBe('season-123');
|
||||
expect(formData.get('teamId')).toBe('team-456');
|
||||
expect(formData.get('isEnabled')).toBe('true');
|
||||
expect(formData.get('mode')).toBe('next_pick');
|
||||
});
|
||||
|
||||
it('should send correct data when changing mode', async () => {
|
||||
render(<AutodraftSettings {...defaultProps} isEnabled={true} mode="next_pick" />);
|
||||
|
||||
const whileOnRadio = screen.getByRole('radio', { name: /while on/i });
|
||||
fireEvent.click(whileOnRadio);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(global.fetch).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
const fetchCall = (global.fetch as any).mock.calls[0];
|
||||
const formData = fetchCall[1].body as FormData;
|
||||
|
||||
expect(formData.get('mode')).toBe('while_on');
|
||||
expect(formData.get('isEnabled')).toBe('true');
|
||||
});
|
||||
|
||||
it('should show loading state during API call', async () => {
|
||||
let resolvePromise: any;
|
||||
const fetchPromise = new Promise((resolve) => {
|
||||
resolvePromise = resolve;
|
||||
});
|
||||
(global.fetch as any).mockReturnValueOnce(fetchPromise);
|
||||
|
||||
render(<AutodraftSettings {...defaultProps} />);
|
||||
|
||||
const switchElement = screen.getByRole('switch');
|
||||
fireEvent.click(switchElement);
|
||||
|
||||
// Switch should be disabled during update
|
||||
await waitFor(() => {
|
||||
expect(switchElement).toBeDisabled();
|
||||
});
|
||||
|
||||
// Resolve the promise
|
||||
resolvePromise({ ok: true, json: async () => ({ success: true }) });
|
||||
|
||||
// Switch should be enabled again
|
||||
await waitFor(() => {
|
||||
expect(switchElement).not.toBeDisabled();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Edge Cases', () => {
|
||||
it('should handle rapid toggle clicks', async () => {
|
||||
render(<AutodraftSettings {...defaultProps} />);
|
||||
|
||||
const switchElement = screen.getByRole('switch');
|
||||
|
||||
// Click multiple times rapidly
|
||||
fireEvent.click(switchElement);
|
||||
fireEvent.click(switchElement);
|
||||
fireEvent.click(switchElement);
|
||||
|
||||
// Should only process the first click while updating
|
||||
await waitFor(() => {
|
||||
expect(global.fetch).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
});
|
||||
|
||||
it('should handle network errors', async () => {
|
||||
it('should handle network errors by reverting state', async () => {
|
||||
const consoleSpy = vi.spyOn(console, 'error').mockImplementation(() => {});
|
||||
(global.fetch as any).mockRejectedValueOnce(new Error('Network error'));
|
||||
|
||||
render(<AutodraftSettings {...defaultProps} />);
|
||||
|
||||
const switchElement = screen.getByRole('switch');
|
||||
fireEvent.click(switchElement);
|
||||
|
||||
fireEvent.click(screen.getByRole('button', { name: 'Next Pick' }));
|
||||
|
||||
await waitFor(() => {
|
||||
expect(consoleSpy).toHaveBeenCalled();
|
||||
|
|
@ -265,23 +168,114 @@ describe('AutodraftSettings Component', () => {
|
|||
|
||||
consoleSpy.mockRestore();
|
||||
});
|
||||
});
|
||||
|
||||
it('should maintain state consistency on error', async () => {
|
||||
(global.fetch as any).mockResolvedValueOnce({
|
||||
ok: false,
|
||||
json: async () => ({ error: 'Server error' }),
|
||||
describe('Queue-Only Toggle', () => {
|
||||
it('should send queueOnly=true when the toggle is switched on', async () => {
|
||||
const onUpdate = vi.fn();
|
||||
render(<AutodraftSettings {...defaultProps} isEnabled={true} queueOnly={false} onUpdate={onUpdate} />);
|
||||
|
||||
fireEvent.click(screen.getByRole('switch'));
|
||||
|
||||
await waitFor(() => {
|
||||
expect(onUpdate).toHaveBeenCalledWith(true, 'next_pick', true);
|
||||
});
|
||||
});
|
||||
|
||||
it('should send queueOnly=false when the toggle is switched off', async () => {
|
||||
const onUpdate = vi.fn();
|
||||
render(<AutodraftSettings {...defaultProps} isEnabled={true} queueOnly={true} onUpdate={onUpdate} />);
|
||||
|
||||
fireEvent.click(screen.getByRole('switch'));
|
||||
|
||||
await waitFor(() => {
|
||||
expect(onUpdate).toHaveBeenCalledWith(true, 'next_pick', false);
|
||||
});
|
||||
});
|
||||
|
||||
it('should disable the queue-only toggle when it is the user\'s turn', () => {
|
||||
render(<AutodraftSettings {...defaultProps} isEnabled={true} isMyTurn={true} />);
|
||||
|
||||
expect(screen.getByRole('switch')).toBeDisabled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('API Integration', () => {
|
||||
it('should post correct formData when switching to Next Pick', async () => {
|
||||
render(<AutodraftSettings {...defaultProps} isEnabled={false} />);
|
||||
|
||||
fireEvent.click(screen.getByRole('button', { name: 'Next Pick' }));
|
||||
|
||||
await waitFor(() => {
|
||||
expect(global.fetch).toHaveBeenCalledWith(
|
||||
'/api/autodraft/update',
|
||||
expect.objectContaining({ method: 'POST', body: expect.any(FormData) })
|
||||
);
|
||||
});
|
||||
|
||||
render(<AutodraftSettings {...defaultProps} isEnabled={false} />);
|
||||
|
||||
const switchElement = screen.getByRole('switch');
|
||||
expect(switchElement).not.toBeChecked();
|
||||
|
||||
fireEvent.click(switchElement);
|
||||
const formData = (global.fetch as any).mock.calls[0][1].body as FormData;
|
||||
expect(formData.get('seasonId')).toBe('season-123');
|
||||
expect(formData.get('teamId')).toBe('team-456');
|
||||
expect(formData.get('isEnabled')).toBe('true');
|
||||
expect(formData.get('mode')).toBe('next_pick');
|
||||
expect(formData.get('queueOnly')).toBe('false');
|
||||
});
|
||||
|
||||
it('should post mode=while_on when switching to All Picks', async () => {
|
||||
render(<AutodraftSettings {...defaultProps} isEnabled={false} />);
|
||||
|
||||
fireEvent.click(screen.getByRole('button', { name: 'All Picks' }));
|
||||
|
||||
// Should revert to original state on error
|
||||
await waitFor(() => {
|
||||
expect(switchElement).not.toBeChecked();
|
||||
expect(global.fetch).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
const formData = (global.fetch as any).mock.calls[0][1].body as FormData;
|
||||
expect(formData.get('mode')).toBe('while_on');
|
||||
expect(formData.get('isEnabled')).toBe('true');
|
||||
});
|
||||
|
||||
it('should post isEnabled=false when switching to Off', async () => {
|
||||
render(<AutodraftSettings {...defaultProps} isEnabled={true} />);
|
||||
|
||||
fireEvent.click(screen.getByRole('button', { name: 'Off' }));
|
||||
|
||||
await waitFor(() => {
|
||||
expect(global.fetch).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
const formData = (global.fetch as any).mock.calls[0][1].body as FormData;
|
||||
expect(formData.get('isEnabled')).toBe('false');
|
||||
});
|
||||
|
||||
it('should disable buttons during an in-flight API call', async () => {
|
||||
let resolve: any;
|
||||
(global.fetch as any).mockReturnValueOnce(new Promise((r) => { resolve = r; }));
|
||||
|
||||
render(<AutodraftSettings {...defaultProps} />);
|
||||
|
||||
fireEvent.click(screen.getByRole('button', { name: 'Next Pick' }));
|
||||
|
||||
await waitFor(() => {
|
||||
expect(screen.getByRole('button', { name: 'Off' })).toBeDisabled();
|
||||
});
|
||||
|
||||
resolve({ ok: true, json: async () => ({ success: true }) });
|
||||
|
||||
await waitFor(() => {
|
||||
expect(screen.getByRole('button', { name: 'Off' })).not.toBeDisabled();
|
||||
});
|
||||
});
|
||||
|
||||
it('should only process the first click when buttons are clicked rapidly', async () => {
|
||||
render(<AutodraftSettings {...defaultProps} />);
|
||||
|
||||
fireEvent.click(screen.getByRole('button', { name: 'Next Pick' }));
|
||||
fireEvent.click(screen.getByRole('button', { name: 'All Picks' }));
|
||||
fireEvent.click(screen.getByRole('button', { name: 'Off' }));
|
||||
|
||||
await waitFor(() => {
|
||||
expect(global.fetch).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue