/ docs / test / navigation_validation.jl
navigation_validation.jl
  1  #!/usr/bin/env julia
  2  
  3  """
  4  Navigation and User Journey Validation Script
  5  
  6  This script validates the complete user journey from landing page through
  7  getting started, ensuring all navigation paths work correctly.
  8  """
  9  
 10  function validate_user_journey()
 11      println("šŸ›¤ļø  Validating User Journey Navigation")
 12      println("=" ^ 40)
 13      
 14      # Define the expected user journey
 15      journey_steps = [
 16          ("docs/src/index.md", "Landing Page"),
 17          ("docs/src/getting-started/index.md", "Getting Started Overview"),
 18          ("docs/src/getting-started/installation.md", "Installation Guide"),
 19          ("docs/src/getting-started/quick-start.md", "Quick Start Guide"),
 20          ("docs/src/getting-started/first-strategy.md", "First Strategy Tutorial")
 21      ]
 22      
 23      validation_results = Dict{String, Bool}()
 24      
 25      for (filepath, description) in journey_steps
 26          println("\nšŸ“„ Validating: $description")
 27          
 28          if !isfile(filepath)
 29              println("  āŒ File missing: $filepath")
 30              validation_results[description] = false
 31              continue
 32          end
 33          
 34          content = read(filepath, String)
 35          
 36          # Check for required elements
 37          checks = Dict{String, Bool}()
 38          
 39          # 1. Has frontmatter
 40          checks["Has frontmatter"] = startswith(content, "---")
 41          
 42          # 2. Has title/heading  
 43          checks["Has main heading"] = occursin(r"^#\s+\w+"m, content) || occursin("\n# ", content)
 44          
 45          # 3. Has navigation elements
 46          if filepath == "docs/src/index.md"
 47              checks["Has user paths"] = occursin("First Time Here", content) || occursin("Getting Started", content)
 48              checks["Has quick access"] = occursin("Quick access", content) || occursin("API Docs", content)
 49          else
 50              checks["Has next steps"] = occursin("Next Steps", content) || occursin("What's Next", content)
 51              checks["Has see also"] = occursin("See Also", content) || occursin("Related", content)
 52          end
 53          
 54          # 4. Links to next step in journey
 55          if filepath != last(journey_steps)[1]  # Not the last step
 56              next_step_index = findfirst(x -> x[1] == filepath, journey_steps)
 57              if next_step_index !== nothing && next_step_index < length(journey_steps)
 58                  next_file = journey_steps[next_step_index + 1][1]
 59                  next_filename = basename(next_file)
 60                  checks["Links to next step"] = occursin(next_filename, content)
 61              end
 62          end
 63          
 64          # 5. Has estimated time (for getting-started pages)
 65          if contains(filepath, "getting-started") && filepath != "docs/src/getting-started/index.md"
 66              checks["Has time estimate"] = occursin("estimated_time", content) || occursin("minutes", content)
 67          end
 68          
 69          # Report results for this page
 70          all_passed = all(values(checks))
 71          validation_results[description] = all_passed
 72          
 73          for (check_name, passed) in checks
 74              status = passed ? "āœ…" : "āŒ"
 75              println("  $status $check_name")
 76          end
 77          
 78          if all_passed
 79              println("  šŸŽ‰ All checks passed for $description")
 80          else
 81              failed_checks = [name for (name, passed) in checks if !passed]
 82              println("  āš ļø  Failed checks: $(join(failed_checks, ", "))")
 83          end
 84      end
 85      
 86      return validation_results
 87  end
 88  
 89  function validate_cross_references()
 90      println("\nšŸ”— Validating Cross-References")
 91      println("=" ^ 30)
 92      
 93      # Key files that should cross-reference each other
 94      cross_ref_pairs = [
 95          ("docs/src/index.md", "docs/src/getting-started/installation.md"),
 96          ("docs/src/getting-started/installation.md", "docs/src/getting-started/quick-start.md"),
 97          ("docs/src/getting-started/quick-start.md", "docs/src/getting-started/first-strategy.md"),
 98          ("docs/src/getting-started/first-strategy.md", "docs/src/guides/strategy-development.md")
 99      ]
