mod bench;
mod session;
use egui::{Event, Key, Modifiers, vec2};
use gled_model::patching::Patch;
use session::Session;
#[test]
fn a_fresh_window_has_nothing_to_apply_or_undo() {
let session = Session::new();
assert!(!session.window.unapplied());
assert!(!session.can_undo());
assert!(!session.can_redo());
}
#[test]
fn a_moving_drag_is_applied_and_undone_whole() {
let mut session = Session::new();
let before = session.patch().clone();
let from = session.on_screen(session.left);
session.drag(from, from + vec2(60.0, 40.0), false);
assert_ne!(*session.patch(), before, "the drag moved the fixture");
assert!(session.window.unapplied(), "the move is there to apply");
assert!(session.can_undo());
assert!(!session.can_redo());
let moved = session.patch().clone();
session.undo();
assert_eq!(
*session.patch(),
before,
"one undo takes the whole move back"
);
assert!(!session.window.unapplied(), "nothing is left to apply");
assert!(!session.can_undo());
assert!(session.can_redo());
session.redo();
assert_eq!(*session.patch(), moved, "redo moves it again");
assert!(session.window.unapplied());
assert!(session.can_undo());
assert!(!session.can_redo());
}
#[test]
fn a_drag_pressed_in_the_frame_it_arrived_moves_the_fixture_under_the_press() {
let mut session = Session::new();
let before = session.patch().clone();
let from = session.on_screen(session.left);
session.drag(from, from + vec2(60.0, 40.0), true);
let moved = &session.patch().topology.default_layout.members;
assert_ne!(
moved[&session.left], before.topology.default_layout.members[&session.left],
"the fixture under the press moved"
);
assert_eq!(
moved[&session.right], before.topology.default_layout.members[&session.right],
"the other one stayed"
);
assert!(session.window.unapplied());
session.undo();
assert_eq!(*session.patch(), before);
assert!(!session.window.unapplied());
}
#[test]
fn a_band_onto_a_fixture_only_selects() {
let mut session = Session::new();
let before = session.patch().clone();
let left = session.on_screen(session.left);
let from = left + vec2(0.0, 120.0);
session.drag(from, left, true);
assert_eq!(*session.patch(), before, "nothing moved");
assert!(!session.window.unapplied());
assert!(!session.can_undo(), "a band leaves no undo step");
assert!(
session
.window
.state
.selected_fixtures
.contains(&session.left)
);
}
#[test]
fn a_band_whose_first_frame_lands_on_a_fixture_only_selects() {
let mut session = Session::new();
let before = session.patch().clone();
let left = session.on_screen(session.left);
let from = left + vec2(0.0, 120.0);
session.frame(vec![Event::PointerMoved(from), Session::button(from, true)]);
session.frame(vec![
Event::PointerMoved(from + vec2(0.0, -60.0)),
Event::PointerMoved(left),
]);
for step in 1..=5 {
session.frame(vec![Event::PointerMoved(left + vec2(step as f32, 0.0))]);
}
session.frame(vec![Session::button(left + vec2(5.0, 0.0), false)]);
session.frame(vec![]);
assert_eq!(*session.patch(), before, "nothing moved");
assert!(!session.window.unapplied());
assert!(!session.can_undo());
}
#[test]
fn a_drag_moves_the_fixture_pressed_on_not_the_one_under_the_pointer() {
let mut session = Session::new();
let before = session.patch().topology.default_layout.members.clone();
let left = session.on_screen(session.left);
let right = session.on_screen(session.right);
session.frame(vec![Event::PointerMoved(left)]);
session.frame(vec![
Session::button(left, true),
Event::PointerMoved(left + (right - left) * 0.5),
Event::PointerMoved(right),
]);
for step in 1..=5 {
session.frame(vec![Event::PointerMoved(right + vec2(step as f32, 0.0))]);
}
session.frame(vec![Session::button(right + vec2(5.0, 0.0), false)]);
session.frame(vec![]);
let after = session.patch().topology.default_layout.members.clone();
assert_ne!(
after[&session.left], before[&session.left],
"the pressed one moved"
);
assert_eq!(
after[&session.right], before[&session.right],
"the other stayed"
);
assert_eq!(
session.window.state.selected_fixtures,
[session.left].into_iter().collect(),
"the pressed one is selected"
);
}
#[test]
fn the_frame_that_starts_a_drag_moves_the_fixture_and_shows_apply() {
let mut session = Session::new();
let before = session.patch().topology.default_layout.members[&session.left];
let from = session.on_screen(session.left);
assert!(!session.frame(vec![Event::PointerMoved(from)]));
session.frame(vec![Session::button(from, true)]);
let shown = session.frame(vec![Event::PointerMoved(from + vec2(10.0, 0.0))]);
let moved = session.patch().topology.default_layout.members[&session.left];
assert!(
moved.pos.x > before.pos.x,
"the fixture follows the pointer"
);
assert!(session.window.unapplied());
assert!(shown, "the frame shows there is something to apply");
let to = from + vec2(60.0, 40.0);
let shown = session.frame(vec![
Event::PointerMoved(to),
Session::button(to, false),
Event::PointerMoved(to + vec2(1.0, 0.0)),
]);
assert!(session.window.unapplied());
assert!(shown);
}
#[test]
fn the_frame_that_lets_go_where_the_drag_began_shows_nothing_to_apply() {
let mut session = Session::new();
let from = session.on_screen(session.left);
session.frame(vec![Event::PointerMoved(from)]);
session.frame(vec![Session::button(from, true)]);
for step in 1..=3 {
session.frame(vec![Event::PointerMoved(
from + vec2(10.0 * step as f32, 0.0),
)]);
}
assert!(session.window.unapplied());
let shown = session.frame(vec![
Event::PointerMoved(from),
Session::button(from, false),
]);
assert!(!session.window.unapplied());
assert!(
!session.can_undo(),
"a drag that changed nothing is no step"
);
assert!(!shown, "the frame shows there is nothing to apply");
}
#[test]
fn the_frame_that_undoes_the_change_shows_nothing_to_apply() {
let mut session = Session::new();
let from = session.on_screen(session.left);
session.drag(from, from + vec2(60.0, 40.0), false);
assert!(session.frame(vec![]));
let undo = Event::Key {
key: Key::Z,
physical_key: None,
pressed: true,
repeat: false,
modifiers: Modifiers::COMMAND,
};
let shown = session.frame(vec![Event::ModifiersChanged(Modifiers::COMMAND), undo]);
assert!(!session.window.unapplied());
assert!(!shown, "the frame shows what it did");
}
#[test]
fn adopting_another_patch_starts_the_draft_over() {
let mut session = Session::new();
let taken = session.project().patch.clone();
let from = session.on_screen(session.left);
session.drag(from, from + vec2(60.0, 40.0), false);
assert!(session.window.unapplied());
session.adopt(taken);
assert!(session.window.unapplied(), "the same patch keeps the draft");
session.adopt(Patch::default());
assert!(!session.window.unapplied(), "another patch starts it over");
assert_eq!(*session.patch(), Patch::default());
}
#[test]
fn apply_hands_the_draft_over_once() {
let mut session = Session::new();
let from = session.on_screen(session.left);
session.drag(from, from + vec2(60.0, 40.0), false);
assert!(!session.window.take_patch_applied());
session.apply();
assert_eq!(session.project().patch, *session.patch());
assert!(!session.window.unapplied());
assert!(session.window.take_patch_applied());
assert!(!session.window.take_patch_applied(), "once");
session.adopt(session.project().patch.clone());
assert!(session.window.draft.is_some());
assert!(!session.window.unapplied());
}