watch_tower 0.0.0.1

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.
Files changed (115) hide show
  1. data/.gitignore +10 -0
  2. data/.todo +33 -0
  3. data/.travis.yml +14 -0
  4. data/Gemfile +43 -0
  5. data/Guardfile +25 -0
  6. data/MIT-LICENSE +20 -0
  7. data/README.md +38 -0
  8. data/Rakefile +8 -0
  9. data/TODO +17 -0
  10. data/bin/watchtower +10 -0
  11. data/ci/adapters/jruby-mysql.yml +8 -0
  12. data/ci/adapters/jruby-postgresql.yml +6 -0
  13. data/ci/adapters/jruby-sqlite.yml +6 -0
  14. data/ci/adapters/ruby-mysql.yml +8 -0
  15. data/ci/adapters/ruby-postgresql.yml +6 -0
  16. data/ci/adapters/ruby-sqlite.yml +6 -0
  17. data/ci/travis.rb +102 -0
  18. data/lib/watch_tower.rb +60 -0
  19. data/lib/watch_tower/appscript.rb +22 -0
  20. data/lib/watch_tower/cli.rb +15 -0
  21. data/lib/watch_tower/cli/.gitkeep +0 -0
  22. data/lib/watch_tower/cli/install.rb +63 -0
  23. data/lib/watch_tower/cli/open.rb +24 -0
  24. data/lib/watch_tower/cli/start.rb +140 -0
  25. data/lib/watch_tower/config.rb +38 -0
  26. data/lib/watch_tower/core_ext.rb +4 -0
  27. data/lib/watch_tower/core_ext/.gitkeep +0 -0
  28. data/lib/watch_tower/editor.rb +17 -0
  29. data/lib/watch_tower/editor/.gitkeep +0 -0
  30. data/lib/watch_tower/editor/base_appscript.rb +34 -0
  31. data/lib/watch_tower/editor/base_ps.rb +6 -0
  32. data/lib/watch_tower/editor/textmate.rb +17 -0
  33. data/lib/watch_tower/editor/xcode.rb +22 -0
  34. data/lib/watch_tower/errors.rb +25 -0
  35. data/lib/watch_tower/eye.rb +79 -0
  36. data/lib/watch_tower/project.rb +14 -0
  37. data/lib/watch_tower/project/.gitkeep +0 -0
  38. data/lib/watch_tower/project/any_based.rb +22 -0
  39. data/lib/watch_tower/project/git_based.rb +86 -0
  40. data/lib/watch_tower/project/init.rb +38 -0
  41. data/lib/watch_tower/project/path_based.rb +144 -0
  42. data/lib/watch_tower/server.rb +62 -0
  43. data/lib/watch_tower/server/.gitkeep +0 -0
  44. data/lib/watch_tower/server/app.rb +37 -0
  45. data/lib/watch_tower/server/assets/images/WatchTower.jpg +0 -0
  46. data/lib/watch_tower/server/assets/images/percentage.png +0 -0
  47. data/lib/watch_tower/server/assets/javascripts/application.js +3 -0
  48. data/lib/watch_tower/server/assets/javascripts/percentage.coffee +8 -0
  49. data/lib/watch_tower/server/assets/stylesheets/application.css +7 -0
  50. data/lib/watch_tower/server/assets/stylesheets/global.sass +71 -0
  51. data/lib/watch_tower/server/assets/stylesheets/project.sass +59 -0
  52. data/lib/watch_tower/server/configurations.rb +10 -0
  53. data/lib/watch_tower/server/configurations/asset.rb +43 -0
  54. data/lib/watch_tower/server/database.rb +105 -0
  55. data/lib/watch_tower/server/db/migrate/001_create_projects.rb +15 -0
  56. data/lib/watch_tower/server/db/migrate/002_create_files.rb +16 -0
  57. data/lib/watch_tower/server/db/migrate/003_create_time_entries.rb +12 -0
  58. data/lib/watch_tower/server/db/migrate/004_create_durations.rb +14 -0
  59. data/lib/watch_tower/server/db/migrate/005_add_hash_to_time_entries.rb +6 -0
  60. data/lib/watch_tower/server/db/migrate/006_add_hash_to_files.rb +6 -0
  61. data/lib/watch_tower/server/decorator.rb +21 -0
  62. data/lib/watch_tower/server/decorator/application_decorator.rb +91 -0
  63. data/lib/watch_tower/server/decorator/file_decorator.rb +38 -0
  64. data/lib/watch_tower/server/decorator/project_decorator.rb +51 -0
  65. data/lib/watch_tower/server/helpers.rb +13 -0
  66. data/lib/watch_tower/server/helpers/asset.rb +29 -0
  67. data/lib/watch_tower/server/helpers/improved_partials.rb +41 -0
  68. data/lib/watch_tower/server/models/duration.rb +11 -0
  69. data/lib/watch_tower/server/models/file.rb +31 -0
  70. data/lib/watch_tower/server/models/project.rb +17 -0
  71. data/lib/watch_tower/server/models/time_entry.rb +64 -0
  72. data/lib/watch_tower/server/public/assets/WatchTower-4d6de11e1bd34165ad91ac46fb711bf3.jpg +0 -0
  73. data/lib/watch_tower/server/public/assets/application-7829b53b5ece1a16d22dc3d00f329023.css +107 -0
  74. data/lib/watch_tower/server/public/assets/application-e0e6b7731aade460f680331e65cf0682.js +9359 -0
  75. data/lib/watch_tower/server/public/assets/percentage-d8589e21a5fc85d32a445f531ff8ab95.png +0 -0
  76. data/lib/watch_tower/server/vendor/assets/javascripts/jquery-ui.js +11729 -0
  77. data/lib/watch_tower/server/vendor/assets/javascripts/jquery.js +8981 -0
  78. data/lib/watch_tower/server/vendor/assets/javascripts/jquery_ujs.js +363 -0
  79. data/lib/watch_tower/server/views/.gitkeep +0 -0
  80. data/lib/watch_tower/server/views/_file.haml +9 -0
  81. data/lib/watch_tower/server/views/_project.haml +13 -0
  82. data/lib/watch_tower/server/views/index.haml +7 -0
  83. data/lib/watch_tower/server/views/layout.haml +32 -0
  84. data/lib/watch_tower/server/views/project.haml +12 -0
  85. data/lib/watch_tower/templates/config.yml +146 -0
  86. data/lib/watch_tower/templates/watchtower.plist +23 -0
  87. data/lib/watch_tower/version.rb +8 -0
  88. data/spec/factories.rb +45 -0
  89. data/spec/spec_helper.rb +26 -0
  90. data/spec/support/active_record.rb +44 -0
  91. data/spec/support/factory_girl.rb +6 -0
  92. data/spec/support/launchy.rb +3 -0
  93. data/spec/support/sinatra.rb +10 -0
  94. data/spec/support/timecop.rb +7 -0
  95. data/spec/watch_tower/appscript_spec.rb +6 -0
  96. data/spec/watch_tower/cli/install_spec.rb +16 -0
  97. data/spec/watch_tower/cli/open_spec.rb +14 -0
  98. data/spec/watch_tower/cli/start_spec.rb +17 -0
  99. data/spec/watch_tower/cli_spec.rb +15 -0
  100. data/spec/watch_tower/config_spec.rb +25 -0
  101. data/spec/watch_tower/editor/textmate_spec.rb +43 -0
  102. data/spec/watch_tower/editor/xcode_spec.rb +43 -0
  103. data/spec/watch_tower/editor_spec.rb +19 -0
  104. data/spec/watch_tower/eye_spec.rb +130 -0
  105. data/spec/watch_tower/project/git_based_spec.rb +131 -0
  106. data/spec/watch_tower/project/path_based_spec.rb +111 -0
  107. data/spec/watch_tower/project_spec.rb +82 -0
  108. data/spec/watch_tower/server/app_spec.rb +186 -0
  109. data/spec/watch_tower/server/decorator/project_decorator_spec.rb +60 -0
  110. data/spec/watch_tower/server/models/file_spec.rb +284 -0
  111. data/spec/watch_tower/server/models/project_spec.rb +165 -0
  112. data/spec/watch_tower/server/models/time_entry_spec.rb +37 -0
  113. data/spec/watch_tower/server_spec.rb +4 -0
  114. data/watch_tower.gemspec +80 -0
  115. metadata +450 -0
