forked from maybe-finance/maybe
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathvalue_group_test.rb
141 lines (111 loc) · 5.35 KB
/
value_group_test.rb
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
require "test_helper"
require "ostruct"
class ValueGroupTest < ActiveSupport::TestCase
setup do
# Level 1
@assets = ValueGroup.new("Assets", :usd)
# Level 2
@depositories = @assets.add_child_group("Depositories", :usd)
@other_assets = @assets.add_child_group("Other Assets", :usd)
# Level 3 (leaf/value nodes)
@checking_node = @depositories.add_value_node(OpenStruct.new({ name: "Checking", value: Money.new(5000) }), Money.new(5000))
@savings_node = @depositories.add_value_node(OpenStruct.new({ name: "Savings", value: Money.new(20000) }), Money.new(20000))
@collectable_node = @other_assets.add_value_node(OpenStruct.new({ name: "Collectable", value: Money.new(550) }), Money.new(550))
end
test "empty group works" do
group = ValueGroup.new("Root", :usd)
assert_equal "Root", group.name
assert_equal [], group.children
assert_equal 0, group.sum
assert_equal 0, group.avg
assert_equal 100, group.percent_of_total
assert_nil group.parent
end
test "group without value nodes has no value" do
assets = ValueGroup.new("Assets")
depositories = assets.add_child_group("Depositories")
assert_equal 0, assets.sum
assert_equal 0, depositories.sum
end
test "sum equals value at leaf level" do
assert_equal @checking_node.value, @checking_node.sum
assert_equal @savings_node.value, @savings_node.sum
assert_equal @collectable_node.value, @collectable_node.sum
end
test "value is nil at rollup levels" do
assert_not_equal @depositories.value, @depositories.sum
assert_nil @depositories.value
assert_nil @other_assets.value
end
test "generates list of value nodes regardless of level in hierarchy" do
assert_equal [ @checking_node, @savings_node, @collectable_node ], @assets.value_nodes
assert_equal [ @checking_node, @savings_node ], @depositories.value_nodes
assert_equal [ @collectable_node ], @other_assets.value_nodes
end
test "group with value nodes aggregates totals correctly" do
assert_equal Money.new(5000), @checking_node.sum
assert_equal Money.new(20000), @savings_node.sum
assert_equal Money.new(550), @collectable_node.sum
assert_equal Money.new(25000), @depositories.sum
assert_equal Money.new(550), @other_assets.sum
assert_equal Money.new(25550), @assets.sum
end
test "group averages leaf nodes" do
assert_equal Money.new(5000), @checking_node.avg
assert_equal Money.new(20000), @savings_node.avg
assert_equal Money.new(550), @collectable_node.avg
assert_in_delta 12500, @depositories.avg.amount, 0.01
assert_in_delta 550, @other_assets.avg.amount, 0.01
assert_in_delta 8516.67, @assets.avg.amount, 0.01
end
# Percentage of parent group (i.e. collectable is 100% of "Other Assets" group)
test "group calculates percent of parent total" do
assert_equal 100, @assets.percent_of_total
assert_in_delta 97.85, @depositories.percent_of_total, 0.1
assert_in_delta 2.15, @other_assets.percent_of_total, 0.1
assert_in_delta 80.0, @savings_node.percent_of_total, 0.1
assert_in_delta 20.0, @checking_node.percent_of_total, 0.1
assert_equal 100, @collectable_node.percent_of_total
end
test "handles unbalanced tree" do
vehicles = @assets.add_child_group("Vehicles")
# Since we didn't add any value nodes to vehicles, shouldn't affect rollups
assert_equal Money.new(25550), @assets.sum
end
test "can attach and aggregate time series" do
checking_series = TimeSeries.new([ { date: 1.day.ago.to_date, value: Money.new(4000) }, { date: Date.current, value: Money.new(5000) } ])
savings_series = TimeSeries.new([ { date: 1.day.ago.to_date, value: Money.new(19000) }, { date: Date.current, value: Money.new(20000) } ])
@checking_node.series = checking_series
@savings_node.series = savings_series
assert_not_nil @checking_node.series
assert_not_nil @savings_node.series
assert_equal @checking_node.sum, @checking_node.series.last.value
assert_equal @savings_node.sum, @savings_node.series.last.value
aggregated_depository_series = TimeSeries.new([ { date: 1.day.ago.to_date, value: Money.new(23000) }, { date: Date.current, value: Money.new(25000) } ])
aggregated_assets_series = TimeSeries.new([ { date: 1.day.ago.to_date, value: Money.new(23000) }, { date: Date.current, value: Money.new(25000) } ])
assert_equal aggregated_depository_series.values, @depositories.series.values
assert_equal aggregated_assets_series.values, @assets.series.values
end
test "attached series must be a TimeSeries" do
assert_raises(RuntimeError) do
@checking_node.series = []
end
end
test "cannot add time series to non-leaf node" do
assert_raises(RuntimeError) do
@assets.series = TimeSeries.new([])
end
end
test "can only add value node at leaf level of tree" do
root = ValueGroup.new("Root Level")
grandparent = root.add_child_group("Grandparent")
parent = grandparent.add_child_group("Parent")
value_node = parent.add_value_node(OpenStruct.new({ name: "Value Node", value: Money.new(100) }), Money.new(100))
assert_raises(RuntimeError) do
value_node.add_value_node(OpenStruct.new({ name: "Value Node", value: Money.new(100) }), Money.new(100))
end
assert_raises(RuntimeError) do
grandparent.add_value_node(OpenStruct.new({ name: "Value Node", value: Money.new(100) }), Money.new(100))
end
end
end