;(window as any).electron = {
getEnvironmentConfig: jest.fn(() => Promise.resolve({ enableMainnet: false })),
testHederaConnection: jest.fn(() => Promise.resolve({ success: true })),
saveConfig: jest.fn(() => Promise.resolve(undefined)),
loadConfig: jest.fn(() => Promise.resolve({})),
reset: jest.fn(),
};
import React from 'react';
import { render, screen, fireEvent, waitFor } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { HederaSettings } from '../../../src/renderer/pages/settings/HederaSettings';
import { useConfigStore } from '../../../src/renderer/stores/configStore';
import type { ConfigStore } from '../../../src/renderer/stores/configStore';
jest.mock('../../../src/renderer/stores/configStore');
const mockUseConfigStore = useConfigStore as jest.MockedFunction<
typeof useConfigStore
>;
describe('HederaSettings', () => {
const mockSetHederaAccountId = jest.fn();
const mockSetHederaPrivateKey = jest.fn();
const mockSetHederaNetwork = jest.fn();
const mockTestHederaConnection = jest.fn();
const mockIsHederaConfigValid = jest.fn();
const defaultConfig = {
hedera: {
accountId: '',
privateKey: '',
network: 'testnet' as const,
},
};
beforeEach(() => {
jest.clearAllMocks();
mockUseConfigStore.mockReturnValue({
config: defaultConfig,
setHederaAccountId: mockSetHederaAccountId,
setHederaPrivateKey: mockSetHederaPrivateKey,
setHederaNetwork: mockSetHederaNetwork,
testHederaConnection: mockTestHederaConnection,
isHederaConfigValid: mockIsHederaConfigValid,
isLoading: false,
error: null,
isConfigured: () => true,
setOpenAIApiKey: jest.fn(),
setOpenAIModel: jest.fn(),
setAnthropicApiKey: jest.fn(),
setAnthropicModel: jest.fn(),
setLLMProvider: jest.fn(),
setTheme: jest.fn().mockResolvedValue(void 0),
setAutoStart: jest.fn(),
setLogLevel: jest.fn(),
setOperationalMode: jest.fn(),
setAutonomousMode: jest.fn(),
saveConfig: jest.fn().mockResolvedValue(void 0),
loadConfig: jest.fn().mockResolvedValue(void 0),
testOpenAIConnection: jest.fn().mockResolvedValue({ success: true }),
testAnthropicConnection: jest.fn().mockResolvedValue({ success: true }),
reset: jest.fn(),
} as ConfigStore);
mockIsHederaConfigValid.mockReturnValue(false);
});
it('should render all form fields', () => {
render();
expect(screen.getByText('Hedera Configuration')).toBeInTheDocument();
expect(
screen.getByText(
'Configure your Hedera account credentials and network settings.'
)
).toBeInTheDocument();
expect(screen.getByText('Account ID')).toBeInTheDocument();
expect(screen.getByPlaceholderText('0.0.12345')).toBeInTheDocument();
expect(screen.getByText('Private Key')).toBeInTheDocument();
expect(
screen.getByPlaceholderText('Enter your private key')
).toBeInTheDocument();
expect(screen.getByText('Network')).toBeInTheDocument();
expect(screen.getByRole('combobox')).toBeInTheDocument();
expect(screen.getByText('Test Connection')).toBeInTheDocument();
});
it('should update account ID on input', async () => {
const user = userEvent.setup();
render();
const accountIdInput = screen.getByPlaceholderText('0.0.12345');
await user.type(accountIdInput, '0.0.99999');
await waitFor(() => {
expect(mockSetHederaAccountId).toHaveBeenCalledWith('0.0.99999');
});
});
it('should update private key on input', async () => {
const user = userEvent.setup();
render();
const privateKeyInput = screen.getByPlaceholderText(
'Enter your private key'
);
const testKey = '0x' + '0'.repeat(64);
await user.type(privateKeyInput, testKey);
await waitFor(() => {
expect(mockSetHederaPrivateKey).toHaveBeenCalledWith(testKey);
});
});
it('should update network on selection', async () => {
const user = userEvent.setup();
render();
const networkSelect = screen.getByRole('combobox');
await user.selectOptions(networkSelect, 'mainnet');
await waitFor(() => {
expect(mockSetHederaNetwork).toHaveBeenCalledWith('mainnet');
});
});
it('should show validation error for invalid account ID', async () => {
render();
const accountIdInput = screen.getByPlaceholderText('0.0.12345');
fireEvent.change(accountIdInput, { target: { value: 'invalid' } });
fireEvent.blur(accountIdInput);
await waitFor(() => {
expect(
screen.getByText('Invalid account ID format (e.g., 0.0.12345)')
).toBeInTheDocument();
});
});
it('should show validation error for invalid private key', async () => {
render();
const privateKeyInput = screen.getByPlaceholderText(
'Enter your private key'
);
fireEvent.change(privateKeyInput, { target: { value: 'too-short' } });
fireEvent.blur(privateKeyInput);
await waitFor(() => {
expect(
screen.getByText('Invalid private key format')
).toBeInTheDocument();
});
});
it('should disable test button when config is invalid', () => {
mockIsHederaConfigValid.mockReturnValue(false);
render();
const testButton = screen.getByText('Test Connection');
expect(testButton).toBeDisabled();
});
it('should enable test button when config is valid', () => {
mockIsHederaConfigValid.mockReturnValue(true);
render();
const testButton = screen.getByText('Test Connection');
expect(testButton).not.toBeDisabled();
});
it('should test connection successfully', async () => {
const user = userEvent.setup();
mockIsHederaConfigValid.mockReturnValue(true);
mockTestHederaConnection.mockResolvedValue({
success: true,
error: undefined,
});
render();
const testButton = screen.getByText('Test Connection');
await user.click(testButton);
expect(screen.getByText('Testing...')).toBeInTheDocument();
await waitFor(() => {
expect(screen.getByText('Connection successful!')).toBeInTheDocument();
});
});
it('should show error on connection test failure', async () => {
const user = userEvent.setup();
mockIsHederaConfigValid.mockReturnValue(true);
mockTestHederaConnection.mockResolvedValue({
success: false,
error: 'Invalid credentials',
});
render();
const testButton = screen.getByText('Test Connection');
await user.click(testButton);
await waitFor(() => {
expect(screen.getByText('Invalid credentials')).toBeInTheDocument();
});
});
it('should handle connection test exception', async () => {
const user = userEvent.setup();
mockIsHederaConfigValid.mockReturnValue(true);
mockTestHederaConnection.mockRejectedValue(new Error('Network error'));
render();
const testButton = screen.getByText('Test Connection');
await user.click(testButton);
await waitFor(() => {
expect(screen.getByText('Network error')).toBeInTheDocument();
});
});
it('should render with pre-filled values', () => {
mockUseConfigStore.mockReturnValue({
config: {
hedera: {
accountId: '0.0.12345',
privateKey: '0x' + '0'.repeat(64),
network: 'mainnet',
},
},
setHederaAccountId: mockSetHederaAccountId,
setHederaPrivateKey: mockSetHederaPrivateKey,
setHederaNetwork: mockSetHederaNetwork,
testHederaConnection: mockTestHederaConnection,
isHederaConfigValid: mockIsHederaConfigValid,
isLoading: false,
error: null,
isConfigured: () => true,
setOpenAIApiKey: jest.fn(),
setOpenAIModel: jest.fn(),
setAnthropicApiKey: jest.fn(),
setAnthropicModel: jest.fn(),
setLLMProvider: jest.fn(),
setTheme: jest.fn().mockResolvedValue(void 0),
setAutoStart: jest.fn(),
setLogLevel: jest.fn(),
setOperationalMode: jest.fn(),
setAutonomousMode: jest.fn(),
saveConfig: jest.fn().mockResolvedValue(void 0),
loadConfig: jest.fn().mockResolvedValue(void 0),
testOpenAIConnection: jest.fn().mockResolvedValue({ success: true }),
testAnthropicConnection: jest.fn().mockResolvedValue({ success: true }),
reset: jest.fn(),
} as ConfigStore);
render();
const accountIdInput = screen.getByPlaceholderText(
'0.0.12345'
) as HTMLInputElement;
expect(accountIdInput.value).toBe('0.0.12345');
const privateKeyInput = screen.getByPlaceholderText(
'Enter your private key'
) as HTMLInputElement;
expect(privateKeyInput.value).toBe('0x' + '0'.repeat(64));
const networkSelect = screen.getByRole('combobox') as HTMLSelectElement;
expect(networkSelect.value).toBe('mainnet');
});
it('should mask private key input', () => {
render();
const privateKeyInput = screen.getByPlaceholderText(
'Enter your private key'
) as HTMLInputElement;
expect(privateKeyInput.type).toBe('password');
});
it('should show security note for private key', () => {
render();
expect(
screen.getByText(
'Your private key is encrypted and stored securely using the system keychain.'
)
).toBeInTheDocument();
});
});