aboutsummaryrefslogtreecommitdiff
path: root/budget/tests/budget.rs
blob: 4ed549cda21046aefd665c35ce0291acd4c290ad (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
use std::collections::HashMap;

use chrono::NaiveDate;

use budget::*;

#[test]
fn can_parse_account() -> Result<(), ParseError> {
	let should_be = Account {
		start_date: NaiveDate::from_ymd(2020, 10, 1),
		end_date: NaiveDate::from_ymd(2020, 10, 31),
		budget: 420.0,
		essential_categories: vec![
			String::from("products"),
			String::from("transport"),
			String::from("utilities"),
		],
		days: vec![
			Day {
				date: NaiveDate::from_ymd(2020, 10, 1),
				expenses: vec![
					Expense {
						name: String::from("Potato masher"),
						price: 3.81,
						qty: 1,
						shared: 1,
						recurring: false,
						category: Some(String::from("supplies")),
					},
					Expense {
						name: String::from("Bacon"),
						price: 3.33,
						qty: 1,
						shared: 3,
						recurring: false,
						category: Some(String::from("products")),
					},
					Expense {
						name: String::from("Yoghurt"),
						price: 1.24,
						qty: 2,
						shared: 2,
						recurring: false,
						category: Some(String::from("products")),
					},
					Expense {
						name: String::from("Onion"),
						price: 0.15,
						qty: 1,
						shared: 1,
						recurring: false,
						category: Some(String::from("products")),
					},
					Expense {
						name: String::from("Chicken"),
						price: 2.28,
						qty: 1,
						shared: 2,
						recurring: false,
						category: Some(String::from("products")),
					},
				],
			},
			Day {
				date: NaiveDate::from_ymd(2020, 10, 4),
				expenses: Vec::<Expense>::new(),
			},
			Day {
				date: NaiveDate::from_ymd(2020, 10, 2),
				expenses: vec![
					Expense {
						name: String::from("VPS"),
						price: 5.0,
						qty: 1,
						shared: 1,
						recurring: true,
						category: Some(String::from("utilities")),
					},
					Expense {
						name: String::from("Transport card"),
						price: 6.9,
						qty: 1,
						shared: 1,
						recurring: false,
						category: Some(String::from("transport")),
					},
				],
			},
		],
	};

	let actually_is = budget::parse_account("tests/test.toml")?;

	assert_eq!(actually_is, should_be);

	Ok(())
}

#[test]
fn can_calculate() -> Result<(), ParseError> {
	let mut should_be = Calculated {
		all_day_average: 5.6775,
		essential_day_average: 4.725,
		categories_day_average: HashMap::<String, f64>::new(),
		essential_subtotal: 18.9,
		categories_subtotal: HashMap::<String, f64>::new(),
		total: 22.71,
		balance: 397.29,
		total_owed: HashMap::<u32, f64>::new(),
		days_left: 69.9762219286658,
		days_left_essential: 84.08253968253969,
		last_day: NaiveDate::from_ymd(2020, 10, 04),
	};

	should_be
		.categories_day_average
		.insert("supplies".to_string(), 0.9525);
	should_be
		.categories_day_average
		.insert("products".to_string(), 1.75);
	should_be
		.categories_day_average
		.insert("transport".to_string(), 1.725);
	should_be
		.categories_day_average
		.insert("utilities".to_string(), 1.25);

	should_be
		.categories_subtotal
		.insert("supplies".to_string(), 3.81);
	should_be
		.categories_subtotal
		.insert("products".to_string(), 7.0);
	should_be
		.categories_subtotal
		.insert("transport".to_string(), 6.9);
	should_be
		.categories_subtotal
		.insert("utilities".to_string(), 5.0);

	should_be.total_owed.insert(2, 1.7599999999999998);
	should_be.total_owed.insert(3, 2.22);

	let account = budget::parse_account("tests/test.toml")?;
	let actually_is = budget::calculate(&account).unwrap();

	assert_eq!(actually_is, should_be);

	Ok(())
}