expertsender_api 0.0.1
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 +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
|