right_hook 0.4.2 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -32,6 +32,7 @@ Or install it yourself as:
32
32
  Create an application by subclassing `RightHook::App`:
33
33
 
34
34
  ```ruby
35
+ #!/usr/bin/env ruby
35
36
  # app.rb
36
37
  require 'right_hook/app'
37
38
  require 'right_hook/event'
@@ -51,9 +52,9 @@ class MyApp < RightHook::App
51
52
  # Code to execute for GitHub's pull request hook.
52
53
  # The secret has already been verified if your code is being called.
53
54
  # See app.rb and spec/app/*_spec.rb for signatures and examples of the valid handlers.
54
- def on_pull_request(owner, repo_name, action, number, pull_request_json)
55
+ def on_pull_request(owner, repo_name, action, pull_request_json)
55
56
  message = <<-MSG
56
- GitHub user #{pull_request_json['user']['login']} has opened pull request ##{number}
57
+ GitHub user #{pull_request_json['user']['login']} has opened pull request ##{pull_request_json['number']}
57
58
  on repository #{owner}/#{repo_name}!
58
59
  MSG
59
60
  send_text_message(MY_PHONE_NUMBER, message) # or whatever you want
@@ -78,6 +79,7 @@ Typically, tokens and other secret values are stored as environment variables fo
78
79
  Here's one way you can generate and list tokens:
79
80
 
80
81
  ```ruby
82
+ #!/usr/bin/env ruby
81
83
  require 'right_hook/authenticator'
82
84
 
83
85
  puts "Please enter your username:"
@@ -101,6 +103,7 @@ Right Hook provides a way to tell GitHub you want to subscribe your Right Hook a
101
103
  It's easy!
102
104
 
103
105
  ```ruby
106
+ #!/usr/bin/env ruby
104
107
  require 'right_hook/subscriber'
105
108
 
106
109
  default_opts = {
@@ -113,7 +116,7 @@ subscriber = RightHook::Subscriber.new(default_opts)
113
116
  subscriber.subscribe(
114
117
  owner: 'octocat',
115
118
  repo_name: 'Hello-World',
116
- event_type: 'pull_request',
119
+ event_type: RightHook::Event::PULL_REQUEST,
117
120
  secret: 'secret_for_hello_world'
118
121
  )
119
122
  ```
@@ -21,12 +21,14 @@ module RightHook
21
21
  json = JSON.parse(params['payload'])
22
22
  case event_type
23
23
  when Event::PULL_REQUEST
24
- on_pull_request(owner, repo_name, json['number'], json['action'], json['pull_request'])
24
+ on_pull_request(owner, repo_name, json['action'], json['pull_request'])
25
25
  when Event::ISSUE
26
26
  on_issue(owner, repo_name, json['action'], json['issue'])
27
27
  else
28
28
  halt 500, "Server bug"
29
29
  end
30
+
31
+ 200
30
32
  end
31
33
 
32
34
  # It is up to you to override secret to determine how to look up the correct secret for an owner/repo combo.
@@ -46,4 +48,12 @@ module RightHook
46
48
  halt 202, "Signature mismatch" unless received_signature == calculated_signature
47
49
  end
48
50
  end
51
+
52
+ # Use this class if you're getting a mysterious 500 error in a test and you want to see what went wrong.
53
+ # Don't use it in production.
54
+ class DebugApp < App
55
+ disable :show_exceptions
56
+ disable :dump_errors
57
+ enable :raise_errors
58
+ end
49
59
  end
@@ -1,10 +1,13 @@
1
1
  require 'openssl'
2
2
  require 'uri'
3
+ require 'rack/test'
3
4
 
4
5
  module RightHook
5
6
  # Helpers for specs!
6
7
  # Typical usage is to include this module into your spec context, just like you would with Rack::Test::Methods.
7
8
  module SpecHelpers
9
+ include Rack::Test::Methods
10
+
8
11
  # Post to the given path, including the correct signature header based on the payload and secret.
9
12
  # @param [Hash] opts The options to use when crafting the request.
