diff options
author | Ariejan de Vroom <ariejan@ariejan.net> | 2011-12-14 17:38:52 +0100 |
---|---|---|
committer | Ariejan de Vroom <ariejan@ariejan.net> | 2011-12-14 17:38:52 +0100 |
commit | edab46e9fa5f568b1423c0021e81d30453d7dc1e (patch) | |
tree | 8efba8b082a534e1a069f4566d55d6117951e6ba /spec | |
parent | 56fc53e8d870b70ca66332daeb6da39ab0eb5ce7 (diff) | |
download | gitlab-ce-edab46e9fa5f568b1423c0021e81d30453d7dc1e.tar.gz |
Added web hooks functionality
This commit includes:
* Projects can have zero or more WebHooks.
* The PostReceive job will ask a project to execute any web hooks defined for that project.
* WebHook has a URL, we post Github-compatible JSON to that URL.
* Failure to execute a WebHook will be silently ignored.
Diffstat (limited to 'spec')
-rw-r--r-- | spec/factories.rb | 4 | ||||
-rw-r--r-- | spec/models/project_spec.rb | 101 | ||||
-rw-r--r-- | spec/models/web_hook_spec.rb | 54 | ||||
-rw-r--r-- | spec/requests/projects_tree_perfomance_spec.rb | 1 | ||||
-rw-r--r-- | spec/spec_helper.rb | 3 | ||||
-rw-r--r-- | spec/workers/post_receive_spec.rb | 26 |
6 files changed, 188 insertions, 1 deletions
diff --git a/spec/factories.rb b/spec/factories.rb index 6951ca2c840..86e4d1e4481 100644 --- a/spec/factories.rb +++ b/spec/factories.rb @@ -54,3 +54,7 @@ Factory.add(:key, Key) do |obj| obj.title = "Example key" obj.key = File.read(File.join(Rails.root, "db", "pkey.example")) end + +Factory.add(:web_hook, WebHook) do |obj| + obj.url = Faker::Internet.url +end diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb index eda20a0c011..0afb73f8dbf 100644 --- a/spec/models/project_spec.rb +++ b/spec/models/project_spec.rb @@ -7,6 +7,7 @@ describe Project do it { should have_many(:issues) } it { should have_many(:notes) } it { should have_many(:snippets) } + it { should have_many(:web_hooks).dependent(:destroy) } end describe "Validation" do @@ -33,6 +34,7 @@ describe Project do it { should respond_to(:repo) } it { should respond_to(:tags) } it { should respond_to(:commit) } + it { should respond_to(:commits_between) } end it "should not allow 'gitolite-admin' as repo name" do @@ -50,6 +52,11 @@ describe Project do project.path_to_repo.should == File.join(Rails.root, "tmp", "tests", "somewhere") end + it "returns the full web URL for this repo" do + project = Project.new(:code => "somewhere") + project.web_url.should == "#{GIT_HOST['host']}/somewhere" + end + describe :valid_repo? do it "should be valid repo" do project = Factory :project @@ -62,6 +69,85 @@ describe Project do end end + describe "web hooks" do + let(:project) { Factory :project } + + context "with no web hooks" do + it "raises no errors" do + lambda { + project.execute_web_hooks('oldrev', 'newrev', 'ref') + }.should_not raise_error + end + end + + context "with web hooks" do + before do + @webhook = Factory(:web_hook) + @webhook_2 = Factory(:web_hook) + project.web_hooks << [@webhook, @webhook_2] + end + + it "executes multiple web hook" do + @webhook.should_receive(:execute).once + @webhook_2.should_receive(:execute).once + + project.execute_web_hooks('oldrev', 'newrev', 'ref') + end + end + + context "when gathering commit data" do + before do + @oldrev, @newrev, @ref = project.fresh_commits(2).last.sha, project.fresh_commits(2).first.sha, 'refs/heads/master' + @commit = project.fresh_commits(2).first + + # Fill nil/empty attributes + project.description = "This is a description" + + @data = project.web_hook_data(@oldrev, @newrev, @ref) + end + + subject { @data } + + it { should include(before: @oldrev) } + it { should include(after: @newrev) } + it { should include(ref: @ref) } + + context "with repository data" do + subject { @data[:repository] } + + it { should include(name: project.name) } + it { should include(url: project.web_url) } + it { should include(description: project.description) } + it { should include(homepage: project.web_url) } + it { should include(private: project.private?) } + end + + context "with commits" do + subject { @data[:commits] } + + it { should be_an(Array) } + it { should have(1).element } + + context "the commit" do + subject { @data[:commits].first } + + it { should include(id: @commit.id) } + it { should include(message: @commit.safe_message) } + it { should include(timestamp: @commit.date.xmlschema) } + it { should include(url: "http://localhost/#{project.code}/commits/#{@commit.id}") } + + context "with a author" do + subject { @data[:commits].first[:author] } + + it { should include(name: @commit.author_name) } + it { should include(email: @commit.author_email) } + end + end + end + + end + end + describe "updates" do let(:project) { Factory :project } @@ -107,6 +193,21 @@ describe Project do it { project.fresh_commits.last.id.should == "0dac878dbfe0b9c6104a87d65fe999149a8d862c" } end + describe "commits_between" do + let(:project) { Factory :project } + + subject do + commits = project.commits_between("a6d1d4aca0c85816ddfd27d93773f43a31395033", + "2fb376f61875b58bceee0492e270e9c805294b1a") + commits.map { |c| c.id } + end + + it { should have(2).elements } + it { should include("2fb376f61875b58bceee0492e270e9c805294b1a") } + it { should include("4571e226fbcd7be1af16e9fa1e13b7ac003bebdf") } + it { should_not include("a6d1d4aca0c85816ddfd27d93773f43a31395033") } + end + describe "Git methods" do let(:project) { Factory :project } diff --git a/spec/models/web_hook_spec.rb b/spec/models/web_hook_spec.rb new file mode 100644 index 00000000000..e73e554adbb --- /dev/null +++ b/spec/models/web_hook_spec.rb @@ -0,0 +1,54 @@ +require 'spec_helper' + +describe WebHook do + describe "Associations" do + it { should belong_to :project } + end + + describe "Validations" do + it { should validate_presence_of(:url) } + + context "url format" do + it { should allow_value("http://example.com").for(:url) } + it { should allow_value("https://excample.com").for(:url) } + it { should allow_value("http://test.com/api").for(:url) } + it { should allow_value("http://test.com/api?key=abc").for(:url) } + it { should allow_value("http://test.com/api?key=abc&type=def").for(:url) } + + it { should_not allow_value("example.com").for(:url) } + it { should_not allow_value("ftp://example.com").for(:url) } + it { should_not allow_value("herp-and-derp").for(:url) } + end + end + + describe "execute" do + before(:each) do + @webhook = Factory :web_hook + @project = Factory :project + @project.web_hooks << [@webhook] + @data = { before: 'oldrev', after: 'newrev', ref: 'ref'} + + WebMock.stub_request(:post, @webhook.url) + end + + it "POSTs to the web hook URL" do + @webhook.execute(@data) + WebMock.should have_requested(:post, @webhook.url).once + end + + it "POSTs the data as JSON" do + json = @data.to_json + + @webhook.execute(@data) + WebMock.should have_requested(:post, @webhook.url).with(body: json).once + end + + it "catches exceptions" do + WebHook.should_receive(:post).and_raise("Some HTTP Post error") + + lambda { + @webhook.execute(@data) + }.should_not raise_error + end + end +end diff --git a/spec/requests/projects_tree_perfomance_spec.rb b/spec/requests/projects_tree_perfomance_spec.rb index 5cf93bf9fbc..93876354416 100644 --- a/spec/requests/projects_tree_perfomance_spec.rb +++ b/spec/requests/projects_tree_perfomance_spec.rb @@ -9,7 +9,6 @@ describe "Projects" do before do @project = Factory :project @project.add_access(@user, :read) - end it "should be fast" do diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 05fd6ca7d9a..f24496ec92c 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -8,6 +8,7 @@ require 'rspec/rails' require 'capybara/rails' require 'capybara/rspec' require 'capybara/dsl' +require 'webmock/rspec' require 'factories' require 'monkeypatch' @@ -48,6 +49,8 @@ RSpec.configure do |config| end DatabaseCleaner.start + + WebMock.disable_net_connect!(allow_localhost: true) end config.after do diff --git a/spec/workers/post_receive_spec.rb b/spec/workers/post_receive_spec.rb new file mode 100644 index 00000000000..500a69982c7 --- /dev/null +++ b/spec/workers/post_receive_spec.rb @@ -0,0 +1,26 @@ +require 'spec_helper' + +describe PostReceive do + + context "as a resque worker" do + it "reponds to #perform" do + PostReceive.should respond_to(:perform) + end + end + + context "web hooks" do + let(:project) { Factory :project } + + it "it retrieves the correct project" do + Project.should_receive(:find_by_path).with(project.path) + PostReceive.perform(project.path, 'sha-old', 'sha-new', 'refs/heads/master') + end + + it "asks the project to execute web hooks" do + Project.stub(find_by_path: project) + project.should_receive(:execute_web_hooks).with('sha-old', 'sha-new', 'refs/heads/master') + + PostReceive.perform(project.path, 'sha-old', 'sha-new', 'refs/heads/master') + end + end +end |