Vapora/crates/vapora-workflow-engine/tests/notification_config.rs

107 lines
3.1 KiB
Rust
Raw Permalink Normal View History

use vapora_channels::ChannelRegistry;
use vapora_workflow_engine::config::WorkflowsConfig;
/// Full TOML round-trip: channels section + per-workflow notification targets.
const TOML_WITH_CHANNELS: &str = r#"
[engine]
max_parallel_tasks = 4
workflow_timeout = 3600
approval_gates_enabled = false
[channels.team-slack]
type = "slack"
webhook_url = "https://hooks.slack.com/services/TEST/TEST/TEST"
[channels.ops-telegram]
type = "telegram"
bot_token = "123:TEST"
chat_id = "-100999"
[[workflows]]
name = "deploy-prod"
trigger = "manual"
[workflows.notifications]
on_completed = ["team-slack"]
on_failed = ["team-slack", "ops-telegram"]
on_approval_required = ["team-slack"]
[[workflows.stages]]
name = "build"
agents = ["developer"]
[[workflows.stages]]
name = "deploy"
agents = ["deployer"]
approval_required = true
"#;
/// Workflow with no [channels] section — should parse without error and leave
/// the channel map empty (registry skipped by orchestrator).
const TOML_WITHOUT_CHANNELS: &str = r#"
[engine]
max_parallel_tasks = 4
workflow_timeout = 3600
approval_gates_enabled = false
[[workflows]]
name = "ci-pipeline"
trigger = "manual"
[[workflows.stages]]
name = "test"
agents = ["developer"]
"#;
#[test]
fn channels_section_parses_into_config() {
let config: WorkflowsConfig = toml::from_str(TOML_WITH_CHANNELS).expect("must parse");
assert_eq!(config.channels.len(), 2);
assert!(config.channels.contains_key("team-slack"));
assert!(config.channels.contains_key("ops-telegram"));
}
#[test]
fn notification_targets_parse_per_workflow() {
let config: WorkflowsConfig = toml::from_str(TOML_WITH_CHANNELS).expect("must parse");
let wf = config.get_workflow("deploy-prod").expect("workflow exists");
assert_eq!(wf.notifications.on_completed, ["team-slack"]);
assert_eq!(wf.notifications.on_failed, ["team-slack", "ops-telegram"]);
assert_eq!(wf.notifications.on_approval_required, ["team-slack"]);
}
#[test]
fn missing_channels_section_defaults_to_empty() {
let config: WorkflowsConfig = toml::from_str(TOML_WITHOUT_CHANNELS).expect("must parse");
assert!(config.channels.is_empty());
}
#[test]
fn missing_notifications_block_defaults_to_empty_vecs() {
let config: WorkflowsConfig = toml::from_str(TOML_WITHOUT_CHANNELS).expect("must parse");
let wf = config.get_workflow("ci-pipeline").expect("workflow exists");
assert!(wf.notifications.on_completed.is_empty());
assert!(wf.notifications.on_failed.is_empty());
assert!(wf.notifications.on_approval_required.is_empty());
}
#[test]
fn channel_registry_builds_from_config() {
let config: WorkflowsConfig = toml::from_str(TOML_WITH_CHANNELS).expect("must parse");
let registry = ChannelRegistry::from_map(config.channels).expect("registry must build");
let mut names = registry.channel_names();
names.sort_unstable();
assert_eq!(names, ["ops-telegram", "team-slack"]);
}
#[test]
fn validation_passes_with_channels_and_notifications() {
let config: WorkflowsConfig = toml::from_str(TOML_WITH_CHANNELS).expect("must parse");
config.validate().expect("validation must pass");
}