10
13
  # @option opts [String] :path The full path of the endpoint to which to post
@@ -8,6 +8,9 @@ module RightHook
8
8
  class Subscriber
9
9
  # The base URL for the binding (where your {RightHook::App} is hosted).
10
10
  attr_accessor :base_url
11
+ #
12
+ # The full target URL for the binding when used with #subscribe_direct.
13
+ attr_accessor :url
11
14
 
12
15
  # The OAuth token to use for authenticating with GitHub.
13
16
  # The token must belong to an account that has the +repo+ scope and collaborator privilege on the given repository.
@@ -20,18 +23,39 @@ module RightHook
20
23
  # See http://developer.github.com/v3/repos/hooks/ for a complete list of valid types.
21
24
  attr_accessor :event_type
22
25
 
26
+ # The user agent value to send on the request to github
27
+ # See: http://developer.github.com/v3/#user-agent-required
28
+ attr_accessor :user_agent
29
+
23
30
  # Initialize takes options which will be used as default values in other methods.
24
- # The valid keys in the options are [+base_url+, +oauth_token+, +owner+, and +event_type+].
31
+ # The valid keys in the options are [+base_url+, +oauth_token+, +owner+, +event_type+, and +user_agent+].
32
+ # @param [Hash] opts Subscription options. Defaults to attr_reader methods when such methods exist.
33
+ # @option opts [String] :owner The owner of the repository
34
+ # @option opts [String] :event_type A constant under RightHook::Event representing an event type
35
+ # @option opts [String] :base_url The URL of where the {RightHook::App} is hosted
36
+ # @option opts [String] :url The URL to receive requests from GitHub when a hook is activated
37
+ # @option opts [String] :oauth_token The OAuth token to use to authenticate with GitHub when subscribing
38
+ # @option opts [String] :user_agent The value to send for the User-Agent header when talking with GitHub
25
39
  def initialize(default_opts = {})
26
40
  @base_url = default_opts[:base_url]
41
+ @url = default_opts[:url]
27
42
  @oauth_token = default_opts[:oauth_token]
28
43
  @owner = default_opts[:owner]
29
44
  @event_type = default_opts[:event_type]
45
+ @user_agent = default_opts[:user_agent]
30
46
  end
31
47
 
32
48
  # Subscribe an instance of {RightHook::App} hosted at +base_url+ to a hook for +owner+/+repo_name+, authenticating with +oauth_token+.
33
49
  # +repo_name+ and +secret+ are required options and they are intentionally not stored as defaults on the +Subscriber+ instance.
50
+ # @param [Hash] opts Subscription options. Defaults to attr_reader methods when such methods exist.
34
51
  # @return [bool success] Whether the request was successful.
52
+ # @option opts [String] :owner The owner of the repository
53
+ # @option opts [String] :repo_name The name of the repository
54
+ # @option opts [String] :event_type A constant under RightHook::Event representing an event type
55
+ # @option opts [String] :base_url The URL of where the {RightHook::App} is hosted
56
+ # @option opts [String] :secret The secret to use to validate that a request came from GitHub. May be omitted
57
+ # @option opts [String] :oauth_token The OAuth token to use to authenticate with GitHub when subscribing
58
+ # @option opts [String] :user_agent The value to send for the User-Agent header when talking with GitHub
35
59
  def subscribe(opts)
36
60
  hub_request_with_mode('subscribe', opts)
37
61
  end
@@ -39,36 +63,82 @@ module RightHook
39
63
  # Unsubscribe an instance of {RightHook::App} hosted at +base_url+ to a hook for +owner+/+repo_name+, authenticating with +oauth_token+.
40
64
  # +repo_name+ and +secret+ are required options and they are intentionally not stored as defaults on the +Subscriber+ instance.
41
65
  # (NB: It's possible that GitHub's API *doesn't* require secret; I haven't checked.)
66
+ # @param [Hash] opts Subscription options. Defaults to attr_reader methods when such methods exist.
42
67
  # @return [bool success] Whether the request was successful.
