module meta import incubaid.herolib.core.playbook import incubaid.herolib.ui.console // Comprehensive HeroScript for testing multi-level navigation depths const test_heroscript_nav_depth = ' !!site.config name: "nav_depth_test" title: "Navigation Depth Test Site" description: "Testing multi-level nested navigation" tagline: "Deep navigation structures" !!site.navbar title: "Nav Depth Test" !!site.navbar_item label: "Home" to: "/" position: "left" // ============================================================ // LEVEL 1: Simple top-level category // ============================================================ !!site.page_category path: "Why" collapsible: true collapsed: false !!site.page src: "why:intro" label: "Why Choose Us" title: "Why Choose Us" description: "Reasons to use this platform" !!site.page src: "benefits" label: "Key Benefits" title: "Key Benefits" description: "Main benefits overview" // ============================================================ // LEVEL 2: Two-level nested category // ============================================================ !!site.page_category path: "Tutorials" collapsible: true collapsed: false !!site.page src: "tutorials:getting_started" label: "Getting Started" title: "Getting Started" description: "Basic tutorial to get started" !!site.page src: "first_steps" label: "First Steps" title: "First Steps" description: "Your first steps with the platform" // ============================================================ // LEVEL 3: Three-level nested category (Tutorials > Operations > Urgent) // ============================================================ !!site.page_category path: "Tutorials/Operations/Urgent" collapsible: true collapsed: false !!site.page src: "operations:emergency_restart" label: "Emergency Restart" title: "Emergency Restart" description: "How to emergency restart the system" !!site.page src: "critical_fixes" label: "Critical Fixes" title: "Critical Fixes" description: "Apply critical fixes immediately" !!site.page src: "incident_response" label: "Incident Response" title: "Incident Response" description: "Handle incidents in real-time" // ============================================================ // LEVEL 2.5: Two-level nested category (Tutorials > Operations) // ============================================================ !!site.page_category path: "Tutorials/Operations" collapsible: true collapsed: false !!site.page src: "ops:daily_checks" label: "Daily Checks" title: "Daily Checks" description: "Daily maintenance checklist" !!site.page src: "monitoring" label: "Monitoring" title: "Monitoring" description: "System monitoring procedures" !!site.page src: "backups" label: "Backups" title: "Backups" description: "Backup and restore procedures" // ============================================================ // LEVEL 1.5: One-to-two level (Tutorials) // ============================================================ // Note: This creates a sibling at the Tutorials level (not nested deeper) !!site.page src: "advanced_concepts" label: "Advanced Concepts" title: "Advanced Concepts" description: "Deep dive into advanced concepts" !!site.page src: "troubleshooting" label: "Troubleshooting" title: "Troubleshooting" description: "Troubleshooting guide" // ============================================================ // LEVEL 2: Two-level nested category (Why > FAQ) // ============================================================ !!site.page_category path: "Why/FAQ" collapsible: true collapsed: false !!site.page src: "faq:general" label: "General Questions" title: "General Questions" description: "Frequently asked questions" !!site.page src: "pricing_questions" label: "Pricing" title: "Pricing Questions" description: "Questions about pricing" !!site.page src: "technical_faq" label: "Technical FAQ" title: "Technical FAQ" description: "Technical frequently asked questions" !!site.page src: "support_faq" label: "Support" title: "Support FAQ" description: "Support-related FAQ" // ============================================================ // LEVEL 3+: Even deeper nesting for comprehensive testing // ============================================================ !!site.page_category path: "Tutorials/Operations/Database/Optimization" collapsible: true collapsed: false !!site.page src: "database:query_optimization" label: "Query Optimization" title: "Query Optimization" description: "Optimize your database queries" !!site.page src: "indexing_strategy" label: "Indexing Strategy" title: "Indexing Strategy" description: "Effective indexing strategies" !!site.page_category path: "Tutorials/Operations/Database" collapsible: true collapsed: false !!site.page src: "db:configuration" label: "Configuration" title: "Database Configuration" description: "Configure your database" !!site.page src: "replication" label: "Replication" title: "Database Replication" description: "Set up database replication" ' pub fn test_navigation_depth() ! { console.print_header('🧭 Navigation Depth Multi-Level Test') console.lf() // ======================================================== // SETUP: Create and process playbook // ======================================================== console.print_item('Creating playbook from HeroScript') mut plbook := playbook.new(text: test_heroscript_nav_depth)! console.print_green('✓ Playbook created') console.lf() console.print_item('Processing site configuration') play(mut plbook)! console.print_green('✓ Site processed') console.lf() console.print_item('Retrieving configured site') mut nav_site := get(name: 'nav_depth_test')! console.print_green('✓ Site retrieved') console.lf() // ======================================================== // TEST 1: Validate Categories Structure // ======================================================== console.print_header('TEST 1: Validate Categories Structure') console.print_item('Total categories: ${nav_site.categories.len}') for i, category in nav_site.categories { depth := calculate_category_depth(category.path) console.print_debug(' [${i}] Path: "${category.path}" (Depth: ${depth})') } // Assertions for category structure mut all_paths := nav_site.categories.map(it.path) assert all_paths.contains('Why'), 'Missing "Why" category' console.print_green('✓ Level 1: "Why" found') assert all_paths.contains('Tutorials'), 'Missing "Tutorials" category' console.print_green('✓ Level 1: "Tutorials" found') assert all_paths.contains('Why/FAQ'), 'Missing "Why/FAQ" category' console.print_green('✓ Level 2: "Why/FAQ" found') assert all_paths.contains('Tutorials/Operations'), 'Missing "Tutorials/Operations" category' console.print_green('✓ Level 2: "Tutorials/Operations" found') assert all_paths.contains('Tutorials/Operations/Urgent'), 'Missing "Tutorials/Operations/Urgent" category' console.print_green('✓ Level 3: "Tutorials/Operations/Urgent" found') assert all_paths.contains('Tutorials/Operations/Database'), 'Missing "Tutorials/Operations/Database" category' console.print_green('✓ Level 3: "Tutorials/Operations/Database" found') assert all_paths.contains('Tutorials/Operations/Database/Optimization'), 'Missing "Tutorials/Operations/Database/Optimization" category' console.print_green('✓ Level 4: "Tutorials/Operations/Database/Optimization" found') console.lf() // ======================================================== // TEST 2: Validate Pages Distribution // ======================================================== console.print_header('TEST 2: Validate Pages Distribution') console.print_item('Total pages: ${nav_site.pages.len}') mut pages_by_category := map[int]int{} for page in nav_site.pages { cat_id := page.category_id if cat_id !in pages_by_category { pages_by_category[cat_id] = 0 } pages_by_category[cat_id]++ } console.print_debug('Pages per category:') for cat_id, count in pages_by_category { mut cat_name := 'Root (Uncategorized)' // category_id is 1-based, index is 0-based if cat_id > 0 && cat_id <= nav_site.categories.len { cat_name = nav_site.categories[cat_id - 1].path } console.print_debug(' Category ${cat_id} [${cat_name}]: ${count} pages') } // Validate we have pages in multiple categories assert pages_by_category.len >= 5, 'Should have pages in at least 5 categories' console.print_green('✓ Pages distributed across multiple category levels') console.lf() // ======================================================== // TEST 3: Validate Navigation Structure (Sidebar) // ======================================================== console.print_header('TEST 3: Navigation Structure Analysis') mut sidebar := nav_site.sidebar() console.print_item('Sidebar root items: ${sidebar.my_sidebar.len}') console.lf() // Analyze structure mut stats := analyze_sidebar_structure(sidebar.my_sidebar) console.print_debug('Structure Analysis:') console.print_debug(' Total root items: ${stats.root_items}') console.print_debug(' Categories: ${stats.categories}') console.print_debug(' Pages: ${stats.pages}') console.print_debug(' Links: ${stats.links}') console.print_debug(' Max nesting depth: ${stats.max_depth}') assert stats.categories >= 6, 'Should have at least 6 categories' console.print_green('✓ Multiple category levels present') assert stats.max_depth >= 4, 'Should have nesting depth of at least 4 levels (0-indexed root, so 3+1)' console.print_green('✓ Deep nesting verified (depth: ${stats.max_depth})') console.lf() // ======================================================== // TEST 4: Validate Specific Path Hierarchies // ======================================================== console.print_header('TEST 4: Path Hierarchy Validation') // Find categories and check parent-child relationships let_test_hierarchy(nav_site.categories) console.lf() // ======================================================== // TEST 5: Print Sidebar Structure // ======================================================== console.print_header('📑 COMPLETE SIDEBAR STRUCTURE') console.lf() println(nav_site.sidebar_str()) console.print_header('✅ All Navigation Depth Tests Passed!') } // ============================================================ // Helper Structures // ============================================================ struct SidebarStats { pub mut: root_items int categories int pages int links int max_depth int // Max nesting depth including root as depth 1 } // ============================================================ // Helper Functions // ============================================================ fn calculate_category_depth(path string) int { if path.len == 0 { return 0 // Or handle as an error/special case } // Count slashes + 1 for the depth // "Why" -> 1 // "Why/FAQ" -> 2 return path.split('/').len } fn analyze_sidebar_structure(items []NavItem) SidebarStats { mut stats := SidebarStats{} stats.root_items = items.len for item in items { // Start depth at 1 for top-level items if item is NavCat { stats.categories++ depth := calculate_nav_item_depth(item, 1) if depth > stats.max_depth { stats.max_depth = depth } // Recursively count pages and categories stats.pages += count_nested_pages_in_navcat(item) stats.categories += count_nested_categories_in_navcat(item) } else if item is NavDoc { stats.pages++ if 1 > stats.max_depth { stats.max_depth = 1 } } else if item is NavLink { stats.links++ if 1 > stats.max_depth { stats.max_depth = 1 } } } return stats } fn calculate_nav_item_depth(item NavItem, current_depth int) int { mut max_depth_in_branch := current_depth if item is NavCat { for sub_item in item.items { depth := calculate_nav_item_depth(sub_item, current_depth + 1) if depth > max_depth_in_branch { max_depth_in_branch = depth } } } // NavDoc and NavLink are leaf nodes, their depth is current_depth return max_depth_in_branch } fn count_nested_pages_in_navcat(cat NavCat) int { mut count := 0 for item in cat.items { if item is NavDoc { count++ } else if item is NavCat { count += count_nested_pages_in_navcat(item) } } return count } fn count_nested_categories_in_navcat(cat NavCat) int { mut count := 0 for item in cat.items { if item is NavCat { count++ count += count_nested_categories_in_navcat(item) } } return count } fn let_test_hierarchy(categories []Category) { console.print_item('Validating path hierarchies:') // Group by depth mut by_depth := map[int][]string{} for category in categories { depth := calculate_category_depth(category.path) if depth !in by_depth { by_depth[depth] = []string{} } by_depth[depth] << category.path } // Print organized by depth // Assuming max depth is 4 based on the script for depth := 1; depth <= 4; depth++ { if depth in by_depth { console.print_debug(' Depth ${depth}:') for path in by_depth[depth] { console.print_debug(' └─ ${path}') } } } // Validate specific hierarchies mut all_paths := categories.map(it.path) // Hierarchy: Why -> Why/FAQ if all_paths.contains('Why') && all_paths.contains('Why/FAQ') { console.print_green('✓ Hierarchy verified: Why → Why/FAQ') } // Hierarchy: Tutorials -> Tutorials/Operations -> Tutorials/Operations/Urgent if all_paths.contains('Tutorials') && all_paths.contains('Tutorials/Operations') && all_paths.contains('Tutorials/Operations/Urgent') { console.print_green('✓ Hierarchy verified: Tutorials → Operations → Urgent') } // Hierarchy: Tutorials/Operations -> Tutorials/Operations/Database -> Tutorials/Operations/Database/Optimization if all_paths.contains('Tutorials/Operations/Database') && all_paths.contains('Tutorials/Operations/Database/Optimization') { console.print_green('✓ Hierarchy verified: Operations → Database → Optimization') } }