mirror of
https://github.com/Dispatcharr/Dispatcharr.git
synced 2026-07-18 09:06:06 +00:00
Conforming to style guide
This commit is contained in:
parent
e95285ec8c
commit
e421c007cc
7 changed files with 339 additions and 136 deletions
|
|
@ -125,13 +125,17 @@ const mockFormValues = {
|
|||
|
||||
const makeFormMock = (overrides = {}) => ({
|
||||
getInputProps: vi.fn((field, opts) => {
|
||||
if (opts?.type === 'checkbox') return { checked: mockFormValues[field] ?? false, onChange: vi.fn() };
|
||||
if (opts?.type === 'checkbox')
|
||||
return { checked: mockFormValues[field] ?? false, onChange: vi.fn() };
|
||||
return { value: mockFormValues[field] ?? '', onChange: vi.fn() };
|
||||
}),
|
||||
setValues: vi.fn(),
|
||||
setFieldValue: vi.fn(),
|
||||
getValues: vi.fn(() => mockFormValues),
|
||||
onSubmit: vi.fn((handler) => (e) => { e?.preventDefault?.(); return handler(); }),
|
||||
onSubmit: vi.fn((handler) => (e) => {
|
||||
e?.preventDefault?.();
|
||||
return handler();
|
||||
}),
|
||||
...overrides,
|
||||
});
|
||||
|
||||
|
|
@ -229,7 +233,9 @@ describe('DvrSettingsForm', () => {
|
|||
expect(screen.getByTestId('tv_template')).toBeInTheDocument();
|
||||
expect(screen.getByTestId('tv_fallback_template')).toBeInTheDocument();
|
||||
expect(screen.getByTestId('movie_template')).toBeInTheDocument();
|
||||
expect(screen.getByTestId('movie_fallback_template')).toBeInTheDocument();
|
||||
expect(
|
||||
screen.getByTestId('movie_fallback_template')
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
|
|
@ -250,7 +256,9 @@ describe('DvrSettingsForm', () => {
|
|||
it('shows "No custom comskip.ini uploaded." when no config exists', async () => {
|
||||
render(<DvrSettingsForm active={true} />);
|
||||
await waitFor(() => {
|
||||
expect(screen.getByText('No custom comskip.ini uploaded.')).toBeInTheDocument();
|
||||
expect(
|
||||
screen.getByText('No custom comskip.ini uploaded.')
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
|
|
@ -261,7 +269,9 @@ describe('DvrSettingsForm', () => {
|
|||
});
|
||||
render(<DvrSettingsForm active={true} />);
|
||||
await waitFor(() => {
|
||||
expect(screen.getByText('Using /app/docker/comskip.ini')).toBeInTheDocument();
|
||||
expect(
|
||||
screen.getByText('Using /app/docker/comskip.ini')
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
@ -306,7 +316,9 @@ describe('DvrSettingsForm', () => {
|
|||
|
||||
it('handles getComskipConfig error gracefully', async () => {
|
||||
vi.mocked(getComskipConfig).mockRejectedValue(new Error('network error'));
|
||||
const consoleSpy = vi.spyOn(console, 'error').mockImplementation(() => {});
|
||||
const consoleSpy = vi
|
||||
.spyOn(console, 'error')
|
||||
.mockImplementation(() => {});
|
||||
render(<DvrSettingsForm active={true} />);
|
||||
await waitFor(() => {
|
||||
expect(consoleSpy).toHaveBeenCalledWith(
|
||||
|
|
@ -357,8 +369,13 @@ describe('DvrSettingsForm', () => {
|
|||
fireEvent.submit(screen.getByText('Save').closest('form'));
|
||||
|
||||
await waitFor(() => {
|
||||
expect(getChangedSettings).toHaveBeenCalledWith(mockFormValues, makeSettings());
|
||||
expect(saveChangedSettings).toHaveBeenCalledWith(makeSettings(), { pre_offset_minutes: 5 });
|
||||
expect(getChangedSettings).toHaveBeenCalledWith(
|
||||
mockFormValues,
|
||||
makeSettings()
|
||||
);
|
||||
expect(saveChangedSettings).toHaveBeenCalledWith(makeSettings(), {
|
||||
pre_offset_minutes: 5,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
|
@ -373,8 +390,12 @@ describe('DvrSettingsForm', () => {
|
|||
});
|
||||
|
||||
it('does not show success alert when saveChangedSettings throws', async () => {
|
||||
vi.mocked(saveChangedSettings).mockRejectedValue(new Error('save failed'));
|
||||
const consoleSpy = vi.spyOn(console, 'error').mockImplementation(() => {});
|
||||
vi.mocked(saveChangedSettings).mockRejectedValue(
|
||||
new Error('save failed')
|
||||
);
|
||||
const consoleSpy = vi
|
||||
.spyOn(console, 'error')
|
||||
.mockImplementation(() => {});
|
||||
|
||||
render(<DvrSettingsForm active={true} />);
|
||||
fireEvent.submit(screen.getByText('Save').closest('form'));
|
||||
|
|
@ -400,11 +421,17 @@ describe('DvrSettingsForm', () => {
|
|||
});
|
||||
|
||||
it('calls uploadComskipIni with the selected file', async () => {
|
||||
const mockFile = new File(['content'], 'comskip.ini', { type: 'text/plain' });
|
||||
vi.mocked(uploadComskipIni).mockResolvedValue({ path: '/uploaded/comskip.ini' });
|
||||
const mockFile = new File(['content'], 'comskip.ini', {
|
||||
type: 'text/plain',
|
||||
});
|
||||
vi.mocked(uploadComskipIni).mockResolvedValue({
|
||||
path: '/uploaded/comskip.ini',
|
||||
});
|
||||
|
||||
render(<DvrSettingsForm active={true} />);
|
||||
fireEvent.change(screen.getByTestId('file-input'), { target: { files: [mockFile] } });
|
||||
fireEvent.change(screen.getByTestId('file-input'), {
|
||||
target: { files: [mockFile] },
|
||||
});
|
||||
|
||||
await waitFor(() => {
|
||||
fireEvent.click(screen.getByText('Upload comskip.ini'));
|
||||
|
|
@ -416,11 +443,17 @@ describe('DvrSettingsForm', () => {
|
|||
});
|
||||
|
||||
it('shows success notification after successful upload', async () => {
|
||||
const mockFile = new File(['content'], 'comskip.ini', { type: 'text/plain' });
|
||||
vi.mocked(uploadComskipIni).mockResolvedValue({ path: '/uploaded/comskip.ini' });
|
||||
const mockFile = new File(['content'], 'comskip.ini', {
|
||||
type: 'text/plain',
|
||||
});
|
||||
vi.mocked(uploadComskipIni).mockResolvedValue({
|
||||
path: '/uploaded/comskip.ini',
|
||||
});
|
||||
|
||||
render(<DvrSettingsForm active={true} />);
|
||||
fireEvent.change(screen.getByTestId('file-input'), { target: { files: [mockFile] } });
|
||||
fireEvent.change(screen.getByTestId('file-input'), {
|
||||
target: { files: [mockFile] },
|
||||
});
|
||||
|
||||
await waitFor(() => {
|
||||
fireEvent.click(screen.getByText('Upload comskip.ini'));
|
||||
|
|
@ -428,17 +461,26 @@ describe('DvrSettingsForm', () => {
|
|||
|
||||
await waitFor(() => {
|
||||
expect(showNotification).toHaveBeenCalledWith(
|
||||
expect.objectContaining({ title: 'comskip.ini uploaded', color: 'green' })
|
||||
expect.objectContaining({
|
||||
title: 'comskip.ini uploaded',
|
||||
color: 'green',
|
||||
})
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
it('sets comskip_custom_path form field after successful upload', async () => {
|
||||
const mockFile = new File(['content'], 'comskip.ini', { type: 'text/plain' });
|
||||
vi.mocked(uploadComskipIni).mockResolvedValue({ path: '/uploaded/comskip.ini' });
|
||||
const mockFile = new File(['content'], 'comskip.ini', {
|
||||
type: 'text/plain',
|
||||
});
|
||||
vi.mocked(uploadComskipIni).mockResolvedValue({
|
||||
path: '/uploaded/comskip.ini',
|
||||
});
|
||||
|
||||
render(<DvrSettingsForm active={true} />);
|
||||
fireEvent.change(screen.getByTestId('file-input'), { target: { files: [mockFile] } });
|
||||
fireEvent.change(screen.getByTestId('file-input'), {
|
||||
target: { files: [mockFile] },
|
||||
});
|
||||
|
||||
await waitFor(() => {
|
||||
fireEvent.click(screen.getByText('Upload comskip.ini'));
|
||||
|
|
@ -453,12 +495,18 @@ describe('DvrSettingsForm', () => {
|
|||
});
|
||||
|
||||
it('handles upload error gracefully', async () => {
|
||||
const mockFile = new File(['content'], 'comskip.ini', { type: 'text/plain' });
|
||||
const mockFile = new File(['content'], 'comskip.ini', {
|
||||
type: 'text/plain',
|
||||
});
|
||||
vi.mocked(uploadComskipIni).mockRejectedValue(new Error('upload failed'));
|
||||
const consoleSpy = vi.spyOn(console, 'error').mockImplementation(() => {});
|
||||
const consoleSpy = vi
|
||||
.spyOn(console, 'error')
|
||||
.mockImplementation(() => {});
|
||||
|
||||
render(<DvrSettingsForm active={true} />);
|
||||
fireEvent.change(screen.getByTestId('file-input'), { target: { files: [mockFile] } });
|
||||
fireEvent.change(screen.getByTestId('file-input'), {
|
||||
target: { files: [mockFile] },
|
||||
});
|
||||
|
||||
await waitFor(() => {
|
||||
fireEvent.click(screen.getByText('Upload comskip.ini'));
|
||||
|
|
@ -480,4 +528,4 @@ describe('DvrSettingsForm', () => {
|
|||
expect(uploadComskipIni).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -64,7 +64,7 @@ vi.mock('@dnd-kit/modifiers', () => ({
|
|||
// Mock Mantine components
|
||||
vi.mock('@mantine/core', () => ({
|
||||
Box: ({ children, ...props }) => <div {...props}>{children}</div>,
|
||||
Button: ({ children, onClick, disabled, ...props }) => (
|
||||
Button: ({ children, onClick, disabled }) => (
|
||||
<button onClick={onClick} disabled={disabled} data-testid="reset-button">
|
||||
{children}
|
||||
</button>
|
||||
|
|
|
|||
|
|
@ -36,8 +36,12 @@ vi.mock('../../../ConfirmationDialog.jsx', () => ({
|
|||
<div data-testid="confirmation-dialog">
|
||||
<div data-testid="confirm-title">{title}</div>
|
||||
<div data-testid="confirm-message">{message}</div>
|
||||
<button data-testid="confirm-ok" onClick={onConfirm}>Confirm</button>
|
||||
<button data-testid="confirm-cancel" onClick={onClose}>Cancel</button>
|
||||
<button data-testid="confirm-ok" onClick={onConfirm}>
|
||||
Confirm
|
||||
</button>
|
||||
<button data-testid="confirm-cancel" onClick={onClose}>
|
||||
Cancel
|
||||
</button>
|
||||
</div>
|
||||
) : null,
|
||||
}));
|
||||
|
|
@ -85,7 +89,10 @@ vi.mock('@mantine/core', () => ({
|
|||
// ──────────────────────────────────────────────────────────────────────────────
|
||||
import useSettingsStore from '../../../../store/settings.jsx';
|
||||
import { useForm } from '@mantine/form';
|
||||
import { checkSetting, updateSetting } from '../../../../utils/pages/SettingsUtils.js';
|
||||
import {
|
||||
checkSetting,
|
||||
updateSetting,
|
||||
} from '../../../../utils/pages/SettingsUtils.js';
|
||||
import {
|
||||
getNetworkAccessFormInitialValues,
|
||||
getNetworkAccessFormValidation,
|
||||
|
|
@ -139,10 +146,15 @@ const setupMocks = ({ settings = makeSettings(), formOverrides = {} } = {}) => {
|
|||
const formMock = makeFormMock(formOverrides);
|
||||
|
||||
vi.mocked(useForm).mockReturnValue(formMock);
|
||||
vi.mocked(getNetworkAccessFormInitialValues).mockReturnValue(mockInitialValues);
|
||||
vi.mocked(getNetworkAccessFormInitialValues).mockReturnValue(
|
||||
mockInitialValues
|
||||
);
|
||||
vi.mocked(getNetworkAccessFormValidation).mockReturnValue({});
|
||||
vi.mocked(getNetworkAccessDefaults).mockReturnValue(mockInitialValues);
|
||||
vi.mocked(checkSetting).mockResolvedValue({ client_ip: '192.168.1.1', UI: ['192.168.0.0/16'] });
|
||||
vi.mocked(checkSetting).mockResolvedValue({
|
||||
client_ip: '192.168.1.1',
|
||||
UI: ['192.168.0.0/16'],
|
||||
});
|
||||
vi.mocked(updateSetting).mockResolvedValue(undefined);
|
||||
|
||||
vi.mocked(useSettingsStore).mockImplementation((sel) => sel({ settings }));
|
||||
|
|
@ -180,7 +192,9 @@ describe('NetworkAccessForm', () => {
|
|||
|
||||
it('does not show confirmation dialog on initial render', () => {
|
||||
render(<NetworkAccessForm active={true} />);
|
||||
expect(screen.queryByTestId('confirmation-dialog')).not.toBeInTheDocument();
|
||||
expect(
|
||||
screen.queryByTestId('confirmation-dialog')
|
||||
).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('does not show error alert on initial render', () => {
|
||||
|
|
@ -238,7 +252,10 @@ describe('NetworkAccessForm', () => {
|
|||
vi.mocked(updateSetting).mockResolvedValue(undefined);
|
||||
const { rerender } = render(<NetworkAccessForm active={true} />);
|
||||
|
||||
fireEvent.submit(screen.getByText('Save').closest('form') ?? screen.getByText('Save').closest('div'));
|
||||
fireEvent.submit(
|
||||
screen.getByText('Save').closest('form') ??
|
||||
screen.getByText('Save').closest('div')
|
||||
);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(screen.queryByTestId('confirmation-dialog')).not.toBeNull();
|
||||
|
|
@ -270,7 +287,9 @@ describe('NetworkAccessForm', () => {
|
|||
fireEvent.click(screen.getByTestId('confirm-cancel'));
|
||||
|
||||
await waitFor(() => {
|
||||
expect(screen.queryByTestId('confirmation-dialog')).not.toBeInTheDocument();
|
||||
expect(
|
||||
screen.queryByTestId('confirmation-dialog')
|
||||
).not.toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
|
|
@ -295,7 +314,9 @@ describe('NetworkAccessForm', () => {
|
|||
|
||||
await waitFor(() => {
|
||||
expect(screen.getByTestId('alert')).toBeInTheDocument();
|
||||
expect(screen.getByTestId('alert-title')).toHaveTextContent('Saved Successfully');
|
||||
expect(screen.getByTestId('alert-title')).toHaveTextContent(
|
||||
'Saved Successfully'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
|
|
@ -312,8 +333,9 @@ describe('NetworkAccessForm', () => {
|
|||
});
|
||||
|
||||
it('does not show success alert when updateSetting throws', async () => {
|
||||
vi.mocked(updateSetting).mockRejectedValue(
|
||||
{ body: { value: { m3u_custom_cidrs: 'Invalid CIDR' } } });
|
||||
vi.mocked(updateSetting).mockRejectedValue({
|
||||
body: { value: { m3u_custom_cidrs: 'Invalid CIDR' } },
|
||||
});
|
||||
render(<NetworkAccessForm active={true} />);
|
||||
fireEvent.click(screen.getByText('Save'));
|
||||
|
||||
|
|
@ -344,7 +366,9 @@ describe('NetworkAccessForm', () => {
|
|||
vi.mocked(checkSetting).mockResolvedValue(null);
|
||||
render(<NetworkAccessForm active={true} />);
|
||||
await waitFor(() => {
|
||||
expect(screen.queryByText(/\d+\.\d+\.\d+\.\d+/)).not.toBeInTheDocument();
|
||||
expect(
|
||||
screen.queryByText(/\d+\.\d+\.\d+\.\d+/)
|
||||
).not.toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
@ -352,9 +376,11 @@ describe('NetworkAccessForm', () => {
|
|||
// ── Network access error ───────────────────────────────────────────────────
|
||||
describe('network access error state', () => {
|
||||
it('clears error state after successful save', async () => {
|
||||
vi.mocked(checkSetting).mockResolvedValue(
|
||||
{ error: true, message: 'Invalid CIDR', data: 'Error details' }
|
||||
);
|
||||
vi.mocked(checkSetting).mockResolvedValue({
|
||||
error: true,
|
||||
message: 'Invalid CIDR',
|
||||
data: 'Error details',
|
||||
});
|
||||
|
||||
render(<NetworkAccessForm active={true} />);
|
||||
|
||||
|
|
@ -362,8 +388,10 @@ describe('NetworkAccessForm', () => {
|
|||
fireEvent.click(screen.getByText('Save'));
|
||||
await waitFor(() => screen.getByTestId('alert'));
|
||||
|
||||
vi.mocked(checkSetting).mockResolvedValue(
|
||||
{ client_ip: '192.168.1.1', UI: ['192.168.0.0/16'] });
|
||||
vi.mocked(checkSetting).mockResolvedValue({
|
||||
client_ip: '192.168.1.1',
|
||||
UI: ['192.168.0.0/16'],
|
||||
});
|
||||
|
||||
// Second save — succeeds
|
||||
fireEvent.click(screen.getByText('Save'));
|
||||
|
|
@ -371,8 +399,10 @@ describe('NetworkAccessForm', () => {
|
|||
fireEvent.click(screen.getByTestId('confirm-ok'));
|
||||
|
||||
await waitFor(() => {
|
||||
expect(screen.getByTestId('alert-title')).toHaveTextContent('Saved Successfully');
|
||||
expect(screen.getByTestId('alert-title')).toHaveTextContent(
|
||||
'Saved Successfully'
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -5,8 +5,14 @@ import ProxySettingsForm from '../ProxySettingsForm';
|
|||
// ── Constants mock ─────────────────────────────────────────────────────────────
|
||||
vi.mock('../../../../constants.js', () => ({
|
||||
PROXY_SETTINGS_OPTIONS: {
|
||||
buffering_timeout: { label: 'Buffering Timeout', description: 'Timeout in seconds' },
|
||||
buffering_speed: { label: 'Buffering Speed', description: 'Speed multiplier' },
|
||||
buffering_timeout: {
|
||||
label: 'Buffering Timeout',
|
||||
description: 'Timeout in seconds',
|
||||
},
|
||||
buffering_speed: {
|
||||
label: 'Buffering Speed',
|
||||
description: 'Speed multiplier',
|
||||
},
|
||||
redis_url: { label: 'Redis URL', description: 'Redis connection URL' },
|
||||
},
|
||||
}));
|
||||
|
|
@ -133,7 +139,9 @@ const setupMocks = ({ settings = makeSettings(), formOverrides = {} } = {}) => {
|
|||
const formMock = makeFormMock(formOverrides);
|
||||
|
||||
vi.mocked(useForm).mockReturnValue(formMock);
|
||||
vi.mocked(getProxySettingsFormInitialValues).mockReturnValue(mockInitialValues);
|
||||
vi.mocked(getProxySettingsFormInitialValues).mockReturnValue(
|
||||
mockInitialValues
|
||||
);
|
||||
vi.mocked(getProxySettingDefaults).mockReturnValue(mockDefaults);
|
||||
vi.mocked(updateSetting).mockResolvedValue({ success: true });
|
||||
vi.mocked(useSettingsStore).mockImplementation((sel) => sel({ settings }));
|
||||
|
|
@ -161,12 +169,16 @@ describe('ProxySettingsForm', () => {
|
|||
|
||||
it('renders NumberInput for buffering_timeout', () => {
|
||||
render(<ProxySettingsForm active={true} />);
|
||||
expect(screen.getByTestId('number-input-Buffering Timeout')).toBeInTheDocument();
|
||||
expect(
|
||||
screen.getByTestId('number-input-Buffering Timeout')
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('renders NumberInput for buffering_speed', () => {
|
||||
render(<ProxySettingsForm active={true} />);
|
||||
expect(screen.getByTestId('number-input-Buffering Speed')).toBeInTheDocument();
|
||||
expect(
|
||||
screen.getByTestId('number-input-Buffering Speed')
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('renders TextInput for redis_url', () => {
|
||||
|
|
@ -216,7 +228,9 @@ describe('ProxySettingsForm', () => {
|
|||
});
|
||||
|
||||
it('handles null settings gracefully', () => {
|
||||
vi.mocked(useSettingsStore).mockImplementation((sel) => sel({ settings: null }));
|
||||
vi.mocked(useSettingsStore).mockImplementation((sel) =>
|
||||
sel({ settings: null })
|
||||
);
|
||||
expect(() => render(<ProxySettingsForm active={true} />)).not.toThrow();
|
||||
});
|
||||
});
|
||||
|
|
@ -261,7 +275,9 @@ describe('ProxySettingsForm', () => {
|
|||
|
||||
await waitFor(() => {
|
||||
expect(screen.getByTestId('alert')).toBeInTheDocument();
|
||||
expect(screen.getByTestId('alert-title')).toHaveTextContent('Saved Successfully');
|
||||
expect(screen.getByTestId('alert-title')).toHaveTextContent(
|
||||
'Saved Successfully'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
|
|
@ -344,4 +360,4 @@ describe('ProxySettingsForm', () => {
|
|||
expect(formMock.getInputProps).toHaveBeenCalledWith('redis_url');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -35,16 +35,16 @@ vi.mock('@mantine/form', () => ({ useForm: vi.fn() }));
|
|||
// ── ConfirmationDialog mock ────────────────────────────────────────────────────
|
||||
vi.mock('../../../ConfirmationDialog.jsx', () => ({
|
||||
default: ({
|
||||
opened,
|
||||
onClose,
|
||||
onConfirm,
|
||||
title,
|
||||
message,
|
||||
confirmLabel,
|
||||
cancelLabel,
|
||||
actionKey,
|
||||
onSuppressChange,
|
||||
}) =>
|
||||
opened,
|
||||
onClose,
|
||||
onConfirm,
|
||||
title,
|
||||
message,
|
||||
confirmLabel,
|
||||
cancelLabel,
|
||||
actionKey,
|
||||
onSuppressChange,
|
||||
}) =>
|
||||
opened ? (
|
||||
<div data-testid="confirmation-dialog">
|
||||
<div data-testid="confirm-title">{title}</div>
|
||||
|
|
@ -98,7 +98,9 @@ vi.mock('@mantine/core', () => ({
|
|||
aria-label={label}
|
||||
multiple
|
||||
onChange={(e) => {
|
||||
const selected = Array.from(e.target.selectedOptions).map((o) => o.value);
|
||||
const selected = Array.from(e.target.selectedOptions).map(
|
||||
(o) => o.value
|
||||
);
|
||||
rest.onChange?.(selected);
|
||||
}}
|
||||
value={rest.value ?? []}
|
||||
|
|
@ -212,12 +214,12 @@ const makeStreamProfiles = () => [
|
|||
];
|
||||
|
||||
const setupMocks = ({
|
||||
settings = makeSettings(),
|
||||
formOverrides = {},
|
||||
warningSuppressed = false,
|
||||
userAgents = makeUserAgents(),
|
||||
streamProfiles = makeStreamProfiles(),
|
||||
} = {}) => {
|
||||
settings = makeSettings(),
|
||||
formOverrides = {},
|
||||
warningSuppressed = false,
|
||||
userAgents = makeUserAgents(),
|
||||
streamProfiles = makeStreamProfiles(),
|
||||
} = {}) => {
|
||||
const formMock = makeFormMock(formOverrides);
|
||||
|
||||
vi.mocked(useForm).mockReturnValue(formMock);
|
||||
|
|
@ -290,7 +292,9 @@ describe('StreamSettingsForm', () => {
|
|||
|
||||
it('renders the Auto-Import Mapped Files switch', () => {
|
||||
render(<StreamSettingsForm active={true} />);
|
||||
expect(screen.getByTestId('auto_import_mapped_files')).toBeInTheDocument();
|
||||
expect(
|
||||
screen.getByTestId('auto_import_mapped_files')
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('renders the M3U Hash Key multiselect', () => {
|
||||
|
|
@ -323,7 +327,9 @@ describe('StreamSettingsForm', () => {
|
|||
|
||||
it('does not show confirmation dialog on initial render', () => {
|
||||
render(<StreamSettingsForm active={true} />);
|
||||
expect(screen.queryByTestId('confirmation-dialog')).not.toBeInTheDocument();
|
||||
expect(
|
||||
screen.queryByTestId('confirmation-dialog')
|
||||
).not.toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
|
|
@ -429,13 +435,19 @@ describe('StreamSettingsForm', () => {
|
|||
fireEvent.submit(screen.getByText('Save').closest('form'));
|
||||
await waitFor(() => {
|
||||
expect(screen.getByTestId('alert')).toBeInTheDocument();
|
||||
expect(screen.getByTestId('alert-title')).toHaveTextContent('Saved Successfully');
|
||||
expect(screen.getByTestId('alert-title')).toHaveTextContent(
|
||||
'Saved Successfully'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
it('does not show success alert when saveChangedSettings throws', async () => {
|
||||
vi.mocked(saveChangedSettings).mockRejectedValue(new Error('save failed'));
|
||||
const consoleSpy = vi.spyOn(console, 'error').mockImplementation(() => {});
|
||||
vi.mocked(saveChangedSettings).mockRejectedValue(
|
||||
new Error('save failed')
|
||||
);
|
||||
const consoleSpy = vi
|
||||
.spyOn(console, 'error')
|
||||
.mockImplementation(() => {});
|
||||
render(<StreamSettingsForm active={true} />);
|
||||
|
||||
fireEvent.submit(screen.getByText('Save').closest('form'));
|
||||
|
|
@ -449,12 +461,17 @@ describe('StreamSettingsForm', () => {
|
|||
it('logs error when saveChangedSettings throws', async () => {
|
||||
const error = new Error('save failed');
|
||||
vi.mocked(saveChangedSettings).mockRejectedValue(error);
|
||||
const consoleSpy = vi.spyOn(console, 'error').mockImplementation(() => {});
|
||||
const consoleSpy = vi
|
||||
.spyOn(console, 'error')
|
||||
.mockImplementation(() => {});
|
||||
render(<StreamSettingsForm active={true} />);
|
||||
|
||||
fireEvent.submit(screen.getByText('Save').closest('form'));
|
||||
await waitFor(() => {
|
||||
expect(consoleSpy).toHaveBeenCalledWith('Error saving settings:', error);
|
||||
expect(consoleSpy).toHaveBeenCalledWith(
|
||||
'Error saving settings:',
|
||||
error
|
||||
);
|
||||
});
|
||||
consoleSpy.mockRestore();
|
||||
});
|
||||
|
|
@ -466,7 +483,9 @@ describe('StreamSettingsForm', () => {
|
|||
await waitFor(() => {
|
||||
expect(saveChangedSettings).toHaveBeenCalled();
|
||||
});
|
||||
expect(screen.queryByTestId('confirmation-dialog')).not.toBeInTheDocument();
|
||||
expect(
|
||||
screen.queryByTestId('confirmation-dialog')
|
||||
).not.toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
|
|
@ -501,7 +520,9 @@ describe('StreamSettingsForm', () => {
|
|||
|
||||
fireEvent.submit(screen.getByText('Save').closest('form'));
|
||||
await waitFor(() => {
|
||||
expect(screen.getByTestId('confirm-ok')).toHaveTextContent('Save and Rehash');
|
||||
expect(screen.getByTestId('confirm-ok')).toHaveTextContent(
|
||||
'Save and Rehash'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
|
|
@ -526,9 +547,7 @@ describe('StreamSettingsForm', () => {
|
|||
render(<StreamSettingsForm active={true} />);
|
||||
|
||||
fireEvent.submit(screen.getByText('Save').closest('form'));
|
||||
await waitFor(() =>
|
||||
screen.getByTestId('confirmation-dialog')
|
||||
);
|
||||
await waitFor(() => screen.getByTestId('confirmation-dialog'));
|
||||
fireEvent.click(screen.getByTestId('confirm-ok'));
|
||||
|
||||
await waitFor(() => {
|
||||
|
|
@ -546,7 +565,9 @@ describe('StreamSettingsForm', () => {
|
|||
fireEvent.click(screen.getByTestId('confirm-ok'));
|
||||
|
||||
await waitFor(() => {
|
||||
expect(screen.getByTestId('alert-title')).toHaveTextContent('Saved Successfully');
|
||||
expect(screen.getByTestId('alert-title')).toHaveTextContent(
|
||||
'Saved Successfully'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
|
|
@ -560,7 +581,9 @@ describe('StreamSettingsForm', () => {
|
|||
fireEvent.click(screen.getByTestId('confirm-ok'));
|
||||
|
||||
await waitFor(() => {
|
||||
expect(screen.queryByTestId('confirmation-dialog')).not.toBeInTheDocument();
|
||||
expect(
|
||||
screen.queryByTestId('confirmation-dialog')
|
||||
).not.toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
|
|
@ -574,7 +597,9 @@ describe('StreamSettingsForm', () => {
|
|||
fireEvent.click(screen.getByTestId('confirm-cancel'));
|
||||
|
||||
await waitFor(() => {
|
||||
expect(screen.queryByTestId('confirmation-dialog')).not.toBeInTheDocument();
|
||||
expect(
|
||||
screen.queryByTestId('confirmation-dialog')
|
||||
).not.toBeInTheDocument();
|
||||
});
|
||||
expect(saveChangedSettings).not.toHaveBeenCalled();
|
||||
});
|
||||
|
|
@ -590,7 +615,9 @@ describe('StreamSettingsForm', () => {
|
|||
await waitFor(() => {
|
||||
expect(saveChangedSettings).toHaveBeenCalled();
|
||||
});
|
||||
expect(screen.queryByTestId('confirmation-dialog')).not.toBeInTheDocument();
|
||||
expect(
|
||||
screen.queryByTestId('confirmation-dialog')
|
||||
).not.toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
|
|
@ -613,7 +640,9 @@ describe('StreamSettingsForm', () => {
|
|||
fireEvent.click(screen.getByText('Rehash Streams'));
|
||||
|
||||
await waitFor(() => {
|
||||
expect(screen.getByTestId('confirm-ok')).toHaveTextContent('Start Rehash');
|
||||
expect(screen.getByTestId('confirm-ok')).toHaveTextContent(
|
||||
'Start Rehash'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
|
|
@ -636,7 +665,9 @@ describe('StreamSettingsForm', () => {
|
|||
await waitFor(() => {
|
||||
expect(rehashStreams).toHaveBeenCalled();
|
||||
});
|
||||
expect(screen.queryByTestId('confirmation-dialog')).not.toBeInTheDocument();
|
||||
expect(
|
||||
screen.queryByTestId('confirmation-dialog')
|
||||
).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('shows rehash success alert after rehash completes', async () => {
|
||||
|
|
@ -654,7 +685,9 @@ describe('StreamSettingsForm', () => {
|
|||
it('does not show rehash success alert when rehashStreams throws', async () => {
|
||||
setupMocks({ warningSuppressed: true });
|
||||
vi.mocked(rehashStreams).mockRejectedValue(new Error('fail'));
|
||||
const consoleSpy = vi.spyOn(console, 'error').mockImplementation(() => {});
|
||||
const consoleSpy = vi
|
||||
.spyOn(console, 'error')
|
||||
.mockImplementation(() => {});
|
||||
render(<StreamSettingsForm active={true} />);
|
||||
fireEvent.click(screen.getByText('Rehash Streams'));
|
||||
|
||||
|
|
@ -669,12 +702,17 @@ describe('StreamSettingsForm', () => {
|
|||
setupMocks({ warningSuppressed: true });
|
||||
const error = new Error('network error');
|
||||
vi.mocked(rehashStreams).mockRejectedValue(error);
|
||||
const consoleSpy = vi.spyOn(console, 'error').mockImplementation(() => {});
|
||||
const consoleSpy = vi
|
||||
.spyOn(console, 'error')
|
||||
.mockImplementation(() => {});
|
||||
render(<StreamSettingsForm active={true} />);
|
||||
fireEvent.click(screen.getByText('Rehash Streams'));
|
||||
|
||||
await waitFor(() => {
|
||||
expect(consoleSpy).toHaveBeenCalledWith('Error rehashing streams:', error);
|
||||
expect(consoleSpy).toHaveBeenCalledWith(
|
||||
'Error rehashing streams:',
|
||||
error
|
||||
);
|
||||
});
|
||||
consoleSpy.mockRestore();
|
||||
});
|
||||
|
|
@ -686,7 +724,9 @@ describe('StreamSettingsForm', () => {
|
|||
fireEvent.click(screen.getByTestId('confirm-cancel'));
|
||||
|
||||
await waitFor(() => {
|
||||
expect(screen.queryByTestId('confirmation-dialog')).not.toBeInTheDocument();
|
||||
expect(
|
||||
screen.queryByTestId('confirmation-dialog')
|
||||
).not.toBeInTheDocument();
|
||||
});
|
||||
expect(rehashStreams).not.toHaveBeenCalled();
|
||||
});
|
||||
|
|
@ -710,7 +750,9 @@ describe('StreamSettingsForm', () => {
|
|||
it('Rehash Streams button is disabled while rehashing', async () => {
|
||||
let resolveRehash;
|
||||
vi.mocked(rehashStreams).mockReturnValue(
|
||||
new Promise((res) => { resolveRehash = res; })
|
||||
new Promise((res) => {
|
||||
resolveRehash = res;
|
||||
})
|
||||
);
|
||||
setupMocks({ warningSuppressed: true });
|
||||
render(<StreamSettingsForm active={true} />);
|
||||
|
|
@ -736,7 +778,9 @@ describe('StreamSettingsForm', () => {
|
|||
|
||||
it('calls getInputProps for default_stream_profile', () => {
|
||||
render(<StreamSettingsForm active={true} />);
|
||||
expect(formMock.getInputProps).toHaveBeenCalledWith('default_stream_profile');
|
||||
expect(formMock.getInputProps).toHaveBeenCalledWith(
|
||||
'default_stream_profile'
|
||||
);
|
||||
});
|
||||
|
||||
it('calls getInputProps for preferred_region', () => {
|
||||
|
|
@ -757,4 +801,4 @@ describe('StreamSettingsForm', () => {
|
|||
expect(formMock.getInputProps).toHaveBeenCalledWith('m3u_hash_key');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -53,7 +53,11 @@ vi.mock('@mantine/core', () => ({
|
|||
// Imports after mocks
|
||||
// ──────────────────────────────────────────────────────────────────────────────
|
||||
import useSettingsStore from '../../../../store/settings.jsx';
|
||||
import { getChangedSettings, parseSettings, saveChangedSettings } from '../../../../utils/pages/SettingsUtils.js';
|
||||
import {
|
||||
getChangedSettings,
|
||||
parseSettings,
|
||||
saveChangedSettings,
|
||||
} from '../../../../utils/pages/SettingsUtils.js';
|
||||
import { getSystemSettingsFormInitialValues } from '../../../../utils/forms/settings/SystemSettingsFormUtils.js';
|
||||
import { useForm } from '@mantine/form';
|
||||
|
||||
|
|
@ -83,7 +87,9 @@ const setupMocks = ({ settings = makeSettings() } = {}) => {
|
|||
vi.mocked(getSystemSettingsFormInitialValues).mockReturnValue(formValues);
|
||||
vi.mocked(useSettingsStore).mockImplementation((sel) => sel({ settings }));
|
||||
vi.mocked(parseSettings).mockReturnValue(formValues);
|
||||
vi.mocked(getChangedSettings).mockReturnValue({ max_system_events: settings?.max_system_events ?? 100 });
|
||||
vi.mocked(getChangedSettings).mockReturnValue({
|
||||
max_system_events: settings?.max_system_events ?? 100,
|
||||
});
|
||||
vi.mocked(saveChangedSettings).mockResolvedValue(undefined);
|
||||
|
||||
return { formMock };
|
||||
|
|
@ -122,7 +128,9 @@ describe('SystemSettingsForm', () => {
|
|||
setupMocks();
|
||||
render(<SystemSettingsForm active={true} />);
|
||||
expect(
|
||||
screen.getByText('Number of events to retain (minimum: 10, maximum: 1000)')
|
||||
screen.getByText(
|
||||
'Number of events to retain (minimum: 10, maximum: 1000)'
|
||||
)
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
|
||||
|
|
@ -184,7 +192,9 @@ describe('SystemSettingsForm', () => {
|
|||
const settings = makeSettings();
|
||||
const { formMock } = setupMocks({ settings });
|
||||
render(<SystemSettingsForm active={true} />);
|
||||
expect(formMock.setValues).toHaveBeenCalledWith({ max_system_events: 100 });
|
||||
expect(formMock.setValues).toHaveBeenCalledWith({
|
||||
max_system_events: 100,
|
||||
});
|
||||
});
|
||||
|
||||
it('does not call parseSettings when settings is null', () => {
|
||||
|
|
@ -197,8 +207,12 @@ describe('SystemSettingsForm', () => {
|
|||
submitting: false,
|
||||
};
|
||||
vi.mocked(useForm).mockReturnValue(formMock);
|
||||
vi.mocked(getSystemSettingsFormInitialValues).mockReturnValue({ max_system_events: 100 });
|
||||
vi.mocked(useSettingsStore).mockImplementation((sel) => sel({ settings: null }));
|
||||
vi.mocked(getSystemSettingsFormInitialValues).mockReturnValue({
|
||||
max_system_events: 100,
|
||||
});
|
||||
vi.mocked(useSettingsStore).mockImplementation((sel) =>
|
||||
sel({ settings: null })
|
||||
);
|
||||
vi.mocked(parseSettings).mockReturnValue({});
|
||||
vi.mocked(saveChangedSettings).mockResolvedValue(undefined);
|
||||
|
||||
|
|
@ -213,8 +227,13 @@ describe('SystemSettingsForm', () => {
|
|||
it('calls form.setFieldValue when NumberInput changes', () => {
|
||||
const { formMock } = setupMocks();
|
||||
render(<SystemSettingsForm active={true} />);
|
||||
fireEvent.change(screen.getByTestId('number-input'), { target: { value: '200' } });
|
||||
expect(formMock.setFieldValue).toHaveBeenCalledWith('max_system_events', 200);
|
||||
fireEvent.change(screen.getByTestId('number-input'), {
|
||||
target: { value: '200' },
|
||||
});
|
||||
expect(formMock.setFieldValue).toHaveBeenCalledWith(
|
||||
'max_system_events',
|
||||
200
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
|
|
@ -229,7 +248,10 @@ describe('SystemSettingsForm', () => {
|
|||
fireEvent.click(screen.getByText('Save'));
|
||||
|
||||
await waitFor(() => {
|
||||
expect(getChangedSettings).toHaveBeenCalledWith(formMock.getValues(), settings);
|
||||
expect(getChangedSettings).toHaveBeenCalledWith(
|
||||
formMock.getValues(),
|
||||
settings
|
||||
);
|
||||
expect(saveChangedSettings).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
|
@ -247,9 +269,13 @@ describe('SystemSettingsForm', () => {
|
|||
});
|
||||
|
||||
it('does not show success alert when saveChangedSettings throws', async () => {
|
||||
const consoleSpy = vi.spyOn(console, 'error').mockImplementation(() => {});
|
||||
const consoleSpy = vi
|
||||
.spyOn(console, 'error')
|
||||
.mockImplementation(() => {});
|
||||
setupMocks();
|
||||
vi.mocked(saveChangedSettings).mockRejectedValue(new Error('save failed'));
|
||||
vi.mocked(saveChangedSettings).mockRejectedValue(
|
||||
new Error('save failed')
|
||||
);
|
||||
|
||||
render(<SystemSettingsForm active={true} />);
|
||||
fireEvent.click(screen.getByText('Save'));
|
||||
|
|
@ -263,7 +289,9 @@ describe('SystemSettingsForm', () => {
|
|||
|
||||
it('logs error when saveChangedSettings throws', async () => {
|
||||
const error = new Error('save failed');
|
||||
const consoleSpy = vi.spyOn(console, 'error').mockImplementation(() => {});
|
||||
const consoleSpy = vi
|
||||
.spyOn(console, 'error')
|
||||
.mockImplementation(() => {});
|
||||
setupMocks();
|
||||
vi.mocked(saveChangedSettings).mockRejectedValue(error);
|
||||
|
||||
|
|
@ -271,7 +299,10 @@ describe('SystemSettingsForm', () => {
|
|||
fireEvent.click(screen.getByText('Save'));
|
||||
|
||||
await waitFor(() => {
|
||||
expect(consoleSpy).toHaveBeenCalledWith('Error saving settings:', error);
|
||||
expect(consoleSpy).toHaveBeenCalledWith(
|
||||
'Error saving settings:',
|
||||
error
|
||||
);
|
||||
});
|
||||
consoleSpy.mockRestore();
|
||||
});
|
||||
|
|
@ -308,4 +339,4 @@ describe('SystemSettingsForm', () => {
|
|||
expect(screen.getByTestId('alert')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -7,7 +7,9 @@ vi.mock('../../../../store/settings.jsx', () => ({ default: vi.fn() }));
|
|||
|
||||
// ── Hook mocks ─────────────────────────────────────────────────────────────────
|
||||
vi.mock('../../../../hooks/useLocalStorage.jsx', () => ({ default: vi.fn() }));
|
||||
vi.mock('../../../../hooks/useTablePreferences.jsx', () => ({ default: vi.fn() }));
|
||||
vi.mock('../../../../hooks/useTablePreferences.jsx', () => ({
|
||||
default: vi.fn(),
|
||||
}));
|
||||
|
||||
// ── Utility mocks ──────────────────────────────────────────────────────────────
|
||||
vi.mock('../../../../utils/dateTimeUtils.js', () => ({
|
||||
|
|
@ -62,7 +64,10 @@ vi.mock('@mantine/core', () => ({
|
|||
import useSettingsStore from '../../../../store/settings.jsx';
|
||||
import useLocalStorage from '../../../../hooks/useLocalStorage.jsx';
|
||||
import useTablePreferences from '../../../../hooks/useTablePreferences.jsx';
|
||||
import { buildTimeZoneOptions, getDefaultTimeZone } from '../../../../utils/dateTimeUtils.js';
|
||||
import {
|
||||
buildTimeZoneOptions,
|
||||
getDefaultTimeZone,
|
||||
} from '../../../../utils/dateTimeUtils.js';
|
||||
import { showNotification } from '../../../../utils/notificationUtils.js';
|
||||
import { saveTimeZoneSetting } from '../../../../utils/forms/settings/UiSettingsFormUtils.js';
|
||||
|
||||
|
|
@ -83,13 +88,13 @@ const TZ_OPTIONS = [
|
|||
];
|
||||
|
||||
const setupMocks = ({
|
||||
settings = makeSettings(),
|
||||
timeFormat = '12h',
|
||||
dateFormat = 'mdy',
|
||||
timeZone = DEFAULT_TZ,
|
||||
headerPinned = false,
|
||||
tableSize = 'default',
|
||||
} = {}) => {
|
||||
settings = makeSettings(),
|
||||
timeFormat = '12h',
|
||||
dateFormat = 'mdy',
|
||||
timeZone = DEFAULT_TZ,
|
||||
headerPinned = false,
|
||||
tableSize = 'default',
|
||||
} = {}) => {
|
||||
const setTimeFormat = vi.fn();
|
||||
const setDateFormat = vi.fn();
|
||||
const setTimeZone = vi.fn();
|
||||
|
|
@ -102,13 +107,12 @@ const setupMocks = ({
|
|||
|
||||
vi.mocked(useSettingsStore).mockImplementation((sel) => sel({ settings }));
|
||||
|
||||
vi.mocked(useLocalStorage)
|
||||
.mockImplementation((key, defaultVal) => {
|
||||
if (key === 'time-format') return [timeFormat, setTimeFormat];
|
||||
if (key === 'date-format') return [dateFormat, setDateFormat];
|
||||
if (key === 'time-zone') return [timeZone, setTimeZone];
|
||||
return [defaultVal, vi.fn()];
|
||||
});
|
||||
vi.mocked(useLocalStorage).mockImplementation((key, defaultVal) => {
|
||||
if (key === 'time-format') return [timeFormat, setTimeFormat];
|
||||
if (key === 'date-format') return [dateFormat, setDateFormat];
|
||||
if (key === 'time-zone') return [timeZone, setTimeZone];
|
||||
return [defaultVal, vi.fn()];
|
||||
});
|
||||
|
||||
vi.mocked(useTablePreferences).mockReturnValue({
|
||||
headerPinned,
|
||||
|
|
@ -117,7 +121,13 @@ const setupMocks = ({
|
|||
setTableSize,
|
||||
});
|
||||
|
||||
return { setTimeFormat, setDateFormat, setTimeZone, setHeaderPinned, setTableSize };
|
||||
return {
|
||||
setTimeFormat,
|
||||
setDateFormat,
|
||||
setTimeZone,
|
||||
setHeaderPinned,
|
||||
setTableSize,
|
||||
};
|
||||
};
|
||||
|
||||
// ──────────────────────────────────────────────────────────────────────────────
|
||||
|
|
@ -164,7 +174,9 @@ describe('UiSettingsForm', () => {
|
|||
it('renders the switch description', () => {
|
||||
setupMocks();
|
||||
render(<UiSettingsForm />);
|
||||
expect(screen.getByText('Keep table headers visible when scrolling')).toBeInTheDocument();
|
||||
expect(
|
||||
screen.getByText('Keep table headers visible when scrolling')
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('renders Table Size select with initial value', () => {
|
||||
|
|
@ -331,7 +343,10 @@ describe('UiSettingsForm', () => {
|
|||
});
|
||||
render(<UiSettingsForm />);
|
||||
await waitFor(() => {
|
||||
expect(saveTimeZoneSetting).toHaveBeenCalledWith(DEFAULT_TZ, makeSettings({ timeZone: null }));
|
||||
expect(saveTimeZoneSetting).toHaveBeenCalledWith(
|
||||
DEFAULT_TZ,
|
||||
makeSettings({ timeZone: null })
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
|
|
@ -359,9 +374,13 @@ describe('UiSettingsForm', () => {
|
|||
|
||||
describe('error handling', () => {
|
||||
it('shows error notification when saveTimeZoneSetting throws on tz change', async () => {
|
||||
const consoleSpy = vi.spyOn(console, 'error').mockImplementation(() => {});
|
||||
const consoleSpy = vi
|
||||
.spyOn(console, 'error')
|
||||
.mockImplementation(() => {});
|
||||
setupMocks({ settings: makeSettings({ timeZone: null }), timeZone: '' });
|
||||
vi.mocked(saveTimeZoneSetting).mockRejectedValue(new Error('network error'));
|
||||
vi.mocked(saveTimeZoneSetting).mockRejectedValue(
|
||||
new Error('network error')
|
||||
);
|
||||
|
||||
render(<UiSettingsForm />);
|
||||
fireEvent.change(screen.getByTestId('select-time-zone'), {
|
||||
|
|
@ -370,7 +389,10 @@ describe('UiSettingsForm', () => {
|
|||
|
||||
await waitFor(() => {
|
||||
expect(showNotification).toHaveBeenCalledWith(
|
||||
expect.objectContaining({ color: 'red', title: 'Failed to update time zone' })
|
||||
expect.objectContaining({
|
||||
color: 'red',
|
||||
title: 'Failed to update time zone',
|
||||
})
|
||||
);
|
||||
});
|
||||
consoleSpy.mockRestore();
|
||||
|
|
@ -378,7 +400,9 @@ describe('UiSettingsForm', () => {
|
|||
|
||||
it('logs error when saveTimeZoneSetting throws on tz change', async () => {
|
||||
const error = new Error('network error');
|
||||
const consoleSpy = vi.spyOn(console, 'error').mockImplementation(() => {});
|
||||
const consoleSpy = vi
|
||||
.spyOn(console, 'error')
|
||||
.mockImplementation(() => {});
|
||||
setupMocks({ settings: makeSettings({ timeZone: null }), timeZone: '' });
|
||||
vi.mocked(saveTimeZoneSetting).mockRejectedValue(error);
|
||||
|
||||
|
|
@ -397,15 +421,25 @@ describe('UiSettingsForm', () => {
|
|||
});
|
||||
|
||||
it('shows error notification when saveTimeZoneSetting throws during initial sync', async () => {
|
||||
const consoleSpy = vi.spyOn(console, 'error').mockImplementation(() => {});
|
||||
setupMocks({ settings: makeSettings({ timeZone: null }), timeZone: DEFAULT_TZ });
|
||||
vi.mocked(saveTimeZoneSetting).mockRejectedValue(new Error('sync failed'));
|
||||
const consoleSpy = vi
|
||||
.spyOn(console, 'error')
|
||||
.mockImplementation(() => {});
|
||||
setupMocks({
|
||||
settings: makeSettings({ timeZone: null }),
|
||||
timeZone: DEFAULT_TZ,
|
||||
});
|
||||
vi.mocked(saveTimeZoneSetting).mockRejectedValue(
|
||||
new Error('sync failed')
|
||||
);
|
||||
|
||||
render(<UiSettingsForm />);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(showNotification).toHaveBeenCalledWith(
|
||||
expect.objectContaining({ color: 'red', title: 'Failed to update time zone' })
|
||||
expect.objectContaining({
|
||||
color: 'red',
|
||||
title: 'Failed to update time zone',
|
||||
})
|
||||
);
|
||||
});
|
||||
consoleSpy.mockRestore();
|
||||
|
|
@ -421,4 +455,4 @@ describe('UiSettingsForm', () => {
|
|||
expect(buildTimeZoneOptions).toHaveBeenCalledWith('America/Chicago');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue