Files
galaxy/app/src/ai/agent_sdk/ambient_tests.rs
T

170 lines
5.9 KiB
Rust

//! Unit tests for `filter_from_args`. Verifies the clap enums are faithfully translated into
//! `TaskListFilter` without dropping any fields.
use chrono::{TimeZone, Utc};
use warp_cli::json_filter::JsonOutput;
use warp_cli::task::{
ArtifactTypeArg, ExecutionLocationArg, ListTasksArgs, RunSortByArg, RunSortOrderArg,
RunSourceArg, RunStateArg,
};
use super::*;
use crate::server::server_api::ai::{ArtifactType, ExecutionLocation, RunSortBy, RunSortOrder};
/// A `ListTasksArgs` whose fields are all at their defaults.
fn empty_args() -> ListTasksArgs {
ListTasksArgs {
limit: 10,
state: vec![],
source: None,
execution_location: None,
creator: None,
environment: None,
skill: None,
schedule: None,
ancestor_run: None,
name: None,
model: None,
artifact_type: None,
created_after: None,
created_before: None,
updated_after: None,
query: None,
sort_by: None,
sort_order: None,
cursor: None,
json_output: JsonOutput::default(),
}
}
#[test]
fn empty_args_yields_default_filter() {
let filter = filter_from_args(&empty_args());
assert!(filter.creator_uid.is_none());
assert!(filter.updated_after.is_none());
assert!(filter.created_after.is_none());
assert!(filter.created_before.is_none());
assert!(filter.states.is_none());
assert!(filter.source.is_none());
assert!(filter.execution_location.is_none());
assert!(filter.environment_id.is_none());
assert!(filter.skill_spec.is_none());
assert!(filter.schedule_id.is_none());
assert!(filter.ancestor_run_id.is_none());
assert!(filter.config_name.is_none());
assert!(filter.model_id.is_none());
assert!(filter.artifact_type.is_none());
assert!(filter.search_query.is_none());
assert!(filter.sort_by.is_none());
assert!(filter.sort_order.is_none());
assert!(filter.cursor.is_none());
}
#[test]
fn state_flags_map_to_filter() {
let args = ListTasksArgs {
state: vec![
RunStateArg::Failed,
RunStateArg::Error,
RunStateArg::Cancelled,
],
..empty_args()
};
let filter = filter_from_args(&args);
assert_eq!(
filter.states.as_deref(),
Some(
[
AmbientAgentTaskState::Failed,
AmbientAgentTaskState::Error,
AmbientAgentTaskState::Cancelled,
]
.as_slice()
)
);
}
#[test]
fn source_cli_maps_to_cli() {
let args = ListTasksArgs {
source: Some(RunSourceArg::Cli),
..empty_args()
};
let filter = filter_from_args(&args);
assert_eq!(filter.source, Some(AgentSource::Cli));
// Sanity-check the wire value: `--source CLI` must send `source=CLI`.
assert_eq!(filter.source.as_ref().map(AgentSource::as_str), Some("CLI"));
}
#[test]
fn source_interactive_maps_to_local() {
// The public API uses `LOCAL` as the source value for local interactive
// tasks. The CLI exposes this as `--source INTERACTIVE` for readability,
// but the request sent to the server must use `LOCAL`.
let args = ListTasksArgs {
source: Some(RunSourceArg::Interactive),
..empty_args()
};
let filter = filter_from_args(&args);
assert_eq!(filter.source, Some(AgentSource::Interactive));
assert_eq!(
filter.source.as_ref().map(AgentSource::as_str),
Some("LOCAL")
);
}
#[test]
fn every_field_maps_through() {
let created_after = Utc.with_ymd_and_hms(2026, 4, 1, 0, 0, 0).unwrap();
let created_before = Utc.with_ymd_and_hms(2026, 4, 2, 0, 0, 0).unwrap();
let updated_after = Utc.with_ymd_and_hms(2026, 4, 3, 12, 30, 0).unwrap();
let args = ListTasksArgs {
limit: 20,
state: vec![RunStateArg::InProgress],
source: Some(RunSourceArg::Api),
execution_location: Some(ExecutionLocationArg::Remote),
creator: Some("user-uid".to_string()),
environment: Some("env-123".to_string()),
skill: Some("owner/repo:SKILL.md".to_string()),
schedule: Some("sched-1".to_string()),
ancestor_run: Some("run-parent".to_string()),
name: Some("nightly".to_string()),
model: Some("claude-4-5".to_string()),
artifact_type: Some(ArtifactTypeArg::PullRequest),
created_after: Some(created_after),
created_before: Some(created_before),
updated_after: Some(updated_after),
query: Some("oz run".to_string()),
sort_by: Some(RunSortByArg::CreatedAt),
sort_order: Some(RunSortOrderArg::Asc),
cursor: Some("abcd==".to_string()),
json_output: JsonOutput::default(),
};
let filter = filter_from_args(&args);
assert_eq!(filter.creator_uid.as_deref(), Some("user-uid"));
assert_eq!(filter.updated_after, Some(updated_after));
assert_eq!(filter.created_after, Some(created_after));
assert_eq!(filter.created_before, Some(created_before));
assert_eq!(
filter.states.as_deref(),
Some([AmbientAgentTaskState::InProgress].as_slice())
);
assert_eq!(filter.source, Some(AgentSource::AgentWebhook));
assert_eq!(filter.execution_location, Some(ExecutionLocation::Remote));
assert_eq!(filter.environment_id.as_deref(), Some("env-123"));
assert_eq!(filter.skill_spec.as_deref(), Some("owner/repo:SKILL.md"));
assert_eq!(filter.schedule_id.as_deref(), Some("sched-1"));
assert_eq!(filter.ancestor_run_id.as_deref(), Some("run-parent"));
assert_eq!(filter.config_name.as_deref(), Some("nightly"));
assert_eq!(filter.model_id.as_deref(), Some("claude-4-5"));
assert_eq!(filter.artifact_type, Some(ArtifactType::PullRequest));
assert_eq!(filter.search_query.as_deref(), Some("oz run"));
assert_eq!(filter.sort_by, Some(RunSortBy::CreatedAt));
assert_eq!(filter.sort_order, Some(RunSortOrder::Asc));
assert_eq!(filter.cursor.as_deref(), Some("abcd=="));
}