;(window as any).electron = { getEnvironmentConfig: jest.fn(() => Promise.resolve({ enableMainnet: false })), testHederaConnection: jest.fn(() => Promise.resolve({ success: true })), testOpenAIConnection: jest.fn(() => Promise.resolve({ success: true })), testAnthropicConnection: 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 { MemoryRouter } from 'react-router-dom'; import SettingsPage from '../../../../src/renderer/pages/SettingsPage'; import { useConfigStore } from '../../../../src/renderer/stores/configStore'; import type { ConfigStore } from '../../../../src/renderer/stores/configStore'; jest.mock('../../../../src/renderer/stores/configStore'); describe('Configuration Save/Load Integration', () => { const mockUseConfigStore = useConfigStore as jest.MockedFunction< typeof useConfigStore >; const mockStore = { config: { hedera: { accountId: '', privateKey: '', network: 'testnet' as const, }, openai: { apiKey: '', model: 'gpt-4' as const, }, advanced: { theme: 'light' as const, autoStart: false, }, }, isLoading: false, error: null, setHederaAccountId: jest.fn(), setHederaPrivateKey: jest.fn(), setHederaNetwork: jest.fn(), setOpenAIApiKey: jest.fn(), setOpenAIModel: jest.fn(), setTheme: jest.fn(), setAutoStart: jest.fn(), saveConfig: jest.fn(), loadConfig: jest.fn(), testHederaConnection: jest.fn(), testOpenAIConnection: jest.fn(), isHederaConfigValid: jest.fn(), isOpenAIConfigValid: jest.fn(), clearError: jest.fn(), setAnthropicApiKey: jest.fn(), setAnthropicModel: jest.fn(), setLLMProvider: jest.fn(), setLogLevel: jest.fn(), setOperationalMode: jest.fn(), setAutonomousMode: jest.fn(), testAnthropicConnection: jest.fn(), isAnthropicConfigValid: jest.fn(), isLLMConfigValid: jest.fn(), isConfigured: jest.fn(), }; beforeEach(() => { mockUseConfigStore.mockReturnValue(mockStore as ConfigStore); window.electron = { saveConfig: jest.fn().mockResolvedValue(undefined), loadConfig: jest.fn().mockResolvedValue({ hedera: { accountId: '0.0.54321', privateKey: 'loaded-key', network: 'mainnet' as const, }, openai: { apiKey: 'sk-loaded-key', model: 'gpt-3.5-turbo' as const, }, advanced: { theme: 'dark' as const, autoStart: true, }, }), testHederaConnection: jest.fn().mockResolvedValue({ success: true }), testOpenAIConnection: jest.fn().mockResolvedValue({ success: true }), }; }); it('should load configuration on mount', async () => { render( ); await waitFor(() => { expect(mockStore.loadConfig).toHaveBeenCalled(); }); }); it('should auto-save valid configuration changes', async () => { const user = userEvent.setup(); mockStore.isHederaConfigValid.mockReturnValue(true); mockStore.isOpenAIConfigValid.mockReturnValue(true); render( ); const hederaTab = screen.getByText(/hedera/i, { selector: 'button' }); fireEvent.click(hederaTab); const accountIdInput = screen.getByLabelText(/account id/i); await user.clear(accountIdInput); await user.type(accountIdInput, '0.0.12345'); await waitFor(() => { expect(mockStore.setHederaAccountId).toHaveBeenCalledWith('0.0.12345'); }); await waitFor( () => { expect(mockStore.saveConfig).toHaveBeenCalled(); }, { timeout: 3000 } ); }); it('should not auto-save invalid configuration', async () => { const user = userEvent.setup(); mockStore.isHederaConfigValid.mockReturnValue(false); render( ); const hederaTab = screen.getByText(/hedera/i, { selector: 'button' }); fireEvent.click(hederaTab); const accountIdInput = screen.getByLabelText(/account id/i); await user.type(accountIdInput, 'invalid'); await waitFor(() => { expect(mockStore.setHederaAccountId).toHaveBeenCalledWith('invalid'); }); await new Promise((resolve) => setTimeout(resolve, 3000)); expect(mockStore.saveConfig).not.toHaveBeenCalled(); }); it('should display save errors', async () => { mockStore.saveConfig.mockRejectedValue( new Error('Failed to save configuration') ); mockStore.error = 'Failed to save configuration'; render( ); await waitFor(() => { expect( screen.getByText(/failed to save configuration/i) ).toBeInTheDocument(); }); }); it('should display load errors', async () => { mockStore.loadConfig.mockRejectedValue( new Error('Failed to load configuration') ); mockStore.error = 'Failed to load configuration'; render( ); await waitFor(() => { expect( screen.getByText(/failed to load configuration/i) ).toBeInTheDocument(); }); }); it('should handle configuration migration', async () => { const oldConfig = { hederaAccountId: '0.0.11111', hederaPrivateKey: 'old-key', openaiApiKey: 'sk-old-key', }; window.electron.loadConfig = jest.fn().mockResolvedValue(oldConfig); render( ); await waitFor(() => { expect(mockStore.loadConfig).toHaveBeenCalled(); }); await waitFor(() => { expect(mockStore.saveConfig).toHaveBeenCalled(); }); }); it('should validate all fields before enabling save', async () => { const user = userEvent.setup(); render( ); const saveButton = screen.getByText(/save configuration/i); expect(saveButton).toBeDisabled(); const hederaTab = screen.getByText(/hedera/i, { selector: 'button' }); fireEvent.click(hederaTab); const accountIdInput = screen.getByLabelText(/account id/i); const privateKeyInput = screen.getByLabelText(/private key/i); await user.type(accountIdInput, '0.0.12345'); await user.type( privateKeyInput, '302e020100300506032b657004220420' + '0'.repeat(64) ); const openaiTab = screen.getByText(/openai/i, { selector: 'button' }); fireEvent.click(openaiTab); const apiKeyInput = screen.getByLabelText(/api key/i); await user.type(apiKeyInput, 'sk-test-key'); mockStore.isHederaConfigValid.mockReturnValue(true); mockStore.isOpenAIConfigValid.mockReturnValue(true); await waitFor(() => { expect(saveButton).not.toBeDisabled(); }); }); it('should reset form to saved values on cancel', async () => { const savedConfig = { hedera: { accountId: '0.0.99999', privateKey: 'saved-key', network: 'mainnet' as const, }, openai: { apiKey: 'sk-saved-key', model: 'gpt-4' as const, }, advanced: { theme: 'dark' as const, autoStart: true, }, }; mockStore.config = savedConfig; render( ); const user = userEvent.setup(); const hederaTab = screen.getByText(/hedera/i, { selector: 'button' }); fireEvent.click(hederaTab); const accountIdInput = screen.getByLabelText(/account id/i); await user.clear(accountIdInput); await user.type(accountIdInput, '0.0.12345'); const cancelButton = screen.getByText(/cancel/i); fireEvent.click(cancelButton); await waitFor(() => { expect(mockStore.loadConfig).toHaveBeenCalled(); }); }); });