This repository has been archived on 2026-05-02. You can view files and clone it, but you cannot make any changes to its state, such as pushing and creating new issues, pull requests or comments.
obsidian-plugin-auto-task-s.../test/settings-management.test.ts
Felipe M. d113c1c027
All checks were successful
CI / build (push) Successful in 16s
Add optional task count properties with structural root-task detection
Introduces opt-in pending/total task count frontmatter fields and a
"count root tasks only" mode. Root tasks are detected structurally by
walking the list tree, so tasks nested under non-task bullets (e.g.
"- **Action items**:") are correctly classified as root.

Also updates the manifest author metadata.
2026-04-14 09:50:45 +02:00

223 lines
6.9 KiB
TypeScript

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);
});
});
});