githubris 0.0.4 → 0.0.5

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 (70) hide show
  1. data/.travis.yml +8 -2
  2. data/Gemfile +6 -3
  3. data/README.md +14 -0
  4. data/Rakefile +5 -11
  5. data/githubris.gemspec +2 -0
  6. data/lib/githubris.rb +18 -8
  7. data/lib/githubris/api.rb +89 -11
  8. data/lib/githubris/api/gist.rb +34 -15
  9. data/lib/githubris/api/http.rb +12 -0
  10. data/lib/githubris/api/user.rb +10 -4
  11. data/lib/githubris/base.rb +80 -0
  12. data/lib/githubris/comment.rb +1 -6
  13. data/lib/githubris/error.rb +5 -0
  14. data/lib/githubris/gist.rb +15 -60
  15. data/lib/githubris/gist/file.rb +1 -8
  16. data/lib/githubris/oauth.rb +36 -0
  17. data/lib/githubris/publicity.rb +13 -0
  18. data/lib/githubris/user.rb +13 -28
  19. data/lib/githubris/version.rb +1 -1
  20. data/spec/githubris/api/gist_spec.rb +8 -41
  21. data/spec/githubris/api/user_spec.rb +17 -2
  22. data/spec/githubris/api_spec.rb +99 -0
  23. data/spec/githubris/base_spec.rb +77 -0
  24. data/spec/githubris/gist_spec.rb +21 -76
  25. data/spec/githubris/oauth_spec.rb +71 -0
  26. data/spec/githubris/publicity_spec.rb +22 -0
  27. data/spec/githubris/user_spec.rb +50 -13
  28. data/spec/githubris_spec.rb +34 -40
  29. data/spec/spec_helper.rb +9 -6
  30. data/spec/support/fixtures.rb +115 -99
  31. data/spec/support/fixtures/vcr_cassettes/Githubris/_find_gist.yml +44 -0
  32. data/spec/support/fixtures/vcr_cassettes/Githubris/_find_user.yml +40 -0
  33. data/spec/support/fixtures/vcr_cassettes/Githubris/_public_gists.yml +55 -0
  34. data/spec/support/fixtures/vcr_cassettes/Githubris_API/_authenticated_/when_authenticated_with_bad_credentials.yml +40 -0
  35. data/spec/support/fixtures/vcr_cassettes/Githubris_API/_authenticated_/when_authenticated_with_good_credentials.yml +42 -0
  36. data/spec/support/fixtures/vcr_cassettes/Githubris_API/_authenticated_/when_there_are_no_credentials.yml +42 -0
  37. data/spec/support/fixtures/vcr_cassettes/Githubris_API_Gist/_get_gist.yml +44 -0
  38. data/spec/support/fixtures/vcr_cassettes/Githubris_API_Gist/_get_public_gists.yml +107 -0
  39. data/spec/support/fixtures/vcr_cassettes/Githubris_API_Gist/_get_user_gists.yml +43 -0
  40. data/spec/support/fixtures/vcr_cassettes/Githubris_API_User/_get_authenticated_user/without_credentials.yml +42 -0
  41. data/spec/support/fixtures/vcr_cassettes/Githubris_API_User/_get_user.yml +40 -0
  42. data/spec/support/fixtures/vcr_cassettes/Githubris_Gist/_save.yml +42 -0
  43. data/spec/support/fixtures/vcr_cassettes/Githubris_Gist/any_gist.yml +44 -0
  44. data/spec/support/fixtures/vcr_cassettes/Githubris_Gist/given_a_gist_full_of_data.yml +44 -0
  45. data/spec/support/fixtures/vcr_cassettes/Githubris_Gist/on_a_gist_with_an_id.yml +44 -0
  46. data/spec/support/fixtures/vcr_cassettes/Githubris_Gist/on_a_gist_with_an_id/_reload.yml +44 -0
  47. data/spec/support/fixtures/vcr_cassettes/Githubris_User/_gists.yml +43 -0
  48. data/spec/support/fixtures/vcr_cassettes/Githubris_User/_reload.yml +40 -0
  49. data/spec/support/fixtures/vcr_cassettes/Githubris_User/_reload/on_a_user_with_a_login.yml +40 -0
  50. data/spec/support/fixtures/vcr_cassettes/Githubris_User/_reload/on_a_user_without_a_login.yml +40 -0
  51. data/spec/support/fixtures/vcr_cassettes/Githubris_User/_starred_gists/on_an_authenticated_user.yml +82 -0
  52. data/spec/support/vcr.rb +6 -0
  53. metadata +57 -21
  54. data/features/get_a_gist.feature +0 -13
  55. data/features/get_a_user.feature +0 -8
  56. data/features/list_of_public_gists.feature +0 -12
  57. data/features/list_of_users_public_gists.feature +0 -13
  58. data/features/step_definitions/general_steps.rb +0 -32
  59. data/features/support/env.rb +0 -6
  60. data/features/support/fakeweb_responses.rb +0 -12
  61. data/features/support/fixtures.rb +0 -47
  62. data/lib/githubris/builder.rb +0 -28
  63. data/spec/githubris/builder_spec.rb +0 -28
  64. data/spec/support/custom_matchers.rb +0 -27
  65. data/spec/support/fakeweb_responses.rb +0 -12
  66. data/spec/support/gist.json +0 -335
  67. data/spec/support/public_gists_page_1.json +0 -884
  68. data/spec/support/public_gists_page_2.json +0 -898
  69. data/spec/support/user.json +0 -14
  70. data/spec/support/user_public_gists.json +0 -65
