linkedin-oauth2 0.1.1 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +9 -9
- data/.gitignore +24 -39
- data/.travis.yml +4 -4
- data/.yardopts +2 -0
- data/CHANGELOG.md +10 -0
- data/CONTRIBUTING.md +1 -0
- data/Gemfile +6 -5
- data/LICENSE +19 -17
- data/README.md +399 -0
- data/Rakefile +15 -22
- data/lib/linked_in/access_token.rb +24 -0
- data/lib/linked_in/api.rb +96 -3
- data/lib/linked_in/api_resource.rb +165 -0
- data/lib/linked_in/communications.rb +40 -0
- data/lib/linked_in/companies.rb +146 -0
- data/lib/linked_in/configuration.rb +41 -0
- data/lib/linked_in/connection.rb +31 -0
- data/lib/linked_in/errors.rb +33 -13
- data/lib/linked_in/groups.rb +116 -0
- data/lib/linked_in/jobs.rb +68 -0
- data/lib/linked_in/mash.rb +34 -34
- data/lib/linked_in/oauth2.rb +223 -0
- data/lib/linked_in/people.rb +141 -0
- data/lib/linked_in/search.rb +58 -43
- data/lib/linked_in/share_and_social_stream.rb +128 -0
- data/lib/linked_in/version.rb +1 -9
- data/lib/linkedin-oauth2.rb +43 -25
- data/linkedin-oauth2.gemspec +35 -21
- data/spec/linked_in/api/api_spec.rb +41 -0
- data/spec/linked_in/api/communications_spec.rb +13 -0
- data/spec/linked_in/api/companies_spec.rb +59 -0
- data/spec/linked_in/api/groups_spec.rb +55 -0
- data/spec/linked_in/api/jobs_spec.rb +33 -0
- data/spec/linked_in/api/people_spec.rb +181 -0
- data/spec/linked_in/api/search_spec.rb +71 -0
- data/spec/linked_in/api/share_and_social_stream_spec.rb +60 -0
- data/spec/linked_in/configuration_spec.rb +46 -0
- data/spec/linked_in/connection_spec.rb +10 -0
- data/spec/linked_in/module_loading_spec.rb +23 -0
- data/spec/linked_in/oauth/access_token_spec.rb +27 -0
- data/spec/linked_in/oauth/auth_code_spec.rb +86 -0
- data/spec/linked_in/oauth/credentials_spec.rb +96 -0
- data/spec/linked_in/oauth/get_access_token_spec.rb +108 -0
- data/spec/spec_helper.rb +15 -0
- data/spec/vcr_cassettes/access_token_success.yml +84 -0
- data/spec/vcr_cassettes/bad_code.yml +78 -0
- data/spec/vcr_cassettes/companies_data.yml +44 -0
- data/spec/vcr_cassettes/invalid_access_token.yml +60 -0
- data/spec/vcr_cassettes/not_found.yml +64 -0
- data/spec/vcr_cassettes/people_picture_urls.yml +54 -0
- data/spec/vcr_cassettes/people_profile_connections_fields.yml +73 -0
- data/spec/vcr_cassettes/people_profile_connections_other.yml +78 -0
- data/spec/vcr_cassettes/people_profile_connections_self.yml +78 -0
- data/spec/vcr_cassettes/people_profile_fields_complex.yml +70 -0
- data/spec/vcr_cassettes/people_profile_fields_simple.yml +57 -0
- data/spec/vcr_cassettes/people_profile_lang_spanish.yml +59 -0
- data/spec/vcr_cassettes/people_profile_multiple_fields.yml +68 -0
- data/spec/vcr_cassettes/people_profile_multiple_uids.yml +70 -0
- data/spec/vcr_cassettes/people_profile_multiple_uids_and_urls.yml +76 -0
- data/spec/vcr_cassettes/people_profile_multiple_urls.yml +70 -0
- data/spec/vcr_cassettes/people_profile_new_connections_fields.yml +69 -0
- data/spec/vcr_cassettes/people_profile_new_connections_other.yml +72 -0
- data/spec/vcr_cassettes/people_profile_new_connections_self.yml +72 -0
- data/spec/vcr_cassettes/people_profile_other_uid.yml +59 -0
- data/spec/vcr_cassettes/people_profile_other_url.yml +59 -0
- data/spec/vcr_cassettes/people_profile_own.yml +59 -0
- data/spec/vcr_cassettes/people_profile_own_secure.yml +59 -0
- data/spec/vcr_cassettes/unauthorized.yml +61 -0
- data/spec/vcr_cassettes/unavailable.yml +81 -0
- metadata +145 -88
- data/.autotest +0 -14
- data/.document +0 -5
- data/.gemtest +0 -0
- data/.rspec +0 -1
- data/.ruby-gemset +0 -1
- data/.ruby-version +0 -1
- data/README.markdown +0 -121
- data/changelog.markdown +0 -94
- data/examples/authenticate.rb +0 -16
- data/examples/network.rb +0 -12
- data/examples/profile.rb +0 -18
- data/examples/sinatra.rb +0 -69
- data/examples/status.rb +0 -6
- data/lib/linked_in/api/query_methods.rb +0 -123
- data/lib/linked_in/api/update_methods.rb +0 -76
- data/lib/linked_in/client.rb +0 -31
- data/lib/linked_in/helpers.rb +0 -6
- data/lib/linked_in/helpers/authorization.rb +0 -106
- data/lib/linked_in/helpers/request.rb +0 -93
- data/spec/cases/api_spec.rb +0 -192
- data/spec/cases/linkedin_spec.rb +0 -37
- data/spec/cases/mash_spec.rb +0 -85
- data/spec/cases/oauth_spec.rb +0 -130
- data/spec/cases/search_spec.rb +0 -190
- data/spec/helper.rb +0 -30
@@ -0,0 +1,71 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe LinkedIn::Search, helpers: :api do
|
4
|
+
let(:access_token) {"dummy_access_token"}
|
5
|
+
let(:api) {LinkedIn::API.new(access_token)}
|
6
|
+
|
7
|
+
def stub(url)
|
8
|
+
url += "oauth2_access_token=#{access_token}"
|
9
|
+
stub_request(:get, url).to_return(body: '{}')
|
10
|
+
end
|
11
|
+
|
12
|
+
it "lets you search for all your contacts" do
|
13
|
+
stub("https://api.linkedin.com/v1/people-search?")
|
14
|
+
expect(api.search()).to be_kind_of LinkedIn::Mash
|
15
|
+
end
|
16
|
+
|
17
|
+
it "allows a keyword search with no hash" do
|
18
|
+
stub("https://api.linkedin.com/v1/people-search?keywords=Proximate%20Harvard&")
|
19
|
+
expect(api.search("Proximate Harvard")).to be_kind_of LinkedIn::Mash
|
20
|
+
end
|
21
|
+
|
22
|
+
it "allows a keyword search with the kewywords option" do
|
23
|
+
stub("https://api.linkedin.com/v1/people-search?keywords=Proximate%20Harvard&")
|
24
|
+
expect(api.search(keywords: "Proximate Harvard")).to be_kind_of LinkedIn::Mash
|
25
|
+
end
|
26
|
+
|
27
|
+
it "lets you search by an attribute" do
|
28
|
+
stub("https://api.linkedin.com/v1/people-search?school-name=Olin%20College%20of%20Engineering&")
|
29
|
+
expect(api.search(school_name: "Olin College of Engineering")).to be_kind_of LinkedIn::Mash
|
30
|
+
end
|
31
|
+
|
32
|
+
it "combines searches" do
|
33
|
+
stub("https://api.linkedin.com/v1/people-search?first-name=Evan&last-name=Morikawa&")
|
34
|
+
expect(api.search(first_name: "Evan", last_name: "Morikawa")).to be_kind_of LinkedIn::Mash
|
35
|
+
end
|
36
|
+
|
37
|
+
it "searches for specific fields" do
|
38
|
+
stub("https://api.linkedin.com/v1/people-search:(people:(id,first-name,last-name),num-results)?")
|
39
|
+
expect(api.search(fields: [{people: ["id", "first-name", "last-name"]}, "num-results"])).to be_kind_of LinkedIn::Mash
|
40
|
+
end
|
41
|
+
|
42
|
+
it "allows you to pass a sort parameter" do
|
43
|
+
stub("https://api.linkedin.com/v1/people-search?sort=connections&")
|
44
|
+
expect(api.search(sort: "connections")).to be_kind_of LinkedIn::Mash
|
45
|
+
end
|
46
|
+
|
47
|
+
it "it allows start and count parameters" do
|
48
|
+
stub("https://api.linkedin.com/v1/people-search?start=10&count=5&")
|
49
|
+
expect(api.search(start: 10, count: 5)).to be_kind_of LinkedIn::Mash
|
50
|
+
end
|
51
|
+
|
52
|
+
it "it lets you search by facets" do
|
53
|
+
stub("https://api.linkedin.com/v1/people-search:(facets:(code,buckets:(code,name)))?facets=location&")
|
54
|
+
|
55
|
+
fields = {facets: ["code", {buckets: ["code", "name"]}]}
|
56
|
+
|
57
|
+
expect(api.search(fields: fields,
|
58
|
+
facets: "location")).to be_kind_of LinkedIn::Mash
|
59
|
+
end
|
60
|
+
|
61
|
+
it "lets you search for complex facets" do
|
62
|
+
stub("https://api.linkedin.com/v1/people-search:(facets:(code,buckets:(code,name,count)))?facets=location,network&facet=location,us:84&facet=network,F&")
|
63
|
+
|
64
|
+
fields = {facets: ["code", {buckets: ["code", "name", "count"]}]}
|
65
|
+
|
66
|
+
expect(api.search(fields: fields,
|
67
|
+
facets: "location,network",
|
68
|
+
facet: ["location,us:84", "network,F"])
|
69
|
+
).to be_kind_of LinkedIn::Mash
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe LinkedIn::ShareAndSocialStream do
|
4
|
+
let(:access_token) {"dummy_access_token"}
|
5
|
+
let(:api) {LinkedIn::API.new(access_token)}
|
6
|
+
|
7
|
+
def stub(url)
|
8
|
+
url += "oauth2_access_token=#{access_token}"
|
9
|
+
stub_request(:get, url).to_return(body: '{}')
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should be able to view network_updates" do
|
13
|
+
stub("https://api.linkedin.com/v1/people/~/network/updates?")
|
14
|
+
expect(api.network_updates).to be_an_instance_of(LinkedIn::Mash)
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should be able to view network_update's comments" do
|
18
|
+
stub("https://api.linkedin.com/v1/people/~/network/updates/key=network_update_key/update-comments?")
|
19
|
+
expect(api.share_comments("network_update_key")).to be_an_instance_of(LinkedIn::Mash)
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should be able to view network_update's likes" do
|
23
|
+
stub("https://api.linkedin.com/v1/people/~/network/updates/key=network_update_key/likes?")
|
24
|
+
expect(api.share_likes("network_update_key")).to be_an_instance_of(LinkedIn::Mash)
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should be able to share a new status" do
|
28
|
+
stub_request(:post, "https://api.linkedin.com/v1/people/~/shares?oauth2_access_token=#{access_token}").to_return(body: "", status: 201)
|
29
|
+
response = api.add_share(:comment => "Testing, 1, 2, 3")
|
30
|
+
expect(response.body).to eq ""
|
31
|
+
expect(response.status).to eq 201
|
32
|
+
end
|
33
|
+
|
34
|
+
it "returns the shares for a person" do
|
35
|
+
stub("https://api.linkedin.com/v1/people/~/network/updates?type=SHAR&scope=self&after=1234&count=35&")
|
36
|
+
api.shares(:after => 1234, :count => 35)
|
37
|
+
end
|
38
|
+
|
39
|
+
it "should be able to comment on network update" do
|
40
|
+
stub_request(:post, "https://api.linkedin.com/v1/people/~/network/updates/key=SOMEKEY/update-comments?oauth2_access_token=#{access_token}").to_return(body: "", status: 201)
|
41
|
+
response = api.update_comment('SOMEKEY', "Testing, 1, 2, 3")
|
42
|
+
expect(response.body).to eq ""
|
43
|
+
expect(response.status).to eq 201
|
44
|
+
end
|
45
|
+
|
46
|
+
it "should be able to like a network update" do
|
47
|
+
stub_request(:put, "https://api.linkedin.com/v1/people/~/network/updates/key=SOMEKEY/is-liked?oauth2_access_token=#{access_token}").
|
48
|
+
with(:body => "true").to_return(body: "", status: 201)
|
49
|
+
response = api.like_share('SOMEKEY')
|
50
|
+
expect(response.body).to eq ""
|
51
|
+
expect(response.status).to eq 201
|
52
|
+
end
|
53
|
+
|
54
|
+
it "should be able to unlike a network update" do
|
55
|
+
stub_request(:put, "https://api.linkedin.com/v1/people/~/network/updates/key=SOMEKEY/is-liked?oauth2_access_token=#{access_token}").to_return(body: "", status: 201)
|
56
|
+
response = api.unlike_share('SOMEKEY')
|
57
|
+
expect(response.body).to eq ""
|
58
|
+
expect(response.status).to eq 201
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe "LinkedIn configuration" do
|
4
|
+
let(:config_value) { "Foo Bar" }
|
5
|
+
|
6
|
+
let(:site) { "https://www.linkedin.com" }
|
7
|
+
let(:token_url) { "/uas/oauth2/accessToken" }
|
8
|
+
let(:authorize_url) { "/uas/oauth2/authorization" }
|
9
|
+
|
10
|
+
subject { LinkedIn.config }
|
11
|
+
|
12
|
+
before(:example) do
|
13
|
+
LinkedIn.configure do |config|
|
14
|
+
config.client_id = config_value
|
15
|
+
config.client_secret = config_value
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
it("has a client_id") do
|
20
|
+
expect(subject.client_id).to eq config_value
|
21
|
+
end
|
22
|
+
|
23
|
+
it("has a client_secret") do
|
24
|
+
expect(subject.client_secret).to eq config_value
|
25
|
+
end
|
26
|
+
|
27
|
+
it("has an aliased api_key") do
|
28
|
+
expect(subject.api_key).to eq config_value
|
29
|
+
end
|
30
|
+
|
31
|
+
it("has an aliased secret_key") do
|
32
|
+
expect(subject.secret_key).to eq config_value
|
33
|
+
end
|
34
|
+
|
35
|
+
it("has the correct default site") do
|
36
|
+
expect(subject.site).to eq site
|
37
|
+
end
|
38
|
+
|
39
|
+
it("has the correct default token_url") do
|
40
|
+
expect(subject.token_url).to eq token_url
|
41
|
+
end
|
42
|
+
|
43
|
+
it("has the correct default authorize_url") do
|
44
|
+
expect(subject.authorize_url).to eq authorize_url
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
describe LinkedIn::Connection do
|
2
|
+
it "inherits from Faraday::Connection" do
|
3
|
+
expect(subject).to be_kind_of Faraday::Connection
|
4
|
+
end
|
5
|
+
|
6
|
+
it "has the correct default url" do
|
7
|
+
url = LinkedIn.config.api + LinkedIn.config.api_version
|
8
|
+
expect(subject.url_prefix.to_s).to eq url
|
9
|
+
end
|
10
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe LinkedIn do
|
4
|
+
it "is a module" do
|
5
|
+
expect(LinkedIn).to be_a Module
|
6
|
+
end
|
7
|
+
|
8
|
+
it "is independently loadable" do
|
9
|
+
expect { require 'linkedin-oauth2' }.not_to raise_error
|
10
|
+
end
|
11
|
+
|
12
|
+
describe LinkedIn::OAuth2 do
|
13
|
+
it "is a class" do
|
14
|
+
expect(LinkedIn::OAuth2).to be_a Class
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
describe LinkedIn::API do
|
19
|
+
it "is a class" do
|
20
|
+
expect(LinkedIn::API).to be_a Class
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
describe "LinkedIn::AccessToken" do
|
2
|
+
let(:tok) {:dummy_access_token}
|
3
|
+
let(:expires_in) { 64000 }
|
4
|
+
let(:expires_at) { Time.utc(2014,1,1) }
|
5
|
+
|
6
|
+
context "When just token is set" do
|
7
|
+
subject {LinkedIn::AccessToken.new(tok)}
|
8
|
+
it("has the token value") { expect(subject.token).to eq tok }
|
9
|
+
end
|
10
|
+
|
11
|
+
context "When only expires_in is set" do
|
12
|
+
subject {LinkedIn::AccessToken.new(tok, expires_in)}
|
13
|
+
it("set expires_in") {expect(subject.expires_in).to eq expires_in}
|
14
|
+
it("calculated expires_at") do
|
15
|
+
calc_time = Time.now + expires_in
|
16
|
+
diff = subject.expires_at - calc_time
|
17
|
+
expect(diff).to be < 1
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
context "When everything is set" do
|
22
|
+
subject {LinkedIn::AccessToken.new(tok, expires_in, expires_at)}
|
23
|
+
it("set token") { expect(subject.token).to eq tok }
|
24
|
+
it("set expires_in") {expect(subject.expires_in).to eq expires_in}
|
25
|
+
it("set expires_at") {expect(subject.expires_at).to eq expires_at}
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
require "uri"
|
3
|
+
require "cgi"
|
4
|
+
|
5
|
+
describe "OAuth2 Auth Code" do
|
6
|
+
before(:example) do
|
7
|
+
LinkedIn.configure do |config|
|
8
|
+
config.client_id = "dummy_client_id"
|
9
|
+
config.client_secret = "dummy_client_secret"
|
10
|
+
end
|
11
|
+
end
|
12
|
+
subject { LinkedIn::OAuth2.new }
|
13
|
+
|
14
|
+
def params(key, opts=nil)
|
15
|
+
CGI.parse(URI.parse(subject.auth_code_url(opts)).query)[key][0]
|
16
|
+
end
|
17
|
+
|
18
|
+
context "When no redirect_uri is given" do
|
19
|
+
before(:example) do
|
20
|
+
LinkedIn.configure { |config| config.redirect_uri = nil }
|
21
|
+
end
|
22
|
+
|
23
|
+
let(:err_msg) { LinkedIn::ErrorMessages.redirect_uri }
|
24
|
+
|
25
|
+
it "Throws an error" do
|
26
|
+
expect {subject.auth_code_url}.to raise_error(LinkedIn::InvalidRequest, err_msg)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
context "When an auth code url is requested with no options" do
|
31
|
+
let(:redirect_uri) { "http://lvh.me:5000" }
|
32
|
+
let(:scope) { "r_fullprofile r_emailaddress r_network" }
|
33
|
+
|
34
|
+
before(:example) do
|
35
|
+
LinkedIn.configure do |config|
|
36
|
+
config.redirect_uri = redirect_uri
|
37
|
+
config.scope = scope
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
it "Returns the client id in the uri" do
|
42
|
+
expect(params("client_id")).to eq LinkedIn.config.client_id
|
43
|
+
end
|
44
|
+
|
45
|
+
it "Includes the configured redirect_uri" do
|
46
|
+
expect(params("redirect_uri")).to eq redirect_uri
|
47
|
+
end
|
48
|
+
|
49
|
+
it "Includes the configured scope" do
|
50
|
+
expect(params("scope")).to eq scope
|
51
|
+
end
|
52
|
+
|
53
|
+
it "Includes an autogenerated state" do
|
54
|
+
expect(params("state")).to_not be_nil
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
context "When an auth code url is requested with options" do
|
59
|
+
let(:state) { "foobarbaz" }
|
60
|
+
let(:scope) { "r_basicprofile rw_nus" }
|
61
|
+
let(:redirect_uri) { "https://example.com" }
|
62
|
+
|
63
|
+
let(:opts) do
|
64
|
+
{state: state,
|
65
|
+
scope: scope,
|
66
|
+
redirect_uri: redirect_uri}
|
67
|
+
end
|
68
|
+
|
69
|
+
it "Returns the client id in the uri" do
|
70
|
+
expect(params("client_id", opts)).to eq LinkedIn.config.client_id
|
71
|
+
end
|
72
|
+
|
73
|
+
it "Includes the custom redirect_uri" do
|
74
|
+
expect(params("redirect_uri", opts)).to eq redirect_uri
|
75
|
+
end
|
76
|
+
|
77
|
+
it "Includes the custom scope" do
|
78
|
+
expect(params("scope", opts)).to eq scope
|
79
|
+
end
|
80
|
+
|
81
|
+
it "Includes the custom state" do
|
82
|
+
expect(params("state", opts)).to eq state
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
end
|
@@ -0,0 +1,96 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe LinkedIn::OAuth2 do
|
4
|
+
let(:site) { LinkedIn.config.site }
|
5
|
+
let(:token_url) { LinkedIn.config.token_url }
|
6
|
+
let(:authorize_url) { LinkedIn.config.authorize_url }
|
7
|
+
|
8
|
+
let(:client_id) { "dummy_client_id" }
|
9
|
+
let(:client_secret) { "dummy_client_secret" }
|
10
|
+
|
11
|
+
shared_examples "verify client" do
|
12
|
+
it "creates a valid oauth object" do
|
13
|
+
expect(subject).to be_kind_of(LinkedIn::OAuth2)
|
14
|
+
end
|
15
|
+
it "is a subclass of OAuth2::Client" do
|
16
|
+
expect(subject).to be_kind_of(OAuth2::Client)
|
17
|
+
end
|
18
|
+
it "assigned the client_id to id" do
|
19
|
+
expect(subject.id).to eq client_id
|
20
|
+
end
|
21
|
+
it "assigned the client_secret to secret" do
|
22
|
+
expect(subject.secret).to eq client_secret
|
23
|
+
end
|
24
|
+
it "assigned the site to site" do
|
25
|
+
expect(subject.site).to eq site
|
26
|
+
end
|
27
|
+
it "assigned the authorize_url option" do
|
28
|
+
expect(subject.options[:authorize_url]).to eq authorize_url
|
29
|
+
end
|
30
|
+
it "assigned the token_url option" do
|
31
|
+
expect(subject.options[:token_url]).to eq token_url
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
shared_examples "options take" do
|
36
|
+
it "overrides default options" do
|
37
|
+
expect(subject.options[:raise_errors]).to eq false
|
38
|
+
end
|
39
|
+
it "sets new options" do
|
40
|
+
expect(subject.options[:new_opt]).to eq "custom option"
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
context "When client credentials exist" do
|
45
|
+
before(:example) do
|
46
|
+
LinkedIn.configure do |config|
|
47
|
+
config.client_id = client_id
|
48
|
+
config.client_secret = client_secret
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
include_examples "verify client"
|
53
|
+
|
54
|
+
let(:options) do
|
55
|
+
return {raise_errors: false,
|
56
|
+
new_opt: "custom option"}
|
57
|
+
end
|
58
|
+
|
59
|
+
context "When custom options are passed in as first arg" do
|
60
|
+
subject do
|
61
|
+
LinkedIn::OAuth2.new(options)
|
62
|
+
end
|
63
|
+
include_examples "options take"
|
64
|
+
end
|
65
|
+
|
66
|
+
context "When custom options are passed in" do
|
67
|
+
subject do
|
68
|
+
LinkedIn::OAuth2.new(client_id, client_secret, options)
|
69
|
+
end
|
70
|
+
include_examples "options take"
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
74
|
+
|
75
|
+
context "When client credentials do not exist" do
|
76
|
+
let(:err_msg) { LinkedIn::ErrorMessages.credentials_missing }
|
77
|
+
|
78
|
+
before(:example) do
|
79
|
+
LinkedIn.configure do |config|
|
80
|
+
config.client_id = nil
|
81
|
+
config.client_secret = nil
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
it "raises an error" do
|
86
|
+
expect { LinkedIn::OAuth2.new }.to raise_error(LinkedIn::InvalidRequest, err_msg)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
context "When client credentials are passed in" do
|
91
|
+
subject { LinkedIn::OAuth2.new(client_id, client_secret) }
|
92
|
+
|
93
|
+
include_examples "verify client"
|
94
|
+
end
|
95
|
+
|
96
|
+
end
|
@@ -0,0 +1,108 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe "Get OAuth2 Access Token" do
|
4
|
+
code = "dummy_code"
|
5
|
+
client_id = "dummy_client_id"
|
6
|
+
client_secret = "dummy_client_secret"
|
7
|
+
redirect_uri = "http://lvh.me:5000"
|
8
|
+
|
9
|
+
before(:example) do
|
10
|
+
LinkedIn.configure do |config|
|
11
|
+
config.client_id = client_id
|
12
|
+
config.client_secret = client_secret
|
13
|
+
config.redirect_uri = redirect_uri
|
14
|
+
end
|
15
|
+
end
|
16
|
+
subject { LinkedIn::OAuth2.new }
|
17
|
+
|
18
|
+
shared_examples "Success Access Token Fetch" do |*args|
|
19
|
+
it "Returns an access token object" do
|
20
|
+
VCR.use_cassette("access token success") do
|
21
|
+
expect(subject.get_access_token(*args)).to be_kind_of LinkedIn::AccessToken
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
it "Sets the AcessToken object" do
|
26
|
+
VCR.use_cassette("access token success") do
|
27
|
+
subject.get_access_token(*args)
|
28
|
+
expect(subject.access_token).to be_kind_of LinkedIn::AccessToken
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
it "Generated an access token string" do
|
33
|
+
VCR.use_cassette("access token success") do
|
34
|
+
subject.get_access_token(*args)
|
35
|
+
expect(subject.access_token.token).to be_kind_of String
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
shared_examples "Raises InvalidRequest" do |*args|
|
41
|
+
it "Raises InvalidRequest" do
|
42
|
+
expect{subject.get_access_token(*args)}.to raise_error(LinkedIn::InvalidRequest, msg)
|
43
|
+
end
|
44
|
+
|
45
|
+
it "Has no AccessToken object set" do
|
46
|
+
expect(subject.access_token).to be_nil
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
context "When a auth_code is provided" do
|
51
|
+
include_examples "Success Access Token Fetch", code
|
52
|
+
end
|
53
|
+
|
54
|
+
context "When no code is given" do
|
55
|
+
let(:msg) {LinkedIn::ErrorMessages.no_auth_code}
|
56
|
+
include_examples "Raises InvalidRequest"
|
57
|
+
end
|
58
|
+
|
59
|
+
context "When redirect_uri is not configured and not passed in" do
|
60
|
+
before(:example) do
|
61
|
+
LinkedIn.configure { |config| config.redirect_uri = nil }
|
62
|
+
end
|
63
|
+
let(:msg) {LinkedIn::ErrorMessages.redirect_uri}
|
64
|
+
include_examples "Raises InvalidRequest", code
|
65
|
+
end
|
66
|
+
|
67
|
+
context "When redirect_uri is configured and not passed in" do
|
68
|
+
before(:example) do
|
69
|
+
LinkedIn.configure { |config| config.redirect_uri = redirect_uri }
|
70
|
+
end
|
71
|
+
include_examples "Success Access Token Fetch", code
|
72
|
+
end
|
73
|
+
|
74
|
+
context "When redirect_uri is passed in" do
|
75
|
+
include_examples "Success Access Token Fetch", code, {redirect_uri: redirect_uri}
|
76
|
+
end
|
77
|
+
|
78
|
+
context "When redirect_uri was previously set by auth_code_url" do
|
79
|
+
before(:example) do
|
80
|
+
LinkedIn.configure { |config| config.redirect_uri = nil }
|
81
|
+
subject.auth_code_url(redirect_uri: redirect_uri)
|
82
|
+
end
|
83
|
+
include_examples "Success Access Token Fetch", code
|
84
|
+
end
|
85
|
+
|
86
|
+
context "When redirect_uri does not match previous setting" do
|
87
|
+
let(:msg) {LinkedIn::ErrorMessages.redirect_uri_mismatch}
|
88
|
+
include_examples "Raises InvalidRequest", code, {redirect_uri: "different"}
|
89
|
+
end
|
90
|
+
|
91
|
+
context "When the service is unavailable" do
|
92
|
+
let(:msg) { /temporarily_unavailable/ }
|
93
|
+
it "raises an OAuthError" do
|
94
|
+
VCR.use_cassette("unavailable") do
|
95
|
+
expect {subject.get_access_token(code)}.to raise_error(LinkedIn::OAuthError, msg)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
context "When the request is invalid" do
|
101
|
+
let(:msg) { /invalid_request/ }
|
102
|
+
it "raises an OAuthError" do
|
103
|
+
VCR.use_cassette("bad code") do
|
104
|
+
expect {subject.get_access_token(code)}.to raise_error(LinkedIn::OAuthError, msg)
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|