fix: menu editor crashed category meta data
This commit is contained in:
@@ -88,6 +88,24 @@ describe('MenuEngine', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('preserves custom title for category archive entries when OPML includes both text and title', async () => {
|
||||
const menuPath = normalizePath(`${menuEngine.getMetaDir()}/menu.opml`);
|
||||
mockFiles.set(
|
||||
menuPath,
|
||||
`<?xml version="1.0" encoding="UTF-8"?>\n<opml version="2.0">\n <head><title>Blog Menu</title></head>\n <body>\n <outline id="menu-home" text="Home" type="home" pageSlug="home"/>\n <outline id="cat-news" text="news" title="Editorial Highlights" type="category-archive" categoryName="news"/>\n </body>\n</opml>`,
|
||||
);
|
||||
|
||||
const result = await menuEngine.getMenu();
|
||||
|
||||
expect(result.items).toHaveLength(2);
|
||||
expect(result.items[1]).toMatchObject({
|
||||
id: 'cat-news',
|
||||
kind: 'category-archive',
|
||||
categoryName: 'news',
|
||||
title: 'Editorial Highlights',
|
||||
});
|
||||
});
|
||||
|
||||
it('writes menu state as OPML and can read it back', async () => {
|
||||
const saved = await menuEngine.saveMenu({
|
||||
items: [
|
||||
@@ -130,4 +148,27 @@ describe('MenuEngine', () => {
|
||||
|
||||
expect(saved.items.some((item) => item.id === 'menu-home')).toBe(true);
|
||||
});
|
||||
|
||||
it('persists category archives as menu references without category metadata fields', async () => {
|
||||
await menuEngine.saveMenu({
|
||||
items: [
|
||||
{
|
||||
id: 'cat-news',
|
||||
title: 'Newsroom',
|
||||
kind: 'category-archive',
|
||||
categoryName: 'news',
|
||||
children: [],
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
const menuPath = normalizePath(`${menuEngine.getMetaDir()}/menu.opml`);
|
||||
const xml = mockFiles.get(menuPath);
|
||||
|
||||
expect(xml).toBeDefined();
|
||||
expect(xml).toContain('categoryName="news"');
|
||||
expect(xml).toContain('text="Newsroom"');
|
||||
expect(xml).not.toContain('renderInLists');
|
||||
expect(xml).not.toContain('showTitle');
|
||||
});
|
||||
});
|
||||
@@ -27,6 +27,13 @@ describe('MenuEditorView entry editor', () => {
|
||||
meta: {
|
||||
...(window as any).electronAPI?.meta,
|
||||
getCategories: vi.fn().mockResolvedValue(['news', 'tech']),
|
||||
getProjectMetadata: vi.fn().mockResolvedValue({
|
||||
name: 'Project 1',
|
||||
categoryMetadata: {
|
||||
news: { title: 'Newsroom', renderInLists: true, showTitle: true },
|
||||
tech: { title: 'Technology', renderInLists: true, showTitle: true },
|
||||
},
|
||||
}),
|
||||
},
|
||||
posts: {
|
||||
...(window as any).electronAPI?.posts,
|
||||
@@ -228,4 +235,44 @@ describe('MenuEditorView entry editor', () => {
|
||||
expect(screen.queryByText(/^submenu$/i)).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('uses category titles for suggestions and outline while saving category slug internally', async () => {
|
||||
render(<MenuEditorView />);
|
||||
|
||||
const categoryButton = await screen.findByRole('button', { name: /add category archive/i });
|
||||
fireEvent.click(categoryButton);
|
||||
|
||||
const input = await screen.findByPlaceholderText(/type a category name/i);
|
||||
fireEvent.input(input, { target: { value: 'room' } });
|
||||
|
||||
const suggestion = await screen.findByRole('button', { name: /newsroom/i });
|
||||
fireEvent.click(suggestion);
|
||||
|
||||
expect(screen.getByText('Newsroom')).toBeInTheDocument();
|
||||
|
||||
const saveButton = screen.getByRole('button', { name: /^save menu$/i });
|
||||
fireEvent.click(saveButton);
|
||||
|
||||
const saveMock = (window as any).electronAPI.menu.save;
|
||||
expect(saveMock).toHaveBeenCalled();
|
||||
const payload = saveMock.mock.calls[0][0];
|
||||
|
||||
const categoryItem = payload.items.find((item: any) => item.kind === 'category-archive');
|
||||
expect(categoryItem).toBeDefined();
|
||||
expect(categoryItem.title).toBe('Newsroom');
|
||||
expect(categoryItem.categoryName).toBe('news');
|
||||
});
|
||||
|
||||
it('allows creating a new category archive from free text', async () => {
|
||||
const { container } = render(<MenuEditorView />);
|
||||
|
||||
const categoryButton = await screen.findByRole('button', { name: /add category archive/i });
|
||||
fireEvent.click(categoryButton);
|
||||
|
||||
const input = await screen.findByPlaceholderText(/type a category name/i);
|
||||
fireEvent.input(input, { target: { value: 'not-existing-category' } });
|
||||
|
||||
const createSuggestion = container.querySelector('.tag-suggestion.create-new');
|
||||
expect(createSuggestion).not.toBeNull();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user