linkedin-drspin 0.3.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (58) hide show
  1. data/.autotest +14 -0
  2. data/.document +5 -0
  3. data/.gemtest +0 -0
  4. data/.gitignore +41 -0
  5. data/.rspec +1 -0
  6. data/.travis.yml +5 -0
  7. data/Gemfile +7 -0
  8. data/LICENSE +20 -0
  9. data/README.markdown +78 -0
  10. data/Rakefile +19 -0
  11. data/changelog.markdown +71 -0
  12. data/examples/authenticate.rb +21 -0
  13. data/examples/network.rb +12 -0
  14. data/examples/profile.rb +18 -0
  15. data/examples/sinatra.rb +77 -0
  16. data/examples/status.rb +6 -0
  17. data/lib/linked_in/api.rb +11 -0
  18. data/lib/linked_in/api/comment_methods.rb +33 -0
  19. data/lib/linked_in/api/company_search_methods.rb +65 -0
  20. data/lib/linked_in/api/group_methods.rb +18 -0
  21. data/lib/linked_in/api/people_search_methods.rb +112 -0
  22. data/lib/linked_in/api/post_methods.rb +33 -0
  23. data/lib/linked_in/api/query_methods.rb +81 -0
  24. data/lib/linked_in/api/update_methods.rb +55 -0
  25. data/lib/linked_in/client.rb +51 -0
  26. data/lib/linked_in/errors.rb +19 -0
  27. data/lib/linked_in/helpers.rb +6 -0
  28. data/lib/linked_in/helpers/authorization.rb +68 -0
  29. data/lib/linked_in/helpers/request.rb +80 -0
  30. data/lib/linked_in/mash.rb +68 -0
  31. data/lib/linked_in/search.rb +56 -0
  32. data/lib/linked_in/version.rb +11 -0
  33. data/lib/linkedin.rb +32 -0
  34. data/linkedin.gemspec +25 -0
  35. data/spec/cases/api_spec.rb +92 -0
  36. data/spec/cases/linkedin_spec.rb +37 -0
  37. data/spec/cases/mash_spec.rb +85 -0
  38. data/spec/cases/oauth_spec.rb +166 -0
  39. data/spec/cases/search_spec.rb +206 -0
  40. data/spec/fixtures/cassette_library/LinkedIn_Api/Company_API.yml +73 -0
  41. data/spec/fixtures/cassette_library/LinkedIn_Client/_authorize_from_request.yml +28 -0
  42. data/spec/fixtures/cassette_library/LinkedIn_Client/_request_token.yml +28 -0
  43. data/spec/fixtures/cassette_library/LinkedIn_Client/_request_token/with_a_callback_url.yml +28 -0
  44. data/spec/fixtures/cassette_library/LinkedIn_Client/_request_token/with_default_options.yml +28 -0
  45. data/spec/fixtures/cassette_library/LinkedIn_Search/_search/by_company_name_option.yml +135 -0
  46. data/spec/fixtures/cassette_library/LinkedIn_Search/_search/by_first_name_and_last_name_options.yml +122 -0
  47. data/spec/fixtures/cassette_library/LinkedIn_Search/_search/by_first_name_and_last_name_options_with_fields.yml +72 -0
  48. data/spec/fixtures/cassette_library/LinkedIn_Search/_search/by_keywords_string_parameter.yml +136 -0
  49. data/spec/fixtures/cassette_library/LinkedIn_Search/_search/by_single_keywords_option.yml +136 -0
  50. data/spec/fixtures/cassette_library/LinkedIn_Search/_search/by_single_keywords_option_with_pagination.yml +128 -0
  51. data/spec/fixtures/cassette_library/LinkedIn_Search/_search_company/by_keywords_options_with_fields.yml +252 -0
  52. data/spec/fixtures/cassette_library/LinkedIn_Search/_search_company/by_keywords_string_parameter.yml +73 -0
  53. data/spec/fixtures/cassette_library/LinkedIn_Search/_search_company/by_single_keywords_option.yml +71 -0
  54. data/spec/fixtures/cassette_library/LinkedIn_Search/_search_company/by_single_keywords_option_with_a_facet.yml +111 -0
  55. data/spec/fixtures/cassette_library/LinkedIn_Search/_search_company/by_single_keywords_option_with_facets_to_return.yml +71 -0
  56. data/spec/fixtures/cassette_library/LinkedIn_Search/_search_company/by_single_keywords_option_with_pagination.yml +66 -0
  57. data/spec/helper.rb +30 -0
  58. metadata +237 -0
