feat: add main features
Agents for developpement added + frontend add + backend added. Git viewer created + agent and template creator + layout and project creator
This commit is contained in:
93
crates/domain/tests/window.rs
Normal file
93
crates/domain/tests/window.rs
Normal file
@ -0,0 +1,93 @@
|
||||
//! L10 tests for the pure `Workspace::move_tab_to_new_window` operation
|
||||
//! (ARCHITECTURE §10): a tab is *moved*, never duplicated; an emptied source
|
||||
//! window is dropped; an active moved tab hands activity back to a sibling.
|
||||
|
||||
use domain::{
|
||||
LayoutNode, LayoutTree, LayoutError, LeafCell, NodeId, ProjectId, Tab, TabId, Window,
|
||||
WindowId, Workspace,
|
||||
};
|
||||
use uuid::Uuid;
|
||||
|
||||
fn tid(n: u128) -> TabId {
|
||||
TabId::from_uuid(Uuid::from_u128(n))
|
||||
}
|
||||
fn wid(n: u128) -> WindowId {
|
||||
WindowId::from_uuid(Uuid::from_u128(n))
|
||||
}
|
||||
fn leaf_tree() -> LayoutTree {
|
||||
LayoutTree::new(LayoutNode::Leaf(LeafCell {
|
||||
id: NodeId::from_uuid(Uuid::from_u128(900)),
|
||||
session: None,
|
||||
agent: None,
|
||||
}))
|
||||
}
|
||||
fn tab(n: u128) -> Tab {
|
||||
Tab {
|
||||
id: tid(n),
|
||||
project_id: ProjectId::from_uuid(Uuid::from_u128(1000 + n)),
|
||||
layout: leaf_tree(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Count how many windows contain a tab with the given id.
|
||||
fn occurrences(ws: &Workspace, tab: TabId) -> usize {
|
||||
ws.windows
|
||||
.iter()
|
||||
.filter(|w| w.tabs.iter().any(|t| t.id == tab))
|
||||
.count()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn move_tab_from_multi_tab_window_keeps_source_and_creates_new() {
|
||||
let src = Window::new(wid(1), vec![tab(1), tab(2)], tid(1)).unwrap();
|
||||
let ws = Workspace { windows: vec![src] };
|
||||
|
||||
let next = ws.move_tab_to_new_window(tid(1), wid(99)).unwrap();
|
||||
|
||||
assert_eq!(next.windows.len(), 2, "source kept + new window");
|
||||
// The moved tab appears exactly once (moved, not duplicated).
|
||||
assert_eq!(occurrences(&next, tid(1)), 1);
|
||||
// Source window kept tab 2 and fell back its active tab to it.
|
||||
let source = next.windows.iter().find(|w| w.id == wid(1)).unwrap();
|
||||
assert_eq!(source.tabs.len(), 1);
|
||||
assert_eq!(source.active_tab, tid(2));
|
||||
// New window holds the moved tab, active.
|
||||
let detached = next.windows.iter().find(|w| w.id == wid(99)).unwrap();
|
||||
assert_eq!(detached.tabs.len(), 1);
|
||||
assert_eq!(detached.active_tab, tid(1));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn move_only_tab_removes_the_emptied_source_window() {
|
||||
let src = Window::new(wid(1), vec![tab(1)], tid(1)).unwrap();
|
||||
let ws = Workspace { windows: vec![src] };
|
||||
|
||||
let next = ws.move_tab_to_new_window(tid(1), wid(99)).unwrap();
|
||||
|
||||
assert_eq!(next.windows.len(), 1, "emptied source dropped");
|
||||
assert_eq!(next.windows[0].id, wid(99));
|
||||
assert_eq!(occurrences(&next, tid(1)), 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn move_unknown_tab_is_rejected() {
|
||||
let ws = Workspace {
|
||||
windows: vec![Window::new(wid(1), vec![tab(1)], tid(1)).unwrap()],
|
||||
};
|
||||
assert!(matches!(
|
||||
ws.move_tab_to_new_window(tid(404), wid(99)).unwrap_err(),
|
||||
LayoutError::TabNotFound(t) if t == tid(404)
|
||||
));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn move_non_active_tab_leaves_source_active_unchanged() {
|
||||
let src = Window::new(wid(1), vec![tab(1), tab(2)], tid(1)).unwrap();
|
||||
let ws = Workspace { windows: vec![src] };
|
||||
|
||||
let next = ws.move_tab_to_new_window(tid(2), wid(99)).unwrap();
|
||||
|
||||
let source = next.windows.iter().find(|w| w.id == wid(1)).unwrap();
|
||||
assert_eq!(source.active_tab, tid(1), "active tab unchanged");
|
||||
assert_eq!(source.tabs.len(), 1);
|
||||
}
|
||||
Reference in New Issue
Block a user