100      
101      cross_ref_results = Dict{String, Bool}()
102      
103      for (source_file, target_file) in cross_ref_pairs
104          if !isfile(source_file) || !isfile(target_file)
105              cross_ref_results["$(basename(source_file)) → $(basename(target_file))"] = false
106              continue
107          end
108          
109          source_content = read(source_file, String)
110          target_filename = basename(target_file)
111          
112          # Check if source links to target
113          has_link = occursin(target_filename, source_content)
114          cross_ref_results["$(basename(source_file)) → $(basename(target_file))"] = has_link
115          
116          status = has_link ? "āœ…" : "āŒ"
117          println("$status $(basename(source_file)) → $(basename(target_file))")
118      end
119      
120      return cross_ref_results
121  end
122  
123  function validate_content_completeness()
124      println("\nšŸ“‹ Validating Content Completeness")
125      println("=" ^ 35)
126      
127      # Required content sections for each page type
128      content_requirements = Dict(
129          "docs/src/index.md" => [
130              "What's Next", "First Time Here", "Ready to Build", "Going Live"
131          ],
132          "docs/src/getting-started/installation.md" => [
133              "Prerequisites", "Docker", "Verification", "Troubleshooting", "Next Steps"
134          ],
135          "docs/src/getting-started/quick-start.md" => [
136              "What You'll Accomplish", "Step 1", "Step 2", "Expected output"
137          ],
138          "docs/src/getting-started/first-strategy.md" => [
139              "What You'll Learn", "Prerequisites", "Strategy Structure", "Step"
140          ]
141      )
142      
143      completeness_results = Dict{String, Float64}()
144      
145      for (filepath, required_sections) in content_requirements
146          if !isfile(filepath)
147              completeness_results[basename(filepath)] = 0.0
148              continue
149          end
150          
151          content = read(filepath, String)
152          found_sections = 0
153          
154          println("\nšŸ“„ $(basename(filepath)):")
155          for section in required_sections
156              has_section = occursin(section, content)
157              status = has_section ? "āœ…" : "āŒ"
158              println("  $status $section")
159              if has_section
160                  found_sections += 1
161              end
162          end
163          
164          completeness_score = found_sections / length(required_sections)
165          completeness_results[basename(filepath)] = completeness_score
166          
167          println("  šŸ“Š Completeness: $(round(completeness_score * 100, digits=1))%")
168      end
169      
170      return completeness_results
171  end
172  
173  function validate_time_requirements()
174      println("\nā±ļø  Validating Time Requirements")
175      println("=" ^ 30)
176      
177      # Extract time estimates from frontmatter
178      time_files = [
179          "docs/src/getting-started/installation.md",
180          "docs/src/getting-started/quick-start.md", 
181          "docs/src/getting-started/first-strategy.md"
182      ]
183      
184      total_time = 0
185      time_results = Dict{String, Int}()
186      
187      for filepath in time_files
188          if !isfile(filepath)
189              continue
190          end
191          
192          content = read(filepath, String)
193          
194          # Look for estimated_time in frontmatter
195          time_match = match(r"estimated_time:\s*[\"']?(\d+)", content)
196          if time_match !== nothing
197              estimated_time = parse(Int, time_match.captures[1])
198              time_results[basename(filepath)] = estimated_time
199              total_time += estimated_time
200              
201              println("šŸ“„ $(basename(filepath)): $estimated_time minutes")
202          else
203              println("āŒ $(basename(filepath)): No time estimate found")
204              time_results[basename(filepath)] = 0
205          end
206      end
207      
208      println("\nšŸ“Š Total estimated time: $total_time minutes")
209      
210      # Check against requirement (should be ≤ 30 minutes)
211      meets_requirement = total_time <= 30
212      status = meets_requirement ? "āœ…" : "āŒ"
213      println("$status Meets 30-minute requirement: $meets_requirement")
214      
215      return time_results, total_time, meets_requirement
216  end
217  
218  # Main execution
219  println("šŸš€ Starting Navigation and User Journey Validation")
220  println("=" ^ 55)
221  
222  # Run all validations
223  journey_results = validate_user_journey()
224  cross_ref_results = validate_cross_references()
225  completeness_results = validate_content_completeness()
226  time_results, total_time, time_ok = validate_time_requirements()
227  
228  # Generate summary report
229  println("\nšŸ“Š VALIDATION SUMMARY")
230  println("=" ^ 25)
231  
232  # Journey validation
233  journey_passed = count(values(journey_results))
234  journey_total = length(journey_results)
235  println("User Journey: $journey_passed/$journey_total pages validated ($(round(journey_passed/journey_total*100, digits=1))%)")
236  
237  # Cross-reference validation
238  cross_ref_passed = count(values(cross_ref_results))
239  cross_ref_total = length(cross_ref_results)
240  println("Cross-References: $cross_ref_passed/$cross_ref_total links working ($(round(cross_ref_passed/cross_ref_total*100, digits=1))%)")
241  
242  # Content completeness
243  avg_completeness = sum(values(completeness_results)) / length(completeness_results) * 100
244  println("Content Completeness: $(round(avg_completeness, digits=1))% average")
245  
246  # Time requirements
247  println("Time Requirements: $(time_ok ? "āœ… PASS" : "āŒ FAIL") ($total_time/30 minutes)")
248  
249  # Overall assessment
250  overall_score = (journey_passed/journey_total + cross_ref_passed/cross_ref_total + avg_completeness/100) / 3
251  println("\nšŸŽÆ Overall Score: $(round(overall_score * 100, digits=1))%")
252  
253  if overall_score >= 0.8
254      println("šŸŽ‰ User journey validation PASSED!")
255      exit(0)
256  else
257      println("āš ļø  User journey validation needs improvement")
258      exit(1)
259  end