68
+ # @option opts [String] :owner The owner of the repository
69
+ # @option opts [String] :repo_name The name of the repository
70
+ # @option opts [String] :event_type A constant under RightHook::Event representing an event type
71
+ # @option opts [String] :base_url The URL of where the {RightHook::App} is hosted
72
+ # @option opts [String] :secret The secret to use to validate that a request came from GitHub. May be omitted
73
+ # @option opts [String] :oauth_token The OAuth token to use to authenticate with GitHub when subscribing
74
+ # @option opts [String] :user_agent The value to send for the User-Agent header when talking with GitHub
43
75
  def unsubscribe(opts)
44
76
  hub_request_with_mode('unsubscribe', opts)
45
77
  end
46
78
 
79
+ # Subscribe directly to a fixed URL, rather than a calculated URL for an instance of {RightHook::App}.
80
+ # @return [bool success] Whether the request was successful.
81
+ # @param [Hash] opts Subscription options. Defaults to attr_reader methods when such methods exist.
82
+ # @option opts [String] :owner The owner of the repository
83
+ # @option opts [String] :repo_name The name of the repository
84
+ # @option opts [String] :event_type A constant under RightHook::Event representing an event type
85
+ # @option opts [String] :url The URL to receive requests from GitHub when a hook is activated
86
+ # @option opts [String] :secret The secret to use to validate that a request came from GitHub. May be omitted
87
+ # @option opts [String] :oauth_token The OAuth token to use to authenticate with GitHub when subscribing
88
+ # @option opts [String] :user_agent The value to send for the User-Agent header when talking with GitHub
89
+ def subscribe_direct(opts)
90
+ direct_hub_request_with_mode('subscribe', opts)
91
+ end
92
+
93
+ # Unsubscribe directly to a fixed URL, rather than a calculated URL for an instance of {RightHook::App}.
94
+ # @return [bool success] Whether the request was successful.
95
+ # @param [Hash] opts Subscription options. Defaults to attr_reader methods when such methods exist.
96
+ # @option opts [String] :owner The owner of the repository
97
+ # @option opts [String] :repo_name The name of the repository
98
+ # @option opts [String] :event_type A constant under RightHook::Event representing an event type
99
+ # @option opts [String] :url The URL to receive requests from GitHub when a hook is activated
100
+ # @option opts [String] :secret The secret to use to validate that a request came from GitHub. May be omitted
101
+ # @option opts [String] :oauth_token The OAuth token to use to authenticate with GitHub when subscribing
102
+ # @option opts [String] :user_agent The value to send for the User-Agent header when talking with GitHub
103
+ def unsubscribe_direct(opts)
104
+ direct_hub_request_with_mode('unsubscribe', opts)
105
+ end
106
+
47
107
  private
48
108
  def hub_request_with_mode(mode, opts)
49
109
  repo_name = opts.fetch(:repo_name) # explicitly not defaulted
50
- secret = opts.fetch(:secret) # explicitly not defaulted
51
- oauth_token = opts.fetch(:oauth_token) { self.oauth_token }
52
110
  owner = opts.fetch(:owner) { self.owner }
53
111
  base_url = opts.fetch(:base_url) { self.base_url }
54
112
  event_type = opts.fetch(:event_type) { self.event_type }
55
113
 
