linkedin-v2 0.1.3
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 +7 -0
- data/CHANGELOG.md +10 -0
- data/CONTRIBUTING.md +1 -0
- data/Gemfile +8 -0
- data/LICENSE +22 -0
- data/README.md +224 -0
- data/Rakefile +19 -0
- data/lib/linked_in/access_token.rb +24 -0
- data/lib/linked_in/api.rb +108 -0
- data/lib/linked_in/api_resource.rb +180 -0
- data/lib/linked_in/communications.rb +40 -0
- data/lib/linked_in/configuration.rb +41 -0
- data/lib/linked_in/connection.rb +35 -0
- data/lib/linked_in/errors.rb +73 -0
- data/lib/linked_in/jobs.rb +11 -0
- data/lib/linked_in/mash.rb +68 -0
- data/lib/linked_in/media.rb +13 -0
- data/lib/linked_in/oauth2.rb +223 -0
- data/lib/linked_in/organizations.rb +217 -0
- data/lib/linked_in/people.rb +151 -0
- data/lib/linked_in/raise_error.rb +28 -0
- data/lib/linked_in/search.rb +70 -0
- data/lib/linked_in/share_and_social_stream.rb +143 -0
- data/lib/linked_in/version.rb +3 -0
- data/lib/linkedin-v2.rb +52 -0
- data/linkedin-v2.gemspec +39 -0
- data/pkg/linkedin-oauth2-2.0.0.gem +0 -0
- 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/jobs_spec.rb +33 -0
- data/spec/linked_in/api/organizations_spec.rb +54 -0
- data/spec/linked_in/api/people_spec.rb +191 -0
- data/spec/linked_in/api/search_spec.rb +71 -0
- data/spec/linked_in/api/share_and_social_stream_spec.rb +87 -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 +16 -0
- data/spec/vcr_cassettes/access_token_success.yml +99 -0
- data/spec/vcr_cassettes/bad_code.yml +99 -0
- data/spec/vcr_cassettes/organization_data.yml +51 -0
- data/spec/vcr_cassettes/people_picture_urls.yml +52 -0
- data/spec/vcr_cassettes/people_profile_connections_fields.yml +52 -0
- data/spec/vcr_cassettes/people_profile_connections_other.yml +52 -0
- data/spec/vcr_cassettes/people_profile_connections_self.yml +52 -0
- data/spec/vcr_cassettes/people_profile_fields_complex.yml +52 -0
- data/spec/vcr_cassettes/people_profile_fields_simple.yml +52 -0
- data/spec/vcr_cassettes/people_profile_lang_spanish.yml +53 -0
- data/spec/vcr_cassettes/people_profile_multiple_fields.yml +52 -0
- data/spec/vcr_cassettes/people_profile_multiple_uids.yml +52 -0
- data/spec/vcr_cassettes/people_profile_multiple_uids_and_urls.yml +52 -0
- data/spec/vcr_cassettes/people_profile_multiple_urls.yml +52 -0
- data/spec/vcr_cassettes/people_profile_new_connections_fields.yml +52 -0
- data/spec/vcr_cassettes/people_profile_new_connections_other.yml +52 -0
- data/spec/vcr_cassettes/people_profile_new_connections_self.yml +52 -0
- data/spec/vcr_cassettes/people_profile_other_uid.yml +57 -0
- data/spec/vcr_cassettes/people_profile_other_url.yml +54 -0
- data/spec/vcr_cassettes/people_profile_own.yml +57 -0
- data/spec/vcr_cassettes/people_profile_own_secure.yml +53 -0
- data/spec/vcr_cassettes/people_profile_skills.yml +52 -0
- data/spec/vcr_cassettes/unavailable.yml +99 -0
- metadata +285 -0
@@ -0,0 +1,143 @@
|
|
1
|
+
module LinkedIn
|
2
|
+
# Share and Social Stream APIs
|
3
|
+
#
|
4
|
+
# @see https://developer.linkedin.com/docs/guide/v2/shares
|
5
|
+
# @see https://developer.linkedin.com/docs/guide/v2/shares/share-api
|
6
|
+
# @see https://developer.linkedin.com/docs/guide/v2/shares/network-update-social-actions
|
7
|
+
#
|
8
|
+
# LinkedIn's v2 API adherence to the documentation is shaky at best. Several of
|
9
|
+
# the calls simply don't work if you, e.g., pass the URN in as a path element
|
10
|
+
# for a resource - you have to use the ids=[URN] format w/ a single URN. Or
|
11
|
+
# sometimes passing in an "actor" parameter in the request body simply doesn't
|
12
|
+
# work, and you have to pass it in as a URL parameter. What you see in this
|
13
|
+
# file is the result of trial-and-error getting these endpoints to work, and the
|
14
|
+
# inconsistency is usually a result of either misunderstanding the docs or the
|
15
|
+
# API not working as advertised. It's also a bit unclear when the API wants
|
16
|
+
# an activity URN vs, e.g., an article URN. Caveat emptor.
|
17
|
+
#
|
18
|
+
# [(contribute here)](https://github.com/mdesjardins/linkedin-v2)
|
19
|
+
class ShareAndSocialStream < APIResource
|
20
|
+
|
21
|
+
# Retrieve shares from a person, organization, or organizationBrand.
|
22
|
+
#
|
23
|
+
# Permissions:
|
24
|
+
# 1.) For personal shares, you may only retrieve shares for the authorized members.
|
25
|
+
# 2.) For organization shares, you may only retrieve shares for organizations for which the
|
26
|
+
# authorized member is an administrator.
|
27
|
+
#
|
28
|
+
# @see https://developer.linkedin.com/docs/guide/v2/shares/share-api#retrieve
|
29
|
+
#
|
30
|
+
# @options options [String] :owner, the URN for whom we are fetching shares.
|
31
|
+
# @return [LinkedIn::Mash]
|
32
|
+
#
|
33
|
+
def shares(options = {})
|
34
|
+
urn = options.delete(:urn)
|
35
|
+
path = "/shares?q=owners&owners=#{urn}"
|
36
|
+
get(path, options)
|
37
|
+
end
|
38
|
+
|
39
|
+
# Create one share from a person, organization, or organizationBrand.
|
40
|
+
#
|
41
|
+
# Permissions:
|
42
|
+
# 1.) For personal shares, you may only post shares as the authorized member.
|
43
|
+
# 2.) For organization shares, you may only post shares as an organization for which the
|
44
|
+
# authorized member is an administrator.
|
45
|
+
#
|
46
|
+
# @see https://developer.linkedin.com/docs/guide/v2/shares/share-api#post
|
47
|
+
#
|
48
|
+
# @option options [String] :owner, the URN of the entity posting the share.
|
49
|
+
# @return [LinkedIn::Mash]
|
50
|
+
#
|
51
|
+
def share(options = {})
|
52
|
+
path = '/shares'
|
53
|
+
defaults = {
|
54
|
+
distribution: {
|
55
|
+
linkedInDistributionTarget: {
|
56
|
+
visibleToGuest: true
|
57
|
+
}
|
58
|
+
}
|
59
|
+
}
|
60
|
+
post(path, MultiJson.dump(defaults.merge(options)), 'Content-Type' => 'application/json')
|
61
|
+
end
|
62
|
+
|
63
|
+
# Retrieves the likes for a specific post.
|
64
|
+
#
|
65
|
+
# @see https://developer.linkedin.com/docs/guide/v2/shares/network-update-social-actions#retrieve
|
66
|
+
#
|
67
|
+
# @option options [String] :urn, the URN of the relevant share, UGC post, or comment
|
68
|
+
# @return [LinkedIn::Mash]
|
69
|
+
#
|
70
|
+
def likes(options = {})
|
71
|
+
urn = options.delete(:urn)
|
72
|
+
path = "/socialActions/#{urn}/likes"
|
73
|
+
get(path, options)
|
74
|
+
end
|
75
|
+
|
76
|
+
# Likes a specific share or comment.
|
77
|
+
#
|
78
|
+
# @see https://developer.linkedin.com/docs/guide/v2/shares/network-update-social-actions#retrieve.
|
79
|
+
# @option options [String] :object, specifies the URN of the entity to which the like belongs.
|
80
|
+
# This object should be a sub-entity of the top-level share indicated in the request URL, and
|
81
|
+
# should be represented as an URN either of format urn:li:share:{id}
|
82
|
+
# @option options [String] :urn, specifies activity being un-liked (e.g., urn:li:activity::123)
|
83
|
+
# @option options [String] :actor, specifies the entity performing the action. It should be
|
84
|
+
# represented by a urn:li:person:{id} or urn:li:organization:{id} URN.
|
85
|
+
#
|
86
|
+
def like(options = {})
|
87
|
+
urn = options.delete(:urn)
|
88
|
+
path = "/socialActions/#{urn}/likes"
|
89
|
+
post(path, MultiJson.dump(options), 'Content-Type' => 'application/json')
|
90
|
+
end
|
91
|
+
|
92
|
+
# Un-likes a previously liked share or comment.
|
93
|
+
#
|
94
|
+
# @see https://developer.linkedin.com/docs/guide/v2/shares/network-update-social-actions#retrieve.
|
95
|
+
# @option options [String] :urn, specifies activity being un-liked (e.g., urn:li:activity:123)
|
96
|
+
# @option options [String] :actor, specifies the entity performing the action. It should b # represented by a urn:li:person:{id} or urn:li:organization:{id} URN.
|
97
|
+
#
|
98
|
+
def unlike(options = {})
|
99
|
+
urn = options.delete(:urn)
|
100
|
+
actor = options.delete(:actor)
|
101
|
+
path = "/socialActions/#{urn}/likes/#{actor}?actor=#{CGI::escape(actor)}"
|
102
|
+
delete(path, MultiJson.dump(options), 'Content-Type' => 'application/json') #options)
|
103
|
+
end
|
104
|
+
|
105
|
+
# Retrieves the comments for a specific post.
|
106
|
+
#
|
107
|
+
# @see https://developer.linkedin.com/docs/guide/v2/shares/network-update-social-actions#retrieve
|
108
|
+
# @option options [String] :urn, specifies activity queried for comments (e.g.,
|
109
|
+
# urn:li:article:123)
|
110
|
+
#
|
111
|
+
def comments(options = {})
|
112
|
+
urn = options.delete(:urn)
|
113
|
+
path = "/socialActions/#{urn}/comments"
|
114
|
+
get(path, options)
|
115
|
+
end
|
116
|
+
|
117
|
+
# Adds a comment to a specific post.
|
118
|
+
#
|
119
|
+
# Permissions:
|
120
|
+
#
|
121
|
+
# @see https://developer.linkedin.com/docs/guide/v2/shares/network-update-social-actions#retrieve
|
122
|
+
#
|
123
|
+
# @option options [String] :urn, specifies activity queried for comments (e.g.,
|
124
|
+
# urn:li:article:123)
|
125
|
+
# @option options [String] :actor, specifies the entity performing the action. It should b # represented by a urn:li:person:{id} or urn:li:organization:{id} URN.
|
126
|
+
# @option options [String] :message, the text content of the comment.
|
127
|
+
#
|
128
|
+
def comment(options = {})
|
129
|
+
urn = options.delete(:urn)
|
130
|
+
actor = options.delete(:actor)
|
131
|
+
message = options.delete(:message)
|
132
|
+
body = {
|
133
|
+
actor: actor,
|
134
|
+
message: {
|
135
|
+
attributes: [],
|
136
|
+
text: message
|
137
|
+
}
|
138
|
+
}
|
139
|
+
path = "/socialActions/#{urn}/comments"
|
140
|
+
post(path, MultiJson.dump(body), 'Content-Type' => 'application/json')
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
data/lib/linkedin-v2.rb
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
require "oauth2"
|
2
|
+
|
3
|
+
require "linked_in/errors"
|
4
|
+
require "linked_in/raise_error"
|
5
|
+
require "linked_in/version"
|
6
|
+
require "linked_in/configuration"
|
7
|
+
|
8
|
+
# Responsible for all authentication
|
9
|
+
# LinkedIn::OAuth2 inherits from OAuth2::Client
|
10
|
+
require "linked_in/oauth2"
|
11
|
+
|
12
|
+
# Coerces LinkedIn JSON to a nice Ruby hash
|
13
|
+
# LinkedIn::Mash inherits from Hashie::Mash
|
14
|
+
require "hashie"
|
15
|
+
require "linked_in/mash"
|
16
|
+
|
17
|
+
# Wraps a LinkedIn-specifc API connection
|
18
|
+
# LinkedIn::Connection inherits from Faraday::Connection
|
19
|
+
require "faraday"
|
20
|
+
require "linked_in/connection"
|
21
|
+
|
22
|
+
# Data object to wrap API access token
|
23
|
+
require "linked_in/access_token"
|
24
|
+
|
25
|
+
# Endpoints inherit from APIResource
|
26
|
+
require "linked_in/api_resource"
|
27
|
+
|
28
|
+
# All of the endpoints
|
29
|
+
require "linked_in/jobs"
|
30
|
+
require "linked_in/people"
|
31
|
+
require "linked_in/search"
|
32
|
+
# require "linked_in/groups" not supported by v2 API?
|
33
|
+
require "linked_in/organizations"
|
34
|
+
require "linked_in/communications"
|
35
|
+
require "linked_in/share_and_social_stream"
|
36
|
+
require 'linked_in/media'
|
37
|
+
|
38
|
+
# The primary API object that makes requests.
|
39
|
+
# It composes in all of the endpoints
|
40
|
+
require "linked_in/api"
|
41
|
+
|
42
|
+
module LinkedIn
|
43
|
+
@config = Configuration.new
|
44
|
+
|
45
|
+
class << self
|
46
|
+
attr_accessor :config
|
47
|
+
end
|
48
|
+
|
49
|
+
def self.configure
|
50
|
+
yield self.config
|
51
|
+
end
|
52
|
+
end
|
data/linkedin-v2.gemspec
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
# Follow http://guides.rubygems.org/ best practices
|
3
|
+
|
4
|
+
require File.expand_path("../lib/linked_in/version", __FILE__)
|
5
|
+
|
6
|
+
Gem::Specification.new do |gem|
|
7
|
+
gem.name = "linkedin-v2"
|
8
|
+
gem.email = ["mike.desjardins@cereslogic.com"]
|
9
|
+
gem.version = LinkedIn::VERSION
|
10
|
+
gem.authors = ["Mike Desjardins"]
|
11
|
+
gem.summary = "Ruby wrapper for the LinkedIn v2 API"
|
12
|
+
gem.license = "MIT"
|
13
|
+
gem.homepage = "http://github.com/mdesjardins/linkedin-v2"
|
14
|
+
gem.description = gem.summary
|
15
|
+
|
16
|
+
gem.files = `git ls-files`.split("\n")
|
17
|
+
gem.test_files = `git ls-files -- spec/**/*`.split("\n")
|
18
|
+
gem.require_paths = ["lib"]
|
19
|
+
|
20
|
+
# To support native JSON. Same requirements as Rails.
|
21
|
+
gem.required_ruby_version = '>= 1.9.3'
|
22
|
+
|
23
|
+
gem.add_dependency "oauth2", "~> 1.0"
|
24
|
+
gem.add_dependency "hashie", "~> 3.2"
|
25
|
+
gem.add_dependency "faraday", "~> 0.11"
|
26
|
+
|
27
|
+
gem.add_development_dependency "rake"
|
28
|
+
gem.add_development_dependency "rspec", "~> 3.0"
|
29
|
+
|
30
|
+
# We use YARD for documentation
|
31
|
+
# Extra gems for GitHub flavored MarkDown in YARD
|
32
|
+
gem.add_development_dependency "yard"
|
33
|
+
gem.add_development_dependency "redcarpet"
|
34
|
+
gem.add_development_dependency "github-markdown"
|
35
|
+
|
36
|
+
# We use VCR to mock LinkedIn API calls
|
37
|
+
gem.add_development_dependency "vcr"
|
38
|
+
gem.add_development_dependency "webmock"
|
39
|
+
end
|
Binary file
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe LinkedIn::API do
|
4
|
+
context "With no access token" do
|
5
|
+
let(:err_msg) { LinkedIn::ErrorMessages.no_access_token }
|
6
|
+
|
7
|
+
it "Raises an error" do
|
8
|
+
expect{LinkedIn::API.new}.to raise_error(LinkedIn::InvalidRequest, err_msg)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
shared_examples "test access token" do
|
13
|
+
it "Build a LinkedIn::API instance" do
|
14
|
+
expect(subject).to be_kind_of LinkedIn::API
|
15
|
+
end
|
16
|
+
|
17
|
+
it "Sets the access_token object" do
|
18
|
+
expect(subject.access_token).to be_kind_of LinkedIn::AccessToken
|
19
|
+
end
|
20
|
+
|
21
|
+
it "Sets the access_token string" do
|
22
|
+
expect(subject.access_token.token).to eq access_token
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
context "With a string access token" do
|
27
|
+
let(:access_token) { "dummy_access_token" }
|
28
|
+
subject {LinkedIn::API.new(access_token)}
|
29
|
+
|
30
|
+
include_examples "test access token"
|
31
|
+
end
|
32
|
+
|
33
|
+
context "With a LinkedIn::AccessToken object" do
|
34
|
+
let(:access_token) { "dummy_access_token" }
|
35
|
+
let(:access_token_obj) { LinkedIn::AccessToken.new(access_token) }
|
36
|
+
|
37
|
+
subject {LinkedIn::API.new(access_token_obj)}
|
38
|
+
|
39
|
+
include_examples "test access token"
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe LinkedIn::Communications do
|
4
|
+
let(:access_token) {"dummy_access_token"}
|
5
|
+
let(:api) {LinkedIn::API.new(access_token)}
|
6
|
+
|
7
|
+
it "should be able to send a message" do
|
8
|
+
stub_request(:post, "https://api.linkedin.com/v1/people/~/mailbox?oauth2_access_token=dummy_access_token").to_return(body: "", status: 201)
|
9
|
+
response = api.send_message("subject", "body", ["recip1", "recip2"])
|
10
|
+
expect(response.body).to eq ""
|
11
|
+
expect(response.status).to eq 201
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe LinkedIn::Jobs, 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 "should be able to view a job listing" do
|
13
|
+
stub("https://api.linkedin.com/v1/jobs/id=1586?")
|
14
|
+
expect(api.job(:id => 1586)).to be_an_instance_of(LinkedIn::Mash)
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should be able to view its job bookmarks" do
|
18
|
+
stub("https://api.linkedin.com/v1/people/~/job-bookmarks?")
|
19
|
+
expect(api.job_bookmarks).to be_an_instance_of(LinkedIn::Mash)
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should be able to view its job suggestion" do
|
23
|
+
stub("https://api.linkedin.com/v1/people/~/suggestions/job-suggestions?")
|
24
|
+
expect(api.job_suggestions).to be_an_instance_of(LinkedIn::Mash)
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should be able to add a bookmark" do
|
28
|
+
stub_request(:post, "https://api.linkedin.com/v1/people/~/job-bookmarks?oauth2_access_token=#{access_token}").to_return(body: "", status: 201)
|
29
|
+
response = api.add_job_bookmark(id: 1452577)
|
30
|
+
expect(response.body).to eq ""
|
31
|
+
expect(response.status).to eq 201
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe LinkedIn::Organizations do
|
4
|
+
let(:access_token) {"dummy access token"}
|
5
|
+
let(:api) {LinkedIn::API.new(access_token)}
|
6
|
+
|
7
|
+
def stub(url)
|
8
|
+
stub_request(:get, url).to_return(body: '{}')
|
9
|
+
end
|
10
|
+
|
11
|
+
it "should be able to view an organization profile" do
|
12
|
+
stub("https://api.linkedin.com/v2/organizations/1586")
|
13
|
+
expect(api.organization(id: 1586)).to be_an_instance_of(LinkedIn::Mash)
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should be able to view an organization by vanity name" do
|
17
|
+
stub("https://api.linkedin.com/v2/organizations?q=vanityName&vanityName=acme")
|
18
|
+
expect(api.organization(vanity_name: "acme")).to be_an_instance_of(LinkedIn::Mash)
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should be able to view an organization by e-mail domain" do
|
22
|
+
stub("https://api.linkedin.com/v2/organizations?q=emailDomain&emailDomain=acme.com")
|
23
|
+
expect(api.organization(email_domain: "acme.com")).to be_an_instance_of(LinkedIn::Mash)
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should load correct organization data" do
|
27
|
+
VCR.use_cassette("organization data") do
|
28
|
+
data = api.organization(id: 11571530)
|
29
|
+
expect(data.id).to eq 11571530
|
30
|
+
expect(data.name).to eq( {"localized"=>{"en_us"=>"del Nariz Social Media"}, "preferred_locale"=>{"country"=>"US", "language"=>"en"}} )
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
it "should load historical page statistics" do
|
35
|
+
stub("https://api.linkedin.com/v2/organizationPageStatistics?q=organization&organization=urn:li:organization:123456")
|
36
|
+
expect(
|
37
|
+
api.organization_page_statistics(urn: "urn:li:organization:123456")
|
38
|
+
).to be_an_instance_of(LinkedIn::Mash)
|
39
|
+
end
|
40
|
+
|
41
|
+
it "should load historical follow statistics" do
|
42
|
+
stub("https://api.linkedin.com/v2/organizationalEntityFollowerStatistics?q=organizationalEntity&organizationalEntity=urn:li:organization:123456")
|
43
|
+
expect(
|
44
|
+
api.organization_follower_statistics(urn: "urn:li:organization:123456")
|
45
|
+
).to be_an_instance_of(LinkedIn::Mash)
|
46
|
+
end
|
47
|
+
|
48
|
+
it "should load historical share statistics" do
|
49
|
+
stub("https://api.linkedin.com/v2/organizationalEntityShareStatistics?q=organizationalEntity&organizationalEntity=urn:li:organization:123456")
|
50
|
+
expect(
|
51
|
+
api.organization_share_statistics(urn: "urn:li:organization:123456")
|
52
|
+
).to be_an_instance_of(LinkedIn::Mash)
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,191 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe LinkedIn::People do
|
4
|
+
let(:uid) {"MpkAFJTlPY"}
|
5
|
+
let(:url) {"www.linkedin.com/in/miguel-santos-del-nariz"}
|
6
|
+
let(:access_token) {"AQVM91zzF-bLiOfCsTi8ktxnq99l-tW9meri8F9ZEWAuHf5g1bO_Pa4p0nFwKvZ7VFdSERAnJZq3eNOq6BzDPFNIyGIy50s-7HkLq2hE5uy6HrAQrsMAQR_qZxnBrSD11g_M2sF5XB5fUHZOXEQFgFaXB0M19VUAsvsz3yg-7zMI7w9Zn_DYTLO1e2W9VEZrOgVmRNt1XBIT_pdQO7pQkKv4702yJTrIBOuhZWNLZRClPHd2RRhPf2SJeTkodbnL4xSvzcyEPpLaTPyZIVJnBcsAzYFiG_pJtyGs7x-iWbUZsYgnUVSy8Wg-5eqmvze5tuZdICIP0PJ0AVMNGOxRRiLOEh8MSg"}
|
7
|
+
|
8
|
+
let(:api) {LinkedIn::API.new(access_token)}
|
9
|
+
|
10
|
+
def verify(result)
|
11
|
+
expect(result).to be_kind_of LinkedIn::Mash
|
12
|
+
end
|
13
|
+
|
14
|
+
###### PROFILES
|
15
|
+
# Self
|
16
|
+
it "grabs your own profile" do
|
17
|
+
VCR.use_cassette("people profile own") do
|
18
|
+
result = api.profile
|
19
|
+
verify result
|
20
|
+
expect(result["firstName"]).to be_kind_of String
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
# Secure
|
25
|
+
it "accepts secure-urls param via secure option" do
|
26
|
+
VCR.use_cassette("people profile own secure") do
|
27
|
+
verify api.profile(secure: true)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
# Language
|
32
|
+
it "gets profiles in a different language" do
|
33
|
+
VCR.use_cassette("people profile lang spanish") do
|
34
|
+
verify api.profile(lang: "es")
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
# Others
|
39
|
+
it "gets another users profile by user id" do
|
40
|
+
VCR.use_cassette("people profile other uid") do
|
41
|
+
result = api.profile(id: uid)
|
42
|
+
verify result
|
43
|
+
expect(result["firstName"]).to be_kind_of String
|
44
|
+
end
|
45
|
+
end
|
46
|
+
it "gets another users profile by url" do
|
47
|
+
VCR.use_cassette("people profile other url") do
|
48
|
+
result = api.profile(url: url)
|
49
|
+
verify result
|
50
|
+
expect(result["firstName"]).to be_kind_of String
|
51
|
+
end
|
52
|
+
end
|
53
|
+
it "gets another users profile by user id" do
|
54
|
+
VCR.use_cassette("people profile other uid") do
|
55
|
+
verify api.profile(uid)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
it "gets another users profile by url" do
|
59
|
+
VCR.use_cassette("people profile other url") do
|
60
|
+
verify api.profile(url)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
# Errors
|
65
|
+
it "errors on bad input" do
|
66
|
+
expect{api.profile("Bad input")}.to raise_error
|
67
|
+
end
|
68
|
+
it "errors on email deprecation" do
|
69
|
+
msg = LinkedIn::ErrorMessages.deprecated
|
70
|
+
expect{api.profile(email: "email@email.com")}.to raise_error(LinkedIn::Deprecated, msg)
|
71
|
+
end
|
72
|
+
|
73
|
+
# Fields
|
74
|
+
it "grabs certain profile fields" do
|
75
|
+
VCR.use_cassette("people profile fields simple") do
|
76
|
+
result = api.profile(fields: ["id","industry"])
|
77
|
+
verify result
|
78
|
+
expect(result["industry"]).to be_kind_of String
|
79
|
+
end
|
80
|
+
end
|
81
|
+
it "grabs more complex profile fields" do
|
82
|
+
VCR.use_cassette("people profile fields complex") do
|
83
|
+
result = api.profile(fields: ["id",{"positions" => ["title"]}])
|
84
|
+
verify result
|
85
|
+
expect(result["positions"]["values"][0]["title"]).to be_kind_of String
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
# Multiple people
|
90
|
+
it "grabs multiple people by uids" do
|
91
|
+
VCR.use_cassette("people profile multiple uids") do
|
92
|
+
result = api.profile(ids: ["self", uid])
|
93
|
+
verify result
|
94
|
+
expect(result["values"].length).to eq 2
|
95
|
+
end
|
96
|
+
end
|
97
|
+
it "grabs multiple people by urls" do
|
98
|
+
VCR.use_cassette("people profile multiple urls") do
|
99
|
+
result = api.profile(urls: ["self", url])
|
100
|
+
verify result
|
101
|
+
expect(result["values"].length).to eq 2
|
102
|
+
end
|
103
|
+
end
|
104
|
+
it "grabs multiple people by uids and urls" do
|
105
|
+
VCR.use_cassette("people profile multiple uids and urls") do
|
106
|
+
result = api.profile(ids: ["self", uid], urls: [url])
|
107
|
+
verify result
|
108
|
+
expect(result["values"].length).to eq 3
|
109
|
+
end
|
110
|
+
end
|
111
|
+
it "grabs certain fields for multiple people" do
|
112
|
+
VCR.use_cassette("people profile multiple fields") do
|
113
|
+
result = api.profile(ids: ["self", uid], fields: ["id", "industry"])
|
114
|
+
verify result
|
115
|
+
expect(result["values"][0]["industry"]).to be_kind_of String
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
###### CONNECTIONS
|
120
|
+
it "grabs your own connections" do
|
121
|
+
VCR.use_cassette("people profile connections self") do
|
122
|
+
result = api.connections
|
123
|
+
verify result
|
124
|
+
expect(result["values"].length).to eq 3
|
125
|
+
end
|
126
|
+
end
|
127
|
+
it "grabs the connections of others" do
|
128
|
+
VCR.use_cassette("people profile connections other") do
|
129
|
+
result = api.connections(id: uid)
|
130
|
+
verify result
|
131
|
+
expect(result["values"].length).to eq 3
|
132
|
+
end
|
133
|
+
end
|
134
|
+
it "grabs certain fields for those connections" do
|
135
|
+
VCR.use_cassette("people profile connections fields") do
|
136
|
+
result = api.connections(fields: ["id", "industry"])
|
137
|
+
verify result
|
138
|
+
expect(result["values"].length).to eq 4
|
139
|
+
expect(result["values"][0]["industry"]).to be_kind_of String
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
it "grabs new connections since a string date" do
|
144
|
+
VCR.use_cassette("people profile new connections self") do
|
145
|
+
result = api.new_connections("2014-01-01")
|
146
|
+
verify result
|
147
|
+
expect(result["values"].length).to eq 2
|
148
|
+
end
|
149
|
+
end
|
150
|
+
it "grabs new connections since a numeric date" do
|
151
|
+
VCR.use_cassette("people profile new connections self") do
|
152
|
+
verify api.new_connections(1388534400000)
|
153
|
+
end
|
154
|
+
end
|
155
|
+
it "grabs new connections since a Time.utc object" do
|
156
|
+
VCR.use_cassette("people profile new connections self") do
|
157
|
+
verify api.new_connections(Time.utc(2014,1,1))
|
158
|
+
end
|
159
|
+
end
|
160
|
+
it "grabs new connections for another user" do
|
161
|
+
VCR.use_cassette("people profile new connections other") do
|
162
|
+
result = api.new_connections("2014-01-01", id: uid)
|
163
|
+
verify result
|
164
|
+
expect(result["values"].length).to eq 2
|
165
|
+
end
|
166
|
+
end
|
167
|
+
it "grabs certain fields of new connections" do
|
168
|
+
VCR.use_cassette("people profile new connections fields") do
|
169
|
+
result = api.new_connections("2014-01-01", fields: ["id", "industry"])
|
170
|
+
verify result
|
171
|
+
expect(result["values"].length).to eq 3
|
172
|
+
expect(result["values"][0]["industry"]).to be_kind_of String
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
it "grabs picture urls" do
|
177
|
+
VCR.use_cassette("people picture urls") do
|
178
|
+
result = api.picture_urls
|
179
|
+
verify result
|
180
|
+
expect(result["values"][0] =~ URI::regexp).to_not be_nil
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
it "grabs skills" do
|
185
|
+
VCR.use_cassette("people profile skills") do
|
186
|
+
result = api.skills
|
187
|
+
verify result
|
188
|
+
expect(result["all"].length).to eq 2
|
189
|
+
end
|
190
|
+
end
|
191
|
+
end
|