feat: Project model with CRUD operations and tests
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
afd092c642
commit
3f6745be45
3 changed files with 186 additions and 0 deletions
|
|
@ -1,5 +1,6 @@
|
|||
mod db;
|
||||
mod error;
|
||||
mod models;
|
||||
|
||||
use std::sync::Mutex;
|
||||
use tauri::Manager;
|
||||
|
|
|
|||
1
src-tauri/src/models/mod.rs
Normal file
1
src-tauri/src/models/mod.rs
Normal file
|
|
@ -0,0 +1 @@
|
|||
pub mod project;
|
||||
184
src-tauri/src/models/project.rs
Normal file
184
src-tauri/src/models/project.rs
Normal file
|
|
@ -0,0 +1,184 @@
|
|||
use rusqlite::{params, Connection, Result};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use uuid::Uuid;
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct Project {
|
||||
pub id: String,
|
||||
pub name: String,
|
||||
pub path: String,
|
||||
pub cloned_from: Option<String>,
|
||||
pub base_branch: String,
|
||||
pub created_at: String,
|
||||
}
|
||||
|
||||
impl Project {
|
||||
pub fn insert(
|
||||
conn: &Connection,
|
||||
name: &str,
|
||||
path: &str,
|
||||
cloned_from: Option<&str>,
|
||||
base_branch: &str,
|
||||
) -> Result<Project> {
|
||||
let id = Uuid::new_v4().to_string();
|
||||
let now = chrono::Utc::now().to_rfc3339();
|
||||
|
||||
conn.execute(
|
||||
"INSERT INTO projects (id, name, path, cloned_from, base_branch, created_at) VALUES (?1, ?2, ?3, ?4, ?5, ?6)",
|
||||
params![id, name, path, cloned_from, base_branch, now],
|
||||
)?;
|
||||
|
||||
Ok(Project {
|
||||
id,
|
||||
name: name.to_string(),
|
||||
path: path.to_string(),
|
||||
cloned_from: cloned_from.map(String::from),
|
||||
base_branch: base_branch.to_string(),
|
||||
created_at: now,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn list(conn: &Connection) -> Result<Vec<Project>> {
|
||||
let mut stmt = conn.prepare(
|
||||
"SELECT id, name, path, cloned_from, base_branch, created_at FROM projects ORDER BY created_at DESC",
|
||||
)?;
|
||||
let rows = stmt.query_map([], |row| {
|
||||
Ok(Project {
|
||||
id: row.get(0)?,
|
||||
name: row.get(1)?,
|
||||
path: row.get(2)?,
|
||||
cloned_from: row.get(3)?,
|
||||
base_branch: row.get(4)?,
|
||||
created_at: row.get(5)?,
|
||||
})
|
||||
})?;
|
||||
rows.collect()
|
||||
}
|
||||
|
||||
pub fn get_by_id(conn: &Connection, id: &str) -> Result<Project> {
|
||||
conn.query_row(
|
||||
"SELECT id, name, path, cloned_from, base_branch, created_at FROM projects WHERE id = ?1",
|
||||
params![id],
|
||||
|row| {
|
||||
Ok(Project {
|
||||
id: row.get(0)?,
|
||||
name: row.get(1)?,
|
||||
path: row.get(2)?,
|
||||
cloned_from: row.get(3)?,
|
||||
base_branch: row.get(4)?,
|
||||
created_at: row.get(5)?,
|
||||
})
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
pub fn update(conn: &Connection, id: &str, name: &str, base_branch: &str) -> Result<()> {
|
||||
conn.execute(
|
||||
"UPDATE projects SET name = ?1, base_branch = ?2 WHERE id = ?3",
|
||||
params![name, base_branch, id],
|
||||
)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn delete(conn: &Connection, id: &str) -> Result<()> {
|
||||
conn.execute("DELETE FROM projects WHERE id = ?1", params![id])?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::db;
|
||||
|
||||
fn setup() -> Connection {
|
||||
db::init_in_memory().expect("db init should succeed")
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_insert_project_local_path() {
|
||||
let conn = setup();
|
||||
let project = Project::insert(&conn, "My Project", "/home/user/code/myproject", None, "main")
|
||||
.expect("insert should succeed");
|
||||
|
||||
assert_eq!(project.name, "My Project");
|
||||
assert_eq!(project.path, "/home/user/code/myproject");
|
||||
assert!(project.cloned_from.is_none());
|
||||
assert_eq!(project.base_branch, "main");
|
||||
assert!(!project.id.is_empty());
|
||||
assert!(!project.created_at.is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_insert_project_cloned() {
|
||||
let conn = setup();
|
||||
let project = Project::insert(
|
||||
&conn,
|
||||
"Cloned Project",
|
||||
"/home/user/code/cloned",
|
||||
Some("https://github.com/org/repo.git"),
|
||||
"stable",
|
||||
)
|
||||
.expect("insert should succeed");
|
||||
|
||||
assert_eq!(project.cloned_from.as_deref(), Some("https://github.com/org/repo.git"));
|
||||
assert_eq!(project.base_branch, "stable");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_list_projects_empty() {
|
||||
let conn = setup();
|
||||
let projects = Project::list(&conn).expect("list should succeed");
|
||||
assert!(projects.is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_list_projects_returns_all() {
|
||||
let conn = setup();
|
||||
Project::insert(&conn, "A", "/path/a", None, "main").unwrap();
|
||||
Project::insert(&conn, "B", "/path/b", None, "main").unwrap();
|
||||
|
||||
let projects = Project::list(&conn).expect("list should succeed");
|
||||
assert_eq!(projects.len(), 2);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_get_by_id() {
|
||||
let conn = setup();
|
||||
let created = Project::insert(&conn, "Test", "/path/test", None, "main").unwrap();
|
||||
let found = Project::get_by_id(&conn, &created.id).expect("get should succeed");
|
||||
|
||||
assert_eq!(found.id, created.id);
|
||||
assert_eq!(found.name, "Test");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_get_by_id_not_found() {
|
||||
let conn = setup();
|
||||
let result = Project::get_by_id(&conn, "nonexistent");
|
||||
assert!(result.is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_update_project() {
|
||||
let conn = setup();
|
||||
let created = Project::insert(&conn, "Old Name", "/path", None, "main").unwrap();
|
||||
|
||||
Project::update(&conn, &created.id, "New Name", "develop").expect("update should succeed");
|
||||
|
||||
let updated = Project::get_by_id(&conn, &created.id).unwrap();
|
||||
assert_eq!(updated.name, "New Name");
|
||||
assert_eq!(updated.base_branch, "develop");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_delete_project() {
|
||||
let conn = setup();
|
||||
let created = Project::insert(&conn, "ToDelete", "/path", None, "main").unwrap();
|
||||
|
||||
Project::delete(&conn, &created.id).expect("delete should succeed");
|
||||
|
||||
let result = Project::get_by_id(&conn, &created.id);
|
||||
assert!(result.is_err());
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue