Skip to content

Commit

Permalink
Merge pull request #4 from jdomenechb/2-adding-an-edit-option
Browse files Browse the repository at this point in the history
Add an "Edit client" option
  • Loading branch information
jdomenechb authored Jul 29, 2022
2 parents 4c527af + ebfd550 commit a18b94e
Show file tree
Hide file tree
Showing 4 changed files with 185 additions and 4 deletions.
105 changes: 104 additions & 1 deletion src/application/handlers.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
use crate::application::dtos::{ClientDto, DtoList};
use crate::application::requests::{CreateClientUseCaseRequest, GetClientUseCaseRequest};
use crate::application::requests::{
CreateClientUseCaseRequest, EditClientUseCaseRequest, GetClientUseCaseRequest,
};
use crate::domain::entities::Client;
use crate::domain::repositories::ClientRepository;
use std::rc::Rc;
Expand Down Expand Up @@ -67,9 +69,34 @@ impl GetAllClientsUseCaseHandler {
}
}

// -------------------------------------------------------------------------------------------------

pub struct EditClientUseCaseHandler {
client_repository: Rc<dyn ClientRepository>,
}

impl EditClientUseCaseHandler {
pub fn new(client_repository: Rc<dyn ClientRepository>) -> Self {
Self { client_repository }
}

pub fn execute(&self, request: EditClientUseCaseRequest) -> Result<(), String> {
let mut client = self.client_repository.by_id(request.client_id.as_str())?;
client.edit(request.name.as_str(), request.location.as_str());

self.client_repository.save(client);

Ok(())
}
}

// -------------------------------------------------------------------------------------------------

#[cfg(test)]
mod test {
use crate::application::dtos::ClientDto;
use crate::application::handlers::EditClientUseCaseHandler;
use crate::application::requests::EditClientUseCaseRequest;
use crate::domain::entities::Client;
use crate::domain::repositories::MockClientRepository;
use crate::{
Expand Down Expand Up @@ -172,4 +199,80 @@ mod test {

assert_eq!(client_dtos, result.0);
}

#[test]
fn edit_client_use_case_handler_execute_ok() {
let client: Client = Faker.fake();

let id = client.id.clone();
let id2 = id.clone();
let id3 = id.clone();

let new_name: String = Faker.fake();
let new_location: String = Faker.fake();

let expected_client = Client::new(id2.as_str(), new_name.as_str(), new_location.as_str());

let mut client_repository_mock = MockClientRepository::new();

client_repository_mock
.expect_by_id()
.withf(move |x: &str| x.eq(id.as_str()))
.times(1)
.return_const(Ok(client));

client_repository_mock
.expect_save()
.withf(move |x: &Client| x == &expected_client)
.times(1)
.return_const(());

let edit_client_use_case_handler =
EditClientUseCaseHandler::new(Rc::new(client_repository_mock));

let result = edit_client_use_case_handler.execute(EditClientUseCaseRequest::new(
id3.as_str(),
new_name.as_str(),
new_location.as_str(),
));

assert_eq!(Ok(()), result);
}

#[test]
fn edit_client_use_case_handler_execute_on_non_existing_client() {
let client: Client = Faker.fake();

let id = client.id.clone();
let id3 = id.clone();

let new_name: String = Faker.fake();
let new_location: String = Faker.fake();

let error_txt: String = Sentence(3..8).fake();

let mut client_repository_mock = MockClientRepository::new();

client_repository_mock
.expect_by_id()
.withf(move |x: &str| x.eq(id.as_str()))
.times(1)
.return_const(Err(error_txt.clone()));

client_repository_mock
.expect_save()
.times(0)
.return_const(());

let edit_client_use_case_handler =
EditClientUseCaseHandler::new(Rc::new(client_repository_mock));

let result = edit_client_use_case_handler.execute(EditClientUseCaseRequest::new(
id3.as_str(),
new_name.as_str(),
new_location.as_str(),
));

assert_eq!(Err(error_txt), result);
}
}
17 changes: 17 additions & 0 deletions src/application/requests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,20 @@ impl GetClientUseCaseRequest {
}
}
}