@@ -1,6 +1 @@
1
- class Githubris
2
- class Comment
3
- def self.build comment_data
4
- end
5
- end
6
- end
1
+ class Githubris::Comment; end
@@ -0,0 +1,5 @@
1
+ class Githubris::Error < StandardError; end
2
+ class Githubris::Error::RequiresAuthentication < Githubris::Error; end
3
+ class Githubris::Error::BadCredentials < Githubris::Error; end
4
+ class Githubris::Error::NotFound < Githubris::Error; end
5
+ class Githubris::Error::InvalidAttributes < Githubris::Error; end
@@ -1,73 +1,28 @@
1
1
  require 'date'
2
2
 
3
- class Githubris::Gist
3
+ class Githubris::Gist < Githubris::Base
4
4
  autoload :File, 'githubris/gist/file'
5
5
 
6
- def self.default_attributes
7
- {
8
- :files => {},
9
- :created_at => DateTime.now.to_s,
10
- :updated_at => DateTime.now.to_s,
11
- }
12
- end
13
-
14
- def initialize attributes={}
15
- attributes.merge! Githubris::Gist.default_attributes do |given_key, given_value|
16
- if Githubris::Gist.default_attributes.has_key? given_key
17
- given_value
18
- end
19
- end
20
-
21
- @attributes = attributes
22
- end
6
+ include Githubris::Publicity
23
7
 
24
- def id
25
- Integer(@attributes[:id])
26
- end
8
+ datetime_attribute :created_at, :updated_at
9
+ accessible_attribute :description
10
+ readable_attribute :id, :files
11
+ uri_attribute :url
27
12
 
28
13
  def user
29
- unless @attributes[:user].instance_of? Githubris::User
30
- @attributes[:user] = Githubris::Builder.new.build_user @attributes[:user]
31
- else
32
- @attributes[:user]
33
- end
34
- end
35
-
36
- def created_at
37
- DateTime.parse @attributes[:created_at]
38
- end
39
-
40
- def updated_at
41
- DateTime.parse @attributes[:updated_at]
42
- end
43
-
44
- def description
45
- @attributes[:description]
14
+ @user ||= Githubris::User.new(@attributes[:user])
46
15
  end
47
16
 
48
- def files
49
- @attributes[:files].values
50
- end
51
-
52
- def url
53
- URI.parse @attributes[:url]
54
- end
55
-
56
- def public?
57
- @attributes[:public]
58
- end
59
-
60
- def comments
61
- Array.new @attributes[:comments], Githubris::Comment.new
62
- end
63
-
64
- def ==(other)
65
- @attributes == other.instance_variable_get(:@attributes)
17
+ def reload
18
+ swap_attributes @api.get_gist @attributes[:id]
66
19
  end
67
20
 
68
- def reload
69
- other = Githubris::API.new.get_gist id
70
- instance_variable_set(:@attributes, other.instance_variable_get(:@attributes))
71
- self
21
+ def save
22
+ swap_attributes @api.post_gist(
23
+ :description => @attributes[:description],
24
+ :public => @attributes[:public],
25
+ :files => @attributes[:files]
26
+ )
72
27
  end
73
28
  end
