soapy_cake 0.2.12 → 0.3.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 14bd5992297bb413711f6163038dab8ad4117773
4
- data.tar.gz: 649fe29a12985a6ff9e8b537c0c2297611226e03
3
+ metadata.gz: 2ab8351326e52185986163c48544e4290cb8e907
4
+ data.tar.gz: a0804c9ff6715e168d22388ecf88682641dcf07d
5
5
  SHA512:
6
- metadata.gz: fcdbb08789b6d84aaef97c8cab50780850962f229f683753bb8c4b3bdf7b4c9e86e0cda6b462be1ef6cb091a5a882b1e87ef306c1f864155c249b67685a9c9d7
7
- data.tar.gz: 6019e5d70f4bf80d63ddbd9faf18c1fef6f816ee5c1feb921e48cfe693ead03f18e7665b3a03c5305cf57a1e989d2e776561ae76ff4fd031213ede84ad96f212
6
+ metadata.gz: 101062b3e3babb569f02a6e4c3c3c02d8e4430a1ac6ccbb7c8c47fadd74a50b7ae1dec77e8abdbe07386892ce9235647efccd7de9982ed4deec887cb5ba9e235
7
+ data.tar.gz: f49d9f6d551c28ab57ae4f09ae857cb1424646eb98d2ae940d3a182e5b329c849a6a04f88dcca3719eb3c14a77b0464db2353a30f4264c770c6a87c44c02991a
@@ -1 +1 @@
1
- 2.1.2
1
+ 2.1.4
data/README.md CHANGED
@@ -29,13 +29,13 @@ environment variables.
29
29
  Export all advertisers:
30
30
 
31
31
  ```ruby
32
- SoapyCake::Client.export.advertisers(opts)
32
+ SoapyCake::Client::CakeClient.export.advertisers(opts)
33
33
  ```
34
34
 
35
35
  Get report for specific date range:
36
36
 
