john_stamos 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. data/README.md +95 -79
  2. data/john_stamos.gemspec +3 -2
  3. data/lib/john_stamos/client.rb +32 -17
  4. data/lib/john_stamos/pin_search.rb +4 -3
  5. data/lib/john_stamos/pinner.rb +1 -1
  6. data/lib/john_stamos/version.rb +1 -1
  7. data/lib/john_stamos.rb +5 -2
  8. data/spec/lib/john_stamos/client_spec.rb +55 -66
  9. data/spec/lib/john_stamos/pin_search_spec.rb +9 -9
  10. data/spec/support/vcr_cassettes/JohnStamos_Client/_make_request/returns_a_string_representation_of_the_response_body.yml +59 -0
  11. data/spec/support/vcr_cassettes/JohnStamos_Client/_page_content/returns_a_Nokogiri_HTML_Document_object.yml +59 -0
  12. data/spec/support/vcr_cassettes/JohnStamos_Client/_search_pins/returns_the_correct_number_of_pins.yml +6448 -980
  13. data/spec/support/vcr_cassettes/JohnStamos_Pin/scraped_data/_pinner/returns_a_Pinner_object.yml +801 -289
  14. data/spec/support/vcr_cassettes/JohnStamos_Pin/scraped_data/_pinner/shows_my_fake_account_as_the_owning_Pinner.yml +802 -289
  15. data/spec/support/vcr_cassettes/JohnStamos_Pin/scraped_data/belongs_to_the_correct_board.yml +801 -289
  16. data/spec/support/vcr_cassettes/JohnStamos_Pin/scraped_data/has_the_correct_description.yml +801 -289
  17. data/spec/support/vcr_cassettes/JohnStamos_Pin/scraped_data/has_the_correct_image.yml +801 -289
  18. data/spec/support/vcr_cassettes/JohnStamos_Pin/scraped_data/has_the_correct_like_count.yml +1329 -287
  19. data/spec/support/vcr_cassettes/JohnStamos_Pin/scraped_data/has_the_correct_repin_count.yml +801 -289
  20. data/spec/support/vcr_cassettes/JohnStamos_Pin/scraped_data/has_the_correct_source_url.yml +801 -290
  21. data/spec/support/vcr_cassettes/JohnStamos_Pin/scraped_data/is_not_a_video.yml +801 -289
  22. data/spec/support/vcr_cassettes/JohnStamos_PinSearch/_execute_/when_using_a_search_term_that_yields_thousands_of_pins/with_a_limit_higher_than_the_default/collects_the_correct_number_of_pin_ids.yml +16392 -2609
  23. data/spec/support/vcr_cassettes/JohnStamos_PinSearch/_execute_/when_using_a_search_term_that_yields_thousands_of_pins/with_a_limit_lower_than_the_default/collects_the_correct_number_of_pin_ids.yml +10844 -1157
  24. data/spec/support/vcr_cassettes/JohnStamos_PinSearch/_execute_/when_using_a_search_term_that_yields_thousands_of_pins/with_a_limit_lower_than_the_default/never_calls_subsequent_retrieval_.yml +10844 -1157
  25. data/spec/support/vcr_cassettes/JohnStamos_PinSearch/_execute_/when_using_a_search_term_that_yields_thousands_of_pins/with_no_limit_specified/limits_the_pin_ids_collected_to_50.yml +10844 -1655
  26. data/spec/support/vcr_cassettes/JohnStamos_PinSearch/_execute_/when_using_a_search_term_that_yields_thousands_of_pins/with_no_limit_specified/limits_to_50_the_default.yml +10844 -1655
  27. data/spec/support/vcr_cassettes/JohnStamos_PinSearch/_first_retrieval_/with_results_found/sets_next_bookmark.yml +5128 -993
  28. data/spec/support/vcr_cassettes/JohnStamos_PinSearch/_first_retrieval_/with_results_found/sets_next_bookmark_with_a_hash_for_the_next_25_results.yml +5170 -0
  29. data/spec/support/vcr_cassettes/JohnStamos_PinSearch/_first_retrieval_/with_results_found/sets_next_bookmark_with_a_hash_for_the_next_batch_of_results.yml +5170 -0
  30. data/spec/support/vcr_cassettes/JohnStamos_PinSearch/_first_retrieval_/with_results_found/should_set_pin_ids.yml +5128 -993
  31. data/spec/support/vcr_cassettes/JohnStamos_PinSearch/_first_retrieval_/without_any_results_found/has_a_nil_next_bookmark.yml +834 -211
  32. data/spec/support/vcr_cassettes/JohnStamos_PinSearch/_first_retrieval_/without_any_results_found/leaves_the_pin_ids_array_empty.yml +834 -212
  33. data/spec/support/vcr_cassettes/JohnStamos_PinSearch/_subsequent_retrieval/with_results_found/sets_next_bookmark_with_a_hash_for_the_next_25_results.yml +9053 -0
  34. data/spec/support/vcr_cassettes/JohnStamos_PinSearch/_subsequent_retrieval/with_results_found/sets_next_bookmark_with_a_hash_for_the_next_batch_of_results.yml +9053 -0
  35. data/spec/support/vcr_cassettes/JohnStamos_PinSearch/_subsequent_retrieval/with_results_found/sets_the_next_bookmark.yml +8972 -1691
  36. data/spec/support/vcr_cassettes/JohnStamos_PinSearch/_subsequent_retrieval/with_results_found/should_append_the_new_pin_ids.yml +8972 -1691
  37. data/spec/support/vcr_cassettes/JohnStamos_Pinner/_about/returns_the_correct_about_text.yml +639 -247
  38. data/spec/support/vcr_cassettes/JohnStamos_Pinner/_avatar/returns_the_correct_avatar_URL.yml +639 -246
  39. data/spec/support/vcr_cassettes/JohnStamos_Pinner/_board_count/returns_the_correct_number_of_boards.yml +639 -246
  40. data/spec/support/vcr_cassettes/JohnStamos_Pinner/_follower_count/returns_a_follower_count_of_0.yml +639 -246
  41. data/spec/support/vcr_cassettes/JohnStamos_Pinner/_location/returns_the_correct_location.yml +639 -247
  42. data/spec/support/vcr_cassettes/JohnStamos_Pinner/_pin_count/returns_the_correct_number_of_pins.yml +639 -246
  43. data/spec/support/vcr_cassettes/JohnStamos_Pinner/_website_url/returns_the_correct_website_url.yml +639 -246
  44. data/spec/support/vcr_cassettes/JohnStamos_Pinner/name_related_attributes/returns_the_correct_first_name.yml +1039 -244
  45. data/spec/support/vcr_cassettes/JohnStamos_Pinner/name_related_attributes/returns_the_correct_full_name.yml +639 -246
  46. data/spec/support/vcr_cassettes/JohnStamos_Pinner/name_related_attributes/returns_the_correct_last_name.yml +639 -246
  47. metadata +163 -146
  48. checksums.yaml +0 -7
  49. data/spec/support/vcr_cassettes/JohnStamos_Client/_page_content/returns_a_Mechanize_Page.yml +0 -221
  50. data/spec/support/vcr_cassettes/JohnStamos_PinSearch/_first_retrieval_/with_results_found/sets_next_bookmark_with_a_hash_for_the_next_50_results.yml +0 -1035
  51. data/spec/support/vcr_cassettes/JohnStamos_PinSearch/_subsequent_retrieval/with_results_found/sets_next_bookmark_with_a_hash_for_the_next_50_results.yml +0 -1772