@@ -0,0 +1,85 @@
1
+ require 'helper'
2
+
3
+ describe LinkedIn::Mash do
4
+
5
+ describe ".from_json" do
6
+ it "should convert a json string to a Mash" do
7
+ json_string = "{\"name\":\"Josh Kalderimis\"}"
8
+ mash = LinkedIn::Mash.from_json(json_string)
9
+
10
+ mash.should have_key('name')
11
+ mash.name.should == 'Josh Kalderimis'
12
+ end
13
+ end
14
+
15
+ describe "#convert_keys" do
16
+ let(:mash) do
17
+ LinkedIn::Mash.new({
18
+ 'firstName' => 'Josh',
19
+ 'LastName' => 'Kalderimis',
20
+ '_key' => 1234,
21
+ '_total' => 1234,
22
+ 'values' => {},
23
+ 'numResults' => 'total_results'
24
+ })
25
+ end
26
+
27
+ it "should convert camal cased hash keys to underscores" do
28
+ mash.should have_key('first_name')
29
+ mash.should have_key('last_name')
30
+ end
31
+
32
+ it "should convert the key _key to id" do
33
+ mash.should have_key('id')
34
+ end
35
+
36
+ it "should convert the key _total to total" do
37
+ mash.should have_key('total')
38
+ end
39
+
40
+ it "should convert the key values to all" do
41
+ mash.should have_key('all')
42
+ end
43
+
44
+ it "should convert the key numResults to total_results" do
45
+ mash.should have_key('total_results')
46
+ end
47
+ end
48
+
49
+ describe '#timestamp' do
50
+ it "should return a valid Time if a key of timestamp exists and the value is an int" do
51
+ time_mash = LinkedIn::Mash.new({ 'timestamp' => 1297083249 })
52
+
53
+ time_mash.timestamp.should be_a_kind_of(Time)
54
+ time_mash.timestamp.to_i.should == 1297083249
55
+ end
56
+
57
+ it "should return a valid Time if a key of timestamp exists and the value is an int which is greater than 9999999999" do
58
+ time_mash = LinkedIn::Mash.new({ 'timestamp' => 1297083249 * 1000 })
59
+
60
+ time_mash.timestamp.should be_a_kind_of(Time)
61
+ time_mash.timestamp.to_i.should == 1297083249
62
+ end
63
+
64
+ it "should not try to convert to a Time object if the value isn't an Integer" do
65
+ time_mash = LinkedIn::Mash.new({ 'timestamp' => 'Foo' })
66
+
67
+ time_mash.timestamp.class.should be String
68
+ end
69
+ end
70
+
71
+ describe "#to_date" do
72
+ let(:date_mash) do
73
+ LinkedIn::Mash.new({
74
+ 'year' => 2010,
75
+ 'month' => 06,
76
+ 'day' => 23
77
+ })
78
+ end
79
+
80
+ it "should return a valid Date if the keys year, month, day all exist" do
81
+ date_mash.to_date.should == Date.civil(2010, 06, 23)
82
+ end
83
+ end
84
+
85
+ end
@@ -0,0 +1,166 @@
1
+ require 'helper'
2
+
3
+ describe "LinkedIn::Client" do
4
+
5
+ let(:client) do
6
+ key = ENV['LINKED_IN_CONSUMER_KEY'] || '1234'
7
+ secret = ENV['LINKED_IN_CONSUMER_SECRET'] || '1234'
8
+ LinkedIn::Client.new(key, secret)
9
+ end
10
+
11
+ describe "#consumer" do
12
+ describe "default oauth options" do
13
+ let(:consumer) { client.consumer }
14
+
15
+ it "should return a configured OAuth consumer" do
16
+ consumer.site.should == 'https://api.linkedin.com'
17
+ consumer.request_token_url.should == 'https://api.linkedin.com/uas/oauth/requestToken'
18
+ consumer.access_token_url.should == 'https://api.linkedin.com/uas/oauth/accessToken'
19
+ consumer.authorize_url.should == 'https://www.linkedin.com/uas/oauth/authorize'
20
+ end
21
+ end
22
+
23
+ describe "different api and auth hosts options" do
24
+ let(:consumer) do
25
+ LinkedIn::Client.new('1234', '1234', {
26
+ :api_host => 'https://api.josh.com',
27
+ :auth_host => 'https://www.josh.com'
28
+ }).consumer
29
+ end
30
+
31
+ it "should return a configured OAuth consumer" do
32
+ consumer.site.should == 'https://api.josh.com'
33
+ consumer.request_token_url.should == 'https://api.josh.com/uas/oauth/requestToken'
34
+ consumer.access_token_url.should == 'https://api.josh.com/uas/oauth/accessToken'
35
+ consumer.authorize_url.should == 'https://www.josh.com/uas/oauth/authorize'
36
+ end
37
+ end
38
+
39
+ describe "different oauth paths" do
40
+ let(:consumer) do
41
+ LinkedIn::Client.new('1234', '1234', {
42
+ :request_token_path => "/secure/oauth/requestToken",
43
+ :access_token_path => "/secure/oauth/accessToken",
44
+ :authorize_path => "/secure/oauth/authorize",
45
+ }).consumer
46
+ end
47
+
48
+ it "should return a configured OAuth consumer" do
49
+ consumer.site.should == 'https://api.linkedin.com'
50
+ consumer.request_token_url.should == 'https://api.linkedin.com/secure/oauth/requestToken'
51
+ consumer.access_token_url.should == 'https://api.linkedin.com/secure/oauth/accessToken'
52
+ consumer.authorize_url.should == 'https://www.linkedin.com/secure/oauth/authorize'
53
+ end
54
+ end
55
+
56
+ describe "specify oauth urls" do
57
+ let(:consumer) do
58
+ LinkedIn::Client.new('1234', '1234', {
59
+ :request_token_url => "https://api.josh.com/secure/oauth/requestToken",
60
+ :access_token_url => "https://api.josh.com/secure/oauth/accessToken",
61
+ :authorize_url => "https://www.josh.com/secure/oauth/authorize",
62
+ }).consumer
63
+ end
64
+
65
+ it "should return a configured OAuth consumer" do
66
+ consumer.site.should == 'https://api.linkedin.com'
67
+ consumer.request_token_url.should == 'https://api.josh.com/secure/oauth/requestToken'
68
+ consumer.access_token_url.should == 'https://api.josh.com/secure/oauth/accessToken'
69
+ consumer.authorize_url.should == 'https://www.josh.com/secure/oauth/authorize'
70
+ end
71
+ end
72
+
73
+ describe "use the :site option to specify the host of all oauth urls" do
74
+ let(:consumer) do
75
+ LinkedIn::Client.new('1234', '1234', {
76
+ :site => "https://api.josh.com"
77
+ }).consumer
78
+ end
79
+
80
+ it "should return a configured OAuth consumer" do
81
+ consumer.site.should == 'https://api.josh.com'
82
+ consumer.request_token_url.should == 'https://api.josh.com/uas/oauth/requestToken'
83
+ consumer.access_token_url.should == 'https://api.josh.com/uas/oauth/accessToken'
84
+ consumer.authorize_url.should == 'https://api.josh.com/uas/oauth/authorize'
85
+ end
86
+ end
87
+ end
88
+
89
+ describe "#request_token" do
90
+ describe "with default options" do
91
+ use_vcr_cassette :record => :new_episodes
92
+
93
+ it "should return a valid request token" do
94
+ request_token = client.request_token
95
+
96
+ request_token.should be_a_kind_of OAuth::RequestToken
97
+ request_token.authorize_url.should include("https://www.linkedin.com/uas/oauth/authorize?oauth_token=")
98
+
99
+ a_request(:post, "https://api.linkedin.com/uas/oauth/requestToken").should have_been_made.once
100
+ end
101
+ end
102
+
103
+ describe "with a callback url" do
104
+ use_vcr_cassette :record => :new_episodes
105
+
106
+ it "should return a valid access token" do
107
+ request_token = client.request_token(:oauth_callback => 'http://www.josh.com')
108
+
109
+ request_token.should be_a_kind_of OAuth::RequestToken
110
+ request_token.authorize_url.should include("https://www.linkedin.com/uas/oauth/authorize?oauth_token=")
111
+ request_token.callback_confirmed?.should == true
112
+
113
+ a_request(:post, "https://api.linkedin.com/uas/oauth/requestToken").should have_been_made.once
114
+ end
115
+ end
116
+ end
117
+
118
+ describe "#authorize_from_request" do
119
+ let(:access_token) do
120
+ # if you remove the related casssette you will need to do the following
121
+ # authorize_from_request request manually
122
+ #
123
+ # request_token = client.request_token
124
+ # puts "token : #{request_token.token} - secret #{request_token.secret}"
125
+ # puts "auth url : #{request_token.authorize_url}"
126
+ # raise 'keep note of the token and secret'
127
+ #
128
+ client.authorize_from_request('dummy-token', 'dummy-secret', 'dummy-pin')
129
+ end
130
+
131
+ use_vcr_cassette :record => :new_episodes, :match_requests_on => [:uri, :method]
132
+
133
+ it "should return a valid access token" do
134
+ access_token.should be_a_kind_of Array
135
+ access_token[0].should be_a_kind_of String
136
+ access_token[1].should be_a_kind_of String
137
+
138
+ a_request(:post, "https://api.linkedin.com/uas/oauth/accessToken").should have_been_made.once
139
+ end
140
+ end
141
+
142
+ describe "#access_token" do
143
+ let(:access_token) do
144
+ client.authorize_from_access('dummy-token', 'dummy-secret')
145
+ client.access_token
146
+ end
147
+
148
+ it "should return a valid auth token" do
149
+ access_token.should be_a_kind_of OAuth::AccessToken
150
+ access_token.token.should be_a_kind_of String
151
+ end
152
+ end
153
+
154
+ describe "#authorize_from_access" do
155
+ let(:auth_token) do
156
+ client.authorize_from_access('dummy-token', 'dummy-secret')
157
+ end
158
+
159
+ it "should return a valid auth token" do
160
+ auth_token.should be_a_kind_of Array
161
+ auth_token[0].should be_a_kind_of String
162
+ auth_token[1].should be_a_kind_of String
163
+ end
164
+ end
165
+
166
+ end
@@ -0,0 +1,206 @@
1
+ require 'helper'
2
+
3
+ describe LinkedIn::Search do
4
+
5
+ # if you remove the related cassettes you will need to inform valid
6
+ # tokens and secrets to regenerate them
7
+ #
8
+ let(:client) do
9
+ consumer_token = ENV['LINKED_IN_CONSUMER_KEY'] || 'key'
10
+ consumer_secret = ENV['LINKED_IN_CONSUMER_SECRET'] || 'secret'
11
+ client = LinkedIn::Client.new(consumer_token, consumer_secret)
12
+
13
+ auth_token = ENV['LINKED_IN_AUTH_KEY'] || 'key'
14
+ auth_secret = ENV['LINKED_IN_AUTH_SECRET'] || 'secret'
15
+ client.authorize_from_access(auth_token, auth_secret)
16
+ client
17
+ end
18
+
19
+ describe "#search_company" do
20
+
21
+ describe "by keywords string parameter" do
22
+ use_vcr_cassette :record => :new_episodes
23
+
24
+ let(:results) do
25
+ client.search('apple', :company)
26
+ end
27
+
28
+ it "should perform a company search" do
29
+ results.companies.all.size.should == 10
30
+ results.companies.all.first.name.should == 'Apple'
31
+ results.companies.all.first.id.should == 162479
32
+ end
33
+ end
34
+
35
+ describe "by single keywords option" do
36
+ use_vcr_cassette :record => :new_episodes
37
+
38
+ let(:results) do
39
+ options = {:keywords => 'apple'}
40
+ client.search(options, :company)
41
+ end
42
+
43
+ it "should perform a company search" do
44
+ results.companies.all.size.should == 10
45
+ results.companies.all.first.name.should == 'Apple'
46
+ results.companies.all.first.id.should == 162479
47
+ end
48
+ end
49
+
50
+ describe "by single keywords option with facets to return" do
51
+ use_vcr_cassette :record => :new_episodes
52
+
53
+ let(:results) do
54
+ options = {:keywords => 'apple', :facets => [:industry]}
55
+ client.search(options, :company)
56
+ end
57
+
58
+ it "should return a facet" do
59
+ results.facets.all.first.buckets.all.first.name.should == 'Information Technology and Services'
60
+ end
61
+ end
62
+
63
+ describe "by single keywords option with pagination" do
64
+ use_vcr_cassette :record => :new_episodes
65
+
66
+ let(:results) do
67
+ options = {:keywords => 'apple', :start => 5, :count => 5}
68
+ client.search(options, :company)
69
+ end
70
+
71
+ it "should perform a search" do
72
+ results.companies.all.size.should == 5
73
+ results.companies.all.first.name.should == 'Apple Vacations'
74
+ results.companies.all.first.id.should == 19271
75
+ results.companies.all.last.name.should == 'Micro Center'
76
+ results.companies.all.last.id.should == 15552
77
+ end
78
+ end
79
+
80
+ describe "by keywords options with fields" do
81
+ use_vcr_cassette :record => :new_episodes
82
+
83
+ let(:results) do
84
+ fields = [{:companies => [:id, :name, :industries, :description, :specialties]}, :num_results]
85
+ client.search({:keywords => 'apple', :fields => fields}, 'company')
86
+ end
87
+
88
+ it "should perform a search" do
89
+ results.companies.all.first.name.should == 'Apple'
90
+ results.companies.all.first.description.should == 'Apple designs Macs, the best personal computers in the world, along with Mac OS X, iLife, iWork, and professional software. Apple leads the digital music revolution with its iPods and iTunes online store. Apple is reinventing the mobile phone with its revolutionary iPhone and App Store, and has recently introduced its magical iPad which is defining the future of mobile media and computing devices.'
91
+ results.companies.all.first.id.should == 162479
92
+ end
93
+ end
94
+
95
+ end
96
+
97
+ describe "#search" do
98
+
99
+ describe "by keywords string parameter" do
100
+ use_vcr_cassette :record => :new_episodes
101
+
102
+ let(:results) do
103
+ client.search('github')
104
+ end
105
+
106
+ it "should perform a search" do
107
+ results.people.all.size.should == 10
108
+ results.people.all.first.first_name.should == 'Giliardi'
109
+ results.people.all.first.last_name.should == 'Pires'
110
+ results.people.all.first.id.should == 'YkdnFl04s_'
111
+ end
112
+ end
113
+
114
+ describe "by single keywords option" do
115
+ use_vcr_cassette :record => :new_episodes
116
+
117
+ let(:results) do
118
+ client.search(:keywords => 'github')
119
+ end
120
+
121
+ it "should perform a search" do
122
+ results.people.all.size.should == 10
123
+ results.people.all.first.first_name.should == 'Giliardi'
124
+ results.people.all.first.last_name.should == 'Pires'
125
+ results.people.all.first.id.should == 'YkdnFl04s_'
126
+ end
127
+ end
128
+
129
+ describe "by single keywords option with pagination" do
130
+ use_vcr_cassette :record => :new_episodes
131
+
132
+ let(:results) do
133
+ client.search(:keywords => 'github', :start => 5, :count => 5)
134
+ end
135
+
136
+ it "should perform a search" do
137
+ results.people.all.size.should == 5
138
+ results.people.all.first.first_name.should == 'Stephen'
139
+ results.people.all.first.last_name.should == 'M.'
140
+ results.people.all.first.id.should == 'z2XMcxa_dR'
141
+ results.people.all.last.first_name.should == 'Pablo'
142
+ results.people.all.last.last_name.should == 'C.'
143
+ results.people.all.last.id.should == 'pdzrGpyP0h'
144
+ end
145
+ end
146
+
147
+ describe "by first_name and last_name options" do
148
+ use_vcr_cassette :record => :new_episodes
149
+
150
+ let(:results) do
151
+ client.search(:first_name => 'Giliardi', :last_name => 'Pires')
152
+ end
153
+
154
+ it "should perform a search" do
155
+ results.people.all.size.should == 1
156
+ results.people.all.first.first_name.should == 'Giliardi'
157
+ results.people.all.first.last_name.should == 'Pires'
158
+ results.people.all.first.id.should == 'YkdnFl04s_'
159
+ end
160
+ end
161
+
162
+ describe "by first_name and last_name options with fields" do
163
+ use_vcr_cassette :record => :new_episodes
164
+
165
+ let(:results) do
166
+ fields = [{:people => [:id, :first_name, :last_name, :public_profile_url, :picture_url]}, :num_results]
167
+ client.search(:first_name => 'Giliardi', :last_name => 'Pires', :fields => fields)
168
+ end
169
+
170
+ it "should perform a search" do
171
+ results.people.all.size.should == 1
172
+ results.people.all.first.first_name.should == 'Giliardi'
173
+ results.people.all.first.last_name.should == 'Pires'
174
+ results.people.all.first.id.should == 'YkdnFl04s_'
175
+ results.people.all.first.picture_url == 'http://media.linkedin.com/mpr/mprx/0_Oz05kn9xkWziAEOUKtOVkqzjXd8Clf7UyqIVkqchR2NtmwZRt1fWoN_aobhg-HmB09jUwPLKrAhU'
176
+ results.people.all.first.public_profile_url == 'http://www.linkedin.com/in/gibanet'
177
+ end
178
+ end
179
+
180
+ describe "by company_name option" do
181
+ use_vcr_cassette :record => :new_episodes
182
+
183
+ let(:results) do
184
+ client.search(:company_name => 'linkedin')
185
+ end
186
+
187
+ it "should perform a search" do
188
+ results.people.all.size.should == 10
189
+ results.people.all.first.first_name.should == 'Donald'
190
+ results.people.all.first.last_name.should == 'Denker'
191
+ results.people.all.first.id.should == 'VQcsz5Hp_h'
192
+ end
193
+ end
194
+
195
+ describe "#field_selector" do
196
+ it "should not modify the parameter object" do
197
+ fields = [{:people => [:id, :first_name]}]
198
+ fields_dup = fields.dup
199
+ client.send(:field_selector, fields)
200
+ fields.should eq fields_dup
201
+ end
202
+ end
203
+
204
+ end
205
+
206
+ end