test: decouple document fixtures from product releases

This commit is contained in:
Kayshen-X 2026-07-15 21:10:08 +08:00
parent e0a2bd4e69
commit 5b0d1edb4c
66 changed files with 261 additions and 225 deletions

View file

@ -412,7 +412,7 @@ mod tests {
/// Bare empty document — no variables, no pages, no children.
fn empty_doc() -> PenDocument {
PenDocument {
version: "0.8.0".into(),
version: "1.0.0".into(),
name: None,
themes: None,
variables: None,

View file

@ -59,7 +59,7 @@ fn add_layer_blur_appends_blur_effect() {
fn add_effect_on_effectless_node_creates_no_undo_state() {
// An icon_font node carries no `effects` list. Adding an
// effect must be a no-op that leaves NO empty undo/dirty state.
let src = r#"{"version":"0.8.0","children":[
let src = r#"{"version":"1.0.0","children":[
{"type":"icon_font","id":"i1","name":"Icon",
"x":0,"y":0,"width":20,"height":20,"iconFontName":"star"}
]}"#;

View file

@ -39,7 +39,7 @@ use jian_ops_schema::node::PenNode;
/// Parse a single node fixture by wrapping it in a canonical doc.
fn node_from(json: &str) -> PenNode {
let doc = format!(r#"{{"version":"0.8.0","children":[{json}]}}"#);
let doc = format!(r#"{{"version":"1.0.0","children":[{json}]}}"#);
jian_ops_schema::load_str(&doc)
.expect("fixture parses")
.value

View file

@ -436,7 +436,7 @@ mod tests {
#[test]
fn from_document_indexes_reusable_frames() {
let mut doc = jian_ops_schema::PenDocument {
version: "0.8.0".into(),
version: "1.0.0".into(),
name: None,
themes: None,
variables: None,

View file

@ -1026,7 +1026,7 @@ mod tests {
/// A bare rectangle node fixture, parsed from `.op` JSON so it
/// stays robust to schema growth.
fn rect_node() -> PenNode {
let src = r#"{"version":"0.8.0","children":[
let src = r#"{"version":"1.0.0","children":[
{"type":"rectangle","id":"r1","name":"R",
"x":0,"y":0,"width":10,"height":10}
]}"#;

View file

@ -8,7 +8,7 @@ use jian_ops_schema::style::{PenFill, PenStroke, SidedThickness, StrokeThickness
fn three_fill_state() -> crate::EditorState {
let src = r##"{
"version":"0.8.0",
"version":"1.0.0",
"children":[{
"type":"rectangle","id":"n1","name":"R",
"x":0,"y":0,"width":10,"height":10,
@ -204,7 +204,7 @@ fn node_stroke_width_reads_max_sided_edge() {
}
fn rect_node() -> PenNode {
let src = r#"{"version":"0.8.0","children":[
let src = r#"{"version":"1.0.0","children":[
{"type":"rectangle","id":"r1","name":"R",
"x":0,"y":0,"width":10,"height":10}
]}"#;

View file

@ -30,7 +30,7 @@ use std::time::Instant;
fn empty_doc() -> PenDocument {
PenDocument {
version: "0.8.0".into(),
version: "1.0.0".into(),
name: None,
themes: None,
variables: None,

View file

@ -383,7 +383,7 @@ fn repair_swap_is_copy_on_write_and_does_not_contaminate_a_shared_sibling_snapsh
// A doc whose top-level entry "inst1" is a NON-Ref node — the
// contamination signature a scope-time snapshot would carry.
let mut doc = PenDocument {
version: "0.8.0".into(),
version: "1.0.0".into(),
..empty()
};
doc.children = vec![
@ -432,7 +432,7 @@ fn repair_swap_is_copy_on_write_and_does_not_contaminate_a_shared_sibling_snapsh
fn empty() -> PenDocument {
PenDocument {
version: "0.8.0".into(),
version: "1.0.0".into(),
name: None,
themes: None,
variables: None,

View file

@ -140,7 +140,7 @@ mod tests {
use crate::EditorState;
const DOC: &str = r##"{
"version":"0.8.0",
"version":"1.0.0",
"children":[
{"type":"frame","id":"button","name":"Button","reusable":true,
"width":120,"height":40,"children":[
@ -159,7 +159,7 @@ mod tests {
fn rich_color_state() -> EditorState {
let doc = jian_ops_schema::load_str(
r##"{
"version":"0.8.0",
"version":"1.0.0",
"children":[
{"type":"frame","id":"card","name":"Card","reusable":true,
"width":120,"height":80,"children":[

View file

@ -460,7 +460,7 @@ mod tests {
use crate::ref_resolve::resolve_refs_for_canvas;
const DOC: &str = r##"{
"version":"0.8.0",
"version":"1.0.0",
"children":[
{"type":"frame","id":"card","name":"Card","reusable":true,"x":0,"y":0,"width":200,"height":100,
"fill":[{"type":"solid","color":"#222222"}],

View file

@ -3,7 +3,7 @@ use crate::walkers::find_node;
use jian_ops_schema::node::container::{AlignItems, JustifyContent};
const HISTORY_DOC: &str = r##"{
"version":"0.8.0",
"version":"1.0.0",
"children":[
{"type":"frame","id":"master","name":"Master","reusable":true,
"x":0,"y":0,"width":100,"height":100,"layout":"vertical",

View file

@ -409,7 +409,7 @@ mod tests {
}
const DOC_WITH_INSTANCE: &str = r##"{
"version":"0.8.0",
"version":"1.0.0",
"children":[
{"type":"frame","id":"card","name":"Card","reusable":true,"x":0,"y":0,"width":200,"height":100,
"fill":[{"type":"solid","color":"#222222"}],
@ -471,7 +471,7 @@ mod tests {
fn unknown_target_and_cycles_drop_instead_of_panicking() {
let doc = doc_from(
r##"{
"version":"0.8.0",
"version":"1.0.0",
"children":[
{"type":"ref","id":"dangling","ref":"missing"},
{"type":"frame","id":"a","name":"A","reusable":true,
@ -508,7 +508,7 @@ mod tests {
// empty (a high-`cornerRadius` `fit_content` card collapses to a
// white circle).
const DOC_WITH_SLOT_INSTANCE: &str = r##"{
"version":"0.8.0",
"version":"1.0.0",
"children":[
{"type":"frame","id":"cardMaster","name":"Card/Default","reusable":true,
"width":"fit_content","height":"fit_content","cornerRadius":24,"padding":16,
@ -562,7 +562,7 @@ mod tests {
// the slot-fallback path).
let doc = doc_from(
r##"{
"version":"0.8.0",
"version":"1.0.0",
"children":[
{"type":"frame","id":"master","name":"Master","reusable":true,
"width":200,"height":100,

View file

@ -565,7 +565,7 @@ fn incremental_container_resize_never_accumulates_descendant_changes() {
#[test]
fn single_axis_resize_freezes_only_that_axis_and_preserves_child_keywords() {
let doc = jian_ops_schema::load_str(
r#"{"version":"0.8.0","children":[{"type":"frame","id":"root","width":"fill_container","height":"fit_content","layout":"vertical","children":[{"type":"rectangle","id":"child","width":"fill_container","height":40}]}]}"#,
r#"{"version":"1.0.0","children":[{"type":"frame","id":"root","width":"fill_container","height":"fit_content","layout":"vertical","children":[{"type":"rectangle","id":"child","width":"fill_container","height":40}]}]}"#,
)
.expect("keyword fixture parses")
.value;

View file

@ -463,7 +463,7 @@ mod tests {
fn doc_with(children: Vec<PenNode>) -> PenDocument {
PenDocument {
version: "0.8.0".to_string(),
version: "1.0.0".to_string(),
name: Some("Source".to_string()),
themes: None,
variables: None,
@ -546,7 +546,7 @@ mod tests {
let kit = import_kit_from_document(&doc, "kit-1".to_string()).expect("kit");
assert_eq!(kit.id, "kit-1");
assert_eq!(kit.name, "Design System");
assert_eq!(kit.version, "0.8.0");
assert_eq!(kit.version, "1.0.0");
assert!(!kit.built_in);
assert_eq!(kit.components.len(), 2);
let button = &kit.components[0];

View file

@ -900,7 +900,7 @@ mod tests {
// `$ref` string and whose gap is a `$spacing` token must
// render concrete values with NO transient editor cache.
let mut doc = doc_from(
r##"{"version":"0.8.0","variables":{"brand":{"type":"color","value":"#ff8800"}},
r##"{"version":"1.0.0","variables":{"brand":{"type":"color","value":"#ff8800"}},
"children":[{"type":"frame","id":"f1","name":"f1","x":0,"y":0,"width":100,"height":50,
"fill":[{"type":"solid","color":"$brand"}],"layout":"vertical","gap":"$spacing-2",
"children":[{"type":"text","id":"t1","name":"t1","content":"$brand"}]}]}"##,
@ -928,7 +928,7 @@ mod tests {
#[test]
fn replace_refs_renames_tokens_and_freezes_values_on_delete() {
let mut doc = doc_from(
r##"{"version":"0.8.0","variables":{"brand":{"type":"color","value":"#ff8800"}},
r##"{"version":"1.0.0","variables":{"brand":{"type":"color","value":"#ff8800"}},
"children":[{"type":"rectangle","id":"r1","name":"r1","x":0,"y":0,"width":10,"height":10,
"fill":[{"type":"solid","color":"$brand"}]}]}"##,
);
@ -971,7 +971,7 @@ mod tests {
#[test]
fn effective_theme_layers_active_over_axis_defaults() {
let doc = doc_from(
r#"{"version":"0.8.0","themes":{"Mode":["Light","Dark"],"Density":["Comfort","Compact"]},"children":[]}"#,
r#"{"version":"1.0.0","themes":{"Mode":["Light","Dark"],"Density":["Comfort","Compact"]},"children":[]}"#,
);
let active = Theme::from([("Mode".to_string(), "Dark".to_string())]);
let theme = effective_theme(&doc, &active);

View file

@ -6,7 +6,7 @@ use op_editor_core::{
fn state() -> EditorState {
let doc = jian_ops_schema::load_str(
r##"{"version":"0.8.0","children":[
r##"{"version":"1.0.0","children":[
{"type":"frame","id":"master","name":"Master","reusable":true,
"x":0,"y":0,"width":100,"height":100,"children":[
{"type":"rectangle","id":"surface","name":"Surface",

View file

@ -9,7 +9,7 @@ use op_editor_host_core::codegen::{
fn two_rect_state() -> EditorState {
let doc = jian_ops_schema::load_str(
r#"{"version":"0.8.0","children":[
r#"{"version":"1.0.0","children":[
{"type":"rectangle","id":"n1","name":"A","x":0,"y":0,"width":10,"height":10},
{"type":"rectangle","id":"n2","name":"B","x":20,"y":0,"width":10,"height":10}
]}"#,

View file

@ -103,7 +103,7 @@ impl RenderBackend for LayerLabelBackend {
fn state_with_layer_name(name: &str) -> EditorState {
let source = format!(
r#"{{"version":"0.8.0","children":[{{"type":"rectangle","id":"n1","name":"{name}","width":10,"height":10}}]}}"#
r#"{{"version":"1.0.0","children":[{{"type":"rectangle","id":"n1","name":"{name}","width":10,"height":10}}]}}"#
);
let doc = jian_ops_schema::load_str(&source)
.expect("layer-label fixture parses")

View file

@ -23,7 +23,7 @@ fn state_from(src: &str) -> EditorState {
/// Four sibling rectangles `n1..n4` in a single-page document.
fn four_rects() -> EditorState {
state_from(
r##"{ "version": "0.8.0", "children": [
r##"{ "version": "1.0.0", "children": [
{"type":"rectangle","id":"n1","name":"A","width":10,"height":10},
{"type":"rectangle","id":"n2","name":"B","width":10,"height":10},
{"type":"rectangle","id":"n3","name":"C","width":10,"height":10},
@ -94,7 +94,7 @@ fn whole_document_replacement_needs_owner_rotation_to_avoid_stale_rows() {
// host's layer-panel owner never rotates on its own.
let doc_a = four_rects(); // rows A/B/C/D
let doc_b = state_from(
r##"{ "version": "0.8.0", "children": [
r##"{ "version": "1.0.0", "children": [
{"type":"rectangle","id":"m1","name":"W","width":10,"height":10},
{"type":"rectangle","id":"m2","name":"X","width":10,"height":10}
]}"##,
@ -181,7 +181,7 @@ fn empty_document_yields_one_default_page_no_layers() {
#[test]
fn collapsed_node_hides_its_children() {
let state = state_from(
r##"{ "version": "0.8.0", "children": [
r##"{ "version": "1.0.0", "children": [
{"type":"frame","id":"n1","name":"Frame","width":100,"height":100,
"children":[
{"type":"rectangle","id":"n2","name":"Child","width":10,"height":10}
@ -205,7 +205,7 @@ fn unnamed_node_row_falls_back_to_kind_label() {
// `name`. The layer row must then show the kind label (TS parity:
// `node.name ?? node.type`) instead of a blank label.
let state = state_from(
r##"{ "version": "0.8.0", "children": [
r##"{ "version": "1.0.0", "children": [
{"type":"rectangle","id":"n1","width":10,"height":10},
{"type":"frame","id":"n2","width":20,"height":20},
{"type":"rectangle","id":"n3","name":"Hero","width":10,"height":10}
@ -226,7 +226,7 @@ fn ghost_item_for_unnamed_node_falls_back_to_kind_label() {
// The drag-ghost row (host paints it at the cursor) shares the same
// name-or-kind fallback so a nameless node isn't a blank ghost.
let state = state_from(
r##"{ "version": "0.8.0", "children": [
r##"{ "version": "1.0.0", "children": [
{"type":"ellipse","id":"n1","width":10,"height":10}
]}"##,
);
@ -503,7 +503,7 @@ fn access_node_advertises_tree_role_and_layers_label() {
#[test]
fn from_document_scopes_to_active_page_only() {
let mut state = state_from(
r##"{ "version": "0.8.0", "children": [], "pages": [
r##"{ "version": "1.0.0", "children": [], "pages": [
{"id":"n1","name":"Page 1","children":[
{"type":"frame","id":"n2","name":"P1-Node","width":10,"height":10}]},
{"id":"n3","name":"Page 2","children":[
@ -606,7 +606,7 @@ fn drop_target_at_in_empty_area_below_rows_drops_at_end() {
}
fn nested_frame_doc(depth: usize) -> String {
let mut src = String::from(r#"{"version":"0.8.0","children":["#);
let mut src = String::from(r#"{"version":"1.0.0","children":["#);
for i in 0..depth {
src.push_str(&format!(
r##"{{"type":"frame","id":"nest-{i:05}","name":"Nested Layer {i:05}","x":8,"y":6,"width":400,"height":220,"fill":[{{"type":"solid","color":"#ffffff20"}}],"stroke":{{"thickness":1,"fill":[{{"type":"solid","color":"#0088ff"}}]}},"children":["##

View file

@ -20,7 +20,7 @@ fn panel_rect() -> Rect {
fn selected_rect_state() -> op_editor_core::EditorState {
let mut state = state_from(
r##"{ "version": "0.8.0", "children": [
r##"{ "version": "1.0.0", "children": [
{"type":"rectangle","id":"rect","name":"Rect",
"x":40,"y":40,"width":160,"height":100,
"fill":[{"type":"solid","color":"#112233"}]}
@ -32,7 +32,7 @@ fn selected_rect_state() -> op_editor_core::EditorState {
fn selected_three_fill_state() -> op_editor_core::EditorState {
let mut state = state_from(
r##"{ "version": "0.8.0", "children": [
r##"{ "version": "1.0.0", "children": [
{"type":"rectangle","id":"rect","name":"Rect",
"x":40,"y":40,"width":160,"height":100,
"fill":[
@ -91,7 +91,7 @@ fn fill_type_picker_hit_uses_shared_outside_protocol() {
fn fill_type_picker_hit_anchors_to_instance_toggle_action_rect() {
let mut state = state_from(
r##"{
"version":"0.8.0",
"version":"1.0.0",
"children":[
{"type":"frame","id":"card","name":"Card","reusable":true,
"x":0,"y":0,"width":"fill_container","height":"fill_container",

View file

@ -94,7 +94,7 @@ fn text_size_section_does_not_emit_clip_content_action() {
#[test]
fn icon_font_selection_exposes_icon_picker_action() {
let mut state = state_from(
r##"{ "version": "0.8.0", "children": [
r##"{ "version": "1.0.0", "children": [
{"type":"icon_font","id":"icon","name":"Search",
"x":40,"y":40,"width":24,"height":24,
"iconFontName":"search","iconFontFamily":"lucide"}

View file

@ -12,7 +12,7 @@ use op_editor_core::NodeId;
fn image_fill_state_with_url(url: &str) -> op_editor_core::EditorState {
let mut state = state_from(&format!(
r##"{{ "version": "0.8.0", "children": [
r##"{{ "version": "1.0.0", "children": [
{{"type":"rectangle","id":"n60","name":"Photo fill",
"x":40,"y":40,"width":180,"height":120,
"fill":[{{"type":"image","url":"{}","mode":"fill",

View file

@ -12,7 +12,7 @@ use crate::{Point2D, Rect};
use op_editor_core::NodeId;
const COMPONENT_DOC: &str = r##"{
"version":"0.8.0",
"version":"1.0.0",
"children":[
{"type":"frame","id":"card","name":"Card","reusable":true,"x":0,"y":0,"width":200,"height":100,
"fill":[{"type":"solid","color":"#222222"}],
@ -80,7 +80,7 @@ fn reusable_component_snapshot_flags_is_reusable() {
fn registered_group_component_snapshot_flags_is_reusable() {
let mut state = state_from(
r##"{
"version":"0.8.0",
"version":"1.0.0",
"children":[
{"type":"group","id":"text_group","name":"Text Group",
"children":[{"type":"text","id":"label","name":"Label","content":"Hello"}]}

View file

@ -78,7 +78,7 @@ fn multi_select_caps_keep_size_hide_fill_and_stroke() {
fn multi_select_panel_shows_even_when_all_zero_size() {
// Symmetry with single-select: a 0x0 node still shows the panel.
let mut state = state_from(
r##"{ "version": "0.8.0", "children": [
r##"{ "version": "1.0.0", "children": [
{"type":"rectangle","id":"n50","name":"A"},
{"type":"rectangle","id":"n51","name":"B"}
]}"##,
@ -96,7 +96,7 @@ fn multi_select_panel_shows_even_when_all_zero_size() {
fn padding_pin_does_not_leak_into_a_different_selection() {
use op_editor_core::PaddingEditMode;
let mut state = state_from(
r#"{"version":"0.8.0","children":[
r#"{"version":"1.0.0","children":[
{"type":"frame","id":"a","name":"A","x":0,"y":0,"width":100,"height":100},
{"type":"frame","id":"b","name":"B","x":200,"y":0,"width":100,"height":100}
]}"#,

View file

@ -13,7 +13,7 @@ fn panel_rect() -> Rect {
fn sided_stroke_state() -> op_editor_core::EditorState {
let mut state = state_from(
r##"{ "version": "0.8.0", "children": [
r##"{ "version": "1.0.0", "children": [
{"type":"rectangle","id":"rect","name":"Rect",
"x":40,"y":40,"width":160,"height":100,
"fill":[{"type":"solid","color":"#ffffff"}],

View file

@ -63,7 +63,7 @@ fn for_selection_with_real_node_builds_snapshot() {
#[test]
fn scene_aware_panel_reports_resolved_fill_and_hug_dimensions() {
let mut state = state_from(
r##"{ "version": "0.8.0", "children": [
r##"{ "version": "1.0.0", "children": [
{"type":"frame","id":"ff","name":"Frame",
"width":"fill_container","height":"fit_content","children":[]}
]}"##,
@ -90,7 +90,7 @@ fn scene_aware_panel_reports_resolved_fill_and_hug_dimensions() {
#[test]
fn scene_aware_panel_keeps_unbounded_group_aggregate_dimensions() {
let mut state = state_from(
r##"{ "version": "0.8.0", "children": [
r##"{ "version": "1.0.0", "children": [
{"type":"group","id":"g","name":"Group","children":[
{"type":"rectangle","id":"child","x":10,"y":20,
"width":70,"height":30}
@ -216,7 +216,7 @@ fn group_snapshot_aggregates_child_bounds() {
#[test]
fn polygon_selection_exposes_sides_layer_input() {
let mut state = state_from(
r##"{ "version": "0.8.0", "children": [
r##"{ "version": "1.0.0", "children": [
{"type":"polygon","id":"poly","name":"Hex",
"x":40,"y":40,"width":120,"height":120,
"polygonCount":6}
@ -250,7 +250,7 @@ fn polygon_selection_exposes_sides_layer_input() {
#[test]
fn ellipse_selection_exposes_arc_layer_inputs() {
let mut state = state_from(
r##"{ "version": "0.8.0", "children": [
r##"{ "version": "1.0.0", "children": [
{"type":"ellipse","id":"ell","name":"Arc",
"x":40,"y":40,"width":120,"height":100,
"startAngle":30,"sweepAngle":270,"innerRadius":0.25}
@ -387,7 +387,7 @@ fn hit_test_action_export_section_returns_picker_toggles() {
#[test]
fn color_variables_add_fill_and_stroke_binding_buttons() {
let mut state = state_from(
r##"{ "version": "0.8.0", "children": [
r##"{ "version": "1.0.0", "children": [
{"type":"rectangle","id":"rect","name":"Rect",
"x":40,"y":40,"width":160,"height":100,
"fill":[{"type":"solid","color":"#ffffff"}],
@ -439,7 +439,7 @@ fn color_variables_add_fill_and_stroke_binding_buttons() {
#[test]
fn color_variable_picker_emits_bind_and_unbind_rows() {
let mut state = state_from(
r##"{ "version": "0.8.0", "children": [
r##"{ "version": "1.0.0", "children": [
{"type":"rectangle","id":"rect","name":"Rect",
"x":40,"y":40,"width":160,"height":100,
"fill":[{"type":"solid","color":"#ffffff"}],
@ -511,7 +511,7 @@ fn fill_width_keeps_both_numeric_inputs_visible_and_hittable() {
use op_editor_core::PropertyFocus;
let fill = {
let mut s = state_from(
r##"{ "version": "0.8.0", "children": [
r##"{ "version": "1.0.0", "children": [
{"type":"frame","id":"ff","name":"Frame",
"x":40,"y":40,"width":"fill_container","height":240,
"layout":"vertical","children":[]}
@ -549,7 +549,7 @@ fn both_dimensions_fill_keep_the_size_input_row() {
};
let panel_for = |w: &str, h: &str| {
let json = format!(
r##"{{ "version": "0.8.0", "children": [
r##"{{ "version": "1.0.0", "children": [
{{"type":"frame","id":"ff","name":"Frame",
"x":40,"y":40,"width":{w},"height":{h},
"layout":"vertical","children":[]}}
@ -599,7 +599,7 @@ fn both_dimensions_fill_keep_the_size_input_row() {
fn fill_and_hug_inputs_paint_snapshot_size_and_numeric_commit_makes_fixed() {
use op_editor_core::PropertyFocus;
let mut state = state_from(
r##"{ "version": "0.8.0", "children": [
r##"{ "version": "1.0.0", "children": [
{"type":"frame","id":"ff","name":"Frame",
"x":40,"y":40,"width":"fill_container","height":"fit_content",
"layout":"vertical","children":[
@ -656,7 +656,7 @@ fn padding_mode_derives_from_values_and_drives_input_count() {
};
let padding_rects = |padding: &str| {
let json = format!(
r##"{{ "version": "0.8.0", "children": [
r##"{{ "version": "1.0.0", "children": [
{{"type":"frame","id":"f","name":"F","x":0,"y":0,
"width":300,"height":200,"layout":"vertical",
"padding":{padding},"children":[]}}
@ -691,7 +691,7 @@ fn padding_mode_derives_from_values_and_drives_input_count() {
#[test]
fn flex_advanced_rows_do_not_overlap_gap_modes() {
let mut state = state_from(
r##"{ "version": "0.8.0", "children": [
r##"{ "version": "1.0.0", "children": [
{"type":"frame","id":"f","name":"Frame",
"x":40,"y":40,"width":360,"height":240,
"layout":"horizontal","gap":0,

View file

@ -23,7 +23,7 @@ fn widget_state(src: &str) -> op_editor_core::EditorState {
#[test]
fn widget_section_hidden_unless_experimental_enabled() {
let src = r##"{ "version": "0.8.0", "children": [
let src = r##"{ "version": "1.0.0", "children": [
{"type":"text_input","id":"email","name":"Email",
"x":24,"y":32,"width":220,"height":40,"placeholder":"Email"}
]}"##;
@ -50,7 +50,7 @@ fn widget_section_hidden_unless_experimental_enabled() {
#[test]
fn text_input_selection_exposes_widget_text_rows() {
let mut state = widget_state(
r##"{ "version": "0.8.0", "children": [
r##"{ "version": "1.0.0", "children": [
{"type":"text_input","id":"email","name":"Email",
"x":24,"y":32,"width":220,"height":40,
"placeholder":"Email address","value":"kai@example.com"}
@ -78,7 +78,7 @@ fn text_input_selection_exposes_widget_text_rows() {
#[test]
fn property_panel_text_input_fields_expose_icon_and_bind_rows() {
let mut state = widget_state(
r##"{ "version": "0.8.0", "children": [
r##"{ "version": "1.0.0", "children": [
{"type":"text_input","id":"email","name":"Email",
"x":24,"y":32,"width":220,"height":40,
"leadingIcon":"mail","trailingIcon":"eye",
@ -113,7 +113,7 @@ fn checkbox_selection_hides_icon_and_bind_rows() {
// Icon + bind editing is Phase-1 scoped to the input kinds; a
// Checkbox widget shows neither.
let mut state = widget_state(
r##"{ "version": "0.8.0", "children": [
r##"{ "version": "1.0.0", "children": [
{"type":"checkbox","id":"cb","name":"Agree","x":0,"y":0,"width":18,"height":18,
"label":"Accept","checked":false}
]}"##,
@ -133,7 +133,7 @@ fn checkbox_selection_hides_icon_and_bind_rows() {
#[test]
fn slider_selection_exposes_widget_range_rows() {
let mut state = widget_state(
r##"{ "version": "0.8.0", "children": [
r##"{ "version": "1.0.0", "children": [
{"type":"slider","id":"volume","name":"Volume",
"x":24,"y":32,"width":220,"height":24,
"min":0,"max":100,"step":5,"value":50}
@ -165,7 +165,7 @@ fn slider_selection_exposes_widget_range_rows() {
#[test]
fn frame_selection_hides_widget_section() {
let mut state = widget_state(
r##"{ "version": "0.8.0", "children": [
r##"{ "version": "1.0.0", "children": [
{"type":"frame","id":"f1","name":"Frame","x":0,"y":0,"width":200,"height":100}
]}"##,
);
@ -188,7 +188,7 @@ fn frame_selection_hides_widget_section() {
fn checkbox_selection_emits_toggle_checked_action() {
use super::property_panel::PropertyPanelAction;
let mut state = widget_state(
r##"{ "version": "0.8.0", "children": [
r##"{ "version": "1.0.0", "children": [
{"type":"checkbox","id":"cb","name":"Agree","x":0,"y":0,"width":18,"height":18,
"label":"Accept","checked":false}
]}"##,
@ -214,7 +214,7 @@ fn checkbox_selection_emits_toggle_checked_action() {
fn committing_placeholder_updates_text_input_node() {
use jian_ops_schema::node::PenNode;
let mut state = widget_state(
r##"{ "version": "0.8.0", "children": [
r##"{ "version": "1.0.0", "children": [
{"type":"text_input","id":"email","name":"Email",
"x":0,"y":0,"width":220,"height":40,"placeholder":"Email"}
]}"##,
@ -235,7 +235,7 @@ fn committing_placeholder_updates_text_input_node() {
fn committing_slider_max_updates_node() {
use jian_ops_schema::node::PenNode;
let mut state = widget_state(
r##"{ "version": "0.8.0", "children": [
r##"{ "version": "1.0.0", "children": [
{"type":"slider","id":"sl","name":"Vol","x":0,"y":0,"width":220,"height":24,
"min":0,"max":100,"step":1,"value":50}
]}"##,

View file

@ -647,7 +647,7 @@ mod tests {
let mut host = WidgetHostNative::new();
let doc = jian_ops_schema::load_str(
r#"{
"version":"0.8.0",
"version":"1.0.0",
"children":[
{"type":"frame","id":"left","name":"Left","x":900,"y":120,"width":240,"height":320},
{"type":"frame","id":"right","name":"Right","x":1320,"y":220,"width":260,"height":280}
@ -695,7 +695,7 @@ mod tests {
let mut host = WidgetHostNative::new();
let doc = jian_ops_schema::load_str(
r#"{
"version":"0.8.0",
"version":"1.0.0",
"children":[{
"type":"frame","id":"root","name":"Explore",
"x":12,"y":24,"width":390,"height":"fit_content",

View file

@ -24,7 +24,7 @@ fn enter(doc: &jian_ops_schema::PenDocument) -> PreviewSession {
fn phone_doc_with_bottom_nav(nav_extra: &str) -> jian_ops_schema::PenDocument {
load(&format!(
r##"{{
"version": "0.8.0",
"version": "1.0.0",
"children": [
{{ "type": "frame", "id": "screen", "x": 0, "y": 0,
"width": 390, "height": 800,
@ -83,7 +83,7 @@ fn framed_root_app_mode_returns_mounted_screen_root() {
fn zero_height_semantic_nav_is_rejected() {
let doc = load(
r##"{
"version": "0.8.0",
"version": "1.0.0",
"children": [
{ "type": "frame", "id": "screen", "x": 0, "y": 0,
"width": 390, "height": 800,
@ -102,7 +102,7 @@ fn zero_height_semantic_nav_is_rejected() {
#[test]
fn framed_root_none_for_empty_page() {
let doc = load(r##"{ "version": "0.8.0", "children": [] }"##);
let doc = load(r##"{ "version": "1.0.0", "children": [] }"##);
let session = enter(&doc);
assert!(session.framed_root().is_none());
}
@ -127,7 +127,7 @@ fn desktop_never_pins() {
fn semantic_nav_pins_even_when_narrow() {
let doc = load(
r##"{
"version": "0.8.0",
"version": "1.0.0",
"children": [
{ "type": "frame", "id": "screen", "x": 0, "y": 0,
"width": 390, "height": 800,
@ -150,7 +150,7 @@ fn semantic_nav_pins_even_when_narrow() {
fn top_nav_with_semantic_role_does_not_pin() {
let doc = load(
r##"{
"version": "0.8.0",
"version": "1.0.0",
"children": [
{ "type": "frame", "id": "screen", "x": 0, "y": 0,
"width": 390, "height": 800,
@ -179,7 +179,7 @@ fn hidden_nav_is_rejected() {
fn heuristic_rejects_each_missing_gate() {
let doc = load(
r##"{
"version": "0.8.0",
"version": "1.0.0",
"children": [
{ "type": "frame", "id": "screen", "x": 0, "y": 0,
"width": 390, "height": 800,
@ -196,7 +196,7 @@ fn heuristic_rejects_each_missing_gate() {
let doc = load(
r##"{
"version": "0.8.0",
"version": "1.0.0",
"children": [
{ "type": "frame", "id": "screen", "x": 0, "y": 0,
"width": 390, "height": 800,
@ -213,7 +213,7 @@ fn heuristic_rejects_each_missing_gate() {
let doc = load(
r##"{
"version": "0.8.0",
"version": "1.0.0",
"children": [
{ "type": "frame", "id": "screen", "x": 0, "y": 0,
"width": 390, "height": 800,
@ -233,7 +233,7 @@ fn heuristic_rejects_each_missing_gate() {
fn oversized_or_hidden_candidates_are_rejected() {
let doc = load(
r##"{
"version": "0.8.0",
"version": "1.0.0",
"children": [
{ "type": "frame", "id": "screen", "x": 0, "y": 0,
"width": 390, "height": 800,

View file

@ -79,7 +79,7 @@ fn assert_same_bounds(design: &LayoutScene, preview: &LayoutScene, id: &str) {
fn preserve_geometry_doc() -> jian_ops_schema::PenDocument {
load(
r##"{
"version": "0.8.0",
"version": "1.0.0",
"children": [
{ "type": "frame", "id": "root", "x": 0, "y": 0,
"width": 400, "height": 300,
@ -125,7 +125,7 @@ fn preview_matches_design_for_preserve_geometry_doc() {
fn role_frame_doc() -> jian_ops_schema::PenDocument {
load(
r##"{
"version": "0.8.0",
"version": "1.0.0",
"children": [
{ "type": "frame", "id": "root", "x": 0, "y": 0,
"width": 400, "height": 600,
@ -237,7 +237,7 @@ fn preview_matches_design_for_free_layout_doc() {
let _guard = crate::font_registry_test_support::lock();
let doc = load(
r##"{
"version": "0.8.0",
"version": "1.0.0",
"children": [
{ "type": "frame", "id": "root", "x": 40, "y": 40,
"width": 300, "height": 200,

View file

@ -633,7 +633,7 @@ fn system_experimental_switch_toggles_preference() {
fn disabling_experimental_exits_active_preview() {
let mut host = WidgetHostNative::new();
let doc = jian_ops_schema::load_str(
r#"{"version":"0.8.0","children":[
r#"{"version":"1.0.0","children":[
{"type":"frame","id":"root","name":"Root","x":0,"y":0,"width":200,"height":200,
"children":[
{"type":"rectangle","id":"r","name":"R","x":10,"y":10,"width":50,"height":50}

View file

@ -14,7 +14,7 @@ use op_editor_core::{own_bounds, NodeId};
const VW: f32 = 1200.0;
const VH: f32 = 800.0;
const ONE_RECT: &str = r#"{"version":"0.8.0","children":[{"type":"rectangle","id":"n1","name":"n1","x":0,"y":0,"width":100,"height":50}]}"#;
const ONE_RECT: &str = r#"{"version":"1.0.0","children":[{"type":"rectangle","id":"n1","name":"n1","x":0,"y":0,"width":100,"height":50}]}"#;
/// Seed a host's `editor_state` from a canonical `.op` JSON snippet.
fn seed(host: &mut WidgetHostNative, json: &str) {

View file

@ -22,7 +22,7 @@ fn seed(host: &mut WidgetHostNative, json: &str) {
/// `card` frame (400, 60, 200×200) with a nested `leaf` rect at
/// relative (40, 40) — leaf renders at doc (440..490, 100..150) —
/// plus a far-away top-level `other` rect at (650, 60, 40×40).
const NESTED: &str = r#"{"version":"0.8.0","children":[
const NESTED: &str = r#"{"version":"1.0.0","children":[
{"type":"frame","id":"card","name":"Card","x":400,"y":60,"width":200,"height":200,
"children":[
{"type":"rectangle","id":"leaf","name":"Leaf","x":40,"y":40,"width":50,"height":50}
@ -33,7 +33,7 @@ const NESTED: &str = r#"{"version":"0.8.0","children":[
/// Four selection depths at the shared probe point: root > l1 > l2 > l3.
/// Every nested node contains doc (470, 130), while `other` remains available
/// for multi-selection and outside-scope tests.
const FOUR_LEVEL: &str = r#"{"version":"0.8.0","children":[
const FOUR_LEVEL: &str = r#"{"version":"1.0.0","children":[
{"type":"frame","id":"root","name":"Root","x":400,"y":60,"width":240,"height":240,
"children":[
{"type":"frame","id":"l1","name":"Level 1","x":20,"y":20,"width":200,"height":200,
@ -231,7 +231,7 @@ fn overlapping_rect_stack(count: usize) -> String {
})
.collect::<Vec<_>>()
.join(",");
format!(r#"{{"version":"0.8.0","children":[{children}]}}"#)
format!(r#"{{"version":"1.0.0","children":[{children}]}}"#)
}
#[test]
@ -257,7 +257,7 @@ fn promotion_inside_entered_container_stops_at_its_child() {
let mut host = WidgetHostNative::new();
seed(
&mut host,
r#"{"version":"0.8.0","children":[
r#"{"version":"1.0.0","children":[
{"type":"frame","id":"card","name":"Card","x":400,"y":60,"width":200,"height":200,
"children":[
{"type":"frame","id":"inner","name":"Inner","x":20,"y":20,"width":150,"height":150,
@ -282,7 +282,7 @@ fn promotion_inside_entered_container_stops_at_its_child() {
/// Vertical auto-layout stack at (400, 60) with three 80×40 flow
/// children (gap 8): a 60..100, b 108..148, c 156..196 in doc y.
const VSTACK: &str = r#"{"version":"0.8.0","children":[
const VSTACK: &str = r#"{"version":"1.0.0","children":[
{"type":"frame","id":"stack","name":"Stack","x":400,"y":60,"width":200,"height":300,
"layout":"vertical","gap":8,
"children":[
@ -292,7 +292,7 @@ const VSTACK: &str = r#"{"version":"0.8.0","children":[
]}
]}"#;
const HSTACK: &str = r#"{"version":"0.8.0","children":[
const HSTACK: &str = r#"{"version":"1.0.0","children":[
{"type":"frame","id":"row","name":"Row","x":400,"y":60,"width":360,"height":120,
"layout":"horizontal","gap":8,
"children":[
@ -541,7 +541,7 @@ fn child_dragged_into_other_layout_uses_cross_container_placeholder() {
let mut host = WidgetHostNative::new();
seed(
&mut host,
r#"{"version":"0.8.0","children":[
r#"{"version":"1.0.0","children":[
{"type":"frame","id":"src","name":"Source","x":400,"y":60,"width":200,"height":120,
"children":[
{"type":"rectangle","id":"box","name":"Box","x":20,"y":20,"width":50,"height":50}
@ -601,7 +601,7 @@ fn text_dragged_fully_outside_parent_reparents_to_page_root() {
let mut host = WidgetHostNative::new();
seed(
&mut host,
r#"{"version":"0.8.0","children":[
r#"{"version":"1.0.0","children":[
{"type":"frame","id":"card","name":"Card","x":400,"y":60,"width":200,"height":100,
"children":[
{"type":"text","id":"label","name":"Label","x":20,"y":20,
@ -638,7 +638,7 @@ fn shape_dragged_outside_parent_becomes_page_root() {
let mut host = WidgetHostNative::new();
seed(
&mut host,
r#"{"version":"0.8.0","children":[
r#"{"version":"1.0.0","children":[
{"type":"frame","id":"card","name":"Card","x":400,"y":60,"width":200,"height":100,
"children":[
{"type":"rectangle","id":"box","name":"Box","x":20,"y":20,"width":50,"height":50}
@ -669,7 +669,7 @@ fn shape_dragged_into_sibling_frame_reparents_to_that_frame() {
let mut host = WidgetHostNative::new();
seed(
&mut host,
r#"{"version":"0.8.0","children":[
r#"{"version":"1.0.0","children":[
{"type":"frame","id":"src","name":"Source","x":400,"y":60,"width":200,"height":120,
"children":[
{"type":"rectangle","id":"box","name":"Box","x":20,"y":20,"width":50,"height":50}
@ -710,7 +710,7 @@ fn root_shape_dragged_into_frame_becomes_that_frame_child() {
let mut host = WidgetHostNative::new();
seed(
&mut host,
r#"{"version":"0.8.0","children":[
r#"{"version":"1.0.0","children":[
{"type":"rectangle","id":"box","name":"Box","x":400,"y":80,"width":50,"height":50},
{"type":"frame","id":"target","name":"Target","x":700,"y":60,"width":220,"height":160,
"children":[]}

View file

@ -107,7 +107,7 @@ mod tests {
use crate::WidgetHostNative;
use op_editor_core::NodeId;
const TEXT_DOC: &str = r#"{"version":"0.8.0","children":[
const TEXT_DOC: &str = r#"{"version":"1.0.0","children":[
{"type":"text","id":"t1","name":"Label","x":0,"y":0,"width":100,"height":40,
"content":"hello","fontSize":20}
]}"#;

View file

@ -24,7 +24,7 @@ fn three_rects(boxes: [(f64, f64, f64, f64); 3], ids: [&str; 3]) -> String {
)
};
format!(
r#"{{"version":"0.8.0","children":[{},{},{}]}}"#,
r#"{{"version":"1.0.0","children":[{},{},{}]}}"#,
node(ids[0], boxes[0]),
node(ids[1], boxes[1]),
node(ids[2], boxes[2]),
@ -36,7 +36,7 @@ fn bottom_right_handle_resizes_only_selected_container() {
let mut host = WidgetHostNative::new();
seed(
&mut host,
r#"{"version":"0.8.0","children":[{
r#"{"version":"1.0.0","children":[{
"type":"frame","id":"frame","name":"frame","x":100,"y":80,
"width":200,"height":160,"layout":"none","children":[
{"type":"rectangle","id":"child","name":"child","x":12,"y":18,
@ -91,7 +91,7 @@ fn edge_handle_freezes_only_its_axis_and_preserves_descendants() {
let mut host = WidgetHostNative::new();
seed(
&mut host,
r#"{"version":"0.8.0","children":[{
r#"{"version":"1.0.0","children":[{
"type":"frame","id":"frame","name":"frame","x":100,"y":80,
"width":"fill_container","height":"fit_content","layout":"vertical",
"children":[
@ -138,7 +138,7 @@ fn fill_child_reflows_to_resized_parent_without_authored_mutation() {
let mut host = WidgetHostNative::new();
seed(
&mut host,
r#"{"version":"0.8.0","children":[{
r#"{"version":"1.0.0","children":[{
"type":"frame","id":"frame","name":"frame","x":100,"y":80,
"width":200,"height":160,"layout":"vertical","children":[
{"type":"rectangle","id":"child","name":"child",
@ -186,7 +186,7 @@ fn anchor_press_release_without_motion_does_not_push_history() {
let mut host = WidgetHostNative::new();
seed(
&mut host,
r#"{"version":"0.8.0","children":[
r#"{"version":"1.0.0","children":[
{"type":"path","id":"n60","name":"p","x":0,"y":0,
"anchors":[{"x":0,"y":0},{"x":50,"y":25}]}
]}"#,
@ -224,7 +224,7 @@ fn anchor_drag_back_to_start_lands_at_start() {
let mut host = WidgetHostNative::new();
seed(
&mut host,
r#"{"version":"0.8.0","children":[
r#"{"version":"1.0.0","children":[
{"type":"path","id":"n60","name":"p","x":0,"y":0,
"anchors":[{"x":0,"y":0},{"x":50,"y":25}]}
]}"#,
@ -266,7 +266,7 @@ fn anchor_drag_with_motion_pushes_one_history_entry() {
let mut host = WidgetHostNative::new();
seed(
&mut host,
r#"{"version":"0.8.0","children":[
r#"{"version":"1.0.0","children":[
{"type":"path","id":"n60","name":"p","x":0,"y":0,
"anchors":[{"x":0,"y":0},{"x":50,"y":25}]}
]}"#,
@ -349,7 +349,7 @@ fn node_drag_snap_does_not_trap_incremental_cursor_motion() {
let mut host = WidgetHostNative::new();
seed(
&mut host,
r#"{"version":"0.8.0","children":[
r#"{"version":"1.0.0","children":[
{"type":"rectangle","id":"moving","name":"moving","x":90,"y":0,"width":10,"height":10},
{"type":"rectangle","id":"guide","name":"guide","x":105,"y":100,"width":100,"height":20}
]}"#,
@ -396,7 +396,7 @@ fn node_drag_skips_smart_guides_for_large_documents() {
1000 + i * 10
));
}
let doc = format!(r#"{{"version":"0.8.0","children":[{}]}}"#, nodes.join(","));
let doc = format!(r#"{{"version":"1.0.0","children":[{}]}}"#, nodes.join(","));
let mut host = WidgetHostNative::new();
seed(&mut host, &doc);
host.editor_state_mut()
@ -428,7 +428,7 @@ fn node_drag_keeps_flex_child_in_layout_flow() {
let mut host = WidgetHostNative::new();
seed(
&mut host,
r#"{"version":"0.8.0","children":[{
r#"{"version":"1.0.0","children":[{
"type":"frame","id":"frame","name":"frame","x":100,"y":100,
"width":200,"height":200,"layout":"vertical","gap":8,
"children":[
@ -478,7 +478,7 @@ fn dragging_a_selection_with_a_locked_node_does_not_drift_it_in_the_scene() {
let mut host = WidgetHostNative::new();
seed(
&mut host,
r#"{"version":"0.8.0","children":[
r#"{"version":"1.0.0","children":[
{"type":"rectangle","id":"free","name":"free","x":100,"y":100,"width":80,"height":60},
{"type":"rectangle","id":"locked","name":"locked","x":600,"y":100,"width":80,"height":60,"locked":true}
]}"#,
@ -525,7 +525,7 @@ fn incremental_drag_then_doc_restored_to_cached_value_rebuilds_the_scene() {
let mut host = WidgetHostNative::new();
seed(
&mut host,
r#"{"version":"0.8.0","children":[
r#"{"version":"1.0.0","children":[
{"type":"rectangle","id":"free","name":"free","x":100,"y":100,"width":80,"height":60}
]}"#,
);

View file

@ -47,7 +47,7 @@ fn layer_hover_does_not_refresh_stale_canvas_layout_scene() {
let mut host = WidgetHostNative::new();
seed(
&mut host,
r#"{"version":"0.8.0","children":[{"type":"rectangle","id":"n1","name":"n1","x":0,"y":0,"width":100,"height":50}]}"#,
r#"{"version":"1.0.0","children":[{"type":"rectangle","id":"n1","name":"n1","x":0,"y":0,"width":100,"height":50}]}"#,
);
host.editor_state_mut().editor_ui.hovered_layer_id = Some(NodeId::new("n1"));
host.mark_paint_dirty_for_test();
@ -76,7 +76,7 @@ fn file_menu_cursor_move_clears_stale_layer_hover() {
let mut host = WidgetHostNative::new();
seed(
&mut host,
r#"{"version":"0.8.0","children":[{"type":"rectangle","id":"n1","name":"n1","x":0,"y":0,"width":100,"height":50}]}"#,
r#"{"version":"1.0.0","children":[{"type":"rectangle","id":"n1","name":"n1","x":0,"y":0,"width":100,"height":50}]}"#,
);
host.last_viewport_w = 1200.0;
host.last_viewport_h = 800.0;
@ -123,7 +123,7 @@ fn property_panel_blank_hover_consumes_and_clears_lower_hover() {
let mut host = WidgetHostNative::new();
seed(
&mut host,
r##"{ "version": "0.8.0", "children": [
r##"{ "version": "1.0.0", "children": [
{"type":"group","id":"shape_group","name":"Shape Group",
"children":[
{"type":"rectangle","id":"box","name":"Box","width":80,"height":40}
@ -150,7 +150,7 @@ fn opening_file_menu_clears_stale_layer_hover() {
let mut host = WidgetHostNative::new();
seed(
&mut host,
r#"{"version":"0.8.0","children":[{"type":"rectangle","id":"n1","name":"n1","x":0,"y":0,"width":100,"height":50}]}"#,
r#"{"version":"1.0.0","children":[{"type":"rectangle","id":"n1","name":"n1","x":0,"y":0,"width":100,"height":50}]}"#,
);
host.last_viewport_w = 1200.0;
host.last_viewport_h = 800.0;
@ -186,7 +186,7 @@ fn layer_row_selection_does_not_dirty_canvas_layout_scene() {
let mut host = WidgetHostNative::new();
seed(
&mut host,
r#"{"version":"0.8.0","children":[{"type":"rectangle","id":"n1","name":"n1","x":0,"y":0,"width":100,"height":50},{"type":"rectangle","id":"n2","name":"n2","x":120,"y":0,"width":100,"height":50}]}"#,
r#"{"version":"1.0.0","children":[{"type":"rectangle","id":"n1","name":"n1","x":0,"y":0,"width":100,"height":50},{"type":"rectangle","id":"n2","name":"n2","x":120,"y":0,"width":100,"height":50}]}"#,
);
let _ = host.layout_scene();
assert!(!host.editor_state_dirty);
@ -216,7 +216,7 @@ fn layer_right_press_does_not_dirty_canvas_layout_scene() {
let mut host = WidgetHostNative::new();
seed(
&mut host,
r#"{"version":"0.8.0","children":[{"type":"rectangle","id":"n1","name":"n1","x":0,"y":0,"width":100,"height":50},{"type":"rectangle","id":"n2","name":"n2","x":120,"y":0,"width":100,"height":50}]}"#,
r#"{"version":"1.0.0","children":[{"type":"rectangle","id":"n1","name":"n1","x":0,"y":0,"width":100,"height":50},{"type":"rectangle","id":"n2","name":"n2","x":120,"y":0,"width":100,"height":50}]}"#,
);
let _ = host.layout_scene();
assert!(!host.editor_state_dirty);
@ -247,7 +247,7 @@ fn layer_right_press_does_not_refresh_stale_canvas_layout_scene() {
let mut host = WidgetHostNative::new();
seed(
&mut host,
r#"{"version":"0.8.0","children":[{"type":"rectangle","id":"n1","name":"n1","x":0,"y":0,"width":100,"height":50}]}"#,
r#"{"version":"1.0.0","children":[{"type":"rectangle","id":"n1","name":"n1","x":0,"y":0,"width":100,"height":50}]}"#,
);
host.mark_paint_dirty_for_test();
@ -381,7 +381,7 @@ fn three_rects(boxes: [(f64, f64, f64, f64); 3], ids: [&str; 3]) -> String {
)
};
format!(
r#"{{"version":"0.8.0","children":[{},{},{}]}}"#,
r#"{{"version":"1.0.0","children":[{},{},{}]}}"#,
node(ids[0], boxes[0]),
node(ids[1], boxes[1]),
node(ids[2], boxes[2]),
@ -708,7 +708,7 @@ fn toolbar_panel_actions_open_variables_and_design_panels() {
let mut host = WidgetHostNative::new();
seed(
&mut host,
r#"{"version":"0.8.0","children":[{"type":"rectangle","id":"n1","name":"n1","x":0,"y":0,"width":100,"height":50}]}"#,
r#"{"version":"1.0.0","children":[{"type":"rectangle","id":"n1","name":"n1","x":0,"y":0,"width":100,"height":50}]}"#,
);
host.editor_state_mut().editor_ui.property_tab = op_editor_core::PropertyTab::Design;
host.editor_state_mut().chat.collapsed = true;
@ -763,7 +763,7 @@ fn explicit_variables_toolbar_opens_floating_variables_panel() {
let mut host = WidgetHostNative::new();
seed(
&mut host,
r##"{"version":"0.8.0","children":[{"type":"frame","id":"frame-1","name":"Frame","x":0,"y":0,"width":100,"height":50}]}"##,
r##"{"version":"1.0.0","children":[{"type":"frame","id":"frame-1","name":"Frame","x":0,"y":0,"width":100,"height":50}]}"##,
);
host.editor_state_mut().selection.anchor = NodeId::new("frame-1");
host.editor_state_mut().selection.set = vec![NodeId::new("frame-1")];
@ -1123,7 +1123,7 @@ fn image_adjustment_drag_updates_live_after_press() {
let mut host = WidgetHostNative::new();
seed(
&mut host,
r##"{ "version": "0.8.0", "children": [
r##"{ "version": "1.0.0", "children": [
{"type":"rectangle","id":"n60","name":"Photo fill",
"x":40,"y":40,"width":180,"height":120,
"fill":[{"type":"image","url":"","mode":"fill",
@ -1161,7 +1161,7 @@ fn image_fill_actions_refresh_the_render_scene() {
let mut host = WidgetHostNative::new();
seed(
&mut host,
r##"{ "version": "0.8.0", "children": [
r##"{ "version": "1.0.0", "children": [
{"type":"rectangle","id":"n61","name":"Photo fill",
"x":40,"y":40,"width":180,"height":120,
"fill":[{"type":"image","url":"data:image/png;base64,AA==","mode":"fill",
@ -1212,7 +1212,7 @@ fn corner_radius_property_focus_updates_selected_rectangle() {
let mut host = WidgetHostNative::new();
seed(
&mut host,
r##"{ "version": "0.8.0", "children": [
r##"{ "version": "1.0.0", "children": [
{"type":"rectangle","id":"n62","name":"Rounded",
"x":40,"y":40,"width":180,"height":120,
"fill":[{"type":"solid","color":"#BDC7D9"}]}
@ -1251,7 +1251,7 @@ fn property_focus_commit_reads_text_input_state() {
let mut host = WidgetHostNative::new();
seed(
&mut host,
r##"{ "version": "0.8.0", "children": [
r##"{ "version": "1.0.0", "children": [
{"type":"rectangle","id":"n62","name":"Wide",
"x":40,"y":40,"width":180,"height":120,
"fill":[{"type":"solid","color":"#BDC7D9"}]}
@ -1274,7 +1274,7 @@ fn widget_leading_icon_focus_commits_onto_text_input() {
let mut host = WidgetHostNative::new();
seed(
&mut host,
r##"{ "version": "0.8.0", "children": [
r##"{ "version": "1.0.0", "children": [
{"type":"text_input","id":"email","name":"Email",
"x":24,"y":32,"width":220,"height":40,"placeholder":"Email"}
]}"##,
@ -1302,7 +1302,7 @@ fn widget_bind_key_focus_writes_state_binding() {
let mut host = WidgetHostNative::new();
seed(
&mut host,
r##"{ "version": "0.8.0", "children": [
r##"{ "version": "1.0.0", "children": [
{"type":"text_input","id":"email","name":"Email",
"x":24,"y":32,"width":220,"height":40,"placeholder":"Email"}
]}"##,
@ -1330,7 +1330,7 @@ fn property_focus_commit_is_undoable() {
let mut host = WidgetHostNative::new();
seed(
&mut host,
r##"{ "version": "0.8.0", "children": [
r##"{ "version": "1.0.0", "children": [
{"type":"rectangle","id":"n62","name":"Wide",
"x":40,"y":40,"width":180,"height":120,
"fill":[{"type":"solid","color":"#BDC7D9"}]}
@ -1357,7 +1357,7 @@ fn property_press_seeds_text_input_state() {
let mut host = WidgetHostNative::new();
seed(
&mut host,
r##"{ "version": "0.8.0", "children": [
r##"{ "version": "1.0.0", "children": [
{"type":"rectangle","id":"n62","name":"Wide",
"x":40,"y":40,"width":180,"height":120,
"fill":[{"type":"solid","color":"#BDC7D9"}]}
@ -1464,7 +1464,7 @@ fn property_step_reads_and_updates_text_input_state() {
let mut host = WidgetHostNative::new();
seed(
&mut host,
r##"{ "version": "0.8.0", "children": [
r##"{ "version": "1.0.0", "children": [
{"type":"rectangle","id":"n62","name":"Wide",
"x":40,"y":40,"width":180,"height":120,
"fill":[{"type":"solid","color":"#BDC7D9"}]}
@ -1506,7 +1506,7 @@ fn polygon_sides_property_focus_updates_selected_polygon() {
let mut host = WidgetHostNative::new();
seed(
&mut host,
r##"{ "version": "0.8.0", "children": [
r##"{ "version": "1.0.0", "children": [
{"type":"polygon","id":"poly","name":"Polygon",
"x":40,"y":40,"width":120,"height":120,
"polygonCount":3}
@ -1540,7 +1540,7 @@ fn ellipse_arc_property_focus_updates_selected_ellipse() {
let mut host = WidgetHostNative::new();
seed(
&mut host,
r##"{ "version": "0.8.0", "children": [
r##"{ "version": "1.0.0", "children": [
{"type":"ellipse","id":"ell","name":"Ellipse",
"x":40,"y":40,"width":120,"height":100}
]}"##,
@ -1883,7 +1883,7 @@ fn layer_context_create_component_click_promotes_frame() {
let mut host = WidgetHostNative::new();
seed(
&mut host,
r#"{"version":"0.8.0","children":[
r#"{"version":"1.0.0","children":[
{"type":"frame","id":"n10","name":"Card","x":0,"y":0,"width":100,"height":80,
"children":[]}
]}"#,
@ -1914,7 +1914,7 @@ fn property_panel_create_component_click_promotes_selected_frame() {
let mut host = WidgetHostNative::new();
seed(
&mut host,
r#"{"version":"0.8.0","children":[
r#"{"version":"1.0.0","children":[
{"type":"frame","id":"n20","name":"Hero","x":0,"y":0,"width":120,"height":90,
"children":[]}
]}"#,
@ -2349,7 +2349,7 @@ fn codegen_hover_tracks_idle_generate_button() {
let mut host = WidgetHostNative::new();
seed(
&mut host,
r#"{"version":"0.8.0","children":[{"type":"rectangle","id":"n-code","name":"n-code","x":0,"y":0,"width":100,"height":50}]}"#,
r#"{"version":"1.0.0","children":[{"type":"rectangle","id":"n-code","name":"n-code","x":0,"y":0,"width":100,"height":50}]}"#,
);
host.last_viewport_w = 1200.0;
host.last_viewport_h = 800.0;
@ -2391,7 +2391,7 @@ fn codegen_preview_drag_selects_code_text() {
let mut host = WidgetHostNative::new();
seed(
&mut host,
r#"{"version":"0.8.0","children":[{"type":"rectangle","id":"n-code","name":"n-code","x":0,"y":0,"width":100,"height":50}]}"#,
r#"{"version":"1.0.0","children":[{"type":"rectangle","id":"n-code","name":"n-code","x":0,"y":0,"width":100,"height":50}]}"#,
);
let viewport_w = 1200.0;
let viewport_h = 800.0;
@ -2426,7 +2426,7 @@ fn codegen_preview_wheel_scrolls_code_not_property_panel() {
let mut host = WidgetHostNative::new();
seed(
&mut host,
r#"{"version":"0.8.0","children":[{"type":"rectangle","id":"n-code","name":"n-code","x":0,"y":0,"width":100,"height":50}]}"#,
r#"{"version":"1.0.0","children":[{"type":"rectangle","id":"n-code","name":"n-code","x":0,"y":0,"width":100,"height":50}]}"#,
);
let viewport_w = 1200.0;
let viewport_h = 800.0;
@ -2462,7 +2462,7 @@ fn property_tab_hover_tracks_inactive_design_tab() {
let mut host = WidgetHostNative::new();
seed(
&mut host,
r#"{"version":"0.8.0","children":[{"type":"rectangle","id":"n-tabs","name":"n-tabs","x":0,"y":0,"width":100,"height":50}]}"#,
r#"{"version":"1.0.0","children":[{"type":"rectangle","id":"n-tabs","name":"n-tabs","x":0,"y":0,"width":100,"height":50}]}"#,
);
host.last_viewport_w = 1200.0;
host.last_viewport_h = 800.0;

View file

@ -11,7 +11,7 @@ use op_editor_core::NodeId;
fn native_move_fill_action_dispatches_as_one_undoable_edit() {
let mut host = WidgetHostNative::new();
let doc = jian_ops_schema::load_str(
r##"{"version":"0.8.0","children":[{
r##"{"version":"1.0.0","children":[{
"type":"rectangle","id":"rect","name":"Rect",
"x":0,"y":0,"width":10,"height":10,
"fill":[
@ -53,7 +53,7 @@ fn native_move_fill_action_dispatches_as_one_undoable_edit() {
fn native_instance_move_fill_undo_restores_the_original_ref() {
let mut host = WidgetHostNative::new();
let doc = jian_ops_schema::load_str(
r##"{"version":"0.8.0","children":[
r##"{"version":"1.0.0","children":[
{"type":"rectangle","id":"master","name":"Master","reusable":true,
"x":0,"y":0,"width":10,"height":10,
"fill":[
@ -135,7 +135,7 @@ fn native_compound_instance_alignment_undo_redo_preserves_each_history_state() {
let mut host = WidgetHostNative::new();
let doc = jian_ops_schema::load_str(
r##"{"version":"0.8.0","children":[
r##"{"version":"1.0.0","children":[
{"type":"frame","id":"master","name":"Master","reusable":true,
"x":0,"y":0,"width":100,"height":100,"layout":"vertical",
"justifyContent":"start","alignItems":"start","children":[]},

View file

@ -13,7 +13,7 @@ use op_editor_core::{NodeId, PenNodeExt};
mod fill_history_tests;
const COMPONENT_DOC: &str = r##"{
"version":"0.8.0",
"version":"1.0.0",
"children":[
{"type":"frame","id":"card","name":"Card","reusable":true,"x":0,"y":0,"width":200,"height":100,
"fill":[{"type":"solid","color":"#222222"}],
@ -344,7 +344,7 @@ fn remote_icon_insert_bakes_svg_d_as_path_node() {
}
const STROKE_RECT_DOC: &str = r##"{
"version":"0.8.0",
"version":"1.0.0",
"children":[
{"type":"rectangle","id":"r1","name":"Box","x":0,"y":0,"width":100,"height":50}
]
@ -518,7 +518,7 @@ fn scene_fill(host: &mut WidgetHostNative, id: &str) -> Option<op_editor_ui::Col
fn remove_fill_clears_scene_fill_on_plain_frame() {
let mut host = WidgetHostNative::new();
let doc = jian_ops_schema::load_str(
r##"{"version":"0.8.0","children":[
r##"{"version":"1.0.0","children":[
{"type":"frame","id":"f1","name":"Box","x":0,"y":0,"width":100,"height":50,
"fill":[{"type":"solid","color":"#ff0000"}]}
]}"##,
@ -556,7 +556,7 @@ fn remove_fill_clears_scene_fill_on_plain_frame() {
fn remove_fill_clears_scene_fill_on_nested_child() {
let mut host = WidgetHostNative::new();
let doc = jian_ops_schema::load_str(
r##"{"version":"0.8.0","children":[
r##"{"version":"1.0.0","children":[
{"type":"frame","id":"screen","name":"Screen","x":0,"y":0,"width":200,"height":200,
"children":[
{"type":"rectangle","id":"bar","name":"Bar","x":10,"y":10,"width":120,"height":40,
@ -587,7 +587,7 @@ fn remove_fill_clears_scene_fill_on_nested_child() {
fn remove_all_multi_fills_clears_scene_fill() {
let mut host = WidgetHostNative::new();
let doc = jian_ops_schema::load_str(
r##"{"version":"0.8.0","children":[
r##"{"version":"1.0.0","children":[
{"type":"frame","id":"f1","name":"Box","x":0,"y":0,"width":100,"height":50,
"fill":[{"type":"solid","color":"#ff0000"},{"type":"solid","color":"#00ff00"}]}
]}"##,
@ -618,7 +618,7 @@ fn remove_variable_bound_fill_clears_scene_color() {
use jian_ops_schema::variable::{VariableKind, VariableScalar};
let mut host = WidgetHostNative::new();
let doc = jian_ops_schema::load_str(
r##"{"version":"0.8.0","children":[
r##"{"version":"1.0.0","children":[
{"type":"rectangle","id":"r1","name":"Box","x":0,"y":0,"width":50,"height":50,
"fill":[{"type":"solid","color":"$brand"}]}
]}"##,

View file

@ -29,7 +29,7 @@ fn two_rects_host() -> WidgetHostNative {
let mut host = WidgetHostNative::new();
seed(
&mut host,
r#"{"version":"0.8.0","children":[
r#"{"version":"1.0.0","children":[
{"type":"rectangle","id":"a","name":"a","x":0,"y":0,"width":40,"height":40},
{"type":"rectangle","id":"b","name":"b","x":60,"y":0,"width":40,"height":40}
]}"#,
@ -42,7 +42,7 @@ fn three_pages_host() -> WidgetHostNative {
let mut host = WidgetHostNative::new();
seed(
&mut host,
r#"{"version":"0.8.0","children":[],"pages":[
r#"{"version":"1.0.0","children":[],"pages":[
{"id":"p1","name":"One","children":[
{"type":"rectangle","id":"r1","name":"r1","x":0,"y":0,"width":10,"height":10}]},
{"id":"p2","name":"Two","children":[
@ -262,7 +262,7 @@ fn delete_last_page_guard_pushes_no_history() {
let mut host = WidgetHostNative::new();
seed(
&mut host,
r#"{"version":"0.8.0","children":[],"pages":[
r#"{"version":"1.0.0","children":[],"pages":[
{"id":"p1","name":"Only","children":[]}
]}"#,
);
@ -382,7 +382,7 @@ fn context_menu_boolean_union_is_undoable() {
let mut host = WidgetHostNative::new();
seed(
&mut host,
r#"{"version":"0.8.0","children":[
r#"{"version":"1.0.0","children":[
{"type":"rectangle","id":"a","name":"a","x":0,"y":0,"width":40,"height":40},
{"type":"rectangle","id":"b","name":"b","x":20,"y":0,"width":40,"height":40}
]}"#,
@ -419,7 +419,7 @@ fn context_menu_create_and_detach_component_are_undoable() {
let mut host = WidgetHostNative::new();
seed(
&mut host,
r#"{"version":"0.8.0","children":[
r#"{"version":"1.0.0","children":[
{"type":"frame","id":"f1","name":"Card","x":0,"y":0,
"width":100,"height":80,"children":[]}
]}"#,

View file

@ -20,7 +20,7 @@ fn seed(host: &mut WidgetHostNative, json: &str) {
fn empty_host() -> WidgetHostNative {
let mut host = WidgetHostNative::new();
seed(&mut host, r#"{"version":"0.8.0","children":[]}"#);
seed(&mut host, r#"{"version":"1.0.0","children":[]}"#);
host
}
@ -29,7 +29,7 @@ fn path_host() -> WidgetHostNative {
let mut host = WidgetHostNative::new();
seed(
&mut host,
r#"{"version":"0.8.0","children":[
r#"{"version":"1.0.0","children":[
{"type":"path","id":"n60","name":"p","x":300,"y":300,
"anchors":[{"x":300,"y":300},{"x":380,"y":300},{"x":380,"y":360}]}
]}"#,
@ -370,7 +370,7 @@ fn handle_drag_preserves_grab_offset_and_anchor_type() {
let mut host = WidgetHostNative::new();
seed(
&mut host,
r#"{"version":"0.8.0","children":[
r#"{"version":"1.0.0","children":[
{"type":"path","id":"n60","name":"p","x":300,"y":300,
"anchors":[{"x":300,"y":300},
{"x":380,"y":300,"handleOut":{"x":20,"y":0}},

View file

@ -21,7 +21,7 @@ fn load(src: &str) -> jian_ops_schema::PenDocument {
fn phone_doc(height: u32) -> jian_ops_schema::PenDocument {
load(&format!(
r##"{{
"version": "0.8.0",
"version": "1.0.0",
"children": [{{
"type": "frame", "id": "screen", "x": 0, "y": 0,
"width": 390, "height": {height},
@ -35,7 +35,7 @@ fn phone_doc(height: u32) -> jian_ops_schema::PenDocument {
fn narrow_semantic_nav_doc() -> jian_ops_schema::PenDocument {
load(
r##"{
"version": "0.8.0",
"version": "1.0.0",
"children": [{
"type": "frame", "id": "screen", "x": 0, "y": 0,
"width": 390, "height": 2000,

View file

@ -95,7 +95,7 @@ fn property_panel_action_press_sets_and_release_clears_pressed_button() {
let mut host = WidgetHostNative::new();
seed(
&mut host,
r##"{ "version": "0.8.0", "children": [
r##"{ "version": "1.0.0", "children": [
{"type":"rectangle","id":"n62","name":"Wide",
"x":40,"y":40,"width":180,"height":120,
"fill":[{"type":"solid","color":"#BDC7D9"}]}
@ -128,7 +128,7 @@ fn fill_width_input_seeds_from_resolved_canvas_width() {
let mut host = WidgetHostNative::new();
seed(
&mut host,
r##"{ "version": "0.8.0", "children": [
r##"{ "version": "1.0.0", "children": [
{"type":"frame","id":"root","width":390,"height":710,
"layout":"vertical","children":[
{"type":"frame","id":"fill","width":"fill_container",
@ -152,7 +152,7 @@ fn disabling_fill_height_freezes_resolved_height_then_numeric_input_resizes_scen
let mut host = WidgetHostNative::new();
seed(
&mut host,
r##"{ "version": "0.8.0", "children": [
r##"{ "version": "1.0.0", "children": [
{"type":"frame","id":"screen","width":390,"height":710,
"layout":"vertical","gap":0,"children":[
{"type":"frame","id":"content","name":"Content Wrapper",
@ -201,7 +201,7 @@ fn property_panel_background_consumes_clicks() {
let mut host = WidgetHostNative::new();
seed(
&mut host,
r##"{ "version": "0.8.0", "children": [
r##"{ "version": "1.0.0", "children": [
{"type":"group","id":"shape_group","name":"Shape Group",
"children":[
{"type":"rectangle","id":"box","name":"Box","width":80,"height":40}
@ -227,7 +227,7 @@ fn native_property_panel_group_component_button_switches_to_detach() {
let mut host = WidgetHostNative::new();
seed(
&mut host,
r##"{ "version": "0.8.0", "children": [
r##"{ "version": "1.0.0", "children": [
{"type":"frame","id":"screen","name":"Screen",
"x":40,"y":40,"width":360,"height":640,
"children":[

View file

@ -1,7 +1,7 @@
use super::WidgetHostNative;
fn nested_frame_doc(depth: usize) -> String {
let mut src = String::from(r#"{"version":"0.8.0","children":["#);
let mut src = String::from(r#"{"version":"1.0.0","children":["#);
for i in 0..depth {
src.push_str(&format!(
r##"{{"type":"frame","id":"nest-{i:05}","name":"Nested Layer {i:05}","x":8,"y":6,"width":400,"height":220,"fill":[{{"type":"solid","color":"#ffffff20"}}],"stroke":{{"thickness":1,"fill":[{{"type":"solid","color":"#0088ff"}}]}},"children":["##

View file

@ -12,9 +12,9 @@ fn seed(host: &mut WidgetHostNative, json: &str) {
host.mark_paint_dirty_for_test();
}
const ONE_RECT: &str = r#"{"version":"0.8.0","children":[{"type":"rectangle","id":"n1","name":"n1","x":400,"y":300,"width":100,"height":50}]}"#;
const ONE_RECT: &str = r#"{"version":"1.0.0","children":[{"type":"rectangle","id":"n1","name":"n1","x":400,"y":300,"width":100,"height":50}]}"#;
const ONE_FRAME: &str = r#"{"version":"0.8.0","children":[{"type":"frame","id":"f1","name":"Card","x":0,"y":0,"width":100,"height":50}]}"#;
const ONE_FRAME: &str = r#"{"version":"1.0.0","children":[{"type":"frame","id":"f1","name":"Card","x":0,"y":0,"width":100,"height":50}]}"#;
#[test]
fn panel_toggle_shortcuts_flip_their_flags() {
@ -78,7 +78,7 @@ fn paste_figma_nodes_centres_fresh_ids_and_selects() {
let mut host = WidgetHostNative::new();
seed(&mut host, ONE_FRAME);
let incoming = jian_ops_schema::load_str(
r#"{"version":"0.8.0","children":[
r#"{"version":"1.0.0","children":[
{"type":"rectangle","id":"r1","name":"A","x":0,"y":0,"width":100,"height":100},
{"type":"rectangle","id":"r2","name":"B","x":100,"y":0,"width":100,"height":100}
]}"#,

View file

@ -17,7 +17,7 @@ const VIEWPORT_W: f32 = 1440.0;
const VIEWPORT_H: f32 = 900.0;
/// `t1` text node (400, 60, 200×60) with two authored lines.
const TWO_LINES: &str = r#"{"version":"0.8.0","children":[
const TWO_LINES: &str = r#"{"version":"1.0.0","children":[
{"type":"text","id":"t1","name":"Label","x":400,"y":60,"width":200,"height":60,
"content":"hello\nworld","fontSize":20,"lineHeight":1}
]}"#;

View file

@ -470,7 +470,7 @@ mod tests {
fn active_page_bbox_resolves_fit_content_root_height() {
let doc = jian_ops_schema::load_str(
r#"{
"version":"0.8.0",
"version":"1.0.0",
"children":[{
"type":"frame", "id":"root", "name":"Explore",
"x":12, "y":24, "width":390, "height":"fit_content",
@ -511,7 +511,7 @@ mod tests {
fn canonical_document_is_not_mistaken_for_legacy() {
// A canonical `.op` file has a *string* `version` — it must not
// trip the legacy detector.
let canonical = r#"{"version":"0.8.0","children":[]}"#;
let canonical = r#"{"version":"1.0.0","children":[]}"#;
assert!(!looks_like_legacy_doc_payload(canonical));
}

View file

@ -57,7 +57,7 @@ mod tests {
/// `test_support` is `#[cfg(test)]`-private to its crate).
fn two_rect_state() -> EditorState {
let doc = jian_ops_schema::load_str(
r#"{"version":"0.8.0","children":[
r#"{"version":"1.0.0","children":[
{"type":"rectangle","id":"n1","name":"A","x":0,"y":0,"width":10,"height":10},
{"type":"rectangle","id":"n2","name":"B","x":20,"y":0,"width":10,"height":10}
]}"#,

View file

@ -634,7 +634,7 @@ mod tests {
fn two_rect_state() -> EditorState {
let doc = jian_ops_schema::load_str(
r#"{"version":"0.8.0","children":[
r#"{"version":"1.0.0","children":[
{"type":"rectangle","id":"n1","name":"A","x":0,"y":0,"width":10,"height":10},
{"type":"rectangle","id":"n2","name":"B","x":20,"y":0,"width":10,"height":10}
]}"#,

View file

@ -412,7 +412,7 @@ mod tests {
#[test]
fn export_kit_document_builds_download_name_and_json() {
let src = r#"{"version":"0.8.0","name":"My Kit!","children":[{"type":"frame","id":"button","name":"Primary Button","reusable":true,"x":0,"y":0,"width":120,"height":40,"children":[]}]}"#;
let src = r#"{"version":"1.0.0","name":"My Kit!","children":[{"type":"frame","id":"button","name":"Primary Button","reusable":true,"x":0,"y":0,"width":120,"height":40,"children":[]}]}"#;
let doc = op_pen_loader::load_canonical(src)
.expect("canonical doc")
.value;
@ -432,7 +432,7 @@ mod tests {
#[test]
fn save_request_body_embeds_document_and_active_page_index() {
let src = r#"{"version":"0.8.0","children":[],"pages":[{"id":"p1","name":"One","children":[]},{"id":"p2","name":"Two","children":[{"type":"rectangle","id":"save-node","name":"Save Node","x":0,"y":0,"width":80,"height":40}]}]}"#;
let src = r#"{"version":"1.0.0","children":[],"pages":[{"id":"p1","name":"One","children":[]},{"id":"p2","name":"Two","children":[{"type":"rectangle","id":"save-node","name":"Save Node","x":0,"y":0,"width":80,"height":40}]}]}"#;
let doc = op_pen_loader::load_canonical(src)
.expect("canonical doc")
.value;
@ -467,7 +467,7 @@ mod tests {
#[test]
fn export_pdf_request_body_embeds_current_document() {
let src = r#"{"version":"0.8.0","children":[],"pages":[{"id":"p1","name":"One","children":[]},{"id":"p2","name":"Two","children":[{"type":"rectangle","id":"pdf-node","name":"PDF Node","x":0,"y":0,"width":80,"height":40}]}]}"#;
let src = r#"{"version":"1.0.0","children":[],"pages":[{"id":"p1","name":"One","children":[]},{"id":"p2","name":"Two","children":[{"type":"rectangle","id":"pdf-node","name":"PDF Node","x":0,"y":0,"width":80,"height":40}]}]}"#;
let doc = op_pen_loader::load_canonical(src)
.expect("canonical doc")
.value;
@ -515,7 +515,7 @@ mod tests {
#[test]
fn export_raster_request_body_embeds_format_scale_document_and_single_selection() {
let src = r#"{"version":"0.8.0","children":[{"type":"rectangle","id":"raster-node","name":"Raster Node","x":0,"y":0,"width":80,"height":40}]}"#;
let src = r#"{"version":"1.0.0","children":[{"type":"rectangle","id":"raster-node","name":"Raster Node","x":0,"y":0,"width":80,"height":40}]}"#;
let doc = op_pen_loader::load_canonical(src)
.expect("canonical doc")
.value;
@ -561,7 +561,7 @@ mod tests {
#[test]
fn import_kit_source_extracts_components_with_supplied_id() {
let src = r#"{"version":"0.8.0","name":"Imported System","children":[{"type":"frame","id":"card","name":"Profile Card","reusable":true,"x":0,"y":0,"width":240,"height":120,"children":[]}]}"#;
let src = r#"{"version":"1.0.0","name":"Imported System","children":[{"type":"frame","id":"card","name":"Profile Card","reusable":true,"x":0,"y":0,"width":240,"height":120,"children":[]}]}"#;
let kit = import_kit_source(src, "web-kit-1".to_string())
.expect("import parses")

View file

@ -7,7 +7,7 @@ use op_editor_ui::Point2D;
const VIEWPORT_W: f32 = 1200.0;
const VIEWPORT_H: f32 = 800.0;
const FOUR_LEVELS: &str = r#"{"version":"0.8.0","children":[
const FOUR_LEVELS: &str = r#"{"version":"1.0.0","children":[
{"type":"frame","id":"root","name":"Root Frame","x":500,"y":100,"width":300,"height":300,
"children":[
{"type":"frame","id":"level-1","name":"Level 1","x":20,"y":20,"width":240,"height":240,

View file

@ -7,7 +7,7 @@ use op_editor_ui::{KeyCode, KeyEvent, KeyLocation, KeyState, KeyValue, Modifiers
fn seed_text_edit(host: &mut WidgetHost, content: &str) {
let doc = jian_ops_schema::load_str(&format!(
r##"{{"version":"0.8.0","children":[
r##"{{"version":"1.0.0","children":[
{{"type":"text","id":"t1","name":"Title","x":0,"y":0,"width":100,"height":24,
"content":{content:?},"font_size":16,"fills":[{{"type":"solid","color":"#111827"}}]}}
]}}"##

View file

@ -11,7 +11,7 @@ const VIEWPORT_H: f32 = 800.0;
fn seed(host: &mut WidgetHost) {
let doc = jian_ops_schema::load_str(
r#"{"version":"0.8.0","children":[
r#"{"version":"1.0.0","children":[
{"type":"rectangle","id":"n1","name":"Header","x":0,"y":0,"width":100,"height":50},
{"type":"rectangle","id":"n2","name":"Card","x":120,"y":0,"width":100,"height":50}
]}"#,
@ -24,7 +24,7 @@ fn seed(host: &mut WidgetHost) {
fn seed_overlapping_rects(host: &mut WidgetHost) {
let doc = jian_ops_schema::load_str(
r#"{"version":"0.8.0","children":[
r#"{"version":"1.0.0","children":[
{"type":"rectangle","id":"n1","name":"Header","x":0,"y":0,"width":100,"height":50},
{"type":"rectangle","id":"n2","name":"Card","x":40,"y":0,"width":100,"height":50}
]}"#,
@ -37,7 +37,7 @@ fn seed_overlapping_rects(host: &mut WidgetHost) {
fn seed_pages(host: &mut WidgetHost) {
let doc = jian_ops_schema::load_str(
r#"{"version":"0.8.0","children":[],"pages":[
r#"{"version":"1.0.0","children":[],"pages":[
{"id":"p1","name":"One","children":[
{"type":"rectangle","id":"r1","name":"r1","x":0,"y":0,"width":10,"height":10}]},
{"id":"p2","name":"Two","children":[
@ -54,7 +54,7 @@ fn seed_pages(host: &mut WidgetHost) {
fn seed_frame(host: &mut WidgetHost) {
let doc = jian_ops_schema::load_str(
r#"{"version":"0.8.0","children":[
r#"{"version":"1.0.0","children":[
{"type":"frame","id":"f1","name":"Card","x":0,"y":0,
"width":100,"height":80,"children":[]}
]}"#,

View file

@ -9,7 +9,7 @@ const VIEWPORT_H: f32 = 800.0;
fn seed(host: &mut WidgetHost) {
let doc = jian_ops_schema::load_str(
r#"{"version":"0.8.0","children":[
r#"{"version":"1.0.0","children":[
{"type":"rectangle","id":"n1","name":"Header","x":0,"y":0,"width":100,"height":50},
{"type":"rectangle","id":"n2","name":"Card","x":120,"y":0,"width":100,"height":50}
]}"#,

View file

@ -9,7 +9,7 @@ const VH: f32 = 800.0;
fn seed(host: &mut WidgetHost) {
seed_json(
host,
r##"{"version":"0.8.0","children":[
r##"{"version":"1.0.0","children":[
{"type":"rectangle","id":"box","name":"Box","x":100,"y":100,"width":120,"height":80,
"fill":[{"type":"solid","color":"#2563EB"}]}
]}"##,
@ -110,7 +110,7 @@ fn option_dragging_vertical_layout_child_up_copies_before_source() {
let mut host = WidgetHost::new();
seed_json(
&mut host,
r#"{"version":"0.8.0","children":[{
r#"{"version":"1.0.0","children":[{
"type":"frame","id":"stack","name":"Stack","x":400,"y":60,"width":200,"height":300,
"layout":"vertical","gap":8,
"children":[
@ -144,7 +144,7 @@ fn option_dragging_horizontal_layout_child_left_copies_before_source() {
let mut host = WidgetHost::new();
seed_json(
&mut host,
r#"{"version":"0.8.0","children":[{
r#"{"version":"1.0.0","children":[{
"type":"frame","id":"row","name":"Row","x":400,"y":60,"width":360,"height":120,
"layout":"horizontal","gap":8,
"children":[
@ -178,7 +178,7 @@ fn arrow_nudge_reorders_selected_child_on_layout_axis() {
let mut host = WidgetHost::new();
seed_json(
&mut host,
r#"{"version":"0.8.0","children":[{
r#"{"version":"1.0.0","children":[{
"type":"frame","id":"stack","name":"Stack","x":400,"y":60,"width":200,"height":300,
"layout":"vertical","gap":8,
"children":[
@ -200,7 +200,7 @@ fn arrow_nudge_reorders_selected_child_on_layout_axis() {
fn select_tool_dragging_flex_child_reorders_during_preview_like_native() {
let mut host = WidgetHost::new();
let doc = jian_ops_schema::load_str(
r#"{"version":"0.8.0","children":[{
r#"{"version":"1.0.0","children":[{
"type":"frame","id":"stack","name":"Stack","x":400,"y":60,"width":200,"height":300,
"layout":"vertical","gap":8,
"children":[
@ -271,7 +271,7 @@ fn select_tool_dragging_flex_child_to_blank_canvas_previews_as_page_root() {
let mut host = WidgetHost::new();
seed_json(
&mut host,
r#"{"version":"0.8.0","children":[{
r#"{"version":"1.0.0","children":[{
"type":"frame","id":"stack","name":"Stack","x":400,"y":60,"width":200,"height":300,
"layout":"vertical","gap":8,
"children":[
@ -319,7 +319,7 @@ fn select_tool_dragging_fill_sized_child_to_blank_canvas_freezes_resolved_size()
let mut host = WidgetHost::new();
seed_json(
&mut host,
r#"{"version":"0.8.0","children":[{
r#"{"version":"1.0.0","children":[{
"type":"frame","id":"screen","name":"Screen","x":400,"y":60,"width":360,"height":220,
"layout":"vertical","gap":8,
"children":[
@ -367,7 +367,7 @@ fn select_tool_dragging_child_into_sibling_frame_reparents_like_native() {
let mut host = WidgetHost::new();
seed_json(
&mut host,
r#"{"version":"0.8.0","children":[
r#"{"version":"1.0.0","children":[
{"type":"frame","id":"src","name":"Source","x":400,"y":60,"width":200,"height":120,
"children":[
{"type":"rectangle","id":"box","name":"Box","x":20,"y":20,"width":50,"height":50}
@ -399,7 +399,7 @@ fn select_tool_dragging_child_into_other_layout_uses_cross_container_placeholder
let mut host = WidgetHost::new();
seed_json(
&mut host,
r#"{"version":"0.8.0","children":[
r#"{"version":"1.0.0","children":[
{"type":"frame","id":"src","name":"Source","x":400,"y":60,"width":200,"height":120,
"children":[
{"type":"rectangle","id":"box","name":"Box","x":20,"y":20,"width":50,"height":50}
@ -447,7 +447,7 @@ fn select_tool_dragging_child_to_blank_canvas_makes_it_page_root_like_native() {
let mut host = WidgetHost::new();
seed_json(
&mut host,
r#"{"version":"0.8.0","children":[
r#"{"version":"1.0.0","children":[
{"type":"frame","id":"card","name":"Card","x":400,"y":60,"width":200,"height":100,
"children":[
{"type":"rectangle","id":"box","name":"Box","x":20,"y":20,"width":50,"height":50}
@ -475,7 +475,7 @@ fn select_tool_dragging_child_to_blank_canvas_makes_it_page_root_like_native() {
fn dragging_a_selection_with_a_locked_node_does_not_drift_it_in_the_scene() {
let mut host = WidgetHost::new();
let doc = jian_ops_schema::load_str(
r##"{"version":"0.8.0","children":[
r##"{"version":"1.0.0","children":[
{"type":"rectangle","id":"free","name":"Free","x":100,"y":100,"width":80,"height":60},
{"type":"rectangle","id":"locked","name":"Locked","x":300,"y":100,"width":80,"height":60,"locked":true}
]}"##,

View file

@ -68,7 +68,7 @@ fn painted_inside(backend: &CaptureBackend, target: Rect) -> bool {
fn seed_layer_doc(host: &mut WidgetHost) {
let doc = jian_ops_schema::load_str(
r#"{"version":"0.8.0","children":[
r#"{"version":"1.0.0","children":[
{"type":"rectangle","id":"n1","name":"Header","x":0,"y":0,"width":100,"height":50}
]}"#,
)

View file

@ -56,7 +56,7 @@ fn horizontal_trackpad_pan_moves_canvas_viewport() {
}
fn nested_frame_doc(depth: usize) -> String {
let mut src = String::from(r#"{"version":"0.8.0","children":["#);
let mut src = String::from(r#"{"version":"1.0.0","children":["#);
for i in 0..depth {
src.push_str(&format!(
r##"{{"type":"frame","id":"nest-{i:05}","name":"Nested Layer {i:05}","x":8,"y":6,"width":400,"height":220,"fill":[{{"type":"solid","color":"#ffffff20"}}],"stroke":{{"thickness":1,"fill":[{{"type":"solid","color":"#0088ff"}}]}},"children":["##

View file

@ -19,7 +19,7 @@ fn path_host() -> WidgetHost {
let mut host = WidgetHost::new();
seed(
&mut host,
r#"{"version":"0.8.0","children":[
r#"{"version":"1.0.0","children":[
{"type":"path","id":"n60","name":"p","x":300,"y":300,
"anchors":[{"x":300,"y":300},{"x":380,"y":300},{"x":380,"y":360}]}
]}"#,
@ -59,7 +59,7 @@ fn handle_drag_preserves_grab_offset_and_anchor_type_like_native() {
let mut host = WidgetHost::new();
seed(
&mut host,
r#"{"version":"0.8.0","children":[
r#"{"version":"1.0.0","children":[
{"type":"path","id":"n60","name":"p","x":300,"y":300,
"anchors":[{"x":300,"y":300},
{"x":380,"y":300,"handleOut":{"x":20,"y":0}},

View file

@ -24,7 +24,7 @@ fn web_move_fill_action_dispatches_as_one_undoable_edit() {
let mut host = WidgetHost::new();
seed(
&mut host,
r##"{"version":"0.8.0","children":[{
r##"{"version":"1.0.0","children":[{
"type":"rectangle","id":"rect","name":"Rect",
"x":0,"y":0,"width":10,"height":10,
"fill":[
@ -147,7 +147,7 @@ fn web_property_action_press_commits_prior_property_input() {
let mut host = WidgetHost::new();
seed(
&mut host,
r##"{ "version": "0.8.0", "children": [
r##"{ "version": "1.0.0", "children": [
{"type":"rectangle","id":"n62","name":"Wide",
"x":40,"y":40,"width":180,"height":120,
"fill":[{"type":"solid","color":"#BDC7D9"}]}
@ -177,7 +177,7 @@ fn web_toolbar_press_commits_property_input_before_tool_switch() {
let mut host = WidgetHost::new();
seed(
&mut host,
r##"{ "version": "0.8.0", "children": [
r##"{ "version": "1.0.0", "children": [
{"type":"rectangle","id":"n62","name":"Wide",
"x":40,"y":40,"width":180,"height":120,
"fill":[{"type":"solid","color":"#BDC7D9"}]}
@ -223,7 +223,7 @@ fn web_property_press_reseeds_from_committed_snapshot() {
let mut host = WidgetHost::new();
seed(
&mut host,
r##"{ "version": "0.8.0", "children": [
r##"{ "version": "1.0.0", "children": [
{"type":"rectangle","id":"n62","name":"Wide",
"x":40,"y":40,"width":180,"height":120,
"fill":[{"type":"solid","color":"#BDC7D9"}]}
@ -250,7 +250,7 @@ fn web_effect_param_refocus_reseeds_from_committed_snapshot() {
let mut host = WidgetHost::new();
seed(
&mut host,
r##"{ "version": "0.8.0", "children": [
r##"{ "version": "1.0.0", "children": [
{"type":"rectangle","id":"n62","name":"Shadowed",
"x":40,"y":40,"width":180,"height":120,
"effects":[{"type":"shadow","offsetX":12,"offsetY":4,
@ -288,7 +288,7 @@ fn web_effect_param_commit_on_instance_creates_override() {
let mut host = WidgetHost::new();
seed(
&mut host,
r##"{ "version":"0.8.0", "children":[
r##"{ "version":"1.0.0", "children":[
{"type":"rectangle","id":"card","name":"Card","reusable":true,
"x":0,"y":0,"width":200,"height":100,
"effects":[{"type":"shadow","offsetX":12,"offsetY":4,
@ -347,7 +347,7 @@ fn web_effect_param_focus_commits_prior_property_input() {
let mut host = WidgetHost::new();
seed(
&mut host,
r##"{ "version": "0.8.0", "children": [
r##"{ "version": "1.0.0", "children": [
{"type":"rectangle","id":"n62","name":"Wide",
"x":40,"y":40,"width":180,"height":120,
"fill":[{"type":"solid","color":"#BDC7D9"}]}
@ -406,7 +406,7 @@ fn web_property_focus_commit_reads_text_input_state() {
let mut host = WidgetHost::new();
seed(
&mut host,
r##"{ "version": "0.8.0", "children": [
r##"{ "version": "1.0.0", "children": [
{"type":"rectangle","id":"n62","name":"Wide",
"x":40,"y":40,"width":180,"height":120,
"fill":[{"type":"solid","color":"#BDC7D9"}]}
@ -428,7 +428,7 @@ fn web_property_focus_commit_is_undoable() {
let mut host = WidgetHost::new();
seed(
&mut host,
r##"{ "version": "0.8.0", "children": [
r##"{ "version": "1.0.0", "children": [
{"type":"rectangle","id":"n62","name":"Wide",
"x":40,"y":40,"width":180,"height":120,
"fill":[{"type":"solid","color":"#BDC7D9"}]}
@ -454,7 +454,7 @@ fn web_property_focus_commit_on_instance_undo_restores_ref() {
let mut host = WidgetHost::new();
seed(
&mut host,
r##"{ "version":"0.8.0", "children":[
r##"{ "version":"1.0.0", "children":[
{"type":"rectangle","id":"card","name":"Card","reusable":true,
"x":0,"y":0,"width":200,"height":100,
"fill":[{"type":"solid","color":"#222222"}]},

View file

@ -154,7 +154,7 @@ fn property_panel_action_press_sets_and_release_clears_pressed_button() {
let mut host = WidgetHost::new();
seed(
&mut host,
r##"{ "version": "0.8.0", "children": [
r##"{ "version": "1.0.0", "children": [
{"type":"rectangle","id":"n62","name":"Wide",
"x":40,"y":40,"width":180,"height":120,
"fill":[{"type":"solid","color":"#BDC7D9"}]}
@ -186,7 +186,7 @@ fn web_disabling_fill_height_freezes_resolved_height_then_numeric_input_resizes_
let mut host = WidgetHost::new();
seed(
&mut host,
r##"{ "version": "0.8.0", "children": [
r##"{ "version": "1.0.0", "children": [
{"type":"frame","id":"screen","width":390,"height":710,
"layout":"vertical","gap":0,"children":[
{"type":"frame","id":"content","name":"Content Wrapper",
@ -226,7 +226,7 @@ fn web_property_panel_component_button_creates_and_detaches_component() {
let mut host = WidgetHost::new();
seed(
&mut host,
r##"{ "version": "0.8.0", "children": [
r##"{ "version": "1.0.0", "children": [
{"type":"frame","id":"card","name":"Card",
"x":40,"y":40,"width":180,"height":120,
"fill":[{"type":"solid","color":"#FFFFFF"}],
@ -263,7 +263,7 @@ fn web_property_panel_group_component_button_switches_to_detach() {
let mut host = WidgetHost::new();
seed(
&mut host,
r##"{ "version": "0.8.0", "children": [
r##"{ "version": "1.0.0", "children": [
{"type":"group","id":"text_group","name":"Text Group",
"children":[
{"type":"text","id":"label","name":"Label","content":"Hello"}
@ -299,7 +299,7 @@ fn web_property_panel_background_consumes_clicks() {
let mut host = WidgetHost::new();
seed(
&mut host,
r##"{ "version": "0.8.0", "children": [
r##"{ "version": "1.0.0", "children": [
{"type":"group","id":"text_group","name":"Text Group",
"children":[
{"type":"text","id":"label","name":"Label","content":"Hello"}
@ -322,7 +322,7 @@ fn web_property_panel_background_consumes_clicks() {
#[test]
fn web_property_panel_instance_buttons_go_to_master_and_detach_instance() {
const COMPONENT_DOC: &str = r##"{ "version":"0.8.0", "children": [
const COMPONENT_DOC: &str = r##"{ "version":"1.0.0", "children": [
{"type":"frame","id":"card","name":"Card","reusable":true,
"x":40,"y":40,"width":180,"height":120,
"fill":[{"type":"solid","color":"#FFFFFF"}],
@ -359,7 +359,7 @@ fn web_property_panel_size_action_on_instance_routes_to_descendants_override() {
let mut host = WidgetHost::new();
seed(
&mut host,
r##"{ "version":"0.8.0", "children": [
r##"{ "version":"1.0.0", "children": [
{"type":"frame","id":"card","name":"Card","reusable":true,
"x":40,"y":40,"width":180,"height":120,
"fill":[{"type":"solid","color":"#FFFFFF"}],
@ -399,7 +399,7 @@ fn web_property_panel_layout_actions_write_selected_node() {
let mut host = WidgetHost::new();
seed(
&mut host,
r##"{ "version": "0.8.0", "children": [
r##"{ "version": "1.0.0", "children": [
{"type":"rectangle","id":"n62","name":"Wide",
"x":40,"y":40,"width":180,"height":120,
"fill":[{"type":"solid","color":"#BDC7D9"}]}
@ -453,7 +453,7 @@ fn web_property_panel_padding_mode_gear_opens_and_selects_mode() {
let mut host = WidgetHost::new();
seed(
&mut host,
r##"{ "version": "0.8.0", "children": [
r##"{ "version": "1.0.0", "children": [
{"type":"group","id":"text_group","name":"Text Group",
"layout":"vertical","gap":8,
"children":[
@ -489,7 +489,7 @@ fn web_property_panel_fill_add_and_remove_match_native() {
let mut host = WidgetHost::new();
seed(
&mut host,
r##"{ "version": "0.8.0", "children": [
r##"{ "version": "1.0.0", "children": [
{"type":"rectangle","id":"n62","name":"No fill",
"x":40,"y":40,"width":180,"height":120,
"fill":[]}
@ -519,7 +519,7 @@ fn web_property_panel_text_layout_actions_match_native() {
let mut host = WidgetHost::new();
seed(
&mut host,
r##"{ "version": "0.8.0", "children": [
r##"{ "version": "1.0.0", "children": [
{"type":"text","id":"label","name":"Label","content":"Hello",
"x":40,"y":40,"width":180,"height":40,
"fontSize":24}
@ -554,7 +554,7 @@ fn web_property_panel_widget_checked_toggle_matches_native() {
let mut host = WidgetHost::new();
seed(
&mut host,
r##"{ "version": "0.8.0", "children": [
r##"{ "version": "1.0.0", "children": [
{"type":"checkbox","id":"cb","name":"Agree",
"x":40,"y":40,"width":18,"height":18,
"label":"Accept","checked":false}

View file

@ -7,7 +7,7 @@ const VH: f32 = 800.0;
fn seed(host: &mut WidgetHost) {
let doc = jian_ops_schema::load_str(
r##"{"version":"0.8.0","children":[
r##"{"version":"1.0.0","children":[
{"type":"rectangle","id":"box","name":"Box","x":100,"y":100,"width":120,"height":80,
"fill":[{"type":"solid","color":"#2563EB"}]}
]}"##,
@ -22,7 +22,7 @@ fn seed(host: &mut WidgetHost) {
fn seed_container(host: &mut WidgetHost) {
let doc = jian_ops_schema::load_str(
r##"{"version":"0.8.0","children":[
r##"{"version":"1.0.0","children":[
{"type":"frame","id":"box","name":"Frame","x":100,"y":100,
"width":120,"height":80,"layout":"none","children":[
{"type":"rectangle","id":"child","name":"Child","x":10,"y":12,

View file

@ -50,7 +50,7 @@ fn selected_two_variant_color_host() -> WidgetHost {
let mut host = WidgetHost::new();
seed(
&mut host,
r##"{ "version": "0.8.0", "children": [
r##"{ "version": "1.0.0", "children": [
{"type":"rectangle","id":"n62","name":"Wide",
"x":40,"y":40,"width":180,"height":120,
"fill":[{"type":"solid","color":"#BDC7D9"}]}
@ -326,7 +326,7 @@ fn variable_row_edit_commits_prior_property_focus_on_web() {
let mut host = WidgetHost::new();
seed(
&mut host,
r##"{ "version": "0.8.0", "children": [
r##"{ "version": "1.0.0", "children": [
{"type":"rectangle","id":"n62","name":"Wide",
"x":40,"y":40,"width":180,"height":120,
"fill":[{"type":"solid","color":"#BDC7D9"}]}

View file

@ -42,7 +42,7 @@ fn preserving_geometry_keeps_authored_nested_positions() {
#[test]
fn minimal_empty_doc() {
let r = load(r#"{"version":"0.8.0","children":[]}"#);
let r = load(r#"{"version":"1.0.0","children":[]}"#);
assert_eq!(r.payload.pages.len(), 1);
assert!(r.payload.pages[0].children.is_empty());
}

View file

@ -971,7 +971,7 @@ mod tests {
use jian_ops_schema::node::PenNode;
fn nested_frame_doc(depth: usize) -> String {
let mut src = String::from(r#"{"version":"0.8.0","children":["#);
let mut src = String::from(r#"{"version":"1.0.0","children":["#);
for i in 0..depth {
src.push_str(&format!(
r##"{{"type":"frame","id":"nest-{i:05}","name":"Nested Layer {i:05}","x":8,"y":6,"width":400,"height":220,"fill":[{{"type":"solid","color":"#ffffff20"}}],"stroke":{{"thickness":1,"fill":[{{"type":"solid","color":"#0088ff"}}]}},"children":["##
@ -1027,7 +1027,7 @@ mod tests {
// LLM-authored image node: `imageSearchQuery` / `imagePrompt` but no
// `src`. jian's `ImageNode.src` is required, so this must be repaired
// on load rather than rejected (the web app opened these files fine).
let doc = r#"{"version":"0.8.0","children":[{"id":"hero","type":"image","name":"Hero","width":120,"height":80,"imageSearchQuery":"pizza","imagePrompt":"a hot pizza"}]}"#;
let doc = r#"{"version":"1.0.0","children":[{"id":"hero","type":"image","name":"Hero","width":120,"height":80,"imageSearchQuery":"pizza","imagePrompt":"a hot pizza"}]}"#;
let loaded = load_canonical(doc).expect("image node without src must load");
assert_eq!(loaded.value.children.len(), 1, "the image node should load");
}
@ -1037,7 +1037,7 @@ mod tests {
// Older TS files write a PenNode `fill` as a bare color string where
// jian expects `Vec<PenFill>`. Must be wrapped, not rejected. The
// type-less `StyledTextSegment.fill` (also a string) stays a string.
let doc = r##"{"version":"0.8.0","children":[{"id":"bg","type":"frame","name":"BG","x":0,"y":0,"width":100,"height":100,"fill":"#1A1D2E","children":[]}]}"##;
let doc = r##"{"version":"1.0.0","children":[{"id":"bg","type":"frame","name":"BG","x":0,"y":0,"width":100,"height":100,"fill":"#1A1D2E","children":[]}]}"##;
let loaded = load_canonical(doc).expect("string fill must load");
assert_eq!(loaded.value.children.len(), 1, "the frame should load");
}

View file

@ -104,7 +104,7 @@ mod tests {
fn state_with_rect(x: f64) -> EditorState {
let doc = jian_ops_schema::load_str(&format!(
r#"{{"version":"0.8.0","children":[
r#"{{"version":"1.0.0","children":[
{{"type":"rectangle","id":"r","name":"r","x":{x},"y":0,"width":40,"height":20}}
]}}"#
))

View file

@ -24,7 +24,7 @@ fn find<'a>(nodes: &'a [NodePayload], name: &str) -> Option<&'a NodePayload> {
fn fixed_square_image_not_shrunk_in_tight_row() {
// 160-wide horizontal row holding a fill image + a fixed 80x80 image.
// The fixed one must stay 80x80 (the fill image absorbs the squeeze).
let doc = r#"{"version":"0.8.0","children":[{"type":"frame","id":"row","width":160,"height":100,"layout":"horizontal","gap":8,"children":[{"type":"image","id":"fill","name":"Fill","width":"fill_container","height":"fill_container","src":""},{"type":"image","id":"sq","name":"Sq","width":80,"height":80,"src":""}]}]}"#;
let doc = r#"{"version":"1.0.0","children":[{"type":"frame","id":"row","width":160,"height":100,"layout":"horizontal","gap":8,"children":[{"type":"image","id":"fill","name":"Fill","width":"fill_container","height":"fill_container","src":""},{"type":"image","id":"sq","name":"Sq","width":80,"height":80,"src":""}]}]}"#;
let loaded = op_pen_loader::load_canonical(doc).expect("loads");
let d = op_pen_loader::pen_document_to_payload(&loaded.value);
let sq = d
@ -48,7 +48,7 @@ fn fill_width_tiles_with_fixed_height_still_share_the_row() {
// height is Number` rule wrongly pinned them (flex_shrink=0) and the
// fill tiles overflowed, showing only the first; the `AND` rule frees
// them to share the row again.
let doc = r#"{"version":"0.8.0","children":[{"type":"frame","id":"row","width":300,"height":100,"layout":"horizontal","gap":0,"children":[{"type":"frame","id":"a","name":"A","width":"fill_container","height":78},{"type":"frame","id":"b","name":"B","width":"fill_container","height":78},{"type":"frame","id":"c","name":"C","width":"fill_container","height":78}]}]}"#;
let doc = r#"{"version":"1.0.0","children":[{"type":"frame","id":"row","width":300,"height":100,"layout":"horizontal","gap":0,"children":[{"type":"frame","id":"a","name":"A","width":"fill_container","height":78},{"type":"frame","id":"b","name":"B","width":"fill_container","height":78},{"type":"frame","id":"c","name":"C","width":"fill_container","height":78}]}]}"#;
let loaded = op_pen_loader::load_canonical(doc).expect("loads");
let d = op_pen_loader::pen_document_to_payload(&loaded.value);
let a = d
@ -71,7 +71,7 @@ fn fixed_sibling_stays_inside_card_when_fill_column_has_wide_content() {
// must shrink below its content's min-width (TS gives fill the remaining
// space, content wraps) so the fixed image stays inside the card instead
// of being pushed out (needs `min_size: 0` on the fill axis).
let doc = r#"{"version":"0.8.0","children":[{"type":"frame","id":"card","width":200,"height":100,"layout":"horizontal","gap":0,"children":[{"type":"frame","id":"col","name":"Col","width":"fill_container","height":"fill_container","layout":"vertical","children":[{"type":"frame","id":"wide","width":150,"height":20}]},{"type":"image","id":"img","name":"Img","width":80,"height":80,"src":""}]}]}"#;
let doc = r#"{"version":"1.0.0","children":[{"type":"frame","id":"card","width":200,"height":100,"layout":"horizontal","gap":0,"children":[{"type":"frame","id":"col","name":"Col","width":"fill_container","height":"fill_container","layout":"vertical","children":[{"type":"frame","id":"wide","width":150,"height":20}]},{"type":"image","id":"img","name":"Img","width":80,"height":80,"src":""}]}]}"#;
let loaded = op_pen_loader::load_canonical(doc).expect("loads");
let d = op_pen_loader::pen_document_to_payload(&loaded.value);
let img = d

36
tools/check-version-fixtures.sh Executable file
View file

@ -0,0 +1,36 @@
#!/usr/bin/env bash
set -euo pipefail
script_dir=$(CDPATH= cd "$(dirname "$0")" && pwd)
repo_root=$(CDPATH= cd "$script_dir/.." && pwd)
current_version=$(bash "$repo_root/scripts/workspace-version.sh")
cd "$repo_root"
rg_status=0
matches=$(rg \
--fixed-strings \
--line-number \
--with-filename \
--color never \
--glob '*.rs' \
--glob '!**/op-host-desktop/src/update_check.rs' \
"$current_version" \
crates) || rg_status=$?
if [[ "$rg_status" -gt 1 ]]; then
printf 'version-fixtures: failed to scan Rust sources with rg (status %s)\n' "$rg_status" >&2
exit "$rg_status"
fi
if [[ -n "$matches" ]]; then
printf 'version-fixtures: ordinary Rust fixtures copy current product version %s:\n' \
"$current_version" >&2
printf '%s\n' "$matches" >&2
printf 'version-fixtures: use stable 1.0.0 test data unless a test explicitly covers compatibility, migration, or updates\n' >&2
exit 1
fi
printf 'version-fixtures: no ordinary Rust fixtures copy current product version %s\n' \
"$current_version"