mirror of
https://github.com/amitwh/markdown-converter.git
synced 2026-08-02 18:10:18 +05:30
feat: enhance WelcomeDialog, export dialogs, GitStatusPanel, add CommandPalette, FindReplaceBar, and new converter dialogs
- WelcomeDialog: add quick start, feature showcase, keyboard shortcuts, recent files, version display - ExportDocxDialog/ExportHtmlDialog/ExportPdfDialog: add header/footer, paper size, margin controls - GitStatusPanel: full staging/unstaging, discard, commit workflow - CommandPalette: fuzzy command search with keyboard navigation - FindReplaceBar: find/replace with regex, case, whole-word options - New dialogs: BatchMediaConverterDialog, HeaderFooterDialog, PdfEditorDialog, UniversalConverterDialog - Tests: comprehensive coverage for all new/updated components
This commit is contained in:
@@ -0,0 +1,91 @@
|
||||
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
||||
import { render, screen, waitFor } from '@testing-library/react';
|
||||
import userEvent from '@testing-library/user-event';
|
||||
import { HeaderFooterDialog } from '@/components/modals/HeaderFooterDialog';
|
||||
import { useAppStore } from '@/stores/app-store';
|
||||
import { useSettingsStore } from '@/stores/settings-store';
|
||||
|
||||
const defaultSettings = {
|
||||
headerEnabled: false,
|
||||
footerEnabled: false,
|
||||
headerLeft: '',
|
||||
headerCenter: '',
|
||||
headerRight: '',
|
||||
footerLeft: '',
|
||||
footerCenter: '',
|
||||
footerRight: '',
|
||||
logoPosition: 'none',
|
||||
logoPath: null,
|
||||
};
|
||||
|
||||
const mockGetSettings = vi.fn().mockResolvedValue(defaultSettings);
|
||||
const mockSaveSettings = vi.fn().mockResolvedValue(undefined);
|
||||
const mockBrowseLogo = vi.fn().mockResolvedValue('/path/to/logo.png');
|
||||
|
||||
beforeEach(() => {
|
||||
localStorage.clear();
|
||||
vi.clearAllMocks();
|
||||
useSettingsStore.setState(useSettingsStore.getInitialState());
|
||||
useAppStore.setState({ modal: { kind: null } } as any);
|
||||
(window.electronAPI as any) = {
|
||||
headerFooter: {
|
||||
getSettings: mockGetSettings,
|
||||
saveSettings: mockSaveSettings,
|
||||
browseLogo: mockBrowseLogo,
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
describe('HeaderFooterDialog', () => {
|
||||
it('loads settings from electronAPI on mount', async () => {
|
||||
render(<HeaderFooterDialog />);
|
||||
await waitFor(() => expect(mockGetSettings).toHaveBeenCalled());
|
||||
expect(screen.getByText(/header & footer/i)).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('toggles header enabled checkbox', async () => {
|
||||
render(<HeaderFooterDialog />);
|
||||
await waitFor(() => expect(screen.getByText(/header & footer/i)).toBeInTheDocument());
|
||||
await userEvent.click(screen.getByRole('checkbox', { name: /enable header/i }));
|
||||
expect(screen.getByRole('checkbox', { name: /enable header/i })).toBeChecked();
|
||||
});
|
||||
|
||||
it('toggles footer enabled checkbox', async () => {
|
||||
render(<HeaderFooterDialog />);
|
||||
await waitFor(() => expect(screen.getByText(/header & footer/i)).toBeInTheDocument());
|
||||
await userEvent.click(screen.getByRole('checkbox', { name: /enable footer/i }));
|
||||
expect(screen.getByRole('checkbox', { name: /enable footer/i })).toBeChecked();
|
||||
});
|
||||
|
||||
it('saves settings via electronAPI on Save', async () => {
|
||||
render(<HeaderFooterDialog />);
|
||||
await waitFor(() => expect(screen.getByText(/header & footer/i)).toBeInTheDocument());
|
||||
await userEvent.click(screen.getByRole('button', { name: /^save$/i }));
|
||||
await waitFor(() => expect(mockSaveSettings).toHaveBeenCalled());
|
||||
});
|
||||
|
||||
it('closes modal on Cancel', async () => {
|
||||
render(<HeaderFooterDialog />);
|
||||
await waitFor(() => expect(screen.getByText(/header & footer/i)).toBeInTheDocument());
|
||||
await userEvent.click(screen.getByRole('button', { name: /^cancel$/i }));
|
||||
expect(useAppStore.getState().modal).toEqual({ kind: null });
|
||||
});
|
||||
|
||||
it('inserts dynamic field token into header input', async () => {
|
||||
mockGetSettings.mockResolvedValue({ ...defaultSettings, headerEnabled: true });
|
||||
render(<HeaderFooterDialog />);
|
||||
await waitFor(() => expect(screen.getByText(/header & footer/i)).toBeInTheDocument());
|
||||
const tokenButton = screen.getAllByTitle('Page')[0];
|
||||
await userEvent.click(tokenButton);
|
||||
expect(screen.getByLabelText(/header left/i)).toHaveValue('$PAGE$');
|
||||
});
|
||||
|
||||
it('shows logo browse when logo position is set to left', async () => {
|
||||
render(<HeaderFooterDialog />);
|
||||
await waitFor(() => expect(screen.getByText(/header & footer/i)).toBeInTheDocument());
|
||||
const logoSelect = screen.getByRole('combobox', { name: /logo position/i });
|
||||
await userEvent.click(logoSelect);
|
||||
await userEvent.click(screen.getByRole('option', { name: 'Left' }));
|
||||
expect(screen.getByRole('button', { name: /^browse$/i })).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user