- React SPA: dashboard, data sources CRUD, widgets CRUD, layout builder, presets. TanStack Router + Query, shadcn/ui, Vite proxy to :3000 - wire media + rss adapters into polling loop, remove xtb source type - media adapter: read username/password from headers, proper subsonic auth - event handler: subscribe to LayoutChanged, push screen update to clients - fix clippy warnings across workspace (Default impls, collapsible ifs, redundant closures, is_none_or, unused imports)
104 lines
2.8 KiB
Rust
104 lines
2.8 KiB
Rust
use client_domain::{BoundingBox, LayoutEngine};
|
|
use domain::{ContainerNode, Direction, LayoutChild, LayoutNode, Sizing};
|
|
|
|
fn screen() -> BoundingBox {
|
|
BoundingBox::screen(240, 320)
|
|
}
|
|
|
|
#[test]
|
|
fn diff_detects_moved_widget_after_layout_change() {
|
|
let layout_a = LayoutNode::Container(ContainerNode {
|
|
direction: Direction::Row,
|
|
gap: 0,
|
|
padding: 0,
|
|
children: vec![
|
|
LayoutChild {
|
|
sizing: Sizing::Flex(1),
|
|
node: LayoutNode::Leaf(1),
|
|
},
|
|
LayoutChild {
|
|
sizing: Sizing::Flex(1),
|
|
node: LayoutNode::Leaf(2),
|
|
},
|
|
],
|
|
});
|
|
|
|
let layout_b = LayoutNode::Container(ContainerNode {
|
|
direction: Direction::Column,
|
|
gap: 0,
|
|
padding: 0,
|
|
children: vec![
|
|
LayoutChild {
|
|
sizing: Sizing::Flex(1),
|
|
node: LayoutNode::Leaf(1),
|
|
},
|
|
LayoutChild {
|
|
sizing: Sizing::Flex(1),
|
|
node: LayoutNode::Leaf(2),
|
|
},
|
|
],
|
|
});
|
|
|
|
let tree_a = LayoutEngine::compute(&layout_a, screen());
|
|
let tree_b = LayoutEngine::compute(&layout_b, screen());
|
|
|
|
let mut changed = tree_b.diff(&tree_a);
|
|
changed.sort();
|
|
assert_eq!(changed, vec![1, 2]);
|
|
}
|
|
|
|
#[test]
|
|
fn diff_returns_empty_for_identical_layouts() {
|
|
let layout = LayoutNode::Container(ContainerNode {
|
|
direction: Direction::Row,
|
|
gap: 0,
|
|
padding: 0,
|
|
children: vec![
|
|
LayoutChild {
|
|
sizing: Sizing::Flex(1),
|
|
node: LayoutNode::Leaf(1),
|
|
},
|
|
LayoutChild {
|
|
sizing: Sizing::Flex(1),
|
|
node: LayoutNode::Leaf(2),
|
|
},
|
|
],
|
|
});
|
|
|
|
let tree_a = LayoutEngine::compute(&layout, screen());
|
|
let tree_b = LayoutEngine::compute(&layout, screen());
|
|
|
|
assert!(tree_b.diff(&tree_a).is_empty());
|
|
}
|
|
|
|
#[test]
|
|
fn diff_detects_added_and_removed_widgets() {
|
|
let layout_a = LayoutNode::Container(ContainerNode {
|
|
direction: Direction::Row,
|
|
gap: 0,
|
|
padding: 0,
|
|
children: vec![LayoutChild {
|
|
sizing: Sizing::Flex(1),
|
|
node: LayoutNode::Leaf(1),
|
|
}],
|
|
});
|
|
|
|
let layout_b = LayoutNode::Container(ContainerNode {
|
|
direction: Direction::Row,
|
|
gap: 0,
|
|
padding: 0,
|
|
children: vec![LayoutChild {
|
|
sizing: Sizing::Flex(1),
|
|
node: LayoutNode::Leaf(2),
|
|
}],
|
|
});
|
|
|
|
let tree_a = LayoutEngine::compute(&layout_a, screen());
|
|
let tree_b = LayoutEngine::compute(&layout_b, screen());
|
|
|
|
let mut changed = tree_b.diff(&tree_a);
|
|
changed.sort();
|
|
// widget 1 was removed (in old but not new), widget 2 was added (in new but not old)
|
|
assert_eq!(changed, vec![1, 2]);
|
|
}
|