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:
111
crates/application/tests/window_usecases.rs
Normal file
111
crates/application/tests/window_usecases.rs
Normal file
@ -0,0 +1,111 @@
|
||||
//! L10 tests for [`MoveTabToNewWindow`] with a fake [`ProjectStore`]: the tab is
|
||||
//! detached and the workspace is persisted (load returns the new state).
|
||||
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
use async_trait::async_trait;
|
||||
use domain::ids::{ProjectId, TabId, WindowId};
|
||||
use domain::layout::{LayoutNode, LayoutTree, LeafCell, Tab, Window, Workspace};
|
||||
use domain::ports::{IdGenerator, ProjectStore, StoreError};
|
||||
use domain::project::Project;
|
||||
use domain::NodeId;
|
||||
use uuid::Uuid;
|
||||
|
||||
use application::{MoveTabToNewWindow, MoveTabToNewWindowInput};
|
||||
|
||||
/// A `ProjectStore` fake that only implements the workspace persistence the use
|
||||
/// case needs (the project methods are never called here).
|
||||
#[derive(Clone)]
|
||||
struct FakeStore(Arc<Mutex<Workspace>>);
|
||||
#[async_trait]
|
||||
impl ProjectStore for FakeStore {
|
||||
async fn list_projects(&self) -> Result<Vec<Project>, StoreError> {
|
||||
unreachable!()
|
||||
}
|
||||
async fn load_project(&self, _id: ProjectId) -> Result<Project, StoreError> {
|
||||
unreachable!()
|
||||
}
|
||||
async fn save_project(&self, _p: &Project) -> Result<(), StoreError> {
|
||||
unreachable!()
|
||||
}
|
||||
async fn save_workspace(&self, ws: &Workspace) -> Result<(), StoreError> {
|
||||
*self.0.lock().unwrap() = ws.clone();
|
||||
Ok(())
|
||||
}
|
||||
async fn load_workspace(&self) -> Result<Workspace, StoreError> {
|
||||
Ok(self.0.lock().unwrap().clone())
|
||||
}
|
||||
}
|
||||
|
||||
struct SeqIds(Mutex<u128>);
|
||||
impl IdGenerator for SeqIds {
|
||||
fn new_uuid(&self) -> Uuid {
|
||||
let mut n = self.0.lock().unwrap();
|
||||
let id = Uuid::from_u128(*n);
|
||||
*n += 1;
|
||||
id
|
||||
}
|
||||
}
|
||||
|
||||
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 tab(n: u128) -> Tab {
|
||||
Tab {
|
||||
id: tid(n),
|
||||
project_id: ProjectId::from_uuid(Uuid::from_u128(1000 + n)),
|
||||
layout: LayoutTree::new(LayoutNode::Leaf(LeafCell {
|
||||
id: NodeId::from_uuid(Uuid::from_u128(900 + n)),
|
||||
session: None,
|
||||
agent: None,
|
||||
})),
|
||||
}
|
||||
}
|
||||
|
||||
fn seeded() -> FakeStore {
|
||||
let ws = Workspace {
|
||||
windows: vec![Window::new(wid(1), vec![tab(1), tab(2)], tid(1)).unwrap()],
|
||||
};
|
||||
FakeStore(Arc::new(Mutex::new(ws)))
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn detaches_tab_and_persists_workspace() {
|
||||
let store = seeded();
|
||||
// The id generator's first uuid (from_u128(7)) becomes the new window id.
|
||||
let ids = Arc::new(SeqIds(Mutex::new(7)));
|
||||
let uc = MoveTabToNewWindow::new(Arc::new(store.clone()), ids);
|
||||
|
||||
let out = uc
|
||||
.execute(MoveTabToNewWindowInput { tab_id: tid(1) })
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(out.new_window_id, WindowId::from_uuid(Uuid::from_u128(7)));
|
||||
assert_eq!(out.workspace.windows.len(), 2);
|
||||
|
||||
// Persisted: reloading the store yields the detached layout.
|
||||
let reloaded = store.load_workspace().await.unwrap();
|
||||
assert_eq!(reloaded, out.workspace);
|
||||
let detached = reloaded
|
||||
.windows
|
||||
.iter()
|
||||
.find(|w| w.id == out.new_window_id)
|
||||
.unwrap();
|
||||
assert_eq!(detached.tabs.len(), 1);
|
||||
assert_eq!(detached.tabs[0].id, tid(1));
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn unknown_tab_is_not_found() {
|
||||
let store = seeded();
|
||||
let uc = MoveTabToNewWindow::new(Arc::new(store), Arc::new(SeqIds(Mutex::new(7))));
|
||||
let err = uc
|
||||
.execute(MoveTabToNewWindowInput { tab_id: tid(404) })
|
||||
.await
|
||||
.unwrap_err();
|
||||
assert_eq!(err.code(), "NOT_FOUND", "got {err:?}");
|
||||
}
|
||||
Reference in New Issue
Block a user