githubris 0.0.6 → 0.0.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (56) hide show
  1. data/.travis.yml +5 -5
  2. data/Rakefile +11 -2
  3. data/githubris.gemspec +3 -2
  4. data/lib/githubris.rb +1 -11
  5. data/lib/githubris/api.rb +61 -40
  6. data/lib/githubris/api/gist.rb +40 -3
  7. data/lib/githubris/api/http.rb +13 -4
  8. data/lib/githubris/api/json.rb +16 -0
  9. data/lib/githubris/base.rb +2 -64
  10. data/lib/githubris/custom_attributes.rb +40 -0
  11. data/lib/githubris/gist.rb +53 -7
  12. data/lib/githubris/oauth.rb +23 -18
  13. data/lib/githubris/publicity.rb +2 -2
  14. data/lib/githubris/version.rb +1 -1
  15. data/spec/githubris/api/gist_spec.rb +2 -6
  16. data/spec/githubris/api_spec.rb +3 -22
  17. data/spec/githubris/base_spec.rb +1 -1
  18. data/spec/githubris/gist_spec.rb +117 -26
  19. data/spec/githubris/oauth_spec.rb +12 -0
  20. data/spec/githubris/publicity_spec.rb +4 -4
  21. data/spec/githubris/user_spec.rb +2 -10
  22. data/spec/githubris_spec.rb +2 -5
  23. data/spec/support/fixtures/vcr_cassettes/Githubris.yml +137 -0
  24. data/spec/support/fixtures/vcr_cassettes/Githubris_API.yml +118 -0
  25. data/spec/support/fixtures/vcr_cassettes/Githubris_API/_authenticated_/when_authenticated_with_good_credentials.yml +6 -6
  26. data/spec/support/fixtures/vcr_cassettes/Githubris_API_Gist.yml +197 -0
  27. data/spec/support/fixtures/vcr_cassettes/Githubris_API_User/_get_authenticated_user/without_credentials.yml +3 -3
  28. data/spec/support/fixtures/vcr_cassettes/Githubris_API_User/_get_user.yml +5 -5
  29. data/spec/support/fixtures/vcr_cassettes/Githubris_Gist.yml +1009 -0
  30. data/spec/support/fixtures/vcr_cassettes/Githubris_User.yml +196 -0
  31. data/spec/support/vcr.rb +1 -0
  32. metadata +78 -39
  33. data/lib/githubris/comment.rb +0 -1
  34. data/lib/githubris/gist/file.rb +0 -2
  35. data/lib/githubris/issue.rb +0 -6
  36. data/lib/githubris/organization.rb +0 -5
  37. data/lib/githubris/repository.rb +0 -7
  38. data/spec/support/fixtures/vcr_cassettes/Githubris/_find_gist.yml +0 -44
  39. data/spec/support/fixtures/vcr_cassettes/Githubris/_find_user.yml +0 -40
  40. data/spec/support/fixtures/vcr_cassettes/Githubris/_public_gists.yml +0 -55
  41. data/spec/support/fixtures/vcr_cassettes/Githubris_API/_authenticated_/when_authenticated_with_bad_credentials.yml +0 -40
  42. data/spec/support/fixtures/vcr_cassettes/Githubris_API/_authenticated_/when_there_are_no_credentials.yml +0 -42
  43. data/spec/support/fixtures/vcr_cassettes/Githubris_API_Gist/_get_gist.yml +0 -44
  44. data/spec/support/fixtures/vcr_cassettes/Githubris_API_Gist/_get_public_gists.yml +0 -107
  45. data/spec/support/fixtures/vcr_cassettes/Githubris_API_Gist/_get_user_gists.yml +0 -43
  46. data/spec/support/fixtures/vcr_cassettes/Githubris_Gist/_save.yml +0 -42
  47. data/spec/support/fixtures/vcr_cassettes/Githubris_Gist/_save/when_authenticated.yml +0 -44
  48. data/spec/support/fixtures/vcr_cassettes/Githubris_Gist/any_gist.yml +0 -44
  49. data/spec/support/fixtures/vcr_cassettes/Githubris_Gist/given_a_gist_full_of_data.yml +0 -44
  50. data/spec/support/fixtures/vcr_cassettes/Githubris_Gist/on_a_gist_with_an_id.yml +0 -44
  51. data/spec/support/fixtures/vcr_cassettes/Githubris_Gist/on_a_gist_with_an_id/_reload.yml +0 -44
  52. data/spec/support/fixtures/vcr_cassettes/Githubris_User/_gists.yml +0 -43
  53. data/spec/support/fixtures/vcr_cassettes/Githubris_User/_reload.yml +0 -40
  54. data/spec/support/fixtures/vcr_cassettes/Githubris_User/_reload/on_a_user_with_a_login.yml +0 -40
  55. data/spec/support/fixtures/vcr_cassettes/Githubris_User/_reload/on_a_user_without_a_login.yml +0 -40
  56. data/spec/support/fixtures/vcr_cassettes/Githubris_User/_starred_gists/on_an_authenticated_user.yml +0 -82
