diff --git a/frontend/src/components/forms/settings/__tests__/StreamSettingsForm.test.jsx b/frontend/src/components/forms/settings/__tests__/StreamSettingsForm.test.jsx
index 25ee46aa..d960e498 100644
--- a/frontend/src/components/forms/settings/__tests__/StreamSettingsForm.test.jsx
+++ b/frontend/src/components/forms/settings/__tests__/StreamSettingsForm.test.jsx
@@ -7,6 +7,7 @@ vi.mock('../../../../store/settings.jsx', () => ({ default: vi.fn() }));
vi.mock('../../../../store/warnings.jsx', () => ({ default: vi.fn() }));
vi.mock('../../../../store/userAgents.jsx', () => ({ default: vi.fn() }));
vi.mock('../../../../store/streamProfiles.jsx', () => ({ default: vi.fn() }));
+vi.mock('../../../../store/outputProfiles.jsx', () => ({ default: vi.fn() }));
// ── Constants mock ─────────────────────────────────────────────────────────────
vi.mock('../../../../constants.js', () => ({
@@ -154,6 +155,7 @@ import useSettingsStore from '../../../../store/settings.jsx';
import useWarningsStore from '../../../../store/warnings.jsx';
import useUserAgentsStore from '../../../../store/userAgents.jsx';
import useStreamProfilesStore from '../../../../store/streamProfiles.jsx';
+import useOutputProfilesStore from '../../../../store/outputProfiles.jsx';
import { useForm } from '@mantine/form';
import {
getChangedSettings,
@@ -172,9 +174,8 @@ import {
const mockFormValues = {
default_user_agent: '1',
default_stream_profile: '2',
- preferred_region: 'us',
- auto_import_mapped_files: false,
m3u_hash_key: ['name'],
+ hdhr_output_profile_id: null,
};
const makeFormMock = (overrides = {}) => ({
@@ -184,6 +185,7 @@ const makeFormMock = (overrides = {}) => ({
}
return { value: mockFormValues[field] ?? '', onChange: vi.fn() };
}),
+ values: mockFormValues,
setValues: vi.fn(),
getValues: vi.fn(() => mockFormValues),
onSubmit: vi.fn((handler) => (e) => {
@@ -219,6 +221,7 @@ const setupMocks = ({
warningSuppressed = false,
userAgents = makeUserAgents(),
streamProfiles = makeStreamProfiles(),
+ outputProfiles = [],
} = {}) => {
const formMock = makeFormMock(formOverrides);
@@ -226,7 +229,7 @@ const setupMocks = ({
vi.mocked(getStreamSettingsFormInitialValues).mockReturnValue(mockFormValues);
vi.mocked(getStreamSettingsFormValidation).mockReturnValue({});
vi.mocked(parseSettings).mockReturnValue(mockFormValues);
- vi.mocked(getChangedSettings).mockReturnValue({ preferred_region: 'eu' });
+ vi.mocked(getChangedSettings).mockReturnValue({ default_user_agent: '1' });
vi.mocked(saveChangedSettings).mockResolvedValue(undefined);
vi.mocked(rehashStreams).mockResolvedValue(undefined);
@@ -243,6 +246,9 @@ const setupMocks = ({
vi.mocked(useStreamProfilesStore).mockImplementation((sel) =>
sel({ profiles: streamProfiles })
);
+ vi.mocked(useOutputProfilesStore).mockImplementation((sel) =>
+ sel({ profiles: outputProfiles })
+ );
return { formMock };
};
@@ -285,18 +291,6 @@ describe('StreamSettingsForm', () => {
expect(screen.getByTestId('default_stream_profile')).toBeInTheDocument();
});
- it('renders the Preferred Region select', () => {
- render();
- expect(screen.getByTestId('preferred_region')).toBeInTheDocument();
- });
-
- it('renders the Auto-Import Mapped Files switch', () => {
- render();
- expect(
- screen.getByTestId('auto_import_mapped_files')
- ).toBeInTheDocument();
- });
-
it('renders the M3U Hash Key multiselect', () => {
render();
expect(screen.getByTestId('m3u_hash_key')).toBeInTheDocument();
@@ -314,12 +308,6 @@ describe('StreamSettingsForm', () => {
expect(screen.getByText('HLS')).toBeInTheDocument();
});
- it('populates region options from REGION_CHOICES', () => {
- render();
- expect(screen.getByText('US')).toBeInTheDocument();
- expect(screen.getByText('EU')).toBeInTheDocument();
- });
-
it('does not show success alert on initial render', () => {
render();
expect(screen.queryByTestId('alert')).not.toBeInTheDocument();
@@ -410,7 +398,9 @@ describe('StreamSettingsForm', () => {
describe('form submission (no M3U hash key change)', () => {
beforeEach(() => {
// Same hash key before and after → no dialog
- vi.mocked(getChangedSettings).mockReturnValue({ preferred_region: 'eu' });
+ vi.mocked(getChangedSettings).mockReturnValue({
+ default_user_agent: '1',
+ });
setupMocks();
formMock = makeFormMock();
vi.mocked(useForm).mockReturnValue(formMock);
@@ -783,16 +773,10 @@ describe('StreamSettingsForm', () => {
);
});
- it('calls getInputProps for preferred_region', () => {
- render();
- expect(formMock.getInputProps).toHaveBeenCalledWith('preferred_region');
- });
-
- it('calls getInputProps for auto_import_mapped_files with checkbox type', () => {
+ it('calls getInputProps for default_output_format', () => {
render();
expect(formMock.getInputProps).toHaveBeenCalledWith(
- 'auto_import_mapped_files',
- { type: 'checkbox' }
+ 'default_output_format'
);
});
diff --git a/frontend/src/components/forms/settings/__tests__/SystemSettingsForm.test.jsx b/frontend/src/components/forms/settings/__tests__/SystemSettingsForm.test.jsx
index 4b610e54..09daace7 100644
--- a/frontend/src/components/forms/settings/__tests__/SystemSettingsForm.test.jsx
+++ b/frontend/src/components/forms/settings/__tests__/SystemSettingsForm.test.jsx
@@ -5,6 +5,14 @@ import SystemSettingsForm from '../SystemSettingsForm';
// ── Store mocks ────────────────────────────────────────────────────────────────
vi.mock('../../../../store/settings.jsx', () => ({ default: vi.fn() }));
+// ── Constants mock ─────────────────────────────────────────────────────────────
+vi.mock('../../../../constants.js', () => ({
+ REGION_CHOICES: [
+ { label: 'United States', value: 'US' },
+ { label: 'Europe', value: 'EU' },
+ ],
+}));
+
// ── Utility mocks ──────────────────────────────────────────────────────────────
vi.mock('../../../../utils/pages/SettingsUtils.js', () => ({
getChangedSettings: vi.fn(),
@@ -52,6 +60,23 @@ vi.mock('@mantine/core', () => ({
),
Stack: ({ children }) =>
{children}
,
+ Group: ({ children }) => {children}
,
+ Select: ({ label, id, data, description }) => (
+
+
+ {description &&
{description}
}
+
+
+ ),
+ Switch: ({ id }) => (
+ {}} />
+ ),
Text: ({ children }) => {children},
Divider: () =>
,
}));
@@ -85,7 +110,11 @@ const setupMocks = ({
settings = makeSettings(),
environment = makeEnvironment(),
} = {}) => {
- const formValues = { max_system_events: settings?.max_system_events ?? 100 };
+ const formValues = {
+ max_system_events: settings?.max_system_events ?? 100,
+ preferred_region: '',
+ auto_import_mapped_files: true,
+ };
const formMock = {
values: formValues,
@@ -94,6 +123,12 @@ const setupMocks = ({
setFieldValue: vi.fn((key, value) => {
formMock.values[key] = value;
}),
+ getInputProps: vi.fn((field, opts) => {
+ if (opts?.type === 'checkbox') {
+ return { checked: formValues[field] ?? false, onChange: vi.fn() };
+ }
+ return { value: formValues[field] ?? '', onChange: vi.fn() };
+ }),
onSubmit: vi.fn((handler) => handler),
submitting: false,
};
@@ -146,16 +181,29 @@ describe('SystemSettingsForm', () => {
render();
expect(
screen.getByText(
- 'Number of events to retain (minimum: 10, maximum: 1000)'
+ 'Number of events to retain (minimum: 10, maximum: 1000). Events are displayed on the Stats page.'
)
).toBeInTheDocument();
});
- it('renders descriptive text about system events', () => {
+ it('renders the Preferred Region select', () => {
+ setupMocks();
+ render();
+ expect(screen.getByLabelText('Preferred Region')).toBeInTheDocument();
+ });
+
+ it('populates region options from REGION_CHOICES', () => {
+ setupMocks();
+ render();
+ expect(screen.getByText('United States')).toBeInTheDocument();
+ expect(screen.getByText('Europe')).toBeInTheDocument();
+ });
+
+ it('renders the Auto-Import Mapped Files switch', () => {
setupMocks();
render();
expect(
- screen.getByText(/Configure how many system events/)
+ screen.getByTestId('auto_import_mapped_files')
).toBeInTheDocument();
});
@@ -194,6 +242,12 @@ describe('SystemSettingsForm', () => {
getValues: vi.fn().mockReturnValue(formValues),
setValues: vi.fn(),
setFieldValue: vi.fn(),
+ getInputProps: vi.fn((field, opts) => {
+ if (opts?.type === 'checkbox') {
+ return { checked: formValues[field] ?? false, onChange: vi.fn() };
+ }
+ return { value: formValues[field] ?? '', onChange: vi.fn() };
+ }),
onSubmit: vi.fn((handler) => handler),
submitting: false,
};
@@ -230,22 +284,34 @@ describe('SystemSettingsForm', () => {
render();
expect(formMock.setValues).toHaveBeenCalledWith({
max_system_events: 100,
+ preferred_region: '',
+ auto_import_mapped_files: true,
});
});
it('does not call parseSettings when settings is null', () => {
+ const nullFormValues = { max_system_events: 100 };
const formMock = {
- values: { max_system_events: 100 },
- getValues: vi.fn().mockReturnValue({ max_system_events: 100 }),
+ values: nullFormValues,
+ getValues: vi.fn().mockReturnValue(nullFormValues),
setValues: vi.fn(),
setFieldValue: vi.fn(),
+ getInputProps: vi.fn((field, opts) => {
+ if (opts?.type === 'checkbox') {
+ return {
+ checked: nullFormValues[field] ?? false,
+ onChange: vi.fn(),
+ };
+ }
+ return { value: nullFormValues[field] ?? '', onChange: vi.fn() };
+ }),
onSubmit: vi.fn((handler) => handler),
submitting: false,
};
vi.mocked(useForm).mockReturnValue(formMock);
- vi.mocked(getSystemSettingsFormInitialValues).mockReturnValue({
- max_system_events: 100,
- });
+ vi.mocked(getSystemSettingsFormInitialValues).mockReturnValue(
+ nullFormValues
+ );
vi.mocked(useSettingsStore).mockImplementation((sel) =>
sel({ settings: null, environment: makeEnvironment() })
);
diff --git a/frontend/src/utils/pages/__tests__/SettingsUtils.test.js b/frontend/src/utils/pages/__tests__/SettingsUtils.test.js
index 43f395d4..91417b6a 100644
--- a/frontend/src/utils/pages/__tests__/SettingsUtils.test.js
+++ b/frontend/src/utils/pages/__tests__/SettingsUtils.test.js
@@ -73,6 +73,7 @@ describe('SettingsUtils', () => {
};
API.updateSetting.mockResolvedValue({});
+ API.createSetting.mockResolvedValue({});
await SettingsUtils.saveChangedSettings(settings, changedSettings);