githubris 0.0.4 → 0.0.5
Sign up to get free protection for your applications and to get access to all the features.
- data/.travis.yml +8 -2
- data/Gemfile +6 -3
- data/README.md +14 -0
- data/Rakefile +5 -11
- data/githubris.gemspec +2 -0
- data/lib/githubris.rb +18 -8
- data/lib/githubris/api.rb +89 -11
- data/lib/githubris/api/gist.rb +34 -15
- data/lib/githubris/api/http.rb +12 -0
- data/lib/githubris/api/user.rb +10 -4
- data/lib/githubris/base.rb +80 -0
- data/lib/githubris/comment.rb +1 -6
- data/lib/githubris/error.rb +5 -0
- data/lib/githubris/gist.rb +15 -60
- data/lib/githubris/gist/file.rb +1 -8
- data/lib/githubris/oauth.rb +36 -0
- data/lib/githubris/publicity.rb +13 -0
- data/lib/githubris/user.rb +13 -28
- data/lib/githubris/version.rb +1 -1
- data/spec/githubris/api/gist_spec.rb +8 -41
- data/spec/githubris/api/user_spec.rb +17 -2
- data/spec/githubris/api_spec.rb +99 -0
- data/spec/githubris/base_spec.rb +77 -0
- data/spec/githubris/gist_spec.rb +21 -76
- data/spec/githubris/oauth_spec.rb +71 -0
- data/spec/githubris/publicity_spec.rb +22 -0
- data/spec/githubris/user_spec.rb +50 -13
- data/spec/githubris_spec.rb +34 -40
- data/spec/spec_helper.rb +9 -6
- data/spec/support/fixtures.rb +115 -99
- data/spec/support/fixtures/vcr_cassettes/Githubris/_find_gist.yml +44 -0
- data/spec/support/fixtures/vcr_cassettes/Githubris/_find_user.yml +40 -0
- data/spec/support/fixtures/vcr_cassettes/Githubris/_public_gists.yml +55 -0
- data/spec/support/fixtures/vcr_cassettes/Githubris_API/_authenticated_/when_authenticated_with_bad_credentials.yml +40 -0
- data/spec/support/fixtures/vcr_cassettes/Githubris_API/_authenticated_/when_authenticated_with_good_credentials.yml +42 -0
- data/spec/support/fixtures/vcr_cassettes/Githubris_API/_authenticated_/when_there_are_no_credentials.yml +42 -0
- data/spec/support/fixtures/vcr_cassettes/Githubris_API_Gist/_get_gist.yml +44 -0
- data/spec/support/fixtures/vcr_cassettes/Githubris_API_Gist/_get_public_gists.yml +107 -0
- data/spec/support/fixtures/vcr_cassettes/Githubris_API_Gist/_get_user_gists.yml +43 -0
- data/spec/support/fixtures/vcr_cassettes/Githubris_API_User/_get_authenticated_user/without_credentials.yml +42 -0
- data/spec/support/fixtures/vcr_cassettes/Githubris_API_User/_get_user.yml +40 -0
- data/spec/support/fixtures/vcr_cassettes/Githubris_Gist/_save.yml +42 -0
- data/spec/support/fixtures/vcr_cassettes/Githubris_Gist/any_gist.yml +44 -0
- data/spec/support/fixtures/vcr_cassettes/Githubris_Gist/given_a_gist_full_of_data.yml +44 -0
- data/spec/support/fixtures/vcr_cassettes/Githubris_Gist/on_a_gist_with_an_id.yml +44 -0
- data/spec/support/fixtures/vcr_cassettes/Githubris_Gist/on_a_gist_with_an_id/_reload.yml +44 -0
- data/spec/support/fixtures/vcr_cassettes/Githubris_User/_gists.yml +43 -0
- data/spec/support/fixtures/vcr_cassettes/Githubris_User/_reload.yml +40 -0
- data/spec/support/fixtures/vcr_cassettes/Githubris_User/_reload/on_a_user_with_a_login.yml +40 -0
- data/spec/support/fixtures/vcr_cassettes/Githubris_User/_reload/on_a_user_without_a_login.yml +40 -0
- data/spec/support/fixtures/vcr_cassettes/Githubris_User/_starred_gists/on_an_authenticated_user.yml +82 -0
- data/spec/support/vcr.rb +6 -0
- metadata +57 -21
- data/features/get_a_gist.feature +0 -13
- data/features/get_a_user.feature +0 -8
- data/features/list_of_public_gists.feature +0 -12
- data/features/list_of_users_public_gists.feature +0 -13
- data/features/step_definitions/general_steps.rb +0 -32
- data/features/support/env.rb +0 -6
- data/features/support/fakeweb_responses.rb +0 -12
- data/features/support/fixtures.rb +0 -47
- data/lib/githubris/builder.rb +0 -28
- data/spec/githubris/builder_spec.rb +0 -28
- data/spec/support/custom_matchers.rb +0 -27
- data/spec/support/fakeweb_responses.rb +0 -12
- data/spec/support/gist.json +0 -335
- data/spec/support/public_gists_page_1.json +0 -884
- data/spec/support/public_gists_page_2.json +0 -898
- data/spec/support/user.json +0 -14
- data/spec/support/user_public_gists.json +0 -65
data/lib/githubris/comment.rb
CHANGED
@@ -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
|
data/lib/githubris/gist.rb
CHANGED
@@ -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
|
-
|
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
|
-
|
25
|
-
|
26
|
-
|
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
|
-
|
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
|
49
|
-
@attributes[:
|
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
|
69
|
-
|
70
|
-
|
71
|
-
|
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
|
data/lib/githubris/gist/file.rb
CHANGED
@@ -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
|
data/lib/githubris/user.rb
CHANGED
@@ -1,36 +1,21 @@
|
|
1
|
-
class Githubris::User
|
2
|
-
|
3
|
-
|
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
|
23
|
-
|
5
|
+
def gists(options={})
|
6
|
+
@api.get_user_gists(@attributes[:login])
|
24
7
|
end
|
25
8
|
|
26
|
-
def
|
27
|
-
@
|
9
|
+
def starred_gists(options={})
|
10
|
+
@api.get_user_starred_gists(options)
|
28
11
|
end
|
29
12
|
|
30
|
-
def
|
31
|
-
|
32
|
-
|
33
|
-
|
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
|
data/lib/githubris/version.rb
CHANGED
@@ -5,66 +5,33 @@ describe Githubris::API::Gist do
|
|
5
5
|
Githubris::API.new
|
6
6
|
end
|
7
7
|
|
8
|
-
describe '#
|
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.
|
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
|
-
|
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
|
-
|
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('
|
25
|
+
api.get_user('GithubrisTestUser')
|
11
26
|
end.should_not raise_error
|
12
27
|
end
|
13
28
|
|
data/spec/githubris/api_spec.rb
CHANGED
@@ -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
|