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