Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bevyengine
GitHub Repository: bevyengine/bevy
Path: blob/main/examples/remote/app_under_test.rs
30632 views
1
//! A Bevy app that can be used as an integration test target.
2
//! It displays a button that must be clicked. The button is placed at a random position and
3
//! moves every 5 seconds.
4
//!
5
//! Run with the `bevy_remote` feature enabled:
6
//! ```bash
7
//! cargo run --example app_under_test --features="bevy_remote"
8
//! ```
9
//! This example can be paired with the `integration_test` example, which will run an integration
10
//! test on this app.
11
12
use bevy::{
13
prelude::*,
14
remote::{http::RemoteHttpPlugin, RemotePlugin},
15
time::common_conditions::on_timer,
16
ui::UiGlobalTransform,
17
};
18
use chacha20::ChaCha8Rng;
19
use rand::{RngExt, SeedableRng};
20
21
fn main() {
22
App::new()
23
.add_plugins(DefaultPlugins)
24
// To make the app available for integration testing, we add these
25
// remote plugins to expose API’s for a testing framework to call.
26
.add_plugins(RemotePlugin::default())
27
.add_plugins(RemoteHttpPlugin::default())
28
.insert_resource(SeededRng(ChaCha8Rng::seed_from_u64(19878367467712)))
29
.add_systems(Startup, setup)
30
.add_systems(
31
Update,
32
(
33
move_button.run_if(on_timer(std::time::Duration::from_secs(5))),
34
log_button_position,
35
),
36
)
37
.run();
38
}
39
40
#[derive(Resource)]
41
struct SeededRng(ChaCha8Rng);
42
43
fn on_button_click(_click: On<Pointer<Click>>, mut exit: MessageWriter<AppExit>) {
44
info!("Button pressed!");
45
exit.write(AppExit::Success);
46
}
47
48
fn log_button_position(
49
transform: Single<&UiGlobalTransform, (With<Button>, Changed<UiGlobalTransform>)>,
50
) {
51
info!(
52
"Button at physical ({}, {})",
53
transform.translation.x, transform.translation.y
54
);
55
}
56
57
fn random_position(rng: &mut ChaCha8Rng) -> (f32, f32) {
58
let left_pct = rng.random_range(0.0..=60.0);
59
let top_pct = rng.random_range(0.0..=60.0);
60
(left_pct, top_pct)
61
}
62
63
fn move_button(mut rng: ResMut<SeededRng>, mut button_query: Query<&mut Node, With<Button>>) {
64
let (left_pct, top_pct) = random_position(&mut rng.0);
65
for mut node in &mut button_query {
66
node.left = percent(left_pct);
67
node.top = percent(top_pct);
68
}
69
}
70
71
fn setup(mut commands: Commands, assets: Res<AssetServer>, mut rng: ResMut<SeededRng>) {
72
let (left_pct, top_pct) = random_position(&mut rng.0);
73
74
commands.spawn(Camera2d);
75
commands
76
.spawn(Node {
77
width: percent(100),
78
height: percent(100),
79
..default()
80
})
81
.with_children(|parent| {
82
parent
83
.spawn((
84
Button,
85
Node {
86
width: px(150),
87
height: px(65),
88
border: UiRect::all(px(5)),
89
justify_content: JustifyContent::Center,
90
align_items: AlignItems::Center,
91
border_radius: BorderRadius::MAX,
92
left: percent(left_pct),
93
top: percent(top_pct),
94
..default()
95
},
96
BorderColor::all(Color::WHITE),
97
BackgroundColor(Color::BLACK),
98
))
99
.observe(on_button_click)
100
.with_children(|parent| {
101
parent.spawn((
102
Text::new("Button"),
103
TextFont {
104
font: assets.load("fonts/FiraSans-Bold.ttf").into(),
105
font_size: FontSize::Px(33.0),
106
..default()
107
},
108
TextColor(Color::srgb(0.9, 0.9, 0.9)),
109
TextShadow::default(),
110
));
111
});
112
});
113
}
114
115