Update user and product entities to not allow empty username and name, and update corresponding tests
This commit is contained in:
parent
0117f9b490
commit
9de4f0b64c
7 changed files with 261 additions and 332 deletions
|
@ -239,10 +239,7 @@ mod tests {
|
||||||
let repo = MockRepository::<User>::new();
|
let repo = MockRepository::<User>::new();
|
||||||
let service = Service::new(repo);
|
let service = Service::new(repo);
|
||||||
|
|
||||||
let create_user = CreateUser {
|
let create_user = CreateUser::new("test_user".to_string(), "test@example.com".to_string()).unwrap();
|
||||||
username: "test_user".to_string(),
|
|
||||||
email: "test@example.com".to_string(),
|
|
||||||
};
|
|
||||||
|
|
||||||
let user = service.create(create_user).await.unwrap();
|
let user = service.create(create_user).await.unwrap();
|
||||||
assert_eq!(user.username, "test_user");
|
assert_eq!(user.username, "test_user");
|
||||||
|
@ -254,10 +251,7 @@ mod tests {
|
||||||
let repo = MockRepository::<User>::new();
|
let repo = MockRepository::<User>::new();
|
||||||
let service = Service::new(repo);
|
let service = Service::new(repo);
|
||||||
|
|
||||||
let create_user = CreateUser {
|
let create_user = CreateUser::new("test_user".to_string(), "test@example.com".to_string()).unwrap();
|
||||||
username: "test_user".to_string(),
|
|
||||||
email: "test@example.com".to_string(),
|
|
||||||
};
|
|
||||||
|
|
||||||
let created = service.create(create_user).await.unwrap();
|
let created = service.create(create_user).await.unwrap();
|
||||||
let found = service.get(created.id).await.unwrap();
|
let found = service.get(created.id).await.unwrap();
|
||||||
|
@ -269,14 +263,8 @@ mod tests {
|
||||||
let repo = MockRepository::<User>::new();
|
let repo = MockRepository::<User>::new();
|
||||||
let service = Service::new(repo);
|
let service = Service::new(repo);
|
||||||
|
|
||||||
let user1 = CreateUser {
|
let user1 = CreateUser::new("user1".to_string(), "user1@example.com".to_string()).unwrap();
|
||||||
username: "user1".to_string(),
|
let user2 = CreateUser::new("user2".to_string(), "user2@example.com".to_string()).unwrap();
|
||||||
email: "user1@example.com".to_string(),
|
|
||||||
};
|
|
||||||
let user2 = CreateUser {
|
|
||||||
username: "user2".to_string(),
|
|
||||||
email: "user2@example.com".to_string(),
|
|
||||||
};
|
|
||||||
|
|
||||||
service.create(user1).await.unwrap();
|
service.create(user1).await.unwrap();
|
||||||
service.create(user2).await.unwrap();
|
service.create(user2).await.unwrap();
|
||||||
|
@ -290,16 +278,10 @@ mod tests {
|
||||||
let repo = MockRepository::<User>::new();
|
let repo = MockRepository::<User>::new();
|
||||||
let service = Service::new(repo);
|
let service = Service::new(repo);
|
||||||
|
|
||||||
let create_user = CreateUser {
|
let create_user = CreateUser::new("test_user".to_string(), "test@example.com".to_string()).unwrap();
|
||||||
username: "test_user".to_string(),
|
|
||||||
email: "test@example.com".to_string(),
|
|
||||||
};
|
|
||||||
|
|
||||||
let created = service.create(create_user).await.unwrap();
|
let created = service.create(create_user).await.unwrap();
|
||||||
let update = UpdateUser {
|
let update = UpdateUser::new(Some("updated_user".to_string()), None).unwrap();
|
||||||
username: Some("updated_user".to_string()),
|
|
||||||
email: None,
|
|
||||||
};
|
|
||||||
|
|
||||||
let updated = service.update(created.id, update).await.unwrap();
|
let updated = service.update(created.id, update).await.unwrap();
|
||||||
assert_eq!(updated.username, "updated_user");
|
assert_eq!(updated.username, "updated_user");
|
||||||
|
@ -311,10 +293,7 @@ mod tests {
|
||||||
let repo = MockRepository::<User>::new();
|
let repo = MockRepository::<User>::new();
|
||||||
let service = Service::new(repo);
|
let service = Service::new(repo);
|
||||||
|
|
||||||
let create_user = CreateUser {
|
let create_user = CreateUser::new("test_user".to_string(), "test@example.com".to_string()).unwrap();
|
||||||
username: "test_user".to_string(),
|
|
||||||
email: "test@example.com".to_string(),
|
|
||||||
};
|
|
||||||
|
|
||||||
let created = service.create(create_user).await.unwrap();
|
let created = service.create(create_user).await.unwrap();
|
||||||
service.delete(created.id).await.unwrap();
|
service.delete(created.id).await.unwrap();
|
||||||
|
@ -326,10 +305,7 @@ mod tests {
|
||||||
let repo = MockRepository::<Product>::new();
|
let repo = MockRepository::<Product>::new();
|
||||||
let service = Service::new(repo);
|
let service = Service::new(repo);
|
||||||
|
|
||||||
let create_product = CreateProduct {
|
let create_product = CreateProduct::new("Test Product".to_string(), "Test Description".to_string()).unwrap();
|
||||||
name: "Test Product".to_string(),
|
|
||||||
description: "Test Description".to_string(),
|
|
||||||
};
|
|
||||||
|
|
||||||
let product = service.create(create_product).await.unwrap();
|
let product = service.create(create_product).await.unwrap();
|
||||||
assert_eq!(product.name, "Test Product");
|
assert_eq!(product.name, "Test Product");
|
||||||
|
@ -341,10 +317,7 @@ mod tests {
|
||||||
let repo = MockRepository::<Product>::new();
|
let repo = MockRepository::<Product>::new();
|
||||||
let service = Service::new(repo);
|
let service = Service::new(repo);
|
||||||
|
|
||||||
let create_product = CreateProduct {
|
let create_product = CreateProduct::new("Test Product".to_string(), "Test Description".to_string()).unwrap();
|
||||||
name: "Test Product".to_string(),
|
|
||||||
description: "Test Description".to_string(),
|
|
||||||
};
|
|
||||||
|
|
||||||
let created = service.create(create_product).await.unwrap();
|
let created = service.create(create_product).await.unwrap();
|
||||||
let found = service.get(created.id).await.unwrap();
|
let found = service.get(created.id).await.unwrap();
|
||||||
|
@ -356,14 +329,8 @@ mod tests {
|
||||||
let repo = MockRepository::<Product>::new();
|
let repo = MockRepository::<Product>::new();
|
||||||
let service = Service::new(repo);
|
let service = Service::new(repo);
|
||||||
|
|
||||||
let product1 = CreateProduct {
|
let product1 = CreateProduct::new("Product 1".to_string(), "Description 1".to_string()).unwrap();
|
||||||
name: "Product 1".to_string(),
|
let product2 = CreateProduct::new("Product 2".to_string(), "Description 2".to_string()).unwrap();
|
||||||
description: "Description 1".to_string(),
|
|
||||||
};
|
|
||||||
let product2 = CreateProduct {
|
|
||||||
name: "Product 2".to_string(),
|
|
||||||
description: "Description 2".to_string(),
|
|
||||||
};
|
|
||||||
|
|
||||||
service.create(product1).await.unwrap();
|
service.create(product1).await.unwrap();
|
||||||
service.create(product2).await.unwrap();
|
service.create(product2).await.unwrap();
|
||||||
|
@ -377,16 +344,10 @@ mod tests {
|
||||||
let repo = MockRepository::<Product>::new();
|
let repo = MockRepository::<Product>::new();
|
||||||
let service = Service::new(repo);
|
let service = Service::new(repo);
|
||||||
|
|
||||||
let create_product = CreateProduct {
|
let create_product = CreateProduct::new("Test Product".to_string(), "Test Description".to_string()).unwrap();
|
||||||
name: "Test Product".to_string(),
|
|
||||||
description: "Test Description".to_string(),
|
|
||||||
};
|
|
||||||
|
|
||||||
let created = service.create(create_product).await.unwrap();
|
let created = service.create(create_product).await.unwrap();
|
||||||
let update = UpdateProduct {
|
let update = UpdateProduct::new(Some("Updated Product".to_string()), None).unwrap();
|
||||||
name: Some("Updated Product".to_string()),
|
|
||||||
description: None,
|
|
||||||
};
|
|
||||||
|
|
||||||
let updated = service.update(created.id, update).await.unwrap();
|
let updated = service.update(created.id, update).await.unwrap();
|
||||||
assert_eq!(updated.name, "Updated Product");
|
assert_eq!(updated.name, "Updated Product");
|
||||||
|
@ -398,10 +359,7 @@ mod tests {
|
||||||
let repo = MockRepository::<Product>::new();
|
let repo = MockRepository::<Product>::new();
|
||||||
let service = Service::new(repo);
|
let service = Service::new(repo);
|
||||||
|
|
||||||
let create_product = CreateProduct {
|
let create_product = CreateProduct::new("Test Product".to_string(), "Test Description".to_string()).unwrap();
|
||||||
name: "Test Product".to_string(),
|
|
||||||
description: "Test Description".to_string(),
|
|
||||||
};
|
|
||||||
|
|
||||||
let created = service.create(create_product).await.unwrap();
|
let created = service.create(create_product).await.unwrap();
|
||||||
service.delete(created.id).await.unwrap();
|
service.delete(created.id).await.unwrap();
|
||||||
|
@ -426,10 +384,7 @@ mod tests {
|
||||||
let repo = MockRepository::<User>::new();
|
let repo = MockRepository::<User>::new();
|
||||||
let service = Service::new(repo);
|
let service = Service::new(repo);
|
||||||
|
|
||||||
let update = UpdateUser {
|
let update = UpdateUser::new(Some("new_username".to_string()), None).unwrap();
|
||||||
username: Some("new_username".to_string()),
|
|
||||||
email: None,
|
|
||||||
};
|
|
||||||
|
|
||||||
let result = service.update(Uuid::new_v4(), update).await;
|
let result = service.update(Uuid::new_v4(), update).await;
|
||||||
assert!(matches!(result, Err(ApplicationError::Domain(domain::DomainError::NotFound(_)))));
|
assert!(matches!(result, Err(ApplicationError::Domain(domain::DomainError::NotFound(_)))));
|
||||||
|
|
|
@ -123,7 +123,7 @@ impl Cli {
|
||||||
match self.command {
|
match self.command {
|
||||||
Some(Commands::User { command }) => match command {
|
Some(Commands::User { command }) => match command {
|
||||||
UserCommands::Create { username, email } => {
|
UserCommands::Create { username, email } => {
|
||||||
let user = user_service.create(CreateUser { username, email }).await?;
|
let user = user_service.create(CreateUser::new(username, email)?).await?;
|
||||||
println!("Created user: {:?}", user);
|
println!("Created user: {:?}", user);
|
||||||
}
|
}
|
||||||
UserCommands::List => {
|
UserCommands::List => {
|
||||||
|
@ -135,7 +135,7 @@ impl Cli {
|
||||||
println!("User: {:?}", user);
|
println!("User: {:?}", user);
|
||||||
}
|
}
|
||||||
UserCommands::Update { id, username, email } => {
|
UserCommands::Update { id, username, email } => {
|
||||||
let update = UpdateUser { username, email };
|
let update = UpdateUser::new(username, email)?;
|
||||||
let user = user_service.update(id, update).await?;
|
let user = user_service.update(id, update).await?;
|
||||||
println!("Updated user: {:?}", user);
|
println!("Updated user: {:?}", user);
|
||||||
}
|
}
|
||||||
|
@ -146,7 +146,7 @@ impl Cli {
|
||||||
},
|
},
|
||||||
Some(Commands::Product { command }) => match command {
|
Some(Commands::Product { command }) => match command {
|
||||||
ProductCommands::Create { name, description } => {
|
ProductCommands::Create { name, description } => {
|
||||||
let product = product_service.create(CreateProduct { name, description }).await?;
|
let product = product_service.create(CreateProduct::new(name, description)?).await?;
|
||||||
println!("Created product: {:?}", product);
|
println!("Created product: {:?}", product);
|
||||||
}
|
}
|
||||||
ProductCommands::List => {
|
ProductCommands::List => {
|
||||||
|
@ -158,7 +158,7 @@ impl Cli {
|
||||||
println!("Product: {:?}", product);
|
println!("Product: {:?}", product);
|
||||||
}
|
}
|
||||||
ProductCommands::Update { id, name, description } => {
|
ProductCommands::Update { id, name, description } => {
|
||||||
let update = UpdateProduct { name, description };
|
let update = UpdateProduct::new(name, description)?;
|
||||||
let product = product_service.update(id, update).await?;
|
let product = product_service.update(id, update).await?;
|
||||||
println!("Updated product: {:?}", product);
|
println!("Updated product: {:?}", product);
|
||||||
}
|
}
|
||||||
|
@ -1074,7 +1074,7 @@ mod tests {
|
||||||
let product_service = MockProductService::new();
|
let product_service = MockProductService::new();
|
||||||
|
|
||||||
let result = cli.run(user_service, product_service).await;
|
let result = cli.run(user_service, product_service).await;
|
||||||
assert!(result.is_ok()); // Should succeed even with empty strings
|
assert!(result.is_err()); // Should fail due to empty username validation
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Tests CLI with empty strings in product creation.
|
/// Tests CLI with empty strings in product creation.
|
||||||
|
@ -1093,7 +1093,7 @@ mod tests {
|
||||||
let product_service = MockProductService::new();
|
let product_service = MockProductService::new();
|
||||||
|
|
||||||
let result = cli.run(user_service, product_service).await;
|
let result = cli.run(user_service, product_service).await;
|
||||||
assert!(result.is_ok()); // Should succeed even with empty strings
|
assert!(result.is_err()); // Should fail due to empty product name validation
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Tests CLI with very long strings.
|
/// Tests CLI with very long strings.
|
||||||
|
|
|
@ -69,24 +69,64 @@ pub struct CreateUser {
|
||||||
pub email: String,
|
pub email: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl CreateUser {
|
||||||
|
pub fn new(username: String, email: String) -> Result<Self> {
|
||||||
|
if username.trim().is_empty() {
|
||||||
|
return Err(DomainError::InvalidInput("Username cannot be empty".to_string()));
|
||||||
|
}
|
||||||
|
Ok(Self { username, email })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
pub struct UpdateUser {
|
pub struct UpdateUser {
|
||||||
pub username: Option<String>,
|
pub username: Option<String>,
|
||||||
pub email: Option<String>,
|
pub email: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl UpdateUser {
|
||||||
|
pub fn new(username: Option<String>, email: Option<String>) -> Result<Self> {
|
||||||
|
if let Some(ref username) = username {
|
||||||
|
if username.trim().is_empty() {
|
||||||
|
return Err(DomainError::InvalidInput("Username cannot be empty".to_string()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(Self { username, email })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
pub struct CreateProduct {
|
pub struct CreateProduct {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub description: String,
|
pub description: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl CreateProduct {
|
||||||
|
pub fn new(name: String, description: String) -> Result<Self> {
|
||||||
|
if name.trim().is_empty() {
|
||||||
|
return Err(DomainError::InvalidInput("Product name cannot be empty".to_string()));
|
||||||
|
}
|
||||||
|
Ok(Self { name, description })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
pub struct UpdateProduct {
|
pub struct UpdateProduct {
|
||||||
pub name: Option<String>,
|
pub name: Option<String>,
|
||||||
pub description: Option<String>,
|
pub description: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl UpdateProduct {
|
||||||
|
pub fn new(name: Option<String>, description: Option<String>) -> Result<Self> {
|
||||||
|
if let Some(ref name) = name {
|
||||||
|
if name.trim().is_empty() {
|
||||||
|
return Err(DomainError::InvalidInput("Product name cannot be empty".to_string()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(Self { name, description })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub trait Repository<T, Create, Update>: Send + Sync
|
pub trait Repository<T, Create, Update>: Send + Sync
|
||||||
where
|
where
|
||||||
T: Send,
|
T: Send,
|
||||||
|
@ -124,25 +164,61 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_create_user_validation() {
|
fn test_create_user_validation() {
|
||||||
let create_user = CreateUser {
|
let create_user = CreateUser::new("test_user".to_string(), "test@example.com".to_string()).unwrap();
|
||||||
username: "test_user".to_string(),
|
|
||||||
email: "test@example.com".to_string(),
|
|
||||||
};
|
|
||||||
|
|
||||||
assert_eq!(create_user.username, "test_user");
|
assert_eq!(create_user.username, "test_user");
|
||||||
assert_eq!(create_user.email, "test@example.com");
|
assert_eq!(create_user.email, "test@example.com");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_create_user_empty_username() {
|
||||||
|
let result = CreateUser::new("".to_string(), "test@example.com".to_string());
|
||||||
|
assert!(result.is_err());
|
||||||
|
assert!(matches!(result.unwrap_err(), DomainError::InvalidInput(_)));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_create_user_whitespace_username() {
|
||||||
|
let result = CreateUser::new(" ".to_string(), "test@example.com".to_string());
|
||||||
|
assert!(result.is_err());
|
||||||
|
assert!(matches!(result.unwrap_err(), DomainError::InvalidInput(_)));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_create_user_empty_email() {
|
||||||
|
let create_user = CreateUser::new("test_user".to_string(), "".to_string()).unwrap();
|
||||||
|
assert_eq!(create_user.username, "test_user");
|
||||||
|
assert_eq!(create_user.email, "");
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_update_user_partial() {
|
fn test_update_user_partial() {
|
||||||
let update_user = UpdateUser {
|
let update_user = UpdateUser::new(Some("new_username".to_string()), None).unwrap();
|
||||||
username: Some("new_username".to_string()),
|
|
||||||
email: None,
|
|
||||||
};
|
|
||||||
|
|
||||||
assert_eq!(update_user.username, Some("new_username".to_string()));
|
assert_eq!(update_user.username, Some("new_username".to_string()));
|
||||||
assert_eq!(update_user.email, None);
|
assert_eq!(update_user.email, None);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_update_user_empty_username() {
|
||||||
|
let result = UpdateUser::new(Some("".to_string()), None);
|
||||||
|
assert!(result.is_err());
|
||||||
|
assert!(matches!(result.unwrap_err(), DomainError::InvalidInput(_)));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_update_user_whitespace_username() {
|
||||||
|
let result = UpdateUser::new(Some(" ".to_string()), None);
|
||||||
|
assert!(result.is_err());
|
||||||
|
assert!(matches!(result.unwrap_err(), DomainError::InvalidInput(_)));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_update_user_empty_email() {
|
||||||
|
let update_user = UpdateUser::new(None, Some("".to_string())).unwrap();
|
||||||
|
assert_eq!(update_user.username, None);
|
||||||
|
assert_eq!(update_user.email, Some("".to_string()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mod product_tests {
|
mod product_tests {
|
||||||
|
@ -164,25 +240,59 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_create_product_validation() {
|
fn test_create_product_validation() {
|
||||||
let create_product = CreateProduct {
|
let create_product = CreateProduct::new("Test Product".to_string(), "Test Description".to_string()).unwrap();
|
||||||
name: "Test Product".to_string(),
|
|
||||||
description: "Test Description".to_string(),
|
|
||||||
};
|
|
||||||
|
|
||||||
assert_eq!(create_product.name, "Test Product");
|
assert_eq!(create_product.name, "Test Product");
|
||||||
assert_eq!(create_product.description, "Test Description");
|
assert_eq!(create_product.description, "Test Description");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_update_product_partial() {
|
fn test_create_product_empty_name() {
|
||||||
let update_product = UpdateProduct {
|
let result = CreateProduct::new("".to_string(), "desc".to_string());
|
||||||
name: Some("New Product Name".to_string()),
|
assert!(result.is_err());
|
||||||
description: None,
|
assert!(matches!(result.unwrap_err(), DomainError::InvalidInput(_)));
|
||||||
};
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_create_product_whitespace_name() {
|
||||||
|
let result = CreateProduct::new(" ".to_string(), "desc".to_string());
|
||||||
|
assert!(result.is_err());
|
||||||
|
assert!(matches!(result.unwrap_err(), DomainError::InvalidInput(_)));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_create_product_empty_description() {
|
||||||
|
let create_product = CreateProduct::new("Test Product".to_string(), "".to_string()).unwrap();
|
||||||
|
assert_eq!(create_product.name, "Test Product");
|
||||||
|
assert_eq!(create_product.description, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_update_product_partial() {
|
||||||
|
let update_product = UpdateProduct::new(Some("New Product Name".to_string()), None).unwrap();
|
||||||
assert_eq!(update_product.name, Some("New Product Name".to_string()));
|
assert_eq!(update_product.name, Some("New Product Name".to_string()));
|
||||||
assert_eq!(update_product.description, None);
|
assert_eq!(update_product.description, None);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_update_product_empty_name() {
|
||||||
|
let result = UpdateProduct::new(Some("".to_string()), None);
|
||||||
|
assert!(result.is_err());
|
||||||
|
assert!(matches!(result.unwrap_err(), DomainError::InvalidInput(_)));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_update_product_whitespace_name() {
|
||||||
|
let result = UpdateProduct::new(Some(" ".to_string()), None);
|
||||||
|
assert!(result.is_err());
|
||||||
|
assert!(matches!(result.unwrap_err(), DomainError::InvalidInput(_)));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_update_product_empty_description() {
|
||||||
|
let update_product = UpdateProduct::new(None, Some("".to_string())).unwrap();
|
||||||
|
assert_eq!(update_product.name, None);
|
||||||
|
assert_eq!(update_product.description, Some("".to_string()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mod domain_error_tests {
|
mod domain_error_tests {
|
||||||
|
@ -229,10 +339,7 @@ mod tests {
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_repository_create() {
|
async fn test_repository_create() {
|
||||||
let repo = MockRepository::<User>::new();
|
let repo = MockRepository::<User>::new();
|
||||||
let create_user = CreateUser {
|
let create_user = CreateUser::new("test_user".to_string(), "test@example.com".to_string()).unwrap();
|
||||||
username: "test_user".to_string(),
|
|
||||||
email: "test@example.com".to_string(),
|
|
||||||
};
|
|
||||||
|
|
||||||
let user = User {
|
let user = User {
|
||||||
id: Uuid::new_v4(),
|
id: Uuid::new_v4(),
|
||||||
|
|
|
@ -346,20 +346,47 @@ async fn test_cli_edge_cases() -> Result<()> {
|
||||||
let user_service = Service::new(user_repo);
|
let user_service = Service::new(user_repo);
|
||||||
let product_service = Service::new(product_repo);
|
let product_service = Service::new(product_repo);
|
||||||
|
|
||||||
// Test empty strings (currently allowed by domain layer)
|
// Test empty username (should fail validation)
|
||||||
let cli = Cli::parse_from(&[
|
let cli = Cli::parse_from(&[
|
||||||
"cli", "user", "create", "--username", "", "--email", ""
|
"cli", "user", "create", "--username", "", "--email", "test@example.com"
|
||||||
]);
|
]);
|
||||||
let _result = cli.run(user_service.clone(), product_service.clone()).await;
|
let result = cli.run(user_service.clone(), product_service.clone()).await;
|
||||||
// Note: Empty strings are currently allowed by the domain layer
|
assert!(result.is_err());
|
||||||
// This test documents the current behavior
|
|
||||||
|
|
||||||
|
// Test whitespace username (should fail validation)
|
||||||
|
let cli = Cli::parse_from(&[
|
||||||
|
"cli", "user", "create", "--username", " ", "--email", "test@example.com"
|
||||||
|
]);
|
||||||
|
let result = cli.run(user_service.clone(), product_service.clone()).await;
|
||||||
|
assert!(result.is_err());
|
||||||
|
|
||||||
|
// Test empty email (should be allowed)
|
||||||
|
let cli = Cli::parse_from(&[
|
||||||
|
"cli", "user", "create", "--username", "testuser", "--email", ""
|
||||||
|
]);
|
||||||
|
let result = cli.run(user_service.clone(), product_service.clone()).await;
|
||||||
|
assert!(result.is_ok());
|
||||||
|
|
||||||
|
// Test empty product name (should fail validation)
|
||||||
let cli = Cli::parse_from(&[
|
let cli = Cli::parse_from(&[
|
||||||
"cli", "product", "create", "--name", "", "--description", ""
|
"cli", "product", "create", "--name", "", "--description", ""
|
||||||
]);
|
]);
|
||||||
let _result = cli.run(user_service.clone(), product_service.clone()).await;
|
let result = cli.run(user_service.clone(), product_service.clone()).await;
|
||||||
// Note: Empty strings are currently allowed by the domain layer
|
assert!(result.is_err());
|
||||||
// This test documents the current behavior
|
|
||||||
|
// Test whitespace product name (should fail validation)
|
||||||
|
let cli = Cli::parse_from(&[
|
||||||
|
"cli", "product", "create", "--name", " ", "--description", "desc"
|
||||||
|
]);
|
||||||
|
let result = cli.run(user_service.clone(), product_service.clone()).await;
|
||||||
|
assert!(result.is_err());
|
||||||
|
|
||||||
|
// Test empty product description (should be allowed)
|
||||||
|
let cli = Cli::parse_from(&[
|
||||||
|
"cli", "product", "create", "--name", "Test Product", "--description", ""
|
||||||
|
]);
|
||||||
|
let result = cli.run(user_service.clone(), product_service.clone()).await;
|
||||||
|
assert!(result.is_ok());
|
||||||
|
|
||||||
// Test very long strings
|
// Test very long strings
|
||||||
let long_string = "a".repeat(1000);
|
let long_string = "a".repeat(1000);
|
||||||
|
|
|
@ -196,10 +196,7 @@ mod tests {
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_create_user() {
|
async fn test_create_user() {
|
||||||
let repo = InMemoryUserRepository::new();
|
let repo = InMemoryUserRepository::new();
|
||||||
let create_data = CreateUser {
|
let create_data = CreateUser::new("testuser".to_string(), "test@example.com".to_string()).unwrap();
|
||||||
username: "testuser".to_string(),
|
|
||||||
email: "test@example.com".to_string(),
|
|
||||||
};
|
|
||||||
|
|
||||||
let user = repo.create(create_data).await.unwrap();
|
let user = repo.create(create_data).await.unwrap();
|
||||||
|
|
||||||
|
@ -213,10 +210,7 @@ mod tests {
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_find_by_id_existing() {
|
async fn test_find_by_id_existing() {
|
||||||
let repo = InMemoryUserRepository::new();
|
let repo = InMemoryUserRepository::new();
|
||||||
let create_data = CreateUser {
|
let create_data = CreateUser::new("testuser".to_string(), "test@example.com".to_string()).unwrap();
|
||||||
username: "testuser".to_string(),
|
|
||||||
email: "test@example.com".to_string(),
|
|
||||||
};
|
|
||||||
|
|
||||||
let created_user = repo.create(create_data).await.unwrap();
|
let created_user = repo.create(create_data).await.unwrap();
|
||||||
let found_user = repo.find_by_id(created_user.id).await.unwrap();
|
let found_user = repo.find_by_id(created_user.id).await.unwrap();
|
||||||
|
@ -255,15 +249,9 @@ mod tests {
|
||||||
async fn test_find_all_with_users() {
|
async fn test_find_all_with_users() {
|
||||||
let repo = InMemoryUserRepository::new();
|
let repo = InMemoryUserRepository::new();
|
||||||
|
|
||||||
let user1 = repo.create(CreateUser {
|
let user1 = repo.create(CreateUser::new("user1".to_string(), "user1@example.com".to_string()).unwrap()).await.unwrap();
|
||||||
username: "user1".to_string(),
|
|
||||||
email: "user1@example.com".to_string(),
|
|
||||||
}).await.unwrap();
|
|
||||||
|
|
||||||
let user2 = repo.create(CreateUser {
|
let user2 = repo.create(CreateUser::new("user2".to_string(), "user2@example.com".to_string()).unwrap()).await.unwrap();
|
||||||
username: "user2".to_string(),
|
|
||||||
email: "user2@example.com".to_string(),
|
|
||||||
}).await.unwrap();
|
|
||||||
|
|
||||||
let users = repo.find_all().await.unwrap();
|
let users = repo.find_all().await.unwrap();
|
||||||
|
|
||||||
|
@ -275,18 +263,12 @@ mod tests {
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_update_user_existing() {
|
async fn test_update_user_existing() {
|
||||||
let repo = InMemoryUserRepository::new();
|
let repo = InMemoryUserRepository::new();
|
||||||
let user = repo.create(CreateUser {
|
let user = repo.create(CreateUser::new("olduser".to_string(), "old@example.com".to_string()).unwrap()).await.unwrap();
|
||||||
username: "olduser".to_string(),
|
|
||||||
email: "old@example.com".to_string(),
|
|
||||||
}).await.unwrap();
|
|
||||||
|
|
||||||
let original_updated_at = user.updated_at;
|
let original_updated_at = user.updated_at;
|
||||||
sleep(Duration::from_millis(1)).await; // Ensure timestamp difference
|
sleep(Duration::from_millis(1)).await; // Ensure timestamp difference
|
||||||
|
|
||||||
let update_data = UpdateUser {
|
let update_data = UpdateUser::new(Some("newuser".to_string()), Some("new@example.com".to_string())).unwrap();
|
||||||
username: Some("newuser".to_string()),
|
|
||||||
email: Some("new@example.com".to_string()),
|
|
||||||
};
|
|
||||||
|
|
||||||
let updated_user = repo.update(user.id, update_data).await.unwrap();
|
let updated_user = repo.update(user.id, update_data).await.unwrap();
|
||||||
|
|
||||||
|
@ -298,15 +280,9 @@ mod tests {
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_update_user_partial() {
|
async fn test_update_user_partial() {
|
||||||
let repo = InMemoryUserRepository::new();
|
let repo = InMemoryUserRepository::new();
|
||||||
let user = repo.create(CreateUser {
|
let user = repo.create(CreateUser::new("testuser".to_string(), "test@example.com".to_string()).unwrap()).await.unwrap();
|
||||||
username: "testuser".to_string(),
|
|
||||||
email: "test@example.com".to_string(),
|
|
||||||
}).await.unwrap();
|
|
||||||
|
|
||||||
let update_data = UpdateUser {
|
let update_data = UpdateUser::new(Some("newuser".to_string()), None).unwrap();
|
||||||
username: Some("newuser".to_string()),
|
|
||||||
email: None,
|
|
||||||
};
|
|
||||||
|
|
||||||
let updated_user = repo.update(user.id, update_data).await.unwrap();
|
let updated_user = repo.update(user.id, update_data).await.unwrap();
|
||||||
|
|
||||||
|
@ -318,10 +294,7 @@ mod tests {
|
||||||
async fn test_update_user_not_found() {
|
async fn test_update_user_not_found() {
|
||||||
let repo = InMemoryUserRepository::new();
|
let repo = InMemoryUserRepository::new();
|
||||||
let non_existent_id = Uuid::new_v4();
|
let non_existent_id = Uuid::new_v4();
|
||||||
let update_data = UpdateUser {
|
let update_data = UpdateUser::new(Some("newuser".to_string()), None).unwrap();
|
||||||
username: Some("newuser".to_string()),
|
|
||||||
email: None,
|
|
||||||
};
|
|
||||||
|
|
||||||
let result = repo.update(non_existent_id, update_data).await;
|
let result = repo.update(non_existent_id, update_data).await;
|
||||||
assert!(result.is_err());
|
assert!(result.is_err());
|
||||||
|
@ -338,10 +311,7 @@ mod tests {
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_delete_user_existing() {
|
async fn test_delete_user_existing() {
|
||||||
let repo = InMemoryUserRepository::new();
|
let repo = InMemoryUserRepository::new();
|
||||||
let user = repo.create(CreateUser {
|
let user = repo.create(CreateUser::new("testuser".to_string(), "test@example.com".to_string()).unwrap()).await.unwrap();
|
||||||
username: "testuser".to_string(),
|
|
||||||
email: "test@example.com".to_string(),
|
|
||||||
}).await.unwrap();
|
|
||||||
|
|
||||||
let result = repo.delete(user.id).await;
|
let result = repo.delete(user.id).await;
|
||||||
assert!(result.is_ok());
|
assert!(result.is_ok());
|
||||||
|
@ -377,10 +347,7 @@ mod tests {
|
||||||
let handles: Vec<_> = (0..10).map(|i| {
|
let handles: Vec<_> = (0..10).map(|i| {
|
||||||
let repo = repo_clone.clone();
|
let repo = repo_clone.clone();
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
repo.create(CreateUser {
|
repo.create(CreateUser::new(format!("user{}", i), format!("user{}@example.com", i)).unwrap()).await
|
||||||
username: format!("user{}", i),
|
|
||||||
email: format!("user{}@example.com", i),
|
|
||||||
}).await
|
|
||||||
})
|
})
|
||||||
}).collect();
|
}).collect();
|
||||||
|
|
||||||
|
@ -402,10 +369,7 @@ mod tests {
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_create_product() {
|
async fn test_create_product() {
|
||||||
let repo = InMemoryProductRepository::new();
|
let repo = InMemoryProductRepository::new();
|
||||||
let create_data = CreateProduct {
|
let create_data = CreateProduct::new("Test Product".to_string(), "Test Description".to_string()).unwrap();
|
||||||
name: "Test Product".to_string(),
|
|
||||||
description: "Test Description".to_string(),
|
|
||||||
};
|
|
||||||
|
|
||||||
let product = repo.create(create_data).await.unwrap();
|
let product = repo.create(create_data).await.unwrap();
|
||||||
|
|
||||||
|
@ -419,10 +383,7 @@ mod tests {
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_find_by_id_existing() {
|
async fn test_find_by_id_existing() {
|
||||||
let repo = InMemoryProductRepository::new();
|
let repo = InMemoryProductRepository::new();
|
||||||
let create_data = CreateProduct {
|
let create_data = CreateProduct::new("Test Product".to_string(), "Test Description".to_string()).unwrap();
|
||||||
name: "Test Product".to_string(),
|
|
||||||
description: "Test Description".to_string(),
|
|
||||||
};
|
|
||||||
|
|
||||||
let created_product = repo.create(create_data).await.unwrap();
|
let created_product = repo.create(create_data).await.unwrap();
|
||||||
let found_product = repo.find_by_id(created_product.id).await.unwrap();
|
let found_product = repo.find_by_id(created_product.id).await.unwrap();
|
||||||
|
@ -461,15 +422,9 @@ mod tests {
|
||||||
async fn test_find_all_with_products() {
|
async fn test_find_all_with_products() {
|
||||||
let repo = InMemoryProductRepository::new();
|
let repo = InMemoryProductRepository::new();
|
||||||
|
|
||||||
let product1 = repo.create(CreateProduct {
|
let product1 = repo.create(CreateProduct::new("Product 1".to_string(), "Description 1".to_string()).unwrap()).await.unwrap();
|
||||||
name: "Product 1".to_string(),
|
|
||||||
description: "Description 1".to_string(),
|
|
||||||
}).await.unwrap();
|
|
||||||
|
|
||||||
let product2 = repo.create(CreateProduct {
|
let product2 = repo.create(CreateProduct::new("Product 2".to_string(), "Description 2".to_string()).unwrap()).await.unwrap();
|
||||||
name: "Product 2".to_string(),
|
|
||||||
description: "Description 2".to_string(),
|
|
||||||
}).await.unwrap();
|
|
||||||
|
|
||||||
let products = repo.find_all().await.unwrap();
|
let products = repo.find_all().await.unwrap();
|
||||||
|
|
||||||
|
@ -481,18 +436,12 @@ mod tests {
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_update_product_existing() {
|
async fn test_update_product_existing() {
|
||||||
let repo = InMemoryProductRepository::new();
|
let repo = InMemoryProductRepository::new();
|
||||||
let product = repo.create(CreateProduct {
|
let product = repo.create(CreateProduct::new("Old Product".to_string(), "Old Description".to_string()).unwrap()).await.unwrap();
|
||||||
name: "Old Product".to_string(),
|
|
||||||
description: "Old Description".to_string(),
|
|
||||||
}).await.unwrap();
|
|
||||||
|
|
||||||
let original_updated_at = product.updated_at;
|
let original_updated_at = product.updated_at;
|
||||||
sleep(Duration::from_millis(1)).await; // Ensure timestamp difference
|
sleep(Duration::from_millis(1)).await; // Ensure timestamp difference
|
||||||
|
|
||||||
let update_data = UpdateProduct {
|
let update_data = UpdateProduct::new(Some("New Product".to_string()), Some("New Description".to_string())).unwrap();
|
||||||
name: Some("New Product".to_string()),
|
|
||||||
description: Some("New Description".to_string()),
|
|
||||||
};
|
|
||||||
|
|
||||||
let updated_product = repo.update(product.id, update_data).await.unwrap();
|
let updated_product = repo.update(product.id, update_data).await.unwrap();
|
||||||
|
|
||||||
|
@ -504,15 +453,9 @@ mod tests {
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_update_product_partial() {
|
async fn test_update_product_partial() {
|
||||||
let repo = InMemoryProductRepository::new();
|
let repo = InMemoryProductRepository::new();
|
||||||
let product = repo.create(CreateProduct {
|
let product = repo.create(CreateProduct::new("Test Product".to_string(), "Test Description".to_string()).unwrap()).await.unwrap();
|
||||||
name: "Test Product".to_string(),
|
|
||||||
description: "Test Description".to_string(),
|
|
||||||
}).await.unwrap();
|
|
||||||
|
|
||||||
let update_data = UpdateProduct {
|
let update_data = UpdateProduct::new(Some("New Product".to_string()), None).unwrap();
|
||||||
name: Some("New Product".to_string()),
|
|
||||||
description: None,
|
|
||||||
};
|
|
||||||
|
|
||||||
let updated_product = repo.update(product.id, update_data).await.unwrap();
|
let updated_product = repo.update(product.id, update_data).await.unwrap();
|
||||||
|
|
||||||
|
@ -524,10 +467,7 @@ mod tests {
|
||||||
async fn test_update_product_not_found() {
|
async fn test_update_product_not_found() {
|
||||||
let repo = InMemoryProductRepository::new();
|
let repo = InMemoryProductRepository::new();
|
||||||
let non_existent_id = Uuid::new_v4();
|
let non_existent_id = Uuid::new_v4();
|
||||||
let update_data = UpdateProduct {
|
let update_data = UpdateProduct::new(Some("New Product".to_string()), None).unwrap();
|
||||||
name: Some("New Product".to_string()),
|
|
||||||
description: None,
|
|
||||||
};
|
|
||||||
|
|
||||||
let result = repo.update(non_existent_id, update_data).await;
|
let result = repo.update(non_existent_id, update_data).await;
|
||||||
assert!(result.is_err());
|
assert!(result.is_err());
|
||||||
|
@ -544,10 +484,7 @@ mod tests {
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_delete_product_existing() {
|
async fn test_delete_product_existing() {
|
||||||
let repo = InMemoryProductRepository::new();
|
let repo = InMemoryProductRepository::new();
|
||||||
let product = repo.create(CreateProduct {
|
let product = repo.create(CreateProduct::new("Test Product".to_string(), "Test Description".to_string()).unwrap()).await.unwrap();
|
||||||
name: "Test Product".to_string(),
|
|
||||||
description: "Test Description".to_string(),
|
|
||||||
}).await.unwrap();
|
|
||||||
|
|
||||||
let result = repo.delete(product.id).await;
|
let result = repo.delete(product.id).await;
|
||||||
assert!(result.is_ok());
|
assert!(result.is_ok());
|
||||||
|
@ -583,10 +520,7 @@ mod tests {
|
||||||
let handles: Vec<_> = (0..10).map(|i| {
|
let handles: Vec<_> = (0..10).map(|i| {
|
||||||
let repo = repo_clone.clone();
|
let repo = repo_clone.clone();
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
repo.create(CreateProduct {
|
repo.create(CreateProduct::new(format!("Product {}", i), format!("Description {}", i)).unwrap()).await
|
||||||
name: format!("Product {}", i),
|
|
||||||
description: format!("Description {}", i),
|
|
||||||
}).await
|
|
||||||
})
|
})
|
||||||
}).collect();
|
}).collect();
|
||||||
|
|
||||||
|
@ -612,10 +546,7 @@ mod tests {
|
||||||
let service = MemoryUserService::new(repo);
|
let service = MemoryUserService::new(repo);
|
||||||
|
|
||||||
// Test create
|
// Test create
|
||||||
let user = service.create(CreateUser {
|
let user = service.create(CreateUser::new("testuser".to_string(), "test@example.com".to_string()).unwrap()).await.unwrap();
|
||||||
username: "testuser".to_string(),
|
|
||||||
email: "test@example.com".to_string(),
|
|
||||||
}).await.unwrap();
|
|
||||||
|
|
||||||
assert_eq!(user.username, "testuser");
|
assert_eq!(user.username, "testuser");
|
||||||
assert_eq!(user.email, "test@example.com");
|
assert_eq!(user.email, "test@example.com");
|
||||||
|
@ -625,10 +556,7 @@ mod tests {
|
||||||
assert_eq!(found_user.id, user.id);
|
assert_eq!(found_user.id, user.id);
|
||||||
|
|
||||||
// Test update
|
// Test update
|
||||||
let updated_user = service.update(user.id, UpdateUser {
|
let updated_user = service.update(user.id, UpdateUser::new(Some("newuser".to_string()), None).unwrap()).await.unwrap();
|
||||||
username: Some("newuser".to_string()),
|
|
||||||
email: None,
|
|
||||||
}).await.unwrap();
|
|
||||||
|
|
||||||
assert_eq!(updated_user.username, "newuser");
|
assert_eq!(updated_user.username, "newuser");
|
||||||
assert_eq!(updated_user.email, "test@example.com");
|
assert_eq!(updated_user.email, "test@example.com");
|
||||||
|
@ -652,10 +580,7 @@ mod tests {
|
||||||
let service = MemoryProductService::new(repo);
|
let service = MemoryProductService::new(repo);
|
||||||
|
|
||||||
// Test create
|
// Test create
|
||||||
let product = service.create(CreateProduct {
|
let product = service.create(CreateProduct::new("Test Product".to_string(), "Test Description".to_string()).unwrap()).await.unwrap();
|
||||||
name: "Test Product".to_string(),
|
|
||||||
description: "Test Description".to_string(),
|
|
||||||
}).await.unwrap();
|
|
||||||
|
|
||||||
assert_eq!(product.name, "Test Product");
|
assert_eq!(product.name, "Test Product");
|
||||||
assert_eq!(product.description, "Test Description");
|
assert_eq!(product.description, "Test Description");
|
||||||
|
@ -665,10 +590,7 @@ mod tests {
|
||||||
assert_eq!(found_product.id, product.id);
|
assert_eq!(found_product.id, product.id);
|
||||||
|
|
||||||
// Test update
|
// Test update
|
||||||
let updated_product = service.update(product.id, UpdateProduct {
|
let updated_product = service.update(product.id, UpdateProduct::new(Some("New Product".to_string()), None).unwrap()).await.unwrap();
|
||||||
name: Some("New Product".to_string()),
|
|
||||||
description: None,
|
|
||||||
}).await.unwrap();
|
|
||||||
|
|
||||||
assert_eq!(updated_product.name, "New Product");
|
assert_eq!(updated_product.name, "New Product");
|
||||||
assert_eq!(updated_product.description, "Test Description");
|
assert_eq!(updated_product.description, "Test Description");
|
||||||
|
@ -695,25 +617,16 @@ mod tests {
|
||||||
let repo = InMemoryUserRepository::new();
|
let repo = InMemoryUserRepository::new();
|
||||||
|
|
||||||
// Create multiple users
|
// Create multiple users
|
||||||
let user1 = repo.create(CreateUser {
|
let user1 = repo.create(CreateUser::new("user1".to_string(), "user1@example.com".to_string()).unwrap()).await.unwrap();
|
||||||
username: "user1".to_string(),
|
|
||||||
email: "user1@example.com".to_string(),
|
|
||||||
}).await.unwrap();
|
|
||||||
|
|
||||||
let user2 = repo.create(CreateUser {
|
let user2 = repo.create(CreateUser::new("user2".to_string(), "user2@example.com".to_string()).unwrap()).await.unwrap();
|
||||||
username: "user2".to_string(),
|
|
||||||
email: "user2@example.com".to_string(),
|
|
||||||
}).await.unwrap();
|
|
||||||
|
|
||||||
// Verify both users exist
|
// Verify both users exist
|
||||||
let users = repo.find_all().await.unwrap();
|
let users = repo.find_all().await.unwrap();
|
||||||
assert_eq!(users.len(), 2);
|
assert_eq!(users.len(), 2);
|
||||||
|
|
||||||
// Update one user
|
// Update one user
|
||||||
let updated_user1 = repo.update(user1.id, UpdateUser {
|
let updated_user1 = repo.update(user1.id, UpdateUser::new(Some("updated_user1".to_string()), None).unwrap()).await.unwrap();
|
||||||
username: Some("updated_user1".to_string()),
|
|
||||||
email: None,
|
|
||||||
}).await.unwrap();
|
|
||||||
|
|
||||||
assert_eq!(updated_user1.username, "updated_user1");
|
assert_eq!(updated_user1.username, "updated_user1");
|
||||||
assert_eq!(updated_user1.email, "user1@example.com");
|
assert_eq!(updated_user1.email, "user1@example.com");
|
||||||
|
@ -732,25 +645,16 @@ mod tests {
|
||||||
let repo = InMemoryProductRepository::new();
|
let repo = InMemoryProductRepository::new();
|
||||||
|
|
||||||
// Create multiple products
|
// Create multiple products
|
||||||
let product1 = repo.create(CreateProduct {
|
let product1 = repo.create(CreateProduct::new("Product 1".to_string(), "Description 1".to_string()).unwrap()).await.unwrap();
|
||||||
name: "Product 1".to_string(),
|
|
||||||
description: "Description 1".to_string(),
|
|
||||||
}).await.unwrap();
|
|
||||||
|
|
||||||
let product2 = repo.create(CreateProduct {
|
let product2 = repo.create(CreateProduct::new("Product 2".to_string(), "Description 2".to_string()).unwrap()).await.unwrap();
|
||||||
name: "Product 2".to_string(),
|
|
||||||
description: "Description 2".to_string(),
|
|
||||||
}).await.unwrap();
|
|
||||||
|
|
||||||
// Verify both products exist
|
// Verify both products exist
|
||||||
let products = repo.find_all().await.unwrap();
|
let products = repo.find_all().await.unwrap();
|
||||||
assert_eq!(products.len(), 2);
|
assert_eq!(products.len(), 2);
|
||||||
|
|
||||||
// Update one product
|
// Update one product
|
||||||
let updated_product1 = repo.update(product1.id, UpdateProduct {
|
let updated_product1 = repo.update(product1.id, UpdateProduct::new(Some("Updated Product 1".to_string()), None).unwrap()).await.unwrap();
|
||||||
name: Some("Updated Product 1".to_string()),
|
|
||||||
description: None,
|
|
||||||
}).await.unwrap();
|
|
||||||
|
|
||||||
assert_eq!(updated_product1.name, "Updated Product 1");
|
assert_eq!(updated_product1.name, "Updated Product 1");
|
||||||
assert_eq!(updated_product1.description, "Description 1");
|
assert_eq!(updated_product1.description, "Description 1");
|
||||||
|
|
|
@ -295,10 +295,7 @@ mod tests {
|
||||||
// Clean up at the beginning to ensure isolation
|
// Clean up at the beginning to ensure isolation
|
||||||
cleanup_test_data(&pool).await;
|
cleanup_test_data(&pool).await;
|
||||||
|
|
||||||
let create_data = CreateUser {
|
let create_data = CreateUser::new("testuser".to_string(), "test@example.com".to_string()).unwrap();
|
||||||
username: "testuser".to_string(),
|
|
||||||
email: "test@example.com".to_string(),
|
|
||||||
};
|
|
||||||
|
|
||||||
let result = repo.create(create_data).await;
|
let result = repo.create(create_data).await;
|
||||||
assert!(result.is_ok());
|
assert!(result.is_ok());
|
||||||
|
@ -322,20 +319,14 @@ mod tests {
|
||||||
// Clean up at the beginning to ensure isolation
|
// Clean up at the beginning to ensure isolation
|
||||||
cleanup_test_data(&pool).await;
|
cleanup_test_data(&pool).await;
|
||||||
|
|
||||||
let create_data = CreateUser {
|
let create_data = CreateUser::new("duplicate_user".to_string(), "test1@example.com".to_string()).unwrap();
|
||||||
username: "duplicate_user".to_string(),
|
|
||||||
email: "test1@example.com".to_string(),
|
|
||||||
};
|
|
||||||
|
|
||||||
// Create first user
|
// Create first user
|
||||||
let result1 = repo.create(create_data.clone()).await;
|
let result1 = repo.create(create_data.clone()).await;
|
||||||
assert!(result1.is_ok());
|
assert!(result1.is_ok());
|
||||||
|
|
||||||
// Try to create second user with same username
|
// Try to create second user with same username
|
||||||
let create_data2 = CreateUser {
|
let create_data2 = CreateUser::new("duplicate_user".to_string(), "test2@example.com".to_string()).unwrap();
|
||||||
username: "duplicate_user".to_string(),
|
|
||||||
email: "test2@example.com".to_string(),
|
|
||||||
};
|
|
||||||
let result2 = repo.create(create_data2).await;
|
let result2 = repo.create(create_data2).await;
|
||||||
assert!(result2.is_err());
|
assert!(result2.is_err());
|
||||||
|
|
||||||
|
@ -351,10 +342,7 @@ mod tests {
|
||||||
// Clean up at the beginning to ensure isolation
|
// Clean up at the beginning to ensure isolation
|
||||||
cleanup_test_data(&pool).await;
|
cleanup_test_data(&pool).await;
|
||||||
|
|
||||||
let create_data = CreateUser {
|
let create_data = CreateUser::new("finduser".to_string(), "find@example.com".to_string()).unwrap();
|
||||||
username: "finduser".to_string(),
|
|
||||||
email: "find@example.com".to_string(),
|
|
||||||
};
|
|
||||||
|
|
||||||
let created_user = repo.create(create_data).await.unwrap();
|
let created_user = repo.create(create_data).await.unwrap();
|
||||||
let found_user = repo.find_by_id(created_user.id).await;
|
let found_user = repo.find_by_id(created_user.id).await;
|
||||||
|
@ -404,15 +392,9 @@ mod tests {
|
||||||
let (username1, email1) = unique_test_data("user1");
|
let (username1, email1) = unique_test_data("user1");
|
||||||
let (username2, email2) = unique_test_data("user2");
|
let (username2, email2) = unique_test_data("user2");
|
||||||
|
|
||||||
let _user1 = repo.create(CreateUser {
|
let _user1 = repo.create(CreateUser::new(username1.clone(), email1).unwrap()).await.unwrap();
|
||||||
username: username1.clone(),
|
|
||||||
email: email1,
|
|
||||||
}).await.unwrap();
|
|
||||||
|
|
||||||
let _user2 = repo.create(CreateUser {
|
let _user2 = repo.create(CreateUser::new(username2.clone(), email2).unwrap()).await.unwrap();
|
||||||
username: username2.clone(),
|
|
||||||
email: email2,
|
|
||||||
}).await.unwrap();
|
|
||||||
|
|
||||||
let users = repo.find_all().await.unwrap();
|
let users = repo.find_all().await.unwrap();
|
||||||
assert_eq!(users.len(), 2);
|
assert_eq!(users.len(), 2);
|
||||||
|
@ -448,19 +430,13 @@ mod tests {
|
||||||
// Clean up at the beginning to ensure isolation
|
// Clean up at the beginning to ensure isolation
|
||||||
cleanup_test_data(&pool).await;
|
cleanup_test_data(&pool).await;
|
||||||
|
|
||||||
let create_data = CreateUser {
|
let create_data = CreateUser::new("updateuser".to_string(), "update@example.com".to_string()).unwrap();
|
||||||
username: "updateuser".to_string(),
|
|
||||||
email: "update@example.com".to_string(),
|
|
||||||
};
|
|
||||||
|
|
||||||
let user = repo.create(create_data).await.unwrap();
|
let user = repo.create(create_data).await.unwrap();
|
||||||
let original_updated_at = user.updated_at;
|
let original_updated_at = user.updated_at;
|
||||||
|
|
||||||
// Update username only
|
// Update username only
|
||||||
let update_data = UpdateUser {
|
let update_data = UpdateUser::new(Some("updateduser".to_string()), None).unwrap();
|
||||||
username: Some("updateduser".to_string()),
|
|
||||||
email: None,
|
|
||||||
};
|
|
||||||
|
|
||||||
let updated_user = repo.update(user.id, update_data).await.unwrap();
|
let updated_user = repo.update(user.id, update_data).await.unwrap();
|
||||||
assert_eq!(updated_user.username, "updateduser");
|
assert_eq!(updated_user.username, "updateduser");
|
||||||
|
@ -479,17 +455,11 @@ mod tests {
|
||||||
// Clean up at the beginning to ensure isolation
|
// Clean up at the beginning to ensure isolation
|
||||||
cleanup_test_data(&pool).await;
|
cleanup_test_data(&pool).await;
|
||||||
|
|
||||||
let create_data = CreateUser {
|
let create_data = CreateUser::new("emailuser".to_string(), "old@example.com".to_string()).unwrap();
|
||||||
username: "emailuser".to_string(),
|
|
||||||
email: "old@example.com".to_string(),
|
|
||||||
};
|
|
||||||
|
|
||||||
let user = repo.create(create_data).await.unwrap();
|
let user = repo.create(create_data).await.unwrap();
|
||||||
|
|
||||||
let update_data = UpdateUser {
|
let update_data = UpdateUser::new(None, Some("new@example.com".to_string())).unwrap();
|
||||||
username: None,
|
|
||||||
email: Some("new@example.com".to_string()),
|
|
||||||
};
|
|
||||||
|
|
||||||
let updated_user = repo.update(user.id, update_data).await.unwrap();
|
let updated_user = repo.update(user.id, update_data).await.unwrap();
|
||||||
assert_eq!(updated_user.username, "emailuser"); // Should remain unchanged
|
assert_eq!(updated_user.username, "emailuser"); // Should remain unchanged
|
||||||
|
@ -507,17 +477,11 @@ mod tests {
|
||||||
// Clean up at the beginning to ensure isolation
|
// Clean up at the beginning to ensure isolation
|
||||||
cleanup_test_data(&pool).await;
|
cleanup_test_data(&pool).await;
|
||||||
|
|
||||||
let create_data = CreateUser {
|
let create_data = CreateUser::new("bothuser".to_string(), "both@example.com".to_string()).unwrap();
|
||||||
username: "bothuser".to_string(),
|
|
||||||
email: "both@example.com".to_string(),
|
|
||||||
};
|
|
||||||
|
|
||||||
let user = repo.create(create_data).await.unwrap();
|
let user = repo.create(create_data).await.unwrap();
|
||||||
|
|
||||||
let update_data = UpdateUser {
|
let update_data = UpdateUser::new(Some("newbothuser".to_string()), Some("newboth@example.com".to_string())).unwrap();
|
||||||
username: Some("newbothuser".to_string()),
|
|
||||||
email: Some("newboth@example.com".to_string()),
|
|
||||||
};
|
|
||||||
|
|
||||||
let updated_user = repo.update(user.id, update_data).await.unwrap();
|
let updated_user = repo.update(user.id, update_data).await.unwrap();
|
||||||
assert_eq!(updated_user.username, "newbothuser");
|
assert_eq!(updated_user.username, "newbothuser");
|
||||||
|
@ -536,10 +500,7 @@ mod tests {
|
||||||
cleanup_test_data(&pool).await;
|
cleanup_test_data(&pool).await;
|
||||||
|
|
||||||
let nonexistent_id = Uuid::new_v4();
|
let nonexistent_id = Uuid::new_v4();
|
||||||
let update_data = UpdateUser {
|
let update_data = UpdateUser::new(Some("nonexistent".to_string()), None).unwrap();
|
||||||
username: Some("nonexistent".to_string()),
|
|
||||||
email: None,
|
|
||||||
};
|
|
||||||
|
|
||||||
let result = repo.update(nonexistent_id, update_data).await;
|
let result = repo.update(nonexistent_id, update_data).await;
|
||||||
assert!(result.is_err());
|
assert!(result.is_err());
|
||||||
|
@ -563,10 +524,7 @@ mod tests {
|
||||||
cleanup_test_data(&pool).await;
|
cleanup_test_data(&pool).await;
|
||||||
|
|
||||||
let (username, email) = unique_test_data("delete_user");
|
let (username, email) = unique_test_data("delete_user");
|
||||||
let create_data = CreateUser {
|
let create_data = CreateUser::new(username.clone(), email.clone()).unwrap();
|
||||||
username: username.clone(),
|
|
||||||
email: email.clone(),
|
|
||||||
};
|
|
||||||
|
|
||||||
let user = repo.create(create_data).await.unwrap();
|
let user = repo.create(create_data).await.unwrap();
|
||||||
let user_id = user.id;
|
let user_id = user.id;
|
||||||
|
@ -619,10 +577,7 @@ mod tests {
|
||||||
cleanup_test_data(&pool).await;
|
cleanup_test_data(&pool).await;
|
||||||
|
|
||||||
let (username, email) = unique_test_data("concurrent_user");
|
let (username, email) = unique_test_data("concurrent_user");
|
||||||
let create_data = CreateUser {
|
let create_data = CreateUser::new(username.clone(), email.clone()).unwrap();
|
||||||
username: username.clone(),
|
|
||||||
email: email.clone(),
|
|
||||||
};
|
|
||||||
|
|
||||||
// Create a user
|
// Create a user
|
||||||
let user = repo.create(create_data).await.unwrap();
|
let user = repo.create(create_data).await.unwrap();
|
||||||
|
@ -666,17 +621,13 @@ mod tests {
|
||||||
// Clean up at the beginning to ensure isolation
|
// Clean up at the beginning to ensure isolation
|
||||||
cleanup_test_data(&pool).await;
|
cleanup_test_data(&pool).await;
|
||||||
|
|
||||||
let (name, _) = unique_test_data("test_product");
|
let create_data = CreateProduct::new("Test Product".to_string(), "Test Description".to_string()).unwrap();
|
||||||
let create_data = CreateProduct {
|
|
||||||
name: name.clone(),
|
|
||||||
description: "Test Description".to_string(),
|
|
||||||
};
|
|
||||||
|
|
||||||
let result = repo.create(create_data).await;
|
let result = repo.create(create_data).await;
|
||||||
assert!(result.is_ok());
|
assert!(result.is_ok());
|
||||||
|
|
||||||
let product = result.unwrap();
|
let product = result.unwrap();
|
||||||
assert_eq!(product.name, name);
|
assert_eq!(product.name, "Test Product");
|
||||||
assert_eq!(product.description, "Test Description");
|
assert_eq!(product.description, "Test Description");
|
||||||
assert!(product.id != Uuid::nil());
|
assert!(product.id != Uuid::nil());
|
||||||
assert!(product.created_at <= Utc::now());
|
assert!(product.created_at <= Utc::now());
|
||||||
|
@ -694,10 +645,7 @@ mod tests {
|
||||||
// Clean up at the beginning to ensure isolation
|
// Clean up at the beginning to ensure isolation
|
||||||
cleanup_test_data(&pool).await;
|
cleanup_test_data(&pool).await;
|
||||||
|
|
||||||
let create_data = CreateProduct {
|
let create_data = CreateProduct::new("findproduct".to_string(), "finddesc".to_string()).unwrap();
|
||||||
name: "Find Product".to_string(),
|
|
||||||
description: "Find Description".to_string(),
|
|
||||||
};
|
|
||||||
|
|
||||||
let created_product = repo.create(create_data).await.unwrap();
|
let created_product = repo.create(create_data).await.unwrap();
|
||||||
let found_product = repo.find_by_id(created_product.id).await;
|
let found_product = repo.find_by_id(created_product.id).await;
|
||||||
|
@ -705,8 +653,8 @@ mod tests {
|
||||||
assert!(found_product.is_ok());
|
assert!(found_product.is_ok());
|
||||||
let product = found_product.unwrap();
|
let product = found_product.unwrap();
|
||||||
assert_eq!(product.id, created_product.id);
|
assert_eq!(product.id, created_product.id);
|
||||||
assert_eq!(product.name, "Find Product");
|
assert_eq!(product.name, "findproduct");
|
||||||
assert_eq!(product.description, "Find Description");
|
assert_eq!(product.description, "finddesc");
|
||||||
|
|
||||||
cleanup_test_data(&pool).await;
|
cleanup_test_data(&pool).await;
|
||||||
}
|
}
|
||||||
|
@ -744,18 +692,11 @@ mod tests {
|
||||||
cleanup_test_data(&pool).await;
|
cleanup_test_data(&pool).await;
|
||||||
|
|
||||||
// Create multiple products with unique names
|
// Create multiple products with unique names
|
||||||
let (name1, _) = unique_test_data("product1");
|
let (name1, desc1) = unique_test_data("product1");
|
||||||
let (name2, _) = unique_test_data("product2");
|
let (name2, desc2) = unique_test_data("product2");
|
||||||
|
|
||||||
let _product1 = repo.create(CreateProduct {
|
let _product1 = repo.create(CreateProduct::new(name1.clone(), desc1).unwrap()).await.unwrap();
|
||||||
name: name1.clone(),
|
let _product2 = repo.create(CreateProduct::new(name2.clone(), desc2).unwrap()).await.unwrap();
|
||||||
description: "Description 1".to_string(),
|
|
||||||
}).await.unwrap();
|
|
||||||
|
|
||||||
let _product2 = repo.create(CreateProduct {
|
|
||||||
name: name2.clone(),
|
|
||||||
description: "Description 2".to_string(),
|
|
||||||
}).await.unwrap();
|
|
||||||
|
|
||||||
let products = repo.find_all().await.unwrap();
|
let products = repo.find_all().await.unwrap();
|
||||||
assert_eq!(products.len(), 2);
|
assert_eq!(products.len(), 2);
|
||||||
|
@ -791,24 +732,17 @@ mod tests {
|
||||||
// Clean up at the beginning to ensure isolation
|
// Clean up at the beginning to ensure isolation
|
||||||
cleanup_test_data(&pool).await;
|
cleanup_test_data(&pool).await;
|
||||||
|
|
||||||
let (name, _) = unique_test_data("update_product");
|
let create_data = CreateProduct::new("updateproduct".to_string(), "updatedesc".to_string()).unwrap();
|
||||||
let create_data = CreateProduct {
|
|
||||||
name: name.clone(),
|
|
||||||
description: "Update Description".to_string(),
|
|
||||||
};
|
|
||||||
|
|
||||||
let product = repo.create(create_data).await.unwrap();
|
let product = repo.create(create_data).await.unwrap();
|
||||||
let original_updated_at = product.updated_at;
|
let original_updated_at = product.updated_at;
|
||||||
|
|
||||||
// Update name only
|
// Update name only
|
||||||
let update_data = UpdateProduct {
|
let update_data = UpdateProduct::new(Some("updatedproduct".to_string()), None).unwrap();
|
||||||
name: Some("Updated Product".to_string()),
|
|
||||||
description: None,
|
|
||||||
};
|
|
||||||
|
|
||||||
let updated_product = repo.update(product.id, update_data).await.unwrap();
|
let updated_product = repo.update(product.id, update_data).await.unwrap();
|
||||||
assert_eq!(updated_product.name, "Updated Product");
|
assert_eq!(updated_product.name, "updatedproduct");
|
||||||
assert_eq!(updated_product.description, "Update Description"); // Should remain unchanged
|
assert_eq!(updated_product.description, "updatedesc"); // Should remain unchanged
|
||||||
assert!(updated_product.updated_at > original_updated_at);
|
assert!(updated_product.updated_at > original_updated_at);
|
||||||
|
|
||||||
cleanup_test_data(&pool).await;
|
cleanup_test_data(&pool).await;
|
||||||
|
@ -971,10 +905,7 @@ mod tests {
|
||||||
cleanup_test_data(&pool).await;
|
cleanup_test_data(&pool).await;
|
||||||
|
|
||||||
let (username, email) = unique_test_data("service_user");
|
let (username, email) = unique_test_data("service_user");
|
||||||
let create_data = CreateUser {
|
let create_data = CreateUser::new(username.clone(), email.clone()).unwrap();
|
||||||
username: username.clone(),
|
|
||||||
email: email.clone(),
|
|
||||||
};
|
|
||||||
|
|
||||||
// Test create
|
// Test create
|
||||||
let user = service.create(create_data).await.unwrap();
|
let user = service.create(create_data).await.unwrap();
|
||||||
|
@ -991,10 +922,7 @@ mod tests {
|
||||||
|
|
||||||
// Test update
|
// Test update
|
||||||
let (new_username, _) = unique_test_data("updated_service_user");
|
let (new_username, _) = unique_test_data("updated_service_user");
|
||||||
let update_data = UpdateUser {
|
let update_data = UpdateUser::new(Some(new_username.clone()), None).unwrap();
|
||||||
username: Some(new_username.clone()),
|
|
||||||
email: None,
|
|
||||||
};
|
|
||||||
let updated_user = service.update(user.id, update_data).await.unwrap();
|
let updated_user = service.update(user.id, update_data).await.unwrap();
|
||||||
assert_eq!(updated_user.username, new_username);
|
assert_eq!(updated_user.username, new_username);
|
||||||
|
|
||||||
|
|
|
@ -212,11 +212,13 @@ where
|
||||||
cmd if cmd.starts_with("user create") => {
|
cmd if cmd.starts_with("user create") => {
|
||||||
match parse_user_create(cmd) {
|
match parse_user_create(cmd) {
|
||||||
Ok((username, email)) => {
|
Ok((username, email)) => {
|
||||||
match user_service_clone
|
match CreateUser::new(username, email) {
|
||||||
.create(CreateUser { username, email })
|
Ok(create_user) => {
|
||||||
.await
|
match user_service_clone.create(create_user).await {
|
||||||
{
|
Ok(user) => app.add_message(format!("Created user: {:?}", user)),
|
||||||
Ok(user) => app.add_message(format!("Created user: {:?}", user)),
|
Err(e) => app.add_message(format!("Error: {}", e)),
|
||||||
|
}
|
||||||
|
}
|
||||||
Err(e) => app.add_message(format!("Error: {}", e)),
|
Err(e) => app.add_message(format!("Error: {}", e)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -233,7 +235,13 @@ where
|
||||||
match parse_product_create(cmd) {
|
match parse_product_create(cmd) {
|
||||||
Ok((name, description)) => {
|
Ok((name, description)) => {
|
||||||
match product_service_clone
|
match product_service_clone
|
||||||
.create(CreateProduct { name, description })
|
.create(match CreateProduct::new(name, description) {
|
||||||
|
Ok(create_product) => create_product,
|
||||||
|
Err(e) => {
|
||||||
|
app.add_message(format!("Error: {}", e));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
})
|
||||||
.await
|
.await
|
||||||
{
|
{
|
||||||
Ok(product) => app.add_message(format!("Created product: {:?}", product)),
|
Ok(product) => app.add_message(format!("Created product: {:?}", product)),
|
||||||
|
|
Loading…
Add table
Reference in a new issue