use rosc::{OscMessage, OscType};
use super::parse_message;
use crate::action::UiAction;
use crate::input::event::InputEvent;
use crate::input::osc::samples::sample_messages;
use crate::storage::asset::animation::argument::ArgumentKindId;
use crate::storage::asset::project::scene_instance_path::SceneInstanceUnion;
fn msg(addr: &str, args: Vec<OscType>) -> OscMessage {
OscMessage {
addr: addr.to_string(),
args,
}
}
#[test]
fn parses_project_main_dimmer() {
let msg = msg("/project/main_dimmer", vec![OscType::Float(0.5)]);
let action = parse_message(&msg).expect("main dimmer should parse");
match action {
UiAction::SetMainDimmer(value) => assert_eq!(value, 0.5),
_ => panic!("wrong action variant"),
}
}
#[test]
fn parses_scene_grid_opacity() {
let msg = msg("/scene/grid/2/1/opacity", vec![OscType::Float(0.7)]);
let action = parse_message(&msg).expect("grid opacity should parse");
match action {
UiAction::SetSceneOpacity(SceneInstanceUnion::Grid(location), value) => {
assert_eq!(location.col, 2);
assert_eq!(location.row, 1);
assert_eq!(value, 0.7);
}
_ => panic!("wrong action variant"),
}
}
#[test]
fn parses_scene_quick_active() {
let msg = msg("/scene/quick/3/active", vec![OscType::Int(1)]);
let action = parse_message(&msg).expect("quick active should parse");
match action {
UiAction::SetSceneActive(SceneInstanceUnion::Quick(index), value) => {
assert_eq!(index.index, 3);
assert!(value);
}
_ => panic!("wrong action variant"),
}
}
#[test]
fn parses_selected_scene_toggle() {
let msg = msg("/scene/selected/toggle", vec![]);
let action = parse_message(&msg).expect("selected toggle should parse");
assert!(matches!(
action,
UiAction::ToggleSceneActive(SceneInstanceUnion::Selected)
));
}
#[test]
fn parses_large_grid_location_without_static_bounds_check() {
let msg = msg("/scene/grid/999/777/opacity", vec![OscType::Float(0.2)]);
match parse_message(&msg).expect("large grid location should parse") {
UiAction::SetSceneOpacity(SceneInstanceUnion::Grid(location), value) => {
assert_eq!(location.col, 999);
assert_eq!(location.row, 777);
assert_eq!(value, 0.2);
}
_ => panic!("wrong action variant"),
}
}
#[test]
fn parses_project_palette_none() {
let msg = msg(
"/project/palette",
vec![OscType::String("none".to_string())],
);
let action = parse_message(&msg).expect("palette none should parse");
match action {
UiAction::SetProjectPaletteFromAsset(value) => assert!(value.is_none()),
_ => panic!("wrong action variant"),
}
}
#[test]
fn parses_scene_effect_config_f32() {
let msg = msg(
"/scene/grid/1/2/effect/0/config/f32/3",
vec![OscType::Float(0.25)],
);
let action = parse_message(&msg).expect("effect config should parse");
match action {
UiAction::SetSceneEffectAnimationConfigF32(
SceneInstanceUnion::Grid(location),
effect_index,
config_index,
value,
) => {
assert_eq!(location.col, 1);
assert_eq!(location.row, 2);
assert_eq!(effect_index, 0);
assert_eq!(config_index, 3);
assert_eq!(value, 0.25);
}
_ => panic!("wrong action variant"),
}
}
#[test]
fn parses_selected_scene_effect_speed_exponent() {
let msg = msg(
"/scene/selected/effect/2/speed_exponent",
vec![OscType::Int(-1)],
);
let action = parse_message(&msg).expect("selected effect speed should parse");
match action {
UiAction::SetSceneEffectSpeedExponent(
SceneInstanceUnion::Selected,
effect_index,
value,
) => {
assert_eq!(effect_index, 2);
assert_eq!(value, -1);
}
_ => panic!("wrong action variant"),
}
}
#[test]
fn parses_project_palette_gradient_edit() {
let msg = msg(
"/project/palette/gradient/4",
vec![
OscType::Float(0.1),
OscType::Float(0.2),
OscType::Float(0.3),
],
);
let action = parse_message(&msg).expect("palette gradient should parse");
match action {
UiAction::SetProjectPaletteGradient(index, rgb) => {
assert_eq!(index, 4);
assert_eq!(rgb, [0.1, 0.2, 0.3]);
}
_ => panic!("wrong action variant"),
}
}
#[test]
fn parses_scene_effect_add() {
let msg = msg("/scene/grid/3/1/effect/add", vec![]);
let action = parse_message(&msg).expect("effect add should parse");
match action {
UiAction::AddSceneEffect(SceneInstanceUnion::Grid(location)) => {
assert_eq!(location.col, 3);
assert_eq!(location.row, 1);
}
_ => panic!("wrong action variant"),
}
}
#[test]
fn parses_selected_scene_effect_delete() {
let msg = msg("/scene/selected/effect/5/delete", vec![]);
let action = parse_message(&msg).expect("effect delete should parse");
match action {
UiAction::RemoveSceneEffect(SceneInstanceUnion::Selected, index) => {
assert_eq!(index, 5)
}
_ => panic!("wrong action variant"),
}
}
#[test]
fn parses_grid_activation_input_artnet() {
let msg = msg(
"/scene/grid/0/0/activation_input/artnet",
vec![OscType::Int(77)],
);
let action = parse_message(&msg).expect("activation input should parse");
match action {
UiAction::SetSceneActivationInput(
SceneInstanceUnion::Grid(location),
Some(InputEvent::Artnet(channel)),
) => {
assert_eq!(location.col, 0);
assert_eq!(location.row, 0);
assert_eq!(channel, 77);
}
_ => panic!("wrong action variant"),
}
}
#[test]
fn parses_selected_palette_overwrite_none() {
let msg = msg(
"/scene/selected/palette_overwrite",
vec![OscType::String("none".to_string())],
);
let action = parse_message(&msg).expect("palette overwrite should parse");
match action {
UiAction::SetScenePaletteOverwriteFromAsset(SceneInstanceUnion::Selected, value) => {
assert!(matches!(value, Some(None)));
}
_ => panic!("wrong action variant"),
}
}
#[test]
fn parses_selected_palette_overwrite_primary_edit() {
let msg = msg(
"/scene/selected/palette_overwrite/primary",
vec![
OscType::Float(0.2),
OscType::Float(0.4),
OscType::Float(0.6),
],
);
let action = parse_message(&msg).expect("selected palette primary should parse");
match action {
UiAction::SetScenePaletteOverwritePrimary(SceneInstanceUnion::Selected, rgb) => {
assert_eq!(rgb, [0.2, 0.4, 0.6]);
}
_ => panic!("wrong action variant"),
}
}
#[test]
fn parses_grid_palette_overwrite_gradient_edit() {
let msg = msg(
"/scene/grid/4/2/palette_overwrite/gradient/3",
vec![
OscType::Float(0.3),
OscType::Float(0.5),
OscType::Float(0.7),
],
);
let action = parse_message(&msg).expect("grid palette gradient should parse");
match action {
UiAction::SetScenePaletteOverwriteGradient(
SceneInstanceUnion::Grid(location),
index,
rgb,
) => {
assert_eq!(location.col, 4);
assert_eq!(location.row, 2);
assert_eq!(index, 3);
assert_eq!(rgb, [0.3, 0.5, 0.7]);
}
_ => panic!("wrong action variant"),
}
}
#[test]
fn parses_project_artnet_control_universe() {
let msg = msg("/project/artnet_control/universe", vec![OscType::Int(1337)]);
let action = parse_message(&msg).expect("artnet control universe should parse");
match action {
UiAction::SetProjectArtnetControlUniverse(universe) => {
assert_eq!(universe, 1337);
}
_ => panic!("wrong action variant"),
}
}
#[test]
fn parses_animation_argument_kind_edit() {
let animation_id = "11111111-1111-1111-1111-111111111111";
let msg = msg(
&format!("/asset/animation/{animation_id}/argument/1/kind"),
vec![OscType::String("degrees".to_string())],
);
let action = parse_message(&msg).expect("animation argument kind should parse");
match action {
UiAction::SetAnimationArgumentKind(_, argument_index, kind) => {
assert_eq!(argument_index, 1);
assert_eq!(kind, ArgumentKindId::Degrees);
}
_ => panic!("wrong action variant"),
}
}
#[test]
fn parses_effect_layout_set() {
let msg = msg("/scene/selected/effect/1/layout", vec![OscType::Int(2)]);
let action = parse_message(&msg).expect("effect layout set should parse");
match action {
UiAction::SetSceneEffectLayout(SceneInstanceUnion::Selected, effect_index, layout) => {
assert_eq!(effect_index, 1);
assert_eq!(layout, Some(2));
}
_ => panic!("wrong action variant"),
}
}
#[test]
fn parses_effect_layout_inherit() {
let msg = msg("/scene/selected/effect/1/layout", vec![OscType::Int(-1)]);
let action = parse_message(&msg).expect("effect layout inherit should parse");
match action {
UiAction::SetSceneEffectLayout(SceneInstanceUnion::Selected, effect_index, layout) => {
assert_eq!(effect_index, 1);
assert_eq!(layout, None);
}
_ => panic!("wrong action variant"),
}
}
#[test]
fn group_endpoints_are_rejected() {
let msg = msg(
"/project/groups/3",
vec![OscType::String("wash".to_string())],
);
assert!(parse_message(&msg).is_err());
}
#[test]
fn parses_project_input_add_artnet() {
let msg = msg("/project/input/tap/add/artnet", vec![OscType::Int(12)]);
let action = parse_message(&msg).expect("project input add should parse");
match action {
UiAction::AddProjectTapInputArtnet(channel) => assert_eq!(channel, 12),
_ => panic!("wrong action variant"),
}
}
#[test]
fn every_sample_address_parses() {
let failed: Vec<String> = sample_messages()
.iter()
.filter(|message| !message.addr.starts_with("/osc/state/"))
.filter(|message| parse_message(message).is_err())
.map(|message| format!("{} {:?}", message.addr, message.args))
.collect();
assert!(failed.is_empty(), "not understood: {failed:#?}");
}