Skip to content

Commit

Permalink
100% coverage for domain
Browse files Browse the repository at this point in the history
  • Loading branch information
Alexandre Hanot committed Oct 10, 2023
1 parent 222fd23 commit 1dea777
Show file tree
Hide file tree
Showing 5 changed files with 128 additions and 107 deletions.
3 changes: 0 additions & 3 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 0 additions & 3 deletions domain/todolist/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,3 @@ version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
serde = { version = "1", features = ["derive"] }
102 changes: 5 additions & 97 deletions domain/todolist/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
use serde::{Deserialize, Serialize};

#[derive(Default, Serialize, Deserialize)]
#[derive(Default)]
pub struct TodoList {
pub tasks: Vec<Task>,
}

#[derive(Serialize, Deserialize)]
pub struct Task {
pub description: String,
pub done: bool,
Expand All @@ -17,9 +14,11 @@ pub enum Command {
}

#[derive(Debug)]
pub enum Error {}
pub enum Error {
TaskNotFound,
}

#[derive(Debug, PartialEq, Serialize, Deserialize)]
// #[derive(Debug, PartialEq, Serialize, Deserialize)]
pub enum Event {
TaskAdded { description: String },
TaskCompleted { index: usize },
Expand Down Expand Up @@ -50,94 +49,3 @@ impl TodoList {
self
}
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn test_add_task() {
let mut todo_list = TodoList::default();
let cmd = Command::AddTask {
description: "Test task".to_string(),
};
let events = todo_list.handle(cmd).unwrap();
todo_list.apply(events);

assert_eq!(todo_list.tasks.len(), 1);
assert_eq!(todo_list.tasks[0].description, "Test task");
assert_eq!(todo_list.tasks[0].done, false);
}

#[test]
fn test_complete_task() {
let mut todo_list = TodoList::default();
let cmd_add = Command::AddTask {
description: "Test task".to_string(),
};
let events_add = todo_list.handle(cmd_add).unwrap();
todo_list.apply(events_add);

let cmd_complete = Command::CompleteTask { index: 0 };
let events_complete = todo_list.handle(cmd_complete).unwrap();
todo_list.apply(events_complete);

assert_eq!(todo_list.tasks.len(), 1);
assert_eq!(todo_list.tasks[0].done, true);
}

#[test]
fn test_handle() {
let todo_list = TodoList::default();

// Testing AddTask command
match todo_list.handle(Command::AddTask {
description: "Test task".to_string(),
}) {
Ok(events) => {
assert_eq!(events.len(), 1);
if let Event::TaskAdded { description } = &events[0] {
assert_eq!(description, "Test task");
} else {
panic!("Expected TaskAdded event");
}
}
Err(_) => panic!("Expected Ok, got Err"),
}

// Testing CompleteTask command
match todo_list.handle(Command::CompleteTask { index: 0 }) {
Ok(events) => {
assert_eq!(events.len(), 1);
if let Event::TaskCompleted { index } = &events[0] {
assert_eq!(*index, 0);
} else {
panic!("Expected TaskCompleted event");
}
}
Err(_) => panic!("Expected Ok, got Err"),
}
}

#[test]
fn test_apply() {
let mut todo_list = TodoList::default();

let events = vec![
Event::TaskAdded {
description: "Task 1".to_string(),
},
Event::TaskAdded {
description: "Task 2".to_string(),
},
Event::TaskCompleted { index: 0 },
];
todo_list.apply(events);

assert_eq!(todo_list.tasks.len(), 2);
assert_eq!(todo_list.tasks[0].description, "Task 1");
assert_eq!(todo_list.tasks[0].done, true);
assert_eq!(todo_list.tasks[1].description, "Task 2");
assert_eq!(todo_list.tasks[1].done, false);
}
}
94 changes: 94 additions & 0 deletions domain/todolist/tests/todolist.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
use todolist::*;

#[test]
fn test_add_task() {
let mut todo_list = TodoList::default();
let cmd = Command::AddTask {
description: "Test task".to_string(),
};
let events = todo_list.handle(cmd).unwrap();
todo_list.apply(events);

assert_eq!(todo_list.tasks.len(), 1);
assert_eq!(todo_list.tasks[0].description, "Test task");
assert_eq!(todo_list.tasks[0].done, false);
}

#[test]
fn test_complete_task() {
let mut todo_list = TodoList::default();
let cmd_add = Command::AddTask {
description: "Test task".to_string(),
};
let events_add = todo_list.handle(cmd_add).unwrap();
todo_list.apply(events_add);

let cmd_complete = Command::CompleteTask { index: 0 };
let events_complete = todo_list.handle(cmd_complete).unwrap();
todo_list.apply(events_complete);

assert_eq!(todo_list.tasks.len(), 1);
assert_eq!(todo_list.tasks[0].done, true);
}

#[test]
fn test_handle() {
let todo_list = TodoList::default();

// Testing AddTask command
match todo_list.handle(Command::AddTask {
description: "Test task".to_string(),
}) {
Ok(events) => {
assert_eq!(events.len(), 1);
if let Event::TaskAdded { description } = &events[0] {
assert_eq!(description, "Test task");
} else {
panic!("Expected TaskAdded event");
}
}
Err(_) => panic!("Expected Ok, got Err"),
}

// Testing CompleteTask command
match todo_list.handle(Command::CompleteTask { index: 0 }) {
Ok(events) => {
assert_eq!(events.len(), 1);
if let Event::TaskCompleted { index } = &events[0] {
assert_eq!(*index, 0);
} else {
panic!("Expected TaskCompleted event");
}
}
Err(_) => panic!("Expected Ok, got Err"),
}
}

#[test]
fn test_apply() {
let mut todo_list = TodoList::default();

let events = vec![
Event::TaskAdded {
description: "Task 1".to_string(),
},
Event::TaskAdded {
description: "Task 2".to_string(),
},
Event::TaskCompleted { index: 0 },
];
todo_list.apply(events);

assert_eq!(todo_list.tasks.len(), 2);
assert_eq!(todo_list.tasks[0].description, "Task 1");
assert_eq!(todo_list.tasks[0].done, true);
assert_eq!(todo_list.tasks[1].description, "Task 2");
assert_eq!(todo_list.tasks[1].done, false);
}

#[test]
fn test_debug_error() {
let error = Error::TaskNotFound;

assert_eq!(format!("{:?}", error), "TaskNotFound");
}
33 changes: 29 additions & 4 deletions infrastructure/local-storage/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use application::services::TodoListStore;
use application::todolist::{Event, TodoList};
use async_trait::async_trait;
use serde::{Deserialize, Serialize};
use web_sys::Storage;

fn get_local_storage() -> Storage {
Expand All @@ -19,12 +20,12 @@ impl TodoListStore for TodoListLocalStorage {
.get_item("todolist")
.unwrap()
.map(|json| {
let events: Vec<Event> = serde_json::from_str(&json).unwrap();
let events: Vec<EventDTO> = serde_json::from_str(&json).unwrap();
events
})
.unwrap_or_default();
let mut todolist = TodoList::default();
todolist.apply(events);
todolist.apply(events.into_iter().map(|e| e.into()).collect());
todolist
}

Expand All @@ -34,12 +35,36 @@ impl TodoListStore for TodoListLocalStorage {
.get_item("todolist")
.unwrap()
.map(|json| {
let events: Vec<Event> = serde_json::from_str(&json).unwrap();
let events: Vec<EventDTO> = serde_json::from_str(&json).unwrap();
events
})
.unwrap_or_default();
events.extend(new_events);
events.extend(new_events.into_iter().map(|e| e.into()));
let json = serde_json::to_string(&events).unwrap();
storage.set_item("todolist", &json).unwrap();
}
}

#[derive(Serialize, Deserialize)]
enum EventDTO {
TaskAdded { description: String },
TaskCompleted { index: usize },
}

impl From<Event> for EventDTO {
fn from(event: Event) -> Self {
match event {
Event::TaskAdded { description } => EventDTO::TaskAdded { description },
Event::TaskCompleted { index } => EventDTO::TaskCompleted { index },
}
}
}

impl From<EventDTO> for Event {
fn from(dto: EventDTO) -> Self {
match dto {
EventDTO::TaskAdded { description } => Event::TaskAdded { description },
EventDTO::TaskCompleted { index } => Event::TaskCompleted { index },
}
}
}

0 comments on commit 1dea777

Please sign in to comment.