#!/usr/bin/env node /** * TDD Tests for Intelligent Save Filename Generation Recovery */ const { TestRunner } = require('./test_runner.js'); const runner = new TestRunner(); // Test intelligent filename generation functionality runner.describe('Intelligent Save Filename Generation System', () => { runner.it('should have generateSaveFilename method in MarkitectCleanEditor', async () => { // Load editor delete require.cache[require.resolve('/home/worsch/markitect_project/markitect/static/editor.js')]; require('/home/worsch/markitect_project/markitect/static/editor.js'); if (global.MarkitectCleanEditor) { const container = document.createElement('div'); const editor = new global.MarkitectCleanEditor('# Test\n\nContent', container); const hasGenerateSaveFilename = typeof editor.generateSaveFilename === 'function'; runner.expect(hasGenerateSaveFilename).toBeTruthy(); } }); runner.it('should use original filename from options when available', async () => { if (global.MarkitectCleanEditor) { const container = document.createElement('div'); const editor = new global.MarkitectCleanEditor('# Test\n\nContent', container, { originalFilename: 'my-document.md' }); const filename = editor.generateSaveFilename(); runner.expect(filename).toBe('my-document.md'); } }); runner.it('should extract filename from page title when no original filename', async () => { if (global.MarkitectCleanEditor) { // Set a mock document title const originalTitle = document.title; document.title = 'My Amazing Document | Website'; const container = document.createElement('div'); const editor = new global.MarkitectCleanEditor('# Test\n\nContent', container); const filename = editor.generateSaveFilename(); runner.expect(filename).toBe('My-Amazing-Document.md'); // Restore original title document.title = originalTitle; } }); runner.it('should extract filename from URL pathname when no title', async () => { if (global.MarkitectCleanEditor) { // Mock window.location const originalLocation = global.location; global.location = { pathname: '/docs/user-guide/getting-started' }; const container = document.createElement('div'); const editor = new global.MarkitectCleanEditor('# Test\n\nContent', container); const filename = editor.generateSaveFilename(); runner.expect(filename).toBe('getting-started.md'); // Restore original location global.location = originalLocation; } }); runner.it('should extract filename from first heading when other methods fail', async () => { if (global.MarkitectCleanEditor) { const container = document.createElement('div'); const markdownContent = '# Advanced JavaScript Patterns\n\nThis is a guide to advanced patterns.'; const editor = new global.MarkitectCleanEditor(markdownContent, container); const filename = editor.generateSaveFilename(); runner.expect(filename).toBe('Advanced-JavaScript-Patterns.md'); } }); runner.it('should use timestamp when all other methods fail', async () => { if (global.MarkitectCleanEditor) { const container = document.createElement('div'); const markdownContent = 'Just some content without any headings or special info.'; const editor = new global.MarkitectCleanEditor(markdownContent, container); const filename = editor.generateSaveFilename(); // Should start with 'document-' and end with '.md' runner.expect(filename.startsWith('document-')).toBeTruthy(); runner.expect(filename.endsWith('.md')).toBeTruthy(); // Should contain timestamp const timestampPart = filename.replace('document-', '').replace('.md', ''); runner.expect(timestampPart.length).toBeGreaterThan(8); // YYYYMMDD format or longer } }); runner.it('should sanitize filenames to be filesystem-safe', async () => { if (global.MarkitectCleanEditor) { const container = document.createElement('div'); const markdownContent = '# This/Has\\Bad:Characters*And?More\n\nContent'; const editor = new global.MarkitectCleanEditor(markdownContent, container); const filename = editor.generateSaveFilename(); // Should not contain filesystem-unsafe characters runner.expect(filename).not.toMatch(/[\/\\:*?"<>|]/); runner.expect(filename).toBe('This-Has-Bad-Characters-And-More-Stuff.md'); } }); runner.it('should handle edge cases like empty content gracefully', async () => { if (global.MarkitectCleanEditor) { const container = document.createElement('div'); const editor = new global.MarkitectCleanEditor('', container); const filename = editor.generateSaveFilename(); runner.expect(filename.endsWith('.md')).toBeTruthy(); runner.expect(filename.length).toBeGreaterThan(3); // More than just '.md' } }); runner.it('should prefer higher priority methods over lower priority', async () => { if (global.MarkitectCleanEditor) { const container = document.createElement('div'); const markdownContent = '# Content Heading\n\nSome content'; const editor = new global.MarkitectCleanEditor(markdownContent, container, { originalFilename: 'priority-test.md' }); const filename = editor.generateSaveFilename(); // Should use original filename (method 1) over heading (method 4) runner.expect(filename).toBe('priority-test.md'); } }); runner.it('should have helper methods for each fallback strategy', async () => { if (global.MarkitectCleanEditor) { const container = document.createElement('div'); const editor = new global.MarkitectCleanEditor('# Test\n\nContent', container); // Test helper methods exist runner.expect(typeof editor.sanitizeFilename).toBe('function'); runner.expect(typeof editor.extractFilenameFromTitle).toBe('function'); runner.expect(typeof editor.extractFilenameFromUrl).toBe('function'); runner.expect(typeof editor.extractFilenameFromHeading).toBe('function'); runner.expect(typeof editor.generateTimestampFilename).toBe('function'); } }); }); // Run the tests if (require.main === module) { console.log('💾 Running TDD Tests for Intelligent Filename Generation Recovery'); runner.run().then(() => { console.log('✅ Test run complete - now implement filename generation!'); }); } module.exports = runner;