@@ -1,9 +1,2 @@
1
- class Githubris
2
- class Gist
3
- class File
4
- def self.build data
5
- new
6
- end
7
- end
8
- end
1
+ class Githubris::Gist::File
9
2
  end
@@ -0,0 +1,36 @@
1
+ class Githubris::OAuth
2
+ REQUEST_ACCESS_URL = "https://github.com/login/oauth/authorize"
3
+
4
+ def initialize(client_id, client_secret)
5
+ @client_id = client_id
6
+ @client_secret = client_secret
7
+ end
8
+
9
+ def request_access_url(options={})
10
+ url = Addressable::URI.parse REQUEST_ACCESS_URL
11
+ query_values = {}
12
+ query_values[:client_id] = @client_id
13
+
14
+ redirect_uri = options.delete(:redirect_uri)
15
+ query_values[:redirect_uri] = redirect_uri if redirect_uri
16
+
17
+ scopes = options.delete :scopes
18
+ if scopes
19
+ scopes = scopes.join ','
20
+ query_values[:scopes] = scopes
21
+ end
22
+
23
+ url.query_values = query_values
24
+ url.query = URI.decode(url.query)
25
+ url.to_s
26
+ end
27
+
28
+ def access_token(code)
29
+ access_token_params = {
30
+ :client_id => @client_id,
31
+ :client_secret => @client_secret,
32
+ :code => code
33
+ }
34
+ Githubris::API.new.post_oauth_access_token(access_token_params)
35
+ end
36
+ end
@@ -0,0 +1,13 @@
1
+ module Githubris::Publicity
2
+ def public?
3
+ @attributes[:public]
4
+ end
5
+
6
+ def publicize
7
+ @attributes[:public] = true
8
+ end
9
+
10
+ def privatize
11
+ @attributes[:public] = false
12
+ end
13
+ end
@@ -1,36 +1,21 @@
1
- class Githubris::User
2
- def initialize attributes={}
3
- @attributes = attributes
4
- end
5
-
6
- def public_gists
7
- Githubris::API.new.get_user_public_gists(@attributes[:login])
8
- end
9
-
10
- def login
11
- @attributes[:login]
12
- end
13
-
14
- def id
15
- Integer(@attributes[:id])
16
- end
17
-
18
- def avatar_url
19
- URI.parse @attributes[:avatar_url]
20
- end
1
+ class Githubris::User < Githubris::Base
2
+ uri_attribute :avatar_url, :url
3
+ readable_attribute :login, :id, :gravatar_id
21
4
 
22
- def url
23
- URI.parse @attributes[:url]
5
+ def gists(options={})
6
+ @api.get_user_gists(@attributes[:login])
24
7
  end
25
8
 
26
- def gravatar_id
27
- @attributes[:gravatar_id]
9
+ def starred_gists(options={})
10
+ @api.get_user_starred_gists(options)
28
11
  end
29
12
 
30
- def == other
31
- other_attrs = other.instance_variable_get(:@attributes)
32
- if other_attrs
33
- @attributes == other_attrs
13
+ def reload
14
+ swap_attributes @api.get_user @attributes[:login]
15
+ rescue Githubris::Error => error
16
+ case error
17
+ when Githubris::Error::NotFound
18
+ raise
34
19
  end
35
20
  end
36
21
  end
@@ -1,3 +1,3 @@
1
1
  class Githubris
2
- VERSION = "0.0.4"
2
+ VERSION = "0.0.5"
3
3
  end
@@ -5,66 +5,33 @@ describe Githubris::API::Gist do
5
5
  Githubris::API.new
6
6
  end
7
7
 
8
- describe '#get_user_public_gists' do
8
+ describe '#get_user_gists' do
9
+ use_vcr_cassette
10
+
9
11
  let(:login) {'GithubrisTestUser'}
10
12
 
11
13
  it 'gets /users/:username/gists' do
12
14
  subject.stub(:user_gists_path => '/users/GithubrisTestUser/gists')
13
- user_public_gists = subject.get_user_public_gists(login)
15
+ user_public_gists = subject.get_user_gists(login)
14
16
  subject.should have_received(:user_gists_path).with(login)
15
17
  end
16
-
17
- context 'given a user with 2 gists' do
18
- it 'returns 2 gists by the given user' do
19
- user_public_gists = subject.get_public_gists(:user => login)
20
- user_public_gists.should have(2).items
21
- user_public_gists.each do |gist|
22
- gist.should be_instance_of Githubris::Gist
23
- end
24
- end
25
- end
26
-
27
18
  end
