github_api 0.4.2 → 0.4.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. data/README.md +2 -2
  2. data/features/authentication.feature +8 -0
  3. data/features/cassettes/errors/repos/create.yml +36 -0
  4. data/features/cassettes/gists/gist.yml +64 -0
  5. data/features/cassettes/gists/gist/first.yml +65 -0
  6. data/features/cassettes/gists/gists/public_all.yml +71 -0
  7. data/features/cassettes/gists/gists/user_all.yml +48 -0
  8. data/features/cassettes/gists/star.yml +34 -0
  9. data/features/cassettes/pagination/repos/per_page/1.yml +134 -0
  10. data/features/cassettes/pagination/repos/per_page/each_page.yml +395 -0
  11. data/features/cassettes/pagination/repos/per_page/first.yml +135 -0
  12. data/features/error_codes.feature +13 -0
  13. data/features/gists.feature +31 -0
  14. data/features/pagination.feature +10 -0
  15. data/features/repos.feature +12 -10
  16. data/features/step_definitions/github_api_steps.rb +20 -5
  17. data/features/support/env.rb +8 -0
  18. data/features/support/helpers.rb +7 -0
  19. data/lib/github_api.rb +6 -6
  20. data/lib/github_api/api.rb +19 -11
  21. data/lib/github_api/authorization.rb +3 -3
  22. data/lib/github_api/connection.rb +1 -1
  23. data/lib/github_api/core_ext/array.rb +1 -2
  24. data/lib/github_api/core_ext/hash.rb +16 -2
  25. data/lib/github_api/deprecation.rb +39 -0
  26. data/lib/github_api/gists.rb +27 -10
  27. data/lib/github_api/page_uri_processor.rb +6 -2
  28. data/lib/github_api/response/raise_error.rb +1 -1
  29. data/lib/github_api/result.rb +2 -1
  30. data/lib/github_api/version.rb +1 -1
  31. data/spec/fixtures/gists/gist.json +58 -0
  32. data/spec/fixtures/gists/gists.json +28 -0
  33. data/spec/github/api_spec.rb +15 -0
  34. data/spec/github/authorization_spec.rb +5 -0
  35. data/spec/github/client_spec.rb +4 -0
  36. data/spec/github/core_ext/hash_spec.rb +45 -18
  37. data/spec/github/deprecation_spec.rb +31 -0
  38. data/spec/github/gists_spec.rb +461 -3
  39. data/spec/github/repos/watching_spec.rb +12 -4
  40. data/spec/github/request_spec.rb +3 -0
  41. data/spec/github_spec.rb +34 -29
  42. data/spec/spec_helper.rb +1 -0
  43. metadata +22 -4
@@ -0,0 +1,13 @@
1
+ Feature: Handles HTTP error codes
2
+
3
+ In order to handle error cases accordingly
4
+ As a developer
5
+ I want to be informed of non-successful responses
6
+
7
+ Scenario: A response of '401 - Unauthorised access'
8
+ Given I have "Github::Repos" instance
9
+ When I am looking for "create_repo"
10
+ And I pass the following request options:
11
+ | name |
12
+ | basic_auth |
13
+ Then request should fail with "Github::Unauthorised" within a cassette named "errors/repos/create"
@@ -0,0 +1,31 @@
1
+ Feature: Accessing Gists Main API
2
+ In order to interact with github gists
3
+ GithubAPI gem
4
+ Should return the expected results depending on passed parameters
5
+
6
+ Background:
7
+ Given I have "Github::Gists" instance
8
+
9
+ Scenario: Lists all user's gists
10
+ When I am looking for "gists" with the following params:
11
+ | user |
12
+ | peter-murach |
13
+ And I make request within a cassette named "gists/gists/user_all"
14
+ Then the response should be "200"
15
+ And the response type should be "JSON"
16
+
17
+ Scenario: Lists all public gists
18
+ When I am looking for "gists" with the following params:
19
+ | user |
20
+ | nil |
21
+ And I make request within a cassette named "gists/gists/public_all"
22
+ Then the response should be "200"
23
+ And the response type should be "JSON"
24
+
25
+ Scenario: Gets a single gist
26
+ When I am looking for "gist" with the following params:
27
+ | gist_id |
28
+ | 1738161 |
29
+ And I make request within a cassette named "gists/gist"
30
+ Then the response should be "200"
31
+ And the response type should be "JSON"
@@ -65,3 +65,13 @@ Feature: Githu API pagination
65
65
  And the response should have 30 items
