yibs_commission_junction 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.document +5 -0
- data/.gitignore +5 -0
- data/LICENSE +24 -0
- data/README.rdoc +49 -0
- data/Rakefile +57 -0
- data/VERSION +1 -0
- data/lib/commission_junction.rb +145 -0
- data/test/commission_junction_test.rb +302 -0
- data/test/test_helper.rb +6 -0
- data/test/test_response.xml +49 -0
- metadata +84 -0
data/.document
ADDED
data/LICENSE
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
Copyright (c) 2010, Albert Vernon
|
|
2
|
+
All rights reserved.
|
|
3
|
+
|
|
4
|
+
Redistribution and use in source and binary forms, with or without modification,
|
|
5
|
+
are permitted provided that the following conditions are met:
|
|
6
|
+
* Redistributions of source code must retain the above copyright notice,
|
|
7
|
+
this list of conditions and the following disclaimer.
|
|
8
|
+
* Redistributions in binary form must reproduce the above copyright notice,
|
|
9
|
+
this list of conditions and the following disclaimer in the documentation
|
|
10
|
+
and/or other materials provided with the distribution.
|
|
11
|
+
* The names of its contributors may not be used to endorse or promote
|
|
12
|
+
products derived from this software without specific prior written
|
|
13
|
+
permission.
|
|
14
|
+
|
|
15
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
16
|
+
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
17
|
+
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
18
|
+
DISCLAIMED. IN NO EVENT SHALL ALBERT VERNON BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
19
|
+
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
20
|
+
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
|
21
|
+
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
|
22
|
+
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
|
23
|
+
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
|
24
|
+
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
data/README.rdoc
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
= commission_junction
|
|
2
|
+
|
|
3
|
+
Ruby wrapper for the Commission Junction product catalog search service API v2 (REST)
|
|
4
|
+
|
|
5
|
+
== Installation
|
|
6
|
+
|
|
7
|
+
sudo gem install commission_junction
|
|
8
|
+
|
|
9
|
+
== Example
|
|
10
|
+
|
|
11
|
+
require 'rubygems'
|
|
12
|
+
require 'commission_junction'
|
|
13
|
+
|
|
14
|
+
# See https://api.cj.com/sign_up.cj
|
|
15
|
+
DEVELOPER_KEY = '????????'
|
|
16
|
+
|
|
17
|
+
# See cj.com > Account > Web site Settings > PID
|
|
18
|
+
WEBSITE_ID = '????????'
|
|
19
|
+
|
|
20
|
+
cj = CommissionJunction.new(DEVELOPER_KEY, WEBSITE_ID)
|
|
21
|
+
|
|
22
|
+
# See http://help.cj.com/en/web_services/product_catalog_search_service_rest.htm
|
|
23
|
+
# for the list of request and response parameters.
|
|
24
|
+
cj.product_search('keywords' => '+blue +jeans',
|
|
25
|
+
'advertiser-ids' => 'joined',
|
|
26
|
+
'serviceable-area' => 'us',
|
|
27
|
+
'currency' => 'usd',
|
|
28
|
+
'records-per-page' => '5').each do |product|
|
|
29
|
+
puts product.name
|
|
30
|
+
puts product.price
|
|
31
|
+
puts product.image_url
|
|
32
|
+
puts ''
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
== Dependencies
|
|
36
|
+
|
|
37
|
+
* httparty
|
|
38
|
+
|
|
39
|
+
== Note on Patches/Pull Requests
|
|
40
|
+
|
|
41
|
+
* Fork the project.
|
|
42
|
+
* Make your feature addition or bug fix.
|
|
43
|
+
* Add tests for it. This is important so I don't break it in a future version unintentionally.
|
|
44
|
+
* Commit, do not mess with Rakefile, VERSION, or history (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull).
|
|
45
|
+
* Send me a pull request. Bonus points for topic branches.
|
|
46
|
+
|
|
47
|
+
== Copyright
|
|
48
|
+
|
|
49
|
+
Copyright (c) 2010 Albert Vernon. See LICENSE for details.
|
data/Rakefile
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
require 'rubygems'
|
|
2
|
+
require 'rake'
|
|
3
|
+
|
|
4
|
+
begin
|
|
5
|
+
require 'jeweler'
|
|
6
|
+
Jeweler::Tasks.new do |gem|
|
|
7
|
+
gem.name = "commission_junction"
|
|
8
|
+
gem.summary = %Q{Commission Junction product catalog search (REST)}
|
|
9
|
+
gem.description = %Q{Ruby wrapper for the Commission Junction product catalog search service API v2 (REST)}
|
|
10
|
+
gem.email = "aev@vernon.nu"
|
|
11
|
+
gem.homepage = "http://github.com/aevernon/commission_junction"
|
|
12
|
+
gem.authors = ["Albert Vernon"]
|
|
13
|
+
gem.add_dependency('httparty')
|
|
14
|
+
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
|
15
|
+
end
|
|
16
|
+
Jeweler::GemcutterTasks.new
|
|
17
|
+
rescue LoadError
|
|
18
|
+
puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
require 'rake/testtask'
|
|
22
|
+
Rake::TestTask.new(:test) do |test|
|
|
23
|
+
test.libs << 'lib' << 'test'
|
|
24
|
+
test.pattern = 'test/**/*_test.rb'
|
|
25
|
+
test.verbose = true
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
begin
|
|
29
|
+
require 'rcov/rcovtask'
|
|
30
|
+
Rcov::RcovTask.new do |test|
|
|
31
|
+
test.libs << 'test'
|
|
32
|
+
test.pattern = 'test/**/*_test.rb'
|
|
33
|
+
test.verbose = true
|
|
34
|
+
end
|
|
35
|
+
rescue LoadError
|
|
36
|
+
task :rcov do
|
|
37
|
+
abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
task :test => :check_dependencies
|
|
42
|
+
|
|
43
|
+
task :default => :test
|
|
44
|
+
|
|
45
|
+
require 'rake/rdoctask'
|
|
46
|
+
Rake::RDocTask.new do |rdoc|
|
|
47
|
+
if File.exist?('VERSION')
|
|
48
|
+
version = File.read('VERSION')
|
|
49
|
+
else
|
|
50
|
+
version = ""
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
rdoc.rdoc_dir = 'rdoc'
|
|
54
|
+
rdoc.title = "commission_junction #{version}"
|
|
55
|
+
rdoc.rdoc_files.include('README*')
|
|
56
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
|
57
|
+
end
|
data/VERSION
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
1.2.0
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
require 'httparty'
|
|
2
|
+
|
|
3
|
+
# Interact with CJ web services.
|
|
4
|
+
class CommissionJunction
|
|
5
|
+
include HTTParty
|
|
6
|
+
format(:xml)
|
|
7
|
+
#debug_output $stderr
|
|
8
|
+
|
|
9
|
+
attr_reader :total_matched,
|
|
10
|
+
:records_returned,
|
|
11
|
+
:page_number,
|
|
12
|
+
:cj_objects
|
|
13
|
+
|
|
14
|
+
WEB_SERVICE_URIS =
|
|
15
|
+
{
|
|
16
|
+
:product_search => 'https://product-search.api.cj.com/v2/product-search',
|
|
17
|
+
:advertiser_lookup => 'https://advertiser-lookup.api.cj.com/v3/advertiser-lookup'
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
def initialize(developer_key, website_id, timeout = 10)
|
|
21
|
+
raise ArgumentError, "developer_key must be a String; got #{developer_key.class} instead" unless developer_key.is_a?(String)
|
|
22
|
+
raise ArgumentError, "You must supply your developer key.\nSee https://api.cj.com/sign_up.cj" unless developer_key.length > 0
|
|
23
|
+
|
|
24
|
+
website_id = website_id.to_s
|
|
25
|
+
raise ArgumentError, "You must supply your website ID.\nSee cj.com > Account > Web site Settings > PID" unless website_id.length > 0
|
|
26
|
+
|
|
27
|
+
raise ArgumentError, "timeout must be a Fixnum; got #{timeout.class} instead" unless timeout.is_a?(Fixnum)
|
|
28
|
+
raise ArgumentError, "timeout must be > 0; got #{timeout} instead" unless timeout > 0
|
|
29
|
+
@timeout = timeout
|
|
30
|
+
|
|
31
|
+
self_class = self.class
|
|
32
|
+
self_class.headers('authorization' => developer_key)
|
|
33
|
+
# This causes the Invalid Key error. We don't need this anymore
|
|
34
|
+
#self_class.default_params('website-id' => website_id)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def advertiser_lookup(params = { 'advertiser-ids' => 'joined', 'records-per-page' => '5' })
|
|
38
|
+
raise ArgumentError, "params must be a Hash; got #{params.class} instead" unless params.is_a?(Hash)
|
|
39
|
+
|
|
40
|
+
unless params.size > 0
|
|
41
|
+
raise ArgumentError, "You must provide at least one request parameter, for example, \"keywords\".\nSee http://help.cj.com/en/web_services/advertiser_lookup_service_rest.htm"
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
@cj_objects = []
|
|
45
|
+
begin
|
|
46
|
+
#response = self.class.get("https://advertiser-lookup.api.cj.com/v3/advertiser-lookup?advertiser-ids=#{advertiser_ids}")
|
|
47
|
+
response = self.class.get(WEB_SERVICE_URIS[:advertiser_lookup], :query => params)
|
|
48
|
+
cj_api = response['cj_api']
|
|
49
|
+
error_message = cj_api['error_message']
|
|
50
|
+
|
|
51
|
+
raise ArgumentError, error_message if error_message
|
|
52
|
+
|
|
53
|
+
advertisers = cj_api['advertisers']
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
@total_matched = advertisers['total_matched'].to_i
|
|
57
|
+
@records_returned = advertisers['records_returned'].to_i
|
|
58
|
+
@page_number = advertisers['page_number'].to_i
|
|
59
|
+
|
|
60
|
+
advertiser = advertisers['advertiser']
|
|
61
|
+
advertiser = [advertiser] if advertiser.is_a?(Hash) # If we got exactly one result, put it in an array.
|
|
62
|
+
advertiser.each { |item| @cj_objects << Advertiser.new(item) } if advertiser
|
|
63
|
+
rescue Timeout::Error
|
|
64
|
+
@total_matched = @records_returned = @page_number = 0
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
@cj_objects
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def product_search(params)
|
|
71
|
+
raise ArgumentError, "params must be a Hash; got #{params.class} instead" unless params.is_a?(Hash)
|
|
72
|
+
|
|
73
|
+
unless params.size > 0
|
|
74
|
+
raise ArgumentError, "You must provide at least one request parameter, for example, \"keywords\".\nSee http://help.cj.com/en/web_services/product_catalog_search_service_rest.htm"
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
@cj_objects = []
|
|
78
|
+
|
|
79
|
+
begin
|
|
80
|
+
if caller_method_name == 'test_product_search_with_keywords_non_live'
|
|
81
|
+
response = Crack::XML.parse(File.read('test/test_response.xml'))
|
|
82
|
+
else
|
|
83
|
+
response = self.class.get(WEB_SERVICE_URIS[:product_search], :query => params, :timeout => @timeout)
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
cj_api = response['cj_api']
|
|
87
|
+
error_message = cj_api['error_message']
|
|
88
|
+
|
|
89
|
+
raise ArgumentError, error_message if error_message
|
|
90
|
+
|
|
91
|
+
products = cj_api['products']
|
|
92
|
+
|
|
93
|
+
@total_matched = products['total_matched'].to_i
|
|
94
|
+
@records_returned = products['records_returned'].to_i
|
|
95
|
+
@page_number = products['page_number'].to_i
|
|
96
|
+
|
|
97
|
+
product = products['product']
|
|
98
|
+
product = [product] if product.is_a?(Hash) # If we got exactly one result, put it in an array.
|
|
99
|
+
product.each { |item| @cj_objects << Product.new(item) } if product
|
|
100
|
+
rescue Timeout::Error
|
|
101
|
+
@total_matched = @records_returned = @page_number = 0
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
@cj_objects
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
class CjObject
|
|
108
|
+
def initialize(params)
|
|
109
|
+
raise ArgumentError, "params must be a Hash; got #{params.class} instead" unless params.is_a?(Hash)
|
|
110
|
+
raise ArgumentError, 'Expecting at least one parameter' unless params.size > 0
|
|
111
|
+
|
|
112
|
+
# Create instance variables and attribute readers on the fly.
|
|
113
|
+
# Credit: http://listlibrary.net/ruby-talk/2004/03/00sGI1cD
|
|
114
|
+
params.each do |key, val|
|
|
115
|
+
raise ArgumentError, "key must be a String; got #{key.class} instead" unless key.is_a?(String)
|
|
116
|
+
instance_variable_set("@#{key}".intern, val)
|
|
117
|
+
instance_eval %Q{ class << self ; attr_reader #{key.intern.inspect} ; end }
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
# Represent products from a catalog search.
|
|
123
|
+
class Product < CjObject
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
class Advertiser < CjObject
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
private
|
|
130
|
+
|
|
131
|
+
# Credit: http://snippets.dzone.com/posts/show/2787
|
|
132
|
+
def caller_method_name
|
|
133
|
+
parse_caller(caller(2).first).last
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
def parse_caller(at)
|
|
137
|
+
if /^(.+?):(\d+)(?::in `(.*)')?/ =~ at
|
|
138
|
+
last_match = Regexp.last_match
|
|
139
|
+
file = last_match[1]
|
|
140
|
+
line = last_match[2].to_i
|
|
141
|
+
method = last_match[3]
|
|
142
|
+
[file, line, method]
|
|
143
|
+
end
|
|
144
|
+
end
|
|
145
|
+
end
|
|
@@ -0,0 +1,302 @@
|
|
|
1
|
+
require 'test_helper'
|
|
2
|
+
|
|
3
|
+
class CommissionJunctionTest < Test::Unit::TestCase
|
|
4
|
+
def test_new_cj_with_no_params
|
|
5
|
+
assert_raise ArgumentError do
|
|
6
|
+
CommissionJunction.new
|
|
7
|
+
end
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def test_new_cj_with_one_param
|
|
11
|
+
assert_raise ArgumentError do
|
|
12
|
+
CommissionJunction.new('fake')
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def test_new_cj_with_nil_param
|
|
17
|
+
assert_raise ArgumentError do
|
|
18
|
+
CommissionJunction.new(nil, 'website_id')
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
assert_raise ArgumentError do
|
|
22
|
+
CommissionJunction.new('developer_key', nil)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
assert_raise ArgumentError do
|
|
26
|
+
CommissionJunction.new('developer_key', 'website_id', nil)
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def test_new_cj_with_empty_param
|
|
31
|
+
assert_raise ArgumentError do
|
|
32
|
+
CommissionJunction.new('', 'website_id')
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
assert_raise ArgumentError do
|
|
36
|
+
CommissionJunction.new('developer_key', '')
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def test_new_cj_with_non_string_param
|
|
41
|
+
assert_raise ArgumentError do
|
|
42
|
+
CommissionJunction.new(123456, 'website_id')
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
assert_nothing_raised ArgumentError do
|
|
46
|
+
CommissionJunction.new('developer_key', 123456)
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def test_new_cj_with_non_fixnum_timeout
|
|
51
|
+
assert_raise ArgumentError do
|
|
52
|
+
CommissionJunction.new('developer_key', 'website_id', '10')
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def test_new_cj_with_non_positive_timeout
|
|
57
|
+
assert_raise ArgumentError do
|
|
58
|
+
CommissionJunction.new('developer_key', 'website_id', 0)
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
assert_raise ArgumentError do
|
|
62
|
+
CommissionJunction.new('developer_key', 'website_id', -1)
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def test_new_cj_with_correct_types
|
|
67
|
+
assert_nothing_raised do
|
|
68
|
+
assert_instance_of(CommissionJunction, CommissionJunction.new('developer_key', 'website_id'))
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
assert_nothing_raised do
|
|
72
|
+
assert_instance_of(CommissionJunction, CommissionJunction.new('developer_key', 'website_id', 50))
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def test_new_product_with_no_params
|
|
77
|
+
assert_raise ArgumentError do
|
|
78
|
+
CommissionJunction::Product.new
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def test_new_product_with_nil_params
|
|
83
|
+
assert_raise ArgumentError do
|
|
84
|
+
CommissionJunction::Product.new(nil)
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def test_new_product_with_empty_params
|
|
89
|
+
assert_raise ArgumentError do
|
|
90
|
+
CommissionJunction::Product.new({})
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def test_new_product_with_non_hash_params
|
|
95
|
+
assert_raise ArgumentError do
|
|
96
|
+
CommissionJunction::Product.new([1, 2, 3])
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def test_new_product_with_hash_params_and_non_string_keys
|
|
101
|
+
assert_raise ArgumentError do
|
|
102
|
+
CommissionJunction::Product.new(:name => 'blue jeans', :price => '49.95')
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def test_new_product_with_hash_params_and_string_keys
|
|
107
|
+
assert_nothing_raised do
|
|
108
|
+
product = CommissionJunction::Product.new('name' => 'blue jeans', 'price' => '49.95')
|
|
109
|
+
assert_instance_of(CommissionJunction::Product, product)
|
|
110
|
+
assert_respond_to(product, :name)
|
|
111
|
+
assert_equal('blue jeans', product.name)
|
|
112
|
+
assert_respond_to(product, :price)
|
|
113
|
+
assert_equal('49.95', product.price)
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
def test_product_search_with_no_params
|
|
118
|
+
assert_raise ArgumentError do
|
|
119
|
+
CommissionJunction.new('developer_key', 'website_id').product_search
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
def test_product_search_with_nil_params
|
|
124
|
+
assert_raise ArgumentError do
|
|
125
|
+
CommissionJunction.new('developer_key', 'website_id').product_search(nil)
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
def test_product_search_with_empty_params
|
|
130
|
+
assert_raise ArgumentError do
|
|
131
|
+
CommissionJunction.new('developer_key', 'website_id').product_search({})
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
def test_product_search_with_non_hash_params
|
|
136
|
+
assert_raise ArgumentError do
|
|
137
|
+
CommissionJunction.new('developer_key', 'website_id').product_search([1, 2, 3])
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
def test_product_search_with_bad_key
|
|
142
|
+
cj = CommissionJunction.new('bad_key', 'website_id')
|
|
143
|
+
|
|
144
|
+
assert_raise ArgumentError do
|
|
145
|
+
cj.product_search('keywords' => '+some +product')
|
|
146
|
+
end
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
def test_product_search_with_keywords_non_live
|
|
150
|
+
cj = CommissionJunction.new('developer_key', 'website_id')
|
|
151
|
+
|
|
152
|
+
assert_nothing_raised do
|
|
153
|
+
cj.product_search('keywords' => '+blue +jeans', 'records-per-page' => '2')
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
check_search_results(cj)
|
|
157
|
+
|
|
158
|
+
assert_equal(10726, cj.total_matched)
|
|
159
|
+
assert_equal(2, cj.records_returned)
|
|
160
|
+
assert_equal(1, cj.page_number)
|
|
161
|
+
|
|
162
|
+
assert_equal('Rockstar Motocross Jeans Blue', cj.cj_objects.first.name)
|
|
163
|
+
assert_equal('Buy Rockstar Motocross Jeans Blue at BlueBee.com', cj.cj_objects.first.description)
|
|
164
|
+
assert_equal('http://www.bluebee.com/cImages/Website_0/type_236/RST01233_255266.jpg', cj.cj_objects.first.image_url.strip)
|
|
165
|
+
assert_equal('209.0', cj.cj_objects.first.price)
|
|
166
|
+
|
|
167
|
+
assert_equal('***James Jeans*** Twiggy Aged Blue', cj.cj_objects.last.name)
|
|
168
|
+
assert_equal('Buy ***James Jeans*** Twiggy Aged Blue at BlueBee.com', cj.cj_objects.last.description)
|
|
169
|
+
assert_equal('http://www.bluebee.com/cImages/Website_0/type_236/JME01383_263394.jpg', cj.cj_objects.last.image_url.strip)
|
|
170
|
+
assert_equal('163.0', cj.cj_objects.last.price)
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
# def test_product_search_with_keywords_live
|
|
174
|
+
# key_file = File.join(ENV['HOME'], '.commission_junction.yaml')
|
|
175
|
+
|
|
176
|
+
# unless File.exist?(key_file)
|
|
177
|
+
# warn "Warning: #{key_file} does not exist. Put your CJ developer key and website ID in there to enable live testing."
|
|
178
|
+
# else
|
|
179
|
+
# credentials = YAML.load(File.read(key_file))
|
|
180
|
+
# cj = CommissionJunction.new(credentials['developer_key'], credentials['website_id'])
|
|
181
|
+
|
|
182
|
+
# # Zero results
|
|
183
|
+
# assert_nothing_raised do
|
|
184
|
+
# cj.product_search('keywords' => 'no_matching_results')
|
|
185
|
+
# end
|
|
186
|
+
|
|
187
|
+
# check_search_results(cj)
|
|
188
|
+
|
|
189
|
+
# # One result
|
|
190
|
+
# assert_nothing_raised do
|
|
191
|
+
# cj.product_search('keywords' => '+blue +jeans', 'records-per-page' => '1')
|
|
192
|
+
# end
|
|
193
|
+
|
|
194
|
+
# check_search_results(cj)
|
|
195
|
+
|
|
196
|
+
# # Multiple results
|
|
197
|
+
# assert_nothing_raised do
|
|
198
|
+
# cj.product_search('keywords' => '+blue +jeans', 'records-per-page' => '2')
|
|
199
|
+
# end
|
|
200
|
+
|
|
201
|
+
# check_search_results(cj)
|
|
202
|
+
|
|
203
|
+
# # Short timeout
|
|
204
|
+
# cj = CommissionJunction.new(credentials['developer_key'], credentials['website_id'], 1)
|
|
205
|
+
|
|
206
|
+
# assert_nothing_raised do
|
|
207
|
+
# cj.product_search('keywords' => 'One Great Blue Jean~No Limits', 'records-per-page' => '1')
|
|
208
|
+
# end
|
|
209
|
+
|
|
210
|
+
# check_search_results(cj)
|
|
211
|
+
# end
|
|
212
|
+
# end
|
|
213
|
+
|
|
214
|
+
def check_search_results(results)
|
|
215
|
+
assert_instance_of(Fixnum, results.total_matched)
|
|
216
|
+
assert_instance_of(Fixnum, results.records_returned)
|
|
217
|
+
assert_instance_of(Fixnum, results.page_number)
|
|
218
|
+
assert_instance_of(Array, results.cj_objects)
|
|
219
|
+
|
|
220
|
+
results.cj_objects.each do |product|
|
|
221
|
+
assert_instance_of(CommissionJunction::Product, product)
|
|
222
|
+
assert_respond_to(product, :ad_id)
|
|
223
|
+
assert_respond_to(product, :advertiser_id)
|
|
224
|
+
assert_respond_to(product, :advertiser_name)
|
|
225
|
+
assert_respond_to(product, :buy_url)
|
|
226
|
+
assert_respond_to(product, :catalog_id)
|
|
227
|
+
assert_respond_to(product, :currency)
|
|
228
|
+
assert_respond_to(product, :description)
|
|
229
|
+
assert_respond_to(product, :image_url)
|
|
230
|
+
assert_respond_to(product, :in_stock)
|
|
231
|
+
assert_respond_to(product, :isbn)
|
|
232
|
+
assert_respond_to(product, :manufacturer_name)
|
|
233
|
+
assert_respond_to(product, :manufacturer_sku)
|
|
234
|
+
assert_respond_to(product, :name)
|
|
235
|
+
assert_respond_to(product, :price)
|
|
236
|
+
assert_respond_to(product, :retail_price)
|
|
237
|
+
assert_respond_to(product, :sale_price)
|
|
238
|
+
assert_respond_to(product, :sku)
|
|
239
|
+
assert_respond_to(product, :upc)
|
|
240
|
+
end
|
|
241
|
+
end
|
|
242
|
+
|
|
243
|
+
|
|
244
|
+
def test_advertiser_search_live
|
|
245
|
+
key_file = File.join(ENV['HOME'], '.commission_junction.yaml')
|
|
246
|
+
|
|
247
|
+
unless File.exist?(key_file)
|
|
248
|
+
warn "Warning: #{key_file} does not exist. Put your CJ developer key and website ID in there to enable live testing."
|
|
249
|
+
else
|
|
250
|
+
credentials = YAML.load(File.read(key_file))
|
|
251
|
+
cj = CommissionJunction.new(credentials['developer_key'], credentials['website_id'])
|
|
252
|
+
|
|
253
|
+
|
|
254
|
+
# One result
|
|
255
|
+
assert_nothing_raised do
|
|
256
|
+
result = cj.advertiser_lookup('advertiser-ids' => 'joined', 'page-number' => '1')
|
|
257
|
+
#The New York Pass
|
|
258
|
+
end
|
|
259
|
+
|
|
260
|
+
check_advertiser_lookup_results(cj)
|
|
261
|
+
|
|
262
|
+
# Multiple results
|
|
263
|
+
assert_nothing_raised do
|
|
264
|
+
cj.advertiser_lookup('keywords' => '+blue +jeans', 'records-per-page' => '2')
|
|
265
|
+
end
|
|
266
|
+
|
|
267
|
+
check_advertiser_lookup_results(cj)
|
|
268
|
+
|
|
269
|
+
# Short timeout
|
|
270
|
+
cj = CommissionJunction.new(credentials['developer_key'], credentials['website_id'], 1)
|
|
271
|
+
|
|
272
|
+
assert_nothing_raised do
|
|
273
|
+
cj.advertiser_lookup('keywords' => 'One Great Blue Jean~No Limits', 'records-per-page' => '1')
|
|
274
|
+
end
|
|
275
|
+
|
|
276
|
+
check_advertiser_lookup_results(cj)
|
|
277
|
+
end
|
|
278
|
+
end
|
|
279
|
+
|
|
280
|
+
def check_advertiser_lookup_results(results)
|
|
281
|
+
assert_instance_of(Fixnum, results.total_matched)
|
|
282
|
+
assert_instance_of(Fixnum, results.records_returned)
|
|
283
|
+
assert_instance_of(Fixnum, results.page_number)
|
|
284
|
+
assert_instance_of(Array, results.cj_objects)
|
|
285
|
+
|
|
286
|
+
results.cj_objects.each do |advertiser|
|
|
287
|
+
assert_instance_of(CommissionJunction::Advertiser, advertiser)
|
|
288
|
+
assert_respond_to(advertiser, :advertiser_id)
|
|
289
|
+
assert_respond_to(advertiser, :advertiser_name)
|
|
290
|
+
assert_respond_to(advertiser, :language)
|
|
291
|
+
assert_respond_to(advertiser, :link_types)
|
|
292
|
+
assert_respond_to(advertiser, :network_rank)
|
|
293
|
+
assert_respond_to(advertiser, :performance_incentives)
|
|
294
|
+
assert_respond_to(advertiser, :primary_category)
|
|
295
|
+
assert_respond_to(advertiser, :program_url)
|
|
296
|
+
assert_respond_to(advertiser, :relationship_status)
|
|
297
|
+
assert_respond_to(advertiser, :seven_day_epc)
|
|
298
|
+
assert_respond_to(advertiser, :three_month_epc)
|
|
299
|
+
end
|
|
300
|
+
end
|
|
301
|
+
|
|
302
|
+
end
|
data/test/test_helper.rb
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<cj-api>
|
|
3
|
+
<products total-matched="10726" records-returned="2" page-number="1">
|
|
4
|
+
<product>
|
|
5
|
+
<ad-id>10505159</ad-id>
|
|
6
|
+
<advertiser-id>2062769</advertiser-id>
|
|
7
|
+
<advertiser-name>Blue Bee</advertiser-name>
|
|
8
|
+
<buy-url>
|
|
9
|
+
http://www.jdoqocy.com/click-3893793-10505159?url=http%3A%2F%2Fwww.bluebee.com%2Fproduct_display.aspx%3Fp%3DRST01233%26l%3D00090119152200000000%26a%3Dcj&cjsku=RST01233
|
|
10
|
+
</buy-url>
|
|
11
|
+
<catalog-id>cjo:2059</catalog-id>
|
|
12
|
+
<currency>USD</currency>
|
|
13
|
+
<description>Buy Rockstar Motocross Jeans Blue at BlueBee.com</description>
|
|
14
|
+
<image-url> http://www.bluebee.com/cImages/Website_0/type_236/RST01233_255266.jpg</image-url>
|
|
15
|
+
<in-stock></in-stock>
|
|
16
|
+
<isbn></isbn>
|
|
17
|
+
<manufacturer-name>t</manufacturer-name>
|
|
18
|
+
<manufacturer-sku></manufacturer-sku>
|
|
19
|
+
<name>Rockstar Motocross Jeans Blue</name>
|
|
20
|
+
<price>209.0</price>
|
|
21
|
+
<retail-price>0.0</retail-price>
|
|
22
|
+
<sale-price>0.0</sale-price>
|
|
23
|
+
<sku>RST01233</sku>
|
|
24
|
+
<upc></upc>
|
|
25
|
+
</product>
|
|
26
|
+
<product>
|
|
27
|
+
<ad-id>10505159</ad-id>
|
|
28
|
+
<advertiser-id>2062769</advertiser-id>
|
|
29
|
+
<advertiser-name>Blue Bee</advertiser-name>
|
|
30
|
+
<buy-url>
|
|
31
|
+
http://www.tkqlhce.com/click-3893793-10505159?url=http%3A%2F%2Fwww.bluebee.com%2Fproduct_display.aspx%3Fp%3DJME01383%26l%3D00080119161400000000%26a%3Dcj&cjsku=JME01383
|
|
32
|
+
</buy-url>
|
|
33
|
+
<catalog-id>cjo:2059</catalog-id>
|
|
34
|
+
<currency>USD</currency>
|
|
35
|
+
<description>Buy ***James Jeans*** Twiggy Aged Blue at BlueBee.com</description>
|
|
36
|
+
<image-url> http://www.bluebee.com/cImages/Website_0/type_236/JME01383_263394.jpg</image-url>
|
|
37
|
+
<in-stock></in-stock>
|
|
38
|
+
<isbn></isbn>
|
|
39
|
+
<manufacturer-name>j</manufacturer-name>
|
|
40
|
+
<manufacturer-sku></manufacturer-sku>
|
|
41
|
+
<name>***James Jeans*** Twiggy Aged Blue</name>
|
|
42
|
+
<price>163.0</price>
|
|
43
|
+
<retail-price>0.0</retail-price>
|
|
44
|
+
<sale-price>0.0</sale-price>
|
|
45
|
+
<sku>JME01383</sku>
|
|
46
|
+
<upc></upc>
|
|
47
|
+
</product>
|
|
48
|
+
</products>
|
|
49
|
+
</cj-api>
|
metadata
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: yibs_commission_junction
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
prerelease: false
|
|
5
|
+
segments:
|
|
6
|
+
- 1
|
|
7
|
+
- 2
|
|
8
|
+
- 0
|
|
9
|
+
version: 1.2.0
|
|
10
|
+
platform: ruby
|
|
11
|
+
authors:
|
|
12
|
+
- Albert Vernon
|
|
13
|
+
autorequire:
|
|
14
|
+
bindir: bin
|
|
15
|
+
cert_chain: []
|
|
16
|
+
|
|
17
|
+
date: 2010-08-27 00:00:00 -07:00
|
|
18
|
+
default_executable:
|
|
19
|
+
dependencies:
|
|
20
|
+
- !ruby/object:Gem::Dependency
|
|
21
|
+
name: httparty
|
|
22
|
+
prerelease: false
|
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
|
24
|
+
requirements:
|
|
25
|
+
- - ">="
|
|
26
|
+
- !ruby/object:Gem::Version
|
|
27
|
+
segments:
|
|
28
|
+
- 0
|
|
29
|
+
version: "0"
|
|
30
|
+
type: :runtime
|
|
31
|
+
version_requirements: *id001
|
|
32
|
+
description: Ruby wrapper for the Commission Junction product catalog search service API v2 (REST)
|
|
33
|
+
email: aev@vernon.nu
|
|
34
|
+
executables: []
|
|
35
|
+
|
|
36
|
+
extensions: []
|
|
37
|
+
|
|
38
|
+
extra_rdoc_files:
|
|
39
|
+
- LICENSE
|
|
40
|
+
- README.rdoc
|
|
41
|
+
files:
|
|
42
|
+
- .document
|
|
43
|
+
- .gitignore
|
|
44
|
+
- LICENSE
|
|
45
|
+
- README.rdoc
|
|
46
|
+
- Rakefile
|
|
47
|
+
- VERSION
|
|
48
|
+
- lib/commission_junction.rb
|
|
49
|
+
- test/commission_junction_test.rb
|
|
50
|
+
- test/test_helper.rb
|
|
51
|
+
- test/test_response.xml
|
|
52
|
+
has_rdoc: true
|
|
53
|
+
homepage: http://github.com/aevernon/commission_junction
|
|
54
|
+
licenses: []
|
|
55
|
+
|
|
56
|
+
post_install_message:
|
|
57
|
+
rdoc_options:
|
|
58
|
+
- --charset=UTF-8
|
|
59
|
+
require_paths:
|
|
60
|
+
- lib
|
|
61
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
62
|
+
requirements:
|
|
63
|
+
- - ">="
|
|
64
|
+
- !ruby/object:Gem::Version
|
|
65
|
+
segments:
|
|
66
|
+
- 0
|
|
67
|
+
version: "0"
|
|
68
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
69
|
+
requirements:
|
|
70
|
+
- - ">="
|
|
71
|
+
- !ruby/object:Gem::Version
|
|
72
|
+
segments:
|
|
73
|
+
- 0
|
|
74
|
+
version: "0"
|
|
75
|
+
requirements: []
|
|
76
|
+
|
|
77
|
+
rubyforge_project:
|
|
78
|
+
rubygems_version: 1.3.6
|
|
79
|
+
signing_key:
|
|
80
|
+
specification_version: 3
|
|
81
|
+
summary: Commission Junction product catalog search (REST)
|
|
82
|
+
test_files:
|
|
83
|
+
- test/test_helper.rb
|
|
84
|
+
- test/commission_junction_test.rb
|