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
         |