#[readonly::make]
pub struct EditClientUseCaseRequest {
pub client_id: String,
pub name: String,
pub location: String,
}

impl EditClientUseCaseRequest {
pub fn new(client_id: &str, name: &str, location: &str) -> Self {
Self {
client_id: client_id.to_string(),
name: name.to_string(),
location: location.to_string(),
}
}
}
25 changes: 24 additions & 1 deletion src/domain/entities.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use fake::{Dummy, Fake};

#[derive(Clone, Dummy)]
#[derive(Clone, Dummy, PartialEq, Eq)]
#[readonly::make]
pub struct Client {
pub id: String,
Expand All @@ -16,6 +16,11 @@ impl Client {
location: location.to_string(),
}
}

pub fn edit(&mut self, name: &str, location: &str) {
self.name = name.to_string();
self.location = location.to_string();
}
}

#[cfg(test)]
Expand All @@ -35,4 +40,22 @@ mod test {
assert_eq!(client.name, name.as_str());
assert_eq!(client.location, location.as_str());
}

#[test]
fn edit_client() {
let mut client: Client = Faker.fake();
let id = client.id.clone();

let new_name: String = Faker.fake();
let new_location: String = Faker.fake();

assert_ne!(client.name, new_name);
assert_ne!(client.location, new_location);

client.edit(new_name.as_str(), new_location.as_str());

assert_eq!(client.id, id);
assert_eq!(client.name, new_name);
assert_eq!(client.location, new_location);
}
}
42 changes: 40 additions & 2 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
extern crate core;
extern crate proc_macro;

use crate::application::handlers::EditClientUseCaseHandler;
use crate::application::requests::EditClientUseCaseRequest;
use crate::presentation::prompt::{ask_question, menu};
use application::handlers::{
CreateClientUseCaseHandler, GetAllClientsUseCaseHandler, GetClientUseCaseHandler,
Expand All @@ -20,14 +22,20 @@ fn main() {
let get_all_clients_use_case_handler =
GetAllClientsUseCaseHandler::new(client_repository.clone());
let get_client_use_case_handler = GetClientUseCaseHandler::new(client_repository.clone());
let create_client_use_case_handler = CreateClientUseCaseHandler::new(client_repository);
let create_client_use_case_handler = CreateClientUseCaseHandler::new(client_repository.clone());
let edit_client_use_case_handler = EditClientUseCaseHandler::new(client_repository);

while {
let option: u8 = menu(
std::io::stdin().lock(),
std::io::stdout(),
std::io::stderr(),
vec!["List all clients", "Read a client", "Create a client"],
vec![
"List all clients",
"Read a client",
"Create a client",
"Edit a client",
],
);

match option {
Expand Down Expand Up @@ -76,6 +84,36 @@ fn main() {
println!("\nClient created!");
}

4 => {
let client_id = ask_question(
std::io::stdin().lock(),
std::io::stdout(),
"Please, enter the ID of the client that you want to read:",
);

let client_name = ask_question(
std::io::stdin().lock(),
std::io::stdout(),
"\nEnter the new name of the client:",
);
let client_location = ask_question(
std::io::stdin().lock(),
std::io::stdout(),
"\nEnter the new location of the client:",
);

let result = edit_client_use_case_handler.execute(EditClientUseCaseRequest::new(
client_id.as_str(),
client_name.as_str(),
client_location.as_str(),
));

match result {
Ok(_) => println!("\nClient edited!"),
Err(e) => eprintln!("\nERROR: {}", e),
}
}

0 => println!("Exiting..."),
_ => println!("Invalid option"),
};
Expand Down

0 comments on commit a18b94e

Please sign in to comment.