ad_leads 0.1.2
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.
- checksums.yaml +7 -0
- data/.gitignore +18 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +35 -0
- data/Rakefile +1 -0
- data/ad_leads.gemspec +27 -0
- data/lib/ad_leads/ad.rb +19 -0
- data/lib/ad_leads/base.rb +19 -0
- data/lib/ad_leads/campaign.rb +43 -0
- data/lib/ad_leads/campaign_helpers.rb +44 -0
- data/lib/ad_leads/client.rb +106 -0
- data/lib/ad_leads/configuration.rb +43 -0
- data/lib/ad_leads/creative_group.rb +13 -0
- data/lib/ad_leads/etag.rb +30 -0
- data/lib/ad_leads/image.rb +48 -0
- data/lib/ad_leads/promotion.rb +39 -0
- data/lib/ad_leads/token.rb +53 -0
- data/lib/ad_leads/version.rb +3 -0
- data/lib/ad_leads.rb +16 -0
- data/spec/ad_leads/ad_spec.rb +25 -0
- data/spec/ad_leads/base_spec.rb +20 -0
- data/spec/ad_leads/campaign_spec.rb +69 -0
- data/spec/ad_leads/client_spec.rb +49 -0
- data/spec/ad_leads/configuration_spec.rb +46 -0
- data/spec/ad_leads/creative_group_spec.rb +25 -0
- data/spec/ad_leads/image_spec.rb +71 -0
- data/spec/ad_leads/network_requests_redux_spec.rb +64 -0
- data/spec/ad_leads/token_spec.rb +97 -0
- data/spec/ad_leads/version_spec.rb +7 -0
- data/spec/fixtures/ad_campaign_obj.rb +24 -0
- data/spec/fixtures/test.jpg +0 -0
- data/spec/spec_helper.rb +4 -0
- metadata +187 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 2ca5e0966af39aecdd5c29834dfcef08da19d37f
|
4
|
+
data.tar.gz: 0a34abc322f7d6db6220d349e4eca701b766d5f0
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 826299ae9ad0040440699bc5192880bc2573fa61cc621bcd55949f1c9b2d98ad5d595fe928d7c366ccdffd3d56fe589f9150d87c16f9b0080ffa6f1ae9e1660d
|
7
|
+
data.tar.gz: 1f59acc22d34c6eb258ee937d5720216f771f6f4772bc17f6f7db19707a4ffebe6b60e31464054649a497727df4ed05631514925e00df800a6c0b9202521e2b8
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2014 Dinshaw
|
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,35 @@
|
|
1
|
+
# AdLeads
|
2
|
+
Wrapper for the Adleads JSON api.
|
3
|
+
|
4
|
+
## Installation
|
5
|
+
|
6
|
+
Add this line to your application's Gemfile:
|
7
|
+
|
8
|
+
gem 'ad_leads'
|
9
|
+
|
10
|
+
And then execute:
|
11
|
+
|
12
|
+
$ bundle
|
13
|
+
|
14
|
+
Or install it yourself as:
|
15
|
+
|
16
|
+
$ gem install ad_leads
|
17
|
+
|
18
|
+
## Usage
|
19
|
+
Steps are outline by request here - https://api.adleads.com/doc/index.html#tutorial
|
20
|
+
|
21
|
+
AdLeads.configure do |config|
|
22
|
+
config.client_id = ENV['AD_LEADS_CLIENT_ID'],
|
23
|
+
config.principle = ENV['AD_LEADS_PRINCIPLE'],
|
24
|
+
config.private_key = ENV['AD_LEADS_PRIVATE_KEY']
|
25
|
+
end
|
26
|
+
|
27
|
+
client = AdLeads::Client.new
|
28
|
+
|
29
|
+
## Contributing
|
30
|
+
|
31
|
+
1. Fork it ( http://github.com/<my-github-username>/ad_leads/fork )
|
32
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
33
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
34
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
35
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
data/ad_leads.gemspec
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'ad_leads/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "ad_leads"
|
8
|
+
spec.version = AdLeads::VERSION
|
9
|
+
spec.authors = ["Dinshaw"]
|
10
|
+
spec.email = ["dgobhai@constantcontact.com"]
|
11
|
+
spec.summary = %q{Ruby Wrapper for AdLeads API}
|
12
|
+
spec.homepage = ""
|
13
|
+
spec.license = "MIT"
|
14
|
+
|
15
|
+
spec.files = `git ls-files -z`.split("\x0")
|
16
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
17
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
18
|
+
spec.require_paths = ["lib"]
|
19
|
+
|
20
|
+
spec.add_dependency 'faraday', '0.9.0'
|
21
|
+
spec.add_dependency 'httpclient', '2.3.4.1'
|
22
|
+
spec.add_dependency 'jwt', '0.1.11'
|
23
|
+
spec.add_development_dependency 'rspec', '~> 2.14'
|
24
|
+
spec.add_development_dependency 'bundler', "~> 1.5"
|
25
|
+
spec.add_development_dependency 'rake'
|
26
|
+
spec.add_development_dependency 'pry'
|
27
|
+
end
|
data/lib/ad_leads/ad.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
class AdLeads::Ad < AdLeads::Base
|
2
|
+
# params = {
|
3
|
+
# 'type' => 'Mobile',
|
4
|
+
# 'name' => 'test mobile ad',
|
5
|
+
# 'headerText' => 'get your ad on this phone today',
|
6
|
+
# 'bodyText' => 'this is mobile ad body copy'
|
7
|
+
# }
|
8
|
+
|
9
|
+
attr_accessor :creative_group_id
|
10
|
+
|
11
|
+
def initialize(creative_group_id)
|
12
|
+
@creative_group_id = creative_group_id
|
13
|
+
end
|
14
|
+
|
15
|
+
def root_path
|
16
|
+
"/creativegroups/#{creative_group_id}/creatives"
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
class AdLeads::Base
|
2
|
+
attr_accessor :response
|
3
|
+
|
4
|
+
def create!(params)
|
5
|
+
self.response = client.post(root_path, params)
|
6
|
+
end
|
7
|
+
|
8
|
+
def client
|
9
|
+
@client ||= AdLeads::Client.new
|
10
|
+
end
|
11
|
+
|
12
|
+
def id
|
13
|
+
@id ||= JSON.parse(response.body)['data'].first
|
14
|
+
end
|
15
|
+
|
16
|
+
def status
|
17
|
+
response.status
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
class AdLeads::Campaign < AdLeads::Base
|
2
|
+
include AdLeads::Etag
|
3
|
+
|
4
|
+
# params = {
|
5
|
+
# 'name' => 'test',
|
6
|
+
# 'verticals' => 82,
|
7
|
+
# 'offerIncentiveCategory' => 5,
|
8
|
+
# 'collectedFields' => 'firstname,lastname,email,companyname',
|
9
|
+
# 'budget' => 50,
|
10
|
+
# 'creativeGroups' => creative_group.id
|
11
|
+
# }
|
12
|
+
|
13
|
+
def update!(params)
|
14
|
+
client.post(campaign_path, params)
|
15
|
+
end
|
16
|
+
|
17
|
+
def verify!
|
18
|
+
client.get(verify_campaign_path)
|
19
|
+
end
|
20
|
+
|
21
|
+
def launch!
|
22
|
+
with_etag do
|
23
|
+
client.post(launch_campaign_path, etag: etag)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def campaign_path
|
28
|
+
root_path + "/#{id}"
|
29
|
+
end
|
30
|
+
alias :etag_path :campaign_path
|
31
|
+
|
32
|
+
def launch_campaign_path
|
33
|
+
campaign_path + '/launch'
|
34
|
+
end
|
35
|
+
|
36
|
+
def root_path
|
37
|
+
'/campaigns'
|
38
|
+
end
|
39
|
+
|
40
|
+
def verify_campaign_path
|
41
|
+
campaign_path + '/plan'
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
class CampaignHelpers
|
2
|
+
|
3
|
+
def creative_group_params
|
4
|
+
{
|
5
|
+
'name' => @ad_campaign_obj[:campaign_info][:name],
|
6
|
+
'productName' => @ad_campaign_obj[:content_info][:name],
|
7
|
+
'active' => @ad_campaign_obj[:content_info][:active],
|
8
|
+
'privacyPolicyUrl' => @ad_campaign_obj[:content_info][:privacy]
|
9
|
+
}
|
10
|
+
end
|
11
|
+
|
12
|
+
def ad_params
|
13
|
+
{
|
14
|
+
'name' => @ad_campaign_obj[:content_info][:name]
|
15
|
+
'type' => @ad_campaign_obj[:content_info][:type],
|
16
|
+
##mobile
|
17
|
+
'headerText' => @ad_campaign_obj[:content_info][:headerText],
|
18
|
+
'bodyText' => @ad_campaign_obj[:content_info][:bodyText],
|
19
|
+
##email
|
20
|
+
'fromAddress' => @ad_campaign_obj[:campaign_info][:email],
|
21
|
+
'subject' => @ad_campaign_obj[:content_info][:subject],
|
22
|
+
'companyName' => @ad_campaign_obj[:campaign_info][:dba],
|
23
|
+
'mailingAddress' => @ad_campaign_obj[:campaign_info][:address],
|
24
|
+
'calltoAction' => @ad_campaign_obj[:campaign_info][:cta],
|
25
|
+
'preHeader' => @ad_campaign_obj[:campaign_info][:pre_header]
|
26
|
+
}
|
27
|
+
end
|
28
|
+
|
29
|
+
def content_holder_params
|
30
|
+
{
|
31
|
+
'type' => @ad_campaign_obj[:content_info][:image_type]
|
32
|
+
}
|
33
|
+
end
|
34
|
+
|
35
|
+
def campaign_params
|
36
|
+
{
|
37
|
+
'name' => @ad_campaign_obj[:content_info][:name],
|
38
|
+
'verticals' => @ad_campaign_obj[:content_info][:verticals],
|
39
|
+
'offerIncentiveCategory' => @ad_campaign_obj[:content_info][:incentives],
|
40
|
+
'collectedFields' => @ad_campaign_obj[:content_info][:collected_fields],
|
41
|
+
'budget' => @ad_campaign_obj[:campaign_info][:spend],
|
42
|
+
'creativeGroups' => @creative_group_id
|
43
|
+
}
|
44
|
+
end
|
@@ -0,0 +1,106 @@
|
|
1
|
+
require 'faraday'
|
2
|
+
require 'json'
|
3
|
+
|
4
|
+
module AdLeads
|
5
|
+
class Client
|
6
|
+
attr_accessor *Configuration::VALID_CONFIG_KEYS
|
7
|
+
|
8
|
+
def initialize(options={})
|
9
|
+
merged_options = AdLeads.options.merge(options)
|
10
|
+
Configuration::VALID_CONFIG_KEYS.each do |key|
|
11
|
+
send("#{key}=", merged_options[key])
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def configure_campaign_signups(ad_campaign_id, etag, params = {})
|
16
|
+
path = "/campaigns/#{ad_campaign_id}/signupdelivery"
|
17
|
+
request(:post, path, params.merge(etag: etag))
|
18
|
+
end
|
19
|
+
|
20
|
+
def get_campaign_status(ad_campaign_id)
|
21
|
+
response = get("/campaigns/#{ad_campaign_id}")
|
22
|
+
JSON.parse(response.body)['status']
|
23
|
+
end
|
24
|
+
|
25
|
+
def get_reports(params)
|
26
|
+
get("/reports/campaign/report", params)
|
27
|
+
end
|
28
|
+
|
29
|
+
def pause_campaign(ad_campaign_id, etag)
|
30
|
+
path = "/campaigns/#{ad_campaign_id}/pause"
|
31
|
+
request(:post, path, etag: etag)
|
32
|
+
end
|
33
|
+
|
34
|
+
def get(path, params = {})
|
35
|
+
request(:get, path, params)
|
36
|
+
end
|
37
|
+
|
38
|
+
def post(path, params = {})
|
39
|
+
request(:post, path, params)
|
40
|
+
end
|
41
|
+
|
42
|
+
private
|
43
|
+
|
44
|
+
def etag_opts(etag)
|
45
|
+
{
|
46
|
+
headers: { 'If-Match' => etag },
|
47
|
+
multipart: true
|
48
|
+
}
|
49
|
+
end
|
50
|
+
|
51
|
+
def connection(opts = {})
|
52
|
+
opts[:headers] ||= { 'Accept' => 'application/json' }
|
53
|
+
|
54
|
+
Faraday.new(url: endpoint) do |faraday|
|
55
|
+
faraday.headers = opts[:headers]
|
56
|
+
faraday.request :multipart if opts[:multipart]
|
57
|
+
|
58
|
+
faraday.authorization :Bearer, token
|
59
|
+
faraday.adapter :httpclient
|
60
|
+
faraday.request :url_encoded
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def token
|
65
|
+
@token ||= AdLeads::Token.new(client_id: client_id, principle: principle).token
|
66
|
+
end
|
67
|
+
|
68
|
+
def request(method, path, params = {})
|
69
|
+
etag = params.delete(:etag)
|
70
|
+
opts = etag ? etag_opts(etag) : {}
|
71
|
+
|
72
|
+
response = connection(opts).send(method, path) do |request|
|
73
|
+
request.params = params if method == :get
|
74
|
+
request.body = params if method == :post
|
75
|
+
end
|
76
|
+
|
77
|
+
case response.status
|
78
|
+
when 401
|
79
|
+
raise AuthError.new(<<-ERROR)
|
80
|
+
token: #{token},
|
81
|
+
method: #{method},
|
82
|
+
endpoint: #{endpoint},
|
83
|
+
path: #{path}",
|
84
|
+
body: #{response.body}
|
85
|
+
ERROR
|
86
|
+
when 500
|
87
|
+
raise ApiError.new(<<-ERROR)
|
88
|
+
endpoint: #{endpoint},
|
89
|
+
method: #{method},
|
90
|
+
path: #{path}",
|
91
|
+
body: #{response.body}
|
92
|
+
ERROR
|
93
|
+
|
94
|
+
else
|
95
|
+
response
|
96
|
+
end
|
97
|
+
|
98
|
+
# rescue Faraday::Error::TimeoutError, Timeout::Error => error
|
99
|
+
# rescue Faraday::Error::ClientError, JSON::ParserError => error
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
class AuthError < StandardError; end
|
104
|
+
class ApiError < StandardError; end
|
105
|
+
end
|
106
|
+
2
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module AdLeads
|
2
|
+
module Configuration
|
3
|
+
|
4
|
+
def configure
|
5
|
+
yield self
|
6
|
+
end
|
7
|
+
|
8
|
+
VALID_CONNECTION_KEYS = [:endpoint, :token_endpoint, :user_agent].freeze
|
9
|
+
VALID_OPTIONS_KEYS = [:client_id, :private_key, :principle, :format].freeze
|
10
|
+
VALID_CONFIG_KEYS = VALID_CONNECTION_KEYS + VALID_OPTIONS_KEYS
|
11
|
+
|
12
|
+
DEFAULT_ENDPOINT = 'https://api.adleads.com'
|
13
|
+
DEFAULT_TOKEN_ENDPOINT = 'https://auth.adleads.com'
|
14
|
+
DEFAULT_USER_AGENT = "AdLeads API Ruby Gem #{AdLeads::VERSION}".freeze
|
15
|
+
|
16
|
+
DEFAULT_FORMAT = :json
|
17
|
+
DEFAULT_CLIENT_ID = 'client_id'
|
18
|
+
DEFAULT_PRINCIPLE = 'principle'
|
19
|
+
DEFAULT_PRIVATE_KEY = 'private_key'
|
20
|
+
|
21
|
+
attr_accessor *VALID_CONFIG_KEYS
|
22
|
+
|
23
|
+
# Make sure we have the default values set when we get 'extended'
|
24
|
+
def self.extended(base)
|
25
|
+
base.reset
|
26
|
+
end
|
27
|
+
|
28
|
+
def options
|
29
|
+
Hash[ * VALID_CONFIG_KEYS.map { |key| [key, send(key)] }.flatten ]
|
30
|
+
end
|
31
|
+
|
32
|
+
def reset
|
33
|
+
self.endpoint = DEFAULT_ENDPOINT
|
34
|
+
self.token_endpoint = DEFAULT_TOKEN_ENDPOINT
|
35
|
+
self.user_agent = DEFAULT_USER_AGENT
|
36
|
+
self.client_id = DEFAULT_CLIENT_ID
|
37
|
+
self.private_key = DEFAULT_PRIVATE_KEY
|
38
|
+
self.principle = DEFAULT_PRINCIPLE
|
39
|
+
self.format = DEFAULT_FORMAT
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module AdLeads::Etag
|
2
|
+
def etag_path
|
3
|
+
# must be implemented in including class
|
4
|
+
end
|
5
|
+
|
6
|
+
def refresh_etag!
|
7
|
+
@etag = client.get(etag_path).headers['Etag']
|
8
|
+
end
|
9
|
+
|
10
|
+
def etag
|
11
|
+
@etag ||= refresh_etag!
|
12
|
+
end
|
13
|
+
|
14
|
+
def with_etag(count = 1, &block)
|
15
|
+
raise MismatchError if count > 3
|
16
|
+
|
17
|
+
response = yield
|
18
|
+
count += 1
|
19
|
+
|
20
|
+
if response.status == 412
|
21
|
+
self.refresh_etag!
|
22
|
+
with_etag(count) do
|
23
|
+
yield
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
|
29
|
+
class MismatchError < StandardError; end
|
30
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
class AdLeads::Image < AdLeads::Base
|
2
|
+
include AdLeads::Etag
|
3
|
+
attr_accessor :creative_group_id, :ad_id
|
4
|
+
|
5
|
+
def initialize(opts)
|
6
|
+
@creative_group_id = opts[:creative_group_id]
|
7
|
+
@ad_id = opts[:ad_id]
|
8
|
+
end
|
9
|
+
|
10
|
+
def ids
|
11
|
+
{ group: creative_group_id, creative: ad_id }
|
12
|
+
end
|
13
|
+
|
14
|
+
def upload!(file)
|
15
|
+
with_etag do
|
16
|
+
client.post(image_upload_path, image_upload_params(file))
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def image_upload_params(file)
|
21
|
+
{
|
22
|
+
file: Faraday::UploadIO.new(file, 'image/jpeg'),
|
23
|
+
etag: etag
|
24
|
+
}
|
25
|
+
end
|
26
|
+
|
27
|
+
def image_upload_path
|
28
|
+
[
|
29
|
+
root_path,
|
30
|
+
id,
|
31
|
+
'file'
|
32
|
+
].join('/')
|
33
|
+
end
|
34
|
+
|
35
|
+
def etag_path
|
36
|
+
root_path + "/#{id}"
|
37
|
+
end
|
38
|
+
|
39
|
+
def root_path
|
40
|
+
[
|
41
|
+
'/creativegroups',
|
42
|
+
creative_group_id,
|
43
|
+
'creatives',
|
44
|
+
ad_id,
|
45
|
+
'images'
|
46
|
+
].join('/')
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module AdLeads
|
2
|
+
class Promotion
|
3
|
+
def self.promotion_params(deal)
|
4
|
+
{
|
5
|
+
account: {
|
6
|
+
external_id: deal.merchant_id,
|
7
|
+
dba: deal.dba,
|
8
|
+
name: deal.from_name,
|
9
|
+
email: deal.from_email,
|
10
|
+
description: deal.merchant_about,
|
11
|
+
website: deal.website,
|
12
|
+
address1: deal.location.address1,
|
13
|
+
address2: deal.location.address2,
|
14
|
+
city: deal.location.city,
|
15
|
+
state: deal.location.state,
|
16
|
+
zip: deal.location.zip,
|
17
|
+
phone: deal.location.phone,
|
18
|
+
country: deal.location.country,
|
19
|
+
facebook: deal.facebook_info,
|
20
|
+
twitter: deal.twitter_info
|
21
|
+
},
|
22
|
+
promotion: {
|
23
|
+
external_id: deal.id,
|
24
|
+
name: deal.name,
|
25
|
+
headline: deal.subject_line,
|
26
|
+
landing_page: deal.full_landing_page_preview_url,
|
27
|
+
landing_page_shortened: deal.shortened_lp_url,
|
28
|
+
spend: deal.distribution_price,
|
29
|
+
range: deal.distribution_range,
|
30
|
+
description: deal.deal_about,
|
31
|
+
kind: deal.deal_type,
|
32
|
+
state: deal.status,
|
33
|
+
time_start: deal.start_date,
|
34
|
+
time_end: deal.end_date,
|
35
|
+
}
|
36
|
+
}
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
module AdLeads
|
2
|
+
|
3
|
+
class Token
|
4
|
+
attr_accessor *Configuration::VALID_CONFIG_KEYS
|
5
|
+
|
6
|
+
def initialize(options={})
|
7
|
+
merged_options = AdLeads.options.merge(options)
|
8
|
+
Configuration::VALID_CONFIG_KEYS.each do |key|
|
9
|
+
send("#{key}=", merged_options[key])
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def assertion
|
14
|
+
claims = {
|
15
|
+
iss: client_id,
|
16
|
+
aud: endpoint,
|
17
|
+
prn: principle,
|
18
|
+
scope: 'campaign_read,campaign_write,reports',
|
19
|
+
exp: Time.now.utc.to_i + (5*60),
|
20
|
+
}
|
21
|
+
JWT.encode(claims, rsa_key, 'RS256')
|
22
|
+
end
|
23
|
+
|
24
|
+
def rsa_key
|
25
|
+
@rsa_key ||= OpenSSL::PKey::RSA.new(private_key)
|
26
|
+
end
|
27
|
+
|
28
|
+
def token
|
29
|
+
unless @token
|
30
|
+
response = connection.post('/oauth/token') do |conn|
|
31
|
+
conn.params = token_request_params
|
32
|
+
end
|
33
|
+
@token = JSON.parse(response.body)['access_token']
|
34
|
+
end
|
35
|
+
@token
|
36
|
+
end
|
37
|
+
|
38
|
+
def connection
|
39
|
+
@connection ||= Faraday.new(url: token_endpoint) do |faraday|
|
40
|
+
faraday.headers['Accept'] = 'application/json'
|
41
|
+
faraday.adapter :httpclient # make requests with Net::HTTP
|
42
|
+
faraday.request :url_encoded
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def token_request_params
|
47
|
+
{
|
48
|
+
grant_type: 'jwt-bearer',
|
49
|
+
assertion: assertion,
|
50
|
+
}
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
data/lib/ad_leads.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'jwt'
|
2
|
+
require 'ad_leads/version'
|
3
|
+
require 'ad_leads/configuration'
|
4
|
+
require 'ad_leads/client'
|
5
|
+
require 'ad_leads/token'
|
6
|
+
require 'ad_leads/base'
|
7
|
+
require 'ad_leads/etag'
|
8
|
+
require 'ad_leads/image'
|
9
|
+
require 'ad_leads/campaign'
|
10
|
+
require 'ad_leads/ad'
|
11
|
+
require 'ad_leads/creative_group'
|
12
|
+
|
13
|
+
module AdLeads
|
14
|
+
extend Configuration
|
15
|
+
# Your code goes here...
|
16
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe AdLeads::Ad do
|
4
|
+
let(:ad) { AdLeads::Ad.new(1) }
|
5
|
+
let(:client) { ad.client }
|
6
|
+
let(:params) { {} }
|
7
|
+
|
8
|
+
it 'inherits from AdLeads::Base' do
|
9
|
+
expect(ad.class.ancestors).to include AdLeads::Base
|
10
|
+
end
|
11
|
+
|
12
|
+
describe '#create!' do
|
13
|
+
it 'posts to Ad Leads ad endpoint for creatives' do
|
14
|
+
expect(client).to receive(:post).with('/creativegroups/1/creatives', params)
|
15
|
+
ad.create!(params)
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'assigns #response' do
|
19
|
+
client.stub(:post) { 'Foobar' }
|
20
|
+
ad.create!(params)
|
21
|
+
expect(ad.response).to eq 'Foobar'
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe AdLeads::Base do
|
4
|
+
let(:base) { AdLeads::Base.new() }
|
5
|
+
|
6
|
+
describe '#id' do
|
7
|
+
let(:response) { double(:response, body: '{ "data": [1] }') }
|
8
|
+
before { base.response = response }
|
9
|
+
|
10
|
+
it 'parses ID from JSON response body' do
|
11
|
+
expect(base.id).to eq 1
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
describe 'client' do
|
16
|
+
it 'returns an instance of AdLeads::Client' do
|
17
|
+
expect(base.client).to be_a AdLeads::Client
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe AdLeads::Campaign do
|
4
|
+
let(:campaign) { AdLeads::Campaign.new() }
|
5
|
+
let(:client) { campaign.client }
|
6
|
+
let(:params) { {} }
|
7
|
+
let(:http_success) { double(:http_success, status: 200) }
|
8
|
+
|
9
|
+
it 'inherits from AdLeads::Base' do
|
10
|
+
expect(campaign.class.ancestors).to include AdLeads::Base
|
11
|
+
end
|
12
|
+
|
13
|
+
describe '#create!' do
|
14
|
+
it 'posts to AdLeads::Campaign#root_path' do
|
15
|
+
expect(client).to receive(:post).with('/campaigns', params)
|
16
|
+
campaign.create!(params)
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'assigns #response' do
|
20
|
+
client.stub(:post) { 'Foobar' }
|
21
|
+
campaign.create!(params)
|
22
|
+
expect(campaign.response).to eq 'Foobar'
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
describe '#update!' do
|
27
|
+
before { campaign.instance_variable_set(:@id, 1) }
|
28
|
+
|
29
|
+
it 'posts to AdLeads::Campaign#campaign_path' do
|
30
|
+
expect(client).to receive(:post).with('/campaigns/1', params)
|
31
|
+
campaign.update!(params)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
describe '#verify!' do
|
36
|
+
before { campaign.instance_variable_set(:@id, 1) }
|
37
|
+
|
38
|
+
it 'sends a GET request to AdLeads::Campaign#verify_campaign_path' do
|
39
|
+
expect(client).to receive(:get).with('/campaigns/1/plan')
|
40
|
+
campaign.verify!
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
describe '#launch!' do
|
45
|
+
before do
|
46
|
+
campaign.stub(:id) { 1 }
|
47
|
+
campaign.stub(:etag) { 'Fake etag' }
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'posts to AdLeads::Campaign#launch_campaign_path' do
|
51
|
+
expect(client).to receive(:post).with('/campaigns/1/launch', { etag: 'Fake etag'}).and_return(http_success)
|
52
|
+
campaign.launch!
|
53
|
+
end
|
54
|
+
|
55
|
+
it 'uses #with_etag block' do
|
56
|
+
client.stub(:post)
|
57
|
+
expect(campaign).to receive(:with_etag)
|
58
|
+
campaign.launch!
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
describe '#etag_path' do
|
63
|
+
before { campaign.instance_variable_set(:@id, 1) }
|
64
|
+
|
65
|
+
it 'is an alias for #campaign_path' do
|
66
|
+
expect(campaign.etag_path).to eq campaign.campaign_path
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'pry'
|
3
|
+
|
4
|
+
describe AdLeads::Client do
|
5
|
+
let(:client) { AdLeads::Client.new }
|
6
|
+
let(:connection) { double(:faraday_connection) }
|
7
|
+
let(:token) { '2f7622c3-da63-42e9-a3d8-4275f70f1f79' }
|
8
|
+
let(:status) { 200 }
|
9
|
+
let(:response) { double(:http_response, status: status, body: {}, headers: {}) }
|
10
|
+
|
11
|
+
before { client.stub(:token) { token } }
|
12
|
+
|
13
|
+
describe '#connection' do
|
14
|
+
let(:config_keys) { AdLeads::Configuration::VALID_CONFIG_KEYS }
|
15
|
+
|
16
|
+
it 'inherits config' do
|
17
|
+
expect(client).to respond_to(config_keys.sample)
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'calls token' do
|
21
|
+
expect(client).to receive(:token).and_return('xyz')
|
22
|
+
client.send(:connection)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
describe '#request' do
|
27
|
+
before do
|
28
|
+
Faraday.stub(:new) { connection }
|
29
|
+
connection.stub(:post) { response }
|
30
|
+
end
|
31
|
+
|
32
|
+
context 'status: 500' do
|
33
|
+
let(:status) { 500 }
|
34
|
+
it 'raises AdLeads::ApiError' do
|
35
|
+
expect {
|
36
|
+
client.post('foo')
|
37
|
+
}.to raise_error AdLeads::ApiError
|
38
|
+
end
|
39
|
+
end
|
40
|
+
context 'status: 401' do
|
41
|
+
let(:status) { 401 }
|
42
|
+
it 'raises AdLeads::ApiError' do
|
43
|
+
expect {
|
44
|
+
client.post('foo')
|
45
|
+
}.to raise_error AdLeads::AuthError
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
describe 'configuration' do
|
2
|
+
|
3
|
+
let(:keys) { AdLeads::Configuration::VALID_CONFIG_KEYS }
|
4
|
+
let(:key) { keys.sample }
|
5
|
+
|
6
|
+
after { AdLeads.reset }
|
7
|
+
|
8
|
+
it 'sets config keys' do
|
9
|
+
AdLeads.configure do |config|
|
10
|
+
config.public_send("#{key}=", key)
|
11
|
+
expect(AdLeads.public_send(key)).to eq key
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'returns default values' do
|
16
|
+
keys.each do |key|
|
17
|
+
expect(AdLeads.send(key)).to eq AdLeads::Configuration.
|
18
|
+
const_get("DEFAULT_#{key.upcase}")
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
describe '#client_id' do
|
23
|
+
it 'should return default key' do
|
24
|
+
expect(AdLeads.client_id).to eq AdLeads::Configuration::DEFAULT_CLIENT_ID
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
describe '#principle' do
|
29
|
+
it 'should return default key' do
|
30
|
+
expect(AdLeads.principle).to eq AdLeads::Configuration::DEFAULT_PRINCIPLE
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
describe '#format' do
|
35
|
+
it 'should return default format' do
|
36
|
+
expect(AdLeads.format).to eq AdLeads::Configuration::DEFAULT_FORMAT
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
describe '#user_agent' do
|
41
|
+
it 'should return default user agent' do
|
42
|
+
expect(AdLeads.user_agent).to eq AdLeads::Configuration::DEFAULT_USER_AGENT
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe AdLeads::CreativeGroup do
|
4
|
+
let(:creative_group) { AdLeads::CreativeGroup.new }
|
5
|
+
let(:client) { creative_group.client }
|
6
|
+
let(:params) {{}}
|
7
|
+
|
8
|
+
it 'inherits from AdLeads::Base' do
|
9
|
+
expect(creative_group.class.ancestors).to include AdLeads::Base
|
10
|
+
end
|
11
|
+
|
12
|
+
describe '#create!' do
|
13
|
+
it 'posts to /creativegroups path' do
|
14
|
+
expect(client).to receive(:post).with('/creativegroups', params)
|
15
|
+
creative_group.create!(params)
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'assigns #response' do
|
19
|
+
client.stub(:post) { 'Foobar' }
|
20
|
+
creative_group.create!(params)
|
21
|
+
expect(creative_group.response).to eq 'Foobar'
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
# TODO: Extract Etag specs!
|
4
|
+
|
5
|
+
describe AdLeads::Image do
|
6
|
+
let(:image) { AdLeads::Image.new( {creative_group_id: 1, ad_id: 1} ) }
|
7
|
+
let(:client) { image.client }
|
8
|
+
let(:params) { {} }
|
9
|
+
let(:success) { double(:http_response, status: 200) }
|
10
|
+
let(:etag_mismatch) { double(:http_response, status: 412) }
|
11
|
+
let(:new_etag) { double(:http_response, status: 200, headers: { 'Etag' => '123'} ) }
|
12
|
+
|
13
|
+
it 'inherits from AdLeads::Base' do
|
14
|
+
expect(image.class.ancestors).to include AdLeads::Base
|
15
|
+
end
|
16
|
+
|
17
|
+
describe '#create!' do
|
18
|
+
it 'posts to AdLeads::Image endpoint' do
|
19
|
+
expect(client).to receive(:post).with('/creativegroups/1/creatives/1/images', params)
|
20
|
+
image.create!(params)
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'assigns #response' do
|
24
|
+
client.stub(:post) { 'Foobar' }
|
25
|
+
image.create!(params)
|
26
|
+
expect(image.response).to eq 'Foobar'
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
describe '#refresh_etag' do
|
31
|
+
before { image.stub(:etag_path) { '/foo' } }
|
32
|
+
it 'sets @etag from response headers' do
|
33
|
+
expect(client).to receive(:get).with('/foo').and_return(new_etag)
|
34
|
+
image.refresh_etag!
|
35
|
+
expect(image.etag).to eq '123'
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
describe '#upload!' do
|
40
|
+
let(:file) { './spec/fixtures/test.jpg' }
|
41
|
+
before do
|
42
|
+
image.stub(:etag) { 'Fake etag' }
|
43
|
+
image.stub(:id) { 1 }
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'posts to AdLeads::Image#image_upload_path' do
|
47
|
+
image.stub(:image_upload_params) {{}}
|
48
|
+
expect(client).to receive(:post).
|
49
|
+
with('/creativegroups/1/creatives/1/images/1/file', params).
|
50
|
+
and_return(success)
|
51
|
+
image.upload!(file)
|
52
|
+
end
|
53
|
+
|
54
|
+
context 'with Etag mismatch' do
|
55
|
+
it 'retries post' do
|
56
|
+
expect(client).to receive(:post).once.and_return(etag_mismatch)
|
57
|
+
expect(image).to receive(:refresh_etag!).and_return(1)
|
58
|
+
expect(client).to receive(:post).once.and_return(success)
|
59
|
+
image.upload!(file)
|
60
|
+
end
|
61
|
+
|
62
|
+
it 'raises EtagMismatchError' do
|
63
|
+
client.stub(:post) { etag_mismatch }
|
64
|
+
client.stub(:get) { new_etag }
|
65
|
+
expect {
|
66
|
+
image.upload!(file)
|
67
|
+
}.to raise_error AdLeads::Etag::MismatchError
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe AdLeads::Client do
|
4
|
+
let!(:client) { AdLeads::Client.new }
|
5
|
+
let(:connection) { client.connection }
|
6
|
+
let(:creative_group_id) { 12858 }
|
7
|
+
let(:token) { '99d3492c-f82e-40c1-ac12-95a3c3326edc' }
|
8
|
+
let(:file) { './spec/fixtures/test.jpg' }
|
9
|
+
|
10
|
+
before do
|
11
|
+
client.stub(:token).and_return(token)
|
12
|
+
AdLeads::Client.stub(:new) { client }
|
13
|
+
end
|
14
|
+
|
15
|
+
context 'Network Requests' do
|
16
|
+
describe 'Ad Campaign' do
|
17
|
+
xit 'uploads logo image, creates campaign using logo image, verifies and launches ad campaign' do
|
18
|
+
|
19
|
+
params = {
|
20
|
+
'name' => 'Creative Group Name',
|
21
|
+
'productName' => 'amazing product',
|
22
|
+
'privacyPolicyUrl' => 'http://privacy_url'
|
23
|
+
}
|
24
|
+
|
25
|
+
creative_group = AdLeads::CreativeGroup.new
|
26
|
+
creative_group.create!(params)
|
27
|
+
|
28
|
+
params = {
|
29
|
+
'type' => 'Mobile',
|
30
|
+
'name' => 'Ad name',
|
31
|
+
'headerText' => 'get your ad on this phone today',
|
32
|
+
'bodyText' => 'this is mobile ad body copy'
|
33
|
+
}
|
34
|
+
|
35
|
+
ad = AdLeads::Ad.new(creative_group.id)
|
36
|
+
ad.create!(params)
|
37
|
+
|
38
|
+
params = { 'type' => 'LogoImage' }
|
39
|
+
|
40
|
+
image = AdLeads::Image.new( { creative_group_id: creative_group.id, ad_id: ad.id } )
|
41
|
+
image.create!(params)
|
42
|
+
image.upload!(file)
|
43
|
+
|
44
|
+
params = {
|
45
|
+
'name' => 'Campaign name',
|
46
|
+
'verticals' => 82,
|
47
|
+
'offerIncentiveCategory' => 5,
|
48
|
+
'collectedFields' => 'firstname,lastname,email,companyname',
|
49
|
+
'budget' => 50,
|
50
|
+
'creativeGroups' => creative_group.id
|
51
|
+
}
|
52
|
+
|
53
|
+
campaign = AdLeads::Campaign.new
|
54
|
+
campaign.create!(params)
|
55
|
+
campaign.verify!
|
56
|
+
campaign.launch!
|
57
|
+
|
58
|
+
expect(campaign.response.status).to eq(200)
|
59
|
+
expect(JSON.parse(campaign.response.body)['result']).to eq true
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
@@ -0,0 +1,97 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe AdLeads::Token do
|
4
|
+
let(:config_keys) { AdLeads::Configuration::VALID_CONFIG_KEYS }
|
5
|
+
let(:token) { AdLeads::Token.new }
|
6
|
+
let(:private_key) { <<-PRIVATE_KEY }
|
7
|
+
-----BEGIN RSA PRIVATE KEY-----
|
8
|
+
MIICXAIBAAKBgQCOcCBGAtoZrwaN068x87WjW0x7GcYh5hXRN7I5Ib30MqT/jz9X
|
9
|
+
AzX9WTg5Cqm+2EYSxlOi+Inoqoz1fILKGuxVnC+R7bWNrRTPWzzd4mAsfUw1Sr7c
|
10
|
+
h9055f0l5BgdBZ4QAoa/9p7avZhKmX+x3pyLZ6EzMXbALoJsQGojmfzotwIDAQAB
|
11
|
+
AoGAQlNZ49/uGSmUHrSkjtkSCng3+9Z7mUtfe2W4+ruIjU6L4GiesPDQ0iEaeg1K
|
12
|
+
D5D7yEBLr8aVyR6ptqH88QlqZJzWtOwA39+9o/HyR9tl9Py7CpMYAUIqTqLHds0r
|
13
|
+
E662oal2A2EZER0iJY3qFAbW8TlGtLSFb4vwvcQmIWl2Q/kCQQDJe9DGN5bySzgD
|
14
|
+
uD8v091Q0tDDCWG/zYkTcMT2Ii2K6tqd4AlYHaJ3wtgOhvFIbOfMqyk2YBgmfRVf
|
15
|
+
DNV4OHdtAkEAtPpj0sJB/Q3tv+ftgzqGIZOygs4UtsRtqUh96nJiUsIrxT4BkD+e
|
16
|
+
LYeCkJytfHMZ3CR0ReGuRPiiAtQAZYjWMwJBAKiZtH16HRUJvojWUAG8v3EXyFu8
|
17
|
+
6RAwdSlQb3Er7oJVvrTnucoDmmWvJU8auqOJhnstK2J2DR+AAjc0rRlZ3w0CQEmx
|
18
|
+
+Ho3TmW8iUbvK6GXcE019qgbQQYXwMwBT/zrLSykEuzTzhEuRrwlhT5b/q1BtZMW
|
19
|
+
aR6Xwr4lPNvH9o1iBk8CQHdh405KMMAZZOsXccXqpgxUl90lTpM0p+cQERLGHmtR
|
20
|
+
OAQfFNhtZpgvPM/VALKb/RfJ7dWJzT9OMnVgtDyNsD8=
|
21
|
+
-----END RSA PRIVATE KEY-----
|
22
|
+
PRIVATE_KEY
|
23
|
+
let(:rsa_key) {
|
24
|
+
OpenSSL::PKey::RSA.new private_key
|
25
|
+
}
|
26
|
+
|
27
|
+
before { token.stub(:private_key) { private_key } }
|
28
|
+
|
29
|
+
it 'inherits config' do
|
30
|
+
expect(token).to respond_to(config_keys.sample)
|
31
|
+
end
|
32
|
+
|
33
|
+
describe '#assertion' do
|
34
|
+
let(:claims) {{
|
35
|
+
iss: token.client_id,
|
36
|
+
aud: token.endpoint,
|
37
|
+
prn: token.principle,
|
38
|
+
scope: 'campaign_read,campaign_write,reports',
|
39
|
+
exp: Time.now.utc.to_i + (5*60)
|
40
|
+
}}
|
41
|
+
|
42
|
+
it 'JWT should receive encode with correct params' do
|
43
|
+
expect(JWT).to receive(:encode).with(claims, an_instance_of(OpenSSL::PKey::RSA), 'RS256')
|
44
|
+
token.assertion
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
describe '#rsa_key' do
|
49
|
+
it 'RSA should initialize with new file' do
|
50
|
+
expect(OpenSSL::PKey::RSA).to receive(:new).with private_key
|
51
|
+
token.rsa_key
|
52
|
+
end
|
53
|
+
|
54
|
+
it 'should memoize the result' do
|
55
|
+
token.instance_variable_set(:@rsa_key, 'Foobar')
|
56
|
+
expect(OpenSSL::PKey::RSA).not_to receive(:new).with private_key
|
57
|
+
token.rsa_key
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
describe '#token' do
|
62
|
+
context '@token is set' do
|
63
|
+
it 'returns @token' do
|
64
|
+
token.instance_variable_set(:@token, 'Foobar')
|
65
|
+
expect(token.token).to eq 'Foobar'
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
context '@token is not set' do
|
70
|
+
let(:response) { double(:response_mock, body: '{ "access_token": "Foobar" }') }
|
71
|
+
|
72
|
+
it 'connection should receive post' do
|
73
|
+
expect(token.connection).to receive(:post).with('/oauth/token') { response }
|
74
|
+
token.token
|
75
|
+
end
|
76
|
+
|
77
|
+
it 'assigns token from response' do
|
78
|
+
token.connection.stub(:post) { response }
|
79
|
+
expect(token.token).to eq 'Foobar'
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
describe '#token_request_params' do
|
85
|
+
let(:assertion) { 'Foobar' }
|
86
|
+
before { token.stub(:assertion) { assertion } }
|
87
|
+
|
88
|
+
it 'is valid' do
|
89
|
+
expect(token.token_request_params).to eq({
|
90
|
+
grant_type: 'jwt-bearer',
|
91
|
+
assertion: assertion
|
92
|
+
})
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
it 'uses AdLeads::Client.connection'
|
97
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
{
|
2
|
+
creative_group_info: {
|
3
|
+
'name' => 'Creative Group Name',
|
4
|
+
'productName' => promotion.name,
|
5
|
+
'privacyPolicyUrl' => 'http://privacy_url' # ask dave
|
6
|
+
},
|
7
|
+
ad_info: {
|
8
|
+
'type' => ad_content.kind,
|
9
|
+
'name' => ad_content.name,
|
10
|
+
'headerText' => ad_content.header,
|
11
|
+
'bodyText' => ad_content.body
|
12
|
+
},
|
13
|
+
image_info: {
|
14
|
+
'type' => image.kind
|
15
|
+
},
|
16
|
+
campaign_info: {
|
17
|
+
'name' => ad_campaign.name,
|
18
|
+
'verticals' => ad_campaign.verticals,
|
19
|
+
'offerIncentiveCategory' => ad_campaign.offer_incentive_category,
|
20
|
+
'collectedFields' => ad_campaign.collected_fields,
|
21
|
+
'budget' => ad_campaign.spend,
|
22
|
+
'creativeGroups' => creative_group.id
|
23
|
+
}
|
24
|
+
}
|
Binary file
|
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,187 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: ad_leads
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.2
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Dinshaw
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-06-05 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: faraday
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - '='
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 0.9.0
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - '='
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 0.9.0
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: httpclient
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - '='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 2.3.4.1
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - '='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 2.3.4.1
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: jwt
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - '='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 0.1.11
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - '='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 0.1.11
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rspec
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '2.14'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '2.14'
|
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.5'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '1.5'
|
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: pry
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
description:
|
112
|
+
email:
|
113
|
+
- dgobhai@constantcontact.com
|
114
|
+
executables: []
|
115
|
+
extensions: []
|
116
|
+
extra_rdoc_files: []
|
117
|
+
files:
|
118
|
+
- ".gitignore"
|
119
|
+
- Gemfile
|
120
|
+
- LICENSE.txt
|
121
|
+
- README.md
|
122
|
+
- Rakefile
|
123
|
+
- ad_leads.gemspec
|
124
|
+
- lib/ad_leads.rb
|
125
|
+
- lib/ad_leads/ad.rb
|
126
|
+
- lib/ad_leads/base.rb
|
127
|
+
- lib/ad_leads/campaign.rb
|
128
|
+
- lib/ad_leads/campaign_helpers.rb
|
129
|
+
- lib/ad_leads/client.rb
|
130
|
+
- lib/ad_leads/configuration.rb
|
131
|
+
- lib/ad_leads/creative_group.rb
|
132
|
+
- lib/ad_leads/etag.rb
|
133
|
+
- lib/ad_leads/image.rb
|
134
|
+
- lib/ad_leads/promotion.rb
|
135
|
+
- lib/ad_leads/token.rb
|
136
|
+
- lib/ad_leads/version.rb
|
137
|
+
- spec/ad_leads/ad_spec.rb
|
138
|
+
- spec/ad_leads/base_spec.rb
|
139
|
+
- spec/ad_leads/campaign_spec.rb
|
140
|
+
- spec/ad_leads/client_spec.rb
|
141
|
+
- spec/ad_leads/configuration_spec.rb
|
142
|
+
- spec/ad_leads/creative_group_spec.rb
|
143
|
+
- spec/ad_leads/image_spec.rb
|
144
|
+
- spec/ad_leads/network_requests_redux_spec.rb
|
145
|
+
- spec/ad_leads/token_spec.rb
|
146
|
+
- spec/ad_leads/version_spec.rb
|
147
|
+
- spec/fixtures/ad_campaign_obj.rb
|
148
|
+
- spec/fixtures/test.jpg
|
149
|
+
- spec/spec_helper.rb
|
150
|
+
homepage: ''
|
151
|
+
licenses:
|
152
|
+
- MIT
|
153
|
+
metadata: {}
|
154
|
+
post_install_message:
|
155
|
+
rdoc_options: []
|
156
|
+
require_paths:
|
157
|
+
- lib
|
158
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
159
|
+
requirements:
|
160
|
+
- - ">="
|
161
|
+
- !ruby/object:Gem::Version
|
162
|
+
version: '0'
|
163
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
164
|
+
requirements:
|
165
|
+
- - ">="
|
166
|
+
- !ruby/object:Gem::Version
|
167
|
+
version: '0'
|
168
|
+
requirements: []
|
169
|
+
rubyforge_project:
|
170
|
+
rubygems_version: 2.2.0
|
171
|
+
signing_key:
|
172
|
+
specification_version: 4
|
173
|
+
summary: Ruby Wrapper for AdLeads API
|
174
|
+
test_files:
|
175
|
+
- spec/ad_leads/ad_spec.rb
|
176
|
+
- spec/ad_leads/base_spec.rb
|
177
|
+
- spec/ad_leads/campaign_spec.rb
|
178
|
+
- spec/ad_leads/client_spec.rb
|
179
|
+
- spec/ad_leads/configuration_spec.rb
|
180
|
+
- spec/ad_leads/creative_group_spec.rb
|
181
|
+
- spec/ad_leads/image_spec.rb
|
182
|
+
- spec/ad_leads/network_requests_redux_spec.rb
|
183
|
+
- spec/ad_leads/token_spec.rb
|
184
|
+
- spec/ad_leads/version_spec.rb
|
185
|
+
- spec/fixtures/ad_campaign_obj.rb
|
186
|
+
- spec/fixtures/test.jpg
|
187
|
+
- spec/spec_helper.rb
|