From 31f04841149f324f2e11aef1f97c985e992de440 Mon Sep 17 00:00:00 2001 From: Andrew Beal Date: Mon, 4 May 2026 16:31:49 +0100 Subject: [PATCH] test: add subscribeToSettingsChanged mock and update settings tests Mock the new subscribeToSettingsChanged method in all AI provider test files to prevent test failures. Update SettingsService tests to use updateSettings method instead of direct settings modification and saveSettings calls, aligning with the new reactive settings API that notifies subscribers of changes. --- __tests__/AIClasses/BaseAIClass.test.ts | 3 +- __tests__/AIClasses/Claude.test.ts | 3 +- .../CrossProviderIntegration.test.ts | 3 +- __tests__/AIClasses/Gemini.test.ts | 3 +- __tests__/AIClasses/Mistral.test.ts | 3 +- __tests__/AIClasses/OpenAI.test.ts | 3 +- __tests__/Services/SettingsService.test.ts | 43 +++++++++++-------- 7 files changed, 37 insertions(+), 24 deletions(-) diff --git a/__tests__/AIClasses/BaseAIClass.test.ts b/__tests__/AIClasses/BaseAIClass.test.ts index 563b499..d6b9f80 100644 --- a/__tests__/AIClasses/BaseAIClass.test.ts +++ b/__tests__/AIClasses/BaseAIClass.test.ts @@ -48,7 +48,8 @@ describe('BaseAIClass Shared Methods', () => { if (provider === AIProvider.Gemini) return 'test-gemini-key'; return ''; }), - getApiKeyForCurrentModel: vi.fn(() => 'test-claude-key') + getApiKeyForCurrentModel: vi.fn(() => 'test-claude-key'), + subscribeToSettingsChanged: vi.fn() }; RegisterSingleton(Services.SettingsService, mockSettingsService); diff --git a/__tests__/AIClasses/Claude.test.ts b/__tests__/AIClasses/Claude.test.ts index c3edd1d..98b3e3a 100644 --- a/__tests__/AIClasses/Claude.test.ts +++ b/__tests__/AIClasses/Claude.test.ts @@ -52,7 +52,8 @@ describe('Claude', () => { if (provider === AIProvider.Gemini) return 'test-gemini-key'; return ''; }), - getApiKeyForCurrentModel: vi.fn(() => 'test-claude-key') + getApiKeyForCurrentModel: vi.fn(() => 'test-claude-key'), + subscribeToSettingsChanged: vi.fn() }; RegisterSingleton(Services.SettingsService, mockSettingsService); diff --git a/__tests__/AIClasses/CrossProviderIntegration.test.ts b/__tests__/AIClasses/CrossProviderIntegration.test.ts index 6924b7c..e8beee5 100644 --- a/__tests__/AIClasses/CrossProviderIntegration.test.ts +++ b/__tests__/AIClasses/CrossProviderIntegration.test.ts @@ -61,7 +61,8 @@ describe('Cross-Provider Integration - Thought Signature Support', () => { if (provider === AIProvider.Gemini) return 'test-gemini-key'; return ''; }), - getApiKeyForCurrentModel: vi.fn(() => 'test-gemini-key') + getApiKeyForCurrentModel: vi.fn(() => 'test-gemini-key'), + subscribeToSettingsChanged: vi.fn() }; RegisterSingleton(Services.SettingsService, mockSettingsService); diff --git a/__tests__/AIClasses/Gemini.test.ts b/__tests__/AIClasses/Gemini.test.ts index e82cca1..bec825b 100644 --- a/__tests__/AIClasses/Gemini.test.ts +++ b/__tests__/AIClasses/Gemini.test.ts @@ -50,7 +50,8 @@ describe('Gemini', () => { if (provider === AIProvider.Gemini) return 'test-gemini-key'; return ''; }), - getApiKeyForCurrentModel: vi.fn(() => 'test-gemini-key') + getApiKeyForCurrentModel: vi.fn(() => 'test-gemini-key'), + subscribeToSettingsChanged: vi.fn() }; RegisterSingleton(Services.SettingsService, mockSettingsService); diff --git a/__tests__/AIClasses/Mistral.test.ts b/__tests__/AIClasses/Mistral.test.ts index 8874441..3c9bdcf 100644 --- a/__tests__/AIClasses/Mistral.test.ts +++ b/__tests__/AIClasses/Mistral.test.ts @@ -53,7 +53,8 @@ describe('Mistral', () => { if (provider === AIProvider.Mistral) return 'test-mistral-key'; return ''; }), - getApiKeyForCurrentModel: vi.fn(() => 'test-mistral-key') + getApiKeyForCurrentModel: vi.fn(() => 'test-mistral-key'), + subscribeToSettingsChanged: vi.fn() }; RegisterSingleton(Services.SettingsService, mockSettingsService); diff --git a/__tests__/AIClasses/OpenAI.test.ts b/__tests__/AIClasses/OpenAI.test.ts index c7ec113..18033e0 100644 --- a/__tests__/AIClasses/OpenAI.test.ts +++ b/__tests__/AIClasses/OpenAI.test.ts @@ -53,7 +53,8 @@ describe('OpenAI', () => { if (provider === AIProvider.Gemini) return 'test-gemini-key'; return ''; }), - getApiKeyForCurrentModel: vi.fn(() => 'test-openai-key') + getApiKeyForCurrentModel: vi.fn(() => 'test-openai-key'), + subscribeToSettingsChanged: vi.fn() }; RegisterSingleton(Services.SettingsService, mockSettingsService); diff --git a/__tests__/Services/SettingsService.test.ts b/__tests__/Services/SettingsService.test.ts index 57d1f1c..127196c 100644 --- a/__tests__/Services/SettingsService.test.ts +++ b/__tests__/Services/SettingsService.test.ts @@ -3,6 +3,7 @@ import { SettingsService, type IVaultkeeperAISettings } from '../../Services/Set import { RegisterSingleton, DeregisterAllServices } from '../../Services/DependencyService'; import { Services } from '../../Services/Services'; import { AIProvider, AIProviderModel, fromModel } from '../../Enums/ApiProvider'; +import { ChatMode } from 'Enums/ChatMode'; describe('SettingsService', () => { let settingsService: SettingsService; @@ -110,7 +111,8 @@ describe('SettingsService', () => { quickActionModel: AIProviderModel.ClaudeSonnet_4_6, enableContextMenuActions: false, enableToolbarActions: false, - hideDrawerElements: false + hideDrawerElements: false, + chatMode: ChatMode.ReadOnly }; settingsService = new SettingsService(loadedSettings); }); @@ -160,7 +162,8 @@ describe('SettingsService', () => { quickActionModel: AIProviderModel.ClaudeSonnet_4_6, enableContextMenuActions: false, enableToolbarActions: false, - hideDrawerElements: false + hideDrawerElements: false, + chatMode: ChatMode.ReadOnly }; settingsService = new SettingsService(loadedSettings); @@ -190,7 +193,8 @@ describe('SettingsService', () => { quickActionModel: AIProviderModel.GPT_5_4_Mini, enableContextMenuActions: false, enableToolbarActions: false, - hideDrawerElements: false + hideDrawerElements: false, + chatMode: ChatMode.ReadOnly }; settingsService = new SettingsService(loadedSettings); @@ -220,7 +224,8 @@ describe('SettingsService', () => { quickActionModel: AIProviderModel.GeminiFlash_2_5, enableContextMenuActions: false, enableToolbarActions: false, - hideDrawerElements: false + hideDrawerElements: false, + chatMode: ChatMode.ReadOnly }; settingsService = new SettingsService(loadedSettings); @@ -278,7 +283,8 @@ describe('SettingsService', () => { quickActionModel: AIProviderModel.ClaudeSonnet_4_6, enableContextMenuActions: false, enableToolbarActions: false, - hideDrawerElements: false + hideDrawerElements: false, + chatMode: ChatMode.ReadOnly }; settingsService = new SettingsService(loadedSettings); }); @@ -342,23 +348,24 @@ describe('SettingsService', () => { quickActionModel: AIProviderModel.ClaudeSonnet_4_6, enableContextMenuActions: false, enableToolbarActions: false, - hideDrawerElements: false + hideDrawerElements: false, + chatMode: ChatMode.ReadOnly }; settingsService = new SettingsService(loadedSettings); + mockPlugin.saveData.mockClear(); }); it('should call plugin.saveData with current settings', async () => { - await settingsService.saveSettings(); + await settingsService.updateSettings(() => {}); expect(mockPlugin.saveData).toHaveBeenCalledWith(settingsService.settings); - expect(mockPlugin.saveData).toHaveBeenCalledTimes(1); }); it('should call plugin.saveData with updated settings after modification', async () => { - settingsService.setApiKeyForProvider(AIProvider.Claude, 'updated-key'); - settingsService.settings.userInstruction = 'Updated instruction'; - - await settingsService.saveSettings(); + await settingsService.updateSettings(settings => { + settings.apiKeys.claude = 'updated-key'; + settings.userInstruction = 'Updated instruction'; + }); expect(mockPlugin.saveData).toHaveBeenCalledWith( expect.objectContaining({ @@ -373,7 +380,7 @@ describe('SettingsService', () => { it('should handle saveData errors gracefully', async () => { mockPlugin.saveData.mockRejectedValue(new Error('Save failed')); - await expect(settingsService.saveSettings()).rejects.toThrow('Save failed'); + await expect(settingsService.updateSettings(() => {})).rejects.toThrow('Save failed'); }); }); @@ -520,7 +527,7 @@ describe('SettingsService', () => { snippetSizeLimit: 250 }); - await settingsService.saveSettings(); + await settingsService.updateSettings(() => {}); expect(mockPlugin.saveData).toHaveBeenCalledWith( expect.objectContaining({ @@ -533,10 +540,10 @@ describe('SettingsService', () => { it('should handle modified limits in saveSettings', async () => { settingsService = new SettingsService({}); - settingsService.settings.searchResultsLimit = 100; - settingsService.settings.snippetSizeLimit = 600; - - await settingsService.saveSettings(); + await settingsService.updateSettings(settings => { + settings.searchResultsLimit = 100; + settings.snippetSizeLimit = 600; + }); expect(mockPlugin.saveData).toHaveBeenCalledWith( expect.objectContaining({