Skip to content

Commit f66f4d0

Browse files
committed
fix: errors
- Handle division by zero - Handle decimals correctly - Add tests
1 parent 379d14c commit f66f4d0

File tree

3 files changed

+146
-8
lines changed

3 files changed

+146
-8
lines changed

src/app/calculation.rs

Lines changed: 129 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -34,12 +34,7 @@ impl Calculation {
3434

3535
pub fn on_number_press(&mut self, number: f32) {
3636
self.display.push_str(&number.to_string());
37-
let number = if number.fract() != 0.0 {
38-
format!("{number}.0")
39-
} else {
40-
number.to_string()
41-
};
42-
self.expression.push_str(&number);
37+
self.expression.push_str(&format!("{:.2}", number));
4338
}
4439

4540
pub fn on_operator_press(&mut self, operator: &Operator) -> Message {
@@ -66,10 +61,16 @@ impl Calculation {
6661

6762
pub fn on_equals_press(&mut self) -> Result<(), Box<dyn Error>> {
6863
let value = eval(&self.expression)?;
69-
log::info!("Expression -> {} = {value}", self.expression);
64+
log::info!("Expression -> {} = {:#?}", self.expression, value);
7065
self.result = match value {
7166
Value::Int(v) => v.to_string(),
72-
Value::Float(v) => v.to_string(),
67+
Value::Float(v) => {
68+
if v.is_infinite() {
69+
return Err(Box::new(crate::error::Error::DivisionByZero));
70+
} else {
71+
v.to_string()
72+
}
73+
}
7374
_ => String::new(),
7475
};
7576
Ok(())
@@ -96,3 +97,123 @@ impl Calculation {
9697
}
9798
}
9899
}
100+
101+
#[cfg(test)]
102+
mod tests {
103+
use super::*;
104+
105+
#[test]
106+
fn test_new_calculation() {
107+
let calc = Calculation::new();
108+
assert_eq!(calc.display, "");
109+
assert_eq!(calc.expression, "");
110+
assert_eq!(calc.result, "");
111+
}
112+
113+
#[test]
114+
fn test_basic_addition() {
115+
let mut calc = Calculation::new();
116+
calc.on_number_press(5.0);
117+
calc.on_operator_press(&Operator::Add);
118+
calc.on_number_press(3.0);
119+
calc.on_equals_press().unwrap();
120+
assert_eq!(calc.result, "8");
121+
}
122+
123+
#[test]
124+
fn test_basic_subtraction() {
125+
let mut calc = Calculation::new();
126+
calc.on_number_press(10.0);
127+
calc.on_operator_press(&Operator::Subtract);
128+
calc.on_number_press(4.0);
129+
calc.on_equals_press().unwrap();
130+
assert_eq!(calc.result, "6");
131+
}
132+
133+
#[test]
134+
fn test_basic_multiplication() {
135+
let mut calc = Calculation::new();
136+
calc.on_number_press(6.0);
137+
calc.on_operator_press(&Operator::Multiply);
138+
calc.on_number_press(7.0);
139+
calc.on_equals_press().unwrap();
140+
assert_eq!(calc.result, "42");
141+
}
142+
143+
#[test]
144+
fn test_basic_division() {
145+
let mut calc = Calculation::new();
146+
calc.on_number_press(15.0);
147+
calc.on_operator_press(&Operator::Divide);
148+
calc.on_number_press(3.0);
149+
calc.on_equals_press().unwrap();
150+
assert_eq!(calc.result, "5");
151+
}
152+
153+
#[test]
154+
fn test_modulus() {
155+
let mut calc = Calculation::new();
156+
calc.on_number_press(17.0);
157+
calc.on_operator_press(&Operator::Modulus);
158+
calc.on_number_press(5.0);
159+
calc.on_equals_press().unwrap();
160+
assert_eq!(calc.result, "2");
161+
}
162+
163+
#[test]
164+
fn test_decimal_calculation() {
165+
let mut calc = Calculation::new();
166+
calc.on_number_press(3.5);
167+
calc.on_operator_press(&Operator::Multiply);
168+
calc.on_number_press(2.0);
169+
calc.on_equals_press().unwrap();
170+
assert_eq!(calc.result, "7");
171+
}
172+
173+
#[test]
174+
fn test_clear() {
175+
let mut calc = Calculation::new();
176+
calc.on_number_press(5.0);
177+
calc.on_operator_press(&Operator::Add);
178+
calc.on_number_press(3.0);
179+
calc.on_operator_press(&Operator::Clear);
180+
assert_eq!(calc.display, "");
181+
assert_eq!(calc.expression, "");
182+
assert_eq!(calc.result, "");
183+
}
184+
185+
#[test]
186+
fn test_multiple_operations() {
187+
let mut calc = Calculation::new();
188+
calc.on_number_press(2.0);
189+
calc.on_operator_press(&Operator::Add);
190+
calc.on_number_press(3.0);
191+
calc.on_operator_press(&Operator::Multiply);
192+
calc.on_number_press(4.0);
193+
calc.on_equals_press().unwrap();
194+
log::info!("{}", calc.expression);
195+
assert_eq!(calc.result, "14");
196+
}
197+
198+
#[test]
199+
fn test_division_by_zero() {
200+
let mut calc = Calculation::new();
201+
calc.on_number_press(5.0);
202+
calc.on_operator_press(&Operator::Divide);
203+
calc.on_number_press(0.0);
204+
assert!(calc.on_equals_press().is_err());
205+
}
206+
207+
#[test]
208+
fn test_input_validation() {
209+
let mut calc = Calculation::new();
210+
211+
// Valid input
212+
calc.on_input("123+456".to_string());
213+
assert_eq!(calc.expression, "123+456");
214+
215+
// Invalid input (letters)
216+
calc.on_input("abc".to_string());
217+
assert_eq!(calc.expression, "123+456");
218+
}
219+
}

src/error.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
use std::fmt::Display;
2+
3+
#[derive(Debug)]
4+
pub enum Error {
5+
DivisionByZero,
6+
}
7+
8+
impl std::error::Error for Error {}
9+
10+
impl Display for Error {
11+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
12+
match self {
13+
Error::DivisionByZero => write!(f, "Attempted to divide by zero"),
14+
}
15+
}
16+
}

src/main.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
use app::Calculator;
44
mod app;
55
mod core;
6+
mod error;
67

78
use app::settings;
89

0 commit comments

Comments
 (0)