@@ -1,8 +1,4 @@
1
- require 'date'
2
-
3
1
  class Githubris::Gist < Githubris::Base
4
- autoload :File, 'githubris/gist/file'
5
-
6
2
  include Githubris::Publicity
7
3
 
8
4
  datetime_attribute :created_at, :updated_at
@@ -14,15 +10,65 @@ class Githubris::Gist < Githubris::Base
14
10
  @user ||= Githubris::User.new(@attributes[:user])
15
11
  end
16
12
 
13
+ def star!
14
+ @api.put_gist_star(@attributes[:id])
15
+ end
16
+
17
+ def unstar!
18
+ @api.delete_gist_star(@attributes[:id])
19
+ end
20
+
21
+ def starred?
22
+ @api.get_gist_starred?(@attributes[:id])
23
+ end
24
+
25
+ def unstarred?
26
+ !starred?
27
+ end
28
+
29
+ def delete!
30
+ @api.delete_gist(@attributes[:id])
31
+ end
32
+
33
+ def history
34
+ @attributes[:history].map do |gist_data|
35
+ Githubris::Gist.new(gist_data)
36
+ end
37
+ end
38
+
17
39
  def reload
18
- swap_attributes @api.get_gist @attributes[:id]
40
+ if @attributes[:id]
41
+ gist = @api.get_gist @attributes[:id]
42
+ elsif @attributes[:url]
43
+ gist = Githubris::Gist.new @api._get @attributes[:url]
44
+ else
45
+ raise Githubris::Error, 'Missing a unique identifier, such as an id or a url'
46
+ end
47
+ swap_attributes gist
19
48
  end
20
49
 
21
50
  def save
22
- swap_attributes @api.post_gist(
51
+ if new?
52
+ saved_attributes = @api.post_gist(saving_attributes)
53
+ else
54
+ saved_attributes = @api.patch_gist(@attributes[:id], saving_attributes)
55
+ end
56
+ swap_attributes saved_attributes
57
+ end
58
+
59
+ def saving_attributes
60
+ {
23
61
  :description => @attributes[:description],
24
62
  :public => @attributes[:public],
25
63
  :files => @attributes[:files]
26
- )
64
+ }
65
+ end
66
+
67
+ def new?
68
+ reload
69
+ rescue Githubris::Error
70
+ true
71
+ else
72
+ false
27
73
  end
28
74
  end
@@ -1,36 +1,41 @@
1
1
  class Githubris::OAuth
2
- REQUEST_ACCESS_URL = "https://github.com/login/oauth/authorize"
2
+ REQUEST_ACCESS_URL = Addressable::URI.parse("https://github.com/login/oauth/authorize")
3
3
 
4
- def initialize(client_id, client_secret)
4
+ def initialize(client_id, client_secret, api=Githubris::API.new)
5
5
  @client_id = client_id
6
6
  @client_secret = client_secret
7
+ @api = api
7
8
  end
8
9
 
