diff --git a/Cargo.toml b/Cargo.toml index ee3a5324cc9c1..8b1751ab7cc27 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4813,6 +4813,30 @@ description = "A Bevy app that you can connect to with the BRP and edit" category = "Remote Protocol" wasm = false +[[example]] +name = "app_under_test" +path = "examples/remote/app_under_test.rs" +doc-scrape-examples = true +required-features = ["bevy_remote"] + +[package.metadata.example.app_under_test] +name = "App Under Test" +description = "A Bevy app that you can connect to with the BRP and control" +category = "Remote Protocol" +wasm = false + +[[example]] +name = "integration_test" +path = "examples/remote/integration_test.rs" +doc-scrape-examples = true +required-features = ["bevy_remote"] + +[package.metadata.example.integration_test] +name = "Integration Test" +description = "Connects to a running Bevy app via BRP, finds a button, and clicks it" +category = "Remote Protocol" +wasm = false + [[example]] name = "anisotropy" path = "examples/3d/anisotropy.rs" diff --git a/crates/bevy_window/src/event.rs b/crates/bevy_window/src/event.rs index 91fff5eafcdd8..b58e3ab73ac5f 100644 --- a/crates/bevy_window/src/event.rs +++ b/crates/bevy_window/src/event.rs @@ -494,7 +494,7 @@ impl AppLifecycle { #[cfg_attr( feature = "bevy_reflect", derive(Reflect), - reflect(Debug, PartialEq, Clone) + reflect(Debug, PartialEq, Clone, Message) )] #[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))] #[cfg_attr( diff --git a/examples/README.md b/examples/README.md index 399e7de23ed02..a388356b555bc 100644 --- a/examples/README.md +++ b/examples/README.md @@ -461,6 +461,8 @@ Example | Description Example | Description --- | --- +[App Under Test](../examples/remote/app_under_test.rs) | A Bevy app that you can connect to with the BRP and control +[Integration Test](../examples/remote/integration_test.rs) | Connects to a running Bevy app via BRP, finds a button, and clicks it [client](../examples/remote/client.rs) | A simple command line client that can control Bevy apps via the BRP [server](../examples/remote/server.rs) | A Bevy app that you can connect to with the BRP and edit diff --git a/examples/remote/app_under_test.rs b/examples/remote/app_under_test.rs new file mode 100644 index 0000000000000..106da810c5927 --- /dev/null +++ b/examples/remote/app_under_test.rs @@ -0,0 +1,113 @@ +//! A Bevy app that can be used as an integration test target. +//! It displays a button that must be clicked. The button is placed at a random position and +//! moves every 5 seconds. +//! +//! Run with the `bevy_remote` feature enabled: +//! ```bash +//! cargo run --example app_under_test --features="bevy_remote" +//! ``` +//! This example can be paired with the `integration_test` example, which will run an integration +//! test on this app. + +use bevy::{ + prelude::*, + remote::{http::RemoteHttpPlugin, RemotePlugin}, + time::common_conditions::on_timer, + ui::UiGlobalTransform, +}; +use chacha20::ChaCha8Rng; +use rand::{RngExt, SeedableRng}; + +fn main() { + App::new() + .add_plugins(DefaultPlugins) + // To make the app available for integration testing, we add these + // remote plugins to expose API’s for a testing framework to call. + .add_plugins(RemotePlugin::default()) + .add_plugins(RemoteHttpPlugin::default()) + .insert_resource(SeededRng(ChaCha8Rng::seed_from_u64(19878367467712))) + .add_systems(Startup, setup) + .add_systems( + Update, + ( + move_button.run_if(on_timer(std::time::Duration::from_secs(5))), + log_button_position, + ), + ) + .run(); +} + +#[derive(Resource)] +struct SeededRng(ChaCha8Rng); + +fn on_button_click(_click: On>, mut exit: MessageWriter) { + info!("Button pressed!"); + exit.write(AppExit::Success); +} + +fn log_button_position( + transform: Single<&UiGlobalTransform, (With