github_api 0.4.2 → 0.4.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 (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