| use crate::connectors::AppInfo; |
| use crate::context::AppsInstructions; |
| use crate::context::ContextualUserFragment; |
| use codex_protocol::protocol::APPS_INSTRUCTIONS_CLOSE_TAG; |
| use codex_protocol::protocol::APPS_INSTRUCTIONS_OPEN_TAG; |
|
|
| pub(crate) fn render_apps_section(connectors: &[AppInfo]) -> Option<String> { |
| connectors |
| .iter() |
| .any(|connector| connector.is_accessible && connector.is_enabled) |
| .then(|| AppsInstructions.render()) |
| } |
|
|
| #[cfg(test)] |
| mod tests { |
| use super::*; |
|
|
| fn connector(id: &str, is_accessible: bool, is_enabled: bool) -> AppInfo { |
| AppInfo { |
| id: id.to_string(), |
| name: id.to_string(), |
| description: None, |
| logo_url: None, |
| logo_url_dark: None, |
| icon_assets: None, |
| icon_dark_assets: None, |
| distribution_channel: None, |
| branding: None, |
| app_metadata: None, |
| labels: None, |
| install_url: None, |
| is_accessible, |
| is_enabled, |
| plugin_display_names: Vec::new(), |
| } |
| } |
|
|
| #[test] |
| fn omits_apps_section_without_accessible_and_enabled_apps() { |
| assert_eq!(render_apps_section(&[]), None); |
| assert_eq!( |
| render_apps_section(&[connector( |
| "calendar", true, false |
| )]), |
| None |
| ); |
| assert_eq!( |
| render_apps_section(&[connector( |
| "calendar", false, true |
| )]), |
| None |
| ); |
| } |
|
|
| #[test] |
| fn renders_apps_section_with_an_accessible_and_enabled_app() { |
| let rendered = render_apps_section(&[connector( |
| "calendar", true, true, |
| )]) |
| .expect("expected apps section"); |
|
|
| assert!(rendered.starts_with(APPS_INSTRUCTIONS_OPEN_TAG)); |
| assert!(rendered.contains("## Apps (Connectors)")); |
| assert!(rendered.ends_with(APPS_INSTRUCTIONS_CLOSE_TAG)); |
| } |
| } |
|
|