9
- def request_access_url(options={})
10
- url = Addressable::URI.parse REQUEST_ACCESS_URL
11
- query_values = {}
12
- query_values[:client_id] = @client_id
10
+ def request_access_url(query={})
11
+ add_query_params_to(REQUEST_ACCESS_URL, query).to_s
12
+ end
13
+
14
+ def access_token(code)
15
+ @api.post_oauth_access_token(access_token_params(code))
16
+ end
13
17
 
14
- redirect_uri = options.delete(:redirect_uri)
15
- query_values[:redirect_uri] = redirect_uri if redirect_uri
18
+ private
16
19
 
17
- scopes = options.delete :scopes
18
- if scopes
19
- scopes = scopes.join ','
20
- query_values[:scopes] = scopes
20
+ def add_query_params_to(uri, query)
21
+ uri.tap do |uri|
22
+ uri.query_values = query_values(query)
23
+ uri.query = URI.decode(uri.query)
21
24
  end
25
+ end
22
26
 
23
- url.query_values = query_values
24
- url.query = URI.decode(url.query)
25
- url.to_s
27
+ def query_values(query)
28
+ query_values = { :client_id => @client_id }
29
+ query_values[:scopes] = query[:scopes].join(',') if query[:scopes]
30
+ query_values[:redirect_uri] = query[:redirect_uri] if query[:redirect_uri]
31
+ query_values
26
32
  end
27
33
 
