tempo-cli 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|