data/README.md CHANGED
@@ -1,26 +1,35 @@
1
- # JohnStamos
1
+ # JohnStamos
2
2
 
3
3
  The greasiest Pinterest client. JohnStamos exposes an interface you can use to query Pinterest for data about individual Pins, Pinners and Pin searches. Have mercy.
4
4
 
5
5
  [![Build Status](https://travis-ci.org/mariozig/john_stamos.png?branch=master)](https://travis-ci.org/mariozig/john_stamos)
6
+ [![Code Climate](https://codeclimate.com/github/mariozig/john_stamos.png)](https://codeclimate.com/github/mariozig/john_stamos)
6
7
 
7
8
  ## Installation
8
9
 
9
10
  Add this line to your application's Gemfile:
10
11
 
11
- gem 'john_stamos'
12
+ ```
13
+ gem 'john_stamos'
14
+ ```
12
15
 
13
16
  And then execute:
14
17
 
15
- $ bundle
18
+ ```
19
+ $ bundle
20
+ ```
16
21
 
17
22
  Or install it yourself as:
18
23
 
19
- $ gem install john_stamos
24
+ ```
25
+ $ gem install john_stamos
26
+ ```
20
27
 
21
28
  Or finally, if none of that stuff applies to you, do what it takes to install the gem and add this to your script:
22
29
 
23
- require 'john_stamos'
30
+ ```ruby
31
+ require 'john_stamos'
32
+ ```
24
33
 
25
34
  ## Usage
26
35
 
@@ -28,95 +37,102 @@ Or finally, if none of that stuff applies to you, do what it takes to install th
28
37
 
29
38
  Here's a typical use-case: You want to search Pinterest for some pins. Once you have those pins, you want to access information about each individual pin as well as information about the person who pinned it.
30
39
 
31
- client = JohnStamos::Client.new
32
-
33
- # Search for some sweet Pins of "pallet gardens"
34
- pins = client.search_pins("pallet gardens", limit: 10)
35
- # Returns an Array of Pin objects
36
-
37
- # The first Pin will be fun to investigate.
38
- first_pallet_garden_pin = pallet_search.first
39
-
40
- # Print some info about the first Pin description
41
- puts first_pallet_garden_pin.description
42
- # => "A cool pallet garden"
43
-
44
- # the full sized image
45
- puts first_pallet_garden_pin.image
46
- # => "http://media-cache-ak0.pinimg.com/originals....whatever.jpg"
47
-
48
- # Pinterest's ID for this Pin
49
- puts first_pallet_garden_pin.id
50
- # => "123456789"
51
-
52
- # URL to the Pin
53
- puts first_pallet_garden_pin.url
54
- # => "http://pinterest.com/pin/123456789"
55
-
56
- # We can even get at the user who Pinned this Pin
57
- first_pallet_garden_pin.pinner
58
-
59
- # Print the Pinner's full name
60
- puts first_pallet_garden_pin.pinner.full_name
61
- # => "Little Bobby Tables"
40
+ ```ruby
41
+ client = JohnStamos::Client.new
42
+
43
+ # Search for some sweet Pins of "pallet gardens"
44
+ pins = client.search_pins("pallet gardens", limit: 10)
45
+ # Returns an Array of Pin objects
46
+
47
+ # The first Pin will be fun to investigate.
48
+ first_pallet_garden_pin = pallet_search.first
49
+
50
+ # Print some info about the first Pin description
51
+ puts first_pallet_garden_pin.description
52
+ # => "A cool pallet garden"
53
+
54
+ # the full sized image
55
+ puts first_pallet_garden_pin.image
56
+ # => "http://media-cache-ak0.pinimg.com/originals....whatever.jpg"
57
+
58
+ # Pinterest's ID for this Pin
59
+ puts first_pallet_garden_pin.id
60
+ # => "123456789"
61
+
62
+ # URL to the Pin
63
+ puts first_pallet_garden_pin.url
64
+ # => "http://pinterest.com/pin/123456789"
65
+
66
+ # We can even get at the user who Pinned this Pin
67
+ first_pallet_garden_pin.pinner
68
+
69
+ # Print the Pinner's full name
70
+ puts first_pallet_garden_pin.pinner.full_name
71
+ # => "Little Bobby Tables"
72
+ ```
62
73
 
63
74
  ### Using the Client
64
75
 
65
- The Client is the single entry point into all things JohnStamos.
76
+ The Client is the single entry point into all things JohnStamos.
66
77
 
67
- # Create a new Client
68
- client = JohnStamos::Client.new
69
-
70
- # The Client also supports using a proxy
71
- client_with_proxy = JohnStamos::Client.new(proxy: 'http://127.1.1.1:4747')
72
-
73
- # Note: If you're hosted on Heroku, you will want to use a proxy.
78
+ ```ruby
79
+ # Create a new Client
80
+ client = JohnStamos::Client.new
74
81
 
82
+ # The Client also supports using a proxy
83
+ client_with_proxy = JohnStamos::Client.new(proxy: 'http://127.1.1.1:4747')
84
+
85
+ # Note: If you're hosted on Heroku, you will want to use a proxy.
86
+ ```
75
87
 
76
88
  ### Accessing Individual Pin Data
77
89
 
78
90
  There are times you might want to access an individual Pin's information. All you need is the ID assigned to the Pin by Pinterest to get going.
79
91
 
80
- client = JohnStamos::Client.new
81
-
82
- # Get a magnificent Pin using it's ID
83
- perfect_strangers_pin = client.pin(161848180328631541)
84
-
85
- puts perfect_strangers_pin.description
86
- # => "Balki Bartokomous and Cousin Larry!!! PERFECT STRANGERS...loved that show!"
87
-
88
- puts perfect_strangers_pin.image
89
- # => "http://media-cache-ec0.pinimg.com/originals/4b/10/d3/4b10d3bd1c172c52934eb2d79ff0031f.jpg"
90
-
91
- # If you didn't look at that image above, please do it before reading further
92
-
93
- puts perfect_strangers_pin.url
94
- # => "http://pinterest.com/pin/161848180328631541/"
95
-
96
- puts perfect_strangers_pin.repin_count
97
- # => 1
92
+ ```ruby
93
+ client = JohnStamos::Client.new
94
+
95
+ # Get a magnificent Pin using it's ID
96
+ perfect_strangers_pin = client.pin(161848180328631541)
97
+
98
+ puts perfect_strangers_pin.description
99
+ # => "Balki Bartokomous and Cousin Larry!!! PERFECT STRANGERS...loved that show!"
100
+
101
+ puts perfect_strangers_pin.image
102
+ # => "http://media-cache-ec0.pinimg.com/originals/4b/10/d3/4b10d3bd1c172c52934eb2d79ff0031f.jpg"
103
+
104
+ # If you didn't look at that image above, please do it before reading further
105
+
106
+ puts perfect_strangers_pin.url
107
+ # => "http://pinterest.com/pin/161848180328631541/"
108
+
109
+ puts perfect_strangers_pin.repin_count
110
+ # => 1
111
+ ```
98
112
 
99
113
  ### Accessing Pinner Data
100
114
 
101
115
  You can also query Pinterest for information about specific Pinners. Just pass in the Pinner's user name and you will be good to go.
102
116
 
103
- client = JohnStamos::Client.new
104
-
105
- # Get Michelle Obama's account
106
- michelle_obama = client.pinner("michelleobama")
107
-
108
- # Print some of the Pinner's information
109
- puts michelle_obama.last_name
110
- # => "Obama"
111
-
112
- puts michelle_obama.first_name
113
- # => "Michelle"
114
-
115
- puts michelle_obama.pin_count
116
- # => "81"
117
-
118
- puts michelle_obama.website_url
119
- # => "http://www.barackobama.com"
117
+ ```ruby
118
+ client = JohnStamos::Client.new
119
+
120
+ # Get Michelle Obama's account
121
+ michelle_obama = client.pinner("michelleobama")
122
+
123
+ # Print some of the Pinner's information
124
+ puts michelle_obama.last_name
125
+ # => "Obama"
126
+
127
+ puts michelle_obama.first_name
128
+ # => "Michelle"
129
+
130
+ puts michelle_obama.pin_count
131
+ # => "81"
132
+
133
+ puts michelle_obama.website_url
134
+ # => "http://www.barackobama.com"
135
+ ```
120
136
 
121
137
  ## Contributing
122
138
 
data/john_stamos.gemspec CHANGED
@@ -25,8 +25,9 @@ Gem::Specification.new do |gem|
25
25
  gem.add_development_dependency "vcr"
26
26
  gem.add_development_dependency "guard-rspec"
27
27
 
28
- gem.add_dependency "mechanize"
29
- gem.add_dependency "rest-client"
28
+ gem.add_dependency "nokogiri"
29
+ gem.add_dependency "faraday"
30
+ gem.add_dependency "typhoeus"
30
31
  gem.add_dependency "json"
31
32
  gem.add_dependency "launchy"
32
33
  end
@@ -1,3 +1,5 @@
1
+ require 'logger'
2
+
1
3
  class JohnStamos::Client
2
4
  attr_accessor :proxy
3
5
 
@@ -23,35 +25,48 @@ class JohnStamos::Client
23
25
  end
24
26
 
25
27
  def page_content(url)
26
- begin
27
- page = mechanize_agent.get(url)
28
- rescue Mechanize::ResponseReadError => e
29
- $stderr.puts "#{e.class}: #{e.message}"
30
- $stderr.puts "An error occured; attempting to force_parse"
31
- page = e.force_parse
32
- end
28
+ response = make_request(url)
33
29
 
34
- page
30
+ Nokogiri::HTML(response)
35
31
  end
36
32
 
37
33
  def json_content(url, params)
38
- RestClient.proxy = @proxy
39
- response = RestClient.get(url, params: params, accept: :json, "X-Requested-With" => "XMLHttpRequest")
34
+ response = make_json_request(url, params)
40
35
 
41
36
  JSON.parse(response)
42
37
  end
43
38
 
44
39
  private
45
- def mechanize_agent
46
- agent = Mechanize.new
47
- agent.user_agent_alias = 'Mac Safari'
40
+ def make_request(url, params={}, accept_json=false)
41
+ request_headers = build_request_headers(accept_json)
48
42
 
49
- if @proxy
50
- proxy_uri = URI.parse(@proxy)
51
- agent.set_proxy(proxy_uri.hostname, proxy_uri.port)
43
+ response = pinterest_connection.get do |req|
44
+ req.url url, params
45
+ req.headers = request_headers
52
46
  end
53
47
 
54
- agent
48
+ response.body
49
+ end
50
+
51
+ def make_json_request(url, params={})
52
+ make_request(url, params, true)
53
+ end
54
+
55
+ def build_request_headers(accept_json=false)
56
+ headers = {}
57
+
58
+ if accept_json
59
+ headers['Accept'] = 'application/json'
60
+ headers['X-Requested-With'] = 'XMLHttpRequest'
61
+ end
62
+ headers['User-Agent'] = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.95 Safari/537.36'
63
+
64
+ headers
65
+ end
66
+
67
+ def pinterest_connection
68
+ pinterest_url = 'http://pinterest.com'
69
+ @pinterest_connection ||= @proxy.nil? ? Faraday.new(url: pinterest_url) : Faraday.new(url: pinterest_url, proxy: @proxy)
55
70
  end
56
71
 
57
72
  end
@@ -25,11 +25,11 @@ class JohnStamos::PinSearch
25
25
 
26
26
  def first_retrieval_url
27
27
  raise JohnStamos::MissingSearchText if @search_text.nil?
28
- "http://pinterest.com/search/pins/?q=#{URI::encode(@search_text)}"
28
+ "/search/pins/?q=#{URI::encode(@search_text)}"
29
29
  end
30
30
 
31
31
  def subsequent_retrieval_url
32
- 'http://pinterest.com/resource/SearchResource/get/'
32
+ '/resource/SearchResource/get/'
33
33
  end
34
34
 
35
35
  def first_retrieval!
@@ -134,7 +134,8 @@ class JohnStamos::PinSearch
134
134
 
135
135
  url_params = {
136
136
  source_url: "/search/pins/?q=#{URI::encode(search_text)}",
137
- "_" => 1375127302668,
137
+ # Pass in the current time in miliseconds (like pinterest does) to prevent caching
138
+ "_" => (Time.now.to_f * 1000.0).to_i,
138
139
  data: data_json.to_json
139
140
  }
140
141
  url_params
@@ -54,7 +54,7 @@ class JohnStamos::Pinner
54
54
 
55
55
  private
56
56
  def page
57
- @page ||= @client.page_content(url)
57
+ @page ||= @client.page_content("/#{@username}/")
58
58
  end
59
59
 
60
60
  def embedded_pinner_json
@@ -1,3 +1,3 @@
1
1
  module JohnStamos
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.2"
3
3
  end
data/lib/john_stamos.rb CHANGED
@@ -1,6 +1,7 @@
1
- require 'mechanize'
1
+ require 'faraday'
2
+ require 'typhoeus/adapters/faraday'
3
+ require 'nokogiri'
2
4
  require 'json'
3
- require 'rest_client'
4
5
  require 'launchy'
5
6
 
6
7
  require 'john_stamos/version'
@@ -13,6 +14,8 @@ module JohnStamos
13
14
  class MissingSearchText < Exception; end
14
15
  class MissingNextBookmark < Exception; end
15
16
 
17
+ Faraday.default_adapter = :typhoeus
18
+
16
19
  private
17
20
  def self.uncle_jesse
18
21
  Launchy.open('http://www.youtube.com/watch?v=bLqAqIj8Rdc')
@@ -2,7 +2,7 @@ require 'spec_helper'
2
2
 
3
3
  describe JohnStamos::Client, :vcr do
4
4
  subject(:client) { JohnStamos::Client.new }
5
- let(:pinterest_url) { 'https://pinterest.com' }
5
+ let(:pinterest_url) { 'http://pinterest.com' }
6
6
 
7
7
  describe '#search_pins' do
8
8
  it 'responds to #search_pins' do
@@ -49,99 +49,88 @@ describe JohnStamos::Client, :vcr do
49
49
  end
50
50
  end
51
51
 
52
- describe '#json_content' do
53
- it 'responds to #json_content' do
54
- expect(client).to respond_to(:json_content)
52
+ describe '#page_content' do
53
+ it 'responds to #page_content' do
54
+ expect(client).to respond_to(:page_content)
55
55
  end
56
56
 
57
- it 'returns a Hash' do
58
- RestClient.stub(:get).and_return('{"json":"json"}')
59
-
60
- expect(client.json_content('url', 'params')).to be_a(Hash)
57
+ it 'returns a Nokogiri::HTML::Document object' do
58
+ expect(client.page_content(pinterest_url)).to be_a(Nokogiri::HTML::Document)
61
59
  end
62
60
  end
63
61
 
64
- describe '#mechanize_agent' do
65
- let(:agent) { client.send(:mechanize_agent) }
66
-
67
- context 'when using a proxy' do
68
- before(:each) do
69
- client.proxy = 'http://proxy.com:4747'
70
- end
71
-
72
- it 'sets the correct hostname' do
73
- expect(agent.proxy_addr).to eq('proxy.com')
74
- end
62
+ describe '#json_content' do
63
+ let(:fake_json) { '{ "key":"value" }' }
75
64
 
76
- it 'sets the correct port' do
77
- expect(agent.proxy_port).to eq(4747)
78
- end
65
+ it 'responds to #json_content' do
66
+ expect(client).to respond_to(:json_content)
79
67
  end
80
68
 
81
- context 'when not using a proxy' do
82
- before(:each) do
83
- client.proxy = nil
84
- end
85
-
86
- it 'does not set a hostname' do
87
- expect(agent.proxy_addr).to be_nil
88
- end
89
-
90
- it 'does not set a port' do
91
- expect(agent.proxy_port).to be_nil
92
- end
69
+ it 'returns a Hash representation of the JSON' do
70
+ client.stub(:make_request).and_return(fake_json)
71
+ expect(client.json_content(nil, nil)).to be_a(Hash)
93
72
  end
94
73
  end
95
74
 
96
- describe '#page_content' do
97
- it 'responds to #page_content' do
98
- expect(client).to respond_to(:page_content)
75
+ describe '#make_request' do
76
+ it 'returns a string representation of the response body' do
77
+ response = client.send(:make_request, pinterest_url, {})
78
+ expect(response).to be_a(String)
99
79
  end
80
+ end
81
+
82
+ describe '#make_json_request' do
83
+ it 'calls #make_request with the correct params' do
84
+ client.stub(:make_request).and_return(nil)
85
+ expect(client).to receive(:make_request).with('a', 'b', true)
100
86
 
101
- it 'returns a Mechanize::Page' do
102
- expect(client.page_content(pinterest_url)).to be_a(Mechanize::Page)
87
+ client.send(:make_json_request, 'a', 'b')
103
88
  end
104
89
  end
105
90
 
106
- describe '#json_content' do
107
- let(:fake_json) { '{"json":"json"}' }
108
-
109
- it 'responds to #json_content' do
110
- expect(client).to respond_to(:json_content)
91
+ describe '#pinterest_connection' do
92
+ context 'when using a proxy' do
93
+ it 'creates a new Faraday proxied instance' do
94
+ client.proxy = 'http://fakeproxy.com:1234'
95
+ expect(Faraday).to receive(:new).with({ url: pinterest_url, proxy: client.proxy })
96
+ client.send(:pinterest_connection)
97
+ end
111
98
  end
112
99
 
113
100
  context 'when not using a proxy' do
114
- before(:each) do
115
- allow(RestClient).to receive(:get).and_return(fake_json)
101
+ it 'creates a new Faraday instance' do
102
+ client.proxy = nil
103
+ expect(Faraday).to receive(:new).with({ url: pinterest_url })
104
+ client.send(:pinterest_connection)
116
105
  end
106
+ end
107
+ end
117
108
 
118
- let(:json_content) { client.json_content('url', 'params') }
119
-
120
- it 'returns a Hash representation of the JSON' do
121
- expect(json_content).to be_a(Hash)
122
- end
109
+ describe '#build_request_headers' do
110
+ it 'has a valid User-Agent' do
111
+ headers = client.send(:build_request_headers)
112
+ expect(headers['User-Agent']).to eq('Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.95 Safari/537.36')
113
+ end
123
114
 
124
- it 'does not set RestClient proxy properties' do
125
- json_content
126
- expect(RestClient.proxy).to be_nil
115
+ context 'non-JSON requests' do
116
+ it 'do not contain JSON request related headers' do
117
+ headers = client.send(:build_request_headers)
118
+ expect(headers).not_to include('Accept', 'X-Requested-With')
127
119
  end
128
120
  end
129
121
 
130
- context 'when using a proxy' do
131
- let(:proxy) { 'http://proxy.com:31337' }
132
- let(:proxy_client) { JohnStamos::Client.new({ proxy: proxy }) }
133
-
134
- before(:each) do
135
- allow(proxy_client).to receive(:proxy).and_return(proxy)
136
- allow(RestClient).to receive(:get).and_return(fake_json)
122
+ context 'JSON requests' do
123
+ let(:json_headers) do
124
+ headers = {}
125
+ headers['Accept'] = 'application/json'
126
+ headers['X-Requested-With'] = 'XMLHttpRequest'
127
+ headers
137
128
  end
138
129
 
139
- it 'sets RestClient proxy properties' do
140
- proxy_client.json_content('url', 'params')
141
- expect(RestClient.proxy).to eq(proxy_client.proxy)
130
+ it 'contain JSON request related headers' do
131
+ headers = client.send(:build_request_headers, true)
132
+ expect(headers).to include(json_headers)
142
133
  end
143
134
  end
144
-
145
-
146
135
  end
147
136
  end
@@ -89,7 +89,7 @@ describe JohnStamos::PinSearch, :vcr do
89
89
 
90
90
  it 'returns the correct URL with the search text URL encoded' do
91
91
  scraper.search_text = search_text
92
- expect(scraper.first_retrieval_url).to eq('http://pinterest.com/search/pins/?q=coffee%20roasting')
92
+ expect(scraper.first_retrieval_url).to eq('/search/pins/?q=coffee%20roasting')
93
93
  end
94
94
  end
95
95
 
@@ -102,15 +102,15 @@ describe JohnStamos::PinSearch, :vcr do
102
102
  expect { scraper.first_retrieval! }.to change{ scraper.next_bookmark }.from(nil)
103
103
  end
104
104
 
105
- it 'sets next_bookmark with a hash for the next 50 results' do
105
+ it 'sets next_bookmark with a hash for the next batch of results' do
106
106
  scraper.first_retrieval!
107
107
  decrypted_hash = Base64.strict_decode64(scraper.next_bookmark)
108
108
  next_page_results_start_position = decrypted_hash.split('|')[0]
109
- next_page_results_start_position.should eq("oo50")
109
+ next_page_results_start_position.should eq("oo25")
110
110
  end
111
111
 
112
112
  it 'should set pin_ids' do
113
- expect { scraper.first_retrieval! }.to change{ scraper.pin_ids.length }.from(0).to(50)
113
+ expect { scraper.first_retrieval! }.to change{ scraper.pin_ids.length }.from(0).to(25)
114
114
  end
115
115
  end
116
116
 
@@ -133,7 +133,7 @@ describe JohnStamos::PinSearch, :vcr do
133
133
 
134
134
  describe '#subsequent_retrieval_url' do
135
135
  it 'returns the correct "resource" url' do
136
- expect(scraper.subsequent_retrieval_url).to eq('http://pinterest.com/resource/SearchResource/get/')
136
+ expect(scraper.subsequent_retrieval_url).to eq('/resource/SearchResource/get/')
137
137
  end
138
138
  end
139
139
 
@@ -163,18 +163,18 @@ describe JohnStamos::PinSearch, :vcr do
163
163
  expect { scraper.subsequent_retrieval! }.to change{ scraper.next_bookmark }
164
164
  end
165
165
 
166
- it 'sets next_bookmark with a hash for the next 50 results' do
166
+ it 'sets next_bookmark with a hash for the next batch of results' do
167
167
  scraper.subsequent_retrieval!
168
168
  decrypted_hash = Base64.strict_decode64(scraper.next_bookmark)
169
169
  next_page_results_start_position = decrypted_hash.split('|')[0]
170
- expect(next_page_results_start_position).to eq("oo100")
170
+ expect(next_page_results_start_position).to eq("oo50")
171
171
  end
172
172
 
173
173
  it 'should append the new pin_ids' do
174
- # The expected count can change based on Pinterest. Sometimes they give 99, sometimes 100.
174
+ # The expected count can change based on Pinterest. Sometimes they give 1 less than expected.
175
175
  # When you update the VCR cassettes it may cause this test to fail... please update it.
176
176
  scraper.subsequent_retrieval!
177
- expect(scraper.pin_ids.length).to eq(100)
177
+ expect(scraper.pin_ids.length).to eq(50)
178
178
  end
179
179
  end
180
180
  end
@@ -0,0 +1,59 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: get
5
+ uri: http://pinterest.com/
6
+ body:
7
+ encoding: US-ASCII
8
+ string: ''
9
+ headers:
10
+ User-Agent:
11
+ - Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_4) AppleWebKit/537.36 (KHTML,
12
+ like Gecko) Chrome/28.0.1500.95 Safari/537.36
13
+ response:
14
+ status:
15
+ code: 302
16
+ message: FOUND
17
+ headers:
18
+ Accept-Ranges:
19
+ - bytes
20
+ Age:
21
+ - '0'
22
+ Cache-Control:
23
+ - no-cache
24
+ Content-Type:
25
+ - text/html; charset=utf-8
26
+ Date:
27
+ - Thu, 22 Aug 2013 23:38:02 GMT
28
+ Location:
29
+ - https://pinterest.com/
30
+ Pinterest-Breed:
31
+ - CORGI
32
+ Pinterest-Generated-By:
33
+ - ngapp-1b3b34b2
34
+ Pinterest-Version:
35
+ - 5bdef68
36
+ Server:
37
+ - nginx
38
+ Set-Cookie:
39
+ - _pinterest_sess="eJzzNvE19PDKjbKoSql0NTLwCApxTPZPystO8yi3tY8vycxNtfUN8TX2q/Ks8HOJNPFNt7VVK04tLs5MsfXM8jSODMk28HPxyvY1iqzwCwk0jQyJNPXNSq/ydwnKisoNrfDL8gLSYTmeQH0AYikjhQ==";
40
+ Domain=.pinterest.com; expires=Sun, 17-Aug-2014 23:38:02 GMT; Max-Age=31103999;
41
+ Path=/
42
+ - csrftoken=3pu9GXdpS9N8ilNUApaOtopW0nV0tOOn; Domain=.pinterest.com; expires=Thu,
43
+ 21-Aug-2014 23:38:02 GMT; Max-Age=31449600; Path=/
44
+ Vary:
45
+ - Cookie
46
+ Via:
47
+ - 1.1 varnish
48
+ X-Varnish:
49
+ - '2111788339'
50
+ Content-Length:
51
+ - '0'
52
+ Connection:
53
+ - keep-alive
54
+ body:
55
+ encoding: UTF-8
56
+ string: ''
57
+ http_version:
58
+ recorded_at: Thu, 22 Aug 2013 23:38:02 GMT
59
+ recorded_with: VCR 2.5.0