114
+ url = "#{base_url}/hook/#{owner}/#{repo_name}/#{event_type}"
115
+ direct_hub_request_with_mode(mode, opts.merge(url: url))
116
+ end
117
+
118
+ def direct_hub_request_with_mode(mode, opts)
119
+ repo_name = opts.fetch(:repo_name) # explicitly not defaulted
120
+ url = opts.fetch(:url) # explicitly not defaulted
121
+ secret = opts.fetch(:secret, nil)
122
+ owner = opts.fetch(:owner) { self.owner }
123
+ oauth_token = opts.fetch(:oauth_token) { self.oauth_token }
124
+ event_type = opts.fetch(:event_type) { self.event_type }
125
+ user_agent = opts.fetch(:user_agent) { self.user_agent }
126
+
56
127
  response = HTTParty.post('https://api.github.com/hub',
57
128
  headers: {
58
129
  # http://developer.github.com/v3/#authentication
59
- 'Authorization' => "token #{oauth_token}"
130
+ 'Authorization' => "token #{oauth_token}",
131
+ 'User-Agent' => user_agent.to_s
60
132
  },
61
133
  body: {
62
- 'hub.mode' => mode,
63
- 'hub.topic' => "https://github.com/#{owner}/#{repo_name}/events/#{Event.github_name(event_type)}",
64
- 'hub.callback' => "#{base_url}/hook/#{owner}/#{repo_name}/#{event_type}",
65
- 'hub.secret' => secret
66
- }
134
+ 'hub.mode' => mode,
135
+ 'hub.topic' => "https://github.com/#{owner}/#{repo_name}/events/#{Event.github_name(event_type)}",
136
+ 'hub.callback' => url,
137
+ 'hub.secret' => secret,
138
+ },
67
139
  )
68
140
 
69
- RightHook.logger.warn("Failure modifying subscription: #{response.inspect}") unless response.success?
70
-
71
- response.success?
141
+ raise "Failure modifying direct subscription: #{response.inspect}" unless response.success?
72
142
  end
73
143
  end
74
144
  end
@@ -1,3 +1,3 @@
1
1
  module RightHook
2
- VERSION = "0.4.2"
2
+ VERSION = "0.5.0"
3
3
  end
@@ -2,18 +2,15 @@ require 'spec_helper'
2
2
 
3
3
  describe RightHook::App do
4
4
  describe 'Pull requests' do
5
- include Rack::Test::Methods
6
-
7
5
  class PullRequestApp < RightHook::App
8
6
  class << self
9
- attr_accessor :owner, :repo_name, :action, :number, :pull_request_json
7
+ attr_accessor :owner, :repo_name, :action, :pull_request_json
10
8
  end
11
9
 
12
- def on_pull_request(owner, repo_name, number, action, pull_request_json)
10
+ def on_pull_request(owner, repo_name, action, pull_request_json)
13
11
  self.class.owner = owner
14
12
  self.class.repo_name = repo_name
15
13
  self.class.action = action
16
- self.class.number = number
17
14
  self.class.pull_request_json = pull_request_json
18
15
  end
19
16
 
@@ -27,7 +24,7 @@ describe RightHook::App do
27
24
  end
28
25
 
29
26
  before do
30
- app.owner = app.repo_name = app.action = app.number = app.pull_request_json = nil
27
+ app.owner = app.repo_name = app.action = app.pull_request_json = nil
31
28
  end
32
29
 
33
30
  it 'captures the interesting data' do
@@ -36,7 +33,6 @@ describe RightHook::App do
36
33
  expect(app.owner).to eq('mark-rushakoff')
37
34
  expect(app.repo_name).to eq('right_hook')
38
35
  expect(app.action).to eq('opened')
39
- expect(app.number).to eq(1)
40
36
 
41
37
  # if it has one key it probably has them all
42
38
  expect(app.pull_request_json['body']).to eq('Please pull these awesome changes')
data/spec/app_spec.rb CHANGED
@@ -3,25 +3,42 @@ require 'spec_helper'
3
3
  describe RightHook::App do
4
4
  class BareApp < RightHook::App
5
5
  def secret(owner, repo_name, event_type)
6
- ''
6
+ 'secret'
7
7
  end
8
8
  end
9
9
 
10
- def app
11
- BareApp
12
- end
10
+ let(:app) { BareApp }
13
11
 
14
- it 'is status 501 for a non-implemented hook' do
15
- post_with_signature(path: '/hook/mark-rushakoff/right_hook/issue', payload: '{}', secret: '')
16
- expect(last_response.status).to eq(501)
17
- end
12
+ context 'An app with no hooks implemented' do
13
+ it 'is status 501 for a non-implemented hook' do
14
+ post_with_signature(path: '/hook/mark-rushakoff/right_hook/issue', payload: '{}', secret: '')
15
+ expect(last_response.status).to eq(501)
16
+ end
18
17
 