28
- def access_token(code)
29
- access_token_params = {
34
+ def access_token_params(code)
35
+ {
30
36
  :client_id => @client_id,
31
37
  :client_secret => @client_secret,
32
38
  :code => code
33
39
  }
34
- Githubris::API.new.post_oauth_access_token(access_token_params)
35
40
  end
36
41
  end
@@ -3,11 +3,11 @@ module Githubris::Publicity
3
3
  @attributes[:public]
4
4
  end
5
5
 
6
- def publicize
6
+ def publicize!
7
7
  @attributes[:public] = true
8
8
  end
9
9
 
10
- def privatize
10
+ def privatize!
11
11
  @attributes[:public] = false
12
12
  end
13
13
  end
@@ -1,3 +1,3 @@
1
1
  class Githubris
2
- VERSION = "0.0.6"
2
+ VERSION = "0.0.7"
3
3
  end
@@ -1,13 +1,13 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Githubris::API::Gist do
4
+ use_vcr_cassette
5
+
4
6
  subject do
5
7
  Githubris::API.new
6
8
  end
7
9
 
8
10
  describe '#get_user_gists' do
9
- use_vcr_cassette
10
-
11
11
  let(:login) {'GithubrisTestUser'}
12
12
 
13
13
  it 'gets /users/:username/gists' do
@@ -18,8 +18,6 @@ describe Githubris::API::Gist do
18
18
  end
19
19
 
20
20
  describe '#get_public_gists' do
21
- use_vcr_cassette
22
-
23
21
  it 'returns an array of gists' do
24
22
  subject.get_public_gists.should be_instance_of Array
25
23
  subject.get_public_gists.each do |gist|
@@ -29,8 +27,6 @@ describe Githubris::API::Gist do
29
27
  end
30
28
 
31
29
  describe '#get_gist' do
32
- use_vcr_cassette
33
-
34
30
  let(:id) { 1 }
35
31
  it 'is a Githubris::Gist' do
36
32
  subject.get_gist(id).should be_instance_of Githubris::Gist
@@ -1,6 +1,8 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Githubris::API do
4
+ use_vcr_cassette
5
+
4
6
  let(:api) { Githubris::API.new }
5
7
 
6
8
  describe '#authenticated?' do
@@ -15,14 +17,10 @@ describe Githubris::API do
15
17
  api.authenticated?
16
18
  end
17
19
 
18
- use_vcr_cassette
19
-
20
20
  it { should be_true }
21
21
  end
22
22
 
23
23
  context 'when authenticated with bad credentials' do
24
- use_vcr_cassette
25
-
26
24
  subject do
27
25
  api.basic_auth('GithubrisTestFakeUser', 'password')
28
26
  api.authenticated?
@@ -32,8 +30,6 @@ describe Githubris::API do
32
30
  end
33
31
 
34
32
  context 'when there are no credentials' do
35
- use_vcr_cassette
36
-
37
33
  subject do
38
34
  api.authenticated?
39
35
  end
@@ -48,25 +44,9 @@ describe Githubris::API do
48
44
  client_secret = 'client_secret'
49
45
  subject.oauth(client_id, client_secret).should be_instance_of Githubris::OAuth
50
46
  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
47
  end
66
48
 
67
49
  describe '#post_oauth_access_token' do
68
- use_vcr_cassette
69
-
70
50
  before do
71
51
  access_token_response =<<-RESPONSE
72
52
  HTTP/1.1 200 OK
@@ -96,6 +76,7 @@ RESPONSE
96
76
  subject.post_oauth_access_token({})
97
77
  end.should_not raise_error
98
78
  end
79
+
99
80
  it 'returns a string' do
100
81
  subject.post_oauth_access_token({}).should be_instance_of String
101
82
  end
@@ -28,7 +28,7 @@ describe Githubris::Base do
28
28
  end
29
29
 
30
30
  describe '::accessible_attribute' do
31
- it 'defines an instance method that returns a URI object' do
31
+ it 'defines an instance method that returns the attribute named by the method' do
32
32
  mock_class.class_eval do
33
33
  accessible_attribute :foo
34
34
  end
@@ -1,52 +1,143 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Githubris::Gist do
4
- let(:id) { 1 }
5
- subject { described_class.new :id => id }
4
+ use_vcr_cassette
6
5
 
7
- context 'on a gist with an id' do
8
- use_vcr_cassette
6
+ describe '#new?' do
7
+ it 'seems new if there are issues when reloading' do
8
+ gist_without_id = Githubris::Gist.new
9
+ gist_without_id.should be_new
10
+ end
9
11
 
10
- describe '#reload' do
11
- it 'returns the same object' do
12
- obj_id = subject.object_id
13
- subject.reload.object_id.should == obj_id
14
- end
12
+ it 'seems to not be new if there are no issues' do
13
+ gist = Githubris::Gist.new :id => 1
14
+ gist.should_not be_new
15
15
  end
16
16
  end
17
17
 
18
- context 'given a gist full of data' do
19
- use_vcr_cassette
18
+ describe '#reload' do
19
+ it 'works with or without an id' do
20
+ gist = Githubris::Gist.new :url => 'https://api.github.com/gists/1'
21
+ lambda { gist.reload }.should_not raise_error
22
+ gist = Githubris::Gist.new :id => 1
23
+ lambda { gist.reload }.should_not raise_error
24
+ end
25
+
26
+ it 'returns the same object' do
27
+ gist = Githubris::Gist.new :id => 1
28
+ obj_id = gist.object_id
29
+ gist.reload.object_id.should == obj_id
30
+ end
31
+
32
+ it 'errors when any indication of identity is absent' do
33
+ gist = Githubris::Gist.new
34
+ lambda { gist.reload }.should raise_error Githubris::Error
35
+ end
36
+ end
20
37
 
21
- describe '#user' do
22
- it 'returns a user' do
23
- subject.reload
24
- subject.user.should be_instance_of Githubris::User
38
+ context 'on a gist with an id' do
39
+ let(:id) { 1 }
40
+ subject { described_class.new :id => 1 }
41
+
42
+ context 'given a gist full of data' do
43
+ describe '#user' do
44
+ it 'returns a user' do
45
+ subject.reload
46
+ subject.user.should be_instance_of Githubris::User
47
+ end
48
+ end
49
+ end
50
+
51
+ describe '#history' do
52
+ context 'on a gist with history' do
53
+ it 'is an array of gists' do
54
+ subject.reload
55
+ subject.history.each do |gist|
56
+ gist.should be_instance_of Githubris::Gist
57
+ end
58
+ end
25
59
  end
26
60
  end
27
61
  end
28
62
 
29
63
  describe '#save' do
30
- use_vcr_cassette
31
-
32
64
  it 'for a public, anonymous gist' do
33
65
  gist = described_class.new :public => true, :files => {'gistfile.txt' => {:content => 'foobar'}}
34
66
  lambda { gist.save }.should_not raise_error
35
67
  end
68
+ end
36
69
 
37
- context 'when authenticated' do
38
- use_vcr_cassette
70
+ context 'when authenticated' do
71
+ let(:api) { Githubris::API.new }
72
+ let(:user) { api.get_authenticated_user }
39
73
 
40
- let(:api) { Githubris::API.new }
74
+ before do
75
+ api.basic_auth 'GithubrisTestUser', 'password'
76
+ api.should be_authenticated
77
+ end
41
78
 
42
- before do
43
- api.basic_auth('GithubrisTestUser', 'password')
79
+ describe '#delete!' do
80
+ let(:gist) { api.get_authenticated_user.gists.first }
81
+
82
+ it 'deletes the gist' do
83
+ gist.delete!
84
+ lambda do
85
+ gist.reload
86
+ end.should raise_error
87
+ end
88
+ end
89
+
90
+ describe '#star!' do
91
+ let(:gist) { Githubris::Gist.new(:id => 1, :_api => api).reload }
92
+
93
+ it 'stars the gist' do
94
+ gist.star!
95
+ gist.should be_starred
96
+ end
97
+ end
98
+
99
+ describe '#unstar!' do
100
+ let(:gist) { api.get_authenticated_user.starred_gists.first }
101
+
102
+ it 'unstars the gist' do
103
+ gist.unstar!
104
+ gist.should be_unstarred
105
+ end
106
+ end
107
+
108
+ describe '#save' do
109
+ context "when creating a public gist" do
110
+ it 'does not raise an error' do
111
+ gist = described_class.new :_api => api, :public => true, :files => {'gistfile.txt' => {:content => 'foobar'}}
112
+ lambda { gist.save }.should_not raise_error
113
+ gist.user.login.should == 'GithubrisTestUser'
114
+ end
44
115
  end
45
116
 
46
- it 'for a gist by an authenticated user' do
47
- gist = described_class.new :_api => api, :public => true, :files => {'gistfile.txt' => {:content => 'foobar'}}
48
- lambda { gist.save }.should_not raise_error
49
- gist.user.login.should == 'GithubrisTestUser'
117
+ context 'when creating a private gist' do
118
+ it 'does not raise an error' do
119
+ gist = described_class.new :_api => api, :public => false, :files => {'gistfile.txt' => {:content => 'foobar'}}
120
+ lambda { gist.save }.should_not raise_error
121
+ gist.user.login.should == 'GithubrisTestUser'
122
+ end
123
+ end
124
+
125
+ context 'editing a file' do
126
+ it 'can be used to edit a file' do
127
+ gist = api.get_authenticated_user.gists.last
128
+ expected_id = gist.id
129
+ gist.files['gistfile.txt'] = {}
130
+ file = gist.files['gistfile.txt']
131
+ content = <<-EOF
132
+ lorem ipsum, all the time.
133
+ EOF
134
+
135
+ file[:content] = content
136
+ lambda { gist.save }.should_not raise_error
137
+
138
+ file[:content].should == content
139
+ gist.id.should == expected_id
140
+ end
50
141
  end
51
142
  end
52
143
  end
@@ -53,6 +53,18 @@ RESPONSE
53
53
  url.should match /scopes=user,public_repo,repo,gist/
54
54
  url.should match /redirect_uri=#{URI.encode(redirect_uri)}/
55
55
  end
56
+
57
+ it 'does not include a redirect_uri when none is given' do
58
+ url = oauth.request_access_url
59
+
60
+ url.should_not match /redirect_uri=/
61
+ end
62
+
63
+ it 'does not include scopes when none are given' do
64
+ url = oauth.request_access_url
65
+
66
+ url.should_not match /scopes=/
67
+ end
56
68
  end
57
69
 
58
70
  describe '#access_token' do