66
66
  And the response collection of resources is different for "sha" attribute
67
67
 
68
+ Scenario: Requesting resources with per_page helper
69
+ Given I have "Github::Repos" instance
70
+ When I am looking for "repos"
71
+ And I pass the following request options:
72
+ | user |
73
+ | wycats |
74
+ And I make request within a cassette named "pagination/repos/per_page/first"
75
+ Then the response should be "200"
76
+ When I iterate through collection pages within a cassette named "pagination/repos/per_page/each_page"
77
+ Then this collection should include first page
@@ -3,28 +3,30 @@ Feature: Accessing Repos Main API
3
3
  GithubAPI gem
4
4
  Should return the expected results depending on passed parameters
5
5
 
6
- Scenario: Returning all repository branches
6
+ Background:
7
7
  Given I have "Github::Repos" instance
8
+
9
+ Scenario: Returning all repository branches
8
10
  When I am looking for "branches" with the following params:
9
11
  | user | repo |
10
12
  | peter-murach | github |
11
- And I make request within a cassette named "repos/branches"
13
+ And I make request within a cassette named "repos/branches"
12
14
  Then the response should be "200"
13
- And the response type should be "JSON"
15
+ And the response type should be "JSON"
14
16
 
15
17
  Scenario: Returning all repository tags
16
- Given I have "Github::Repos" instance
17
18
  When I am looking for "tags" with the following params:
18
19
  | user | repo |
19
20
  | peter-murach | github |
20
- And I make request within a cassette named "repos/tags"
21
+ And I make request within a cassette named "repos/tags"
21
22
  Then the response should be "200"
23
+ And the response type should be "JSON"
22
24
 
23
25
  Scenario: Returning all repositories for the user
24
- Given I have "Github::Repos" instance
25
26
  When I am looking for "list_repos"
26
- And I pass the following request options:
27
- | user |
28
- | peter-murach |
29
- And I make request within a cassette named "repos/tags"
27
+ And I pass the following request options:
28
+ | user |
29
+ | peter-murach |
30
+ And I make request within a cassette named "repos/tags"
30
31
  Then the response should be "200"
32
+ And the response type should be "JSON"
@@ -3,11 +3,7 @@ Given /^I have github instance$/ do
3
3
  end
4
4
 
5
5
  Given /^I have "([^"]*)" instance$/ do |api_classes|
6
- constant = Object
7
- api_classes.split('::').each do |api_class|
8
- constant = constant.const_get api_class
9
- end
10
- @instance = constant.new
6
+ @instance = convert_to_constant(api_classes).new
11
7
  end
12
8
 
13
9
  When /^I fetch "([^"]*)"$/ do |method|
@@ -45,6 +41,25 @@ When /^I request "([^"]*)" page$/ do |link|
45
41
  @next_response = @response.send :"#{link}_page"
46
42
  end
47
43
 
44
+ When /^I iterate through collection pages$/ do
45
+ @pages = []
46
+ @response.each_page do |page|
47
+ @pages << page.flatten
48
+ end
49
+ end
50
+
48
51
  Then /^the response collection of resources is different for "([^"]*)" attribute$/ do |attr|
49
52
  @next_response.first.send(:"#{attr}").should_not eql @response.first.send(:"#{attr}")
50
53
  end
