mirror of
https://github.com/Dispatcharr/Dispatcharr.git
synced 2026-07-18 00:55:50 +00:00
Updated tests after sync
This commit is contained in:
parent
216e582a91
commit
04e2886ba5
4 changed files with 487 additions and 9 deletions
|
|
@ -40,9 +40,6 @@ const localStorageMock = (() => {
|
|||
|
||||
global.localStorage = localStorageMock;
|
||||
|
||||
// Mock console methods
|
||||
global.console.error = vi.fn();
|
||||
|
||||
// Helper to create a mock JWT token
|
||||
const createMockToken = (expiresInSeconds = 3600) => {
|
||||
const now = Math.floor(Date.now() / 1000);
|
||||
|
|
@ -161,7 +158,9 @@ describe('useAuthStore', () => {
|
|||
await result.current.login({ username: 'testuser', password: 'wrong' });
|
||||
});
|
||||
|
||||
expect(console.error).toHaveBeenCalledWith('Login failed:', expect.any(Error));
|
||||
expect(API.login).toHaveBeenCalledWith('testuser', 'wrong');
|
||||
expect(result.current.isAuthenticated).toBe(false);
|
||||
expect(localStorageMock.setItem).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
|
|
@ -183,7 +182,6 @@ describe('useAuthStore', () => {
|
|||
|
||||
expect(API.refreshToken).toHaveBeenCalledWith('old-refresh-token');
|
||||
expect(newToken).toBe(mockNewAccessToken);
|
||||
expect(result.current.isAuthenticated).toBe(true);
|
||||
expect(localStorageMock.setItem).toHaveBeenCalledWith('accessToken', mockNewAccessToken);
|
||||
});
|
||||
|
||||
|
|
@ -212,7 +210,6 @@ describe('useAuthStore', () => {
|
|||
await result.current.getRefreshToken();
|
||||
});
|
||||
|
||||
expect(console.error).toHaveBeenCalledWith('Token refresh failed:', expect.any(Error));
|
||||
expect(result.current.isAuthenticated).toBe(false);
|
||||
expect(localStorageMock.removeItem).toHaveBeenCalledWith('accessToken');
|
||||
expect(localStorageMock.removeItem).toHaveBeenCalledWith('refreshToken');
|
||||
|
|
@ -292,7 +289,6 @@ describe('useAuthStore', () => {
|
|||
await result.current.logout();
|
||||
});
|
||||
|
||||
expect(console.error).toHaveBeenCalledWith('Logout API call failed:', expect.any(Error));
|
||||
expect(result.current.isAuthenticated).toBe(false);
|
||||
expect(localStorageMock.removeItem).toHaveBeenCalled();
|
||||
});
|
||||
|
|
@ -435,8 +431,6 @@ describe('useAuthStore', () => {
|
|||
await act(async () => {
|
||||
await result.current.initData();
|
||||
});
|
||||
|
||||
expect(console.error).toHaveBeenCalledWith('Error initializing data:', expect.any(Error));
|
||||
});
|
||||
});
|
||||
|
||||
|
|
@ -476,4 +470,162 @@ describe('useAuthStore', () => {
|
|||
expect(result.current.superuserExists).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getRefreshToken edge cases', () => {
|
||||
it('should return false if API response has no access token', async () => {
|
||||
localStorageMock.getItem.mockReturnValue('refresh-token');
|
||||
API.refreshToken.mockResolvedValue({});
|
||||
|
||||
const { result } = renderHook(() => useAuthStore());
|
||||
|
||||
let response;
|
||||
await act(async () => {
|
||||
response = await result.current.getRefreshToken();
|
||||
});
|
||||
|
||||
expect(response).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('login edge cases', () => {
|
||||
it('should not update state if response has no access token', async () => {
|
||||
API.login.mockResolvedValue({});
|
||||
|
||||
const { result } = renderHook(() => useAuthStore());
|
||||
|
||||
await act(async () => {
|
||||
await result.current.login({ username: 'testuser', password: 'password' });
|
||||
});
|
||||
|
||||
expect(result.current.accessToken).toBeNull();
|
||||
expect(localStorageMock.setItem).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('logout edge cases', () => {
|
||||
it('should reset isInitializing flag on logout', async () => {
|
||||
useAuthStore.setState({ isInitializing: true });
|
||||
API.logout.mockResolvedValue();
|
||||
|
||||
const { result } = renderHook(() => useAuthStore());
|
||||
|
||||
await act(async () => {
|
||||
await result.current.logout();
|
||||
});
|
||||
|
||||
expect(result.current.isInitializing).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('initializeAuth edge cases', () => {
|
||||
it('should return false if refresh token API call fails', async () => {
|
||||
localStorageMock.getItem.mockReturnValue('refresh-token');
|
||||
API.refreshToken.mockRejectedValue(new Error('Token expired'));
|
||||
API.logout.mockResolvedValue();
|
||||
|
||||
const { result } = renderHook(() => useAuthStore());
|
||||
|
||||
let initialized;
|
||||
await act(async () => {
|
||||
initialized = await result.current.initializeAuth();
|
||||
});
|
||||
|
||||
expect(initialized).toBe(false);
|
||||
});
|
||||
|
||||
it('should return false if refresh returns no access token', async () => {
|
||||
localStorageMock.getItem.mockReturnValue('refresh-token');
|
||||
API.refreshToken.mockResolvedValue({});
|
||||
|
||||
const { result } = renderHook(() => useAuthStore());
|
||||
|
||||
let initialized;
|
||||
await act(async () => {
|
||||
initialized = await result.current.initializeAuth();
|
||||
});
|
||||
|
||||
expect(initialized).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('initData edge cases', () => {
|
||||
it('should skip initialization if already initialized', async () => {
|
||||
useAuthStore.setState({ isInitialized: true });
|
||||
|
||||
const { result } = renderHook(() => useAuthStore());
|
||||
|
||||
await act(async () => {
|
||||
await result.current.initData();
|
||||
});
|
||||
|
||||
expect(API.me).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should skip initialization if already initializing', async () => {
|
||||
useAuthStore.setState({ isInitializing: true });
|
||||
|
||||
const { result } = renderHook(() => useAuthStore());
|
||||
|
||||
await act(async () => {
|
||||
await result.current.initData();
|
||||
});
|
||||
|
||||
expect(API.me).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should set isInitializing to false on error', async () => {
|
||||
// Reset state before the test
|
||||
useAuthStore.setState({
|
||||
isInitializing: false,
|
||||
isInitialized: false
|
||||
});
|
||||
|
||||
API.me.mockRejectedValue(new Error('API error'));
|
||||
|
||||
const { result } = renderHook(() => useAuthStore());
|
||||
|
||||
await act(async () => {
|
||||
try {
|
||||
await result.current.initData();
|
||||
} catch {
|
||||
// Expected error
|
||||
}
|
||||
});
|
||||
|
||||
expect(result.current.isInitializing).toBe(false);
|
||||
expect(result.current.isInitialized).toBe(false);
|
||||
});
|
||||
|
||||
it('should call fetchChannels in background after initialization', async () => {
|
||||
const mockUser = {
|
||||
username: 'admin',
|
||||
email: 'admin@test.com',
|
||||
user_level: USER_LEVELS.ADMIN,
|
||||
};
|
||||
|
||||
const fetchChannels = vi.fn().mockResolvedValue();
|
||||
useChannelsStore.getState = () => ({
|
||||
fetchChannels,
|
||||
fetchChannelGroups: vi.fn().mockResolvedValue(),
|
||||
fetchChannelProfiles: vi.fn().mockResolvedValue(),
|
||||
});
|
||||
|
||||
API.me.mockResolvedValue(mockUser);
|
||||
|
||||
const { result } = renderHook(() => useAuthStore());
|
||||
|
||||
await act(async () => {
|
||||
await result.current.initData();
|
||||
});
|
||||
|
||||
// Wait for the background call to complete
|
||||
await act(async () => {
|
||||
await new Promise(resolve => setTimeout(resolve, 10));
|
||||
});
|
||||
|
||||
// The background fetchChannels is called synchronously without await
|
||||
// so we just need to verify it was called
|
||||
expect(fetchChannels).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -292,4 +292,111 @@ describe('useChannelsTableStore', () => {
|
|||
expect(result.current.sorting).toEqual([]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('isUnlocked', () => {
|
||||
it('should initialize with default false value', () => {
|
||||
const { result } = renderHook(() => useChannelsTableStore());
|
||||
|
||||
expect(result.current.isUnlocked).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('setIsUnlocked', () => {
|
||||
it('should update isUnlocked to true', () => {
|
||||
const { result } = renderHook(() => useChannelsTableStore());
|
||||
|
||||
act(() => {
|
||||
result.current.setIsUnlocked(true);
|
||||
});
|
||||
|
||||
expect(result.current.isUnlocked).toBe(true);
|
||||
});
|
||||
|
||||
it('should update isUnlocked to false', () => {
|
||||
const { result } = renderHook(() => useChannelsTableStore());
|
||||
|
||||
act(() => {
|
||||
result.current.setIsUnlocked(true);
|
||||
});
|
||||
|
||||
expect(result.current.isUnlocked).toBe(true);
|
||||
|
||||
act(() => {
|
||||
result.current.setIsUnlocked(false);
|
||||
});
|
||||
|
||||
expect(result.current.isUnlocked).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('updateChannel', () => {
|
||||
it('should update an existing channel', () => {
|
||||
const { result } = renderHook(() => useChannelsTableStore());
|
||||
|
||||
const mockChannels = [
|
||||
{ id: 1, name: 'Channel 1', channel_number: 1 },
|
||||
{ id: 2, name: 'Channel 2', channel_number: 2 },
|
||||
{ id: 3, name: 'Channel 3', channel_number: 3 },
|
||||
];
|
||||
|
||||
act(() => {
|
||||
useChannelsTableStore.setState({ channels: mockChannels });
|
||||
});
|
||||
|
||||
const updatedChannel = { id: 2, name: 'Updated Channel 2', channel_number: 22 };
|
||||
|
||||
act(() => {
|
||||
result.current.updateChannel(updatedChannel);
|
||||
});
|
||||
|
||||
expect(result.current.channels).toEqual([
|
||||
{ id: 1, name: 'Channel 1', channel_number: 1 },
|
||||
{ id: 2, name: 'Updated Channel 2', channel_number: 22 },
|
||||
{ id: 3, name: 'Channel 3', channel_number: 3 },
|
||||
]);
|
||||
});
|
||||
|
||||
it('should not modify channels when updating non-existent channel', () => {
|
||||
const { result } = renderHook(() => useChannelsTableStore());
|
||||
|
||||
const mockChannels = [
|
||||
{ id: 1, name: 'Channel 1', channel_number: 1 },
|
||||
{ id: 2, name: 'Channel 2', channel_number: 2 },
|
||||
];
|
||||
|
||||
act(() => {
|
||||
useChannelsTableStore.setState({ channels: mockChannels });
|
||||
});
|
||||
|
||||
const updatedChannel = { id: 999, name: 'Non-existent', channel_number: 999 };
|
||||
|
||||
act(() => {
|
||||
result.current.updateChannel(updatedChannel);
|
||||
});
|
||||
|
||||
expect(result.current.channels).toEqual(mockChannels);
|
||||
});
|
||||
|
||||
it('should preserve other channels when updating one channel', () => {
|
||||
const { result } = renderHook(() => useChannelsTableStore());
|
||||
|
||||
const mockChannels = [
|
||||
{ id: 1, name: 'Channel 1', channel_number: 1, streams: ['stream1'] },
|
||||
{ id: 2, name: 'Channel 2', channel_number: 2, streams: ['stream2'] },
|
||||
];
|
||||
|
||||
act(() => {
|
||||
useChannelsTableStore.setState({ channels: mockChannels });
|
||||
});
|
||||
|
||||
const updatedChannel = { id: 1, name: 'Updated Channel 1', channel_number: 10 };
|
||||
|
||||
act(() => {
|
||||
result.current.updateChannel(updatedChannel);
|
||||
});
|
||||
|
||||
expect(result.current.channels[0]).toEqual(updatedChannel);
|
||||
expect(result.current.channels[1]).toEqual(mockChannels[1]);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -16,6 +16,10 @@ describe('useSettingsStore', () => {
|
|||
country_name: '',
|
||||
env_mode: 'prod',
|
||||
},
|
||||
version: {
|
||||
version: '',
|
||||
timestamp: null,
|
||||
},
|
||||
isLoading: false,
|
||||
error: null,
|
||||
});
|
||||
|
|
@ -201,4 +205,149 @@ describe('useSettingsStore', () => {
|
|||
|
||||
expect(result.current.settings).toEqual({});
|
||||
});
|
||||
|
||||
it('should initialize version with default state', () => {
|
||||
const { result } = renderHook(() => useSettingsStore());
|
||||
|
||||
expect(result.current.version).toEqual({
|
||||
version: '',
|
||||
timestamp: null,
|
||||
});
|
||||
});
|
||||
|
||||
it('should fetch version successfully', async () => {
|
||||
const mockVersion = {
|
||||
version: '1.2.3',
|
||||
timestamp: '2024-01-01T00:00:00Z',
|
||||
};
|
||||
|
||||
api.getVersion.mockResolvedValue(mockVersion);
|
||||
|
||||
const { result } = renderHook(() => useSettingsStore());
|
||||
|
||||
let versionResult;
|
||||
await act(async () => {
|
||||
versionResult = await result.current.fetchVersion();
|
||||
});
|
||||
|
||||
expect(api.getVersion).toHaveBeenCalled();
|
||||
expect(result.current.version).toEqual({
|
||||
version: '1.2.3',
|
||||
timestamp: '2024-01-01T00:00:00Z',
|
||||
});
|
||||
expect(versionResult).toEqual({
|
||||
version: '1.2.3',
|
||||
timestamp: '2024-01-01T00:00:00Z',
|
||||
});
|
||||
});
|
||||
|
||||
it('should skip fetching version if already loaded', async () => {
|
||||
useSettingsStore.setState({
|
||||
version: {
|
||||
version: '1.0.0',
|
||||
timestamp: '2023-01-01T00:00:00Z',
|
||||
},
|
||||
});
|
||||
|
||||
api.getVersion.mockResolvedValue({ version: '2.0.0', timestamp: '2024-01-01T00:00:00Z' });
|
||||
|
||||
const { result } = renderHook(() => useSettingsStore());
|
||||
|
||||
let versionResult;
|
||||
await act(async () => {
|
||||
versionResult = await result.current.fetchVersion();
|
||||
});
|
||||
|
||||
expect(api.getVersion).not.toHaveBeenCalled();
|
||||
expect(result.current.version).toEqual({
|
||||
version: '1.0.0',
|
||||
timestamp: '2023-01-01T00:00:00Z',
|
||||
});
|
||||
expect(versionResult).toEqual({
|
||||
version: '1.0.0',
|
||||
timestamp: '2023-01-01T00:00:00Z',
|
||||
});
|
||||
});
|
||||
|
||||
it('should handle null version response', async () => {
|
||||
api.getVersion.mockResolvedValue(null);
|
||||
|
||||
const { result } = renderHook(() => useSettingsStore());
|
||||
|
||||
await act(async () => {
|
||||
await result.current.fetchVersion();
|
||||
});
|
||||
|
||||
expect(result.current.version).toEqual({
|
||||
version: '',
|
||||
timestamp: null,
|
||||
});
|
||||
});
|
||||
|
||||
it('should handle fetch version error', async () => {
|
||||
const mockError = new Error('Version fetch failed');
|
||||
api.getVersion.mockRejectedValue(mockError);
|
||||
|
||||
const { result } = renderHook(() => useSettingsStore());
|
||||
|
||||
let versionResult;
|
||||
await act(async () => {
|
||||
versionResult = await result.current.fetchVersion();
|
||||
});
|
||||
|
||||
expect(versionResult).toEqual({
|
||||
version: '',
|
||||
timestamp: null,
|
||||
});
|
||||
});
|
||||
|
||||
it('should fetch version with settings when version not loaded', async () => {
|
||||
const mockSettings = [{ key: 'setting1', value: 'value1' }];
|
||||
const mockEnv = { public_ip: '192.168.1.1' };
|
||||
const mockVersion = { version: '1.0.0', timestamp: '2024-01-01T00:00:00Z' };
|
||||
|
||||
api.getSettings.mockResolvedValue(mockSettings);
|
||||
api.getEnvironmentSettings.mockResolvedValue(mockEnv);
|
||||
api.getVersion.mockResolvedValue(mockVersion);
|
||||
|
||||
const { result } = renderHook(() => useSettingsStore());
|
||||
|
||||
await act(async () => {
|
||||
await result.current.fetchSettings();
|
||||
});
|
||||
|
||||
expect(api.getVersion).toHaveBeenCalled();
|
||||
expect(result.current.version).toEqual({
|
||||
version: '1.0.0',
|
||||
timestamp: '2024-01-01T00:00:00Z',
|
||||
});
|
||||
});
|
||||
|
||||
it('should skip fetching version with settings when already loaded', async () => {
|
||||
useSettingsStore.setState({
|
||||
version: {
|
||||
version: '1.0.0',
|
||||
timestamp: '2023-01-01T00:00:00Z',
|
||||
},
|
||||
});
|
||||
|
||||
const mockSettings = [{ key: 'setting1', value: 'value1' }];
|
||||
const mockEnv = { public_ip: '192.168.1.1' };
|
||||
|
||||
api.getSettings.mockResolvedValue(mockSettings);
|
||||
api.getEnvironmentSettings.mockResolvedValue(mockEnv);
|
||||
api.getVersion.mockResolvedValue({ version: '2.0.0', timestamp: '2024-01-01T00:00:00Z' });
|
||||
|
||||
const { result } = renderHook(() => useSettingsStore());
|
||||
|
||||
await act(async () => {
|
||||
await result.current.fetchSettings();
|
||||
});
|
||||
|
||||
expect(api.getVersion).not.toHaveBeenCalled();
|
||||
expect(result.current.version).toEqual({
|
||||
version: '1.0.0',
|
||||
timestamp: '2023-01-01T00:00:00Z',
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -477,4 +477,74 @@ describe('useVODLogosStore', () => {
|
|||
|
||||
expect(api.getVODLogos).toHaveBeenCalledWith({ search: 'test', page: 2 });
|
||||
});
|
||||
|
||||
it('should get unused logos count successfully', async () => {
|
||||
const mockResponse = {
|
||||
results: [{ id: 1, name: 'Unused Logo' }],
|
||||
count: 42,
|
||||
};
|
||||
|
||||
api.getVODLogos.mockResolvedValue(mockResponse);
|
||||
|
||||
const { result } = renderHook(() => useVODLogosStore());
|
||||
|
||||
let unusedCount;
|
||||
await act(async () => {
|
||||
unusedCount = await result.current.getUnusedLogosCount();
|
||||
});
|
||||
|
||||
expect(api.getVODLogos).toHaveBeenCalledWith({
|
||||
used: 'false',
|
||||
page_size: 1,
|
||||
});
|
||||
expect(unusedCount).toBe(42);
|
||||
});
|
||||
|
||||
it('should return 0 when unused logos count response has no count', async () => {
|
||||
api.getVODLogos.mockResolvedValue({ results: [] });
|
||||
|
||||
const { result } = renderHook(() => useVODLogosStore());
|
||||
|
||||
let unusedCount;
|
||||
await act(async () => {
|
||||
unusedCount = await result.current.getUnusedLogosCount();
|
||||
});
|
||||
|
||||
expect(unusedCount).toBe(0);
|
||||
});
|
||||
|
||||
it('should handle get unused logos count error', async () => {
|
||||
const mockError = new Error('Failed to fetch count');
|
||||
api.getVODLogos.mockRejectedValue(mockError);
|
||||
|
||||
const consoleErrorSpy = vi.spyOn(console, 'error').mockImplementation(() => {});
|
||||
|
||||
const { result } = renderHook(() => useVODLogosStore());
|
||||
|
||||
await act(async () => {
|
||||
try {
|
||||
await result.current.getUnusedLogosCount();
|
||||
} catch (error) {
|
||||
expect(error).toBe(mockError);
|
||||
}
|
||||
});
|
||||
|
||||
expect(consoleErrorSpy).toHaveBeenCalledWith('Failed to fetch unused logos count:', mockError);
|
||||
|
||||
consoleErrorSpy.mockRestore();
|
||||
});
|
||||
|
||||
it('should update currentPage and pageSize state', () => {
|
||||
const { result } = renderHook(() => useVODLogosStore());
|
||||
|
||||
act(() => {
|
||||
useVODLogosStore.setState({
|
||||
currentPage: 3,
|
||||
pageSize: 50,
|
||||
});
|
||||
});
|
||||
|
||||
expect(result.current.currentPage).toBe(3);
|
||||
expect(result.current.pageSize).toBe(50);
|
||||
});
|
||||
});
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue