use bevy_app::TaskPoolPlugin;
use rig_ecs::AgentPlugin;
use rig_ecs::prelude::*;
use super::*;
use crate::ask::AskPlugin;
use crate::commands::{AppCommandsExt, CommandArgs};
#[derive(Resource, Default)]
struct Seen {
ran: Vec<(Entity, String)>,
picked: Vec<Option<Chosen>>,
}
fn app() -> (App, Entity) {
let mut app = App::new();
app.add_plugins((
TaskPoolPlugin::default(),
AgentPlugin,
AskPlugin,
PickPlugin,
))
.init_resource::<Seen>()
.add_command(
"note",
"Notes its arguments",
|In(args): In<CommandArgs>, mut seen: ResMut<Seen>| {
seen.ran.push((args.agent, args.args));
},
)
.add_observer(|picked: On<Picked>, mut seen: ResMut<Seen>| {
seen.picked.push(picked.chosen.clone());
});
app.update();
app.update();
let agent = app.world().resource::<ShownAgent>().0;
(app, agent.unwrap_or(Entity::PLACEHOLDER))
}
#[test]
fn a_pick_runs_the_items_command_for_the_agent_shown_and_closes_the_picker() {
let (mut app, agent) = app();
let world = app.world_mut();
assert!(
world.get::<Agent>(agent).is_some(),
"the primary agent is shown"
);
let size = Picker::new("Size")
.item("small", "note small")
.item("large", "note large");
let picker = world.spawn(size).id();
let closed = world.spawn(Picker::new("Other").item("x", "note x")).id();
world.trigger(Pick::person(picker, Some(Chosen::item(1))));
world.trigger(Pick::person(closed, None));
app.update();
let world = app.world();
assert!(world.get_entity(picker).is_err() && world.get_entity(closed).is_err());
let seen = world.resource::<Seen>();
assert_eq!(seen.ran, [(agent, "large".to_owned())]);
assert_eq!(seen.picked, [Some(Chosen::item(1)), None]);
}
#[test]
fn a_pick_of_several_items_runs_their_commands_in_list_order() {
let (mut app, agent) = app();
let world = app.world_mut();
let files = Picker::new("Delete which files?")
.multiple()
.item("a.tmp", "note a.tmp")
.checked(true)
.item("b.log", "note b.log")
.item("c.tmp", "note c.tmp");
let picker = world.spawn(files).id();
world.trigger(Pick::person(picker, Some(Chosen::items([2, 0]))));
app.update();
let seen = app.world().resource::<Seen>();
let ran = [(agent, "a.tmp".to_owned()), (agent, "c.tmp".to_owned())];
assert_eq!(seen.ran, ran);
assert_eq!(seen.picked, [Some(Chosen::items([2, 0]))]);
}
#[test]
fn a_pick_answers_a_question_with_its_choices_and_a_note() {
let (mut app, agent) = app();
let world = app.world_mut();
let text = world
.spawn((Ask::yes_no("Why?").free_text(), ForAgent(agent)))
.id();
let noted = world
.spawn((Ask::yes_no("Deploy?").free_text(), ForAgent(agent)))
.id();
let choice = world.spawn((Ask::yes_no("Run?"), ForAgent(agent))).id();
let both = world.spawn((Ask::yes_no("Both?"), ForAgent(agent))).id();
let closed = world.spawn((Ask::yes_no("Again?"), ForAgent(agent))).id();
let several = Ask::yes_no("Which?").choice("maybe", "Maybe").multiple();
let several = world.spawn((several, ForAgent(agent))).id();
world.trigger(Pick::person(text, Some(Chosen::text("because"))));
let note = Chosen::item(1).with_text("not on a Friday");
world.trigger(Pick::person(noted, Some(note)));
world.trigger(Pick::person(choice, Some(Chosen::item(1))));
world.trigger(Pick::person(both, Some(Chosen::items([0, 1]))));
world.trigger(Pick::person(closed, None));
world.trigger(Pick::person(several, Some(Chosen::items([2, 0]))));
app.update();
let world = app.world();
let answer = |ask: Entity| world.get::<Outcome>(ask).map(Answer::of);
assert_eq!(
[text, noted, choice, both, closed, several].map(answer),
[
Some(Some(Answer::text("because"))),
Some(Some(Answer::choice("no").with_text("not on a Friday"))),
Some(Some(Answer::choice("no"))),
None,
Some(None),
Some(Some(Answer::choices(["yes", "maybe"]))),
]
);
}