mirror of
https://github.com/Dispatcharr/Dispatcharr.git
synced 2026-07-18 00:55:50 +00:00
Added tests for utils
This commit is contained in:
parent
6d5a5a549a
commit
f6ad115a1f
3 changed files with 409 additions and 0 deletions
210
frontend/src/utils/forms/__tests__/OutputProfileUtils.test.js
Normal file
210
frontend/src/utils/forms/__tests__/OutputProfileUtils.test.js
Normal file
|
|
@ -0,0 +1,210 @@
|
|||
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
||||
|
||||
// ── Mocks ──────────────────────────────────────────────────────────────────────
|
||||
|
||||
vi.mock('../../../api', () => ({
|
||||
default: {
|
||||
addOutputProfile: vi.fn(),
|
||||
updateOutputProfile: vi.fn(),
|
||||
},
|
||||
}));
|
||||
|
||||
const mockResolver = vi.fn();
|
||||
vi.mock('@hookform/resolvers/yup', () => ({
|
||||
yupResolver: vi.fn(() => mockResolver),
|
||||
}));
|
||||
|
||||
// ── Imports after mocks ────────────────────────────────────────────────────────
|
||||
|
||||
import API from '../../../api';
|
||||
import { yupResolver } from '@hookform/resolvers/yup';
|
||||
import {
|
||||
BUILT_IN_COMMANDS,
|
||||
COMMAND_EXAMPLES,
|
||||
toCommandSelection,
|
||||
schema,
|
||||
addOutputProfile,
|
||||
updateOutputProfile,
|
||||
getResolver,
|
||||
} from '../OutputProfileUtils';
|
||||
|
||||
// ──────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
describe('OutputProfileUtils', () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
vi.mocked(yupResolver).mockReturnValue(mockResolver);
|
||||
});
|
||||
|
||||
// ── Constants ──────────────────────────────────────────────────────────────
|
||||
|
||||
describe('BUILT_IN_COMMANDS', () => {
|
||||
it('includes the ffmpeg entry', () => {
|
||||
expect(BUILT_IN_COMMANDS).toContainEqual({
|
||||
value: 'ffmpeg',
|
||||
label: 'FFmpeg',
|
||||
});
|
||||
});
|
||||
|
||||
it('includes the custom entry', () => {
|
||||
expect(BUILT_IN_COMMANDS).toContainEqual({
|
||||
value: '__custom__',
|
||||
label: 'Custom…',
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('COMMAND_EXAMPLES', () => {
|
||||
it('has a non-empty string example for ffmpeg', () => {
|
||||
expect(typeof COMMAND_EXAMPLES.ffmpeg).toBe('string');
|
||||
expect(COMMAND_EXAMPLES.ffmpeg.length).toBeGreaterThan(0);
|
||||
});
|
||||
});
|
||||
|
||||
// ── toCommandSelection ─────────────────────────────────────────────────────
|
||||
|
||||
describe('toCommandSelection', () => {
|
||||
it('returns the command value when it matches a non-custom built-in', () => {
|
||||
expect(toCommandSelection('ffmpeg')).toBe('ffmpeg');
|
||||
});
|
||||
|
||||
it('returns "__custom__" when command is "__custom__"', () => {
|
||||
// __custom__ is in BUILT_IN_COMMANDS but excluded by the o.value !== '__custom__' guard
|
||||
expect(toCommandSelection('__custom__')).toBe('__custom__');
|
||||
});
|
||||
|
||||
it('returns "__custom__" for an unrecognized command string', () => {
|
||||
expect(toCommandSelection('my-arbitrary-tool')).toBe('__custom__');
|
||||
});
|
||||
|
||||
it('returns "__custom__" for an empty string', () => {
|
||||
expect(toCommandSelection('')).toBe('__custom__');
|
||||
});
|
||||
|
||||
it('returns "__custom__" for undefined', () => {
|
||||
expect(toCommandSelection(undefined)).toBe('__custom__');
|
||||
});
|
||||
});
|
||||
|
||||
// ── schema ─────────────────────────────────────────────────────────────────
|
||||
|
||||
describe('schema', () => {
|
||||
it('validates a fully populated object', async () => {
|
||||
await expect(
|
||||
schema.validate({
|
||||
name: 'HD Profile',
|
||||
command: 'ffmpeg',
|
||||
parameters: '-c:v copy',
|
||||
})
|
||||
).resolves.toMatchObject({
|
||||
name: 'HD Profile',
|
||||
command: 'ffmpeg',
|
||||
parameters: '-c:v copy',
|
||||
});
|
||||
});
|
||||
|
||||
it('validates when parameters is omitted (optional)', async () => {
|
||||
await expect(
|
||||
schema.validate({ name: 'HD Profile', command: 'ffmpeg' })
|
||||
).resolves.toMatchObject({ name: 'HD Profile', command: 'ffmpeg' });
|
||||
});
|
||||
|
||||
it('rejects when name is missing', async () => {
|
||||
await expect(schema.validate({ command: 'ffmpeg' })).rejects.toThrow(
|
||||
'Name is required'
|
||||
);
|
||||
});
|
||||
|
||||
it('rejects when name is an empty string', async () => {
|
||||
await expect(
|
||||
schema.validate({ name: '', command: 'ffmpeg' })
|
||||
).rejects.toThrow('Name is required');
|
||||
});
|
||||
|
||||
it('rejects when command is missing', async () => {
|
||||
await expect(schema.validate({ name: 'HD Profile' })).rejects.toThrow(
|
||||
'Command is required'
|
||||
);
|
||||
});
|
||||
|
||||
it('rejects when command is an empty string', async () => {
|
||||
await expect(
|
||||
schema.validate({ name: 'HD Profile', command: '' })
|
||||
).rejects.toThrow('Command is required');
|
||||
});
|
||||
});
|
||||
|
||||
// ── addOutputProfile ───────────────────────────────────────────────────────
|
||||
|
||||
describe('addOutputProfile', () => {
|
||||
it('calls API.addOutputProfile with the provided values', async () => {
|
||||
const values = { name: 'New Profile', command: 'ffmpeg', parameters: '' };
|
||||
vi.mocked(API.addOutputProfile).mockResolvedValue({ id: 1, ...values });
|
||||
|
||||
await addOutputProfile(values);
|
||||
|
||||
expect(API.addOutputProfile).toHaveBeenCalledWith(values);
|
||||
expect(API.addOutputProfile).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('returns the API response', async () => {
|
||||
const values = { name: 'New Profile', command: 'ffmpeg' };
|
||||
const response = { id: 42, ...values };
|
||||
vi.mocked(API.addOutputProfile).mockResolvedValue(response);
|
||||
|
||||
const result = await addOutputProfile(values);
|
||||
|
||||
expect(result).toEqual(response);
|
||||
});
|
||||
|
||||
it('propagates errors thrown by API.addOutputProfile', async () => {
|
||||
vi.mocked(API.addOutputProfile).mockRejectedValue(
|
||||
new Error('Network error')
|
||||
);
|
||||
|
||||
await expect(addOutputProfile({})).rejects.toThrow('Network error');
|
||||
});
|
||||
});
|
||||
|
||||
// ── updateOutputProfile ────────────────────────────────────────────────────
|
||||
|
||||
describe('updateOutputProfile', () => {
|
||||
it('calls API.updateOutputProfile with the provided values', async () => {
|
||||
const values = { id: 1, name: 'Updated Profile', command: 'ffmpeg' };
|
||||
vi.mocked(API.updateOutputProfile).mockResolvedValue(values);
|
||||
|
||||
await updateOutputProfile(values);
|
||||
|
||||
expect(API.updateOutputProfile).toHaveBeenCalledWith(values);
|
||||
expect(API.updateOutputProfile).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('returns the API response', async () => {
|
||||
const values = { id: 7, name: 'Updated Profile', command: 'ffmpeg' };
|
||||
vi.mocked(API.updateOutputProfile).mockResolvedValue(values);
|
||||
|
||||
const result = await updateOutputProfile(values);
|
||||
|
||||
expect(result).toEqual(values);
|
||||
});
|
||||
|
||||
it('propagates errors thrown by API.updateOutputProfile', async () => {
|
||||
vi.mocked(API.updateOutputProfile).mockRejectedValue(
|
||||
new Error('Update failed')
|
||||
);
|
||||
|
||||
await expect(updateOutputProfile({})).rejects.toThrow('Update failed');
|
||||
});
|
||||
});
|
||||
|
||||
// ── getResolver ────────────────────────────────────────────────────────────
|
||||
|
||||
describe('getResolver', () => {
|
||||
it('returns the result of yupResolver called with schema', () => {
|
||||
const resolver = getResolver();
|
||||
|
||||
expect(yupResolver).toHaveBeenCalledWith(schema);
|
||||
expect(resolver).toBe(mockResolver);
|
||||
});
|
||||
});
|
||||
});
|
||||
114
frontend/src/utils/forms/__tests__/ServerGroupUtils.test.js
Normal file
114
frontend/src/utils/forms/__tests__/ServerGroupUtils.test.js
Normal file
|
|
@ -0,0 +1,114 @@
|
|||
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
||||
|
||||
// ── Mocks ──────────────────────────────────────────────────────────────────────
|
||||
|
||||
vi.mock('../../../api', () => ({
|
||||
default: {
|
||||
addServerGroup: vi.fn(),
|
||||
updateServerGroup: vi.fn(),
|
||||
},
|
||||
}));
|
||||
|
||||
const mockResolver = vi.fn();
|
||||
vi.mock('@hookform/resolvers/yup', () => ({
|
||||
yupResolver: vi.fn(() => mockResolver),
|
||||
}));
|
||||
|
||||
// ── Imports after mocks ────────────────────────────────────────────────────────
|
||||
|
||||
import API from '../../../api';
|
||||
import { yupResolver } from '@hookform/resolvers/yup';
|
||||
import {
|
||||
getResolver,
|
||||
addServerGroup,
|
||||
updateServerGroup,
|
||||
} from '../ServerGroupUtils';
|
||||
|
||||
// ──────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
describe('ServerGroupUtils', () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
vi.mocked(yupResolver).mockReturnValue(mockResolver);
|
||||
});
|
||||
|
||||
// ── getResolver ────────────────────────────────────────────────────────────
|
||||
|
||||
describe('getResolver', () => {
|
||||
it('calls yupResolver with a schema and returns the result', () => {
|
||||
const resolver = getResolver();
|
||||
|
||||
expect(yupResolver).toHaveBeenCalledTimes(1);
|
||||
expect(yupResolver).toHaveBeenCalledWith(expect.any(Object));
|
||||
expect(resolver).toBe(mockResolver);
|
||||
});
|
||||
|
||||
it('returns a new resolver on each call', () => {
|
||||
const resolverA = getResolver();
|
||||
const resolverB = getResolver();
|
||||
|
||||
expect(yupResolver).toHaveBeenCalledTimes(2);
|
||||
expect(resolverA).toBe(mockResolver);
|
||||
expect(resolverB).toBe(mockResolver);
|
||||
});
|
||||
});
|
||||
|
||||
// ── addServerGroup ─────────────────────────────────────────────────────────
|
||||
|
||||
describe('addServerGroup', () => {
|
||||
it('calls API.addServerGroup with the provided values', async () => {
|
||||
const values = { name: 'US East' };
|
||||
vi.mocked(API.addServerGroup).mockResolvedValue({ id: 1, ...values });
|
||||
|
||||
await addServerGroup(values);
|
||||
|
||||
expect(API.addServerGroup).toHaveBeenCalledWith(values);
|
||||
expect(API.addServerGroup).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('returns the API response', async () => {
|
||||
const values = { name: 'US East' };
|
||||
const response = { id: 1, ...values };
|
||||
vi.mocked(API.addServerGroup).mockResolvedValue(response);
|
||||
|
||||
const result = await addServerGroup(values);
|
||||
|
||||
expect(result).toEqual(response);
|
||||
});
|
||||
|
||||
it('propagates errors thrown by API.addServerGroup', async () => {
|
||||
vi.mocked(API.addServerGroup).mockRejectedValue(new Error('Network error'));
|
||||
|
||||
await expect(addServerGroup({ name: 'Test' })).rejects.toThrow('Network error');
|
||||
});
|
||||
});
|
||||
|
||||
// ── updateServerGroup ──────────────────────────────────────────────────────
|
||||
|
||||
describe('updateServerGroup', () => {
|
||||
it('calls API.updateServerGroup with the provided values', async () => {
|
||||
const values = { id: 5, name: 'EU West' };
|
||||
vi.mocked(API.updateServerGroup).mockResolvedValue(values);
|
||||
|
||||
await updateServerGroup(values);
|
||||
|
||||
expect(API.updateServerGroup).toHaveBeenCalledWith(values);
|
||||
expect(API.updateServerGroup).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('returns the API response', async () => {
|
||||
const values = { id: 5, name: 'EU West' };
|
||||
vi.mocked(API.updateServerGroup).mockResolvedValue(values);
|
||||
|
||||
const result = await updateServerGroup(values);
|
||||
|
||||
expect(result).toEqual(values);
|
||||
});
|
||||
|
||||
it('propagates errors thrown by API.updateServerGroup', async () => {
|
||||
vi.mocked(API.updateServerGroup).mockRejectedValue(new Error('Update failed'));
|
||||
|
||||
await expect(updateServerGroup({ id: 1, name: 'Test' })).rejects.toThrow('Update failed');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
@ -11,6 +11,9 @@ vi.mock('../../../api.js', () => ({
|
|||
reloadPlugins: vi.fn(),
|
||||
deletePlugin: vi.fn(),
|
||||
getPluginDetailManifest: vi.fn(),
|
||||
getPluginRepoSettings: vi.fn(),
|
||||
updatePluginRepoSettings: vi.fn(),
|
||||
previewPluginRepo: vi.fn(),
|
||||
},
|
||||
}));
|
||||
|
||||
|
|
@ -344,4 +347,86 @@ describe('PluginsUtils', () => {
|
|||
expect(API.getPluginDetailManifest).toHaveBeenCalledWith(null, null);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getPluginRepoSettings', () => {
|
||||
it('should call API getPluginRepoSettings', () => {
|
||||
PluginsUtils.getPluginRepoSettings();
|
||||
|
||||
expect(API.getPluginRepoSettings).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('should return API response', () => {
|
||||
const mockResponse = { repos: [] };
|
||||
|
||||
API.getPluginRepoSettings.mockReturnValue(mockResponse);
|
||||
|
||||
const result = PluginsUtils.getPluginRepoSettings();
|
||||
|
||||
expect(result).toEqual(mockResponse);
|
||||
});
|
||||
});
|
||||
|
||||
describe('updatePluginRepoSettings', () => {
|
||||
it('should call API updatePluginRepoSettings with values', () => {
|
||||
const values = { repos: ['https://example.com/repo.json'] };
|
||||
|
||||
PluginsUtils.updatePluginRepoSettings(values);
|
||||
|
||||
expect(API.updatePluginRepoSettings).toHaveBeenCalledWith(values);
|
||||
expect(API.updatePluginRepoSettings).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('should return API response', () => {
|
||||
const values = { repos: ['https://example.com/repo.json'] };
|
||||
const mockResponse = { success: true };
|
||||
|
||||
API.updatePluginRepoSettings.mockReturnValue(mockResponse);
|
||||
|
||||
const result = PluginsUtils.updatePluginRepoSettings(values);
|
||||
|
||||
expect(result).toEqual(mockResponse);
|
||||
});
|
||||
});
|
||||
|
||||
describe('previewPluginRepo', () => {
|
||||
it('should call API previewPluginRepo with url and publicKey', () => {
|
||||
const url = 'https://example.com/repo.json';
|
||||
const publicKey = 'public-key';
|
||||
|
||||
PluginsUtils.previewPluginRepo(url, publicKey);
|
||||
|
||||
expect(API.previewPluginRepo).toHaveBeenCalledWith(url, publicKey);
|
||||
expect(API.previewPluginRepo).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('should return API response', () => {
|
||||
const url = 'https://example.com/repo.json';
|
||||
const publicKey = 'public-key';
|
||||
const mockResponse = { name: 'Test Repo', plugins: [] };
|
||||
|
||||
API.previewPluginRepo.mockReturnValue(mockResponse);
|
||||
|
||||
const result = PluginsUtils.previewPluginRepo(url, publicKey);
|
||||
|
||||
expect(result).toEqual(mockResponse);
|
||||
});
|
||||
|
||||
it('should handle empty string url and publicKey', () => {
|
||||
const url = '';
|
||||
const publicKey = '';
|
||||
|
||||
PluginsUtils.previewPluginRepo(url, publicKey);
|
||||
|
||||
expect(API.previewPluginRepo).toHaveBeenCalledWith('', '');
|
||||
});
|
||||
|
||||
it('should handle null url and publicKey', () => {
|
||||
const url = null;
|
||||
const publicKey = null;
|
||||
|
||||
PluginsUtils.previewPluginRepo(url, publicKey);
|
||||
|
||||
expect(API.previewPluginRepo).toHaveBeenCalledWith(null, null);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue