diff options
| author | Kevin Hoerr <kjhoerr@submelon.dev> | 2026-04-16 11:37:21 -0400 |
|---|---|---|
| committer | Kevin Hoerr <kjhoerr@submelon.dev> | 2026-04-16 11:37:21 -0400 |
| commit | 615d44041d35ee1a08ddc66423f67a9d48f53ae9 (patch) | |
| tree | 9720d6a192e0bae9c7393b8b99ff8ae401ec7f72 /src/app/mod.rs | |
| parent | 51623bc995c29937bb0a13d5b71ff908be8d1a1c (diff) | |
| download | equity-tracker-615d44041d35ee1a08ddc66423f67a9d48f53ae9.tar.gz equity-tracker-615d44041d35ee1a08ddc66423f67a9d48f53ae9.tar.bz2 equity-tracker-615d44041d35ee1a08ddc66423f67a9d48f53ae9.zip | |
Switch to distrobox as base for development
Diffstat (limited to 'src/app/mod.rs')
| -rw-r--r-- | src/app/mod.rs | 224 |
1 files changed, 224 insertions, 0 deletions
diff --git a/src/app/mod.rs b/src/app/mod.rs new file mode 100644 index 0000000..6003640 --- /dev/null +++ b/src/app/mod.rs @@ -0,0 +1,224 @@ +mod store; + +use store::{Context, Store}; +use miette::{Diagnostic, ErrReport, Result}; +use thiserror::Error; + +#[derive(Default)] +pub struct App { + context: Context, + error: Option<ErrReport>, + exit: bool, +} + +#[derive(Diagnostic, Debug, Error, PartialEq)] +#[error("An overflow error occurred")] +#[diagnostic()] +pub struct OverflowError { + #[help] + pub _msg: String, +} + +impl App { + + /// Build context in App and pass it forward + pub fn init_context(&mut self) -> Result<&mut Self> { + let store = self.context.unwrap_store(); + + store.init()?; + Ok(self) + } + + pub fn get_exit_status(&self) -> bool { + self.exit + } + + pub fn exit(&mut self) -> Result<()> { + self.exit = true; + Ok(()) + } + + pub fn decrement_counter(&mut self) -> Result<()> { + let store = self.context.unwrap_store(); + let count = store.get_counter()?; + + if count == 0 { + Err(OverflowError { + _msg: "Cannot count below 0".into(), + } + .into()) + } else { + store.set_counter(count - 1)?; + Ok(()) + } + } + + pub fn increment_counter(&mut self) -> Result<()> { + let store = self.context.unwrap_store(); + let count = store.get_counter()?; + + if count == u8::MAX { + Err(OverflowError { + _msg: "Cannot count above u8::MAX".into(), + } + .into()) + } else { + store.set_counter(count + 1)?; + Ok(()) + } + } + + pub fn display_counter(&self) -> String { + self.context + .get_store() + .get_counter() + .map(|u| u.to_string()) + .unwrap_or("Error".into()) + } + + pub fn set_error(&mut self, error: ErrReport) -> Result<()> { + self.error = Some(error); + Ok(()) + } + + pub fn get_error(&self) -> &Option<ErrReport> { + &self.error + } + + /// Clears any existing input error in the app state + pub fn clear_error(&mut self) -> Result<()> { + self.error = None; + Ok(()) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use store::ContextError; + + fn get_count(app: &App) -> Result<u8, ContextError> { + app.context.get_store().get_counter() + } + + #[test] + fn display_counter_inited() { + let mut app = App::default(); + assert!(app.init_context().is_ok()); + + let count = app.display_counter(); + + assert_eq!(count, "0"); + } + + #[test] + fn display_counter_noninited() { + let app = App::default(); + + let count = app.display_counter(); + + assert_eq!(count, "Error"); + } + + #[test] + fn increment_decrement() { + let mut app = App::default(); + assert!(app.init_context().is_ok()); + + let res = app.increment_counter(); + assert!(res.is_ok()); + assert_eq!(get_count(&app).unwrap(), 1); + + let res = app.decrement_counter(); + assert!(res.is_ok()); + assert_eq!(get_count(&app).unwrap(), 0); + } + + #[test] + fn increment_n() { + let mut app = App::default(); + assert!(app.init_context().is_ok()); + let n = 8; + + for i in 1..=n { + let res = app.increment_counter(); + assert!(res.is_ok()); + assert_eq!(get_count(&app).unwrap(), i); + } + assert_eq!(get_count(&app).unwrap(), n); + } + + #[test] + fn increment_n_decrement() { + let mut app = App::default(); + assert!(app.init_context().is_ok()); + let n = 8; + + for i in 1..=n { + let res = app.increment_counter(); + assert!(res.is_ok()); + assert_eq!(get_count(&app).unwrap(), i); + } + assert_eq!(get_count(&app).unwrap(), n); + + let res = app.decrement_counter(); + assert!(res.is_ok()); + assert_eq!(get_count(&app).unwrap(), n - 1); + } + + #[test] + fn exit() { + let mut app = App::default(); + assert!(app.init_context().is_ok()); + + let res = app.exit(); + + assert!(res.is_ok()); + assert!(app.exit); + } + + #[test] + fn decrement_counter_error() { + let mut app = App::default(); + assert!(app.init_context().is_ok()); + let res = app.decrement_counter(); + + assert!(res.is_err()); + let res_err = res.unwrap_err(); + let casted_val = res_err + .downcast_ref::<OverflowError>() + .expect("something bad occurred"); + + let expected_err_msg: String = "Cannot count below 0".into(); + assert_eq!(casted_val._msg, expected_err_msg); + assert_eq!( + *casted_val, + OverflowError { + _msg: expected_err_msg, + }, + ); + } + + #[test] + fn increment_counter_error() { + let mut app = App::default(); + assert!(app.init_context().is_ok()); + assert!(app.context.unwrap_store().set_counter(u8::MAX).is_ok()); + let res = app.increment_counter(); + + assert!(res.is_err()); + let res_err = res.unwrap_err(); + let casted_val = res_err + .downcast_ref::<OverflowError>() + .expect("something bad occurred"); + + let expected_err_msg: String = "Cannot count above u8::MAX".into(); + assert_eq!(casted_val._msg, expected_err_msg); + assert_eq!( + *casted_val, + OverflowError { + _msg: expected_err_msg, + }, + ); + } +} |
