tempo-cli 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +4 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +56 -0
- data/README.md +326 -0
- data/Rakefile +65 -0
- data/bin/tempo +477 -0
- data/features/arrange.feature +43 -0
- data/features/checkout.feature +63 -0
- data/features/end.feature +65 -0
- data/features/project.feature +246 -0
- data/features/report.feature +62 -0
- data/features/start.feature +87 -0
- data/features/step_definitions/tempo_steps.rb +138 -0
- data/features/support/env.rb +26 -0
- data/features/tempo.feature +13 -0
- data/features/update.feature +69 -0
- data/lib/file_record/directory.rb +11 -0
- data/lib/file_record/directory_structure/tempo/README.txt +4 -0
- data/lib/file_record/directory_structure/tempo/tempo_projects.yaml +6 -0
- data/lib/file_record/record.rb +120 -0
- data/lib/tempo/controllers/arrange_controller.rb +52 -0
- data/lib/tempo/controllers/base.rb +117 -0
- data/lib/tempo/controllers/checkout_controller.rb +42 -0
- data/lib/tempo/controllers/end_controller.rb +42 -0
- data/lib/tempo/controllers/projects_controller.rb +107 -0
- data/lib/tempo/controllers/records_controller.rb +21 -0
- data/lib/tempo/controllers/report_controller.rb +55 -0
- data/lib/tempo/controllers/start_controller.rb +42 -0
- data/lib/tempo/controllers/update_controller.rb +78 -0
- data/lib/tempo/models/base.rb +176 -0
- data/lib/tempo/models/composite.rb +71 -0
- data/lib/tempo/models/log.rb +194 -0
- data/lib/tempo/models/project.rb +73 -0
- data/lib/tempo/models/time_record.rb +235 -0
- data/lib/tempo/version.rb +3 -0
- data/lib/tempo/views/arrange_view.rb +27 -0
- data/lib/tempo/views/base.rb +82 -0
- data/lib/tempo/views/formatters/base.rb +30 -0
- data/lib/tempo/views/formatters/screen.rb +86 -0
- data/lib/tempo/views/projects_view.rb +82 -0
- data/lib/tempo/views/report_view.rb +26 -0
- data/lib/tempo/views/reporter.rb +70 -0
- data/lib/tempo/views/time_record_view.rb +30 -0
- data/lib/tempo/views/view_records/base.rb +117 -0
- data/lib/tempo/views/view_records/composite.rb +40 -0
- data/lib/tempo/views/view_records/log.rb +28 -0
- data/lib/tempo/views/view_records/project.rb +32 -0
- data/lib/tempo/views/view_records/time_record.rb +48 -0
- data/lib/tempo.rb +26 -0
- data/lib/time_utilities.rb +30 -0
- data/tempo-cli.gemspec +26 -0
- data/test/lib/file_record/directory_test.rb +30 -0
- data/test/lib/file_record/record_test.rb +106 -0
- data/test/lib/tempo/controllers/base_controller_test.rb +60 -0
- data/test/lib/tempo/controllers/project_controller_test.rb +24 -0
- data/test/lib/tempo/models/base_test.rb +173 -0
- data/test/lib/tempo/models/composite_test.rb +76 -0
- data/test/lib/tempo/models/log_test.rb +171 -0
- data/test/lib/tempo/models/project_test.rb +105 -0
- data/test/lib/tempo/models/time_record_test.rb +212 -0
- data/test/lib/tempo/views/base_test.rb +31 -0
- data/test/lib/tempo/views/formatters/base_test.rb +13 -0
- data/test/lib/tempo/views/formatters/screen_test.rb +94 -0
- data/test/lib/tempo/views/reporter_test.rb +40 -0
- data/test/lib/tempo/views/view_records/base_test.rb +77 -0
- data/test/lib/tempo/views/view_records/composite_test.rb +57 -0
- data/test/lib/tempo/views/view_records/log_test.rb +28 -0
- data/test/lib/tempo/views/view_records/project_test.rb +0 -0
- data/test/lib/tempo/views/view_records/time_record_test.rb +0 -0
- data/test/support/factories.rb +177 -0
- data/test/support/helpers.rb +69 -0
- data/test/test_helper.rb +31 -0
- metadata +230 -0
@@ -0,0 +1,212 @@
|
|
1
|
+
require "test_helper"
|
2
|
+
|
3
|
+
describe Tempo do
|
4
|
+
|
5
|
+
before do
|
6
|
+
# See Rakefile for directory prep and cleanup
|
7
|
+
@dir = File.join( Dir.home,"tempo" )
|
8
|
+
Dir.mkdir(@dir, 0700) unless File.exists?(@dir)
|
9
|
+
end
|
10
|
+
|
11
|
+
after do
|
12
|
+
FileUtils.rm_r(@dir) if File.exists?(@dir)
|
13
|
+
end
|
14
|
+
|
15
|
+
describe "Model::TimeRecord" do
|
16
|
+
|
17
|
+
it "has project as an accessible attribute" do
|
18
|
+
time_record_factory
|
19
|
+
has_attr_accessor?( @record_1, :description ).must_equal true
|
20
|
+
end
|
21
|
+
|
22
|
+
it "defaults to the current project" do
|
23
|
+
project_factory
|
24
|
+
Tempo::Model::TimeRecord.clear_all
|
25
|
+
@record_1 = Tempo::Model::TimeRecord.new({ description: "day 1 pet the sheep",
|
26
|
+
start_time: Time.new(2014, 1, 1, 7 ) })
|
27
|
+
@record_1.project.must_equal Tempo::Model::Project.current.id
|
28
|
+
end
|
29
|
+
|
30
|
+
it "has an accessible description" do
|
31
|
+
time_record_factory
|
32
|
+
has_attr_accessor?( @record_1, :description ).must_equal true
|
33
|
+
end
|
34
|
+
|
35
|
+
it "has a readable end time" do
|
36
|
+
time_record_factory
|
37
|
+
has_attr_reader?( @record_1, :end_time ).must_equal true
|
38
|
+
end
|
39
|
+
|
40
|
+
it "has readable tags" do
|
41
|
+
time_record_factory
|
42
|
+
has_attr_read_only?( @record_1, :tags ).must_equal true
|
43
|
+
end
|
44
|
+
|
45
|
+
it "is taggable with an array of tags" do
|
46
|
+
time_record_factory
|
47
|
+
@record_2.tag(["fungi", "breakfast"])
|
48
|
+
@record_2.tags.must_equal(["breakfast", "fungi"])
|
49
|
+
end
|
50
|
+
|
51
|
+
it "is untaggable with an array of tags" do
|
52
|
+
time_record_factory
|
53
|
+
@record_3.untag( ["horticulture"] )
|
54
|
+
@record_3.tags.must_equal(["trees"])
|
55
|
+
end
|
56
|
+
|
57
|
+
it "has a current project getter" do
|
58
|
+
time_record_factory
|
59
|
+
Tempo::Model::TimeRecord.current.must_equal @record_6
|
60
|
+
@record_6.end_time.must_equal :running
|
61
|
+
end
|
62
|
+
|
63
|
+
it "closes current when adding an end time to current" do
|
64
|
+
time_record_factory
|
65
|
+
@record_6.end_time = Time.new(2014, 1, 2, 19, 00 )
|
66
|
+
Tempo::Model::TimeRecord.current.must_equal nil
|
67
|
+
end
|
68
|
+
|
69
|
+
it "has a running? method" do
|
70
|
+
time_record_factory
|
71
|
+
@record_1.running?.must_equal false
|
72
|
+
@record_6.running?.must_equal true
|
73
|
+
end
|
74
|
+
|
75
|
+
it "has a duration method returning seconds" do
|
76
|
+
time_record_factory
|
77
|
+
@record_1.duration.must_equal 1800
|
78
|
+
@record_6.duration.must_be_kind_of Integer
|
79
|
+
end
|
80
|
+
|
81
|
+
it "closes out the last current project on new" do
|
82
|
+
time_record_factory
|
83
|
+
@record_1.end_time.must_equal @record_2.start_time
|
84
|
+
@record_2.end_time.must_equal @record_3.start_time
|
85
|
+
|
86
|
+
@record_4.end_time.must_equal @record_5.start_time
|
87
|
+
@record_5.end_time.must_equal @record_6.start_time
|
88
|
+
end
|
89
|
+
|
90
|
+
it "closes projects on the start day" do
|
91
|
+
time_record_factory
|
92
|
+
@record_3.end_time.must_equal Time.new(2014,1,1,23,59)
|
93
|
+
end
|
94
|
+
|
95
|
+
it "closes out new projects if not the most recent" do
|
96
|
+
project_factory
|
97
|
+
Tempo::Model::TimeRecord.clear_all
|
98
|
+
@record_2 = Tempo::Model::TimeRecord.new({ project: @project_2, description: "day 1 drinking coffee, check on the mushrooms", start_time: Time.new(2014, 1, 1, 7, 30 ) })
|
99
|
+
@record_1 = Tempo::Model::TimeRecord.new({ project: @project_1, description: "day 1 pet the sheep", start_time: Time.new(2014, 1, 1, 7 ) })
|
100
|
+
Tempo::Model::TimeRecord.current.must_equal @record_2
|
101
|
+
@record_1.end_time.must_equal @record_2.start_time
|
102
|
+
end
|
103
|
+
|
104
|
+
it "closes out all projects when init with an end time" do
|
105
|
+
project_factory
|
106
|
+
Tempo::Model::TimeRecord.clear_all
|
107
|
+
@record_1 = Tempo::Model::TimeRecord.new({ project: @project_2, description: "day 1 drinking coffee, check on the mushrooms", start_time: Time.new(2014, 1, 1, 7, 30 ) })
|
108
|
+
@record_2 = Tempo::Model::TimeRecord.new({ project: @project_1, description: "day 1 pet the sheep", start_time: Time.new(2014, 1, 1, 8 ), end_time: Time.new(2014, 1, 1, 10 ) })
|
109
|
+
@record_1.end_time.must_equal @record_2.start_time
|
110
|
+
Tempo::Model::TimeRecord.current.must_equal nil
|
111
|
+
end
|
112
|
+
|
113
|
+
it "errors when start time inside existing record" do
|
114
|
+
time_record_factory
|
115
|
+
proc { Tempo::Model::TimeRecord.new({ start_time: Time.new(2014, 1, 1, 12 ) }) }.must_raise ArgumentError
|
116
|
+
end
|
117
|
+
|
118
|
+
it "errors when start time same as existing record" do
|
119
|
+
time_record_factory
|
120
|
+
proc { Tempo::Model::TimeRecord.new({ start_time: @record_1.start_time }) }.must_raise ArgumentError
|
121
|
+
end
|
122
|
+
|
123
|
+
it "errors when end time is before start time" do
|
124
|
+
Tempo::Model::TimeRecord.clear_all
|
125
|
+
proc { Tempo::Model::TimeRecord.new({ start_time: Time.new(2014, 1, 1, 12 ), end_time: Time.new(2014, 1, 1, 10 ) }) }.must_raise ArgumentError
|
126
|
+
end
|
127
|
+
|
128
|
+
it "accepts and end time equal to start time" do
|
129
|
+
Tempo::Model::TimeRecord.clear_all
|
130
|
+
record = Tempo::Model::TimeRecord.new({ start_time: Time.new(2014, 1, 1, 12 ), end_time: Time.new(2014, 1, 1, 12 ) })
|
131
|
+
record.end_time.must_equal record.start_time
|
132
|
+
end
|
133
|
+
|
134
|
+
it "end time can equal a previous start time" do
|
135
|
+
Tempo::Model::TimeRecord.clear_all
|
136
|
+
r1 = Tempo::Model::TimeRecord.new({ start_time: Time.new(2014, 1, 1, 10 ), end_time: Time.new(2014, 1, 1, 12 ) })
|
137
|
+
r2 = Tempo::Model::TimeRecord.new({ start_time: Time.new(2014, 1, 1, 8 ), end_time: Time.new(2014, 1, 1, 10 ) })
|
138
|
+
r1.start_time.must_equal r2.end_time
|
139
|
+
end
|
140
|
+
|
141
|
+
it "errors when end time is on a different day" do
|
142
|
+
Tempo::Model::TimeRecord.clear_all
|
143
|
+
proc { Tempo::Model::TimeRecord.new({ start_time: Time.new(2014, 1, 1, 10 ), end_time: Time.new(2014, 1, 2, 12 ) }) }.must_raise ArgumentError
|
144
|
+
end
|
145
|
+
|
146
|
+
it "errors when end time in existing record" do
|
147
|
+
Tempo::Model::TimeRecord.clear_all
|
148
|
+
r1 = Tempo::Model::TimeRecord.new({ start_time: Time.new(2014, 1, 1, 10 ), end_time: Time.new(2014, 1, 1, 12 ) })
|
149
|
+
proc { Tempo::Model::TimeRecord.new({ start_time: Time.new(2014, 1, 1, 8 ), end_time: Time.new(2014, 1, 1, 11 ) }) }.must_raise ArgumentError
|
150
|
+
end
|
151
|
+
|
152
|
+
it "errors when record spans an existing record" do
|
153
|
+
Tempo::Model::TimeRecord.clear_all
|
154
|
+
r1 = Tempo::Model::TimeRecord.new({ start_time: Time.new(2014, 1, 1, 10 ), end_time: Time.new(2014, 1, 1, 11 ) })
|
155
|
+
proc { Tempo::Model::TimeRecord.new({ start_time: Time.new(2014, 1, 1, 8 ), end_time: Time.new(2014, 1, 1, 12 ) }) }.must_raise ArgumentError
|
156
|
+
end
|
157
|
+
|
158
|
+
it "errors when record spans a running record" do
|
159
|
+
Tempo::Model::TimeRecord.clear_all
|
160
|
+
r1 = Tempo::Model::TimeRecord.new({ start_time: Time.new(2014, 1, 1, 10 ) })
|
161
|
+
proc { Tempo::Model::TimeRecord.new({ start_time: Time.new(2014, 1, 1, 8 ), end_time: Time.new(2014, 1, 1, 12 ) }) }.must_raise ArgumentError
|
162
|
+
end
|
163
|
+
|
164
|
+
it "has a valid start time check for existing record" do
|
165
|
+
time_record_factory
|
166
|
+
@record_2.valid_start_time?(@record_2.start_time).must_equal true
|
167
|
+
@record_2.valid_start_time?(@record_1.start_time).must_equal false
|
168
|
+
end
|
169
|
+
|
170
|
+
it "has a valid end time check for existing record" do
|
171
|
+
time_record_factory
|
172
|
+
@record_2.valid_end_time?(@record_2.end_time).must_equal true
|
173
|
+
@record_2.valid_end_time?(@record_3.end_time).must_equal false
|
174
|
+
end
|
175
|
+
|
176
|
+
it "comes with freeze dry for free" do
|
177
|
+
Tempo::Model::TimeRecord.clear_all
|
178
|
+
time_record_factory
|
179
|
+
@record_3.freeze_dry.must_equal({ :start_time=>Time.new(2014,1,1,17,30), :id=>3, :project=>3,
|
180
|
+
:end_time=>Time.new(2014,1,1,23,59), :description=>"day 1 water the bonsai",
|
181
|
+
:tags=>["horticulture", "trees"], :project_title=>"horticulture - backyard bonsai"})
|
182
|
+
end
|
183
|
+
|
184
|
+
it "saves to file a collection of projects" do
|
185
|
+
time_record_factory
|
186
|
+
Tempo::Model::TimeRecord.save_to_file
|
187
|
+
test_file_1 = File.join(ENV['HOME'],'tempo/tempo_time_records/20140101.yaml')
|
188
|
+
test_file_2 = File.join(ENV['HOME'],'tempo/tempo_time_records/20140102.yaml')
|
189
|
+
contents = eval_file_as_array( test_file_1 )
|
190
|
+
contents.must_equal [ "---", ":project_title: sheep herding", ":description: day 1 pet the sheep",
|
191
|
+
":start_time: 2014-01-01 07:00:00.000000000 -05:00", ":end_time: 2014-01-01 07:30:00.000000000 -05:00",
|
192
|
+
":id: 1", ":project: 1", ":tags: []",
|
193
|
+
"---", ":project_title: horticulture - basement mushrooms", ":description: day 1 drinking coffee, check on the mushrooms",
|
194
|
+
":start_time: 2014-01-01 07:30:00.000000000 -05:00", ":end_time: 2014-01-01 17:30:00.000000000 -05:00",
|
195
|
+
":id: 2", ":project: 2", ":tags: []",
|
196
|
+
"---", ":project_title: horticulture - backyard bonsai", ":description: day 1 water the bonsai",
|
197
|
+
":start_time: 2014-01-01 17:30:00.000000000 -05:00", ":end_time: 2014-01-01 23:59:00.000000000 -05:00",
|
198
|
+
":id: 3", ":project: 3", ":tags:", "- horticulture", "- trees"]
|
199
|
+
contents = eval_file_as_array( test_file_2 )
|
200
|
+
# TODO: test this one too when stable
|
201
|
+
contents.must_equal ["---", ":project_title: sheep herding", ":description: day 2 pet the sheep",
|
202
|
+
":start_time: 2014-01-02 07:15:00.000000000 -05:00", ":end_time: 2014-01-02 07:45:00.000000000 -05:00",
|
203
|
+
":id: 1", ":project: 1", ":tags: []",
|
204
|
+
"---", ":project_title: horticulture - basement mushrooms", ":description: day 2 drinking coffee, check on the mushrooms",
|
205
|
+
":start_time: 2014-01-02 07:45:00.000000000 -05:00", ":end_time: 2014-01-02 17:00:00.000000000 -05:00",
|
206
|
+
":id: 2", ":project: 2", ":tags: []",
|
207
|
+
"---", ":project_title: horticulture - backyard bonsai", ":description: day 2 water the bonsai",
|
208
|
+
":start_time: 2014-01-02 17:00:00.000000000 -05:00", ":end_time: :running",
|
209
|
+
":id: 3", ":project: 3", ":tags: []"]
|
210
|
+
end
|
211
|
+
end
|
212
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require "test_helper"
|
2
|
+
|
3
|
+
describe Tempo do
|
4
|
+
describe "Views" do
|
5
|
+
|
6
|
+
before do
|
7
|
+
project_factory
|
8
|
+
Tempo::Views::Reporter.clear_records
|
9
|
+
end
|
10
|
+
|
11
|
+
describe "project list view" do
|
12
|
+
|
13
|
+
it "adds projects to reporter by default" do
|
14
|
+
Tempo::Views::projects_list_view
|
15
|
+
|
16
|
+
view = []
|
17
|
+
Tempo::Views::Reporter.view_records.each {|r| view << r.title}
|
18
|
+
view.must_equal [ "gardening", "horticulture - backyard bonsai", "horticulture - basement mushrooms", "sheep herding" ]
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should be able to return a subset of projects" do
|
22
|
+
subset = Tempo::Model::Project.index[1..3]
|
23
|
+
Tempo::Views::projects_list_view subset
|
24
|
+
|
25
|
+
view = []
|
26
|
+
Tempo::Views::Reporter.view_records.each {|r| view << r.title}
|
27
|
+
view.must_equal [ "gardening", "horticulture - backyard bonsai", "horticulture - basement mushrooms" ]
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
require "test_helper"
|
2
|
+
|
3
|
+
describe Tempo do
|
4
|
+
describe "Views" do
|
5
|
+
describe "Formatters" do
|
6
|
+
describe "Screen" do
|
7
|
+
|
8
|
+
before do
|
9
|
+
view_records_factory
|
10
|
+
@formatter = Tempo::Views::Formatters::Screen.new
|
11
|
+
end
|
12
|
+
|
13
|
+
describe "Message View Records" do
|
14
|
+
|
15
|
+
it "outputs the message" do
|
16
|
+
records = [@message_1, @message_2]
|
17
|
+
out = capture_stdout { @formatter.format_records records }
|
18
|
+
|
19
|
+
assert_equal "All The Things I Did\non a busy busy day\n", out.string
|
20
|
+
end
|
21
|
+
|
22
|
+
it "raises an error when type error" do
|
23
|
+
proc { @formatter.format_records [@error] }.must_raise RuntimeError
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
describe "Duration View Records" do
|
28
|
+
|
29
|
+
it "outputs the duration" do
|
30
|
+
records = [@duration]
|
31
|
+
out = capture_stdout { @formatter.format_records records }
|
32
|
+
|
33
|
+
assert_equal "2:40\n", out.string
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
describe "Project View Records" do
|
38
|
+
|
39
|
+
it "outputs the project title" do
|
40
|
+
records = [@project_1]
|
41
|
+
out = capture_stdout { @formatter.format_records records }
|
42
|
+
|
43
|
+
assert_equal "sheep herding\n", out.string
|
44
|
+
end
|
45
|
+
|
46
|
+
it "accepts option to include tags with spacing" do
|
47
|
+
records = [@project_1, @project_2]
|
48
|
+
out = capture_stdout { @formatter.format_records records, { tags: true }}
|
49
|
+
|
50
|
+
assert_equal "sheep herding tags: none\n" +
|
51
|
+
"horticulture - basement mushrooms tags: [farming, fungi]\n", out.string
|
52
|
+
end
|
53
|
+
|
54
|
+
it "accepts option to include id" do
|
55
|
+
records = [@project_2]
|
56
|
+
out = capture_stdout { @formatter.format_records records, { id: true }}
|
57
|
+
|
58
|
+
assert_equal " [2] horticulture - basement mushrooms\n", out.string
|
59
|
+
end
|
60
|
+
|
61
|
+
it "accepts option to indent projects to proper depth" do
|
62
|
+
@project_1.depth = 3
|
63
|
+
records = [@project_1]
|
64
|
+
out = capture_stdout { @formatter.format_records records, { depth: true }}
|
65
|
+
|
66
|
+
assert_equal " sheep herding\n", out.string
|
67
|
+
end
|
68
|
+
|
69
|
+
it "indicates active project" do
|
70
|
+
records = [@project_1, @project_2]
|
71
|
+
out = capture_stdout { @formatter.format_records records, {active: true}}
|
72
|
+
assert_equal " sheep herding\n* horticulture - basement mushrooms\n", out.string
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
describe "TimeRecord View Records" do
|
77
|
+
it "has start/end time, duration, project and description" do
|
78
|
+
records = [@time_record_1]
|
79
|
+
out = capture_stdout { @formatter.format_records records }
|
80
|
+
|
81
|
+
assert_equal "07:00 - 07:30 [0:30] sheep herding: day 1 pet the sheep\n", out.string
|
82
|
+
end
|
83
|
+
|
84
|
+
it "outputs a running indicator" do
|
85
|
+
records = [@time_record_6]
|
86
|
+
out = capture_stdout { @formatter.format_records records }
|
87
|
+
|
88
|
+
assert_match /17:00 - \d{2}:\d{2}\*/, out.string
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require "test_helper"
|
2
|
+
|
3
|
+
describe Tempo do
|
4
|
+
describe "Views" do
|
5
|
+
describe "Reporter" do
|
6
|
+
it "adds and reports formats" do
|
7
|
+
Tempo::Views::Reporter.add_format :html, :json, :logs
|
8
|
+
Tempo::Views::Reporter.formats.must_equal [:html, :json, :logs]
|
9
|
+
end
|
10
|
+
|
11
|
+
it "collects view records as they are initialized" do
|
12
|
+
Tempo::Views::Reporter.clear_records
|
13
|
+
record_1 = Tempo::Views::ViewRecords::Message.new "a message to report"
|
14
|
+
record_2 = Tempo::Views::ViewRecords::Message.new "a second message to report"
|
15
|
+
record_3 = Tempo::Views::ViewRecords::Message.new "a third message to report"
|
16
|
+
|
17
|
+
Tempo::Views::Reporter.view_records.length.must_equal 3
|
18
|
+
end
|
19
|
+
|
20
|
+
it "raises and error when view records of unknown format" do
|
21
|
+
record = "an invalid record object"
|
22
|
+
proc { Tempo::Views::Reporter.add_view_record record }.must_raise Tempo::Views::InvalidViewRecordError
|
23
|
+
end
|
24
|
+
|
25
|
+
it "sends the reports to the screen formatter on report" do
|
26
|
+
Tempo::Views::Reporter.clear_records
|
27
|
+
record_1 = Tempo::Views::ViewRecords::Message.new "a message to report"
|
28
|
+
|
29
|
+
out = capture_stdout { Tempo::Views::Reporter.report }
|
30
|
+
assert_equal "a message to report\n", out.string
|
31
|
+
end
|
32
|
+
|
33
|
+
it "has a mutable collection of options" do
|
34
|
+
assert_equal Tempo::Views::Reporter.options, {}
|
35
|
+
Tempo::Views::Reporter.add_options({ tags: true, depth: 3, color: "red" })
|
36
|
+
assert_equal Tempo::Views::Reporter.options, { :tags=>true, :depth=>3, :color=>"red" }
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
require "test_helper"
|
2
|
+
|
3
|
+
describe Tempo do
|
4
|
+
describe "Views" do
|
5
|
+
describe "ViewRecords" do
|
6
|
+
|
7
|
+
describe "Message" do
|
8
|
+
|
9
|
+
it "has a type, category,and message attribute" do
|
10
|
+
record = Tempo::Views::ViewRecords::Message.new "a message view record"
|
11
|
+
record.type.must_equal "message"
|
12
|
+
record.category.must_equal :info
|
13
|
+
record.message.must_equal "a message view record"
|
14
|
+
|
15
|
+
record = Tempo::Views::ViewRecords::Message.new "an error message", category: :error
|
16
|
+
record.category.must_equal :error
|
17
|
+
end
|
18
|
+
|
19
|
+
it "has a default format" do
|
20
|
+
record = Tempo::Views::ViewRecords::Message.new "a message view record"
|
21
|
+
record.format.must_equal "a message view record"
|
22
|
+
end
|
23
|
+
|
24
|
+
it "adds itself to the Reporter" do
|
25
|
+
length_before = Tempo::Views::Reporter.view_records.length
|
26
|
+
record = Tempo::Views::ViewRecords::Message.new "a message view record"
|
27
|
+
Tempo::Views::Reporter.view_records.length.must_equal length_before + 1
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
describe "Duration" do
|
32
|
+
|
33
|
+
it "has a type of duration" do
|
34
|
+
record = Tempo::Views::ViewRecords::Duration.new
|
35
|
+
record.type.must_equal "duration"
|
36
|
+
end
|
37
|
+
|
38
|
+
it "starts with given seconds or default to zero" do
|
39
|
+
record = Tempo::Views::ViewRecords::Duration.new
|
40
|
+
record.total.must_equal 0
|
41
|
+
|
42
|
+
record = Tempo::Views::ViewRecords::Duration.new 30
|
43
|
+
record.total.must_equal 30
|
44
|
+
end
|
45
|
+
|
46
|
+
it "has add and subtract methods" do
|
47
|
+
record = Tempo::Views::ViewRecords::Duration.new 30
|
48
|
+
record.add 160
|
49
|
+
record.total.must_equal 190
|
50
|
+
record.subtract 50
|
51
|
+
record.total.must_equal 140
|
52
|
+
end
|
53
|
+
|
54
|
+
it "has a default format" do
|
55
|
+
|
56
|
+
record = Tempo::Views::ViewRecords::Duration.new 1800
|
57
|
+
record.format.must_equal "0:30"
|
58
|
+
|
59
|
+
record = Tempo::Views::ViewRecords::Duration.new 18000
|
60
|
+
record.format.must_equal "5:00"
|
61
|
+
|
62
|
+
record = Tempo::Views::ViewRecords::Duration.new 36300
|
63
|
+
record.format.must_equal "10:05"
|
64
|
+
|
65
|
+
record = Tempo::Views::ViewRecords::Duration.new 39000
|
66
|
+
record.format.must_equal "10:50"
|
67
|
+
end
|
68
|
+
|
69
|
+
it "accepts a formatting block" do
|
70
|
+
record = Tempo::Views::ViewRecords::Duration.new 39000
|
71
|
+
formatted = record.format {|d| "I have a duration of #{d.total} seconds!"}
|
72
|
+
formatted.must_equal "I have a duration of 39000 seconds!"
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
require "test_helper"
|
2
|
+
|
3
|
+
#TODO Useful tree traversal methods should become view helpers?
|
4
|
+
def parse_tree_to_composite_record records, options={}
|
5
|
+
depth = options.fetch( :depth, 0 )
|
6
|
+
parent = options.fetch( :parent, :root )
|
7
|
+
view = []
|
8
|
+
|
9
|
+
records.each do |r|
|
10
|
+
if r.parent == parent
|
11
|
+
v = Tempo::Views::ViewRecords::Composite.new r, depth: depth
|
12
|
+
view << v
|
13
|
+
if not r.children.empty?
|
14
|
+
child_opts = options.clone
|
15
|
+
child_opts[:depth] = depth + 1
|
16
|
+
child_opts[:parent] = r.id
|
17
|
+
child_array = parse_tree_to_composite_record records, child_opts
|
18
|
+
view.push *child_array
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
view
|
24
|
+
end
|
25
|
+
|
26
|
+
describe Tempo do
|
27
|
+
describe "Views" do
|
28
|
+
describe "ViewRecords" do
|
29
|
+
describe "Composite" do
|
30
|
+
before do
|
31
|
+
tree_factory
|
32
|
+
@record = parse_tree_to_composite_record Tempo::Model::Tree.index
|
33
|
+
end
|
34
|
+
|
35
|
+
it "has a depth attribute" do
|
36
|
+
inspector = ""
|
37
|
+
@record.each {|r| inspector += "<#{r.id}:#{r.depth}>"}
|
38
|
+
inspector.must_equal "<1:0><3:1><7:2><8:2><2:0><4:1><5:1><6:2>"
|
39
|
+
end
|
40
|
+
|
41
|
+
it "has a default format" do
|
42
|
+
@record[7].format.must_equal " Tree 6"
|
43
|
+
end
|
44
|
+
|
45
|
+
it "has a class max depth" do
|
46
|
+
Tempo::Views::ViewRecords::Composite.max_depth.must_equal 2
|
47
|
+
end
|
48
|
+
|
49
|
+
it "adds itself to the Reporter" do
|
50
|
+
length_before = Tempo::Views::Reporter.view_records.length
|
51
|
+
record = Tempo::Views::ViewRecords::Message.new "a message view record"
|
52
|
+
Tempo::Views::Reporter.view_records.length.must_equal length_before + 1
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require "test_helper"
|
2
|
+
|
3
|
+
describe Tempo do
|
4
|
+
describe "Views" do
|
5
|
+
describe "ViewRecords" do
|
6
|
+
describe "Log" do
|
7
|
+
before do
|
8
|
+
log_factory
|
9
|
+
@record = Tempo::Views::ViewRecords::Log.new @log_1
|
10
|
+
end
|
11
|
+
|
12
|
+
it "has a start_time and date id attribute" do
|
13
|
+
@record.d_id.must_equal "20140101"
|
14
|
+
@record.start_time.must_equal Time.new(2014, 1, 1, 7 )
|
15
|
+
end
|
16
|
+
|
17
|
+
it "has a default format" do
|
18
|
+
@record.format.must_equal "Messagelog 20140101-1 07:00"
|
19
|
+
end
|
20
|
+
|
21
|
+
it "accepts a formatting block" do
|
22
|
+
f = @record.format {|m| "#{m.d_id}-#{m.id}"}
|
23
|
+
f.must_equal "20140101-1"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
File without changes
|
File without changes
|