54
+
55
+ Then /^this collection should include first page$/ do
56
+ @pages.flatten.map(&:name).should include @response.first.name
57
+ end
58
+
59
+ Then /^request should fail with "([^"]*)"$/ do |exception|
60
+ @options ||= {}
61
+ @attributes ||= {}
62
+ expect {
63
+ @response = @instance.send @method, *@attributes.values, @options
64
+ }.to raise_error(convert_to_constant(exception))
65
+ end
@@ -7,6 +7,14 @@ rescue Bundler::BundlerError => e
7
7
  exit e.status_code
8
8
  end
9
9
 
10
+ $LOAD_PATH.unshift(File.dirname(__FILE__) + '/../../spec')
11
+
12
+ if RUBY_VERSION > '1.9' and ENV['COVERAGE']
13
+ require 'coverage_adapter'
14
+ SimpleCov.start 'github_api'
15
+ SimpleCov.coverage_dir 'coverage/cucumber'
16
+ end
17
+
10
18
  $LOAD_PATH.unshift(File.dirname(__FILE__) + '/../../lib')
11
19
  require 'github_api'
12
20
 
@@ -0,0 +1,7 @@
1
+ def convert_to_constant(classes)
2
+ constant = Object
3
+ classes.split('::').each do |klass|
4
+ constant = constant.const_get klass
5
+ end
6
+ return constant
7
+ end
@@ -5,21 +5,21 @@ require 'github_api/configuration'
5
5
  require 'github_api/constants'
6
6
  require 'github_api/utils/url'
7
7
  require 'github_api/connection'
8
+ require 'github_api/deprecation'
8
9
 
9
10
  module Github
10
11
  extend Configuration
11
12
 
12
13
  class << self
14
+
15
+ # Handle for the client instance
16
+ attr_accessor :api_client
17
+
13
18
  # Alias for Github::Client.new
14
19
  #
15
20
  # @return [Github::Client]
16
21
  def new(options = {}, &block)
17
- @@api_client = Github::Client.new(options, &block)
18
- end
19
-
20
- # Returns handle for the client instance
21
- def api_client
22
- @@api_client
22
+ @api_client = Github::Client.new(options, &block)
23
23
  end
24
24
 
25
25
  # Delegate to Github::Client
@@ -44,6 +44,7 @@ module Github
44
44
  send("#{key}=", options[key])
45
45
  end
46
46
  _process_basic_auth(options[:basic_auth])
47
+ _set_api_client
47
48
  client if client_id? && client_secret?
48
49
 
49
50
  self.instance_eval(&block) if block_given?
@@ -55,14 +56,27 @@ module Github
55
56
  def _process_basic_auth(auth)
56
57
  case auth
57
58
  when String
58
- login = auth.split(':').first
59
- password = auth.split(':').last
59
+ self.login = auth.split(':').first
60
+ self.password = auth.split(':').last
60
61
  when Hash
61
- login = auth[:login]
62
- password = auth[:password]
62
+ self.login = auth[:login]
63
+ self.password = auth[:password]
63
64
  end
64
65
  end
65
66
 
67
+ # Assigns current api class
68
+ def _set_api_client
69
+ Github.api_client = self
70
+ end
71
+
72
+ # Passes configuration options to instantiated class
73
+ def _create_instance(klass, options)
74
+ options.symbolize_keys!
75
+ instance = klass.send :new, options
76
+ Github.api_client = instance
77
+ instance
78
+ end
79
+
66
80
  # Responds to attribute query or attribute clear
67
81
  def method_missing(method, *args, &block) # :nodoc:
68
82
  case method.to_s
@@ -77,7 +91,7 @@ module Github
77
91
 
78
92
  def _validate_inputs(required, provided) # :nodoc:
79
93
  required.all? do |key|
80
- provided.has_key? key
94
+ provided.has_deep_key? key
81
95
  end
82
96
  end
83
97
 
@@ -187,12 +201,6 @@ module Github
187
201
  end
188
202
  end
189
203
 
