expertsender_api 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +14 -0
- data/Gemfile +3 -0
- data/README.md +3 -0
- data/Rakefile +11 -0
- data/expertsender_api.gemspec +26 -0
- data/lib/expertsender_api.rb +22 -0
- data/lib/expertsender_api/api.rb +190 -0
- data/lib/expertsender_api/concerns/serializeable.rb +21 -0
- data/lib/expertsender_api/email.rb +5 -0
- data/lib/expertsender_api/email/content.rb +23 -0
- data/lib/expertsender_api/email/receiver.rb +22 -0
- data/lib/expertsender_api/email/recipients.rb +23 -0
- data/lib/expertsender_api/email/snippet.rb +27 -0
- data/lib/expertsender_api/expertsender_error.rb +5 -0
- data/lib/expertsender_api/result.rb +64 -0
- data/lib/expertsender_api/subscriber.rb +5 -0
- data/lib/expertsender_api/subscriber/property.rb +27 -0
- data/lib/expertsender_api/subscriber/tag.rb +47 -0
- data/spec/expertsender_api/api_spec.rb +232 -0
- data/spec/expertsender_api/email/content_spec.rb +41 -0
- data/spec/expertsender_api/email/receiver_spec.rb +33 -0
- data/spec/expertsender_api/email/recipients_spec.rb +30 -0
- data/spec/expertsender_api/email/snippet_spec.rb +30 -0
- data/spec/expertsender_api/subscriber/property_spec.rb +33 -0
- data/spec/expertsender_api/subscriber/tag_spec.rb +60 -0
- data/spec/spec_helper.rb +12 -0
- metadata +134 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 38a52cdaf7f8d15625b76d4fa4032729a903b341
|
4
|
+
data.tar.gz: a3a9ff5795c99eb610e10977d5e3996ce0ff3bb7
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 5d995b6cafc6e7208646554f105861909c3401e160cb1e80ecfe28079415881374e64ac1a61a6b05bd6e8fbd010bcbed0e8d6bfb9adadc8babb861e8905e7878
|
7
|
+
data.tar.gz: 68e2f8414cf3d93a119c8f93ac8d5941df52d9c7b6acd147812dd7086c1b240849e94005d01a4f9ecd562c79aa0b963f5ad8b4b6b8366c03e57613b26fa27d47
|
data/.gitignore
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
# See http://help.github.com/ignore-files/ for more about ignoring files.
|
2
|
+
#
|
3
|
+
# If you find yourself ignoring temporary files generated by your text editor
|
4
|
+
# or operating system, you probably want to add a global ignore instead:
|
5
|
+
# git config --global core.excludesfile ~/.gitignore_global
|
6
|
+
|
7
|
+
# Ignore bundler config
|
8
|
+
/.bundle
|
9
|
+
/Gemfile.lock
|
10
|
+
/gems
|
11
|
+
/tags
|
12
|
+
|
13
|
+
*.swp
|
14
|
+
.ruby-version
|
data/Gemfile
ADDED
data/README.md
ADDED
data/Rakefile
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rspec/core/rake_task'
|
3
|
+
require 'rubygems/specification'
|
4
|
+
require 'bundler/gem_tasks'
|
5
|
+
|
6
|
+
task :default => :spec
|
7
|
+
desc "Run specs"
|
8
|
+
RSpec::Core::RakeTask.new do |t|
|
9
|
+
t.pattern = FileList['spec/**/*_spec.rb']
|
10
|
+
t.rspec_opts = %w(-fs --color)
|
11
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
$:.push File.expand_path("../lib", __FILE__)
|
2
|
+
|
3
|
+
Gem::Specification.new do |s|
|
4
|
+
s.name = "expertsender_api"
|
5
|
+
s.version = "0.0.1"
|
6
|
+
s.authors = ["kinderly"]
|
7
|
+
s.email = ["beorc@httplab.ru"]
|
8
|
+
s.homepage = "http://github.com/kinderly/expertsender_api"
|
9
|
+
|
10
|
+
s.summary = %q{A wrapper for ExpertSender API}
|
11
|
+
s.description = %q{A wrapper for ExpertSender API}
|
12
|
+
s.license = "MIT"
|
13
|
+
|
14
|
+
s.rubyforge_project = "expertsender_api"
|
15
|
+
|
16
|
+
s.files = `git ls-files`.split("\n")
|
17
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
18
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
19
|
+
s.require_paths = ["lib"]
|
20
|
+
|
21
|
+
s.add_dependency('httparty')
|
22
|
+
s.add_dependency('nokogiri')
|
23
|
+
|
24
|
+
s.add_development_dependency 'rake'
|
25
|
+
s.add_development_dependency "rspec"
|
26
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'httparty'
|
2
|
+
require 'nokogiri'
|
3
|
+
require 'cgi'
|
4
|
+
|
5
|
+
require 'expertsender_api/email'
|
6
|
+
require 'expertsender_api/concerns/serializeable'
|
7
|
+
|
8
|
+
require 'expertsender_api/subscriber'
|
9
|
+
require 'expertsender_api/subscriber/tag'
|
10
|
+
require 'expertsender_api/subscriber/property'
|
11
|
+
require 'expertsender_api/email/recipients'
|
12
|
+
require 'expertsender_api/email/receiver'
|
13
|
+
require 'expertsender_api/email/content'
|
14
|
+
require 'expertsender_api/email/snippet'
|
15
|
+
require 'expertsender_api/result'
|
16
|
+
require 'expertsender_api/expertsender_error'
|
17
|
+
|
18
|
+
require 'expertsender_api/api'
|
19
|
+
|
20
|
+
|
21
|
+
module ExpertSenderApi
|
22
|
+
end
|
@@ -0,0 +1,190 @@
|
|
1
|
+
module ExpertSenderApi
|
2
|
+
class API
|
3
|
+
include HTTParty
|
4
|
+
|
5
|
+
class << self
|
6
|
+
attr_accessor :api_key, :api_endpoint, :throws_exceptions
|
7
|
+
end
|
8
|
+
|
9
|
+
attr_accessor :api_key, :api_endpoint, :throws_exceptions
|
10
|
+
|
11
|
+
SUBSCRIBER_INFO_OPTION_SHORT = 1
|
12
|
+
SUBSCRIBER_INFO_OPTION_MEDIUM = 2
|
13
|
+
SUBSCRIBER_INFO_OPTION_FULL = 3
|
14
|
+
|
15
|
+
XML_NAMESPACES = { 'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
|
16
|
+
'xmlns:xs' => 'http://www.w3.org/2001/XMLSchema' }
|
17
|
+
|
18
|
+
def initialize(key: nil, **parameters)
|
19
|
+
@api_key = key || self.class.api_key || ENV['EXPERTSENDER_API_KEY']
|
20
|
+
@api_key = @api_key.strip if @api_key
|
21
|
+
|
22
|
+
@throws_exceptions = parameters.has_key?(:throws_exceptions) ? parameters.delete(:throws_exceptions) : self.class.throws_exceptions
|
23
|
+
@api_endpoint = parameters.delete(:api_endpoint) || self.class.api_endpoint
|
24
|
+
|
25
|
+
unless api_endpoint.nil?
|
26
|
+
@subscribers_url = api_endpoint + '/Api/Subscribers'
|
27
|
+
@removed_subscribers_url = api_endpoint + '/Api/RemovedSubscribers'
|
28
|
+
@newsletters_url = api_endpoint + '/Api/Newsletters'
|
29
|
+
@transactionals_url = api_endpoint + '/Api/Transactionals'
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def add_subscriber_to_list(subscriber)
|
34
|
+
add_subscribers_to_list([subscriber])
|
35
|
+
end
|
36
|
+
|
37
|
+
def add_subscribers_to_list(subscribers)
|
38
|
+
builder = Nokogiri::XML::Builder.new do |xml|
|
39
|
+
xml.ApiRequest(XML_NAMESPACES) {
|
40
|
+
xml.ApiKey api_key
|
41
|
+
xml.MultiData {
|
42
|
+
subscribers.each { |subscriber| subscriber.insert_to(xml) }
|
43
|
+
}
|
44
|
+
}
|
45
|
+
end
|
46
|
+
|
47
|
+
xml = builder.to_xml save_with: Nokogiri::XML::Node::SaveOptions::NO_DECLARATION
|
48
|
+
response = self.class.post(@subscribers_url, body: xml)
|
49
|
+
|
50
|
+
handle_response(response)
|
51
|
+
end
|
52
|
+
|
53
|
+
def remove_subscriber_from_list(options)
|
54
|
+
email = options.delete :email
|
55
|
+
id = options.delete :id
|
56
|
+
|
57
|
+
response = id.nil? ? remove_subscriber_by_email(email, options) : remove_subscriber_by_id(id, options)
|
58
|
+
|
59
|
+
handle_response(response)
|
60
|
+
end
|
61
|
+
|
62
|
+
def get_subscriber_info(option: SUBSCRIBER_INFO_OPTION_FULL, email: nil)
|
63
|
+
params = { apiKey: api_key, email: email, option: option }
|
64
|
+
|
65
|
+
response = self.class.get(@subscribers_url, query: params)
|
66
|
+
|
67
|
+
handle_response(response)
|
68
|
+
end
|
69
|
+
|
70
|
+
def update_subscriber(email, subscriber)
|
71
|
+
result = get_subscriber_info(email: email)
|
72
|
+
|
73
|
+
return result if result.failed?
|
74
|
+
|
75
|
+
expertsender_id = result.parsed_response.xpath('//Data/Id').text
|
76
|
+
list_ids = result.parsed_response.xpath('//StateOnList/ListId').map(&:text)
|
77
|
+
|
78
|
+
subscriber.id = expertsender_id
|
79
|
+
|
80
|
+
list_ids.each do |list_id|
|
81
|
+
subscriber.list_id = list_id
|
82
|
+
res = add_subscriber_to_list(subscriber)
|
83
|
+
end
|
84
|
+
|
85
|
+
result
|
86
|
+
end
|
87
|
+
|
88
|
+
def add_or_update_subscriber(email, subscriber)
|
89
|
+
result = update_subscriber(email, subscriber)
|
90
|
+
|
91
|
+
return add_subscriber_to_list(subscriber) if result.failed?
|
92
|
+
|
93
|
+
result
|
94
|
+
end
|
95
|
+
|
96
|
+
def create_and_send_email(options)
|
97
|
+
recipients = options.delete :recipients
|
98
|
+
content = options.delete :content
|
99
|
+
|
100
|
+
builder = Nokogiri::XML::Builder.new do |xml|
|
101
|
+
xml.ApiRequest(XML_NAMESPACES) {
|
102
|
+
xml.ApiKey api_key
|
103
|
+
xml.Data {
|
104
|
+
recipients.insert_to xml
|
105
|
+
content.insert_to xml
|
106
|
+
}
|
107
|
+
}
|
108
|
+
end
|
109
|
+
|
110
|
+
xml = builder.to_xml save_with: Nokogiri::XML::Node::SaveOptions::NO_DECLARATION
|
111
|
+
response = self.class.post(@newsletters_url, body: xml)
|
112
|
+
|
113
|
+
handle_response(response)
|
114
|
+
end
|
115
|
+
|
116
|
+
def send_transaction_email(options)
|
117
|
+
letter_id = options.delete :letter_id
|
118
|
+
receiver = options.delete :receiver
|
119
|
+
snippets = options.delete :snippets
|
120
|
+
|
121
|
+
builder = Nokogiri::XML::Builder.new do |xml|
|
122
|
+
xml.ApiRequest(XML_NAMESPACES) {
|
123
|
+
xml.ApiKey api_key
|
124
|
+
xml.Data {
|
125
|
+
receiver.insert_to xml
|
126
|
+
if snippets.any?
|
127
|
+
xml.Snippets {
|
128
|
+
snippets.each { |snippet| snippet.insert_to(xml) }
|
129
|
+
}
|
130
|
+
end
|
131
|
+
}
|
132
|
+
}
|
133
|
+
end
|
134
|
+
|
135
|
+
xml = builder.to_xml save_with: Nokogiri::XML::Node::SaveOptions::NO_DECLARATION
|
136
|
+
response = self.class.post("#{@transactionals_url}/#{letter_id}", body: xml)
|
137
|
+
|
138
|
+
handle_response(response)
|
139
|
+
end
|
140
|
+
|
141
|
+
def get_deleted_subscribers(options = {})
|
142
|
+
params = { apiKey: api_key }
|
143
|
+
|
144
|
+
list_ids = options[:list_ids]
|
145
|
+
remove_types = options[:remove_types]
|
146
|
+
start_date = options[:start_date]
|
147
|
+
end_date = options[:end_date]
|
148
|
+
|
149
|
+
params[:listIds] = list_ids.join(',') if list_ids.respond_to?(:any?)
|
150
|
+
params[:removeTypes] = remove_types.join(',') if remove_types.respond_to?(:any?)
|
151
|
+
params[:startDate] = start_date.to_s unless start_date.nil?
|
152
|
+
params[:endDate] = end_date.to_s unless end_date.nil?
|
153
|
+
|
154
|
+
response = self.class.get(@removed_subscribers_url, query: params)
|
155
|
+
|
156
|
+
handle_response(response)
|
157
|
+
end
|
158
|
+
|
159
|
+
private
|
160
|
+
|
161
|
+
def handle_response(response)
|
162
|
+
result = Result.new(response)
|
163
|
+
|
164
|
+
if should_raise_for_response?(result)
|
165
|
+
error = ExpertSenderError.new("ExpertSender API Error: #{result.error_message} (code #{result.error_code})")
|
166
|
+
error.code = result.error_code
|
167
|
+
raise error
|
168
|
+
end
|
169
|
+
|
170
|
+
result
|
171
|
+
end
|
172
|
+
|
173
|
+
def should_raise_for_response?(result)
|
174
|
+
@throws_exceptions and result.failed?
|
175
|
+
end
|
176
|
+
|
177
|
+
def remove_subscriber_by_email(email, options = {})
|
178
|
+
params = options.merge({ apiKey: api_key, email: email })
|
179
|
+
|
180
|
+
self.class.delete(@subscribers_url, query: params)
|
181
|
+
end
|
182
|
+
|
183
|
+
def remove_subscriber_by_id(id, options = {})
|
184
|
+
params = options.merge({ apiKey: api_key })
|
185
|
+
|
186
|
+
self.class.delete("#{@subscribers_url}/#{id}", query: params)
|
187
|
+
end
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module ExpertSenderApi
|
2
|
+
module Serializeable
|
3
|
+
|
4
|
+
private
|
5
|
+
|
6
|
+
def attributes
|
7
|
+
variables_to_serialize.map do |ivar|
|
8
|
+
{ name: camel_case(ivar.to_s[1..-1]), value: instance_variable_get(ivar) }
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def camel_case(str)
|
13
|
+
str.split(/[\W_]/).map {|c| c.capitalize}.join
|
14
|
+
end
|
15
|
+
|
16
|
+
def variables_to_serialize
|
17
|
+
instance_variables
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module ExpertSenderApi::Email
|
2
|
+
class Content
|
3
|
+
include ::ExpertSenderApi::Serializeable
|
4
|
+
|
5
|
+
attr_accessor :from_name, :from_email, :reply_to_name, :reply_to_email,
|
6
|
+
:subject, :html, :plain
|
7
|
+
|
8
|
+
def initialize(parameters = {})
|
9
|
+
parameters.each { |key, value| send("#{key}=", value) }
|
10
|
+
end
|
11
|
+
|
12
|
+
def insert_to(xml)
|
13
|
+
xml.Content {
|
14
|
+
attributes.each do |attr|
|
15
|
+
xml.send(attr[:name], attr[:value]) unless attr[:value].nil?
|
16
|
+
end
|
17
|
+
}
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
|
23
|
+
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module ExpertSenderApi::Email
|
2
|
+
class Receiver
|
3
|
+
include ::ExpertSenderApi::Serializeable
|
4
|
+
attr_accessor :id, :email, :list_id
|
5
|
+
|
6
|
+
def initialize(parameters = {})
|
7
|
+
parameters.each { |key, value| send("#{key}=", value) }
|
8
|
+
end
|
9
|
+
|
10
|
+
def insert_to(xml)
|
11
|
+
xml.Receiver {
|
12
|
+
attributes.each do |attr|
|
13
|
+
xml.send(attr[:name], attr[:value]) unless attr[:value].nil?
|
14
|
+
end
|
15
|
+
}
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
|
21
|
+
|
22
|
+
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module ExpertSenderApi::Email
|
2
|
+
class Recipients
|
3
|
+
attr_accessor :subscriber_lists
|
4
|
+
|
5
|
+
def initialize(subscriber_lists: [])
|
6
|
+
@subscriber_lists = subscriber_lists
|
7
|
+
end
|
8
|
+
|
9
|
+
def insert_to(xml)
|
10
|
+
xml.Recipients {
|
11
|
+
if subscriber_lists.any?
|
12
|
+
xml.SubscriberLists {
|
13
|
+
subscriber_lists.each do |list_id|
|
14
|
+
xml.SubscriberList list_id
|
15
|
+
end
|
16
|
+
}
|
17
|
+
end
|
18
|
+
}
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module ExpertSenderApi::Email
|
2
|
+
class Snippet
|
3
|
+
attr_accessor :name, :value, :cdata
|
4
|
+
|
5
|
+
def initialize(name: nil, value: nil, cdata: true)
|
6
|
+
@name = name
|
7
|
+
@value = value
|
8
|
+
@cdata = cdata
|
9
|
+
end
|
10
|
+
|
11
|
+
def insert_to(xml)
|
12
|
+
if !name.empty? and !value.empty?
|
13
|
+
xml.Snippet {
|
14
|
+
xml.Name name
|
15
|
+
if cdata
|
16
|
+
xml.Value { xml.cdata value }
|
17
|
+
else
|
18
|
+
xml.Value value
|
19
|
+
end
|
20
|
+
}
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
|
27
|
+
|
@@ -0,0 +1,64 @@
|
|
1
|
+
module ExpertSenderApi
|
2
|
+
class Result
|
3
|
+
attr_reader :response, :parsed_response, :error_code, :error_message
|
4
|
+
|
5
|
+
def initialize(response)
|
6
|
+
@response = response
|
7
|
+
|
8
|
+
if (@response.body)
|
9
|
+
@parsed_response = Nokogiri::XML(@response.body)
|
10
|
+
|
11
|
+
if @parsed_response.xpath('//ErrorMessage').any?
|
12
|
+
@error_message = @parsed_response.xpath('//ErrorMessage/Message').text
|
13
|
+
@error_code = @parsed_response.xpath('//ErrorMessage/Code').text
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
freeze
|
18
|
+
end
|
19
|
+
|
20
|
+
def success?
|
21
|
+
status_success? and
|
22
|
+
error_code.nil? and
|
23
|
+
error_message.nil?
|
24
|
+
end
|
25
|
+
|
26
|
+
def failed?
|
27
|
+
not success?
|
28
|
+
end
|
29
|
+
|
30
|
+
def status_success?
|
31
|
+
response.code == 200 or
|
32
|
+
response.code == 201 or
|
33
|
+
response.code == 202
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
|
39
|
+
clients=Client.joins(:childs).
|
40
|
+
where("clients.created_at > '2014-01-13 00:00:00.000000' and clients.created_at < '2014-01-13 23:59:59.999999'").
|
41
|
+
where(synchronized: false).
|
42
|
+
where('children.client_id is not null')
|
43
|
+
not_subscribed_clients = []
|
44
|
+
clients.each do |c|
|
45
|
+
si = account.expertsender.get_subscriber_info email: c.email
|
46
|
+
subscribed = si.parsed_response.css('StateOnList').
|
47
|
+
select { |e| e.css('ListId').text.to_i == 2 && e.css('Status').text == 'Active' }.size == 1
|
48
|
+
p "Client: #{c.email}, sync: #{c.synchronized}, uns: #{c.unsubscribed}, registered: #{c.registered}, MainList: #{subscribed}"
|
49
|
+
not_subscribed_clients.push c unless subscribed
|
50
|
+
end;nil
|
51
|
+
p "Subscribed: #{clients.count - not_subscribed_clients.size}/#{clients.count}"
|
52
|
+
|
53
|
+
orders = OrderChange.where("created_at > '2014-01-13 00:00:00.000000' and created_at < '2014-01-13 23:59:59.999999'").map(&:order)
|
54
|
+
ios = []
|
55
|
+
no_ios = []
|
56
|
+
orders.each do |o|
|
57
|
+
begin
|
58
|
+
io = InsalesApi::Order.find o.insales_order_id
|
59
|
+
ios << io
|
60
|
+
rescue => e
|
61
|
+
p e
|
62
|
+
no_ios << o
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module ExpertSenderApi::Subscriber
|
2
|
+
class Property
|
3
|
+
attr_accessor :id, :value, :type
|
4
|
+
|
5
|
+
TYPE_INTEGER = 'int'
|
6
|
+
TYPE_STRING = 'string'
|
7
|
+
TYPE_DATE = 'date'
|
8
|
+
TYPE_DATE_TIME = 'dateTime'
|
9
|
+
|
10
|
+
def initialize(id: nil, value: nil, type: TYPE_STRING)
|
11
|
+
@id = id
|
12
|
+
@value = value
|
13
|
+
@type = type
|
14
|
+
end
|
15
|
+
|
16
|
+
def insert_to(xml)
|
17
|
+
xml.Property {
|
18
|
+
xml.Id id
|
19
|
+
xml.Value value, 'xsi:type' => "xs:#{type}"
|
20
|
+
}
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
|
26
|
+
|
27
|
+
|
@@ -0,0 +1,47 @@
|
|
1
|
+
module ExpertSenderApi::Subscriber
|
2
|
+
class Tag
|
3
|
+
include ::ExpertSenderApi::Serializeable
|
4
|
+
|
5
|
+
MODE_ADD_AND_UPDATE = 'AddAndUpdate'
|
6
|
+
MODE_ADD_AND_REPLACE = 'AddAndReplace'
|
7
|
+
MODE_ADD_AND_IGNORE = 'AddAndIgnore'
|
8
|
+
MODE_IGNORE_AND_UPDATE = 'IgnoreAndUpdate'
|
9
|
+
MODE_IGNORE_AND_REPLACE = 'IgnoreAndReplace'
|
10
|
+
|
11
|
+
class << self
|
12
|
+
attr_accessor :mode, :force, :list_id
|
13
|
+
end
|
14
|
+
|
15
|
+
attr_accessor :mode, :force, :list_id, :id, :email, :firstname, :lastname,
|
16
|
+
:tracking_code, :name, :vendor, :ip, :properties
|
17
|
+
|
18
|
+
def initialize(mode: MODE_ADD_AND_UPDATE, **parameters)
|
19
|
+
@mode = mode || self.class.mode
|
20
|
+
@force = parameters[:force] || self.class.force
|
21
|
+
@list_id = parameters[:list_id] || self.class.list_id
|
22
|
+
@properties = parameters.delete(:properties) || []
|
23
|
+
|
24
|
+
parameters.each { |key, value| send("#{key}=", value) }
|
25
|
+
end
|
26
|
+
|
27
|
+
def insert_to(xml)
|
28
|
+
xml.Subscriber {
|
29
|
+
attributes.each do |attr|
|
30
|
+
xml.send(attr[:name], attr[:value]) unless attr[:value].nil?
|
31
|
+
end
|
32
|
+
if properties.any?
|
33
|
+
xml.Properties {
|
34
|
+
properties.each { |property| property.insert_to(xml) }
|
35
|
+
}
|
36
|
+
end
|
37
|
+
}
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
def variables_to_serialize
|
43
|
+
instance_variables.select { |var| var != :@properties }
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
@@ -0,0 +1,232 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe ExpertSenderApi::API do
|
4
|
+
let(:api_key) { "123-us1" }
|
5
|
+
let(:api_endpoint) { 'https://api2.esv2.com' }
|
6
|
+
|
7
|
+
let(:subscribers) { [ExpertSenderApi::Subscriber::Tag.new(subscriber_attributes)] }
|
8
|
+
let(:subscriber_attributes) { { id: 1, list_id: 52, email: "test@httplab.ru" } }
|
9
|
+
let(:subscribers_url) { "#{api_endpoint}/Api/Subscribers" }
|
10
|
+
|
11
|
+
let(:recipients) { ExpertSenderApi::Email::Recipients.new(recipients_attributes) }
|
12
|
+
let(:recipients_attributes) { { subscriber_lists: [52, 53] } }
|
13
|
+
|
14
|
+
let(:content) { ExpertSenderApi::Email::Content.new(content_attributes) }
|
15
|
+
let(:content_attributes) { { from_name: 'From Name Test',
|
16
|
+
from_email: 'test@httplab.ru',
|
17
|
+
reply_to_name: 'Reply To Name Test',
|
18
|
+
reply_to_email: 'Reply To Email Test',
|
19
|
+
subject: 'Subject test',
|
20
|
+
plain: 'Plain Test Content' } }
|
21
|
+
|
22
|
+
let(:receiver) { ExpertSenderApi::Email::Receiver.new(receiver_attributes) }
|
23
|
+
let(:receiver_attributes) { { id: 123,
|
24
|
+
email: 'test@test.ru',
|
25
|
+
list_id: 53 } }
|
26
|
+
|
27
|
+
let(:snippets) { [ExpertSenderApi::Email::Snippet.new(snippet_attributes)] }
|
28
|
+
let(:snippet_attributes) { { name: 'Test snippet name',
|
29
|
+
value: 'Test snippet value' } }
|
30
|
+
describe "attributes" do
|
31
|
+
it "have no API key by default" do
|
32
|
+
having_env('EXPERTSENDER_API_KEY', nil) { @expertsender = ExpertSenderApi::API.new }
|
33
|
+
expect(@expertsender.api_key).to be_nil
|
34
|
+
end
|
35
|
+
|
36
|
+
it "set an API key in constructor" do
|
37
|
+
@expertsender = ExpertSenderApi::API.new(key: api_key)
|
38
|
+
expect(@expertsender.api_key).to eq(api_key)
|
39
|
+
end
|
40
|
+
|
41
|
+
it "set an API key from the 'EXPERTSENDER_API_KEY' ENV variable" do
|
42
|
+
having_env('EXPERTSENDER_API_KEY', api_key) { @expertsender = ExpertSenderApi::API.new }
|
43
|
+
expect(@expertsender.api_key).to eq(api_key)
|
44
|
+
end
|
45
|
+
|
46
|
+
it "set an API key via setter" do
|
47
|
+
@expertsender = ExpertSenderApi::API.new
|
48
|
+
@expertsender.api_key = api_key
|
49
|
+
expect(@expertsender.api_key).to eq(api_key)
|
50
|
+
end
|
51
|
+
|
52
|
+
it "detect api endpoint from initializer parameters" do
|
53
|
+
@expertsender = ExpertSenderApi::API.new(key: api_key, api_endpoint: api_endpoint)
|
54
|
+
expect(api_endpoint).to eq(@expertsender.api_endpoint)
|
55
|
+
end
|
56
|
+
|
57
|
+
it "sets the 'throws_exceptions' option from initializer parameters" do
|
58
|
+
@expertsender = ExpertSenderApi::API.new(key: api_key, throws_exceptions: false)
|
59
|
+
expect(false).to eq(@expertsender.throws_exceptions)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
describe "ExpertSenderApi class variables" do
|
64
|
+
before do
|
65
|
+
ExpertSenderApi::API.api_key = "123-us1"
|
66
|
+
ExpertSenderApi::API.throws_exceptions = false
|
67
|
+
ExpertSenderApi::API.api_endpoint = api_endpoint
|
68
|
+
end
|
69
|
+
|
70
|
+
after do
|
71
|
+
ExpertSenderApi::API.api_key = nil
|
72
|
+
ExpertSenderApi::API.throws_exceptions = nil
|
73
|
+
ExpertSenderApi::API.api_endpoint = nil
|
74
|
+
end
|
75
|
+
|
76
|
+
it "set api key on new instances" do
|
77
|
+
expect(ExpertSenderApi::API.new.api_key).to eq(ExpertSenderApi::API.api_key)
|
78
|
+
end
|
79
|
+
|
80
|
+
it "set throws_exceptions on new instances" do
|
81
|
+
expect(ExpertSenderApi::API.new.throws_exceptions).to eq(ExpertSenderApi::API.throws_exceptions)
|
82
|
+
end
|
83
|
+
|
84
|
+
it "set api_endpoint on new instances" do
|
85
|
+
expect(ExpertSenderApi::API.api_endpoint).not_to be_nil
|
86
|
+
expect(ExpertSenderApi::API.new.api_endpoint).to eq(ExpertSenderApi::API.api_endpoint)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
context 'when configured properly' do
|
91
|
+
subject { ExpertSenderApi::API.new key: api_key, api_endpoint: api_endpoint }
|
92
|
+
|
93
|
+
its '#add_subscribers_to_list calls post with correct body' do
|
94
|
+
builder = Nokogiri::XML::Builder.new do |xml|
|
95
|
+
xml.ApiRequest {
|
96
|
+
xml.ApiKey api_key
|
97
|
+
xml.MultiData {
|
98
|
+
subscribers.each { |subscriber| subscriber.insert_to(xml) }
|
99
|
+
}
|
100
|
+
}
|
101
|
+
end
|
102
|
+
|
103
|
+
xml = builder.to_xml save_with: Nokogiri::XML::Node::SaveOptions::NO_DECLARATION
|
104
|
+
|
105
|
+
expect_post(subscribers_url, xml)
|
106
|
+
subject.add_subscribers_to_list(subscribers)
|
107
|
+
end
|
108
|
+
|
109
|
+
its '#remove_subscriber_from_list by id calls delete with correct parameters' do
|
110
|
+
expected_params = { apiKey: api_key,
|
111
|
+
listId: subscriber_attributes[:list_id] }
|
112
|
+
expect_delete("#{subscribers_url}/#{subscriber_attributes[:id]}", expected_params)
|
113
|
+
|
114
|
+
subject.remove_subscriber_from_list(id: subscriber_attributes[:id], listId: subscriber_attributes[:list_id])
|
115
|
+
end
|
116
|
+
|
117
|
+
its '#remove_subscriber_from_list by email returns success response' do
|
118
|
+
expected_params = { apiKey: api_key,
|
119
|
+
email: subscriber_attributes[:email],
|
120
|
+
listId: subscriber_attributes[:list_id] }
|
121
|
+
expect_delete(subscribers_url, expected_params)
|
122
|
+
|
123
|
+
subject.remove_subscriber_from_list(email: subscriber_attributes[:email], listId: subscriber_attributes[:list_id])
|
124
|
+
end
|
125
|
+
|
126
|
+
its '#get_subscriber_info calls get with correct parameters' do
|
127
|
+
expected_params = { apiKey: api_key,
|
128
|
+
email: subscriber_attributes[:email],
|
129
|
+
option: ExpertSenderApi::API::SUBSCRIBER_INFO_OPTION_FULL }
|
130
|
+
expect_get(subscribers_url, expected_params)
|
131
|
+
|
132
|
+
subject.get_subscriber_info(email: subscriber_attributes[:email])
|
133
|
+
end
|
134
|
+
|
135
|
+
its '#create_and_send_email calls post with correct body' do
|
136
|
+
|
137
|
+
builder = Nokogiri::XML::Builder.new do |xml|
|
138
|
+
xml.ApiRequest {
|
139
|
+
xml.ApiKey api_key
|
140
|
+
xml.Data {
|
141
|
+
recipients.insert_to xml
|
142
|
+
content.insert_to xml
|
143
|
+
}
|
144
|
+
}
|
145
|
+
end
|
146
|
+
|
147
|
+
xml = builder.to_xml save_with: Nokogiri::XML::Node::SaveOptions::NO_DECLARATION
|
148
|
+
|
149
|
+
expect_post("#{api_endpoint}/Api/Newsletters", xml)
|
150
|
+
subject.create_and_send_email(recipients: recipients, content: content)
|
151
|
+
end
|
152
|
+
|
153
|
+
its '#send_transaction_email' do
|
154
|
+
letter_id = 93
|
155
|
+
|
156
|
+
builder = Nokogiri::XML::Builder.new do |xml|
|
157
|
+
xml.ApiRequest {
|
158
|
+
xml.ApiKey api_key
|
159
|
+
xml.Data {
|
160
|
+
receiver.insert_to xml
|
161
|
+
if snippets.any?
|
162
|
+
xml.Snippets {
|
163
|
+
snippets.each { |snippet| snippet.insert_to(xml) }
|
164
|
+
}
|
165
|
+
end
|
166
|
+
}
|
167
|
+
}
|
168
|
+
end
|
169
|
+
|
170
|
+
xml = builder.to_xml save_with: Nokogiri::XML::Node::SaveOptions::NO_DECLARATION
|
171
|
+
|
172
|
+
expect_post("#{api_endpoint}/Api/Transactionals/#{letter_id}", xml)
|
173
|
+
subject.send_transaction_email(letter_id: letter_id,
|
174
|
+
receiver: receiver,
|
175
|
+
snippets: snippets)
|
176
|
+
end
|
177
|
+
|
178
|
+
its '#get_deleted_subscribers calls get with correct parameters' do
|
179
|
+
expected_params = { apiKey: api_key,
|
180
|
+
listIds: '52,53',
|
181
|
+
removeTypes: 'OptOutLink,Compliant,Ui',
|
182
|
+
startDate: Date.today.to_s,
|
183
|
+
endDate: Date.new(2090, 1, 1).to_s }
|
184
|
+
|
185
|
+
expect_get("#{api_endpoint}/Api/RemovedSubscribers", expected_params)
|
186
|
+
|
187
|
+
subject.get_deleted_subscribers(list_ids: [52, 53],
|
188
|
+
remove_types: ['OptOutLink', 'Compliant', 'Ui'],
|
189
|
+
start_date: Date.today,
|
190
|
+
end_date: Date.new(2090, 1, 1))
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
context 'when has wrong api key' do
|
195
|
+
subject { ExpertSenderApi::API.new key: 'wrong', api_endpoint: api_endpoint, throws_exceptions: true }
|
196
|
+
|
197
|
+
its '#add_subscribers_to_list raises exception' do
|
198
|
+
expect { subject.add_subscribers_to_list(subscribers) }.to raise_error(ExpertSenderApi::ExpertSenderError)
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
202
|
+
private
|
203
|
+
|
204
|
+
def having_env(key, value)
|
205
|
+
prev_value = ENV[key]
|
206
|
+
ENV[key] = value
|
207
|
+
yield
|
208
|
+
ENV[key] = prev_value
|
209
|
+
end
|
210
|
+
|
211
|
+
def expect_get(expected_url, expected_params)
|
212
|
+
ExpertSenderApi::API.should_receive(:get).with do |url, opts|
|
213
|
+
expect(url).to eq expected_url
|
214
|
+
expect(expected_params).to eq opts[:query]
|
215
|
+
end.and_return(Struct.new(:body).new(nil))
|
216
|
+
end
|
217
|
+
|
218
|
+
def expect_post(expected_url, expected_body)
|
219
|
+
ExpertSenderApi::API.should_receive(:post).with do |url, opts|
|
220
|
+
expect(url).to eq expected_url
|
221
|
+
expect(expected_body).to eq opts[:body]
|
222
|
+
end.and_return(Struct.new(:body).new(nil))
|
223
|
+
end
|
224
|
+
|
225
|
+
def expect_delete(expected_url, expected_params)
|
226
|
+
ExpertSenderApi::API.should_receive(:delete).with do |url, opts|
|
227
|
+
expect(url).to eq expected_url
|
228
|
+
expect(expected_params).to eq opts[:query]
|
229
|
+
end.and_return(Struct.new(:body).new(nil))
|
230
|
+
end
|
231
|
+
end
|
232
|
+
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe ExpertSenderApi::Email::Content do
|
4
|
+
context :with_valid_attributes do
|
5
|
+
let(:valid_attributes) { { from_name: 'From Name Test',
|
6
|
+
from_email: 'test@httplab.ru',
|
7
|
+
reply_to_name: 'Reply To Name Test',
|
8
|
+
reply_to_email: 'Reply To Email Test',
|
9
|
+
subject: 'Subject test',
|
10
|
+
html: 'Html Test Content',
|
11
|
+
plain: 'Plain Test Content' } }
|
12
|
+
|
13
|
+
subject do
|
14
|
+
ExpertSenderApi::Email::Content.new valid_attributes
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'has proper attributes' do
|
18
|
+
valid_attributes.each do |key, value|
|
19
|
+
subject.send(key).should eq value
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'generates proper markup' do
|
24
|
+
builder = Nokogiri::XML::Builder.new do |xml|
|
25
|
+
subject.insert_to(xml)
|
26
|
+
end
|
27
|
+
|
28
|
+
xml = Nokogiri::XML(builder.to_xml)
|
29
|
+
|
30
|
+
xml.xpath('//FromName').text.should eq valid_attributes[:from_name]
|
31
|
+
xml.xpath('//FromEmail').text.should eq valid_attributes[:from_email]
|
32
|
+
xml.xpath('//ReplyToName').text.should eq valid_attributes[:reply_to_name]
|
33
|
+
xml.xpath('//ReplyToEmail').text.should eq valid_attributes[:reply_to_email]
|
34
|
+
xml.xpath('//Subject').text.should eq valid_attributes[:subject]
|
35
|
+
xml.xpath('//Html').text.should eq valid_attributes[:html]
|
36
|
+
xml.xpath('//Plain').text.should eq valid_attributes[:plain]
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe ExpertSenderApi::Email::Receiver do
|
4
|
+
context :with_valid_attributes do
|
5
|
+
let(:valid_attributes) { { id: '777',
|
6
|
+
email: 'test@test.com',
|
7
|
+
list_id: '53' } }
|
8
|
+
|
9
|
+
subject do
|
10
|
+
ExpertSenderApi::Email::Receiver.new valid_attributes
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'has proper attributes' do
|
14
|
+
subject.id.should eq valid_attributes[:id]
|
15
|
+
subject.email.should eq valid_attributes[:email]
|
16
|
+
subject.list_id.should eq valid_attributes[:list_id]
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'generates proper markup' do
|
20
|
+
builder = Nokogiri::XML::Builder.new do |xml|
|
21
|
+
subject.insert_to(xml)
|
22
|
+
end
|
23
|
+
|
24
|
+
xml = Nokogiri::XML(builder.to_xml)
|
25
|
+
|
26
|
+
xml.xpath('//Receiver/Id').text.should eq valid_attributes[:id]
|
27
|
+
xml.xpath('//Receiver/Email').text.should eq valid_attributes[:email]
|
28
|
+
xml.xpath('//Receiver/ListId').text.should eq valid_attributes[:list_id]
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe ExpertSenderApi::Email::Recipients do
|
4
|
+
context :with_valid_attributes do
|
5
|
+
let(:valid_attributes) { { subscriber_lists: [53, 53] } }
|
6
|
+
|
7
|
+
subject do
|
8
|
+
ExpertSenderApi::Email::Recipients.new valid_attributes
|
9
|
+
end
|
10
|
+
|
11
|
+
it 'has proper attributes' do
|
12
|
+
valid_attributes.each do |key, value|
|
13
|
+
subject.send(key).should eq value
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'generates proper markup' do
|
18
|
+
builder = Nokogiri::XML::Builder.new do |xml|
|
19
|
+
subject.insert_to(xml)
|
20
|
+
end
|
21
|
+
|
22
|
+
xml = Nokogiri::XML(builder.to_xml)
|
23
|
+
|
24
|
+
xml.xpath('//SubscriberLists/SubscriberList').map(&:text).should eq valid_attributes[:subscriber_lists].map(&:to_s)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
|
30
|
+
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe ExpertSenderApi::Email::Snippet do
|
4
|
+
context :with_valid_attributes do
|
5
|
+
let(:valid_attributes) { { name: 'TestSnippetName',
|
6
|
+
value: 'TestSnippetValue' } }
|
7
|
+
|
8
|
+
subject do
|
9
|
+
ExpertSenderApi::Email::Snippet.new valid_attributes
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'has proper attributes' do
|
13
|
+
subject.name.should eq valid_attributes[:name]
|
14
|
+
subject.value.should eq valid_attributes[:value]
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'generates proper markup' do
|
18
|
+
builder = Nokogiri::XML::Builder.new do |xml|
|
19
|
+
subject.insert_to(xml)
|
20
|
+
end
|
21
|
+
|
22
|
+
xml = Nokogiri::XML(builder.to_xml)
|
23
|
+
|
24
|
+
xml.xpath('//Name').text.should eq valid_attributes[:name]
|
25
|
+
xml.xpath('//Value').text.should eq valid_attributes[:value]
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe ExpertSenderApi::Subscriber::Property do
|
4
|
+
context :with_valid_attributes do
|
5
|
+
let(:valid_attributes) { { id: 123,
|
6
|
+
type: 'string',
|
7
|
+
value: 'Test Property Value' } }
|
8
|
+
|
9
|
+
subject do
|
10
|
+
ExpertSenderApi::Subscriber::Property.new valid_attributes
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'has proper attributes' do
|
14
|
+
subject.id.should eq valid_attributes[:id]
|
15
|
+
subject.type.should eq valid_attributes[:type]
|
16
|
+
subject.value.should eq valid_attributes[:value]
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'generates proper markup' do
|
20
|
+
builder = Nokogiri::XML::Builder.new do |xml|
|
21
|
+
subject.insert_to(xml)
|
22
|
+
end
|
23
|
+
|
24
|
+
xml = Nokogiri::XML(builder.to_xml)
|
25
|
+
|
26
|
+
xml.xpath('//Property/Id').text.to_i.should eq valid_attributes[:id]
|
27
|
+
xml.xpath('//Property/Value').attribute('xsi:type').value.should eq "xs:#{valid_attributes[:type]}"
|
28
|
+
xml.xpath('//Property/Value').text.should eq valid_attributes[:value]
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe ExpertSenderApi::Subscriber::Tag do
|
4
|
+
context :with_valid_attributes do
|
5
|
+
let(:properties) { [ExpertSenderApi::Subscriber::Property.new(id: 123,
|
6
|
+
value: 'test',
|
7
|
+
type: 'string'),
|
8
|
+
ExpertSenderApi::Subscriber::Property.new(id: 456,
|
9
|
+
value: 'test1',
|
10
|
+
type: 'string')] }
|
11
|
+
let(:valid_attributes) { { list_id: 52,
|
12
|
+
email: 'test@httplab.ru',
|
13
|
+
mode: ExpertSenderApi::Subscriber::Tag::MODE_ADD_AND_IGNORE,
|
14
|
+
id: 777,
|
15
|
+
firstname: 'Test1',
|
16
|
+
lastname: 'Test2',
|
17
|
+
name: 'Test3',
|
18
|
+
tracking_code: '123',
|
19
|
+
vendor: 'Vendor',
|
20
|
+
ip: '127.0.0.1',
|
21
|
+
properties: properties } }
|
22
|
+
|
23
|
+
subject do
|
24
|
+
ExpertSenderApi::Subscriber::Tag.new valid_attributes
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'has proper attributes' do
|
28
|
+
valid_attributes.each do |key, value|
|
29
|
+
subject.send(key).should eq value
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'generates proper markup' do
|
34
|
+
builder = Nokogiri::XML::Builder.new do |xml|
|
35
|
+
subject.insert_to(xml)
|
36
|
+
end
|
37
|
+
|
38
|
+
xml = Nokogiri::XML(builder.to_xml)
|
39
|
+
|
40
|
+
xml.xpath('//Subscriber/ListId').text.to_i.should eq valid_attributes[:list_id]
|
41
|
+
xml.xpath('//Subscriber/Email').text.should eq valid_attributes[:email]
|
42
|
+
xml.xpath('//Subscriber/Mode').text.should eq valid_attributes[:mode]
|
43
|
+
xml.xpath('//Subscriber/Id').text.to_i.should eq valid_attributes[:id]
|
44
|
+
xml.xpath('//Subscriber/Firstname').text.should eq valid_attributes[:firstname]
|
45
|
+
xml.xpath('//Subscriber/Lastname').text.should eq valid_attributes[:lastname]
|
46
|
+
xml.xpath('//Subscriber/Name').text.should eq valid_attributes[:name]
|
47
|
+
xml.xpath('//Subscriber/TrackingCode').text.should eq valid_attributes[:tracking_code]
|
48
|
+
xml.xpath('//Subscriber/Vendor').text.should eq valid_attributes[:vendor]
|
49
|
+
xml.xpath('//Subscriber/Ip').text.should eq valid_attributes[:ip]
|
50
|
+
|
51
|
+
properties.each_with_index do |property, i|
|
52
|
+
xml_prop = xml.xpath('//Subscriber/Properties/Property')[i]
|
53
|
+
xml_prop.xpath('Id').text.to_i.should eq property.id
|
54
|
+
xml_prop.xpath('Value').attribute('xsi:type').value.should eq "xs:#{property.type}"
|
55
|
+
xml_prop.xpath('Value').text.should eq property.value
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'bundler'
|
3
|
+
|
4
|
+
Bundler.setup(:default, :development)
|
5
|
+
|
6
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
7
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
8
|
+
require 'expertsender_api'
|
9
|
+
|
10
|
+
RSpec.configure do |config|
|
11
|
+
config.color_enabled = true
|
12
|
+
end
|
metadata
ADDED
@@ -0,0 +1,134 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: expertsender_api
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- kinderly
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-03-03 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: httparty
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - '>='
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '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'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: nokogiri
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rake
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - '>='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rspec
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - '>='
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
description: A wrapper for ExpertSender API
|
70
|
+
email:
|
71
|
+
- beorc@httplab.ru
|
72
|
+
executables: []
|
73
|
+
extensions: []
|
74
|
+
extra_rdoc_files: []
|
75
|
+
files:
|
76
|
+
- .gitignore
|
77
|
+
- Gemfile
|
78
|
+
- README.md
|
79
|
+
- Rakefile
|
80
|
+
- expertsender_api.gemspec
|
81
|
+
- lib/expertsender_api.rb
|
82
|
+
- lib/expertsender_api/api.rb
|
83
|
+
- lib/expertsender_api/concerns/serializeable.rb
|
84
|
+
- lib/expertsender_api/email.rb
|
85
|
+
- lib/expertsender_api/email/content.rb
|
86
|
+
- lib/expertsender_api/email/receiver.rb
|
87
|
+
- lib/expertsender_api/email/recipients.rb
|
88
|
+
- lib/expertsender_api/email/snippet.rb
|
89
|
+
- lib/expertsender_api/expertsender_error.rb
|
90
|
+
- lib/expertsender_api/result.rb
|
91
|
+
- lib/expertsender_api/subscriber.rb
|
92
|
+
- lib/expertsender_api/subscriber/property.rb
|
93
|
+
- lib/expertsender_api/subscriber/tag.rb
|
94
|
+
- spec/expertsender_api/api_spec.rb
|
95
|
+
- spec/expertsender_api/email/content_spec.rb
|
96
|
+
- spec/expertsender_api/email/receiver_spec.rb
|
97
|
+
- spec/expertsender_api/email/recipients_spec.rb
|
98
|
+
- spec/expertsender_api/email/snippet_spec.rb
|
99
|
+
- spec/expertsender_api/subscriber/property_spec.rb
|
100
|
+
- spec/expertsender_api/subscriber/tag_spec.rb
|
101
|
+
- spec/spec_helper.rb
|
102
|
+
homepage: http://github.com/kinderly/expertsender_api
|
103
|
+
licenses:
|
104
|
+
- MIT
|
105
|
+
metadata: {}
|
106
|
+
post_install_message:
|
107
|
+
rdoc_options: []
|
108
|
+
require_paths:
|
109
|
+
- lib
|
110
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
111
|
+
requirements:
|
112
|
+
- - '>='
|
113
|
+
- !ruby/object:Gem::Version
|
114
|
+
version: '0'
|
115
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
116
|
+
requirements:
|
117
|
+
- - '>='
|
118
|
+
- !ruby/object:Gem::Version
|
119
|
+
version: '0'
|
120
|
+
requirements: []
|
121
|
+
rubyforge_project: expertsender_api
|
122
|
+
rubygems_version: 2.2.2
|
123
|
+
signing_key:
|
124
|
+
specification_version: 4
|
125
|
+
summary: A wrapper for ExpertSender API
|
126
|
+
test_files:
|
127
|
+
- spec/expertsender_api/api_spec.rb
|
128
|
+
- spec/expertsender_api/email/content_spec.rb
|
129
|
+
- spec/expertsender_api/email/receiver_spec.rb
|
130
|
+
- spec/expertsender_api/email/recipients_spec.rb
|
131
|
+
- spec/expertsender_api/email/snippet_spec.rb
|
132
|
+
- spec/expertsender_api/subscriber/property_spec.rb
|
133
|
+
- spec/expertsender_api/subscriber/tag_spec.rb
|
134
|
+
- spec/spec_helper.rb
|