githubris 0.0.4 → 0.0.5

Sign up to get free protection for your applications and to get access to all the features.
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