mirror of
https://github.com/storytold/effectcraft.git
synced 2026-10-31 15:48:33 +00:00
Text: the text-edit tests count layers with the shared helper; forwarding docs name Duplicate (#2226)
The engine's text-edit tests repeated one layer-count closure in five places; they now use the layer_count helper the 3D tests already had. The doc of forwardable_during_text_edit and of the Type-tool test helper still spoke of Deselect All alone, though the editor now forwards Duplicate too.
This commit is contained in:
1 parent
eeedd6b540
commit
0e3b894cd9
4 files changed
+20
-22
No files matched your search
@@ -7,6 +7,7 @@ use serde_json::json;
|
||||
|
||||
use crate::Session;
|
||||
use crate::commands::text_edit::{MAX_IME_TEXT_BYTES, ime_stamp_revision, ime_surrounding, layer_doc};
|
||||
use crate::tests::three_d::layer_count;
|
||||
|
||||
fn session(text: &str) -> (Session, u64) {
|
||||
let mut s = Session::default();
|
||||
@@ -278,7 +279,7 @@ fn type_tool_layers_point_box_and_empty_cleanup() {
|
||||
let pos = l.props.prop("transform/position").unwrap().value.as_vec3();
|
||||
assert_eq!([pos[0], pos[1]], [190.0, 110.0]);
|
||||
s.execute("text.endEdit", json!({})).unwrap();
|
||||
assert_eq!(s.active_comp().unwrap().layers.len(), 1);
|
||||
assert_eq!(layer_count(&s), 1);
|
||||
// Resizing the box (layer space) is an attribute too.
|
||||
s.execute("layer.setText", json!({"layer": b, "box": [-100, -60, 200, 120]})).unwrap();
|
||||
assert_eq!(doc(&s, b).box_size, Some([200.0, 120.0]));
|
||||
@@ -1209,14 +1210,13 @@ fn deselect_all_discards_an_empty_type_tool_layer() {
|
||||
s.state.text_edit.as_ref().is_some_and(|e| e.created && e.layer == effectcraft_project::LayerId(new)),
|
||||
"the Type tool opens the edit on its new, empty layer"
|
||||
);
|
||||
let count = |s: &Session| s.active_comp().map_or(0, |c| c.layers.len());
|
||||
let before = count(&s);
|
||||
let before = layer_count(&s);
|
||||
s.execute("edit.deselectAll", json!({})).unwrap();
|
||||
assert!(s.state.text_edit.is_none());
|
||||
assert!(s.state.selected_layers.is_empty());
|
||||
assert_eq!(count(&s), before - 1, "a Type-tool layer left empty is removed, as text.endEdit does");
|
||||
assert_eq!(layer_count(&s), before - 1, "a Type-tool layer left empty is removed, as text.endEdit does");
|
||||
s.execute("edit.undo", json!({})).unwrap();
|
||||
assert_eq!(count(&s), before, "that removal is one undo step of its own, as on text.endEdit");
|
||||
assert_eq!(layer_count(&s), before, "that removal is one undo step of its own, as on text.endEdit");
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -1230,7 +1230,7 @@ fn duplicate_ends_an_edit_on_already_committed_text() {
|
||||
assert_eq!(doc(&s, t).text, "Hello", "the committed text is kept on the original");
|
||||
assert_eq!(doc(&s, copy).text, "Hello", "and carried by the copy");
|
||||
s.execute("edit.undo", json!({})).unwrap();
|
||||
assert_eq!(s.active_comp().map_or(0, |c| c.layers.len()), 1, "undo removes the copy");
|
||||
assert_eq!(layer_count(&s), 1, "undo removes the copy");
|
||||
assert!(s.state.text_edit.is_none(), "undo does not reopen the edit");
|
||||
}
|
||||
|
||||
@@ -1256,25 +1256,24 @@ fn duplicate_during_an_edit_copies_the_layer_not_a_selected_property_group() {
|
||||
|s: &Session| s.active_comp().unwrap().layer(LayerId(owner)).unwrap().props.group(path).unwrap().groups().map(|g| g.uid).collect::<Vec<_>>();
|
||||
let item = items(&s)[0];
|
||||
let n = items(&s).len();
|
||||
let layers = |s: &Session| s.active_comp().map_or(0, |c| c.layers.len());
|
||||
let before = layers(&s);
|
||||
let before = layer_count(&s);
|
||||
s.execute("prop.select", json!({"layer": owner, "prop": item})).unwrap();
|
||||
begin_edit_at(&mut s, t, 5);
|
||||
let r = s.execute("edit.duplicate", json!({})).unwrap();
|
||||
assert!(s.state.text_edit.is_none(), "{what}: Duplicate ends the open edit");
|
||||
assert_eq!(items(&s).len(), n, "{what}: the selected {what} is not duplicated");
|
||||
assert_eq!(layers(&s), before + 1, "{what}: the edited layer is");
|
||||
assert_eq!(layer_count(&s), before + 1, "{what}: the edited layer is");
|
||||
assert_eq!(s.state.selected_layers, vec![LayerId(r[0].as_u64().unwrap())], "{what}: and its copy is selected");
|
||||
// The selection the edit passed over goes with it: the next Duplicate copies the selected
|
||||
// copy rather than reaching back to the original's {what}.
|
||||
s.execute("edit.duplicate", json!({})).unwrap();
|
||||
assert_eq!(items(&s).len(), n, "{what}: a second Duplicate leaves the original's {what} alone");
|
||||
assert_eq!(layers(&s), before + 2, "{what}: and copies the copy");
|
||||
assert_eq!(layer_count(&s), before + 2, "{what}: and copies the copy");
|
||||
// With no edit open, the selected item keeps its precedence over the layers.
|
||||
s.execute("prop.select", json!({"layer": owner, "prop": item})).unwrap();
|
||||
s.execute("edit.duplicate", json!({})).unwrap();
|
||||
assert_eq!(items(&s).len(), n + 1, "{what}: outside an edit Duplicate copies the selected {what}");
|
||||
assert_eq!(layers(&s), before + 2, "{what}: and no layer");
|
||||
assert_eq!(layer_count(&s), before + 2, "{what}: and no layer");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1294,12 +1293,12 @@ fn duplicate_ends_the_open_edit_and_selects_the_copy() {
|
||||
// The edit ending is no undoable step of its own (as with text.endEdit): undo takes the
|
||||
// duplicate, it does not reopen the edit or undo the typing.
|
||||
s.execute("edit.undo", json!({})).unwrap();
|
||||
assert_eq!(s.active_comp().map_or(0, |c| c.layers.len()), 1, "undo removed the copy");
|
||||
assert_eq!(layer_count(&s), 1, "undo removed the copy");
|
||||
assert_eq!(doc(&s, t).text, "Hello!", "the typed text stays committed");
|
||||
assert!(s.state.text_edit.is_none(), "undo does not reopen the edit");
|
||||
// With no open edit Duplicate is untouched by all of this: same behavior, no extra steps.
|
||||
s.execute("edit.duplicate", json!({"layers": [t]})).unwrap();
|
||||
assert_eq!(s.active_comp().map_or(0, |c| c.layers.len()), 2, "a plain duplicate still duplicates");
|
||||
assert_eq!(layer_count(&s), 2, "a plain duplicate still duplicates");
|
||||
assert!(s.state.text_edit.is_none());
|
||||
}
|
||||
|
||||
@@ -1311,18 +1310,17 @@ fn duplicate_of_an_empty_type_tool_layer_discards_it_as_endedit_does() {
|
||||
s.state.text_edit.as_ref().is_some_and(|e| e.created && e.layer == effectcraft_project::LayerId(new)),
|
||||
"the Type tool opens the edit on its new, empty layer"
|
||||
);
|
||||
let count = |s: &Session| s.active_comp().map_or(0, |c| c.layers.len());
|
||||
let before = count(&s);
|
||||
let before = layer_count(&s);
|
||||
s.execute("edit.duplicate", json!({})).unwrap();
|
||||
assert!(s.state.text_edit.is_none(), "the edit ends the way text.endEdit ends it");
|
||||
assert_eq!(count(&s), before - 1, "a Type-tool layer left empty is discarded, not duplicated");
|
||||
assert_eq!(layer_count(&s), before - 1, "a Type-tool layer left empty is discarded, not duplicated");
|
||||
assert!(s.state.selected_layers.is_empty(), "nothing is selected: the layer that would be copied is gone");
|
||||
// The edit is committed before Duplicate resolves its layers, so naming the very layer
|
||||
// the empty edit was on addresses nothing: the commit still happened, the duplicate errors.
|
||||
let new2 = s.execute("layer.newText", json!({"text": "", "position": [90.0, 90.0], "edit": true})).unwrap()["layer"].as_u64().unwrap();
|
||||
assert!(s.execute("edit.duplicate", json!({"layers": [new2]})).is_err(), "the named layer is gone once the edit commits");
|
||||
assert!(s.state.text_edit.is_none(), "and the edit ended all the same");
|
||||
assert_eq!(count(&s), before - 1, "with the empty layer discarded, nothing left to duplicate");
|
||||
assert_eq!(layer_count(&s), before - 1, "with the empty layer discarded, nothing left to duplicate");
|
||||
s.execute("edit.undo", json!({})).unwrap();
|
||||
assert_eq!(count(&s), before, "that removal is one undo step of its own, as on text.endEdit");
|
||||
assert_eq!(layer_count(&s), before, "that removal is one undo step of its own, as on text.endEdit");
|
||||
}
|
||||
@@ -26,7 +26,7 @@ fn auto_orient_command() {
|
||||
assert!(!effectcraft_render::three_d::camera::is_two_node(&s.active_comp().unwrap().layers[0]));
|
||||
}
|
||||
|
||||
fn layer_count(s: &Session) -> usize {
|
||||
pub(crate) fn layer_count(s: &Session) -> usize {
|
||||
s.active_comp().unwrap().layers.len()
|
||||
}
|
||||
|
||||
|
||||
@@ -136,8 +136,8 @@ pub fn chord_matches(session: &effectcraft_engine::Session, command: &str, key:
|
||||
bindings(session).into_iter().any(|(m, k, id, _)| id == command && k == key && mods_match(m, mods))
|
||||
}
|
||||
|
||||
/// Whether a Deselect All chord matched by [`chord_matches`] may run while a text editor holds
|
||||
/// the keyboard. Chords carrying Cmd/Ctrl/Alt are command chords (the editor treats them as
|
||||
/// Whether a Deselect All or Duplicate chord matched by [`chord_matches`] may run while a text
|
||||
/// editor holds the keyboard. Chords carrying Cmd/Ctrl/Alt are command chords (the editor treats them as
|
||||
/// such for undo and the rest), and function keys never type, so those forward from the editor;
|
||||
/// a chord that could instead produce a character — a bare or Shift-only letter, digit or
|
||||
/// punctuation key, as from a pathological bare-letter rebinding — stays with the editor so
|
||||
|
||||
@@ -580,7 +580,7 @@ fn type_tool_selected_text_preference_skips_ineligible_layers_and_falls_back_to_
|
||||
}
|
||||
|
||||
/// Opens a fresh Type-tool edit holding `text` and returns the harness with the new layer id,
|
||||
/// so the Deselect All tests start from the same state.
|
||||
/// so the Deselect All and Duplicate tests start from the same state.
|
||||
fn type_tool_edit(a: EffectcraftApp, text: &str) -> (Harness<'static, EffectcraftApp>, u64) {
|
||||
let mut h = harness(a);
|
||||
h.run_steps(3);
|
||||
|
||||
Reference in new issue
Block a user