alphasights-integrity 0.1.9.3

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 (93) hide show
  1. data/.gitignore +13 -0
  2. data/CHANGES +48 -0
  3. data/README.md +82 -0
  4. data/Rakefile +58 -0
  5. data/bin/integrity +4 -0
  6. data/config/config.sample.ru +21 -0
  7. data/config/config.sample.yml +41 -0
  8. data/config/heroku/.gems +1 -0
  9. data/config/heroku/Rakefile +6 -0
  10. data/config/heroku/config.ru +7 -0
  11. data/config/heroku/integrity-config.rb +14 -0
  12. data/config/thin.sample.yml +13 -0
  13. data/integrity.gemspec +137 -0
  14. data/lib/integrity.rb +77 -0
  15. data/lib/integrity/app.rb +138 -0
  16. data/lib/integrity/author.rb +39 -0
  17. data/lib/integrity/build.rb +52 -0
  18. data/lib/integrity/commit.rb +61 -0
  19. data/lib/integrity/core_ext/object.rb +6 -0
  20. data/lib/integrity/helpers.rb +16 -0
  21. data/lib/integrity/helpers/authorization.rb +33 -0
  22. data/lib/integrity/helpers/breadcrumbs.rb +20 -0
  23. data/lib/integrity/helpers/gravatar.rb +16 -0
  24. data/lib/integrity/helpers/pretty_output.rb +45 -0
  25. data/lib/integrity/helpers/rendering.rb +49 -0
  26. data/lib/integrity/helpers/resources.rb +19 -0
  27. data/lib/integrity/helpers/urls.rb +59 -0
  28. data/lib/integrity/installer.rb +138 -0
  29. data/lib/integrity/migrations.rb +153 -0
  30. data/lib/integrity/notifier.rb +44 -0
  31. data/lib/integrity/notifier/base.rb +74 -0
  32. data/lib/integrity/notifier/test.rb +52 -0
  33. data/lib/integrity/notifier/test/fixtures.rb +108 -0
  34. data/lib/integrity/notifier/test/hpricot_matcher.rb +38 -0
  35. data/lib/integrity/project.rb +94 -0
  36. data/lib/integrity/project/notifiers.rb +31 -0
  37. data/lib/integrity/project/push.rb +43 -0
  38. data/lib/integrity/project_builder.rb +56 -0
  39. data/lib/integrity/scm.rb +19 -0
  40. data/lib/integrity/scm/git.rb +84 -0
  41. data/lib/integrity/scm/git/uri.rb +57 -0
  42. data/public/buttons.css +82 -0
  43. data/public/reset.css +7 -0
  44. data/public/spinner.gif +0 -0
  45. data/test/acceptance/api_test.rb +97 -0
  46. data/test/acceptance/browse_project_builds_test.rb +65 -0
  47. data/test/acceptance/browse_project_test.rb +99 -0
  48. data/test/acceptance/build_notifications_test.rb +114 -0
  49. data/test/acceptance/create_project_test.rb +97 -0
  50. data/test/acceptance/delete_project_test.rb +53 -0
  51. data/test/acceptance/edit_project_test.rb +117 -0
  52. data/test/acceptance/error_page_test.rb +21 -0
  53. data/test/acceptance/installer_test.rb +81 -0
  54. data/test/acceptance/manual_build_project_test.rb +82 -0
  55. data/test/acceptance/not_found_page_test.rb +29 -0
  56. data/test/acceptance/project_syndication_test.rb +30 -0
  57. data/test/acceptance/stylesheet_test.rb +26 -0
  58. data/test/acceptance/unauthorized_page_test.rb +20 -0
  59. data/test/helpers.rb +75 -0
  60. data/test/helpers/acceptance.rb +82 -0
  61. data/test/helpers/acceptance/email_notifier.rb +52 -0
  62. data/test/helpers/acceptance/git_helper.rb +99 -0
  63. data/test/helpers/acceptance/notifier_helper.rb +47 -0
  64. data/test/helpers/acceptance/textfile_notifier.rb +26 -0
  65. data/test/helpers/expectations.rb +4 -0
  66. data/test/helpers/expectations/be_a.rb +23 -0
  67. data/test/helpers/expectations/change.rb +90 -0
  68. data/test/helpers/expectations/have.rb +105 -0
  69. data/test/helpers/expectations/predicates.rb +37 -0
  70. data/test/helpers/initial_migration_fixture.sql +44 -0
  71. data/test/unit/build_test.rb +72 -0
  72. data/test/unit/commit_test.rb +66 -0
  73. data/test/unit/helpers_test.rb +103 -0
  74. data/test/unit/integrity_test.rb +35 -0
  75. data/test/unit/migrations_test.rb +57 -0
  76. data/test/unit/notifier/base_test.rb +43 -0
  77. data/test/unit/notifier_test.rb +96 -0
  78. data/test/unit/project_builder_test.rb +118 -0
  79. data/test/unit/project_test.rb +344 -0
  80. data/test/unit/scm_test.rb +54 -0
  81. data/views/_commit_info.haml +30 -0
  82. data/views/build.haml +2 -0
  83. data/views/error.haml +37 -0
  84. data/views/home.haml +22 -0
  85. data/views/integrity.sass +424 -0
  86. data/views/layout.haml +29 -0
  87. data/views/new.haml +50 -0
  88. data/views/not_found.haml +31 -0
  89. data/views/notifier.haml +7 -0
  90. data/views/project.builder +21 -0
  91. data/views/project.haml +31 -0
  92. data/views/unauthorized.haml +38 -0
  93. metadata +324 -0