@@ -0,0 +1,23 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3
+ <plist version="1.0">
4
+ <dict>
5
+ <key>Label</key>
6
+ <string>fr.technogate.WatchTower</string>
7
+
8
+ <key>Program</key>
9
+ <string>watchtower</string>
10
+
11
+ <key>ProgramArguments</key>
12
+ <array>
13
+ <string>start</string>
14
+ <string>--bootloader</string>
15
+ </array>
16
+
17
+ <key>OnDemand</key>
18
+ <false/>
19
+
20
+ <key>RunAtLoad</key>
21
+ <true/>
22
+ </dict>
23
+ </plist>
@@ -0,0 +1,8 @@
1
+ module WatchTower
2
+ MAJOR = 0
3
+ MINOR = 0
4
+ PATCH = 0
5
+ PRE = 1
6
+
7
+ VERSION = [MAJOR, MINOR, PATCH, PRE].join('.')
8
+ end
data/spec/factories.rb ADDED
@@ -0,0 +1,45 @@
1
+ FactoryGirl.define do
2
+ factory :project, class: Server::Project do
3
+ name
4
+ path
5
+ end
6
+
7
+ factory :file, class: Server::File do
8
+ project
9
+ file_hash
10
+ path
11
+ end
12
+
13
+ factory :time_entry, class: Server::TimeEntry do
14
+ file
15
+ file_hash
16
+ mtime
17
+ end
18
+
19
+ factory :duration, class: Server::Duration do
20
+ file
21
+ date
22
+ duration { Random.rand(1000) }
23
+ end
24
+
25
+ sequence :name do |n|
26
+ "project_#{n}"
27
+ end
28
+
29
+ sequence :path do |n|
30
+ "/path/to/project_#{n}"
31
+ end
32
+
33
+ sequence :mtime do |n|
34
+ Time.now + 2 * n
35
+ end
36
+
37
+ sequence :date do |n|
38
+ Time.now + 2 * n
39
+ end
40
+
41
+ sequence :file_hash do |n|
42
+ require 'digest/sha1'
43
+ Digest::SHA1.hexdigest('WatchTower' * n)
44
+ end
45
+ end
@@ -0,0 +1,26 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib'))
3
+
4
+ ENV['WATCH_TOWER_ENV'] = 'test'
5
+
6
+ require 'rubygems'
7
+ require 'rspec'
8
+
9
+ # Require the library
10
+ require 'watch_tower'
11
+
12
+ include WatchTower
13
+
14
+ # Require support files
15
+ Dir[ROOT_PATH + "/spec/support/**/*.rb"].each {|f| require f}
16
+
17
+ RSpec.configure do |config|
18
+ # == Mock Framework
19
+ #
20
+ # If you prefer to use mocha, flexmock or RR, uncomment the appropriate line:
21
+ #
22
+ config.mock_with :mocha
23
+ # config.mock_with :flexmock
24
+ # config.mock_with :rr
25
+ # config.mock_with :rspec
26
+ end
@@ -0,0 +1,44 @@
1
+ # Include only Rspec's active record functionalities
2
+ require 'rspec/rails/extensions/active_record/base'
3
+ require 'rspec/rails/adapters'
4
+ require 'rspec/rails/matchers/be_a_new'
5
+ require 'rspec/rails/matchers/be_new_record'
6
+ require 'rspec/rails/matchers/have_extension'
7
+ # Uncomment for 2.6.2
8
+ # require 'rspec/rails/matchers/relation_match_array'
9
+ require 'rspec/rails/fixture_support'
10
+ require 'rspec/rails/mocks'
11
+ require 'rspec/rails/example/rails_example_group'
12
+ require 'rspec/rails/example/model_example_group'
13
+
14
+ RSpec::configure do |config|
15
+ def config.escaped_path(*parts)
16
+ Regexp.compile(parts.join('[\\\/]'))
17
+ end unless config.respond_to? :escaped_path
18
+
19
+ config.include RSpec::Rails::ModelExampleGroup, :type => :model, :example_group => {
20
+ :file_path => config.escaped_path(%w[spec watch_tower server models])
21
+ }
22
+
23
+ # If you're not using ActiveRecord, or you'd prefer not to run each of your
24
+ # examples within a transaction, remove the following line or assign false
25
+ # instead of true.
26
+ config.use_transactional_fixtures = true
27
+
28
+ # This is a hack to empty up the database before each test
29
+ # I wasn't able to replicate what Rails / RSpec does for the test suite
30
+ # I'd appreciate any hints to speed up the test suite.
31
+ config.before(:each) do
32
+ WatchTower::Server.constants. # Collect the defined constants
33
+ collect { |c| "::WatchTower::Server::#{c}"}. # Access them under the Server module
34
+ collect(&:constantize). # Make them a constant
35
+ select { |c| c.class == Class }. # Keep only classes
36
+ select { |c| c.superclass == ActiveRecord::Base }. # Keep only those with superclass ActiveRecord::Base
37
+ each(&:delete_all) # Run delete_all on each class
38
+ end
39
+
40
+ # Start the server before all examples
41
+ config.before(:all) do
42
+ WatchTower::Server::Database.start!
43
+ end
44
+ end
@@ -0,0 +1,6 @@
1
+ # Factory girl
2
+ require 'factory_girl'
3
+
4
+ # Tell factory_girl where to find migrations
5
+ FactoryGirl.definition_file_paths << File.expand_path("#{ROOT_PATH}/spec/factories")
6
+ FactoryGirl.find_definitions
@@ -0,0 +1,3 @@
1
+ require 'capybara'
2
+ # Put html files in a special folder
3
+ Capybara.save_and_open_page_path = 'tmp/capybara/'
@@ -0,0 +1,10 @@
1
+ require 'capybara'
2
+ require 'capybara/dsl'
3
+
4
+ Capybara.app = WatchTower::Server::App
5
+
6
+ RSpec.configure do |config|
7
+ config.include Capybara::DSL, :example_group => {
8
+ :file_path => config.escaped_path(%w[spec watch_tower server])
9
+ }
10
+ end
@@ -0,0 +1,7 @@
1
+ require 'timecop'
2
+
3
+ RSpec.configure do |config|
4
+ config.before(:each) do
5
+ Timecop.return
6
+ end
7
+ end
@@ -0,0 +1,6 @@
1
+ require 'spec_helper'
2
+ require 'watch_tower/appscript'
3
+
4
+ describe ::Appscript do
5
+ it { should be_kind_of(Module) }
6
+ end
@@ -0,0 +1,16 @@
1
+ require 'spec_helper'
2
+
3
+ describe CLI do
4
+ describe "Install" do
5
+ before(:all) do
6
+ @valid_initialize_options = []
7
+ end
8
+
9
+ subject { CLI::Runner.new(@valid_initialize_options) }
10
+
11
+ it { should respond_to :install }
12
+
13
+ it "should copy the config file"
14
+ it "should copy the bootloader"
15
+ end
16
+ end
@@ -0,0 +1,14 @@
1
+ require 'spec_helper'
2
+
3
+ describe CLI do
4
+ describe "Open" do
5
+ before(:all) do
6
+ @valid_initialize_options = []
7
+ end
8
+
9
+ subject { CLI::Runner.new(@valid_initialize_options) }
10
+
11
+ it { should respond_to :open }
12
+
13
+ end
14
+ end
@@ -0,0 +1,17 @@
1
+ require 'spec_helper'
2
+
3
+ describe CLI do
4
+ describe "Start" do
5
+ before(:all) do
6
+ @valid_initialize_options = []
7
+ end
8
+
9
+ subject { CLI::Runner.new(@valid_initialize_options) }
10
+
11
+ it { should respond_to :start }
12
+
13
+ it "should allow running in the foreground"
14
+ it "should allow setting the host/port of the sinatra app"
15
+ it "should be able to determine if the bootloader called watchtower or not"
16
+ end
17
+ end
@@ -0,0 +1,15 @@
1
+ require 'spec_helper'
2
+
3
+ describe CLI do
4
+ before(:all) do
5
+ @valid_initialize_options = []
6
+ end
7
+
8
+ subject { CLI::Runner.new(@valid_initialize_options) }
9
+
10
+ describe "Thor definition" do
11
+ subject { CLI::Runner }
12
+ it { should respond_to(:desc) }
13
+ it { should respond_to(:method_option) }
14
+ end
15
+ end
@@ -0,0 +1,25 @@
1
+ require 'spec_helper'
2
+
3
+ describe WatchTower::Config do
4
+
5
+ describe "@@config" do
6
+ it "should have and class_variable @@config" do
7
+ -> { subject.send(:class_variable_get, :@@config) }.should_not raise_error NameError
8
+ end
9
+ end
10
+
11
+ describe "#ensure_config_file_exists" do
12
+ it "should respond_to ensure_config_file_exists" do
13
+ -> { subject.send :ensure_config_file_exists }.should_not raise_error NoMethodError
14
+ end
15
+
16
+ it "should be able to create the config file from the template if it doesn't exist" do
17
+ config_file = mock
18
+ config_file.expects(:write).once
19
+ File.expects(:exists?).with(WatchTower::Config::CONFIG_FILE).returns(false).once
20
+ File.expects(:open).with(WatchTower::Config::CONFIG_FILE, 'w').yields(config_file).once
21
+
22
+ subject.send :ensure_config_file_exists
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,43 @@
1
+ require 'spec_helper'
2
+
3
+ module Editor
4
+ describe Textmate do
5
+ it { should respond_to :current_path }
6
+
7
+ describe "#is_running?" do
8
+ it { should respond_to :is_running? }
9
+
10
+ it "should return wether Textmate is running or not" do
11
+ app = mock()
12
+ app.expects(:is_running?).returns(true).once
13
+ Textmate.any_instance.stubs(:editor).returns(app)
14
+
15
+ subject.is_running?.should be_true
16
+ end
17
+
18
+ it "should return the current_path if textmate running" do
19
+ app = mock()
20
+ app.expects(:is_running?).returns(true).once
21
+ documents = mock
22
+ document = mock
23
+ path = mock
24
+ path.expects(:get).returns('/path/to/file.rb')
25
+ document.expects(:path).returns(path).once
26
+ documents.expects(:get).returns([document]).once
27
+ app.expects(:document).returns(documents).once
28
+ Textmate.any_instance.stubs(:editor).returns(app)
29
+
30
+ subject.current_path.should == '/path/to/file.rb'
31
+ end
32
+
33
+ it "should return nil if textmate ain't running" do
34
+ app = mock()
35
+ app.expects(:is_running?).returns(false).once
36
+ Textmate.any_instance.stubs(:editor).returns(app)
37
+
38
+ subject.current_path.should be_nil
39
+ end
40
+
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,43 @@
1
+ require 'spec_helper'
2
+
3
+ module Editor
4
+ describe Xcode do
5
+ it { should respond_to :current_path }
6
+
7
+ describe "#is_running?" do
8
+ it { should respond_to :is_running? }
9
+
10
+ it "should return wether Xcode is running or not" do
11
+ app = mock()
12
+ app.expects(:is_running?).returns(true).once
13
+ Xcode.any_instance.stubs(:editor).returns(app)
14
+
15
+ subject.is_running?.should be_true
16
+ end
17
+
18
+ it "should return the current_path if textmate running" do
19
+ app = mock()
20
+ app.expects(:is_running?).returns(true).once
21
+ documents = mock
22
+ document = mock
23
+ path = mock
24
+ path.expects(:get).returns('/path/to/file.rb')
25
+ document.expects(:path).returns(path).once
26
+ documents.expects(:get).returns([document]).once
27
+ app.expects(:document).returns(documents).once
28
+ Xcode.any_instance.stubs(:editor).returns(app)
29
+
30
+ subject.current_path.should == '/path/to/file.rb'
31
+ end
32
+
33
+ it "should return nil if textmate ain't running" do
34
+ app = mock()
35
+ app.expects(:is_running?).returns(false).once
36
+ Xcode.any_instance.stubs(:editor).returns(app)
37
+
38
+ subject.current_path.should be_nil
39
+ end
40
+
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,19 @@
1
+ require 'spec_helper'
2
+
3
+ describe Editor do
4
+ describe "#editors" do
5
+ it { should respond_to :editors}
6
+
7
+ it "should return an array of editors" do
8
+ subject.editors.should be_instance_of Array
9
+ end
10
+
11
+ it "should return Textmate" do
12
+ subject.editors.should include Editor::Textmate
13
+ end
14
+
15
+ it "should return Xcode" do
16
+ subject.editors.should include Editor::Xcode
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,130 @@
1
+ require 'spec_helper'
2
+
3
+ describe Eye do
4
+ before(:each) do
5
+ # We don't want to locked in a loop
6
+ $close_eye = true
7
+
8
+ # Set the project's name and path
9
+ @file_path = '/home/user/Code/OpenSource/watch_tower/lib/watch_tower/server/models/time_entries.rb'
10
+ @project_path = '/home/user/Code/OpenSource/watch_tower'
11
+ @project_name = 'watch_tower'
12
+
13
+ # Mock the editor
14
+ @editor = mock
15
+ @editor.stubs(:new).returns(@editor)
16
+ @editor.stubs(:is_running?).returns(true)
17
+ @editor.stubs(:current_paths).returns([@file_path])
18
+ Editor.stubs(:editors).returns([@editor])
19
+
20
+ # Mock the project
21
+ @project = mock
22
+ @project.stubs(:path).returns(@project_path)
23
+ @project.stubs(:name).returns(@project_name)
24
+ Project.stubs(:new_from_path).returns(@project)
25
+
26
+ # Stub the mtime
27
+ @mtime = Time.now
28
+ @file_stat = mock
29
+ @file_stat.stubs(:mtime).returns(@mtime)
30
+ ::File.stubs(:stat).returns(@file_stat)
31
+
32
+ # Stub the file_hash
33
+ @file_hash = mock
34
+ @file_hash.stubs(:hexdigest).returns('b1843f2aeea08c34a4a0b978b117256cd4615a6c')
35
+ Digest::SHA1.stubs(:file).with(@file_path).returns(@file_hash)
36
+ end
37
+
38
+ describe "#start totally mocked" do
39
+ before(:each) do
40
+ # Mock the project's model
41
+ # @time_entry = stub_everything('time_entry')
42
+ # @file_model = stub_everything('file', time_entries: [@time_entries])
43
+ # @project_model = stub_everything('project', files: [@file_model])
44
+ # Server::Project.stubs(:find_or_create_by_name_and_path).returns(@project_model)
45
+ end
46
+
47
+ it { should respond_to :start }
48
+
49
+ it "should tries to get the editors list" do
50
+ Editor.expects(:editors).returns([]).once
51
+
52
+ subject.start
53
+ end
54
+
55
+ it "should call is_running? on the editor" do
56
+ @editor.expects(:is_running?).returns(false).once
57
+ Editor.stubs(:editors).returns([@editor])
58
+
59
+ subject.start
60
+ end
61
+
62
+ it "should call current_paths on the editor to determine the file path" do
63
+ @editor.expects(:current_paths).returns([@file_path]).once
64
+
65
+ subject.start
66
+ end
67
+
68
+ it "should get the file's hash from Digest::SHA1" do
69
+ Digest::SHA1.expects(:file).with(@file_path).returns(@file_hash).once
70
+
71
+ subject.start
72
+ end
73
+
74
+ it "should create a new project from the file path" do
75
+ Project.expects(:new_from_path).returns(@project).once
76
+
77
+ subject.start
78
+ end
79
+
80
+ it "should ask the project for the project's name" do
81
+ @project.expects(:name).returns(@project_name).once
82
+
83
+ subject.start
84
+ end
85
+
86
+ it "should ask the project for the project's path" do
87
+ @project.expects(:path).returns(@project_path).once
88
+
89
+ subject.start
90
+ end
91
+
92
+ it "should create a new (or fetch existing) Project in the database"
93
+ it "should create a new (or fetch existing) File in the database"
94
+ it "should create a new TimeEntry in the database"
95
+
96
+ it "should ask the file for mtime" do
97
+ @file_stat.expects(:mtime).returns(Time.now).once
98
+ ::File.expects(:stat).with(@file_path).returns(@file_stat)
99
+
100
+ subject.start
101
+ end
102
+ end
103
+
104
+ describe "#start database validations" do
105
+ it "should create a new (or fetch existing) Project in the database" do
106
+ subject.start
107
+
108
+ Server::Project.last.name.should == @project_name
109
+ Server::Project.last.path.should == @project_path
110
+ end
111
+
112
+ it "should create a new (or fetch existing) File in the database" do
113
+ subject.start
114
+
115
+ Server::File.last.path.should == @file_path
116
+ end
117
+
118
+ it "should create a new TimeEntry in the database" # do
119
+ # subject.start
120
+ #
121
+ # Server::TimeEntry.last.mtime.should == @mtime
122
+ # end
123
+
124
+ it "should not raise an error if the time entry for the file already exists" do
125
+ subject.start
126
+
127
+ -> { subject.start }.should_not raise_error
128
+ end
129
+ end
130
+ end