28
19
 
29
20
  describe '#get_public_gists' do
21
+ use_vcr_cassette
22
+
30
23
  it 'returns an array of gists' do
31
24
  subject.get_public_gists.should be_instance_of Array
32
25
  subject.get_public_gists.each do |gist|
33
26
  gist.should be_instance_of Githubris::Gist
34
27
  end
35
28
  end
36
-
37
- it 'accepts an options hash' do
38
- lambda do
39
- subject.get_public_gists({:foo => 'bar'})
40
- end.should_not raise_error
41
- end
42
-
43
- context 'given a page option' do
44
- it 'returns an array of 30 gists from that page' do
45
- page_one_gists = subject.get_public_gists(:page => 1)
46
- page_two_gists = subject.get_public_gists(:page => 2)
47
- page_one_gists.should have(30).items
48
- page_two_gists.should have(30).items
49
- end
50
- end
51
-
52
- context 'given a user option' do
53
- it 'delegates to #get_user_public_gists' do
54
- login = 'GithubrisTestUser'
55
- subject.should_receive(:get_user_public_gists).with(login)
56
- subject.get_public_gists(:user => login)
57
- end
58
- end
59
29
  end
60
30
 
61
31
  describe '#get_gist' do
62
- let(:id) { 1 }
63
- it 'uses GET' do
64
- subject.should_receive(:get).with(subject.gist_path(id))
65
- subject.get_gist(id)
66
- end
32
+ use_vcr_cassette
67
33
 
34
+ let(:id) { 1 }
68
35
  it 'is a Githubris::Gist' do
69
36
  subject.get_gist(id).should be_instance_of Githubris::Gist
70
37
  end
@@ -2,12 +2,27 @@ require 'spec_helper'
2
2
 
3
3
  describe Githubris::API::User do
4
4
  let(:api) { Githubris::API.new }
5
+ subject { api }
6
+
7
+ describe '#get_authenticated_user' do
8
+ context 'without credentials' do
9
+ use_vcr_cassette
10
+
11
+ it 'raises a Githubris::Error::RequiresAuthentication' do
12
+ lambda do
13
+ subject.get_authenticated_user
14
+ end.should raise_error(Githubris::Error::RequiresAuthentication)
15
+ end
16
+ end
17
+ end
5
18
 
6
19
  describe '#get_user' do
7
- subject { api.get_user('login') }
20
+ use_vcr_cassette
21
+
22
+ subject { api.get_user('GithubrisTestUser') }
8
23
  it 'takes a login' do
9
24
  lambda do
10
- api.get_user('login')
25
+ api.get_user('GithubrisTestUser')
11
26
  end.should_not raise_error
12
27
  end
13
28
 