@@ -0,0 +1,96 @@
1
+ require File.dirname(__FILE__) + "/../helpers"
2
+ require "helpers/acceptance/textfile_notifier"
3
+
4
+ class NotifierTest < Test::Unit::TestCase
5
+ specify "IRC fixture is valid and can be saved" do
6
+ lambda do
7
+ Notifier.generate(:irc).tap do |project|
8
+ project.should be_valid
9
+ project.save
10
+ end
11
+ end.should change(Project, :count).by(1)
12
+ end
13
+
14
+ specify "Twitter fixture is valid and can be saved" do
15
+ lambda do
16
+ Notifier.generate(:twitter).tap do |project|
17
+ project.should be_valid
18
+ project.save
19
+ end
20
+ end.should change(Project, :count).by(1)
21
+ end
22
+
23
+ describe "Properties" do
24
+ before(:each) do
25
+ @notifier = Notifier.generate(:irc)
26
+ end
27
+
28
+ it "has a name" do
29
+ @notifier.name.should == "IRC"
30
+ end
31
+
32
+ it "has a config" do
33
+ @notifier.config.should == {:uri => "irc://irc.freenode.net/integrity"}
34
+ end
35
+ end
36
+
37
+ describe "Validation" do
38
+ it "requires a name" do
39
+ lambda do
40
+ Notifier.generate(:irc, :name => nil)
41
+ end.should_not change(Notifier, :count)
42
+ end
43
+
44
+ it "requires a config" do
45
+ lambda do
46
+ Notifier.generate(:irc, :config => nil)
47
+ end.should_not change(Notifier, :count)
48
+ end
49
+
50
+ it "requires a project" do
51
+ lambda do
52
+ Notifier.generate(:irc, :project => nil)
53
+ end.should_not change(Notifier, :count)
54
+ end
55
+
56
+ it "requires an unique name in project scope" do
57
+ project = Project.generate
58
+ irc = Notifier.gen(:irc, :project => project)
59
+
60
+ project.tap { |project| project.notifiers << irc }.save
61
+
62
+ lambda do
63
+ project.tap { |project| project.notifiers << irc }.save
64
+ end.should_not change(project.notifiers, :count).from(1).to(2)
65
+
66
+ lambda { Notifier.gen(:irc) }.should change(Notifier, :count).to(2)
67
+ end
68
+ end
69
+
70
+ describe "Registering a notifier" do
71
+ it "registers given notifier class" do
72
+ Notifier.register(Integrity::Notifier::Textfile)
73
+
74
+ assert_equal Integrity::Notifier::Textfile,
75
+ Notifier.available["Textfile"]
76
+ end
77
+
78
+ it "raises ArgumentError if given class is not a valid notifier" do
79
+ assert_raise(ArgumentError) {
80
+ Notifier.register(Class.new)
81
+ }
82
+
83
+ assert Notifier.available.empty?
84
+ end
85
+ end
86
+
87
+ it "knows how to notify the world of a build" do
88
+ irc = Notifier.gen(:irc)
89
+ Notifier.register(Integrity::Notifier::IRC)
90
+ build = Build.gen
91
+
92
+ mock(Notifier::IRC).notify_of_build(build, irc.config) { nil }
93
+
94
+ irc.notify_of_build(build)
95
+ end
96
+ end
@@ -0,0 +1,118 @@
1
+ require File.dirname(__FILE__) + "/../helpers"
2
+
3
+ class ProjectBuilderTest < Test::Unit::TestCase
4
+ before(:all) do
5
+ unless File.directory?(Integrity.config[:export_directory])
6
+ FileUtils.mkdir(Integrity.config[:export_directory])
7
+ end
8
+
9
+ @directory = Integrity.config[:export_directory] + "/foca-integrity-master"
10
+ FileUtils.mkdir(@directory)
11
+ end
12
+
13
+ after(:all) do
14
+ FileUtils.rm_rf(@directory)
15
+ end
16
+
17
+ before(:each) do
18
+ @project = Integrity::Project.generate(:integrity, :command => "echo 'output!'")
19
+ ignore_logs!
20
+ end
21
+
22
+ it "creates a new SCM with given project's uri, branch and export_directory" do
23
+ SCM::Git.expects(:new).with(@project.uri, @project.branch, @directory)
24
+ ProjectBuilder.new(@project)
25
+ end
26
+
27
+ describe "When building" do
28
+ before(:each) do
29
+ @commit = @project.commits.gen(:pending)
30
+ end
31
+
32
+ it "sets the started and completed timestamps" do
33
+ SCM::Git.any_instance.expects(:with_revision).with(@commit.identifier).yields
34
+ SCM::Git.any_instance.expects(:info).returns({})
35
+
36
+ build = ProjectBuilder.new(@project).build(@commit)
37
+ build.output.should == "output!\n"
38
+ build.started_at.should_not be_nil
39
+ build.completed_at.should_not be_nil
40
+ build.should be_successful
41
+ end
42
+
43
+ it "ensures completed_at is set, even if something horrible happens" do
44
+ lambda {
45
+ SCM::Git.any_instance.expects(:with_revision).with(@commit.identifier).raises
46
+ SCM::Git.any_instance.expects(:info).returns({})
47
+
48
+ build = ProjectBuilder.new(@project).build(@commit)
49
+ build.started_at.should_not be_nil
50
+ build.completed_at.should_not be_nil
51
+ build.should be_failed
52
+ }.should raise_error
53
+ end
54
+
55
+ it "sets the build status to failure when the build command exits with a non-zero status" do
56
+ @project.update_attributes(:command => "exit 1")
57
+ SCM::Git.any_instance.expects(:with_revision).with(@commit.identifier).yields
58
+ SCM::Git.any_instance.expects(:info).returns({})
59
+
60
+ build = ProjectBuilder.new(@project).build(@commit)
61
+ build.should be_failed
62
+ end
63
+
64
+ it "sets the build status to success when the build command exits with a zero status" do
65
+ @project.update_attributes(:command => "exit 0")
66
+ SCM::Git.any_instance.expects(:with_revision).with(@commit.identifier).yields
67
+ SCM::Git.any_instance.expects(:info).returns({})
68
+
69
+ build = ProjectBuilder.new(@project).build(@commit)
70
+ build.should be_successful
71
+ end
72
+
73
+ it "runs the command in the export directory" do
74
+ @project.update_attributes(:command => "cat foo.txt")
75
+ File.open(@directory + "/foo.txt", "w") { |file| file << "bar!" }
76
+ SCM::Git.any_instance.expects(:with_revision).with(@commit.identifier).yields
77
+ SCM::Git.any_instance.expects(:info).returns({})
78
+
79
+ build = ProjectBuilder.new(@project).build(@commit)
80
+ build.output.should == "bar!"
81
+ end
82
+
83
+ it "captures both stdout and stderr" do
84
+ @project.update_attributes(:command => "echo foo through out && echo bar through err 1>&2")
85
+ SCM::Git.any_instance.expects(:with_revision).with(@commit.identifier).yields
86
+ SCM::Git.any_instance.expects(:info).returns({})
87
+
88
+ build = ProjectBuilder.new(@project).build(@commit)
89
+ build.output.should == "foo through out\nbar through err\n"
90
+ end
91
+
92
+ it "raises SCMUnknownError if it can't figure the scm from the uri" do
93
+ @project.update_attributes(:uri => "scm://example.org")
94
+ lambda { ProjectBuilder.new(@project) }.should raise_error(SCM::SCMUnknownError)
95
+ end
96
+
97
+ it "doesn't fail if the commit identifier can't be retrieved" do
98
+ SCM::Git.any_instance.expects(:with_revision).with(@commit.identifier).yields
99
+ SCM::Git.any_instance.expects(:info).returns(false)
100
+ lambda {
101
+ ProjectBuilder.new(@project).build(@commit)
102
+ }.should_not raise_error
103
+ end
104
+ end
105
+
106
+ describe "When deleting the code from disk" do
107
+ it "destroys the directory" do
108
+ lambda do
109
+ ProjectBuilder.new(@project).delete_code
110
+ end.should change(Pathname.new(@directory), :directory?).from(true).to(false)
111
+ end
112
+
113
+ it "don't complains if the directory doesn't exists" do
114
+ Pathname.new(@directory).should_not be_directory
115
+ lambda { ProjectBuilder.new(@project).delete_code }.should_not raise_error
116
+ end
117
+ end
118
+ end
@@ -0,0 +1,344 @@
1
+ require File.dirname(__FILE__) + "/../helpers"
2
+
3
+ class ProjectTest < Test::Unit::TestCase
4
+ before(:each) do
5
+ RR.reset
6
+ ignore_logs!
7
+ end
8
+
9
+ specify "default fixture is valid and can be saved" do
10
+ lambda do
11
+ Project.generate.tap do |project|
12
+ project.should be_valid
13
+ project.save
14
+ end
15
+ end.should change(Project, :count).by(1)
16
+ end
17
+
18
+ specify "integrity fixture is valid and can be saved" do
19
+ lambda do
20
+ Project.generate(:integrity).tap do |project|
21
+ project.should be_valid
22
+ project.save
23
+ end
24
+ end.should change(Project, :count).by(1)
25
+ end
26
+
27
+ describe "Properties" do
28
+ before(:each) do
29
+ @project = Project.generate(:integrity)
30
+ end
31
+
32
+ it "has a name" do
33
+ @project.name.should == "Integrity"
34
+ end
35
+
36
+ it "has a permalink" do
37
+ @project.permalink.should == "integrity"
38
+
39
+ @project.tap do |project|
40
+ project.name = "foo's bar/baz and BACON?!"
41
+ project.save
42
+ end.permalink.should == "foos-bar-baz-and-bacon"
43
+ end
44
+
45
+ it "has an URI" do
46
+ @project.uri.should == Addressable::URI.parse("git://github.com/foca/integrity.git")
47
+ end
48
+
49
+ it "has a branch" do
50
+ @project.branch.should == "master"
51
+ end
52
+
53
+ specify "branch defaults to master" do
54
+ Project.new.branch.should == "master"
55
+ end
56
+
57
+ it "has a command" do
58
+ # TODO: rename to build_command
59
+ @project.command.should == "rake"
60
+ end
61
+
62
+ specify "command defaults to 'rake'" do
63
+ Project.new.command.should == "rake"
64
+ end
65
+
66
+ it "has a building flag" do
67
+ @project.should_not be_building
68
+ end
69
+
70
+ specify "building flag default to false" do
71
+ Project.new.should_not be_building
72
+ end
73
+
74
+ it "knows it's visibility" do
75
+ # TODO: rename Project#public property to visibility
76
+ # TODO: and have utility method to query its state instead
77
+
78
+ Project.new.should be_public
79
+
80
+ @project.should be_public
81
+ @project.tap { |p| p.public = "1" }.should be_public
82
+ @project.tap { |p| p.public = "0" }.should_not be_public
83
+
84
+ Project.gen(:public => "false").should be_public
85
+ Project.gen(:public => "true").should be_public
86
+ Project.gen(:public => false).should_not be_public
87
+ Project.gen(:public => nil).should_not be_public
88
+ end
89
+
90
+ it "has a created_at" do
91
+ @project.created_at.should be_a(DateTime)
92
+ end
93
+
94
+ it "has an updated_at" do
95
+ @project.updated_at.should be_a(DateTime)
96
+ end
97
+
98
+ it "knows it's status" do
99
+ Project.gen(:commits => 1.of{ Commit.gen(:successful) }).status.should == :success
100
+ Project.gen(:commits => 2.of{ Commit.gen(:successful) }).status.should == :success
101
+ Project.gen(:commits => 2.of{ Commit.gen(:failed) }).status.should == :failed
102
+ Project.gen(:commits => 1.of{ Commit.gen(:pending) }).status.should == :pending
103
+ Project.gen(:commits => []).status.should be_nil
104
+ end
105
+
106
+ it "knows it's last build" do
107
+ Project.gen(:commits => []).last_commit.should be_nil
108
+
109
+ commits = 5.of { Commit.gen(:successful) }
110
+ project = Project.gen(:commits => commits)
111
+ project.last_commit.should == commits.sort_by {|c| c.committed_at }.last
112
+ end
113
+ end
114
+
115
+ describe "Validation" do
116
+ it "requires a name" do
117
+ lambda do
118
+ Project.gen(:name => nil).should_not be_valid
119
+ end.should_not change(Project, :count)
120
+ end
121
+
122
+ it "requires an URI" do
123
+ lambda do
124
+ Project.gen(:uri => nil).should_not be_valid
125
+ end.should_not change(Project, :count)
126
+ end
127
+
128
+ it "requires a branch" do
129
+ lambda do
130
+ Project.gen(:branch => nil).should_not be_valid
131
+ end.should_not change(Project, :count)
132
+ end
133
+
134
+ it "requires a command" do
135
+ lambda do
136
+ Project.gen(:command => nil).should_not be_valid
137
+ end.should_not change(Project, :count)
138
+ end
139
+
140
+ it "ensures its name is unique" do
141
+ Project.gen(:name => "Integrity")
142
+ lambda do
143
+ Project.gen(:name => "Integrity").should_not be_valid
144
+ end.should_not change(Project, :count)
145
+ end
146
+ end
147
+
148
+ describe "When finding its previous builds" do
149
+ before(:each) do
150
+ @project = Project.generate(:commits => 5.of { Commit.gen })
151
+ @commits = @project.commits.sort_by {|c| c.committed_at }.reverse
152
+ end
153
+
154
+ it "has 4 previous builds" do
155
+ @project.should have(4).previous_commits
156
+ end
157
+
158
+ it "returns the builds ordered chronogicaly (desc) by creation date" do
159
+ @project.previous_commits.should == @commits[1..-1]
160
+ end
161
+
162
+ it "excludes the last build" do
163
+ @project.previous_commits.should_not include(@project.last_commit)
164
+ end
165
+
166
+ it "returns an empty array if it has only one build" do
167
+ project = Project.gen(:commits => 1.of { Integrity::Commit.gen })
168
+ project.should have(:no).previous_commits
169
+ end
170
+
171
+ it "returns an empty array if there are no builds" do
172
+ project = Project.gen(:commits => [])
173
+ project.should have(:no).previous_commits
174
+ end
175
+ end
176
+
177
+ describe "When getting destroyed" do
178
+ before(:each) do
179
+ @commits = 7.of { Commit.gen }
180
+ @project = Project.generate(:commits => @commits)
181
+ end
182
+
183
+ it "destroys itself and tell ProjectBuilder to delete the code from disk" do
184
+ lambda do
185
+ stub.instance_of(ProjectBuilder).delete_code
186
+ @project.destroy
187
+ end.should change(Project, :count).by(-1)
188
+ end
189
+
190
+ it "destroys its builds" do
191
+ lambda do
192
+ @project.destroy
193
+ end.should change(Commit, :count).by(-7)
194
+ end
195
+ end
196
+
197
+ describe "When updating its notifiers" do
198
+ setup do
199
+ twitter = Notifier.gen(:twitter, :enabled => true)
200
+ irc = Notifier.gen(:irc, :enabled => false)
201
+
202
+ @project = Project.gen(:notifiers => [twitter, irc])
203
+ end
204
+
205
+ it "creates and enable the given notifiers" do
206
+ Notifier.all.destroy!
207
+
208
+ project = Project.gen
209
+ project.update_notifiers(["IRC", "Twitter"],
210
+ {"IRC" => {"uri" => "irc://irc.freenode.net/integrity"},
211
+ "Twitter" => {"username" => "john"}})
212
+
213
+ assert_equal 2, Notifier.count
214
+ assert_equal 2, project.enabled_notifiers.count
215
+ assert_equal "IRC", project.notifiers.first.name
216
+ assert_equal "Twitter", project.notifiers.last.name
217
+
218
+ project.update_notifiers(["Twitter"],
219
+ {"IRC" => {"uri" => "irc://irc.freenode.net/integrity"},
220
+ "Twitter" => {"username" => "john"}})
221
+
222
+ assert_equal 2, Notifier.count
223
+ assert ! project.notifies?("IRC")
224
+ assert project.notifies?("Twitter")
225
+ end
226
+
227
+ it "creates notifiers present in config even when they're disabled" do
228
+ @project.update_notifiers(["IRC"],
229
+ {"IRC" => {"uri" => "irc://irc.freenode.net/integrity"},
230
+ "Twitter" => {"username" => "john"}})
231
+
232
+ assert_equal 2, @project.notifiers.count
233
+ end
234
+
235
+ it "disables notifiers that are not included in the list" do
236
+ @project.update_notifiers(["IRC"],
237
+ {"IRC" => {"uri" => "irc://irc.freenode.net/integrity"},
238
+ "Twitter" => {"username" => "john"}})
239
+
240
+ @project.update_notifiers(["IRC"],
241
+ {"IRC" => {"uri" => "irc://irc.freenode.net/integrity"}})
242
+
243
+ assert ! @project.notifiers.first(:name => "Twitter").enabled?
244
+ assert @project.notifiers.first(:name => "IRC").enabled?
245
+ end
246
+
247
+ it "preserves config of notifiers that are being disabled" do
248
+ @project.update_notifiers(["IRC"],
249
+ {"IRC" => {"uri" => "irc://irc.freenode.net/integrity"},
250
+ "Twitter" => {"username" => "john"}})
251
+
252
+ assert_equal "john",
253
+ @project.notifiers.first(:name => "Twitter").config["username"]
254
+ end
255
+
256
+ it "does nothing if given nil as the list of notifiers to enable" do
257
+ lambda { Project.gen.update_notifiers(nil, {}) }.should_not change(Notifier, :count)
258
+ end
259
+
260
+ it "doesn't destroy any of the other notifiers that exist for other projects" do
261
+ irc = Notifier.generate(:irc)
262
+
263
+ project = Project.gen
264
+ project.update_notifiers("IRC", {"IRC" => irc.config})
265
+
266
+ lambda {
267
+ Project.gen.update_notifiers("IRC", {"IRC" => irc.config})
268
+ }.should_not change(project.notifiers, :count)
269
+ end
270
+ end
271
+
272
+ describe "When retrieving state about its notifier" do
273
+ before(:each) do
274
+ @project = Project.gen
275
+ @irc = Notifier.generate(:irc)
276
+ end
277
+
278
+ it "knows which notifiers are enabled" do
279
+ notifiers = [Notifier.gen(:irc, :enabled => false),
280
+ Notifier.gen(:twitter, :enabled => true)]
281
+ project = Project.gen(:notifiers => notifiers)
282
+
283
+ assert_equal 1, project.enabled_notifiers.size
284
+ end
285
+
286
+ specify "#config_for returns given notifier's configuration" do
287
+ @project.update_attributes(:notifiers => [@irc])
288
+ @project.config_for("IRC").should == {:uri => "irc://irc.freenode.net/integrity"}
289
+ end
290
+
291
+ specify "#config_for returns an empty hash for unknown notifier" do
292
+ @project.config_for("IRC").should == {}
293
+ end
294
+
295
+ specify "#notifies? is true if the notifier exists and is enabled" do
296
+ assert ! @project.notifies?("UndefinedNotifier")
297
+
298
+ @project.update_attributes(:notifiers =>
299
+ [ Notifier.gen(:irc, :enabled => true),
300
+ Notifier.gen(:twitter, :enabled => false) ])
301
+
302
+ assert @project.notifies?("IRC")
303
+ assert ! @project.notifies?("Twitter")
304
+ end
305
+ end
306
+
307
+ describe "When building a commit" do
308
+ before(:each) do
309
+ @commits = 2.of { Commit.gen }
310
+ @project = Project.gen(:integrity, :commits => @commits)
311
+ stub.instance_of(ProjectBuilder).build { nil }
312
+ end
313
+
314
+ it "gets the specified commit and creates a pending build for it" do
315
+ commit = @commits.last
316
+
317
+ lambda {
318
+ @project.build(commit.identifier)
319
+ }.should change(Build, :count).by(1)
320
+
321
+ build = Build.all.last
322
+ build.commit.should be(commit)
323
+ build.should be_pending
324
+
325
+ commit.should be_pending
326
+ end
327
+
328
+ it "creates an empty commit with the head of the project if passed 'HEAD' (the default)" do
329
+ mock(@project).head_of_remote_repo { "FOOBAR" }
330
+
331
+ lambda {
332
+ @project.build("HEAD")
333
+ }.should change(Commit, :count).by(1)
334
+
335
+ build = Build.all.last
336
+ build.commit.should == @project.last_commit
337
+
338
+ @project.last_commit.should be_pending
339
+ @project.last_commit.identifier.should == "FOOBAR"
340
+ @project.last_commit.author.name.should == "<Commit author not loaded>"
341
+ @project.last_commit.message.should == "<Commit message not loaded>"
342
+ end
343
+ end
344
+ end