feat: adds some Navigator actions
This commit is contained in:
parent
5411e39548
commit
7ec23699a8
174
src/navigator.rs
174
src/navigator.rs
@ -1,39 +1,64 @@
|
||||
use anyhow::{anyhow, Result, Context, Ok};
|
||||
use anyhow::{anyhow, Context, Ok, Result};
|
||||
use std::rc::Rc;
|
||||
|
||||
use crate::{ui::{Page, HomePage, EpicDetail, StoryDetail, Prompts}, db::JiraDatabase, models::Action};
|
||||
use crate::{
|
||||
db::JiraDatabase,
|
||||
models::Action,
|
||||
ui::{EpicDetail, HomePage, Page, Prompts, StoryDetail},
|
||||
};
|
||||
|
||||
pub struct Navigator {
|
||||
pages: Vec<Box<dyn Page>>,
|
||||
prompts: Prompts,
|
||||
db: Rc<JiraDatabase>
|
||||
db: Rc<JiraDatabase>,
|
||||
}
|
||||
|
||||
impl Navigator {
|
||||
pub fn new(db: Rc<JiraDatabase>) -> Self {
|
||||
todo!()
|
||||
Self {
|
||||
pages: vec![],
|
||||
prompts: Prompts::new(),
|
||||
db,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_current_page(&self) -> Option<&Box<dyn Page>> {
|
||||
todo!() // this should always return the last element in the pages vector
|
||||
self.pages.last()
|
||||
}
|
||||
|
||||
pub fn handle_action(&mut self, action: Action) -> Result<()> {
|
||||
match action {
|
||||
Action::NavigateToEpicDetail { epic_id } => {
|
||||
todo!() // create a new EpicDetail instance and add it to the pages vector
|
||||
// create a new EpicDetail instance and add it to the pages vector
|
||||
self.pages.push(Box::new(EpicDetail {
|
||||
epic_id,
|
||||
db: Rc::clone(&self.db),
|
||||
}));
|
||||
}
|
||||
Action::NavigateToStoryDetail { epic_id, story_id } => {
|
||||
todo!() // create a new StoryDetail instance and add it to the pages vector
|
||||
// create a new StoryDetail instance and add it to the pages vector
|
||||
self.pages.push(Box::new(StoryDetail {
|
||||
epic_id,
|
||||
story_id,
|
||||
db: Rc::clone(&self.db),
|
||||
}));
|
||||
}
|
||||
Action::NavigateToPreviousPage => {
|
||||
todo!() // remove the last page from the pages vector
|
||||
// remove the last page from the pages vector
|
||||
let _ = self.pages.pop();
|
||||
}
|
||||
Action::CreateEpic => {
|
||||
todo!() // prompt the user to create a new epic and persist it in the database
|
||||
// prompt the user to create a new epic and persist it in the database
|
||||
self.db.create_epic((self.prompts.create_epic)());
|
||||
}
|
||||
Action::UpdateEpicStatus { epic_id } => {
|
||||
todo!() // prompt the user to update status and persist it in the database
|
||||
todo!(); // prompt the user to update status and persist it in the database
|
||||
// let status = (self.prompts.update_status)().(|| {
|
||||
// return Err(anyhow!("failed to update epic status")
|
||||
// .context(format!("invalid status given")));
|
||||
// });
|
||||
self.db
|
||||
.update_epic_status(epic_id, crate::models::Status::Open);
|
||||
}
|
||||
Action::DeleteEpic { epic_id } => {
|
||||
todo!() // prompt the user to delete the epic and persist it in the database
|
||||
@ -48,8 +73,9 @@ impl Navigator {
|
||||
todo!() // prompt the user to delete the story and persist it in the database
|
||||
}
|
||||
Action::Exit => {
|
||||
todo!() // remove all pages from the pages vector
|
||||
},
|
||||
// remove all pages from the pages vector
|
||||
self.pages.clear();
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
@ -68,12 +94,17 @@ impl Navigator {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::{db::test_utils::MockDB, models::{Epic, Status, Story}};
|
||||
use super::*;
|
||||
use crate::{
|
||||
db::test_utils::MockDB,
|
||||
models::{Epic, Status, Story},
|
||||
};
|
||||
|
||||
#[test]
|
||||
fn should_start_on_home_page() {
|
||||
let db = Rc::new(JiraDatabase { database: Box::new(MockDB::new()) });
|
||||
let db = Rc::new(JiraDatabase {
|
||||
database: Box::new(MockDB::new()),
|
||||
});
|
||||
let nav = Navigator::new(db);
|
||||
|
||||
assert_eq!(nav.get_page_count(), 1);
|
||||
@ -86,18 +117,25 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn handle_action_should_navigate_pages() {
|
||||
let db = Rc::new(JiraDatabase { database: Box::new(MockDB::new()) });
|
||||
let db = Rc::new(JiraDatabase {
|
||||
database: Box::new(MockDB::new()),
|
||||
});
|
||||
|
||||
let mut nav = Navigator::new(db);
|
||||
|
||||
nav.handle_action(Action::NavigateToEpicDetail { epic_id: 1 }).unwrap();
|
||||
|
||||
nav.handle_action(Action::NavigateToEpicDetail { epic_id: 1 })
|
||||
.unwrap();
|
||||
assert_eq!(nav.get_page_count(), 2);
|
||||
|
||||
let current_page = nav.get_current_page().unwrap();
|
||||
let epic_detail_page = current_page.as_any().downcast_ref::<EpicDetail>();
|
||||
assert_eq!(epic_detail_page.is_some(), true);
|
||||
|
||||
nav.handle_action(Action::NavigateToStoryDetail { epic_id: 1, story_id: 2 }).unwrap();
|
||||
nav.handle_action(Action::NavigateToStoryDetail {
|
||||
epic_id: 1,
|
||||
story_id: 2,
|
||||
})
|
||||
.unwrap();
|
||||
assert_eq!(nav.get_page_count(), 3);
|
||||
|
||||
let current_page = nav.get_current_page().unwrap();
|
||||
@ -127,12 +165,19 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn handle_action_should_clear_pages_on_exit() {
|
||||
let db = Rc::new(JiraDatabase { database: Box::new(MockDB::new()) });
|
||||
let db = Rc::new(JiraDatabase {
|
||||
database: Box::new(MockDB::new()),
|
||||
});
|
||||
|
||||
let mut nav = Navigator::new(db);
|
||||
|
||||
nav.handle_action(Action::NavigateToEpicDetail { epic_id: 1 }).unwrap();
|
||||
nav.handle_action(Action::NavigateToStoryDetail { epic_id: 1, story_id: 2 }).unwrap();
|
||||
|
||||
nav.handle_action(Action::NavigateToEpicDetail { epic_id: 1 })
|
||||
.unwrap();
|
||||
nav.handle_action(Action::NavigateToStoryDetail {
|
||||
epic_id: 1,
|
||||
story_id: 2,
|
||||
})
|
||||
.unwrap();
|
||||
nav.handle_action(Action::Exit).unwrap();
|
||||
|
||||
assert_eq!(nav.get_page_count(), 0);
|
||||
@ -140,7 +185,9 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn handle_action_should_handle_create_epic() {
|
||||
let db = Rc::new(JiraDatabase { database: Box::new(MockDB::new()) });
|
||||
let db = Rc::new(JiraDatabase {
|
||||
database: Box::new(MockDB::new()),
|
||||
});
|
||||
|
||||
let mut nav = Navigator::new(Rc::clone(&db));
|
||||
|
||||
@ -148,7 +195,7 @@ mod tests {
|
||||
prompts.create_epic = Box::new(|| Epic::new("name".to_owned(), "description".to_owned()));
|
||||
|
||||
nav.set_prompts(prompts);
|
||||
|
||||
|
||||
nav.handle_action(Action::CreateEpic).unwrap();
|
||||
|
||||
let db_state = db.read_db().unwrap();
|
||||
@ -161,8 +208,12 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn handle_action_should_handle_update_epic() {
|
||||
let db = Rc::new(JiraDatabase { database: Box::new(MockDB::new()) });
|
||||
let epic_id = db.create_epic(Epic::new("".to_owned(), "".to_owned())).unwrap();
|
||||
let db = Rc::new(JiraDatabase {
|
||||
database: Box::new(MockDB::new()),
|
||||
});
|
||||
let epic_id = db
|
||||
.create_epic(Epic::new("".to_owned(), "".to_owned()))
|
||||
.unwrap();
|
||||
|
||||
let mut nav = Navigator::new(Rc::clone(&db));
|
||||
|
||||
@ -170,17 +221,25 @@ mod tests {
|
||||
prompts.update_status = Box::new(|| Some(Status::InProgress));
|
||||
|
||||
nav.set_prompts(prompts);
|
||||
|
||||
nav.handle_action(Action::UpdateEpicStatus { epic_id }).unwrap();
|
||||
|
||||
nav.handle_action(Action::UpdateEpicStatus { epic_id })
|
||||
.unwrap();
|
||||
|
||||
let db_state = db.read_db().unwrap();
|
||||
assert_eq!(db_state.epics.get(&epic_id).unwrap().status, Status::InProgress);
|
||||
assert_eq!(
|
||||
db_state.epics.get(&epic_id).unwrap().status,
|
||||
Status::InProgress
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn handle_action_should_handle_delete_epic() {
|
||||
let db = Rc::new(JiraDatabase { database: Box::new(MockDB::new()) });
|
||||
let epic_id = db.create_epic(Epic::new("".to_owned(), "".to_owned())).unwrap();
|
||||
let db = Rc::new(JiraDatabase {
|
||||
database: Box::new(MockDB::new()),
|
||||
});
|
||||
let epic_id = db
|
||||
.create_epic(Epic::new("".to_owned(), "".to_owned()))
|
||||
.unwrap();
|
||||
|
||||
let mut nav = Navigator::new(Rc::clone(&db));
|
||||
|
||||
@ -188,7 +247,7 @@ mod tests {
|
||||
prompts.delete_epic = Box::new(|| true);
|
||||
|
||||
nav.set_prompts(prompts);
|
||||
|
||||
|
||||
nav.handle_action(Action::DeleteEpic { epic_id }).unwrap();
|
||||
|
||||
let db_state = db.read_db().unwrap();
|
||||
@ -197,8 +256,12 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn handle_action_should_handle_create_story() {
|
||||
let db = Rc::new(JiraDatabase { database: Box::new(MockDB::new()) });
|
||||
let epic_id = db.create_epic(Epic::new("".to_owned(), "".to_owned())).unwrap();
|
||||
let db = Rc::new(JiraDatabase {
|
||||
database: Box::new(MockDB::new()),
|
||||
});
|
||||
let epic_id = db
|
||||
.create_epic(Epic::new("".to_owned(), "".to_owned()))
|
||||
.unwrap();
|
||||
|
||||
let mut nav = Navigator::new(Rc::clone(&db));
|
||||
|
||||
@ -206,7 +269,7 @@ mod tests {
|
||||
prompts.create_story = Box::new(|| Story::new("name".to_owned(), "description".to_owned()));
|
||||
|
||||
nav.set_prompts(prompts);
|
||||
|
||||
|
||||
nav.handle_action(Action::CreateStory { epic_id }).unwrap();
|
||||
|
||||
let db_state = db.read_db().unwrap();
|
||||
@ -219,9 +282,15 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn handle_action_should_handle_update_story() {
|
||||
let db = Rc::new(JiraDatabase { database: Box::new(MockDB::new()) });
|
||||
let epic_id = db.create_epic(Epic::new("".to_owned(), "".to_owned())).unwrap();
|
||||
let story_id = db.create_story(Story::new("".to_owned(), "".to_owned()), epic_id).unwrap();
|
||||
let db = Rc::new(JiraDatabase {
|
||||
database: Box::new(MockDB::new()),
|
||||
});
|
||||
let epic_id = db
|
||||
.create_epic(Epic::new("".to_owned(), "".to_owned()))
|
||||
.unwrap();
|
||||
let story_id = db
|
||||
.create_story(Story::new("".to_owned(), "".to_owned()), epic_id)
|
||||
.unwrap();
|
||||
|
||||
let mut nav = Navigator::new(Rc::clone(&db));
|
||||
|
||||
@ -229,18 +298,28 @@ mod tests {
|
||||
prompts.update_status = Box::new(|| Some(Status::InProgress));
|
||||
|
||||
nav.set_prompts(prompts);
|
||||
|
||||
nav.handle_action(Action::UpdateStoryStatus { story_id }).unwrap();
|
||||
|
||||
nav.handle_action(Action::UpdateStoryStatus { story_id })
|
||||
.unwrap();
|
||||
|
||||
let db_state = db.read_db().unwrap();
|
||||
assert_eq!(db_state.stories.get(&story_id).unwrap().status, Status::InProgress);
|
||||
assert_eq!(
|
||||
db_state.stories.get(&story_id).unwrap().status,
|
||||
Status::InProgress
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn handle_action_should_handle_delete_story() {
|
||||
let db = Rc::new(JiraDatabase { database: Box::new(MockDB::new()) });
|
||||
let epic_id = db.create_epic(Epic::new("".to_owned(), "".to_owned())).unwrap();
|
||||
let story_id = db.create_story(Story::new("".to_owned(), "".to_owned()), epic_id).unwrap();
|
||||
let db = Rc::new(JiraDatabase {
|
||||
database: Box::new(MockDB::new()),
|
||||
});
|
||||
let epic_id = db
|
||||
.create_epic(Epic::new("".to_owned(), "".to_owned()))
|
||||
.unwrap();
|
||||
let story_id = db
|
||||
.create_story(Story::new("".to_owned(), "".to_owned()), epic_id)
|
||||
.unwrap();
|
||||
|
||||
let mut nav = Navigator::new(Rc::clone(&db));
|
||||
|
||||
@ -248,10 +327,11 @@ mod tests {
|
||||
prompts.delete_story = Box::new(|| true);
|
||||
|
||||
nav.set_prompts(prompts);
|
||||
|
||||
nav.handle_action(Action::DeleteStory { epic_id, story_id }).unwrap();
|
||||
|
||||
nav.handle_action(Action::DeleteStory { epic_id, story_id })
|
||||
.unwrap();
|
||||
|
||||
let db_state = db.read_db().unwrap();
|
||||
assert_eq!(db_state.stories.len(), 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user