19
- it 'is 404 for an unknown hook' do
20
- post_with_signature(path: '/hook/mark-rushakoff/right_hook/not_a_real_thing', payload: '{}', secret: '')
21
- expect(last_response.status).to eq(404)
18
+ it 'is 404 for an unknown hook' do
19
+ post_with_signature(path: '/hook/mark-rushakoff/right_hook/not_a_real_thing', payload: '{}', secret: '')
20
+ expect(last_response.status).to eq(404)
21
+ end
22
22
  end
23
23
 
24
24
  it 'raises NotImplementedError for an unimplemented secret' do
25
25
  expect { RightHook::App.new!.secret('owner', 'repo', 'issue') }.to raise_error(NotImplementedError)
26
26
  end
27
+
28
+ describe 'the status of a request' do
29
+ class WeirdApp < BareApp
30
+ def on_issue(owner, repo_name, action, issue_json)
31
+ 302
32
+ end
33
+ end
34
+
35
+ let(:app) { WeirdApp }
36
+
37
+ it 'is 200 regardless of what the hook method returns' do
38
+ payload = '{}'
39
+ WeirdApp.any_instance.should_receive(:on_issue).and_call_original
40
+ post_with_signature(path: '/hook/mark-rushakoff/right_hook/issue', payload: payload, secret: 'secret')
41
+ expect(last_response.status).to eq(200)
42
+ end
43
+ end
27
44
  end
data/spec/spec_helper.rb CHANGED
@@ -1,3 +1,6 @@
1
+ require 'coveralls'
2
+ Coveralls.wear!
3
+
1
4
  require 'right_hook'
2
5
  require 'right_hook/app'
3
6
  require 'right_hook/authenticated_client'
@@ -10,10 +13,6 @@ require 'right_hook/subscriber'
10
13
  require 'webmock/rspec'
11
14
  require 'rack/test'
12
15
 
13
- require 'coveralls'
14
- Coveralls.wear!
15
-
16
16
  RSpec.configure do |c|
17
- c.include Rack::Test::Methods
18
17
  c.include RightHook::SpecHelpers
19
18
  end
@@ -7,6 +7,7 @@ describe RightHook::Subscriber do
7
7
  owner: 'mark-rushakoff',
8
8
  base_url: 'http://example.com',
9
9
  event_type: RightHook::Event::ISSUE,
10
+ user_agent: 'My-User-Agent',
10
11
  )
11
12
  end
12
13
 
@@ -14,15 +15,16 @@ describe RightHook::Subscriber do
14
15
  let!(:stubbed_request) do
15
16
  stub_request(:post, 'https://api.github.com/hub').
16
17
  with(:body => 'hub.mode=subscribe&hub.topic=https%3A%2F%2Fgithub.com%2Fmark-rushakoff%2Fright_hook%2Fevents%2Fissues&hub.callback=http%3A%2F%2Fexample.com%2Fhook%2Fmark-rushakoff%2Fright_hook%2Fissue&hub.secret=the-secret',
17
- :headers => {'Authorization' => 'token my_token'}
18
+ :headers => {'Authorization' => 'token my_token', 'User-Agent' => 'My-User-Agent'}
18
19
  ).to_return(:status => status_code, :body => '', :headers => {})
19
20
  end
20
21
 
21
22
  context 'When the request succeeds' do
22
23
  let(:status_code) { 200 }
23
- it 'returns true' do
24
- result = subscriber.subscribe(repo_name: 'right_hook', secret: 'the-secret')
25
- expect(result).to eq(true)
24
+ it 'does not raise' do
25
+ expect {
26
+ subscriber.subscribe(repo_name: 'right_hook', secret: 'the-secret')
27
+ }.not_to raise_error
26
28
 
27
29
  expect(stubbed_request).to have_been_requested
28
30
  end
@@ -30,9 +32,10 @@ describe RightHook::Subscriber do
30
32
 
31
33
  context 'When the request fails' do
