222 lines
7.7 KiB
TypeScript
222 lines
7.7 KiB
TypeScript
/**
|
|
* Tests for SettingsView component behavior
|
|
* Validates VS Code-style structured preferences with Dropbox sync settings
|
|
*/
|
|
|
|
import { describe, it, expect, beforeEach, vi } from 'vitest';
|
|
import { useAppStore } from '../../../src/renderer/store/appStore';
|
|
|
|
// Direct store access
|
|
const getStore = () => useAppStore.getState();
|
|
const setState = useAppStore.setState;
|
|
|
|
describe('SettingsView Behavior', () => {
|
|
beforeEach(() => {
|
|
setState({
|
|
syncConfigured: false,
|
|
syncStatus: 'idle',
|
|
});
|
|
vi.clearAllMocks();
|
|
localStorage.clear();
|
|
});
|
|
|
|
describe('Settings Categories', () => {
|
|
it('should have sync settings as a category in the store', () => {
|
|
// The activeView: 'settings' should be a valid view
|
|
getStore().setActiveView('settings');
|
|
expect(getStore().activeView).toBe('settings');
|
|
});
|
|
|
|
it('should persist preferred editor mode', () => {
|
|
getStore().setPreferredEditorMode('markdown');
|
|
expect(getStore().preferredEditorMode).toBe('markdown');
|
|
});
|
|
});
|
|
|
|
describe('Turso Cloud Sync Configuration', () => {
|
|
it('should call sync.configure with Turso credentials', async () => {
|
|
const mockConfigure = vi.fn().mockResolvedValue(undefined);
|
|
(window as any).electronAPI.sync.configure = mockConfigure;
|
|
|
|
await window.electronAPI?.sync.configure({
|
|
tursoUrl: 'libsql://test.turso.io',
|
|
tursoAuthToken: 'test-token',
|
|
autoSync: true,
|
|
syncInterval: 5,
|
|
});
|
|
|
|
expect(mockConfigure).toHaveBeenCalledWith({
|
|
tursoUrl: 'libsql://test.turso.io',
|
|
tursoAuthToken: 'test-token',
|
|
autoSync: true,
|
|
syncInterval: 5,
|
|
});
|
|
});
|
|
|
|
it('should update syncConfigured status after successful configure', () => {
|
|
getStore().setSyncConfigured(true);
|
|
expect(getStore().syncConfigured).toBe(true);
|
|
});
|
|
});
|
|
|
|
describe('Dropbox Sync Configuration', () => {
|
|
it('should call dropbox.configure with Dropbox credentials', async () => {
|
|
const mockConfigure = vi.fn().mockResolvedValue(undefined);
|
|
(window as any).electronAPI.dropbox = {
|
|
configure: mockConfigure,
|
|
isConfigured: vi.fn(),
|
|
getStatus: vi.fn(),
|
|
syncAll: vi.fn(),
|
|
startWatching: vi.fn(),
|
|
stopWatching: vi.fn(),
|
|
startPolling: vi.fn(),
|
|
stopPolling: vi.fn(),
|
|
getConflicts: vi.fn(),
|
|
resolveConflict: vi.fn(),
|
|
getLastSyncTime: vi.fn(),
|
|
};
|
|
|
|
await window.electronAPI?.dropbox?.configure({
|
|
accessToken: 'dbx-test-token',
|
|
appKey: 'test-app-key',
|
|
remotePath: '/blog',
|
|
});
|
|
|
|
expect(mockConfigure).toHaveBeenCalledWith({
|
|
accessToken: 'dbx-test-token',
|
|
appKey: 'test-app-key',
|
|
remotePath: '/blog',
|
|
});
|
|
});
|
|
|
|
it('should check dropbox configuration status', async () => {
|
|
const mockIsConfigured = vi.fn().mockResolvedValue(true);
|
|
(window as any).electronAPI.dropbox = {
|
|
...((window as any).electronAPI.dropbox || {}),
|
|
isConfigured: mockIsConfigured,
|
|
};
|
|
|
|
const result = await window.electronAPI?.dropbox?.isConfigured();
|
|
expect(mockIsConfigured).toHaveBeenCalled();
|
|
expect(result).toBe(true);
|
|
});
|
|
|
|
it('should trigger Dropbox full sync', async () => {
|
|
const mockSyncAll = vi.fn().mockResolvedValue({ uploaded: 0, downloaded: 0, conflicts: 0 });
|
|
(window as any).electronAPI.dropbox = {
|
|
...((window as any).electronAPI.dropbox || {}),
|
|
syncAll: mockSyncAll,
|
|
};
|
|
|
|
await window.electronAPI?.dropbox?.syncAll();
|
|
expect(mockSyncAll).toHaveBeenCalled();
|
|
});
|
|
|
|
it('should get last sync time', async () => {
|
|
const mockGetLastSyncTime = vi.fn().mockResolvedValue('2026-02-10T12:00:00Z');
|
|
(window as any).electronAPI.dropbox = {
|
|
...((window as any).electronAPI.dropbox || {}),
|
|
getLastSyncTime: mockGetLastSyncTime,
|
|
};
|
|
|
|
const result = await window.electronAPI?.dropbox?.getLastSyncTime();
|
|
expect(result).toBe('2026-02-10T12:00:00Z');
|
|
});
|
|
});
|
|
|
|
describe('Credentials Storage', () => {
|
|
it('should save credentials to localStorage', () => {
|
|
const creds = {
|
|
tursoUrl: 'libsql://test.turso.io',
|
|
tursoToken: 'test-token',
|
|
dropboxAccessToken: 'dbx-token',
|
|
dropboxAppKey: 'dbx-key',
|
|
dropboxRemotePath: '/blog',
|
|
};
|
|
localStorage.setItem('bds-credentials', JSON.stringify(creds));
|
|
|
|
const saved = JSON.parse(localStorage.getItem('bds-credentials') || '{}');
|
|
expect(saved.tursoUrl).toBe('libsql://test.turso.io');
|
|
expect(saved.dropboxAccessToken).toBe('dbx-token');
|
|
expect(saved.dropboxAppKey).toBe('dbx-key');
|
|
expect(saved.dropboxRemotePath).toBe('/blog');
|
|
});
|
|
|
|
it('should load credentials from localStorage', () => {
|
|
const creds = {
|
|
tursoUrl: 'libsql://saved.turso.io',
|
|
tursoToken: 'saved-token',
|
|
dropboxAccessToken: 'saved-dbx-token',
|
|
};
|
|
localStorage.setItem('bds-credentials', JSON.stringify(creds));
|
|
|
|
const loaded = JSON.parse(localStorage.getItem('bds-credentials') || '{}');
|
|
expect(loaded.tursoUrl).toBe('libsql://saved.turso.io');
|
|
expect(loaded.dropboxAccessToken).toBe('saved-dbx-token');
|
|
});
|
|
|
|
it('should handle clearing sync credentials independently', () => {
|
|
const creds = {
|
|
tursoUrl: 'libsql://test.turso.io',
|
|
tursoToken: 'test-token',
|
|
dropboxAccessToken: 'dbx-token',
|
|
dropboxAppKey: 'dbx-key',
|
|
};
|
|
localStorage.setItem('bds-credentials', JSON.stringify(creds));
|
|
|
|
// Clear only Turso credentials
|
|
const loaded = JSON.parse(localStorage.getItem('bds-credentials') || '{}');
|
|
const cleared = { ...loaded, tursoUrl: '', tursoToken: '' };
|
|
localStorage.setItem('bds-credentials', JSON.stringify(cleared));
|
|
|
|
const result = JSON.parse(localStorage.getItem('bds-credentials') || '{}');
|
|
expect(result.tursoUrl).toBe('');
|
|
expect(result.tursoToken).toBe('');
|
|
// Dropbox credentials should be untouched
|
|
expect(result.dropboxAccessToken).toBe('dbx-token');
|
|
expect(result.dropboxAppKey).toBe('dbx-key');
|
|
});
|
|
|
|
it('should handle clearing Dropbox credentials independently', () => {
|
|
const creds = {
|
|
tursoUrl: 'libsql://test.turso.io',
|
|
tursoToken: 'test-token',
|
|
dropboxAccessToken: 'dbx-token',
|
|
dropboxAppKey: 'dbx-key',
|
|
dropboxRemotePath: '/blog',
|
|
};
|
|
localStorage.setItem('bds-credentials', JSON.stringify(creds));
|
|
|
|
// Clear only Dropbox credentials
|
|
const loaded = JSON.parse(localStorage.getItem('bds-credentials') || '{}');
|
|
const cleared = { ...loaded, dropboxAccessToken: '', dropboxAppKey: '', dropboxRemotePath: '' };
|
|
localStorage.setItem('bds-credentials', JSON.stringify(cleared));
|
|
|
|
const result = JSON.parse(localStorage.getItem('bds-credentials') || '{}');
|
|
// Turso credentials should be untouched
|
|
expect(result.tursoUrl).toBe('libsql://test.turso.io');
|
|
expect(result.tursoToken).toBe('test-token');
|
|
expect(result.dropboxAccessToken).toBe('');
|
|
expect(result.dropboxAppKey).toBe('');
|
|
});
|
|
});
|
|
|
|
describe('Data Management Settings', () => {
|
|
it('should call rebuild posts from files', async () => {
|
|
const mockRebuild = vi.fn().mockResolvedValue(undefined);
|
|
(window as any).electronAPI.posts.rebuildFromFiles = mockRebuild;
|
|
|
|
await window.electronAPI?.posts.rebuildFromFiles();
|
|
expect(mockRebuild).toHaveBeenCalled();
|
|
});
|
|
|
|
it('should call rebuild media from files', async () => {
|
|
const mockRebuild = vi.fn().mockResolvedValue(undefined);
|
|
(window as any).electronAPI.media.rebuildFromFiles = mockRebuild;
|
|
|
|
await window.electronAPI?.media.rebuildFromFiles();
|
|
expect(mockRebuild).toHaveBeenCalled();
|
|
});
|
|
});
|
|
});
|