use bevy::prelude::*;
#[derive(Debug, Clone)]
pub(crate) struct InsertTestIdIfExists {
pub entity: Entity,
pub id: String,
}
impl Command for InsertTestIdIfExists {
fn apply(self, world: &mut World) {
let Ok(mut entity_mut) = world.get_entity_mut(self.entity) else {
return;
};
if entity_mut.get::<TestId>().is_none() {
entity_mut.insert(TestId::new(self.id));
}
}
}
pub struct TelemetryPlugin;
impl Plugin for TelemetryPlugin {
fn build(&self, app: &mut App) {
let enabled = std::env::var("BEVY_TELEMETRY").is_ok();
app.insert_resource(TelemetryConfig { enabled });
if enabled {
info!("📊 Telemetry enabled");
}
}
}
#[derive(Resource, Clone, Debug, Default)]
pub struct TelemetryConfig {
pub enabled: bool,
}
impl TelemetryConfig {
pub fn enabled() -> Self {
Self { enabled: true }
}
pub fn disabled() -> Self {
Self { enabled: false }
}
}
#[derive(Component, Debug, Clone)]
pub struct TestId(pub String);
impl TestId {
pub fn new(id: impl Into<String>) -> Self {
Self(id.into())
}
pub fn id(&self) -> &str {
&self.0
}
}
pub trait WithTestId {
fn with_test_id(self, id: impl Into<String>, config: &TelemetryConfig) -> Self;
}
pub trait InsertTestId {
fn insert_test_id(&mut self, id: impl Into<String>, config: &TelemetryConfig) -> &mut Self;
}
impl InsertTestId for EntityCommands<'_> {
fn insert_test_id(&mut self, id: impl Into<String>, config: &TelemetryConfig) -> &mut Self {
if config.enabled {
self.insert(TestId::new(id));
}
self
}
}
pub fn test_id_if_enabled(id: impl Into<String>, config: &TelemetryConfig) -> Option<TestId> {
if config.enabled {
Some(TestId::new(id))
} else {
None
}
}
#[derive(Debug, Clone)]
pub struct ElementBounds {
pub test_id: String,
pub x: f32,
pub y: f32,
pub width: f32,
pub height: f32,
pub parent: Option<String>,
}
impl ElementBounds {
pub fn new(test_id: impl Into<String>, x: f32, y: f32, width: f32, height: f32) -> Self {
Self {
test_id: test_id.into(),
x,
y,
width,
height,
parent: None,
}
}
pub fn with_parent(mut self, parent: impl Into<String>) -> Self {
self.parent = Some(parent.into());
self
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_telemetry_config_default() {
let config = TelemetryConfig::default();
assert!(!config.enabled);
}
#[test]
fn test_telemetry_config_enabled() {
let config = TelemetryConfig::enabled();
assert!(config.enabled);
}
#[test]
fn test_telemetry_config_disabled() {
let config = TelemetryConfig::disabled();
assert!(!config.enabled);
}
#[test]
fn test_test_id_new() {
let id = TestId::new("my_button");
assert_eq!(id.id(), "my_button");
}
#[test]
fn test_test_id_if_enabled_true() {
let config = TelemetryConfig::enabled();
let id = test_id_if_enabled("test", &config);
assert!(id.is_some());
assert_eq!(id.unwrap().id(), "test");
}
#[test]
fn test_test_id_if_enabled_false() {
let config = TelemetryConfig::disabled();
let id = test_id_if_enabled("test", &config);
assert!(id.is_none());
}
#[test]
fn test_element_bounds_new() {
let bounds = ElementBounds::new("button", 10.0, 20.0, 100.0, 50.0);
assert_eq!(bounds.test_id, "button");
assert_eq!(bounds.x, 10.0);
assert_eq!(bounds.y, 20.0);
assert_eq!(bounds.width, 100.0);
assert_eq!(bounds.height, 50.0);
assert!(bounds.parent.is_none());
}
#[test]
fn test_element_bounds_with_parent() {
let bounds = ElementBounds::new("child", 0.0, 0.0, 50.0, 50.0).with_parent("parent");
assert_eq!(bounds.parent, Some("parent".to_string()));
}
}