import AutoStatusPlugin from '../src/main'; import { App } from 'obsidian'; // Default settings constant that matches the plugin const DEFAULT_SETTINGS = { propertyName: 'Pending tasks', enableAutoProcessing: true, excludeFolders: [] as string[], includeFolders: [] as string[], debounceDelay: 500, enableTaskCounts: false, pendingTasksCountProperty: 'Pending tasks count', totalTasksCountProperty: 'Total tasks count', countRootTasksOnly: false, }; describe('Settings Management', () => { let plugin: AutoStatusPlugin; let mockApp: App; beforeEach(() => { mockApp = new App(); plugin = new AutoStatusPlugin(mockApp, {} as any); // Initialize settings to prevent undefined errors plugin.settings = { ...DEFAULT_SETTINGS }; }); describe('loadSettings', () => { test('should load default settings when no saved data exists', async () => { plugin.loadData = jest.fn().mockResolvedValue(undefined); await plugin.loadSettings(); expect(plugin.settings).toEqual(DEFAULT_SETTINGS); }); test('should merge saved settings with defaults', async () => { const savedSettings = { propertyName: 'Custom Tasks', enableAutoProcessing: false, excludeFolders: ['Templates'], }; plugin.loadData = jest.fn().mockResolvedValue(savedSettings); await plugin.loadSettings(); expect(plugin.settings).toEqual({ ...DEFAULT_SETTINGS, propertyName: 'Custom Tasks', enableAutoProcessing: false, excludeFolders: ['Templates'], }); }); test('should fill in new task-count fields when loading legacy data', async () => { const legacySettings = { propertyName: 'Pending tasks', enableAutoProcessing: true, excludeFolders: [], includeFolders: [], debounceDelay: 500, }; plugin.loadData = jest.fn().mockResolvedValue(legacySettings); await plugin.loadSettings(); expect(plugin.settings.enableTaskCounts).toBe(false); expect(plugin.settings.pendingTasksCountProperty).toBe('Pending tasks count'); expect(plugin.settings.totalTasksCountProperty).toBe('Total tasks count'); expect(plugin.settings.countRootTasksOnly).toBe(false); }); test('should handle invalid saved data gracefully', async () => { plugin.loadData = jest.fn().mockResolvedValue(null); await plugin.loadSettings(); expect(plugin.settings).toEqual(DEFAULT_SETTINGS); }); }); describe('saveSettings', () => { test('should save current settings', async () => { plugin.saveData = jest.fn().mockResolvedValue(undefined); plugin.settings = { ...DEFAULT_SETTINGS, propertyName: 'My Tasks', enableAutoProcessing: false, excludeFolders: ['Archive'], includeFolders: ['Work'], debounceDelay: 1000, }; await plugin.saveSettings(); expect(plugin.saveData).toHaveBeenCalledWith(plugin.settings); }); test('should recreate debounced function after saving', async () => { plugin.saveData = jest.fn().mockResolvedValue(undefined); plugin.debouncedProcessFile = jest.fn(); // Ensure settings are properly initialized plugin.settings = { ...DEFAULT_SETTINGS }; const originalDebouncedFn = plugin.debouncedProcessFile; await plugin.saveSettings(); // The debounced function should be recreated expect(plugin.debouncedProcessFile).toBeDefined(); expect(plugin.debouncedProcessFile).not.toBe(originalDebouncedFn); }); }); describe('default settings validation', () => { test('should have valid default property name', () => { const defaults = { propertyName: 'Pending tasks', enableAutoProcessing: true, excludeFolders: [] as string[], includeFolders: [] as string[], debounceDelay: 500, }; expect(defaults.propertyName).toBeTruthy(); expect(typeof defaults.propertyName).toBe('string'); }); test('should have valid default processing state', () => { const defaults = { propertyName: 'Pending tasks', enableAutoProcessing: true, excludeFolders: [] as string[], includeFolders: [] as string[], debounceDelay: 500, }; expect(typeof defaults.enableAutoProcessing).toBe('boolean'); expect(defaults.enableAutoProcessing).toBe(true); }); test('should have valid default folder arrays', () => { const defaults = { propertyName: 'Pending tasks', enableAutoProcessing: true, excludeFolders: [] as string[], includeFolders: [] as string[], debounceDelay: 500, }; expect(Array.isArray(defaults.excludeFolders)).toBe(true); expect(Array.isArray(defaults.includeFolders)).toBe(true); expect(defaults.excludeFolders.length).toBe(0); expect(defaults.includeFolders.length).toBe(0); }); test('should have valid default debounce delay', () => { const defaults = { propertyName: 'Pending tasks', enableAutoProcessing: true, excludeFolders: [] as string[], includeFolders: [] as string[], debounceDelay: 500, }; expect(typeof defaults.debounceDelay).toBe('number'); expect(defaults.debounceDelay).toBeGreaterThan(0); }); }); describe('settings validation edge cases', () => { test('should handle empty string property name', async () => { const savedSettings = { propertyName: '', enableAutoProcessing: true, excludeFolders: [] as string[], includeFolders: [] as string[], debounceDelay: 500, }; plugin.loadData = jest.fn().mockResolvedValue(savedSettings); await plugin.loadSettings(); // Should accept empty string if provided expect(plugin.settings.propertyName).toBe(''); }); test('should handle negative debounce delay', async () => { const savedSettings = { propertyName: 'Tasks', enableAutoProcessing: true, excludeFolders: [] as string[], includeFolders: [] as string[], debounceDelay: -100, }; plugin.loadData = jest.fn().mockResolvedValue(savedSettings); await plugin.loadSettings(); // Should accept negative value if provided (validation happens in UI) expect(plugin.settings.debounceDelay).toBe(-100); }); test('should handle non-array folder settings', async () => { const savedSettings = { propertyName: 'Tasks', enableAutoProcessing: true, excludeFolders: 'Templates', // Should be array includeFolders: null as any, // Should be array debounceDelay: 500, }; plugin.loadData = jest.fn().mockResolvedValue(savedSettings); await plugin.loadSettings(); // Object.assign will overwrite with non-array values expect(plugin.settings.excludeFolders).toBe('Templates'); expect(plugin.settings.includeFolders).toBe(null); }); }); });