Cover timeline right-click Pre-compose grouping the whole selection (#985, #1003)

Right-clicking selected layers and choosing Pre-compose grouped only the
right-clicked layer in 0.8.0 while Layer > Pre-compose grouped all of them.
The menu plumbing was fixed since; add a regression test driving the dialog
from both the outline row and the layer bar and asserting both selected
layers end up nested in the new composition.
This commit is contained in:
Vikram Bhaskaran committed 2026-10-13 00:35:59 +11:00
1 parent 9efe75330c
commit cbc1ce26e2
1 file changed
+42 -1
+42 -1
View File
@@ -1,6 +1,6 @@
//! User-reported selection, Project deletion, and render-queue drop regressions.
use effectcraft_engine::{Session, project::LayerId};
use effectcraft_ui_egui::{EffectcraftApp, dock::PanelKind};
use effectcraft_ui_egui::{Dialog, EffectcraftApp, dock::PanelKind};
use egui::{Event, Modifiers, PointerButton, Pos2, Rect, pos2, vec2};
use egui_kittest::Harness;
use egui_kittest::kittest::Queryable as _;
@@ -508,3 +508,44 @@ fn project_context_move_to_root_acts_on_the_whole_selection() {
assert_eq!(project.item(effectcraft_engine::project::ItemId(*id)).unwrap().parent, None);
}
}
/// Timeline right-click "Pre-compose…" groups every selected layer into one composition,
/// like Layer > Pre-compose does, from both the outline row and the layer bar
/// (#985, #1003).
#[test]
fn timeline_context_menu_precompose_groups_the_whole_selection() {
let right_click = |h: &mut Harness<'_, EffectcraftApp>, p: Pos2| {
for pressed in [true, false] {
h.input_mut().events.push(Event::PointerMoved(p));
h.input_mut().events.push(Event::PointerButton { pos: p, button: PointerButton::Secondary, pressed, modifiers: Modifiers::NONE });
h.step();
}
h.run_steps(3);
};
let row = |h: &Harness<'_, EffectcraftApp>, id: LayerId| {
let r = rect(h, &format!("timeline.layer.{}.row", id.0));
pos2(r.min.x + 210.0, r.center().y)
};
let bar = |h: &Harness<'_, EffectcraftApp>, id: LayerId| rect(h, &format!("timeline.layer.{}.bar", id.0)).center();
for via_bar in [false, true] {
let mut h = harness();
let ids: Vec<LayerId> = h.state().session.active_comp().unwrap().layers.iter().map(|l| l.id).collect();
let mut want: Vec<String> =
h.state().session.active_comp().unwrap().layers.iter().filter(|l| l.id == ids[0] || l.id == ids[1]).map(|l| l.name.clone()).collect();
want.sort();
h.state_mut().session.execute("layer.select", json!({"layers":[ids[0].0, ids[1].0]})).unwrap();
h.run_steps(3);
let p = if via_bar { bar(&h, ids[1]) } else { row(&h, ids[1]) };
right_click(&mut h, p);
h.get_by_label("Pre-compose…").click();
h.run_steps(3);
assert_eq!(h.state().dialog, Some(Dialog::Precompose), "via_bar={via_bar}: Pre-compose opens its dialog");
let ok = rect(&h, "dialog.precompose.ok").center();
click(&mut h, ok, Modifiers::NONE);
h.run_steps(3);
// The dialog opens the new composition holding both nested layers.
let mut nested: Vec<String> = h.state().session.active_comp().unwrap().layers.iter().map(|l| l.name.clone()).collect();
nested.sort();
assert_eq!(nested, want, "via_bar={via_bar}: both selected layers are nested");
}
}