Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Add functionality to update and complete todos w/ tests #13

Merged
merged 1 commit into from
Oct 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use diesel::prelude::*;
use diesel::SqliteConnection;
use rocket::local::blocking::Client;
use rocket::{self, routes};
use crate::routes::{get_todos, add_todo, delete_todo};
use crate::routes::{get_todos, add_todo, delete_todo, update_todo, complete_todo};
use std::fs;
use diesel::sql_query;
use diesel::r2d2::{self, ConnectionManager};
Expand All @@ -20,7 +20,7 @@ pub fn setup_rocket() -> Client {

let rocket = rocket::build()
.manage(pool)
.mount("/", routes![get_todos, add_todo, delete_todo]);
.mount("/", routes![get_todos, add_todo, delete_todo, update_todo, complete_todo]);
Client::tracked(rocket).expect("valid rocket instance")
}

Expand Down
2 changes: 1 addition & 1 deletion src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,5 @@ fn rocket() -> _ {
let pool = db::establish_connection();
rocket::build()
.manage(pool)
.mount("/", routes![routes::get_todos, routes::add_todo, routes::delete_todo])
.mount("/", routes![routes::get_todos, routes::add_todo, routes::delete_todo, routes::update_todo, routes::complete_todo])
}
42 changes: 41 additions & 1 deletion src/routes.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use rocket::http::Status;
use rocket::State;
use rocket::serde::{json::Json};
use rocket::serde::json::Json;
use crate::db::{TodoItem, NewTodoItem};
use crate::schema::todos;
use diesel::prelude::*;
Expand Down Expand Up @@ -44,3 +44,43 @@ pub fn delete_todo(pool: &State<DbPool>, id: i32) -> Result<&'static str, (Statu

Ok("Todo deleted successfully!")
}

// Update an existing to-do item
#[put("/todos/<id>", format = "json", data = "<updated_todo>")]
pub fn update_todo(pool: &State<DbPool>, id: i32, updated_todo: Json<NewTodoItem>) -> Result<&'static str, (Status, &'static str)> {
let mut connection = pool.get().map_err(|_| (Status::InternalServerError, "Failed to get connection from pool"))?;

// Get the existing todo item from the database
let target = todos::table.find(id);

// Create updated data based on existing and new values
let updated_data = NewTodoItem {
title: updated_todo.title,
completed: updated_todo.completed,
};

// Update the todo in the database
diesel::update(target)
.set((
todos::dsl::title.eq(updated_data.title),
todos::dsl::completed.eq(updated_data.completed),
))
.execute(&mut connection)
.map_err(|_| (Status::InternalServerError, "Failed to update todo"))?;

Ok("Todo updated successfully!")
}

// Mark a to-do item as completed
#[put("/todos/<id>/complete")]
pub fn complete_todo(pool: &State<DbPool>, id: i32) -> Result<&'static str, (Status, &'static str)> {
let mut connection = pool.get().map_err(|_| (Status::InternalServerError, "Failed to get connection from pool"))?;

// Update the completed status of the todo
diesel::update(todos::table.find(id))
.set(todos::dsl::completed.eq(true))
.execute(&mut connection)
.map_err(|_| (Status::InternalServerError, "Failed to complete todo"))?;

Ok("Todo marked as completed!")
}
50 changes: 50 additions & 0 deletions tests/complete_todo.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
use rocket::http::Status;
use dooly::{db::TodoItem, helpers::{cleanup_database, establish_connection, run_seed_script, setup_rocket}};
use serde_json::json;
use rocket::http::ContentType;

#[test]
fn test_complete_todo() {
cleanup_database(); // Clean up the database before starting the test
let mut connection = establish_connection();
run_seed_script(&mut connection); // Seed the database with initial data

let client = setup_rocket();

// Create a new todo item
let new_todo = json!({
"title": "Test Incomplete Todo",
"completed": false
});

let response = client.post("/todos")
.header(ContentType::JSON)
.body(new_todo.to_string())
.dispatch();

assert_eq!(response.status(), Status::Ok);
assert_eq!(response.into_string().unwrap(), "Todo added successfully!");

// Fetch the todo items to get the ID of the newly added todo
let response = client.get("/todos")
.dispatch();

assert_eq!(response.status(), Status::Ok);
let todos: Vec<TodoItem> = serde_json::from_str(&response.into_string().unwrap()).unwrap();
let todo_id = todos[0].id; // Assuming this is the only todo item

// Mark the todo item as completed
let response = client.put(format!("/todos/{}/complete", todo_id))
.dispatch();

assert_eq!(response.status(), Status::Ok);
assert_eq!(response.into_string().unwrap(), "Todo marked as completed!");

// Fetch the updated todo to verify the changes
let response = client.get("/todos")
.dispatch();

assert_eq!(response.status(), Status::Ok);
let todos: Vec<TodoItem> = serde_json::from_str(&response.into_string().unwrap()).unwrap();
assert_eq!(todos[0].completed, true);
}
50 changes: 50 additions & 0 deletions tests/update_todo.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
use rocket::http::Status;
use dooly::{db::TodoItem, helpers::{cleanup_database, establish_connection, run_seed_script, setup_rocket}};
use serde_json::json;
use rocket::http::ContentType;

#[test]
fn test_update_todo() {
cleanup_database(); // Clean up the database before starting the test
let mut connection = establish_connection();
run_seed_script(&mut connection); // Seed the database with initial data

let client = setup_rocket();

// Create a new todo item to update
let new_todo = json!({
"title": "Initial Todo",
"completed": false
});

let response = client.post("/todos")
.header(ContentType::JSON)
.body(new_todo.to_string())
.dispatch();

assert_eq!(response.status(), Status::Ok);
assert_eq!(response.into_string().unwrap(), "Todo added successfully!");

// Update the existing todo item
let updated_todo = json!({
"title": "Updated Todo Title",
"completed": true
});

let response = client.put("/todos/1")
.header(ContentType::JSON)
.body(updated_todo.to_string())
.dispatch();

assert_eq!(response.status(), Status::Ok);
assert_eq!(response.into_string().unwrap(), "Todo updated successfully!");

// Fetch the updated todo to verify the changes
let response = client.get("/todos")
.dispatch();

assert_eq!(response.status(), Status::Ok);
let todos: Vec<TodoItem> = serde_json::from_str(&response.into_string().unwrap()).unwrap();
assert_eq!(todos[0].title, "Updated Todo Title");
assert_eq!(todos[0].completed, true);
}
Loading