1pub mod codegen;
8pub mod config;
9pub mod escape;
10pub mod field_access;
11pub mod fixture;
12pub mod format;
13pub mod scaffold;
14pub mod template_env;
15pub mod validate;
16
17use alef_core::backend::GeneratedFile;
18use alef_core::config::e2e::DependencyMode;
19use alef_core::config::{Language, ResolvedCrateConfig};
20use anyhow::{Context, Result};
21use config::E2eConfig;
22use fixture::{group_fixtures, load_fixtures};
23use std::path::Path;
24use tracing::{info, warn};
25use validate::Severity;
26
27pub fn default_e2e_languages(scaffolded: &[Language]) -> Vec<String> {
38 let mut names: Vec<String> = scaffolded
39 .iter()
40 .map(|l| match l {
41 Language::Ffi => "c".to_string(),
42 other => other.to_string(),
43 })
44 .collect();
45 if !names.iter().any(|n| n == "rust") {
46 names.push("rust".to_string());
47 }
48 names
49}
50
51pub fn generate_e2e(
56 config: &ResolvedCrateConfig,
57 e2e_config: &E2eConfig,
58 languages: Option<&[String]>,
59) -> Result<Vec<GeneratedFile>> {
60 let fixtures_dir = Path::new(&e2e_config.fixtures);
61 let fixtures = load_fixtures(fixtures_dir)
62 .with_context(|| format!("failed to load fixtures from {}", fixtures_dir.display()))?;
63
64 info!("Loaded {} fixture(s) from {}", fixtures.len(), e2e_config.fixtures);
65
66 let resolved_languages: Vec<String> = if let Some(langs) = languages {
77 langs.to_vec()
78 } else if !e2e_config.languages.is_empty() {
79 e2e_config.languages.clone()
80 } else {
81 default_e2e_languages(&config.languages)
82 };
83
84 let diagnostics = validate::validate_fixtures_semantic(&fixtures, e2e_config, &resolved_languages);
88 for diag in &diagnostics {
89 match diag.severity {
90 Severity::Error => warn!("{}: {}", diag.file, diag.message),
91 Severity::Warning => warn!("{}: {}", diag.file, diag.message),
92 }
93 }
94
95 let all_groups = group_fixtures(&fixtures);
96
97 let groups: Vec<_> =
100 if e2e_config.dep_mode == DependencyMode::Registry && !e2e_config.registry.categories.is_empty() {
101 let allowed = &e2e_config.registry.categories;
102 all_groups
103 .into_iter()
104 .filter(|g| allowed.iter().any(|c| c == &g.category))
105 .collect()
106 } else {
107 all_groups
108 };
109
110 let generators = codegen::generators_for(&resolved_languages);
111
112 let mut all_files = Vec::new();
113 for generator in &generators {
114 let files = generator.generate(&groups, e2e_config, config)?;
115 info!(" [{}] generated {} file(s)", generator.language_name(), files.len());
116 all_files.extend(files);
117 }
118
119 Ok(all_files)
120}