diff --git a/src/main/engine/ImportExecutionEngine.ts b/src/main/engine/ImportExecutionEngine.ts
index ce8e38c..04a932d 100644
--- a/src/main/engine/ImportExecutionEngine.ts
+++ b/src/main/engine/ImportExecutionEngine.ts
@@ -267,10 +267,16 @@ export class ImportExecutionEngine extends EventEmitter {
options: ImportExecutionOptions,
progress: (phase: string, current: number, total: number, detail?: string) => void
): Promise {
- const total = report.posts.items.length;
+ // Filter to only actual posts (postType === 'post'), skip nav_menu_item, revision, etc.
+ const postsToImport = report.posts.items.filter(item => item.wxrPost.postType === 'post');
+ const total = postsToImport.length;
- for (let i = 0; i < report.posts.items.length; i++) {
- const analyzed = report.posts.items[i];
+ // Count skipped "other" post types
+ const skippedOther = report.posts.items.length - postsToImport.length;
+ result.posts.skipped += skippedOther;
+
+ for (let i = 0; i < postsToImport.length; i++) {
+ const analyzed = postsToImport[i];
progress('posts', i + 1, total, `Processing: ${analyzed.wxrPost.title}`);
try {
diff --git a/tests/assets/import-test-cases.wxr b/tests/assets/import-test-cases.wxr
index 96424fb..8f32359 100644
--- a/tests/assets/import-test-cases.wxr
+++ b/tests/assets/import-test-cases.wxr
@@ -45,6 +45,11 @@
6. PAGE IMPORT
- Page ID 501: Standard page → becomes post with "page" category
- Page ID 502: Page with HTML content for conversion test
+
+ 7. OTHER POST TYPES (should be analyzed but NOT imported)
+ - Post ID 601: nav_menu_item → analyzed but skipped
+ - Post ID 602: revision → analyzed but skipped
+ - Post ID 603: wp_template → analyzed but skipped
-->
]]>
0
+
+
+
+
+
+
+ -
+ Home Menu Link
+ https://testblog.example.com/home-menu/
+ Mon, 01 Jan 2024 00:00:00 +0000
+
+
+ 601
+ 2024-01-01 00:00:00
+ 2024-01-01 00:00:00
+ 2024-01-01 00:00:00
+ 2024-01-01 00:00:00
+ home-menu-link
+ publish
+ nav_menu_item
+ 0
+
+
+
+ -
+ HTML Formatting Test: Basic Text Styles (Revision)
+ https://testblog.example.com/?p=602
+ Mon, 01 Jan 2024 09:00:00 +0000
+
+ Old revision content that should be ignored.
]]>
+ 602
+ 2024-01-01 09:00:00
+ 2024-01-01 09:00:00
+ 2024-01-01 09:00:00
+ 2024-01-01 09:00:00
+ 101-revision-v1
+ inherit
+ revision
+ 101
+
+
+
+ -
+ Single Post Template
+ https://testblog.example.com/wp_template/single/
+ Tue, 02 Jan 2024 00:00:00 +0000
+
+
+
+]]>
+ 603
+ 2024-01-02 00:00:00
+ 2024-01-02 00:00:00
+ 2024-01-02 00:00:00
+ 2024-01-02 00:00:00
+ single
+ publish
+ wp_template
+ 0
+
+
diff --git a/tests/engine/ImportExecutionEngine.e2e.test.ts b/tests/engine/ImportExecutionEngine.e2e.test.ts
index 81dccb3..782f968 100644
--- a/tests/engine/ImportExecutionEngine.e2e.test.ts
+++ b/tests/engine/ImportExecutionEngine.e2e.test.ts
@@ -11,6 +11,7 @@
* 4. Conflict Resolution - verifies ignore/overwrite/import behaviors
* 5. Media Import - verifies media file handling with post linkage
* 6. Page Import - verifies pages become posts with "page" category
+ * 7. Other Post Types - verifies nav_menu_item, revision, wp_template are analyzed but not imported
*/
import { describe, it, expect, beforeEach, vi, afterEach } from 'vitest';
@@ -1375,4 +1376,145 @@ describe('ImportExecutionEngine E2E Tests', () => {
expect(result.wpIdToPostId.size).toBeGreaterThanOrEqual(2); // post1, post3
});
});
+
+ // ==========================================================================
+ // SECTION 7: OTHER POST TYPES (analyzed but not imported)
+ // ==========================================================================
+
+ describe('Other Post Types (analyzed but not imported)', () => {
+ it('should include nav_menu_item, revision, and wp_template in WXR parsed data', () => {
+ // Verify the WXR parser includes these in the posts array
+ const navMenuItem = wxrData.posts.find(p => p.wpId === 601);
+ const revision = wxrData.posts.find(p => p.wpId === 602);
+ const wpTemplate = wxrData.posts.find(p => p.wpId === 603);
+
+ expect(navMenuItem).toBeDefined();
+ expect(navMenuItem!.postType).toBe('nav_menu_item');
+ expect(navMenuItem!.title).toBe('Home Menu Link');
+
+ expect(revision).toBeDefined();
+ expect(revision!.postType).toBe('revision');
+ expect(revision!.slug).toBe('101-revision-v1');
+
+ expect(wpTemplate).toBeDefined();
+ expect(wpTemplate!.postType).toBe('wp_template');
+ expect(wpTemplate!.title).toBe('Single Post Template');
+ });
+
+ it('should include other post types in analysis report but skip them during import', async () => {
+ // Find the "other" post types from parsed WXR
+ const navMenuItem = wxrData.posts.find(p => p.wpId === 601)!;
+ const revision = wxrData.posts.find(p => p.wpId === 602)!;
+ const wpTemplate = wxrData.posts.find(p => p.wpId === 603)!;
+
+ // Also include a regular post to verify it gets imported
+ const regularPost = wxrData.posts.find(p => p.wpId === 101)!;
+
+ // Create analysis report that includes both regular posts and "other" post types
+ const report: ImportAnalysisReport = {
+ wxrData: wxrData,
+ posts: {
+ total: 4,
+ new: 4,
+ update: 0,
+ conflict: 0,
+ items: [
+ {
+ wxrPost: regularPost,
+ status: 'new' as PostAnalysisStatus,
+ contentHash: 'hash1',
+ markdownPreview: '',
+ },
+ {
+ wxrPost: navMenuItem,
+ status: 'new' as PostAnalysisStatus,
+ contentHash: 'hash2',
+ markdownPreview: '',
+ },
+ {
+ wxrPost: revision,
+ status: 'new' as PostAnalysisStatus,
+ contentHash: 'hash3',
+ markdownPreview: '',
+ },
+ {
+ wxrPost: wpTemplate,
+ status: 'new' as PostAnalysisStatus,
+ contentHash: 'hash4',
+ markdownPreview: '',
+ },
+ ],
+ },
+ pages: { total: 0, new: 0, update: 0, conflict: 0, items: [] },
+ media: { total: 0, new: 0, update: 0, conflict: 0, missing: 0, items: [] },
+ tags: [],
+ categories: [],
+ site: wxrData.site,
+ macros: { totalUniqueMacros: 0, totalMacroUsages: 0, allMapped: true, macros: [] },
+ };
+
+ const result = await engine.executeImport(report, {});
+
+ // Verify only the regular post was imported
+ expect(result.posts.imported).toBe(1);
+
+ // The 3 "other" post types should be skipped
+ expect(result.posts.skipped).toBe(3);
+ expect(result.posts.errors).toBe(0);
+
+ // Verify only one post was actually written to database/filesystem
+ expect(insertedPosts.length).toBe(1);
+ expect(insertedPosts[0].slug).toBe('html-formatting-basic');
+
+ // Verify no files were written for nav_menu_item, revision, or wp_template
+ const writtenSlugs = writtenFiles.map(f => f.path);
+ expect(writtenSlugs.some(p => p.includes('home-menu-link'))).toBe(false);
+ expect(writtenSlugs.some(p => p.includes('101-revision-v1'))).toBe(false);
+ expect(writtenSlugs.some(p => p.includes('single'))).toBe(false);
+ });
+
+ it('should correctly count skipped "other" types in result summary', async () => {
+ // Test with only "other" post types to verify counting
+ const navMenuItem = wxrData.posts.find(p => p.wpId === 601)!;
+ const revision = wxrData.posts.find(p => p.wpId === 602)!;
+
+ const report: ImportAnalysisReport = {
+ wxrData: wxrData,
+ posts: {
+ total: 2,
+ new: 2,
+ update: 0,
+ conflict: 0,
+ items: [
+ {
+ wxrPost: navMenuItem,
+ status: 'new' as PostAnalysisStatus,
+ contentHash: 'hash1',
+ markdownPreview: '',
+ },
+ {
+ wxrPost: revision,
+ status: 'new' as PostAnalysisStatus,
+ contentHash: 'hash2',
+ markdownPreview: '',
+ },
+ ],
+ },
+ pages: { total: 0, new: 0, update: 0, conflict: 0, items: [] },
+ media: { total: 0, new: 0, update: 0, conflict: 0, missing: 0, items: [] },
+ tags: [],
+ categories: [],
+ site: wxrData.site,
+ macros: { totalUniqueMacros: 0, totalMacroUsages: 0, allMapped: true, macros: [] },
+ };
+
+ const result = await engine.executeImport(report, {});
+
+ // All should be skipped, none imported
+ expect(result.posts.imported).toBe(0);
+ expect(result.posts.skipped).toBe(2);
+ expect(result.posts.errors).toBe(0);
+ expect(insertedPosts.length).toBe(0);
+ });
+ });
});