linkedin-oauth2 0.1.1 → 1.0.0
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.
- 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
|