use std::{fs, path::Path};
use gled_model::{
asset::{Asset, project::Project, scene::grid::GridLocation},
asset_id::AssetId,
};
use gled_protocol::{
codec::encode,
project_update::{ProjectPatch, ProjectUpdate},
};
fn fixture_project() -> Project {
let path = Path::new(env!("CARGO_MANIFEST_DIR"))
.join("../gled-model/tests/fixtures/projects/0bb3f5cd-f47f-4453-bd89-8bc53d9e1eb3.json");
let text = fs::read(&path).expect("fixture project is readable");
Asset::<Project>::read(text.as_slice(), AssetId::default())
.expect("fixture project loads")
.data
.clone()
}
fn first_location(project: &Project) -> GridLocation {
*project
.scenes_instances_grid
.keys()
.min_by_key(|location| (location.row, location.col))
.expect("the fixture has scenes")
}
fn patch(old: &Project, new: &Project) -> ProjectPatch {
let update = ProjectUpdate::between(Some(old), Some(new));
let mut replica = Some(old.clone());
update.clone().apply_to(&mut replica);
assert_eq!(replica.as_ref(), Some(new));
match update {
ProjectUpdate::Patched(patch) => patch,
other => panic!("expected a patch, got {other:?}"),
}
}
#[test]
fn a_scene_edit_sends_only_that_scene() {
let old = fixture_project();
let mut new = old.clone();
let location = first_location(&new);
if let Some(scene) = new.scenes_instances_grid.get_mut(&location) {
scene.active = !scene.active;
}
let patch = patch(&old, &new);
assert_eq!(patch.scenes.len(), 1);
assert!(patch.svg.is_none());
assert!(patch.rest.is_none());
let whole = encode(&new).expect("encodes").len();
let patched = encode(&patch).expect("encodes").len();
println!("whole project {whole} bytes, scene edit {patched} bytes");
assert!(patched * 5 < whole);
}
#[test]
fn removed_scenes_svg_and_settings_are_patched() {
let old = fixture_project();
let mut new = old.clone();
let location = first_location(&new);
new.scenes_instances_grid.remove(&location);
new.svg = None;
new.main_dimmer = 0.25;
let patch = patch(&old, &new);
assert_eq!(patch.scenes, vec![(location, None)]);
assert_eq!(patch.svg, Some(None));
let rest = patch.rest.expect("the dimmer changed");
assert!(rest.scenes_instances_grid.is_empty());
assert!(rest.svg.is_none());
}
#[test]
fn unchanged_and_replaced_projects() {
let project = fixture_project();
assert_eq!(
ProjectUpdate::between(Some(&project), Some(&project)),
ProjectUpdate::Unchanged
);
let mut replica = Some(project.clone());
ProjectUpdate::between(Some(&project), None).apply_to(&mut replica);
assert_eq!(replica, None);
ProjectUpdate::between(None, Some(&project)).apply_to(&mut replica);
assert_eq!(replica, Some(project));
}