effectcraft/crates/script/src/tests_callable.rs

97 lines
3.6 KiB
Rust

//! Layers, property groups and properties are callable like After Effects (#758):
//! `layer("ADBE Effect Parade")`, `fxGroup(1)` and `fx("Slider")` are `.property(...)`.
use std::sync::Arc;
use effectcraft_engine::Session;
use effectcraft_engine::keyframe::Value as KV;
use serde_json::json;
use crate::{Outcome, run_code};
fn session() -> Session {
let mut s = Session { expr: Some(Arc::new(effectcraft_expr::Expressions)), expr_check: Some(effectcraft_expr::check_syntax), ..Default::default() };
crate::install(&mut s);
s
}
fn ok(s: &mut Session, code: &str) -> Outcome {
let o = run_code(s, code, "test.jsx");
assert!(o.error.is_none(), "script failed: {:?}\noutput: {:?}", o.error, o.output);
o
}
#[test]
fn layers_groups_and_properties_are_callable() {
let mut s = session();
let o = ok(
&mut s,
r#"
var c = app.project.items.addComp("M", 200, 200, 1, 2, 30);
var l = c.layers.addSolid([1, 1, 1], "S", 200, 200, 1);
l("ADBE Effect Parade").addProperty("ADBE Slider Control");
var fxGroup = l("Effects");
var fx = fxGroup(1);
fx("Slider").setValue(42);
l("ADBE Mask Parade").addProperty("ADBE Mask Atom");
var pos = l("ADBE Transform Group")("ADBE Position");
[
l("ADBE Effect Parade").matchName, fxGroup.numProperties, fx.matchName, fx.name,
l("Effects")("Slider Control")("Slider").value, fxGroup(1)(1).value,
l("Masks")(1).matchName, l("Masks")(1)("ADBE Mask Shape").name,
pos.matchName, pos.name, pos.propertyIndex, pos.parentProperty("Opacity").value,
pos.parentProperty.parentProperty(1).matchName === l.property(1).matchName,
l("Nope") === null, fxGroup(9) === null, pos("anything") === null,
l instanceof AVLayer, fxGroup instanceof PropertyGroup, pos instanceof Property, l.name,
l.transform.position.matchName, l.Effects(1).matchName
]
"#,
);
assert_eq!(
o.result,
json!([
"ADBE Effect Parade",
1,
"ADBE Slider Control",
"Slider Control",
42,
42,
"ADBE Mask Atom",
"Mask Path",
"ADBE Position",
"Position",
2,
100,
true,
true,
true,
true,
true,
true,
true,
"S",
"ADBE Position",
"ADBE Slider Control"
])
);
let c = s.project.items.values().find_map(|i| i.as_comp()).expect("comp");
let l = c.layers.first().expect("layer");
assert_eq!(l.props.prop("effects/#1/slider").map(|p| p.value.clone()), Some(KV::Scalar(42.0)));
}
#[test]
fn calling_without_a_name_is_a_script_error() {
let mut s = session();
for code in [
"var c = app.project.items.addComp('M', 100, 100, 1, 1, 25); var l = c.layers.addNull(); l();",
"var c = app.project.items.addComp('M', 100, 100, 1, 1, 25); var l = c.layers.addNull(); l('Transform')(null);",
"var c = app.project.items.addComp('M', 100, 100, 1, 1, 25); var l = c.layers.addNull(); new l('Transform');",
] {
let o = run_code(&mut s, code, "test.jsx");
assert!(o.error.is_some(), "expected an error for {code}");
}
// A called layer still reports itself as a layer, and its JSON result is unchanged.
let o = ok(&mut s, "var c = app.project.items.addComp('N', 100, 100, 1, 1, 25); var l = c.layers.addNull(); l.name = 'Ctl'; l");
assert_eq!(o.result, json!({ "type": "[object AVLayer]", "name": "Ctl" }));
}