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,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
|