feat: more cleanup work in UI
This commit is contained in:
163
tests/renderer/store/appStore.test.ts
Normal file
163
tests/renderer/store/appStore.test.ts
Normal file
@@ -0,0 +1,163 @@
|
||||
/**
|
||||
* Tests for the app store
|
||||
* Validates state management behavior for posts, dirty tracking, and UI state
|
||||
*/
|
||||
|
||||
import { describe, it, expect, beforeEach } from 'vitest';
|
||||
import { useAppStore, PostData } from '../../../src/renderer/store/appStore';
|
||||
|
||||
// Helper to create a mock post
|
||||
const createMockPost = (overrides: Partial<PostData> = {}): PostData => ({
|
||||
id: `post-${Date.now()}-${Math.random().toString(36).substring(7)}`,
|
||||
title: 'Test Post',
|
||||
slug: 'test-post',
|
||||
content: '# Test Content',
|
||||
status: 'draft',
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
tags: [],
|
||||
categories: [],
|
||||
...overrides,
|
||||
});
|
||||
|
||||
// Direct store access without React rendering
|
||||
const getStore = () => useAppStore.getState();
|
||||
const setState = useAppStore.setState;
|
||||
|
||||
describe('AppStore', () => {
|
||||
beforeEach(() => {
|
||||
// Reset store state before each test
|
||||
setState({
|
||||
posts: [],
|
||||
selectedPostId: null,
|
||||
dirtyPosts: new Set(),
|
||||
});
|
||||
});
|
||||
|
||||
describe('Post Management', () => {
|
||||
it('should add a post to the store', () => {
|
||||
const post = createMockPost({ id: 'post-1', title: 'New Post' });
|
||||
|
||||
getStore().addPost(post);
|
||||
|
||||
expect(getStore().posts).toHaveLength(1);
|
||||
expect(getStore().posts[0].title).toBe('New Post');
|
||||
});
|
||||
|
||||
it('should update an existing post in the store', () => {
|
||||
const post = createMockPost({ id: 'post-1', title: 'Original Title' });
|
||||
|
||||
getStore().addPost(post);
|
||||
getStore().updatePost('post-1', { title: 'Updated Title' });
|
||||
|
||||
expect(getStore().posts).toHaveLength(1);
|
||||
expect(getStore().posts[0].title).toBe('Updated Title');
|
||||
});
|
||||
|
||||
it('should preserve other post fields when updating', () => {
|
||||
const post = createMockPost({
|
||||
id: 'post-1',
|
||||
title: 'Original',
|
||||
content: 'Original Content',
|
||||
tags: ['tag1'],
|
||||
});
|
||||
|
||||
getStore().addPost(post);
|
||||
getStore().updatePost('post-1', { title: 'Updated Title' });
|
||||
|
||||
expect(getStore().posts[0].content).toBe('Original Content');
|
||||
expect(getStore().posts[0].tags).toEqual(['tag1']);
|
||||
});
|
||||
|
||||
it('should remove a post from the store', () => {
|
||||
const post = createMockPost({ id: 'post-1' });
|
||||
|
||||
getStore().addPost(post);
|
||||
getStore().removePost('post-1');
|
||||
|
||||
expect(getStore().posts).toHaveLength(0);
|
||||
});
|
||||
|
||||
it('should clear selectedPostId when the selected post is removed', () => {
|
||||
const post = createMockPost({ id: 'post-1' });
|
||||
|
||||
getStore().addPost(post);
|
||||
getStore().setSelectedPost('post-1');
|
||||
|
||||
expect(getStore().selectedPostId).toBe('post-1');
|
||||
|
||||
getStore().removePost('post-1');
|
||||
|
||||
expect(getStore().selectedPostId).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
describe('Dirty Tracking', () => {
|
||||
it('should mark a post as dirty', () => {
|
||||
getStore().markDirty('post-1');
|
||||
|
||||
expect(getStore().isDirty('post-1')).toBe(true);
|
||||
});
|
||||
|
||||
it('should mark a post as clean', () => {
|
||||
getStore().markDirty('post-1');
|
||||
getStore().markClean('post-1');
|
||||
|
||||
expect(getStore().isDirty('post-1')).toBe(false);
|
||||
});
|
||||
|
||||
it('should track multiple dirty posts independently', () => {
|
||||
getStore().markDirty('post-1');
|
||||
getStore().markDirty('post-2');
|
||||
|
||||
expect(getStore().isDirty('post-1')).toBe(true);
|
||||
expect(getStore().isDirty('post-2')).toBe(true);
|
||||
|
||||
getStore().markClean('post-1');
|
||||
|
||||
expect(getStore().isDirty('post-1')).toBe(false);
|
||||
expect(getStore().isDirty('post-2')).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false for non-dirty posts', () => {
|
||||
expect(getStore().isDirty('non-existent-post')).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Post Selection', () => {
|
||||
it('should set selected post ID', () => {
|
||||
getStore().setSelectedPost('post-1');
|
||||
|
||||
expect(getStore().selectedPostId).toBe('post-1');
|
||||
});
|
||||
|
||||
it('should clear selected post ID when set to null', () => {
|
||||
getStore().setSelectedPost('post-1');
|
||||
getStore().setSelectedPost(null);
|
||||
|
||||
expect(getStore().selectedPostId).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
describe('UI State', () => {
|
||||
it('should toggle sidebar visibility', () => {
|
||||
const initialState = getStore().sidebarVisible;
|
||||
|
||||
getStore().toggleSidebar();
|
||||
|
||||
expect(getStore().sidebarVisible).toBe(!initialState);
|
||||
});
|
||||
|
||||
it('should set active view', () => {
|
||||
getStore().setActiveView('media');
|
||||
|
||||
expect(getStore().activeView).toBe('media');
|
||||
});
|
||||
|
||||
it('should set preferred editor mode', () => {
|
||||
getStore().setPreferredEditorMode('markdown');
|
||||
|
||||
expect(getStore().preferredEditorMode).toBe('markdown');
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user