190
- # Passes configuration options to instantiated class
191
- def _create_instance(klass, options)
192
- options.symbolize_keys!
193
- klass.new(options)
194
- end
195
-
196
204
  def _token_required
197
205
  end
198
206
 
@@ -54,10 +54,10 @@ module Github
54
54
 
55
55
  # Select authentication parameters
56
56
  def authentication
57
- if login? && password?
58
- { :login => login, :password => password }
59
- elsif basic_auth?
57
+ if basic_auth?
60
58
  { :basic_auth => basic_auth }
59
+ elsif login? && password?
60
+ { :login => login, :password => password }
61
61
  else
62
62
  { }
63
63
  end
@@ -54,7 +54,7 @@ module Github
54
54
  builder.use Faraday::Request::JSON
55
55
  builder.use Faraday::Request::Multipart
56
56
  builder.use Faraday::Request::UrlEncoded
57
- builder.use Faraday::Response::Logger
57
+ builder.use Faraday::Response::Logger if ENV['DEBUG']
58
58
 
59
59
  builder.use Github::Request::OAuth2, oauth_token if oauth_token?
60
60
  builder.use Github::Request::BasicAuth, authentication if basic_authed?
@@ -1,7 +1,6 @@
1
1
  class Array # :nodoc:
2
2
 
3
3
  def except(*keys) # :nodoc:
4
- puts "module except works!!!"
5
4
  self.dup.except!(*keys)
6
5
  end unless method_defined?(:except)
7
6
 
@@ -11,4 +10,4 @@ class Array # :nodoc:
11
10
  copy
12
11
  end unless method_defined?(:except!)
13
12
 
14
- end # Hash
13
+ end # Array
@@ -1,7 +1,6 @@
1
1
  class Hash # :nodoc:
2
2
 
3
3
  def except(*items) # :nodoc:
4
- puts "array except works!!!"
5
4
  self.dup.except!(*items)
6
5
  end unless method_defined?(:except)
7
6
 
@@ -16,7 +15,7 @@ class Hash # :nodoc:
16
15
  hash[(key.to_sym rescue key) || key] = value
17
16
  hash
18
17
  end
19
- end
18
+ end unless method_defined?(:symbolize_keys)
20
19
 
21
20
  def symbolize_keys! # :nodoc:
22
21
  hash = symbolize_keys
@@ -39,4 +38,19 @@ class Hash # :nodoc:
39
38
  self.map { |key, val| [key, val].join("=") }.join("&")
40
39
  end unless method_defined?(:serialize)
41
40
 
41
+ def all_keys # :nodoc:
42
+ keys = self.keys
43
+ keys.each do |key|
44
+ if self[key].is_a?(Hash)
45
+ keys << self[key].all_keys.compact.flatten
46
+ next
47
+ end
48
+ end
49
+ keys.flatten
50
+ end unless method_defined?(:all_keys)
51
+
52
+ def has_deep_key?(key)
53
+ self.all_keys.include? key
54
+ end unless method_defined?(:has_deep_key?)
55
+
42
56
  end # Hash
@@ -0,0 +1,39 @@
1
+ # encoding: utf-8
2
+
3
+ module Github
4
+
5
+ DEPRECATION_PREFIX = "[GithubAPI] Deprecation warning:"
6
+
7
+ class << self
8
+
9
+ attr_writer :deprecation_tracker
10
+
11
+ def deprecation_tracker
12
+ @deprecation_tracker ||= []
13
+ end
14
+
15
+ # Displays deprecation message to the user.
16
+ # Each message is printed once.
17
+ def deprecate(method, alternate_method=nil)
18
+ return if deprecation_tracker.include? method
19
+ deprecation_tracker << method
20
+
21
+ message = <<-NOTICE
22
+ #{DEPRECATION_PREFIX}
23
+
24
+ * #{method} is deprecated.
25
+ NOTICE
26
+ if alternate_method
27
+ message << <<-ADDITIONAL
28
+ * please use #{alternate_method} instead.
29
+ ADDITIONAL
30
+ end
31
+ warn_deprecation(message)
32
+ end
33
+
34
+ def warn_deprecation(message)
35
+ send :warn, message
36
+ end
37
+ end
38
+
39
+ end # Github
@@ -9,7 +9,12 @@ module Github
9
9
 