32
34
  let(:status_code) { 404 }
33
- it 'returns false' do
34
- result = subscriber.subscribe(repo_name: 'right_hook', secret: 'the-secret')
35
- expect(result).to eq(false)
35
+ it 'raises' do
36
+ expect {
37
+ subscriber.subscribe(repo_name: 'right_hook', secret: 'the-secret')
38
+ }.to raise_error
36
39
 
37
40
  expect(stubbed_request).to have_been_requested
38
41
  end
@@ -41,16 +44,67 @@ describe RightHook::Subscriber do
41
44
  context 'When everything is overridden' do
42
45
  let(:status_code) { 200 }
43
46
  it 'works' do
44
- s = described_class.new
45
- result = s.subscribe(
46
- repo_name: 'right_hook',
47
- secret: 'the-secret',
48
- oauth_token: 'my_token',
49
- owner: 'mark-rushakoff',
50
- base_url: 'http://example.com',
51
- event_type: RightHook::Event::ISSUE
52
- )
53
- expect(result).to eq(true)
47
+ expect {
48
+ described_class.new.subscribe(
49
+ repo_name: 'right_hook',
50
+ secret: 'the-secret',
51
+ oauth_token: 'my_token',
52
+ owner: 'mark-rushakoff',
53
+ base_url: 'http://example.com',
54
+ event_type: RightHook::Event::ISSUE,
55
+ user_agent: 'My-User-Agent',
56
+ )
57
+ }.not_to raise_error
58
+
59
+ expect(stubbed_request).to have_been_requested
60
+ end
61
+ end
62
+ end
63
+
64
+ describe '.subscribe_direct' do
65
+ let!(:stubbed_request) do
66
+ stub_request(:post, 'https://api.github.com/hub').
67
+ with(:body => 'hub.mode=subscribe&hub.topic=https%3A%2F%2Fgithub.com%2Fmark-rushakoff%2Fright_hook%2Fevents%2Fissues&hub.callback=http%3A%2F%2Fhook.example.com&hub.secret=the-secret',
68
+ :headers => {'Authorization' => 'token my_token', 'User-Agent' => 'My-User-Agent'}
69
+ ).to_return(:status => status_code, :body => '', :headers => {})
70
+ end
71
+
72
+ context 'When the request succeeds' do
73
+ let(:status_code) { 200 }
74
+ it 'does not raise' do
75
+ expect {
76
+ subscriber.subscribe_direct(repo_name: 'right_hook', secret: 'the-secret', url: 'http://hook.example.com')
77
+ }.not_to raise_error
78
+
79
+ expect(stubbed_request).to have_been_requested
80
+ end
81
+ end
82
+
83
+ context 'When the request fails' do
84
+ let(:status_code) { 404 }
85
+ it 'raises' do
86
+ expect {
87
+ subscriber.subscribe_direct(repo_name: 'right_hook', secret: 'the-secret', url: 'http://hook.example.com')
88
+ }.to raise_error
89
+
90
+ expect(stubbed_request).to have_been_requested
91
+ end
92
+ end
93
+
94
+ context 'When everything is overridden' do
95
+ let(:status_code) { 200 }
96
+ it 'works' do
97
+ expect {
98
+ described_class.new.subscribe_direct(
99
+ owner: 'mark-rushakoff',
100
+ repo_name: 'right_hook',
101
+ event_type: RightHook::Event::ISSUE,
102
+ url: 'http://hook.example.com',
103
+ secret: 'the-secret',
104
+ oauth_token: 'my_token',
105
+ user_agent: 'My-User-Agent',
106
+ )
107
+ }.not_to raise_error
54
108
 
55
109
  expect(stubbed_request).to have_been_requested
56
110
  end
@@ -61,16 +115,17 @@ describe RightHook::Subscriber do
61
115
  let!(:stubbed_request) do
62
116
  stub_request(:post, 'https://api.github.com/hub').
