ezlinkedin 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: fd3bc787edf277267d4ecdf564c7afddabb8398a
4
+ data.tar.gz: f9e5b890bfdd7ec4aa283c67e47e2b2371e36bca
5
+ SHA512:
6
+ metadata.gz: 595165aee0f3d837399c8aef7ec38f1982f31d8620fb2cae076c1bcd434b83ae863dd87e5aa2cc09e5fc740c3849b11314a181b50773dfc65ad76895340c614a
7
+ data.tar.gz: 7cccd7d271e2f0b7601b9f42c60fa48cebf097358103031e2d378a96d87b750331daa498c77a424cde888c0e1ee07c5fb43a5026453b301ab3be00bfaae8c1a1
data/.gitignore ADDED
@@ -0,0 +1,19 @@
1
+ *~
2
+ *.*~
3
+ *.gem
4
+ *.rbc
5
+ .bundle
6
+ .config
7
+ .yardoc
8
+ Gemfile.lock
9
+ InstalledFiles
10
+ _yardoc
11
+ coverage
12
+ doc/
13
+ lib/bundler/man
14
+ pkg
15
+ rdoc
16
+ spec/reports
17
+ test/tmp
18
+ test/version_tmp
19
+ tmp
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format progress
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in ezlinkedin.gemspec
4
+ gemspec
data/Guardfile ADDED
@@ -0,0 +1,24 @@
1
+ # A sample Guardfile
2
+ # More info at https://github.com/guard/guard#readme
3
+
4
+ guard :rspec do
5
+ watch(%r{^spec/.+_spec\.rb$})
6
+ watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
7
+ watch('spec/spec_helper.rb') { "spec" }
8
+
9
+ # Rails example
10
+ watch(%r{^app/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
11
+ watch(%r{^app/(.*)(\.erb|\.haml)$}) { |m| "spec/#{m[1]}#{m[2]}_spec.rb" }
12
+ watch(%r{^app/controllers/(.+)_(controller)\.rb$}) { |m| ["spec/routing/#{m[1]}_routing_spec.rb", "spec/#{m[2]}s/#{m[1]}_#{m[2]}_spec.rb", "spec/acceptance/#{m[1]}_spec.rb"] }
13
+ watch(%r{^spec/support/(.+)\.rb$}) { "spec" }
14
+ watch('config/routes.rb') { "spec/routing" }
15
+ watch('app/controllers/application_controller.rb') { "spec/controllers" }
16
+
17
+ # Capybara features specs
18
+ watch(%r{^app/views/(.+)/.*\.(erb|haml)$}) { |m| "spec/features/#{m[1]}_spec.rb" }
19
+
20
+ # Turnip features and steps
21
+ watch(%r{^spec/acceptance/(.+)\.feature$})
22
+ watch(%r{^spec/acceptance/steps/(.+)_steps\.rb$}) { |m| Dir[File.join("**/#{m[1]}.feature")][0] || 'spec/acceptance' }
23
+ end
24
+
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 akonwi
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,44 @@
1
+ # Ezlinkedin
2
+
3
+ A simple way to make calls on Linkedin's API. NOTE: It is not yet completed and does not encompass all of the api at this time. It serves the purpose I made it for but I will continue to develop it.
4
+
5
+ This is heavily inspired and influenced by pengwynn's linkedin gem. I was having issues with his gem though and there is very little documentation for using it so I decided to redo it myself in order to:
6
+ * Make it work for what I needed
7
+ * Add precise and useful documentation
8
+ * contribute a bit more robust ruby wrapper for Linkedin's API
9
+
10
+ Most of the tests are from pengwynn's gem
11
+
12
+ ## Installation
13
+
14
+ Add this line to your application's Gemfile:
15
+
16
+ gem 'ezlinkedin'
17
+
18
+ And then execute:
19
+
20
+ $ bundle
21
+
22
+ Or install it yourself as:
23
+
24
+ $ gem install ezlinkedin
25
+
26
+ ## Usage
27
+
28
+ This is meant to be used alongside omniauth. Obtain access tokens from omniauth authentication and then use them to make api calls.
29
+
30
+ require 'ezlinkedin'
31
+
32
+ # Create a client
33
+ linkedin = EzLinkedin::Client.new("API KEY", "SECRET KEY", options) # options are the typical OAuth consumer options
34
+ linkedin.authorize("access_token", "access_token_secret") # tokens obtained from omniauth
35
+
36
+ Currently, one can post shares, retrieve updates, user profile, and connections.
37
+
38
+ ## Contributing
39
+
40
+ 1. Fork it
41
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
42
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
43
+ 4. Push to the branch (`git push origin my-new-feature`)
44
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,7 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new
5
+
6
+ task :default => :spec
7
+ task :test => :spec
@@ -0,0 +1,32 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'ezlinkedin/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "ezlinkedin"
8
+ spec.version = Ezlinkedin::VERSION
9
+ spec.authors = ["akonwi"]
10
+ spec.email = ["akonwi@gmail.com"]
11
+ spec.description = "A simple way to make calls on Linkedin's API"
12
+ spec.summary = %q{It's a simple way to access Linkedin and it's coupled well will omniauth}
13
+ spec.homepage = ""
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_runtime_dependency 'oauth', '~> 0.4.7'
22
+ spec.add_runtime_dependency 'hashie', '~> 2.0.5'
23
+ spec.add_runtime_dependency 'json', '~> 1.8.0'
24
+ spec.add_runtime_dependency 'multi_json', '~> 1.7.3'
25
+ spec.add_development_dependency "bundler", "~> 1.3"
26
+ spec.add_development_dependency "rake"
27
+ spec.add_development_dependency "rspec", '~> 2.6'
28
+ spec.add_development_dependency 'guard'
29
+ spec.add_development_dependency 'guard-rspec'
30
+ spec.add_development_dependency 'libnotify'
31
+ spec.add_development_dependency "webmock", '~> 1.11.0'
32
+ end
@@ -0,0 +1,115 @@
1
+ module EzLinkedin
2
+ module Api
3
+
4
+ module QueryMethods
5
+
6
+ #
7
+ # Retrieve a certain profile depending on the options passed in.
8
+ # @param options={} [Hash] can be an array of fields as strings and an id,
9
+ # and a url to a public profile. This can also contain request
10
+ # headers
11
+ #
12
+ # @return [Mash] a Mash hash representing the found profile
13
+ def profile(options={})
14
+ path = person_path(options)
15
+ make_query(path, options, true)
16
+ end
17
+
18
+
19
+ #
20
+ # Retrieve the authenticated user's connections
21
+ # @param options={} [Hash] pass in fields and/or a count
22
+ #
23
+ # @return [Mash] Mash hash of connections
24
+ def connections(options={})
25
+ path = "#{person_path(options)}/connections"
26
+ make_query(path, options, true)
27
+ end
28
+
29
+ #
30
+ # Retrieve the user's social feed
31
+ # @param options={} [Hash] visit Linkedin's api to
32
+ # see possible options. it will default to an
33
+ # aggregated feed unless :scope => 'self'.
34
+ # :types => [:shar, :recu, :apps]
35
+ # :count => 5
36
+ #
37
+ # @return [Mash] Mash hash of updates
38
+ def network_updates(options={})
39
+ path = "#{person_path(options)}/network/updates"
40
+ make_query(path, options, false)
41
+ end
42
+
43
+ private
44
+
45
+ def person_path(options)
46
+ path = "/people/"
47
+ if id = options.delete(:id)
48
+ path += "id=#{id}"
49
+ elsif url = options.delete(:url)
50
+ path += "url=#{CGI.escape(url)}"
51
+ else
52
+ path += '~'
53
+ end
54
+ end
55
+
56
+ #
57
+ # create a valid path to make a restful request
58
+ # @param path [String] current path
59
+ # @param options [Hash] set of options
60
+ # @param use_fields |boolean| does request need fields?
61
+ #
62
+ # @return [Mash] hash object with results
63
+ def make_query(path, options, use_fields)
64
+
65
+ fields = options.delete(:fields) || EzLinkedin.default_profile_fields if use_fields
66
+ if fields
67
+ path += ":(#{fields.join(',')})"
68
+ elsif path.end_with? "network/updates"
69
+ path += network_options(options).to_s # if getting updates, add relevant options to the path
70
+ elsif count = options.delete(:count)
71
+ path += "?count=#{count}"
72
+ end
73
+
74
+ Mash.from_json(get(path, options))
75
+ end
76
+
77
+ # handle the options passed in pertaining to network updates
78
+ def network_options(options)
79
+ path = "?"
80
+ options_path = nil
81
+
82
+ if types = options.delete(:types)
83
+ types = types.map { |type| "type=#{type.to_s.upcase}" }
84
+ options_path = types.join('&')
85
+ end
86
+
87
+ if count = options.delete(:count)
88
+ string = "count=#{count}"
89
+ options_path = add_to_path(string, options_path)
90
+ end
91
+
92
+ if scope = options.delete(:scope)
93
+ string = "scope=self"
94
+ options_path = add_to_path(string, options_path)
95
+ end
96
+
97
+ if options_path.nil?
98
+ ""
99
+ else
100
+ "#{path}#{options_path}"
101
+ end
102
+ end
103
+
104
+ # helper for previous method
105
+ def add_to_path(option, options_path)
106
+ if options_path.nil?
107
+ options_path = option
108
+ else
109
+ options_path += "&#{option}"
110
+ end
111
+ end
112
+ end
113
+
114
+ end
115
+ end
@@ -0,0 +1,27 @@
1
+ module EzLinkedin
2
+ module Api
3
+
4
+ module UpdateMethods
5
+
6
+ #
7
+ # post a share to Linkedin
8
+ # @param share [Hash] a hash containing at least the required
9
+ # attributes for a share.
10
+ # post_share({:comment => "I'm a comment",
11
+ # :content => { :title => "A title!",
12
+ # :description => "A description",
13
+ # :submitted_url => "http...",
14
+ # :submitted_image_url => "http..."
15
+ # }
16
+ # :visibility => { :code => "anyone"}
17
+ # })
18
+ #
19
+ # @return [HTTP::Response?] response of post call
20
+ def post_share(share)
21
+ path = "/people/~/shares"
22
+ defaults = { visibility: { code: 'anyone' } }
23
+ post(path, defaults.merge(share).to_json, "Content-Type" => "application/json")
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,6 @@
1
+ module EzLinkedin
2
+ module Api
3
+ autoload :QueryMethods, 'ezlinkedin/api/query_methods'
4
+ autoload :UpdateMethods, 'ezlinkedin/api/update_methods'
5
+ end
6
+ end
@@ -0,0 +1,31 @@
1
+ require "cgi"
2
+
3
+ module EzLinkedin
4
+ class Client
5
+ include Request
6
+ include Api::QueryMethods
7
+ include Api::UpdateMethods
8
+
9
+ attr_reader :consumer_key, :consumer_secret, :access_token, :client
10
+ attr_accessor :consumer_options
11
+
12
+ def initialize(c_key=EzLinkedin.token, c_secret=EzLinkedin.secret, options={})
13
+ @consumer_key = c_key
14
+ @consumer_secret = c_secret
15
+ @consumer_options = { site: 'https://api.linkedin.com',
16
+ request_token_path: '/uas/oauth/requestToken',
17
+ access_token_path: '/uas/oauth/accessToken',
18
+ authorize_path: '/uas/oauth/authorize' }
19
+ @consumer_options.merge(options)
20
+ @client = OAuth::Consumer.new(c_key, c_secret, @consumer_options)
21
+ end
22
+
23
+ # Create and outh access token to make api calls with
24
+ # param: token - the access token obtained from omniauth
25
+ # param: token_secret - the access token secret obtained from omniauth
26
+ def authorize(token, token_secret)
27
+ @access_token = OAuth::AccessToken.new(@client, token, token_secret)
28
+ end
29
+
30
+ end
31
+ end
@@ -0,0 +1,19 @@
1
+ module EzLinkedin
2
+ module Errors
3
+ class LinkedInError < StandardError
4
+ attr_reader :data
5
+ def initialize(data)
6
+ @data = data
7
+ super
8
+ end
9
+ end
10
+
11
+ class UnauthorizedError < LinkedInError; end
12
+ class GeneralError < LinkedInError; end
13
+ class AccessDeniedError < LinkedInError; end
14
+
15
+ class UnavailableError < StandardError; end
16
+ class InformLinkedInError < StandardError; end
17
+ class NotFoundError < StandardError; end
18
+ end
19
+ end
@@ -0,0 +1,68 @@
1
+ require 'hashie'
2
+ require 'multi_json'
3
+
4
+ module EzLinkedin
5
+ class Mash < ::Hashie::Mash
6
+
7
+ # a simple helper to convert a json string to a Mash
8
+ def self.from_json(json_string)
9
+ result_hash = ::MultiJson.decode(json_string)
10
+ new(result_hash)
11
+ end
12
+
13
+ # returns a Date if we have year, month and day, and no conflicting key
14
+ def to_date
15
+ if !self.has_key?('to_date') && contains_date_fields?
16
+ Date.civil(self.year, self.month, self.day)
17
+ else
18
+ super
19
+ end
20
+ end
21
+
22
+ def timestamp
23
+ value = self['timestamp']
24
+ if value.kind_of? Integer
25
+ value = value / 1000 if value > 9999999999
26
+ Time.at(value)
27
+ else
28
+ value
29
+ end
30
+ end
31
+
32
+ protected
33
+
34
+ def contains_date_fields?
35
+ self.year? && self.month? && self.day?
36
+ end
37
+
38
+ # overload the convert_key mash method so that the LinkedIn
39
+ # keys are made a little more ruby-ish
40
+ def convert_key(key)
41
+ case key.to_s
42
+ when '_key'
43
+ 'id'
44
+ when '_total'
45
+ 'total'
46
+ when 'values'
47
+ 'all'
48
+ when 'numResults'
49
+ 'total_results'
50
+ else
51
+ underscore(key)
52
+ end
53
+ end
54
+
55
+ # borrowed from ActiveSupport
56
+ # no need require an entire lib when we only need one method
57
+ def underscore(camel_cased_word)
58
+ word = camel_cased_word.to_s.dup
59
+ word.gsub!(/::/, '/')
60
+ word.gsub!(/([A-Z]+)([A-Z][a-z])/,'\1_\2')
61
+ word.gsub!(/([a-z\d])([A-Z])/,'\1_\2')
62
+ word.tr!("-", "_")
63
+ word.downcase!
64
+ word
65
+ end
66
+
67
+ end
68
+ end
@@ -0,0 +1,50 @@
1
+ module EzLinkedin
2
+
3
+ module Request
4
+ DEFAULT_HEADERS = {
5
+ 'x-li-format' => 'json'
6
+ }
7
+
8
+ API_PATH = "https://api.linkedin.com/v1"
9
+
10
+ protected
11
+
12
+ def get(path, options={})
13
+ response = access_token.get("#{API_PATH}#{path}", DEFAULT_HEADERS.merge(options))
14
+ raise_errors(response)
15
+ response.body
16
+ end
17
+
18
+ def post(path, body='', options={})
19
+ response = access_token.post("#{API_PATH}#{path}", body, DEFAULT_HEADERS.merge(options))
20
+ raise_errors(response)
21
+ response
22
+ end
23
+
24
+ private
25
+
26
+ def raise_errors(response)
27
+ # Even if the json answer contains the HTTP status code, LinkedIn also sets this code
28
+ # in the HTTP answer (thankfully).
29
+ case response.code.to_i
30
+ when 401
31
+ data = Mash.from_json(response.body)
32
+ raise EzLinkedin::Errors::UnauthorizedError.new(data), "(#{data.status}): #{data.message}"
33
+ when 400
34
+ data = Mash.from_json(response.body)
35
+ raise EzLinkedin::Errors::GeneralError.new(data), "(#{data.status}): #{data.message}"
36
+ when 403
37
+ data = Mash.from_json(response.body)
38
+ raise EzLinkedin::Errors::AccessDeniedError.new(data), "(#{data.status}): #{data.message}"
39
+ when 404
40
+ raise EzLinkedin::Errors::NotFoundError, "(#{response.code}): #{response.message}"
41
+ when 500
42
+ raise EzLinkedin::Errors::InformLinkedInError, "LinkedIn had an internal error. Please let them know in the forum. (#{response.code}): #{response.message}"
43
+ when 502..503
44
+ raise EzLinkedin::Errors::UnavailableError, "(#{response.code}): #{response.message}"
45
+ end
46
+ end
47
+
48
+ end
49
+
50
+ end
@@ -0,0 +1,3 @@
1
+ module Ezlinkedin
2
+ VERSION = "0.0.1"
3
+ end
data/lib/ezlinkedin.rb ADDED
@@ -0,0 +1,27 @@
1
+ require "ezlinkedin/version"
2
+ require 'ezlinkedin/request'
3
+ require 'ezlinkedin/api'
4
+ require 'ezlinkedin/mash'
5
+ require 'ezlinkedin/client'
6
+ require 'ezlinkedin/errors'
7
+ require 'oauth'
8
+
9
+ module EzLinkedin
10
+ class << self
11
+ attr_accessor :token, :secret, :default_profile_fields
12
+
13
+ # EzLinkedin.configure do |config|
14
+ # config.token = 'consumer_token'
15
+ # config.secret = 'consumer_secret'
16
+ # config.default_profile_fields = ['education', 'positions']
17
+ # end
18
+ #
19
+ # elsewhere
20
+ #
21
+ # client = EzLinkedin::Client.new
22
+ def configure
23
+ yield self
24
+ true
25
+ end
26
+ end
27
+ end
data/spec/api_spec.rb ADDED
@@ -0,0 +1,156 @@
1
+ require 'spec_helper'
2
+
3
+ describe EzLinkedin::Api do
4
+ before do
5
+ EzLinkedin.default_profile_fields = nil
6
+ client.stub(:consumer).and_return(consumer)
7
+ client.authorize('atoken', 'asecret')
8
+ end
9
+
10
+ let(:client){EzLinkedin::Client.new('token', 'secret')}
11
+ let(:consumer){OAuth::Consumer.new('token', 'secret', {:site => 'https://api.linkedin.com'})}
12
+
13
+ it "should be able to view the account profile" do
14
+ stub_request(:get, "https://api.linkedin.com/v1/people/~").to_return(:body => "{}")
15
+ client.profile.should be_an_instance_of(EzLinkedin::Mash)
16
+ end
17
+
18
+ it "should be able to view public profiles" do
19
+ stub_request(:get, "https://api.linkedin.com/v1/people/id=123").to_return(:body => "{}")
20
+ client.profile(:id => 123).should be_an_instance_of(EzLinkedin::Mash)
21
+ end
22
+
23
+ it "should be able to view connections" do
24
+ stub_request(:get, "https://api.linkedin.com/v1/people/~/connections").to_return(:body => "{}")
25
+ client.connections.should be_an_instance_of(EzLinkedin::Mash)
26
+ end
27
+
28
+ it "should be able to view network_updates" do
29
+ stub_request(:get, "https://api.linkedin.com/v1/people/~/network/updates").to_return(:body => "{}")
30
+ client.network_updates.should be_an_instance_of(EzLinkedin::Mash)
31
+ end
32
+
33
+ it "should be able to view network_updates with options" do
34
+ stub_request(:get, "https://api.linkedin.com/v1/people/~/network/updates?type=SHAR&count=5&scope=self").to_return(:body => "{}")
35
+ client.network_updates(types: [:shar], count: 5, scope: 'self').should be_an_instance_of(EzLinkedin::Mash)
36
+ end
37
+
38
+ # it "should be able to view network_update's comments" do
39
+ # stub_request(:get, "https://api.linkedin.com/v1/people/~/network/updates/key=network_update_key/update-comments").to_return(:body => "{}")
40
+ # client.share_comments("network_update_key").should be_an_instance_of(EzLinkedin::Mash)
41
+ # end
42
+
43
+ # it "should be able to view network_update's likes" do
44
+ # stub_request(:get, "https://api.linkedin.com/v1/people/~/network/updates/key=network_update_key/likes").to_return(:body => "{}")
45
+ # client.share_likes("network_update_key").should be_an_instance_of(EzLinkedin::Mash)
46
+ # end
47
+ #
48
+ # it "should be able to search with a keyword if given a String" do
49
+ # stub_request(:get, "https://api.linkedin.com/v1/people-search?keywords=business").to_return(:body => "{}")
50
+ # client.search("business").should be_an_instance_of(EzLinkedin::Mash)
51
+ # end
52
+ #
53
+ # it "should be able to search with an option" do
54
+ # stub_request(:get, "https://api.linkedin.com/v1/people-search?first-name=Javan").to_return(:body => "{}")
55
+ # client.search(:first_name => "Javan").should be_an_instance_of(EzLinkedin::Mash)
56
+ # end
57
+ #
58
+ # it "should be able to search with an option and fetch specific fields" do
59
+ # stub_request(:get, "https://api.linkedin.com/v1/people-search:(num-results,total)?first-name=Javan").to_return(
60
+ # :body => "{}")
61
+ # client.search(:first_name => "Javan", :fields => ["num_results", "total"]).should be_an_instance_of(EzLinkedin::Mash)
62
+ # end
63
+ #
64
+ it "should be able to post a share" do
65
+ stub_request(:post, "https://api.linkedin.com/v1/people/~/shares").to_return(:body => "", :status => 201)
66
+ response = client.post_share({:comment => "Testing, 1, 2, 3"})
67
+ response.body.should == nil
68
+ response.code.should == "201"
69
+ end
70
+ #
71
+ # it "should be able to comment on network update" do
72
+ # stub_request(:post, "https://api.linkedin.com/v1/people/~/network/updates/key=SOMEKEY/update-comments").to_return(
73
+ # :body => "", :status => 201)
74
+ # response = client.update_comment('SOMEKEY', "Testing, 1, 2, 3")
75
+ # response.body.should == nil
76
+ # response.code.should == "201"
77
+ # end
78
+ #
79
+ # it "should be able to send a message" do
80
+ # stub_request(:post, "https://api.linkedin.com/v1/people/~/mailbox").to_return(:body => "", :status => 201)
81
+ # response = client.send_message("subject", "body", ["recip1", "recip2"])
82
+ # response.body.should == nil
83
+ # response.code.should == "201"
84
+ # end
85
+ #
86
+ # it "should be able to like a network update" do
87
+ # stub_request(:put, "https://api.linkedin.com/v1/people/~/network/updates/key=SOMEKEY/is-liked").
88
+ # with(:body => "true").to_return(:body => "", :status => 201)
89
+ # response = client.like_share('SOMEKEY')
90
+ # response.body.should == nil
91
+ # response.code.should == "201"
92
+ # end
93
+ #
94
+ # it "should be able to unlike a network update" do
95
+ # stub_request(:put, "https://api.linkedin.com/v1/people/~/network/updates/key=SOMEKEY/is-liked").
96
+ # with(:body => "false").to_return(:body => "", :status => 201)
97
+ # response = client.unlike_share('SOMEKEY')
98
+ # response.body.should == nil
99
+ # response.code.should == "201"
100
+ # end
101
+ #
102
+ # context "Company API" do
103
+ # # use_vcr_cassette
104
+ #
105
+ # it "should be able to view a company profile" do
106
+ # stub_request(:get, "https://api.linkedin.com/v1/companies/id=1586").to_return(:body => "{}")
107
+ # client.company(:id => 1586).should be_an_instance_of(EzLinkedin::Mash)
108
+ # end
109
+ #
110
+ # it "should be able to view a company by universal name" do
111
+ # stub_request(:get, "https://api.linkedin.com/v1/companies/universal-name=acme").to_return(:body => "{}")
112
+ # client.company(:name => 'acme').should be_an_instance_of(EzLinkedin::Mash)
113
+ # end
114
+ #
115
+ # it "should be able to view a company by e-mail domain" do
116
+ # stub_request(:get, "https://api.linkedin.com/v1/companies/email-domain=acme.com").to_return(:body => "{}")
117
+ # client.company(:domain => 'acme.com').should be_an_instance_of(EzLinkedin::Mash)
118
+ # end
119
+ #
120
+ # it "should load correct company data" do
121
+ # client.company(:id => 1586).name.should == "Amazon"
122
+ #
123
+ # data = client.company(:id => 1586, :fields => %w{ id name industry locations:(address:(city state country-code) is-headquarters) employee-count-range })
124
+ # data.id.should == 1586
125
+ # data.name.should == "Amazon"
126
+ # data.employee_count_range.name.should == "10001+"
127
+ # data.industry.should == "Internet"
128
+ # data.locations.all[0].address.city.should == "Seattle"
129
+ # data.locations.all[0].is_headquarters.should == true
130
+ # end
131
+ # end
132
+
133
+ # context "Group API" do
134
+ #
135
+ # it "should be able to list group memberships for a profile" do
136
+ # stub_request(:get, "https://api.linkedin.com/v1/people/~/group-memberships").to_return(:body => "{}")
137
+ # client.group_memberships.should be_an_instance_of(EzLinkedin::Mash)
138
+ # end
139
+ #
140
+ # it "should be able to join a group" do
141
+ # stub_request(:put, "https://api.linkedin.com/v1/people/~/group-memberships/123").to_return(:body => "", :status => 201)
142
+ #
143
+ # response = client.join_group(123)
144
+ # response.body.should == nil
145
+ # response.code.should == "201"
146
+ # end
147
+ #
148
+ # end
149
+
150
+ context "Errors" do
151
+ it "should raise AccessDeniedError when EzLinkedin returns 403 status code" do
152
+ stub_request(:get, "https://api.linkedin.com/v1/people/~").to_return(:body => "{}", :status => 403)
153
+ expect{ client.profile }.to raise_error(EzLinkedin::Errors::AccessDeniedError)
154
+ end
155
+ end
156
+ end
@@ -0,0 +1,20 @@
1
+ require 'spec_helper'
2
+ require 'ezlinkedin'
3
+
4
+ describe EzLinkedin::Client do
5
+ let(:client) { EzLinkedin::Client.new('api_key', 'secret_key') }
6
+
7
+ it "client initializes" do
8
+ client.nil?.should_not be_true
9
+ client.consumer_key.should eql('api_key')
10
+ client.consumer_secret.should eql('secret_key')
11
+ client.client.should be_a_kind_of OAuth::Consumer
12
+ end
13
+
14
+ it 'creates an access token' do
15
+ client.authorize('token', 'token_secret')
16
+ access_token = client.access_token
17
+ access_token.should be_a_kind_of OAuth::AccessToken
18
+ end
19
+
20
+ end
@@ -0,0 +1,37 @@
1
+ require 'spec_helper'
2
+ require 'ezlinkedin'
3
+
4
+ describe EzLinkedin do
5
+ before(:each) do
6
+ EzLinkedin.token = nil
7
+ EzLinkedin.secret = nil
8
+ EzLinkedin.default_profile_fields = nil
9
+ end
10
+
11
+ it "should be able to set the consumer token and consumer secret" do
12
+ EzLinkedin.token = 'consumer_token'
13
+ EzLinkedin.secret = 'consumer_secret'
14
+
15
+ EzLinkedin.token.should == 'consumer_token'
16
+ EzLinkedin.secret.should == 'consumer_secret'
17
+ end
18
+
19
+ it "should be able to set the default profile fields" do
20
+ EzLinkedin.default_profile_fields = ['education', 'positions']
21
+
22
+ EzLinkedin.default_profile_fields.should == ['education', 'positions']
23
+ end
24
+
25
+ it "should be able to set the consumer token and consumer secret via a configure block" do
26
+ EzLinkedin.configure do |config|
27
+ config.token = 'consumer_token'
28
+ config.secret = 'consumer_secret'
29
+ config.default_profile_fields = ['education', 'positions']
30
+ end
31
+
32
+ EzLinkedin.token.should == 'consumer_token'
33
+ EzLinkedin.secret.should == 'consumer_secret'
34
+ EzLinkedin.default_profile_fields.should == ['education', 'positions']
35
+ end
36
+
37
+ end
data/spec/mash_spec.rb ADDED
@@ -0,0 +1,85 @@
1
+ require 'spec_helper'
2
+
3
+ describe EzLinkedin::Mash do
4
+
5
+ describe ".from_json" do
6
+ it "should convert a json string to a Mash" do
7
+ json_string = "{\"name\":\"Akonwi Ngoh\"}"
8
+ mash = EzLinkedin::Mash.from_json(json_string)
9
+
10
+ mash.should have_key('name')
11
+ mash.name.should == 'Akonwi Ngoh'
12
+ end
13
+ end
14
+
15
+ describe "#convert_keys" do
16
+ let(:mash) do
17
+ EzLinkedin::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 = EzLinkedin::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 = EzLinkedin::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 = EzLinkedin::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
+ EzLinkedin::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,16 @@
1
+ require 'webmock/rspec'
2
+ require 'ezlinkedin'
3
+ require 'ezlinkedin/errors'
4
+
5
+ # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
6
+ RSpec.configure do |config|
7
+ config.treat_symbols_as_metadata_keys_with_true_values = true
8
+ config.run_all_when_everything_filtered = true
9
+ config.filter_run :focus
10
+
11
+ # Run specs in random order to surface order dependencies. If you find an
12
+ # order dependency and want to debug it, you can fix the order by providing
13
+ # the seed, which is printed after each run.
14
+ # --seed 1234
15
+ config.order = 'random'
16
+ end
metadata ADDED
@@ -0,0 +1,225 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ezlinkedin
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - akonwi
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-05-20 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: oauth
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: 0.4.7
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: 0.4.7
27
+ - !ruby/object:Gem::Dependency
28
+ name: hashie
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ~>
32
+ - !ruby/object:Gem::Version
33
+ version: 2.0.5
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ~>
39
+ - !ruby/object:Gem::Version
40
+ version: 2.0.5
41
+ - !ruby/object:Gem::Dependency
42
+ name: json
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ~>
46
+ - !ruby/object:Gem::Version
47
+ version: 1.8.0
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: 1.8.0
55
+ - !ruby/object:Gem::Dependency
56
+ name: multi_json
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: 1.7.3
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ~>
67
+ - !ruby/object:Gem::Version
68
+ version: 1.7.3
69
+ - !ruby/object:Gem::Dependency
70
+ name: bundler
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ~>
74
+ - !ruby/object:Gem::Version
75
+ version: '1.3'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ~>
81
+ - !ruby/object:Gem::Version
82
+ version: '1.3'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rake
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - '>='
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - '>='
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: rspec
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ~>
102
+ - !ruby/object:Gem::Version
103
+ version: '2.6'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ~>
109
+ - !ruby/object:Gem::Version
110
+ version: '2.6'
111
+ - !ruby/object:Gem::Dependency
112
+ name: guard
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - '>='
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - '>='
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: guard-rspec
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - '>='
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - '>='
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
139
+ - !ruby/object:Gem::Dependency
140
+ name: libnotify
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - '>='
144
+ - !ruby/object:Gem::Version
145
+ version: '0'
146
+ type: :development
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - '>='
151
+ - !ruby/object:Gem::Version
152
+ version: '0'
153
+ - !ruby/object:Gem::Dependency
154
+ name: webmock
155
+ requirement: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - ~>
158
+ - !ruby/object:Gem::Version
159
+ version: 1.11.0
160
+ type: :development
161
+ prerelease: false
162
+ version_requirements: !ruby/object:Gem::Requirement
163
+ requirements:
164
+ - - ~>
165
+ - !ruby/object:Gem::Version
166
+ version: 1.11.0
167
+ description: A simple way to make calls on Linkedin's API
168
+ email:
169
+ - akonwi@gmail.com
170
+ executables: []
171
+ extensions: []
172
+ extra_rdoc_files: []
173
+ files:
174
+ - .gitignore
175
+ - .rspec
176
+ - Gemfile
177
+ - Guardfile
178
+ - LICENSE.txt
179
+ - README.md
180
+ - Rakefile
181
+ - ezlinkedin.gemspec
182
+ - lib/ezlinkedin.rb
183
+ - lib/ezlinkedin/api.rb
184
+ - lib/ezlinkedin/api/query_methods.rb
185
+ - lib/ezlinkedin/api/update_methods.rb
186
+ - lib/ezlinkedin/client.rb
187
+ - lib/ezlinkedin/errors.rb
188
+ - lib/ezlinkedin/mash.rb
189
+ - lib/ezlinkedin/request.rb
190
+ - lib/ezlinkedin/version.rb
191
+ - spec/api_spec.rb
192
+ - spec/client_spec.rb
193
+ - spec/ezlinkedin_spec.rb
194
+ - spec/mash_spec.rb
195
+ - spec/spec_helper.rb
196
+ homepage: ''
197
+ licenses:
198
+ - MIT
199
+ metadata: {}
200
+ post_install_message:
201
+ rdoc_options: []
202
+ require_paths:
203
+ - lib
204
+ required_ruby_version: !ruby/object:Gem::Requirement
205
+ requirements:
206
+ - - '>='
207
+ - !ruby/object:Gem::Version
208
+ version: '0'
209
+ required_rubygems_version: !ruby/object:Gem::Requirement
210
+ requirements:
211
+ - - '>='
212
+ - !ruby/object:Gem::Version
213
+ version: '0'
214
+ requirements: []
215
+ rubyforge_project:
216
+ rubygems_version: 2.0.3
217
+ signing_key:
218
+ specification_version: 4
219
+ summary: It's a simple way to access Linkedin and it's coupled well will omniauth
220
+ test_files:
221
+ - spec/api_spec.rb
222
+ - spec/client_spec.rb
223
+ - spec/ezlinkedin_spec.rb
224
+ - spec/mash_spec.rb
225
+ - spec/spec_helper.rb