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.
- data/.gitignore +10 -0
- data/.todo +33 -0
- data/.travis.yml +14 -0
- data/Gemfile +43 -0
- data/Guardfile +25 -0
- data/MIT-LICENSE +20 -0
- data/README.md +38 -0
- data/Rakefile +8 -0
- data/TODO +17 -0
- data/bin/watchtower +10 -0
- data/ci/adapters/jruby-mysql.yml +8 -0
- data/ci/adapters/jruby-postgresql.yml +6 -0
- data/ci/adapters/jruby-sqlite.yml +6 -0
- data/ci/adapters/ruby-mysql.yml +8 -0
- data/ci/adapters/ruby-postgresql.yml +6 -0
- data/ci/adapters/ruby-sqlite.yml +6 -0
- data/ci/travis.rb +102 -0
- data/lib/watch_tower.rb +60 -0
- data/lib/watch_tower/appscript.rb +22 -0
- data/lib/watch_tower/cli.rb +15 -0
- data/lib/watch_tower/cli/.gitkeep +0 -0
- data/lib/watch_tower/cli/install.rb +63 -0
- data/lib/watch_tower/cli/open.rb +24 -0
- data/lib/watch_tower/cli/start.rb +140 -0
- data/lib/watch_tower/config.rb +38 -0
- data/lib/watch_tower/core_ext.rb +4 -0
- data/lib/watch_tower/core_ext/.gitkeep +0 -0
- data/lib/watch_tower/editor.rb +17 -0
- data/lib/watch_tower/editor/.gitkeep +0 -0
- data/lib/watch_tower/editor/base_appscript.rb +34 -0
- data/lib/watch_tower/editor/base_ps.rb +6 -0
- data/lib/watch_tower/editor/textmate.rb +17 -0
- data/lib/watch_tower/editor/xcode.rb +22 -0
- data/lib/watch_tower/errors.rb +25 -0
- data/lib/watch_tower/eye.rb +79 -0
- data/lib/watch_tower/project.rb +14 -0
- data/lib/watch_tower/project/.gitkeep +0 -0
- data/lib/watch_tower/project/any_based.rb +22 -0
- data/lib/watch_tower/project/git_based.rb +86 -0
- data/lib/watch_tower/project/init.rb +38 -0
- data/lib/watch_tower/project/path_based.rb +144 -0
- data/lib/watch_tower/server.rb +62 -0
- data/lib/watch_tower/server/.gitkeep +0 -0
- data/lib/watch_tower/server/app.rb +37 -0
- data/lib/watch_tower/server/assets/images/WatchTower.jpg +0 -0
- data/lib/watch_tower/server/assets/images/percentage.png +0 -0
- data/lib/watch_tower/server/assets/javascripts/application.js +3 -0
- data/lib/watch_tower/server/assets/javascripts/percentage.coffee +8 -0
- data/lib/watch_tower/server/assets/stylesheets/application.css +7 -0
- data/lib/watch_tower/server/assets/stylesheets/global.sass +71 -0
- data/lib/watch_tower/server/assets/stylesheets/project.sass +59 -0
- data/lib/watch_tower/server/configurations.rb +10 -0
- data/lib/watch_tower/server/configurations/asset.rb +43 -0
- data/lib/watch_tower/server/database.rb +105 -0
- data/lib/watch_tower/server/db/migrate/001_create_projects.rb +15 -0
- data/lib/watch_tower/server/db/migrate/002_create_files.rb +16 -0
- data/lib/watch_tower/server/db/migrate/003_create_time_entries.rb +12 -0
- data/lib/watch_tower/server/db/migrate/004_create_durations.rb +14 -0
- data/lib/watch_tower/server/db/migrate/005_add_hash_to_time_entries.rb +6 -0
- data/lib/watch_tower/server/db/migrate/006_add_hash_to_files.rb +6 -0
- data/lib/watch_tower/server/decorator.rb +21 -0
- data/lib/watch_tower/server/decorator/application_decorator.rb +91 -0
- data/lib/watch_tower/server/decorator/file_decorator.rb +38 -0
- data/lib/watch_tower/server/decorator/project_decorator.rb +51 -0
- data/lib/watch_tower/server/helpers.rb +13 -0
- data/lib/watch_tower/server/helpers/asset.rb +29 -0
- data/lib/watch_tower/server/helpers/improved_partials.rb +41 -0
- data/lib/watch_tower/server/models/duration.rb +11 -0
- data/lib/watch_tower/server/models/file.rb +31 -0
- data/lib/watch_tower/server/models/project.rb +17 -0
- data/lib/watch_tower/server/models/time_entry.rb +64 -0
- data/lib/watch_tower/server/public/assets/WatchTower-4d6de11e1bd34165ad91ac46fb711bf3.jpg +0 -0
- data/lib/watch_tower/server/public/assets/application-7829b53b5ece1a16d22dc3d00f329023.css +107 -0
- data/lib/watch_tower/server/public/assets/application-e0e6b7731aade460f680331e65cf0682.js +9359 -0
- data/lib/watch_tower/server/public/assets/percentage-d8589e21a5fc85d32a445f531ff8ab95.png +0 -0
- data/lib/watch_tower/server/vendor/assets/javascripts/jquery-ui.js +11729 -0
- data/lib/watch_tower/server/vendor/assets/javascripts/jquery.js +8981 -0
- data/lib/watch_tower/server/vendor/assets/javascripts/jquery_ujs.js +363 -0
- data/lib/watch_tower/server/views/.gitkeep +0 -0
- data/lib/watch_tower/server/views/_file.haml +9 -0
- data/lib/watch_tower/server/views/_project.haml +13 -0
- data/lib/watch_tower/server/views/index.haml +7 -0
- data/lib/watch_tower/server/views/layout.haml +32 -0
- data/lib/watch_tower/server/views/project.haml +12 -0
- data/lib/watch_tower/templates/config.yml +146 -0
- data/lib/watch_tower/templates/watchtower.plist +23 -0
- data/lib/watch_tower/version.rb +8 -0
- data/spec/factories.rb +45 -0
- data/spec/spec_helper.rb +26 -0
- data/spec/support/active_record.rb +44 -0
- data/spec/support/factory_girl.rb +6 -0
- data/spec/support/launchy.rb +3 -0
- data/spec/support/sinatra.rb +10 -0
- data/spec/support/timecop.rb +7 -0
- data/spec/watch_tower/appscript_spec.rb +6 -0
- data/spec/watch_tower/cli/install_spec.rb +16 -0
- data/spec/watch_tower/cli/open_spec.rb +14 -0
- data/spec/watch_tower/cli/start_spec.rb +17 -0
- data/spec/watch_tower/cli_spec.rb +15 -0
- data/spec/watch_tower/config_spec.rb +25 -0
- data/spec/watch_tower/editor/textmate_spec.rb +43 -0
- data/spec/watch_tower/editor/xcode_spec.rb +43 -0
- data/spec/watch_tower/editor_spec.rb +19 -0
- data/spec/watch_tower/eye_spec.rb +130 -0
- data/spec/watch_tower/project/git_based_spec.rb +131 -0
- data/spec/watch_tower/project/path_based_spec.rb +111 -0
- data/spec/watch_tower/project_spec.rb +82 -0
- data/spec/watch_tower/server/app_spec.rb +186 -0
- data/spec/watch_tower/server/decorator/project_decorator_spec.rb +60 -0
- data/spec/watch_tower/server/models/file_spec.rb +284 -0
- data/spec/watch_tower/server/models/project_spec.rb +165 -0
- data/spec/watch_tower/server/models/time_entry_spec.rb +37 -0
- data/spec/watch_tower/server_spec.rb +4 -0
- data/watch_tower.gemspec +80 -0
- metadata +450 -0
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
class Project
|
|
4
|
+
describe GitBased do
|
|
5
|
+
before(:all) do
|
|
6
|
+
# Arguments
|
|
7
|
+
@code = '/home/user/Code'
|
|
8
|
+
@file_path = '/home/user/Code/OpenSource/watch_tower/lib/watch_tower/server/models/time_entries.rb'
|
|
9
|
+
|
|
10
|
+
# Expected results
|
|
11
|
+
@project_path = '/home/user/Code/OpenSource/watch_tower'
|
|
12
|
+
@project_git_folder_path = @project_path + '/.git'
|
|
13
|
+
@project_name = 'watch_tower'
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
before(:each) do
|
|
17
|
+
# Project.stubs(:expand_path).returns
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
describe "#project_git_folder_path" do
|
|
21
|
+
it "should respond to :project_git_folder_path" do
|
|
22
|
+
-> { subject.send(:project_git_folder_path) }.should_not raise_error NoMethodError
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
it "should return a path if exists" do
|
|
26
|
+
@file_path.split('/').each_index do |i|
|
|
27
|
+
path = @file_path.split('/')[0..i].join('/') + '/.git'
|
|
28
|
+
if @project_git_folder_path == path
|
|
29
|
+
File.stubs(:exists?).with(path).returns(true)
|
|
30
|
+
else
|
|
31
|
+
File.stubs(:exists?).with(path).returns(false)
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
subject.send(:project_git_folder_path, @file_path).should == @project_git_folder_path
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
it "should return nil if path does not exist" do
|
|
39
|
+
file_path = @file_path.gsub(%r{#{@code}}, '/some/other/path')
|
|
40
|
+
file_path.split('/').each_index do |i|
|
|
41
|
+
path = file_path.split('/')[0..i].join('/')
|
|
42
|
+
File.stubs(:exists?).with(path + '/.git').returns(false)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
subject.send(:project_git_folder_path, file_path).should be_nil
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
it "should cache it" do
|
|
49
|
+
File.expects(:exists?).never
|
|
50
|
+
|
|
51
|
+
subject.send(:project_git_folder_path, @file_path).should == @project_git_folder_path
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
describe "#active_for_path?" do
|
|
57
|
+
it { should respond_to(:active_for_path?) }
|
|
58
|
+
|
|
59
|
+
it "should be able to determine if a path is git-ized" do
|
|
60
|
+
GitBased.expects(:project_git_folder_path).returns(@project_path)
|
|
61
|
+
|
|
62
|
+
subject.active_for_path?(@file_path).should be_true
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
it "should be able to determine if a path is not git-ized" do
|
|
66
|
+
GitBased.expects(:project_git_folder_path).returns(nil)
|
|
67
|
+
|
|
68
|
+
subject.active_for_path?(@file_path).should be_false
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
describe "#working_directory" do
|
|
73
|
+
it { should respond_to(:working_directory) }
|
|
74
|
+
|
|
75
|
+
it "should return the working directory of a path" do
|
|
76
|
+
GitBased.stubs(:project_git_folder_path).returns(@project_git_folder_path)
|
|
77
|
+
|
|
78
|
+
subject.working_directory(@file_path).should == @project_path
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
it "should cache it" do
|
|
82
|
+
GitBased.expects(:project_git_folder_path).never
|
|
83
|
+
|
|
84
|
+
subject.working_directory(@file_path).should == @project_path
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
describe "#project_name" do
|
|
89
|
+
it { should respond_to(:project_name) }
|
|
90
|
+
|
|
91
|
+
it "should return the working directory of a path" do
|
|
92
|
+
GitBased.stubs(:project_git_folder_path).returns(@project_git_folder_path)
|
|
93
|
+
|
|
94
|
+
subject.project_name(@file_path).should == @project_name
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
it "should cache it" do
|
|
98
|
+
GitBased.expects(:project_git_folder_path).never
|
|
99
|
+
|
|
100
|
+
subject.project_name(@file_path).should == @project_name
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
describe "#head" do
|
|
105
|
+
before(:each) do
|
|
106
|
+
GitBased.stubs(:active_for_path?).returns(true)
|
|
107
|
+
GitBased.stubs(:working_directory).returns(@project_path)
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
it { should respond_to :head }
|
|
111
|
+
|
|
112
|
+
it "should create a Git::Base object" do
|
|
113
|
+
commit = mock
|
|
114
|
+
git_base = mock
|
|
115
|
+
git_base.stubs(:log).returns([commit])
|
|
116
|
+
::Git.expects(:open).with(@project_path).returns(git_base).once
|
|
117
|
+
|
|
118
|
+
subject.head(@project_path)
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
it "should return the head revision" do
|
|
122
|
+
commit = mock
|
|
123
|
+
git_base = mock
|
|
124
|
+
git_base.stubs(:log).returns([commit])
|
|
125
|
+
::Git.stubs(:open).with(@project_path).returns(git_base)
|
|
126
|
+
|
|
127
|
+
subject.head(@project_path).should == commit
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
end
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
class Project
|
|
4
|
+
describe PathBased do
|
|
5
|
+
before(:all) do
|
|
6
|
+
# Arguments
|
|
7
|
+
@code = '/home/user/Code'
|
|
8
|
+
@file_path = '/home/user/Code/OpenSource/watch_tower/lib/watch_tower/server/models/time_entries.rb'
|
|
9
|
+
@nested_project_layers = 2
|
|
10
|
+
@args = [@code, @file_path, @nested_project_layers]
|
|
11
|
+
@options = {
|
|
12
|
+
code: @code,
|
|
13
|
+
nested_project_layers: @nested_project_layers
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
# Expected results
|
|
17
|
+
@project_path = '/home/user/Code/OpenSource/watch_tower'
|
|
18
|
+
@project_name = 'watch_tower'
|
|
19
|
+
@project_path_parts = ['/home/user/Code', 'OpenSource', 'watch_tower']
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
before(:each) do
|
|
23
|
+
PathBased.stubs(:code_path).returns(@code)
|
|
24
|
+
PathBased.stubs(:code_path).returns(@code)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
describe "#project_path_part" do
|
|
28
|
+
it "should respond to #project_path_part" do
|
|
29
|
+
-> { subject.send :project_path_part, *@args }.should_not raise_error NoMethodError
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
it "should be able to return the project name from the path Given the correct path" do
|
|
33
|
+
subject.send(:project_path_part, *@args).should == @project_path_parts
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
it "should raises PathNotUnderCodePath if the path is not nested under code" do
|
|
37
|
+
file_path = @file_path.gsub(%r{#{@code}}, '/some/other/path')
|
|
38
|
+
-> { subject.send(:project_path_part, @code, file_path, @nested_project_layers) }.should raise_error PathNotUnderCodePath
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
it "should cache the path it" do
|
|
42
|
+
file_path = @file_path
|
|
43
|
+
file_path.expects(:scan).never
|
|
44
|
+
|
|
45
|
+
subject.send(:project_path_part, @code, file_path, @nested_project_layers).should == @project_path_parts
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
describe "#project_name_from_nested_path" do
|
|
50
|
+
it "should respond to #project_name_from_nested_path" do
|
|
51
|
+
-> { subject.send :project_name_from_nested_path, *@args }.should_not raise_error NoMethodError
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
it "should be able to return the project path parts from the path Given the correct path" do
|
|
55
|
+
subject.send(:project_name_from_nested_path, *@args).should == @project_name
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
it "should raises PathNotUnderCodePath if the path is not nested under code" do
|
|
59
|
+
file_path = @file_path.gsub(%r{#{@code}}, '/some/other/path')
|
|
60
|
+
-> { subject.send(:project_name_from_nested_path, @code, file_path, @nested_project_layers) }.should raise_error PathNotUnderCodePath
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
describe "#project_path_from_nested_path" do
|
|
65
|
+
it "should respond to #project_path_from_nested_path" do
|
|
66
|
+
-> { subject.send :project_path_from_nested_path, *@args }.should_not raise_error NoMethodError
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
it "should be able to return the project name from the path Given the correct path" do
|
|
70
|
+
subject.send(:project_path_from_nested_path, *@args).should == @project_path
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
it "should raises PathNotUnderCodePath if the path is not nested under code" do
|
|
74
|
+
file_path = @file_path.gsub(%r{#{@code}}, '/some/other/path')
|
|
75
|
+
-> { subject.send(:project_path_from_nested_path, @code, file_path, @nested_project_layers) }.should raise_error PathNotUnderCodePath
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
describe "#working_directory" do
|
|
80
|
+
it { should respond_to :working_directory }
|
|
81
|
+
|
|
82
|
+
it "should return the project path from nested path of the given path" do
|
|
83
|
+
PathBased.expects(:project_path_from_nested_path).with(*@args).returns(@project_path).once
|
|
84
|
+
|
|
85
|
+
subject.working_directory(@file_path, @options).should == @project_path
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
it "should cache the path it" do
|
|
89
|
+
PathBased.expects(:project_path_from_nested_path).with(*@args).returns(@project_path).never
|
|
90
|
+
|
|
91
|
+
subject.working_directory(@file_path, @options).should == @project_path
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
describe "#project_name" do
|
|
96
|
+
it { should respond_to :project_name }
|
|
97
|
+
|
|
98
|
+
it "should return the project path from nested path of the given path" do
|
|
99
|
+
PathBased.expects(:project_name_from_nested_path).with(*@args).returns(@project_name).once
|
|
100
|
+
|
|
101
|
+
subject.project_name(@file_path, @options).should == @project_name
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
it "should cache the path it" do
|
|
105
|
+
PathBased.expects(:project_name_from_nested_path).with(*@args).returns(@project_name).never
|
|
106
|
+
|
|
107
|
+
subject.project_name(@file_path, @options).should == @project_name
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
end
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe Project do
|
|
4
|
+
describe "Class Methods" do
|
|
5
|
+
subject { Project }
|
|
6
|
+
|
|
7
|
+
before(:all) do
|
|
8
|
+
# Arguments
|
|
9
|
+
@code = '/home/user/Code'
|
|
10
|
+
@file_path = '/home/user/Code/OpenSource/watch_tower/lib/watch_tower/server/models/time_entries.rb'
|
|
11
|
+
|
|
12
|
+
# Expected results
|
|
13
|
+
@project_path = '/home/user/Code/OpenSource/watch_tower'
|
|
14
|
+
@project_name = 'watch_tower'
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
before(:each) do
|
|
18
|
+
::File.stubs(:exists?).returns(true)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
describe "#new_from_path" do
|
|
22
|
+
|
|
23
|
+
it { should respond_to :new_from_path }
|
|
24
|
+
|
|
25
|
+
describe "path based" do
|
|
26
|
+
before(:each) do
|
|
27
|
+
Project::GitBased.expects(:active_for_path?).returns(false).once
|
|
28
|
+
Project::PathBased.expects(:working_directory).returns(@project_path).once
|
|
29
|
+
Project::PathBased.expects(:project_name).returns(@project_name).once
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
it "should create a project based off of git" do
|
|
33
|
+
p = subject.new_from_path(@file_path)
|
|
34
|
+
p.should be_instance_of subject
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
it "should return the name of the project" do
|
|
38
|
+
p = subject.new_from_path(@file_path)
|
|
39
|
+
p.name.should == @project_name
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
it "should return the path of the project" do
|
|
43
|
+
p = subject.new_from_path(@file_path)
|
|
44
|
+
p.path.should == @project_path
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
describe "git based" do
|
|
49
|
+
before(:each) do
|
|
50
|
+
Project::GitBased.expects(:active_for_path?).returns(true).once
|
|
51
|
+
Project::GitBased.expects(:working_directory).returns(@project_path).once
|
|
52
|
+
Project::GitBased.expects(:project_name).returns(@project_name).once
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
it "should create a project based off of git" do
|
|
56
|
+
p = subject.new_from_path(@file_path)
|
|
57
|
+
p.should be_instance_of subject
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
it "should return the name of the project" do
|
|
61
|
+
p = subject.new_from_path(@file_path)
|
|
62
|
+
p.name.should == @project_name
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
it "should return the path of the project" do
|
|
66
|
+
p = subject.new_from_path(@file_path)
|
|
67
|
+
p.path.should == @project_path
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
describe "Instance Methods" do
|
|
74
|
+
subject { Project.new @project_name, @project_path }
|
|
75
|
+
|
|
76
|
+
it { should respond_to :name }
|
|
77
|
+
it { should respond_to :path }
|
|
78
|
+
|
|
79
|
+
its(:name) { should == @project_name }
|
|
80
|
+
its(:path) { should == @project_path }
|
|
81
|
+
end
|
|
82
|
+
end
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
module Server
|
|
4
|
+
describe App do
|
|
5
|
+
before(:each) do
|
|
6
|
+
@projects = {
|
|
7
|
+
empty: {files: [], time_entries:[] },
|
|
8
|
+
not_empty: {files: [], time_entries: []}
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
@projects[:not_empty][:project] = FactoryGirl.create(:project)
|
|
12
|
+
2.times do
|
|
13
|
+
@projects[:not_empty][:files] << FactoryGirl.create(:file, project: @projects[:not_empty][:project])
|
|
14
|
+
end
|
|
15
|
+
5.times do
|
|
16
|
+
@projects[:not_empty][:time_entries] << FactoryGirl.create(:time_entry, file: @projects[:not_empty][:files].first)
|
|
17
|
+
end
|
|
18
|
+
@projects[:not_empty][:duration] = FactoryGirl.create(:duration, file: @projects[:not_empty][:files].first)
|
|
19
|
+
|
|
20
|
+
@projects[:empty][:project] = FactoryGirl.create(:project)
|
|
21
|
+
2.times do
|
|
22
|
+
@projects[:empty][:files] << FactoryGirl.create(:file, project: @projects[:empty][:project])
|
|
23
|
+
end
|
|
24
|
+
@projects[:empty][:time_entries] << FactoryGirl.create(:time_entry, file: @projects[:empty][:files].first)
|
|
25
|
+
@projects[:empty][:duration] = FactoryGirl.create(:duration, file: @projects[:empty][:files].first)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
describe "#index" do
|
|
29
|
+
before(:each) do
|
|
30
|
+
visit '/'
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
it "should render the layout" do
|
|
34
|
+
page.should have_selector :xpath, '//html/head/title'
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
it "should have the correct title" do
|
|
38
|
+
within :xpath, '//html/head/title' do
|
|
39
|
+
page.should have_content "Watch Tower - Projects"
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
it "should have a projects section" do
|
|
44
|
+
within :xpath, '//html/body' do
|
|
45
|
+
page.should have_selector 'section#projects'
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
it "should display each project as an article" do
|
|
50
|
+
within 'section#projects' do
|
|
51
|
+
page.should have_selector '.project'
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
it "should display have a section for the project's name" do
|
|
56
|
+
within 'section#projects' do
|
|
57
|
+
page.should have_selector '.project > .name'
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
it "should display the name of each project" do
|
|
62
|
+
within 'section#projects .project > .name' do
|
|
63
|
+
page.should have_content @projects[:not_empty][:project].name.camelcase
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
it "should not show the project with an empty time entries" do
|
|
68
|
+
within 'section#projects' do
|
|
69
|
+
page.should_not have_content @projects[:empty][:project].name.camelcase
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
it "should display the elapsed time of each project" do
|
|
74
|
+
within 'section#projects' do
|
|
75
|
+
page.should have_selector '.project > .elapsed'
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
it "should display an image under each project's name to categorize percentage" do
|
|
80
|
+
within 'section#projects' do
|
|
81
|
+
page.should have_selector '.project > .percentage_img_container > .percentage > img'
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
it "should have link on each project's name" do
|
|
86
|
+
within 'section#projects .project .name' do
|
|
87
|
+
page.should have_selector('a')
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
it "should link to the project's page" do
|
|
92
|
+
within 'section#projects .project .name' do
|
|
93
|
+
page.should have_selector('a', href: "/project/#{@projects[:not_empty][:project].id}")
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
describe "#project" do
|
|
99
|
+
before(:each) do
|
|
100
|
+
visit "/project/#{@projects[:not_empty][:project].id}"
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
it "should render the layout" do
|
|
104
|
+
page.should have_selector :xpath, '//html/head/title'
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
it "should have the correct title" do
|
|
108
|
+
within :xpath, '//html/head/title' do
|
|
109
|
+
page.should have_content "Watch Tower - Project - #{@projects[:not_empty][:project].name.camelcase}"
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
it "should have a projects section" do
|
|
114
|
+
within :xpath, '//html/body' do
|
|
115
|
+
page.should have_selector 'article#project'
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
it "should have the an h1 for the project's name" do
|
|
120
|
+
within 'article#project' do
|
|
121
|
+
page.should have_selector 'header > h1.project_name'
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
it "should have the project's name in an h1" do
|
|
126
|
+
within 'article#project header > h1.project_name' do
|
|
127
|
+
page.should have_content @projects[:not_empty][:project].name.camelcase
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
it "should have the an h2 for the project's path" do
|
|
132
|
+
within 'article#project' do
|
|
133
|
+
page.should have_selector 'header > h2.project_path'
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
it "should have the project's path in an h2" do
|
|
138
|
+
within 'article#project header > h2.project_path' do
|
|
139
|
+
page.should have_content @projects[:not_empty][:project].path
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
it "should have a section for the files" do
|
|
144
|
+
within 'article#project' do
|
|
145
|
+
page.should have_selector 'section#files'
|
|
146
|
+
end
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
it "should have a div for the file's path" do
|
|
150
|
+
within 'article#project section#files article.file' do
|
|
151
|
+
page.should have_selector 'div.path'
|
|
152
|
+
end
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
it "should display the file's path" do
|
|
156
|
+
within 'article#project section#files article.file div.path' do
|
|
157
|
+
page.should have_content @projects[:not_empty][:files].first.path
|
|
158
|
+
end
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
it "should have a div for the file's elapsed time" do
|
|
162
|
+
within 'article#project section#files article.file' do
|
|
163
|
+
page.should have_selector 'div.elapsed'
|
|
164
|
+
end
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
it "should display the file's elaped time" do
|
|
168
|
+
within 'article#project section#files article.file div.elapsed' do
|
|
169
|
+
page.should have_content @projects[:not_empty][:files].first.elapsed_time.to_s
|
|
170
|
+
end
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
it "should display an image under each file's name to categorize percentage" do
|
|
174
|
+
within 'article#project section#files article.file' do
|
|
175
|
+
page.should have_selector '.percentage_img_container > .percentage > img'
|
|
176
|
+
end
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
it "should not display files having 0 seconds" do
|
|
180
|
+
within 'article#project section#files' do
|
|
181
|
+
page.should_not have_content @projects[:not_empty][:files].last.path
|
|
182
|
+
end
|
|
183
|
+
end
|
|
184
|
+
end
|
|
185
|
+
end
|
|
186
|
+
end
|