63
117
  with(:body => 'hub.mode=unsubscribe&hub.topic=https%3A%2F%2Fgithub.com%2Fmark-rushakoff%2Fright_hook%2Fevents%2Fissues&hub.callback=http%3A%2F%2Fexample.com%2Fhook%2Fmark-rushakoff%2Fright_hook%2Fissue&hub.secret=the-secret',
64
- :headers => {'Authorization' => 'token my_token'}
118
+ :headers => {'Authorization' => 'token my_token', 'User-Agent' => 'My-User-Agent'}
65
119
  ).to_return(:status => status_code, :body => '', :headers => {})
66
120
  end
67
121
 
68
122
 
69
123
  context 'When the request succeeds' do
70
124
  let(:status_code) { 200 }
71
- it 'returns true' do
72
- result = subscriber.unsubscribe(repo_name: 'right_hook', secret: 'the-secret')
73
- expect(result).to eq(true)
125
+ it 'does not raise' do
126
+ expect {
127
+ subscriber.unsubscribe(repo_name: 'right_hook', secret: 'the-secret')
128
+ }.not_to raise_error
74
129
 
75
130
  expect(stubbed_request).to have_been_requested
76
131
  end
@@ -78,9 +133,60 @@ describe RightHook::Subscriber do
78
133
 
79
134
  context 'When the request fails' do
80
135
  let(:status_code) { 404 }
81
- it 'returns false' do
82
- result = subscriber.unsubscribe(repo_name: 'right_hook', secret: 'the-secret')
83
- expect(result).to eq(false)
136
+ it 'raises' do
137
+ expect {
138
+ subscriber.unsubscribe(repo_name: 'right_hook', secret: 'the-secret')
139
+ }.to raise_error
140
+
141
+ expect(stubbed_request).to have_been_requested
142
+ end
143
+ end
144
+ end
145
+
146
+ describe '.unsubscribe_direct' do
147
+ let!(:stubbed_request) do
148
+ stub_request(:post, 'https://api.github.com/hub').
149
+ with(:body => 'hub.mode=unsubscribe&hub.topic=https%3A%2F%2Fgithub.com%2Fmark-rushakoff%2Fright_hook%2Fevents%2Fissues&hub.callback=http%3A%2F%2Fhook.example.com&hub.secret=the-secret',
150
+ :headers => {'Authorization' => 'token my_token', 'User-Agent' => 'My-User-Agent'}
151
+ ).to_return(:status => status_code, :body => '', :headers => {})
152
+ end
153
+
154
+ context 'When the request succeeds' do
155
+ let(:status_code) { 200 }
156
+ it 'does not raise' do
157
+ expect {
158
+ subscriber.unsubscribe_direct(repo_name: 'right_hook', secret: 'the-secret', url: 'http://hook.example.com')
159
+ }.not_to raise_error
160
+
161
+ expect(stubbed_request).to have_been_requested
162
+ end
163
+ end
164
+
165
+ context 'When the request fails' do
166
+ let(:status_code) { 404 }
167
+ it 'raises' do
168
+ expect {
169
+ subscriber.unsubscribe_direct(repo_name: 'right_hook', secret: 'the-secret', url: 'http://hook.example.com')
170
+ }.to raise_error
171
+
172
+ expect(stubbed_request).to have_been_requested
173
+ end
174
+ end
175
+
176
+ context 'When everything is overridden' do
177
+ let(:status_code) { 200 }
178
+ it 'works' do
179
+ expect {
180
+ described_class.new.unsubscribe_direct(
181
+ owner: 'mark-rushakoff',
182
+ repo_name: 'right_hook',
183
+ event_type: RightHook::Event::ISSUE,
184
+ url: 'http://hook.example.com',
185
+ secret: 'the-secret',
186
+ oauth_token: 'my_token',
187
+ user_agent: 'My-User-Agent',
188
+ )
189
+ }.not_to raise_error
84
190
 
85
191
  expect(stubbed_request).to have_been_requested
86
192
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: right_hook
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.2
4
+ version: 0.5.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-10-02 00:00:00.000000000 Z
12
+ date: 2013-12-03 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: bundler