Files
herolib/lib/web/doctree/meta/site_nav_test.v
2025-12-02 05:05:11 +01:00

461 lines
14 KiB
V

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}')
println(nav_site.sidebar_str())
println(sidebar)
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 {
// Calculate depth for the current item and update max_depth
// The calculate_nav_item_depth function correctly handles recursion for NavCat
// and returns current_depth for leaf nodes (NavDoc, NavLink).
// We start at depth 1 for root-level items.
depth := calculate_nav_item_depth(item, 1)
if depth > stats.max_depth {
stats.max_depth = depth
}
// Now categorize and count based on item type
if item is NavCat {
stats.categories++
// Recursively count pages and categories within this NavCat
stats.pages += count_nested_pages_in_navcat(item)
stats.categories += count_nested_categories_in_navcat(item)
} else if item is NavDoc {
stats.pages++
} else if item is NavLink {
stats.links++
}
}
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')
}
}