10
10
  include Github::Gists::Comments
11
11
 
12
- REQUIRED_GIST_INPUTS = %w[ description public files content ]
12
+ REQUIRED_GIST_INPUTS = %w[
13
+ description
14
+ public
15
+ files
16
+ content
17
+ ].freeze
13
18
 
14
19
  # Creates new Gists API
15
20
  def initialize(options = {})
@@ -53,19 +58,25 @@ module Github
53
58
  #
54
59
  def starred(params={})
55
60
  _normalize_params_keys(params)
56
- get("/gists/starred", params)
61
+
62
+ response = get("/gists/starred", params)
63
+ return response unless block_given?
64
+ response.each { |el| yield el }
57
65
  end
58
66
 
59
67
  # Get a single gist
60
68
  #
61
69
  # = Examples
62
- # @github = Github.new :oauth_token => '...'
70
+ # @github = Github.new
63
71
  # @github.gists.get_gist 'gist-id'
64
72
  #
65
- def get_gist(gist_id, params={})
73
+ def gist(gist_id, params={})
66
74
  _normalize_params_keys(params)
75
+ _validate_presence_of(gist_id)
76
+
67
77
  get("/gists/#{gist_id}", params)
68
78
  end
79
+ alias :get_gist :gist
69
80
 
70
81
  # Create a gist
71
82
  #
@@ -78,8 +89,8 @@ module Github
78
89
  # <tt>:content</tt> - Required string - File contents.
79
90
  #
80
91
  # = Examples
81
- # @github = Github.new :oauth_token => '...'
82
- # @github.gists.create_gist
92
+ # @github = Github.new
93
+ # @github.gists.create_gist
83
94
  # 'description' => 'the description for this gist',
84
95
  # 'public' => true,
85
96
  # 'files' => {
@@ -90,7 +101,11 @@ module Github
90
101
  #
91
102
  def create_gist(params={})
92
103
  _normalize_params_keys(params)
93
- _filter_params_keys(REQUIRED_GIST_INPUTS, params)
104
+
105
+ unless _validate_inputs(REQUIRED_GIST_INPUTS, params)
106
+ raise ArgumentError,
107
+ "Required parameters are: #{REQUIRED_GIST_INPUTS.join(', ')}"
108
+ end
94
109
 
95
110
  post("/gists", params)
96
111
  end
@@ -126,7 +141,6 @@ module Github
126
141
  def edit_gist(gist_id, params={})
127
142
  _validate_presence_of(gist_id)
128
143
  _normalize_params_keys(params)
129
- _filter_params_keys(REQUIRED_GIST_INPUTS, params)
130
144
 
131
145
  patch("/gists/#{gist_id}", params)
132
146
  end
@@ -150,14 +164,14 @@ module Github
150
164
  # @github = Github.new
151
165
  # @github.gists.unstar 'gist-id'
152
166
  #
153
- def unstar_gist(gist_id, params={})
167
+ def unstar(gist_id, params={})
154
168
  _validate_presence_of(gist_id)
155
169
  _normalize_params_keys(params)
156
170
 
157
171
  delete("/gists/#{gist_id}/star", params)
158
172
  end
159
173
 
160
- # Check if a gist is starred
174
+ # Check if a gist is starred
161
175
  #
162
176
  # = Examples
163
177
  # @github = Github.new
@@ -168,6 +182,9 @@ module Github
168
182
  _normalize_params_keys(params)
169
183
 
170
184
  get("/gists/#{gist_id}/star", params)
185
+ true
186
+ rescue Github::ResourceNotFound
187
+ false
171
188
  end
172
189
 
173
190
  # Fork a gist