@@ -1,4 +1,103 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Githubris::API do
4
+ let(:api) { Githubris::API.new }
5
+
6
+ describe '#authenticated?' do
7
+ it 'checks for an authenticated user' do
8
+ subject.should_receive(:get_authenticated_user)
9
+ subject.authenticated?
10
+ end
11
+
12
+ context 'when authenticated with good credentials' do
13
+ subject do
14
+ api.basic_auth('GithubrisTestUser', 'password')
15
+ api.authenticated?
16
+ end
17
+
18
+ use_vcr_cassette
19
+
20
+ it { should be_true }
21
+ end
22
+
23
+ context 'when authenticated with bad credentials' do
24
+ use_vcr_cassette
25
+
26
+ subject do
27
+ api.basic_auth('GithubrisTestFakeUser', 'password')
28
+ api.authenticated?
29
+ end
30
+
31
+ it { should be_false }
32
+ end
33
+
34
+ context 'when there are no credentials' do
35
+ use_vcr_cassette
36
+
37
+ subject do
38
+ api.authenticated?
39
+ end
40
+
41
+ it { should be_false }
42
+ end
43
+ end
44
+
45
+ describe '#oauth' do
46
+ it 'returns a Githubris::OAuth' do
47
+ client_id = 'client_id'
48
+ client_secret = 'client_secret'
49
+ subject.oauth(client_id, client_secret).should be_instance_of Githubris::OAuth
50
+ end
51
+
52
+ it 'returns a Githubris::OAuth initialized with the client id and secret' do
53
+ client_id = 'client_id'
54
+ client_secret = 'client_secret'
55
+ Githubris::OAuth.should_receive(:new).with(client_id, client_secret)
56
+ subject.oauth(client_id, client_secret)
57
+ end
58
+
59
+ it 'can take options' do
60
+ client_id = 'client_id'
61
+ client_secret = 'client_secret'
62
+ Githubris::OAuth.should_receive(:new).with(client_id, client_secret)
63
+ subject.oauth(client_id, client_secret)
64
+ end
65
+ end
66
+
67
+ describe '#post_oauth_access_token' do
68
+ use_vcr_cassette
69
+
70
+ before do
71
+ access_token_response =<<-RESPONSE
72
+ HTTP/1.1 200 OK
73
+ Server: nginx/1.0.13
74
+ Date: Wed, 21 Mar 2012 12:54:41 GMT
75
+ Content-Type: application/x-www-form-urlencoded; charset=utf-8
76
+ Connection: keep-alive
77
+ Status: 200 OK
78
+ ETag: "fa6a87d35864200004d1eff50d685301"
79
+ X-Frame-Options: deny
80
+ X-Runtime: 14
81
+ Content-Length: 71
82
+ Cache-Control: private, max-age=0, must-revalidate
83
+ Strict-Transport-Security: max-age=2592000
84
+
85
+ access_token=1663860ddbbb9137119ff03ef2a9d819bbce4d0e&token_type=bearer
86
+ RESPONSE
87
+ FakeWeb.register_uri(:post, /github.com\/login\/oauth\/access_token/, :response => access_token_response)
88
+ end
89
+
90
+ after do
91
+ FakeWeb.clean_registry
92
+ end
93
+
94
+ it 'takes params' do
95
+ lambda do
96
+ subject.post_oauth_access_token({})
97
+ end.should_not raise_error
98
+ end
99
+ it 'returns a string' do
100
+ subject.post_oauth_access_token({}).should be_instance_of String
101
+ end
102
+ end
4
103
  end
@@ -0,0 +1,77 @@
1
+ require 'spec_helper'
2
+
3
+ describe Githubris::Base do
4
+ it 'has an attributes hash' do
5
+ subject.instance_variable_get(:@attributes).should be_instance_of Hash
6
+ end
7
+
8
+ describe '#==' do
9
+ it 'matches based on attributes' do
10
+ object1 = described_class.new({:foo => 'bar'})
11
+ object2 = described_class.new({:foo => 'bar'})
12
+ object1.should == object2
13
+ end
14
+ end
15
+
16
+ context 'defining attributes' do
17
+ let(:mock_class) { Class.new(described_class) }
18
+
19
+ describe '::uri_attribute' do
20
+ it 'defines an instance method that returns a URI object' do
21
+ mock_class.class_eval do
22
+ uri_attribute :foo
23
+ end
24
+
25
+ object = mock_class.new(:foo => 'http://google.com')
26
+ object.foo.should be_kind_of URI
27
+ end
28
+ end
29
+
30
+ describe '::accessible_attribute' do
31
+ it 'defines an instance method that returns a URI object' do
32
+ mock_class.class_eval do
33
+ accessible_attribute :foo
34
+ end
35
+
36
+ lots_of_text = 'this is a lot of text'
37
+ object = mock_class.new(:foo => lots_of_text)
38
+
39
+ lambda do
40
+ object.foo == lots_of_text
41
+ object.foo = 'Not a ton of text'
42
+ end.should_not raise_error
43
+
44
+ object.foo.should == 'Not a ton of text'
45
+ end
46
+ end
47
+
48
+ describe '::datetime_attribute' do
49
+ it 'defines an instance method that returns a DateTime object' do
50
+ mock_class.class_eval do
51
+ datetime_attribute :foo
52
+ end
53
+
54
+ object = mock_class.new(:foo => '3:00PM 1/3/1994')
55
+ object.foo.should be_kind_of DateTime
56
+ end
57
+ end
58
+
59
+ describe '::readable_attribute' do
60
+ it 'defines a getter for the attributes passed in' do
61
+ mock_class.class_eval do
62
+ readable_attribute :foo, :bar, :baz
63
+ end
64
+
65
+ object = mock_class.new(:foo => 'asdf',
66
+ :bar => 'fdsa',
67
+ :baz => 'qwerty')
68
+
69
+ lambda do
70
+ object.foo.should == 'asdf'
71
+ object.bar.should == 'fdsa'
72
+ object.baz.should == 'qwerty'
73
+ end.should_not raise_error
74
+ end
75
+ end
76
+ end
77
+ end