mirror of
https://github.com/storytold/figcraft.git
synced 2026-11-03 01:00:39 +00:00
111 lines
5.3 KiB
Rust
111 lines
5.3 KiB
Rust
//! Dev Mode in the UI, the tail: the compare view compares with a saved version picked at its
|
|
//! bottom, and falls back when that version goes away.
|
|
|
|
use figcraft_engine::Session;
|
|
use serde_json::json;
|
|
|
|
use crate::dev_compare::CompareView;
|
|
use crate::present_tests::{Ui, id};
|
|
|
|
#[test]
|
|
fn compare_view_compares_with_a_saved_version() {
|
|
let mut s = Session::new();
|
|
let f = id(&s.execute("frame.create", &json!({"x": 0, "y": 0, "width": 300, "height": 400, "name": "Login"})).unwrap());
|
|
let r = id(&s.execute("shape.rectangle", &json!({"x": 20, "y": 300, "width": 120, "height": 40, "parent": f})).unwrap());
|
|
let mut u = Ui::new(s);
|
|
u.app.ui.right_tab = crate::RightTab::Inspect;
|
|
u.frame(vec![]);
|
|
// Neither ready for dev nor any version: nothing to compare with, the view doesn't stay.
|
|
u.app.ui.dev.compare = Some(CompareView::new(f, None));
|
|
u.frames(2, Vec::new);
|
|
assert!(u.app.ui.dev.compare.is_none());
|
|
let v = u.run("file.saveVersion", json!({"name": "Kickoff"}));
|
|
let v = v["id"].as_str().unwrap().to_string();
|
|
u.run("node.set", json!({"id": r, "props": {"width": 160}}));
|
|
u.run("dev.compare", json!({"id": f, "version": v, "show": true}));
|
|
u.frames(2, Vec::new);
|
|
assert_eq!(u.app.inspect()["devCompare"]["version"], json!(v));
|
|
// Opened without one, a layer that isn't ready compares with the newest version.
|
|
u.app.ui.dev.compare = Some(CompareView::new(f, None));
|
|
u.frames(2, Vec::new);
|
|
assert_eq!(u.app.inspect()["devCompare"]["version"], json!(v));
|
|
// Ready for dev: the snapshot from when it was marked is there too, and a deleted version
|
|
// falls back to it.
|
|
u.run("node.set", json!({"id": f, "props": {"devStatus": "readyForDev"}}));
|
|
u.run("node.set", json!({"id": r, "props": {"height": 48}}));
|
|
u.run("version.delete", json!({"id": v}));
|
|
u.frames(2, Vec::new);
|
|
assert_eq!(u.app.inspect()["devCompare"]["version"], json!(null));
|
|
assert!(u.app.ui.dev.compare.is_some());
|
|
}
|
|
|
|
#[test]
|
|
fn dev_mode_keys_refuse_design_edits_and_say_why() {
|
|
let mut s = Session::new();
|
|
let f = id(&s.execute("frame.create", &json!({"x": 0, "y": 0, "width": 300, "height": 400, "name": "Login"})).unwrap());
|
|
let r = id(&s.execute("shape.rectangle", &json!({"x": 20, "y": 30, "width": 120, "height": 40, "parent": f})).unwrap());
|
|
s.execute("select.set", &json!({"ids": [r]})).unwrap();
|
|
let mut u = Ui::new(s);
|
|
u.app.ui.right_tab = crate::RightTab::Inspect;
|
|
u.frame(vec![]);
|
|
let at = egui::pos2(700.0, 450.0);
|
|
let x = |u: &Ui| u.app.session.doc().unwrap().node(r).map(|n| n.transform.as_coeffs()[4]);
|
|
for key in [egui::Key::Delete, egui::Key::ArrowRight, egui::Key::Num5, egui::Key::R] {
|
|
u.key(at, key);
|
|
}
|
|
assert!(u.app.session.doc().unwrap().contains(r), "not deleted");
|
|
assert_eq!(x(&u), Some(20.0), "not nudged");
|
|
assert_eq!(u.app.session.doc().unwrap().node(r).map(|n| n.opacity), Some(1.0), "opacity kept");
|
|
assert_eq!(u.app.session.tool.tool, figcraft_engine::tools::ToolId::Move, "no drawing tool");
|
|
assert!(u.app.ui.toast.as_ref().is_some_and(|(m, _)| m.contains("Shift+D")));
|
|
// In the design the same keys edit.
|
|
u.app.ui.right_tab = crate::RightTab::Design;
|
|
u.frame(vec![]);
|
|
u.key(at, egui::Key::ArrowRight);
|
|
assert_eq!(x(&u), Some(21.0));
|
|
}
|
|
|
|
#[test]
|
|
fn read_only_plugins_run_from_the_inspect_tab_show_their_panel() {
|
|
use base64::Engine as _;
|
|
let wasm = base64::engine::general_purpose::STANDARD.encode(crate::plugin_panel_tests::panel_module());
|
|
let manifest = json!({"id": "org.test.inspect", "name": "Inspect panel", "main": "p.wasm", "api": 2, "permissions": {"access": "read"}});
|
|
let mut s = Session::new();
|
|
s.execute("plugin.import", &json!({"manifest": manifest, "wasm": wasm})).unwrap();
|
|
let mut u = Ui::new(s);
|
|
u.app.ui.right_tab = crate::RightTab::Inspect;
|
|
u.frame(vec![]);
|
|
// What the Inspect tab's Plugins row runs.
|
|
crate::plugins_ui::start(&mut u.app, "org.test.inspect", "run");
|
|
u.frame(vec![]);
|
|
assert_eq!(u.app.session.plugins.panels.len(), 1, "its panel shows");
|
|
// Its callbacks only read: the button that would draw is refused and the design stays.
|
|
let layers = |u: &Ui| u.app.session.doc().unwrap().ids().count();
|
|
let before = layers(&u);
|
|
assert!(u.app.session.execute("plugin.event", &json!({"id": "org.test.inspect", "control": "go"})).is_err());
|
|
assert_eq!(layers(&u), before);
|
|
}
|
|
|
|
/// A clipboard holding only text.
|
|
struct TextClip(String);
|
|
|
|
impl crate::Services for TextClip {
|
|
fn clipboard_get_text(&mut self) -> Option<String> {
|
|
Some(self.0.clone())
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn dev_mode_pastes_only_a_comments_link() {
|
|
let mut s = Session::new();
|
|
let c = s.execute("comment.add", &json!({"x": 10, "y": 10, "text": "Check the spacing"})).unwrap()["id"].as_u64().unwrap();
|
|
let layers = |app: &crate::FigApp| app.session.doc().unwrap().node(app.session.page().unwrap()).unwrap().children.len();
|
|
let mut app = crate::FigApp::new(s, Box::new(TextClip("Pasted words".into())));
|
|
app.ui.right_tab = crate::RightTab::Inspect;
|
|
crate::menus::paste(&mut app, None, None);
|
|
assert_eq!(layers(&app), 0, "text doesn't paste into the design in Dev Mode");
|
|
app.services = Box::new(TextClip(format!("figcraft://comment/{c}")));
|
|
crate::menus::paste(&mut app, None, None);
|
|
assert_eq!(app.ui.comments.open, Some(c), "the link opens its thread");
|
|
}
|