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,173 @@
|
|
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
|
+
describe "Model::Base" do
|
12
|
+
|
13
|
+
it "inheritale from" do
|
14
|
+
Tempo::Model::Animal.superclass.must_equal Tempo::Model::Base
|
15
|
+
end
|
16
|
+
|
17
|
+
it "grants child objects the freeze-dry method" do
|
18
|
+
frog_factory
|
19
|
+
frozen = @gray_tree_frog.freeze_dry
|
20
|
+
frozen.must_equal( {:id=>1, :genious=>"hyla", :species=>"h. versicolor"} )
|
21
|
+
end
|
22
|
+
|
23
|
+
it "grants child objects a self indexing method" do
|
24
|
+
frog_factory
|
25
|
+
Tempo::Model::Animal.index.length.must_equal 5
|
26
|
+
Tempo::Model::Animal.index.each do |animal|
|
27
|
+
animal.id.must_be_kind_of(Integer)
|
28
|
+
animal.genious.must_match "hyla"
|
29
|
+
animal.species.must_match /^h\. \w./
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
it "creates a file name to save to" do
|
34
|
+
frog_factory
|
35
|
+
Tempo::Model::Animal.file.must_equal "tempo_animals.yaml"
|
36
|
+
end
|
37
|
+
|
38
|
+
it "grants children the ability to write to a file" do
|
39
|
+
frog_factory
|
40
|
+
test_file = File.join(ENV['HOME'],'tempo','tempo_animals.yaml')
|
41
|
+
File.delete(test_file) if File.exists?( test_file )
|
42
|
+
contents = Tempo::Model::Animal.save_to_file
|
43
|
+
contents = eval_file_as_array( test_file )
|
44
|
+
contents.must_equal ["---", ":id: 1", ":genious: hyla", ":species: h. versicolor",
|
45
|
+
"---", ":id: 2", ":genious: hyla", ":species: h. chrysoscelis",
|
46
|
+
"---", ":id: 3", ":genious: hyla", ":species: h. avivoca",
|
47
|
+
"---", ":id: 4", ":genious: hyla", ":species: h. andersonii",
|
48
|
+
"---", ":id: 5", ":genious: hyla", ":species: h. chinensis" ]
|
49
|
+
end
|
50
|
+
|
51
|
+
it "grants children ability to read from a file" do
|
52
|
+
test_file = File.join(ENV['HOME'],'tempo','tempo_animals.yaml')
|
53
|
+
File.delete(test_file) if File.exists?( test_file )
|
54
|
+
file_lines = [ "---", ":id: 11", ":genious: hyla", ":species: h. versicolor",
|
55
|
+
"---", ":id: 12", ":genious: hyla", ":species: h. chrysoscelis",
|
56
|
+
"---", ":id: 14", ":genious: hyla", ":species: h. andersonii",
|
57
|
+
"---", ":id: 13", ":genious: hyla", ":species: h. avivoca",
|
58
|
+
"---", ":id: 15", ":genious: hyla", ":species: h. chinensis" ]
|
59
|
+
File.open( test_file,'a' ) do |f|
|
60
|
+
file_lines.each do |l|
|
61
|
+
f.puts l
|
62
|
+
end
|
63
|
+
end
|
64
|
+
Tempo::Model::Animal.clear_all
|
65
|
+
Tempo::Model::Animal.read_from_file
|
66
|
+
Tempo::Model::Animal.ids.must_equal [11,12,13,14,15]
|
67
|
+
Tempo::Model::Animal.index.each do |animal|
|
68
|
+
animal.id.must_be_kind_of(Integer)
|
69
|
+
animal.genious.must_match "hyla"
|
70
|
+
animal.species.must_match /^h\. \w./
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
it "gives id as a readable attribute" do
|
75
|
+
frog_factory
|
76
|
+
@gray_tree_frog.id.must_equal 1
|
77
|
+
end
|
78
|
+
|
79
|
+
it "manages uniqe ids" do
|
80
|
+
frog_factory
|
81
|
+
@copes_gray_tree_frog.id.must_equal 2
|
82
|
+
end
|
83
|
+
|
84
|
+
it "handles ids assigned and out of order" do
|
85
|
+
frog_factory
|
86
|
+
Tempo::Model::Animal.ids.must_equal [1,2,3,4,5]
|
87
|
+
@pine_barrens_tree_frog.id.must_equal 4
|
88
|
+
@bird_voiced_tree_frog.id.must_equal 3
|
89
|
+
@chinese_tree_frog.id.must_equal 5
|
90
|
+
end
|
91
|
+
|
92
|
+
it "raises an error on duplicate id" do
|
93
|
+
frog_factory
|
94
|
+
args = { genious: "hyla",
|
95
|
+
species: "h. flatulus",
|
96
|
+
id: 1
|
97
|
+
}
|
98
|
+
proc { gassy_tree_frog = Tempo::Model::Animal.new( args ) }.must_raise Tempo::Model::IdentityConflictError
|
99
|
+
end
|
100
|
+
|
101
|
+
it "finds matching instances of the class" do
|
102
|
+
frog_factory
|
103
|
+
search = Tempo::Model::Animal.find("id", 2)
|
104
|
+
search.must_equal [ @copes_gray_tree_frog ]
|
105
|
+
|
106
|
+
search = Tempo::Model::Animal.find("species", "h. versicolor" )
|
107
|
+
search.must_equal [ @gray_tree_frog ]
|
108
|
+
|
109
|
+
search = Tempo::Model::Animal.find("species", /h\. / )
|
110
|
+
search.length.must_equal 5
|
111
|
+
end
|
112
|
+
|
113
|
+
it "uses case insensitivity searches" do
|
114
|
+
frog_factory
|
115
|
+
search = Tempo::Model::Animal.find("species", "Versicolor" )
|
116
|
+
search.must_equal [ @gray_tree_frog ]
|
117
|
+
end
|
118
|
+
|
119
|
+
it "has a find_by_ method" do
|
120
|
+
frog_factory
|
121
|
+
search = Tempo::Model::Animal.find_by_id(2)
|
122
|
+
search.must_equal @copes_gray_tree_frog
|
123
|
+
|
124
|
+
search = Tempo::Model::Animal.find_by_species("h. versicolor")
|
125
|
+
search.must_equal [ @gray_tree_frog ]
|
126
|
+
|
127
|
+
search = Tempo::Model::Animal.find_by_species("Versicolor")
|
128
|
+
search.must_equal [ @gray_tree_frog ]
|
129
|
+
|
130
|
+
# # test, does this work, and should it?
|
131
|
+
# search = Tempo::Model::Animal.find_by_species("h. color")
|
132
|
+
# search.must_equal [ @gray_tree_frog ]
|
133
|
+
|
134
|
+
search = Tempo::Model::Animal.find_by_genious("hyla")
|
135
|
+
search.length.must_equal 5
|
136
|
+
|
137
|
+
search = Tempo::Model::Animal.find_by_genious_and_species("hyla", /versicolor/)
|
138
|
+
search.must_equal [ @gray_tree_frog ]
|
139
|
+
end
|
140
|
+
|
141
|
+
it "has a sort_by_ method" do
|
142
|
+
frog_factory
|
143
|
+
list = Tempo::Model::Animal.sort_by_species [ @gray_tree_frog, @pine_barrens_tree_frog ]
|
144
|
+
list.must_equal [ @pine_barrens_tree_frog, @gray_tree_frog ]
|
145
|
+
|
146
|
+
list = Tempo::Model::Animal.sort_by_id [ @gray_tree_frog, @pine_barrens_tree_frog ]
|
147
|
+
list.must_equal [ @gray_tree_frog, @pine_barrens_tree_frog ]
|
148
|
+
|
149
|
+
list = Tempo::Model::Animal.sort_by_species
|
150
|
+
list.must_equal [ @pine_barrens_tree_frog, @bird_voiced_tree_frog,
|
151
|
+
@chinese_tree_frog, @copes_gray_tree_frog, @gray_tree_frog ]
|
152
|
+
|
153
|
+
list = Tempo::Model::Animal.sort_by_species do |frog|
|
154
|
+
species_list = ""
|
155
|
+
frog.each do |f|
|
156
|
+
species_list += "#{f.species}, "
|
157
|
+
end
|
158
|
+
species_list[0..-3]
|
159
|
+
end
|
160
|
+
list.must_equal "h. andersonii, h. avivoca, h. chinensis, h. chrysoscelis, h. versicolor"
|
161
|
+
end
|
162
|
+
|
163
|
+
it "has a method_missing method" do
|
164
|
+
proc { Tempo::Model::Animal.foo }.must_raise NoMethodError
|
165
|
+
end
|
166
|
+
|
167
|
+
it "has a delete instance method" do
|
168
|
+
frog_factory
|
169
|
+
@gray_tree_frog.delete
|
170
|
+
Tempo::Model::Animal.ids.must_equal [2,3,4,5]
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|
@@ -0,0 +1,76 @@
|
|
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
|
+
describe "Model::Composite" do
|
12
|
+
|
13
|
+
it "should inherit readable only id" do
|
14
|
+
tree_factory
|
15
|
+
inherits_attr_read_only?( @forest[0], :id ).must_equal true
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should find a project by id" do
|
19
|
+
tree_factory
|
20
|
+
project = Tempo::Model::Tree.find_by_id(4)
|
21
|
+
project.must_equal @forest[3]
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should come with freeze dry for free" do
|
25
|
+
tree_factory
|
26
|
+
@forest[2].freeze_dry.must_equal({:id=>3, :parent=>1, :children=>[7,8], :position=>"branch1"})
|
27
|
+
end
|
28
|
+
|
29
|
+
it "should save to file a collection of composits" do
|
30
|
+
tree_factory
|
31
|
+
test_file = File.join(ENV['HOME'],'tempo','tempo_trees.yaml')
|
32
|
+
Tempo::Model::Tree.save_to_file
|
33
|
+
contents = eval_file_as_array( test_file )
|
34
|
+
contents.must_equal [ "---", ":id: 1", ":parent: :root", ":children:", "- 3", ":position: root1",
|
35
|
+
"---", ":id: 2", ":parent: :root", ":children:", "- 4", "- 5", ":position: root2",
|
36
|
+
"---", ":id: 3", ":parent: 1", ":children:", "- 7", "- 8", ":position: branch1",
|
37
|
+
"---", ":id: 4", ":parent: 2", ":children: []", ":position: branch2",
|
38
|
+
"---", ":id: 5", ":parent: 2", ":children:", "- 6", ":position: branch3",
|
39
|
+
"---", ":id: 6", ":parent: 5", ":children: []", ":position: branch4",
|
40
|
+
"---", ":id: 7", ":parent: 3", ":children: []", ":position: leaf1",
|
41
|
+
"---", ":id: 8", ":parent: 3", ":children: []", ":position: leaf2"]
|
42
|
+
end
|
43
|
+
|
44
|
+
it "should revive a tree structure from a file" do
|
45
|
+
tree_factory
|
46
|
+
test_file = File.join(ENV['HOME'],'tempo','tempo_trees.yaml')
|
47
|
+
File.delete(test_file) if File.exists?( test_file )
|
48
|
+
contents = Tempo::Model::Tree.save_to_file
|
49
|
+
Tempo::Model::Tree.clear_all
|
50
|
+
Tempo::Model::Tree.read_from_file
|
51
|
+
branch1 = Tempo::Model::Tree.find_by_id 3
|
52
|
+
branch1.parent.must_equal 1
|
53
|
+
branch1.children.must_equal [7,8]
|
54
|
+
end
|
55
|
+
|
56
|
+
it "should have a << child method" do
|
57
|
+
tree_factory
|
58
|
+
@forest[1] << @forest[2]
|
59
|
+
@forest[1].freeze_dry.must_equal({:id=>2, :parent=>:root, :children=>[3,4,5], :position=>"root2"})
|
60
|
+
@forest[2].freeze_dry.must_equal({:id=>3, :parent=>2, :children=>[7,8], :position=>"branch1"})
|
61
|
+
end
|
62
|
+
|
63
|
+
it "should have a report method" do
|
64
|
+
tree_factory
|
65
|
+
forest_array = Tempo::Model::Tree.report_trees
|
66
|
+
forest_array.must_equal "[[1,[3,[7,8]]],[2,[4,5,[6]]]]"
|
67
|
+
end
|
68
|
+
|
69
|
+
it "returns childern to root when deleted" do
|
70
|
+
tree_factory
|
71
|
+
Tempo::Model::Tree.delete @forest[0]
|
72
|
+
Tempo::Model::Tree.index.length.must_equal 7
|
73
|
+
@forest[2].parent.must_equal :root
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,171 @@
|
|
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::Log" do
|
16
|
+
|
17
|
+
it "inherits the freeze-dry method" do
|
18
|
+
log_factory
|
19
|
+
frozen = @log_4.freeze_dry
|
20
|
+
frozen.must_equal({ :start_time=>Time.new(2014, 01, 02, 07, 15),
|
21
|
+
:id=>1, :message=>"day 2 pet the sheep"})
|
22
|
+
end
|
23
|
+
|
24
|
+
it "inherits the same indexing method" do
|
25
|
+
log_factory
|
26
|
+
Tempo::Model::MessageLog.index.length.must_equal 6
|
27
|
+
end
|
28
|
+
|
29
|
+
it "should also have a days indexing method" do
|
30
|
+
log_factory
|
31
|
+
Tempo::Model::MessageLog.days_index.length.must_equal 2
|
32
|
+
Tempo::Model::MessageLog.days_index[:"20140101"].length.must_equal 3
|
33
|
+
Tempo::Model::MessageLog.days_index[:"20140102"].length.must_equal 3
|
34
|
+
end
|
35
|
+
|
36
|
+
it "creates a file name to save to" do
|
37
|
+
log_factory
|
38
|
+
date = Time.new(2014,1,1)
|
39
|
+
Tempo::Model::MessageLog.file(date).must_equal "20140101.yaml"
|
40
|
+
end
|
41
|
+
|
42
|
+
it "grants children the ability to write to a file" do
|
43
|
+
log_factory
|
44
|
+
test_dir = File.join(ENV['HOME'],'tempo','tempo_message_logs')
|
45
|
+
# FileUtils.rm_r test_dir if File.exists?(test_dir)
|
46
|
+
Tempo::Model::MessageLog.save_to_file
|
47
|
+
test_file_1 = File.join(test_dir, "20140101.yaml")
|
48
|
+
test_file_2 = File.join(test_dir, "20140102.yaml")
|
49
|
+
contents = eval_file_as_array( test_file_1 )
|
50
|
+
contents.must_equal [ "---", ":start_time: 2014-01-01 07:00:00.000000000 -05:00",
|
51
|
+
":id: 1", ":message: day 1 pet the sheep",
|
52
|
+
"---", ":start_time: 2014-01-01 07:30:00.000000000 -05:00",
|
53
|
+
":id: 2", ":message: day 1 drinking coffee, check on the mushrooms",
|
54
|
+
"---", ":start_time: 2014-01-01 12:30:00.000000000 -05:00",
|
55
|
+
":id: 3", ":message: day 1 water the bonsai"]
|
56
|
+
contents = eval_file_as_array( test_file_2 )
|
57
|
+
contents.must_equal [ "---", ":start_time: 2014-01-02 07:15:00.000000000 -05:00",
|
58
|
+
":id: 1", ":message: day 2 pet the sheep",
|
59
|
+
"---", ":start_time: 2014-01-02 07:45:00.000000000 -05:00",
|
60
|
+
":id: 2", ":message: day 2 drinking coffee, check on the mushrooms",
|
61
|
+
"---", ":start_time: 2014-01-02 12:00:00.000000000 -05:00",
|
62
|
+
":id: 3", ":message: day 2 water the bonsai"]
|
63
|
+
end
|
64
|
+
|
65
|
+
it "grants children ability to read from a file" do
|
66
|
+
log_record_factory
|
67
|
+
time = Time.new(2014, 1, 1)
|
68
|
+
Tempo::Model::MessageLog.read_from_file time
|
69
|
+
Tempo::Model::MessageLog.ids( time ).must_equal [1,2,3]
|
70
|
+
Tempo::Model::MessageLog.index[0].message.must_equal "day 1 pet the sheep"
|
71
|
+
end
|
72
|
+
|
73
|
+
it "loads the records for a given day" do
|
74
|
+
log_record_factory
|
75
|
+
time = Time.new(2014, 1, 1)
|
76
|
+
Tempo::Model::MessageLog.load_day_record time
|
77
|
+
Tempo::Model::MessageLog.ids( time ).must_equal [1,2,3]
|
78
|
+
Tempo::Model::MessageLog.index[0].message.must_equal "day 1 pet the sheep"
|
79
|
+
end
|
80
|
+
|
81
|
+
it "loads the records for a the most recent day and return day" do
|
82
|
+
log_record_factory
|
83
|
+
last_day = Tempo::Model::MessageLog.load_last_day
|
84
|
+
|
85
|
+
time_1 = Time.new(2014, 1, 1) # should not load
|
86
|
+
time_2 = Time.new(2014, 1, 2) # should load
|
87
|
+
Tempo::Model::MessageLog.ids( time_1 ).must_equal []
|
88
|
+
Tempo::Model::MessageLog.ids( time_2 ).must_equal [1,2,3]
|
89
|
+
Tempo::Model::MessageLog.index[0].message.must_equal "day 2 pet the sheep"
|
90
|
+
last_day.must_equal Time.new(2014, 1, 2)
|
91
|
+
end
|
92
|
+
|
93
|
+
it "loads the records for a time frame" do
|
94
|
+
log_record_factory
|
95
|
+
time_1 = Time.new(2014, 1, 1)
|
96
|
+
time_2 = Time.new(2014, 1, 2)
|
97
|
+
|
98
|
+
Tempo::Model::MessageLog.load_days_records time_1, time_2
|
99
|
+
|
100
|
+
Tempo::Model::MessageLog.ids( time_1 ).must_equal [1,2,3]
|
101
|
+
Tempo::Model::MessageLog.ids( time_2 ).must_equal [1,2,3]
|
102
|
+
Tempo::Model::MessageLog.index[0].message.must_equal "day 1 pet the sheep"
|
103
|
+
|
104
|
+
# The index is still being sorted by id
|
105
|
+
Tempo::Model::MessageLog.index[1].message.must_equal "day 2 pet the sheep"
|
106
|
+
end
|
107
|
+
|
108
|
+
it "loads the days index before adding new" do
|
109
|
+
log_record_factory
|
110
|
+
new_record = Tempo::Model::MessageLog.new({ message: "day 1 pet the sheep",
|
111
|
+
start_time: Time.new(2014, 1, 2, 7 ) })
|
112
|
+
new_record.id.must_equal 4
|
113
|
+
end
|
114
|
+
|
115
|
+
it "gives id as a readable attribute" do
|
116
|
+
log_factory
|
117
|
+
@log_6.id.must_equal 3
|
118
|
+
end
|
119
|
+
|
120
|
+
it "raises an error on duplicate id" do
|
121
|
+
log_factory
|
122
|
+
args = { message: "duplicate id",
|
123
|
+
start_time: Time.new(2014, 1, 1, 3 ),
|
124
|
+
id: 1
|
125
|
+
}
|
126
|
+
proc { Tempo::Model::MessageLog.new( args ) }.must_raise Tempo::Model::IdentityConflictError
|
127
|
+
end
|
128
|
+
|
129
|
+
it "finds logs by id" do
|
130
|
+
log_factory
|
131
|
+
search = Tempo::Model::MessageLog.find("id", 2 )
|
132
|
+
search.must_equal [ @log_2, @log_5 ]
|
133
|
+
end
|
134
|
+
|
135
|
+
it "has a day_id method" do
|
136
|
+
day_id = Tempo::Model::MessageLog.day_id Time.new(2014, 1, 1)
|
137
|
+
day_id.must_equal "20140101"
|
138
|
+
end
|
139
|
+
|
140
|
+
it "has a find_by_id using day_id method" do
|
141
|
+
log_factory
|
142
|
+
search = Tempo::Model::MessageLog.find_by_id( 2, "20140101" )
|
143
|
+
search.must_equal @log_2
|
144
|
+
|
145
|
+
search = Tempo::Model::MessageLog.find_by_id( 2, "20140102" )
|
146
|
+
search.must_equal @log_5
|
147
|
+
end
|
148
|
+
|
149
|
+
it "has a find_by_id using time method" do
|
150
|
+
log_factory
|
151
|
+
search = Tempo::Model::MessageLog.find_by_id( 2, Time.new(2014, 1, 1))
|
152
|
+
search.must_equal @log_2
|
153
|
+
search = Tempo::Model::MessageLog.find_by_id( 2, Time.new(2014, 1, 2))
|
154
|
+
search.must_equal @log_5
|
155
|
+
end
|
156
|
+
|
157
|
+
it "has a sort_by_start_time method" do
|
158
|
+
list = Tempo::Model::MessageLog.sort_by_start_time [ @log_5, @log_1, @log_3 ]
|
159
|
+
list.must_equal [ @log_1, @log_3, @log_5 ]
|
160
|
+
end
|
161
|
+
|
162
|
+
it "has a delete instance method" do
|
163
|
+
log_factory
|
164
|
+
@log_1.delete
|
165
|
+
Tempo::Model::MessageLog.ids(Time.new(2014,1,1)).must_equal [2,3]
|
166
|
+
Tempo::Model::MessageLog.index.must_equal [ @log_4, @log_2, @log_5, @log_3, @log_6 ]
|
167
|
+
Tempo::Model::MessageLog.days_index[:"20140101"].length.must_equal 2
|
168
|
+
Tempo::Model::MessageLog.days_index[:"20140102"].length.must_equal 3
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|
@@ -0,0 +1,105 @@
|
|
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
|
+
describe "Model::Project" do
|
12
|
+
|
13
|
+
it "inherits readable only id" do
|
14
|
+
project_factory
|
15
|
+
inherits_attr_read_only?( @project_1, :id ).must_equal true
|
16
|
+
end
|
17
|
+
|
18
|
+
it "has accessible title" do
|
19
|
+
project_factory
|
20
|
+
has_attr_accessor?( @project_1, :title ).must_equal true
|
21
|
+
end
|
22
|
+
|
23
|
+
it "has readable tags" do
|
24
|
+
project_factory
|
25
|
+
has_attr_read_only?( @project_1, :tags ).must_equal true
|
26
|
+
end
|
27
|
+
|
28
|
+
it "is taggable with an array of tags" do
|
29
|
+
project_factory
|
30
|
+
@project_2.tag(["seasonal", "moist"])
|
31
|
+
@project_2.tags.must_equal(["farming", "fungi", "moist", "seasonal"])
|
32
|
+
end
|
33
|
+
|
34
|
+
it "is untaggable with an array of tags" do
|
35
|
+
project_factory
|
36
|
+
@project_3.untag( ["farming", "miniaturization"] )
|
37
|
+
@project_3.tags.must_equal(["trees"])
|
38
|
+
end
|
39
|
+
|
40
|
+
it "comes with freeze dry for free" do
|
41
|
+
project_factory
|
42
|
+
@project_3.freeze_dry.must_equal({:id=>3, :parent=>4, :children=>[],
|
43
|
+
:title=>"horticulture - backyard bonsai",
|
44
|
+
:tags=>["farming", "miniaturization", "trees"]})
|
45
|
+
end
|
46
|
+
|
47
|
+
it "saves to file a collection of projects" do
|
48
|
+
project_factory
|
49
|
+
test_file = File.join(ENV['HOME'],'tempo','tempo_projects.yaml')
|
50
|
+
Tempo::Model::Project.save_to_file
|
51
|
+
contents = eval_file_as_array( test_file )
|
52
|
+
contents.must_equal [ "---", ":id: 1", ":parent: :root", ":children: []", ":title: sheep herding", ":tags: []",
|
53
|
+
"---", ":id: 2", ":parent: 4", ":children: []", ":title: horticulture - basement mushrooms", ":tags:", "- farming", "- fungi", ":current: true",
|
54
|
+
"---", ":id: 3", ":parent: 4", ":children: []", ":title: horticulture - backyard bonsai", ":tags:", "- farming", "- miniaturization", "- trees",
|
55
|
+
"---", ":id: 4", ":parent: :root", ":children:", "- 2", "- 3", ":title: gardening", ":tags: []"]
|
56
|
+
end
|
57
|
+
|
58
|
+
it "returns an boolean to the include? method" do
|
59
|
+
project_factory
|
60
|
+
Tempo::Model::Project.include?("bonsai").must_equal false
|
61
|
+
Tempo::Model::Project.include?("horticulture - backyard bonsai").must_equal true
|
62
|
+
end
|
63
|
+
|
64
|
+
it "has a current project getter" do
|
65
|
+
project_factory
|
66
|
+
Tempo::Model::Project.current.must_equal @project_2
|
67
|
+
end
|
68
|
+
|
69
|
+
it "has a current project setter" do
|
70
|
+
project_factory
|
71
|
+
Tempo::Model::Project.current = @project_3
|
72
|
+
Tempo::Model::Project.current.must_equal @project_3
|
73
|
+
end
|
74
|
+
|
75
|
+
it "has a current boolean method" do
|
76
|
+
project_factory
|
77
|
+
@project_2.current?.must_equal true
|
78
|
+
@project_3.current?.must_equal false
|
79
|
+
end
|
80
|
+
|
81
|
+
it "can not set current to a non-existant project" do
|
82
|
+
project_factory
|
83
|
+
proc { Tempo::Model::Project.current = Tempo::Model::Base.new }.must_raise ArgumentError
|
84
|
+
end
|
85
|
+
|
86
|
+
it "takes current in args to new instance" do
|
87
|
+
project_factory
|
88
|
+
project_4 = Tempo::Model::Project.new({ title: 'horticulture - basement mushrooms', current: true})
|
89
|
+
Tempo::Model::Project.current.must_equal project_4
|
90
|
+
end
|
91
|
+
|
92
|
+
it "saves current in freeze dry" do
|
93
|
+
project_factory
|
94
|
+
@project_2.freeze_dry.must_equal({:id=>2, :parent=>4, :children=>[],
|
95
|
+
:title=>"horticulture - basement mushrooms",
|
96
|
+
:tags=>["farming", "fungi"], :current=>true})
|
97
|
+
end
|
98
|
+
|
99
|
+
it "finds a project by id" do
|
100
|
+
project_factory
|
101
|
+
project = Tempo::Model::Project.find_by_id(1)
|
102
|
+
project.must_equal @project_1
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|