37
37
  ```ruby
38
- SoapyCake::Client.reports.affiliate_summary(
38
+ SoapyCake::Client::CakeClient.reports.affiliate_summary(
39
39
  start_date: Date.beginning_of_month,
40
40
  end_date: Date.today
41
41
  )
@@ -1,8 +1,10 @@
1
1
  require 'active_support/core_ext/string'
2
2
  require 'active_support/core_ext/date'
3
3
  require 'soapy_cake/version'
4
- require 'soapy_cake/http_client'
5
4
  require 'soapy_cake/client'
5
+ require 'soapy_cake/admin'
6
+ require 'soapy_cake/advertiser'
7
+ require 'soapy_cake/affiliate'
6
8
 
7
9
  module SoapyCake
8
10
  API_VERSIONS = YAML.load(File.read(File.expand_path('../../api_versions.yml', __FILE__)))
@@ -0,0 +1,87 @@
1
+ module SoapyCake
2
+ class Admin
3
+ def initialize(_opts = {})
4
+ end
5
+
6
+ def affiliate_bills(opts = {})
7
+ Client::CakeClient.accounting.export_affiliate_bills(opts)
8
+ end
9
+
10
+ def advertiser_bills(opts = {})
11
+ Client::CakeClient.accounting.export_advertiser_bills(opts)
12
+ end
13
+
14
+ def affiliate_bill_received!(opts = {})
15
+ Client::CakeClient.accounting.mark_affiliate_bill_as_received(opts)
16
+ end
17
+
18
+ def advertisers(opts = {})
19
+ Client::CakeClient.export.advertisers(opts)
20
+ end
21
+
22
+ def affiliates(opts = {})
23
+ Client::CakeClient.export.affiliates(opts)
24
+ end
25
+
26
+ def campaigns(opts = {})
27
+ Client::CakeClient.export.campaigns(opts)
28
+ end
29
+
30
+ def offers(opts = {})
31
+ Client::CakeClient.export.offers(opts)
32
+ end
33
+
34
+ def campaign_summary(opts)
35
+ Client::CakeClient.reports.campaign_summary(opts_with_date_range(opts))
36
+ end
37
+
38
+ def offer_summary(opts)
39
+ Client::CakeClient.reports.offer_summary(opts_with_date_range(opts))
40
+ end
41
+
42
+ def affiliate_summary(opts)
43
+ Client::CakeClient.reports.affiliate_summary(opts_with_date_range(opts))
44
+ end
45
+
46
+ def advertiser_summary(opts)
47
+ Client::CakeClient.reports.advertiser_summary(opts_with_date_range(opts))
48
+ end
49
+
50
+ def conversions(opts)
51
+ Client::CakeClient.reports.conversions(opts.merge(conversion_type: 'conversions'))
52
+ end
53
+
54
+ def events(opts)
55
+ Client::CakeClient.reports.conversions(opts.merge(conversion_type: 'events'))
56
+ end
57
+
58
+ def currencies
59
+ Client::CakeClient.get.currencies
60
+ end
61
+
62
+ def mark_affiliate_bill_as_paid(opts)
63
+ Client::CakeClient.accounting.mark_affiliate_bill_as_paid(opts)
64
+ end
65
+
66
+ def creatives(opts = {})
67
+ Client::CakeClient.export.creatives(opts)
68
+ end
69
+
70
+ def update_creative(opts = {})
71
+ Client::CakeClient.addedit.creative(opts)
72
+ end
73
+
74
+ def traffic(opts)
75
+ Client::CakeClient.reports.traffic_export(opts_with_date_range(opts))
76
+ end
77
+
78
+ private
79
+
80
+ def opts_with_date_range(opts)
81
+ start_date = opts[:start_date].to_date
82
+ end_date = opts[:end_date] || start_date + 1
83
+
84
+ opts.merge(start_date: start_date, end_date: end_date)
85
+ end
86
+ end
87
+ end
@@ -0,0 +1,21 @@
1
+ module SoapyCake
2
+ class Advertiser
3
+ attr_reader :api_key, :advertiser_id
4
+
5
+ def initialize(opts = {})
6
+ @api_key = opts[:api_key]
7
+ @advertiser_id = opts[:advertiser_id]
8
+ end
9
+
10
+ def bills(opts = {})
11
+ cake_client(:reports, :bills, opts)
12
+ end
13
+
14
+ private
15
+
16
+ def cake_client(api, method, opts = {})
17
+ Client::CakeClient.send(api, role: :advertisers)
18
+ .public_send(method, opts.merge(advertiser_id: advertiser_id, api_key: api_key))
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,29 @@
1
+ module SoapyCake
2
+ class Affiliate
3
+ attr_reader :api_key, :affiliate_id
4
+
5
+ def initialize(opts = {})
6
+ @api_key = opts[:api_key]
7
+ @affiliate_id = opts[:affiliate_id]
8
+ end
9
+
10
+ def bills(opts = {})
11
+ cake_client(:reports, :bills, opts)
12
+ end
13
+
14
+ def offer_feed(opts = {})
15
+ cake_client(:offers, :offer_feed, opts)
16
+ end
17
+
18
+ def campaign(opts = {})
19
+ cake_client(:offers, :get_campaign, opts)
20
+ end
21
+
22
+ private
23
+
24
+ def cake_client(api, method, opts = {})
25
+ Client::CakeClient.send(api, role: :affiliates)
26
+ .send(method, opts.merge(affiliate_id: affiliate_id, api_key: api_key))
27
+ end
28
+ end
29
+ end
@@ -1,155 +1,5 @@
1
- require 'sekken'
2
- require 'active_support/core_ext/time/zones'
3
- require 'local_copy'
1
+ require 'soapy_cake/client/http_client'
2
+ require 'soapy_cake/client/cake_client'
4
3
 
5
- module SoapyCake
6
- class Client
7
- attr_reader :service, :api_key, :domain, :role
8
-
9
- def initialize(service, opts = {})
10
- @service = service.to_sym
11
- @version = opts[:version]
12
- @role = opts[:role] || :admin
13
-
14
- @domain = opts.fetch(:domain) do
15
- if ENV['CAKE_DOMAIN'].present?
16
- ENV['CAKE_DOMAIN']
17
- else
18
- fail 'We need a domain'
19
- end
20
- end
21
-
22
- @api_key = opts.fetch(:api_key) do
23
- if opts[:username] && opts[:password]
24
- get_api_key(opts[:username], opts[:password])
25
- elsif ENV['CAKE_API_KEY']
26
- ENV['CAKE_API_KEY']
27
- else
28
- fail 'We need an API key here!'
29
- end
30
- end
31
- end
32
-
33
- def self.method_missing(method, opts = {})
34
- new(method, opts)
35
- end
36
-
37
- def sekken_client(method)
38
- self.class.sekken_client(wsdl_url(version(method)))
39
- end
40
-
41
- def self.sekken_client(url)
42
- path = LocalCopy.fetch(url)
43
- @sekken_clients ||= {}
44
- @sekken_clients[url] ||= Sekken.new(path, HTTPartySekken.new)
45
- end
46
-
47
- def method_missing(method, opts = {})
48
- if supported?(method)
49
- method = method.to_s
50
- operation = sekken_client(method).operation(service, "#{service}Soap12", method.camelize)
51
- operation.body = build_body(method, opts)
52
- process_response(method, operation.call.body)
53
- else
54
- super
55
- end
56
- end
57
-
58
- def known_params_for(method)
59
- method = method.to_s
60
- operation = sekken_client(method).operation(service, "#{service}Soap12", method.camelize)
61
- operation.example_body
62
- end
63
-
64
- private
65
-
66
- def build_body(method, opts)
67
- {
68
- method.camelize.to_sym => { api_key: api_key }.merge(
69
- opts.each_with_object({}) do |(key, value), memo|
70
- memo[key] = format_param(value)
71
- end
72
- )
73
- }
74
- end
75
-
76
- def format_param(value)
77
- case value
78
- when Time
79
- value.utc.strftime('%Y-%m-%dT%H:%M:%S')
80
- when Date
81
- value.strftime('%Y-%m-%dT00:00:00')
82
- else
83
- value
84
- end
85
- end
86
-
87
- def process_response(method, response)
88
- Time.use_zone('UTC') do
89
- fail RequestUnsuccessful, response[:fault][:reason][:text] if response[:fault]
90
- node_name = {
91
- 'affiliate_summary' => 'affiliates',
92
- 'advertiser_summary' => 'advertisers',
93
- 'affiliate_tags' => 'tags',
94
- 'offer_summary' => 'offers',
95
- 'campaign_summary' => 'campaigns',
96
- 'offer_feed' => 'offers',
97
- 'export_affiliate_bills' => 'affiliate_bills',
98
- 'export_advertiser_bills' => 'advertiser_bills',
99
- }.fetch(method, method)
100
-
101
- result = response[:"#{method}_response"][:"#{method}_result"]
102
- fail RequestUnsuccessful, result[:message] if result[:success] == false
103
- return result unless result_has_collection?(result, method)
104
- extract_collection(node_name, result)
105
- .map { |hash| remove_prefix(node_name, hash) }
106
- end
107
- end
108
-
109
- def result_has_collection?(result, method)
110
- !result.key?(:message) && !method.to_s.starts_with?('get_')
111
- end
112
-
113
- def extract_collection(node_name, response)
114
- node_name = node_name.to_sym
115
- if response.key?(node_name)
116
- return [] if response[node_name].nil?
117
- response = response[node_name]
118
- end
119
- [response[response.keys.first]].flatten
120
- end
121
-
122
- def remove_prefix(prefix, object)
123
- object.each_with_object({}) do |(k, v), m|
124
- prefix_ = "#{prefix.singularize}_"
125
- if k.to_s.start_with?(prefix_)
126
- m[k[(prefix_.size)..-1].to_sym] = v
127
- else
128
- m[k] = v
129
- end
130
- end
131
- end
132
-
133
- def get_api_key(username, password)
134
- operation = sekken_client(:get_api_key).operation('get', 'getSoap12', 'GetAPIKey')
135
- operation.body = { GetAPIKey: { username: username, password: password } }
136
- response = operation.call.body
137
- response[:get_api_key_response][:get_api_key_result]
138
- end
139
-
140
- def wsdl_url(version)
141
- role_path = (role && role != :admin) ? "/#{role}" : nil
142
- "https://#{domain}#{role_path}/api/#{version}/#{service}.asmx?WSDL"
143
- end
144
-
145
- def version(method)
146
- API_VERSIONS[role][service][method.to_sym]
147
- end
148
-
149
- def supported?(method)
150
- API_VERSIONS[role][service].keys.include?(method)
151
- end
152
-
153
- class RequestUnsuccessful < RuntimeError; end
154
- end
4
+ module SoapyCake::Client
155
5
  end
@@ -0,0 +1,157 @@
1
+ require 'sekken'
2
+ require 'active_support/core_ext/time/zones'
3
+ require 'local_copy'
4
+
5
+ module SoapyCake
6
+ module Client
7
+ class CakeClient
8
+ attr_reader :service, :api_key, :domain, :role
9
+
10
+ def initialize(service, opts = {})
11
+ @service = service.to_sym
12
+ @version = opts[:version]
13
+ @role = opts[:role] || :admin
14
+
15
+ @domain = opts.fetch(:domain) do
16
+ if ENV['CAKE_DOMAIN'].present?
17
+ ENV['CAKE_DOMAIN']
18
+ else
19
+ fail 'We need a domain'
20
+ end
21
+ end
22
+
23
+ @api_key = opts.fetch(:api_key) do
24
+ if opts[:username] && opts[:password]
25
+ get_api_key(opts[:username], opts[:password])
26
+ elsif ENV['CAKE_API_KEY']
27
+ ENV['CAKE_API_KEY']
28
+ else
29
+ fail 'We need an API key here!'
30
+ end
31
+ end
32
+ end
33
+
34
+ def self.method_missing(method, opts = {})
35
+ new(method, opts)
36
+ end
37
+
38
+ def sekken_client(method)
39
+ self.class.sekken_client(wsdl_url(version(method)))
40
+ end
41
+
42
+ def self.sekken_client(url)
43
+ path = LocalCopy.fetch(url)
44
+ @sekken_clients ||= {}
45
+ @sekken_clients[url] ||= Sekken.new(path, HTTPartySekken.new)
46
+ end
47
+
48
+ def method_missing(method, opts = {})
49
+ if supported?(method)
50
+ method = method.to_s
51
+ operation = sekken_client(method).operation(service, "#{service}Soap12", method.camelize)
52
+ operation.body = build_body(method, opts)
53
+ process_response(method, operation.call.body)
54
+ else
55
+ super
56
+ end
57
+ end
58
+
59
+ def known_params_for(method)
60
+ method = method.to_s
61
+ operation = sekken_client(method).operation(service, "#{service}Soap12", method.camelize)
62
+ operation.example_body
63
+ end
64
+
65
+ private
66
+
67
+ def build_body(method, opts)
68
+ {
69
+ method.camelize.to_sym => { api_key: api_key }.merge(
70
+ opts.each_with_object({}) do |(key, value), memo|
71
+ memo[key] = format_param(value)
72
+ end
73
+ )
74
+ }
75
+ end
76
+
77
+ def format_param(value)
78
+ case value
79
+ when Time
80
+ value.utc.strftime('%Y-%m-%dT%H:%M:%S')
81
+ when Date
82
+ value.strftime('%Y-%m-%dT00:00:00')
83
+ else
84
+ value
85
+ end
86
+ end
87
+
88
+ def process_response(method, response)
89
+ Time.use_zone('UTC') do
90
+ fail RequestUnsuccessful, response[:fault][:reason][:text] if response[:fault]
91
+ node_name = {
92
+ 'affiliate_summary' => 'affiliates',
93
+ 'advertiser_summary' => 'advertisers',
94
+ 'affiliate_tags' => 'tags',
95
+ 'offer_summary' => 'offers',
96
+ 'campaign_summary' => 'campaigns',
97
+ 'offer_feed' => 'offers',
98
+ 'export_affiliate_bills' => 'affiliate_bills',
99
+ 'export_advertiser_bills' => 'advertiser_bills',
100
+ }.fetch(method, method)
101
+
102
+ result = response[:"#{method}_response"][:"#{method}_result"]
103
+ fail RequestUnsuccessful, result[:message] if result[:success] == false
104
+ return result unless result_has_collection?(result, method)
105
+ extract_collection(node_name, result)
106
+ .map { |hash| remove_prefix(node_name, hash) }
107
+ end
108
+ end
109
+
110
+ def result_has_collection?(result, method)
111
+ !result.key?(:message) && !method.to_s.starts_with?('get_')
112
+ end
113
+
114
+ def extract_collection(node_name, response)
115
+ node_name = node_name.to_sym
116
+ if response.key?(node_name)
117
+ return [] if response[node_name].nil?
118
+ response = response[node_name]
119
+ end
120
+ [response[response.keys.first]].flatten
121
+ end
122
+
123
+ def remove_prefix(prefix, object)
124
+ object.each_with_object({}) do |(k, v), m|
125
+ prefix_ = "#{prefix.singularize}_"
126
+ if k.to_s.start_with?(prefix_)
127
+ m[k[(prefix_.size)..-1].to_sym] = v
128
+ else
129
+ m[k] = v
130
+ end
131
+ end
132
+ end
133
+
134
+ def get_api_key(username, password)
135
+ operation = sekken_client(:get_api_key).operation('get', 'getSoap12', 'GetAPIKey')
136
+ operation.body = { GetAPIKey: { username: username, password: password } }
137
+ response = operation.call.body
138
+ response[:get_api_key_response][:get_api_key_result]
139
+ end
140
+
141
+ def wsdl_url(version)
142
+ role_path = (role && role != :admin) ? "/#{role}" : nil
143
+ "https://#{domain}#{role_path}/api/#{version}/#{service}.asmx?WSDL"
144
+ end
145
+
146
+ def version(method)
147
+ API_VERSIONS[role][service][method.to_sym]
148
+ end
149
+
150
+ def supported?(method)
151
+ API_VERSIONS[role][service].keys.include?(method)
152
+ end
153
+
154
+ class RequestUnsuccessful < RuntimeError; end
155
+ end
156
+ end
157
+ end
@@ -0,0 +1,14 @@
1
+ require 'httparty'
2
+
3
+ class HTTPartySekken
4
+ include HTTParty
5
+ read_timeout 3 * 60
6
+
7
+ def get(url)
8
+ self.class.get(url).body
9
+ end
10
+
11
+ def post(url, headers, body)
12
+ self.class.post(url, headers: headers, body: body).body
13
+ end
14
+ end
@@ -1,3 +1,3 @@
1
1
  module SoapyCake
2
- VERSION = '0.2.12'
2
+ VERSION = '0.3.1'
3
3
  end
@@ -0,0 +1,251 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe SoapyCake::Admin do
4
+ describe '.affiliate_bill_received!' do
5
+ it 'marks an affiliate bill as received' do
6
+ expect_any_instance_of(SoapyCake::Client::CakeClient)
7
+ .to receive(:mark_affiliate_bill_as_received)
8
+ .with(affiliate_id: 2)
9
+
10
+ subject.affiliate_bill_received!(affiliate_id: 2)
11
+ end
12
+ end
13
+
14
+ describe '.affiliate_bills' do
15
+ it 'exports bills' do
16
+ expect_any_instance_of(SoapyCake::Client::CakeClient)
17
+ .to receive(:export_affiliate_bills)
18
+ .with(affiliate_id: 2)
19
+
20
+ subject.affiliate_bills(affiliate_id: 2)
21
+ end
22
+ end
23
+
24
+ describe '.advertiser_bills' do
25
+ it 'exports bills' do
26
+ expect_any_instance_of(SoapyCake::Client::CakeClient)
27
+ .to receive(:export_advertiser_bills)
28
+ .with(advertiser_id: 2)
29
+
30
+ subject.advertiser_bills(advertiser_id: 2)
31
+ end
32
+ end
33
+
34
+ describe '.campaign_summary' do
35
+ let(:start_date) { Date.new(2014, 7, 1) }
36
+ let(:end_date) { Date.new(2014, 7, 3) }
37
+
38
+ it 'returns the campaign summary report for the given days' do
39
+ expect_any_instance_of(SoapyCake::Client::CakeClient)
40
+ .to receive(:campaign_summary)
41
+ .with(start_date: start_date, end_date: end_date, offer_id: 12)
42
+ .and_return('result')
43
+
44
+ expect(subject.campaign_summary(start_date: start_date, end_date: end_date, offer_id: 12))
45
+ .to eq('result')
46
+ end
47
+
48
+ it 'returns the campaign summary report for the start_date if no end_date is given' do
49
+ expect_any_instance_of(SoapyCake::Client::CakeClient)
50
+ .to receive(:campaign_summary)
51
+ .with(start_date: start_date, end_date: start_date + 1, offer_id: 12)
52
+ .and_return('result')
53
+
54
+ expect(subject.campaign_summary(start_date: start_date, offer_id: 12))
55
+ .to eq('result')
56
+ end
57
+ end
58
+
59
+
60
+ describe '.advertisers' do
61
+ it 'returns advertisers' do
62
+ expect_any_instance_of(SoapyCake::Client::CakeClient)
63
+ .to receive(:advertisers)
64
+
65
+ subject.advertisers
66
+ end
67
+ end
68
+
69
+ describe '.affiliates' do
70
+ it 'returns affiliates' do
71
+ expect_any_instance_of(SoapyCake::Client::CakeClient)
72
+ .to receive(:affiliates)
73
+
74
+ subject.affiliates(force: true)
75
+ end
76
+ end
77
+
78
+ describe '.campaigns' do
79
+ it 'returns all campaigns' do
80
+ opts = { foo: :bar }
81
+ expected = [{ ping: :pong }]
82
+ expect_any_instance_of(SoapyCake::Client::CakeClient)
83
+ .to receive(:campaigns)
84
+ .with(opts).and_return(expected)
85
+ expect(subject.campaigns(opts)).to eq(expected)
86
+ end
87
+ end
88
+
89
+ describe '.offers' do
90
+ it 'returns all offers' do
91
+ opts = { foo: :bar }
92
+ expected = [{ ping: :pong }]
93
+ expect_any_instance_of(SoapyCake::Client::CakeClient)
94
+ .to receive(:offers)
95
+ .with(opts).and_return(expected)
96
+ expect(subject.offers(opts)).to eq(expected)
97
+ end
98
+ end
99
+
100
+ describe '.affiliate_summary' do
101
+ let(:start_date) { Date.new(2014, 7, 1) }
102
+ let(:end_date) { Date.new(2014, 7, 3) }
103
+
104
+ it 'returns the affiliate summary report for the given days' do
105
+ expect_any_instance_of(SoapyCake::Client::CakeClient)
106
+ .to receive(:affiliate_summary)
107
+ .with(start_date: start_date, end_date: end_date).and_return(
108
+ [{ affiliate: { affiliate_id: '1' } },
109
+ { affiliate: { affiliate_id: '2' } }]
110
+ )
111
+
112
+ expect(subject.affiliate_summary(start_date: start_date, end_date: end_date))
113
+ .to eq(
114
+ [{ affiliate: { affiliate_id: '1' } },
115
+ { affiliate: { affiliate_id: '2' } }]
116
+ )
117
+ end
118
+
119
+ it 'returns the affiliate summary report for the start_date if no end_date is given' do
120
+ expect_any_instance_of(SoapyCake::Client::CakeClient)
121
+ .to receive(:affiliate_summary)
122
+ .with(start_date: start_date, end_date: start_date + 1).and_return(
123
+ [{ affiliate: { affiliate_id: '1' } },
124
+ { affiliate: { affiliate_id: '2' } }]
125
+ )
126
+
127
+ expect(subject.affiliate_summary(start_date: start_date)).to eq(
128
+ [{ affiliate: { affiliate_id: '1' } },
129
+ { affiliate: { affiliate_id: '2' } }]
130
+ )
131
+ end
132
+ end
133
+
134
+ describe '.advertiser_summary' do
135
+ let(:start_date) { Date.new(2014, 7, 1) }
136
+ let(:end_date) { Date.new(2014, 7, 3) }
137
+
138
+ it 'returns the advertiser summary report for the given days' do
139
+ expect_any_instance_of(SoapyCake::Client::CakeClient)
140
+ .to receive(:advertiser_summary)
141
+ .with(start_date: start_date, end_date: end_date).and_return(
142
+ [{ advertiser: { advertiser_id: '1' } },
143
+ { advertiser: { advertiser_id: '2' } }]
144
+ )
145
+
146
+ expect(subject.advertiser_summary(start_date: start_date, end_date: end_date))
147
+ .to eq(
148
+ [{ advertiser: { advertiser_id: '1' } },
149
+ { advertiser: { advertiser_id: '2' } }]
150
+ )
151
+ end
152
+
153
+ it 'returns the advertiser summary report for the start_date if no end_date is given' do
154
+ expect_any_instance_of(SoapyCake::Client::CakeClient)
155
+ .to receive(:advertiser_summary)
156
+ .with(start_date: start_date, end_date: start_date + 1).and_return(
157
+ [{ advertiser: { advertiser_id: '1' } },
158
+ { advertiser: { advertiser_id: '2' } }]
159
+ )
160
+
161
+ expect(subject.advertiser_summary(start_date: start_date)).to eq(
162
+ [{ advertiser: { advertiser_id: '1' } },
163
+ { advertiser: { advertiser_id: '2' } }]
164
+ )
165
+ end
166
+ end
167
+
168
+ describe '.offer_summary' do
169
+ let(:start_date) { Date.new(2014, 7, 1) }
170
+ let(:end_date) { Date.new(2014, 7, 3) }
171
+
172
+ it 'returns the offer summary report for the given days' do
173
+ expect_any_instance_of(SoapyCake::Client::CakeClient)
174
+ .to receive(:offer_summary)
175
+ .with(start_date: start_date, end_date: end_date, offer_id: 1)
176
+ .and_return('result')
177
+
178
+ expect(subject.offer_summary(start_date: start_date, end_date: end_date, offer_id: 1))
179
+ .to eq('result')
180
+ end
181
+
182
+ it 'returns the offer summary report for the start_date if no end_date is given' do
183
+ expect_any_instance_of(SoapyCake::Client::CakeClient)
184
+ .to receive(:offer_summary)
185
+ .with(start_date: start_date, end_date: start_date + 1, offer_id: 1)
186
+ .and_return('result')
187
+
188
+ expect(subject.offer_summary(start_date: start_date, offer_id: 1))
189
+ .to eq('result')
190
+ end
191
+ end
192
+
193
+ describe '.conversions' do
194
+ it 'returns only conversions' do
195
+ expect_any_instance_of(SoapyCake::Client::CakeClient)
196
+ .to receive(:conversions)
197
+ .with(color: 'green', conversion_type: 'conversions')
198
+
199
+ subject.conversions(color: 'green')
200
+ end
201
+ end
202
+
203
+ describe '.events' do
204
+ it 'returns only events' do
205
+ expect_any_instance_of(SoapyCake::Client::CakeClient)
206
+ .to receive(:conversions)
207
+ .with(color: 'red', conversion_type: 'events')
208
+
209
+ subject.events(color: 'red')
210
+ end
211
+ end
212
+
213
+ describe '#mark_affiliate_bill_as_paid' do
214
+ it 'marks credit notes as paid' do
215
+ expect_any_instance_of(SoapyCake::Client::CakeClient)
216
+ .to receive(:mark_affiliate_bill_as_paid).with(bill_id: 1)
217
+ subject.mark_affiliate_bill_as_paid(bill_id: 1)
218
+ end
219
+ end
220
+
221
+ describe '#creatives' do
222
+ it 'fetches creatives from CAKE' do
223
+ expect_any_instance_of(SoapyCake::Client::CakeClient)
224
+ .to receive(:creatives)
225
+ .with(offer_id: 1)
226
+ subject.creatives(offer_id: 1)
227
+ end
228
+ end
229
+
230
+ describe '#traffic' do
231
+ let(:start_date) { Date.new(2014, 7, 1) }
232
+ let(:end_date) { Date.new(2014, 7, 3) }
233
+
234
+ it 'fetches a traffic report' do
235
+ expect_any_instance_of(SoapyCake::Client::CakeClient)
236
+ .to receive(:traffic_export)
237
+ .with(start_date: start_date, end_date: end_date)
238
+
239
+ subject.traffic(start_date: start_date, end_date: end_date)
240
+ end
241
+ end
242
+
243
+ describe '#update_creative' do
244
+ it 'updates a creative' do
245
+ expect_any_instance_of(SoapyCake::Client::CakeClient).to receive(:creative)
246
+ .with(offer_id: 1, creative_status_id: 1)
247
+
248
+ subject.update_creative(offer_id: 1, creative_status_id: 1)
249
+ end
250
+ end
251
+ end
@@ -0,0 +1,14 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe SoapyCake::Advertiser do
4
+ subject { described_class.new(api_key: 'abc', advertiser_id: 1) }
5
+
6
+ describe '.bills' do
7
+ it 'returns bills for an advertiser' do
8
+ expect_any_instance_of(SoapyCake::Client::CakeClient).to receive(:bills)
9
+ .with(advertiser_id: 1, api_key: 'abc')
10
+
11
+ subject.bills
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,50 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe SoapyCake::Affiliate do
4
+ subject { described_class.new(api_key: 'abc', affiliate_id: 1) }
5
+
6
+ let(:client) { double('soap client') }
7
+
8
+ describe '#bills' do
9
+ it 'returns bills' do
10
+ expect(SoapyCake::Client::CakeClient).to receive(:reports)
11
+ .with(role: :affiliates)
12
+ .and_return(client)
13
+
14
+ expect(client).to receive(:bills).with(affiliate_id: 1, api_key: 'abc')
15
+
16
+ subject.bills
17
+ end
18
+ end
19
+
20
+ describe '#offer_feed' do
21
+ let(:offers) { double('offers') }
22
+
23
+ it 'returns offers' do
24
+ expect(SoapyCake::Client::CakeClient).to receive(:offers)
25
+ .with(role: :affiliates)
26
+ .and_return(client)
27
+
28
+ expect(client).to receive(:offer_feed)
29
+ .with(affiliate_id: 1, api_key: 'abc', status_id: 3)
30
+ .and_return(offers)
31
+
32
+ expect(subject.offer_feed(status_id: 3)).to eq(offers)
33
+ end
34
+ end
35
+
36
+ describe '#campaign' do
37
+ let(:campaign) { double('campaign') }
38
+
39
+ it 'returns a campaign' do
40
+ expect(SoapyCake::Client::CakeClient).to receive(:offers)
41
+ .with(role: :affiliates)
42
+ .and_return(client)
43
+
44
+ expect(client).to receive(:get_campaign)
45
+ .with(affiliate_id: 1, api_key: 'abc', campaign_id: 12)
46
+ .and_return(campaign)
47
+ expect(subject.campaign(campaign_id: 12)).to eq(campaign)
48
+ end
49
+ end
50
+ end
@@ -2,12 +2,12 @@
2
2
 
3
3
  require 'spec_helper'
4
4
 
5
- RSpec.describe SoapyCake::Client do
5
+ RSpec.describe SoapyCake::Client::CakeClient do
6
6
  before do
7
- SoapyCake::Client.instance_variable_set(:@sekken_clients, nil)
7
+ described_class.instance_variable_set(:@sekken_clients, nil)
8
8
  end
9
9
 
10
- subject(:client) { SoapyCake::Client.new(:get, opts) }
10
+ subject(:client) { described_class.new(:get, opts) }
11
11
  let(:opts) { {} }
12
12
 
13
13
  describe '.new' do
@@ -89,7 +89,7 @@ RSpec.describe SoapyCake::Client do
89
89
 
90
90
  context 'for offer summary' do
91
91
  subject do
92
- SoapyCake::Client.new(:reports, opts).offer_summary(
92
+ described_class.new(:reports, opts).offer_summary(
93
93
  start_date: Time.utc(2013, 1, 1),
94
94
  end_date: Time.utc(2013, 1, 2)
95
95
  )
@@ -177,20 +177,20 @@ RSpec.describe SoapyCake::Client do
177
177
  client.send(:process_response, :affiliate, affiliate_response: {
178
178
  affiliate_result: { message: 'FAIL!', success: false }
179
179
  })
180
- end.to raise_error(SoapyCake::Client::RequestUnsuccessful, 'FAIL!')
180
+ end.to raise_error(described_class::RequestUnsuccessful, 'FAIL!')
181
181
  end
182
182
 
183
183
  it 'raises RequestUnsuccessful if response contains `:fault` key' do
184
184
  expect do
185
185
  client.send(:process_response, :affiliate,
186
186
  fault: { reason: { text: 'FAIL!' } })
187
- end.to raise_error(SoapyCake::Client::RequestUnsuccessful, 'FAIL!')
187
+ end.to raise_error(described_class::RequestUnsuccessful, 'FAIL!')
188
188
  end
189
189
  end
190
190
 
191
191
  describe 'instantiating through class method' do
192
192
  it 'creates an instance with the service set according to the method name used' do
193
- instance = SoapyCake::Client.get
193
+ instance = described_class.get
194
194
  expect(instance.service).to eq(:get)
195
195
  end
196
196
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: soapy_cake
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.12
4
+ version: 0.3.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - ad2games GmbH
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-11-06 00:00:00.000000000 Z
11
+ date: 2014-12-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -166,8 +166,12 @@ files:
166
166
  - Rakefile
167
167
  - api_versions.yml
168
168
  - lib/soapy_cake.rb
169
+ - lib/soapy_cake/admin.rb
170
+ - lib/soapy_cake/advertiser.rb
171
+ - lib/soapy_cake/affiliate.rb
169
172
  - lib/soapy_cake/client.rb
170
- - lib/soapy_cake/http_client.rb
173
+ - lib/soapy_cake/client/cake_client.rb
174
+ - lib/soapy_cake/client/http_client.rb
171
175
  - lib/soapy_cake/version.rb
172
176
  - script/update_versions.rb
173
177
  - soapy_cake.gemspec
@@ -193,7 +197,10 @@ files:
193
197
  - spec/fixtures/vcr_cassettes/client_new_verticals.yml
194
198
  - spec/fixtures/vcr_cassettes/client_new_with_username_and_password.yml
195
199
  - spec/fixtures/vcr_cassettes/client_sekken_client_caches_results.yml
196
- - spec/lib/soapy_cake/client_spec.rb
200
+ - spec/lib/soapy_cake/admin_spec.rb
201
+ - spec/lib/soapy_cake/advertiser_spec.rb
202
+ - spec/lib/soapy_cake/affiliate_spec.rb
203
+ - spec/lib/soapy_cake/client/cake_client_spec.rb
197
204
  - spec/spec_helper.rb
198
205
  homepage: http://ad2games.com
199
206
  licenses:
@@ -242,5 +249,8 @@ test_files:
242
249
  - spec/fixtures/vcr_cassettes/client_new_verticals.yml
243
250
  - spec/fixtures/vcr_cassettes/client_new_with_username_and_password.yml
244
251
  - spec/fixtures/vcr_cassettes/client_sekken_client_caches_results.yml
245
- - spec/lib/soapy_cake/client_spec.rb
252
+ - spec/lib/soapy_cake/admin_spec.rb
253
+ - spec/lib/soapy_cake/advertiser_spec.rb
254
+ - spec/lib/soapy_cake/affiliate_spec.rb
255
+ - spec/lib/soapy_cake/client/cake_client_spec.rb
246
256
  - spec/spec_helper.rb
@@ -1,11 +0,0 @@
1
- require 'httparty'
2
-
3
- class HTTPartySekken
4
- def get(url)
5
- HTTParty.get(url).body
6
- end
7
-
8
- def post(url, headers, body)
9
- HTTParty.post(url, headers: headers, body: body).body
10
- end
11
- end