expresspigeon-ruby 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +19 -0
- data/.rvmrc +8 -0
- data/Gemfile +5 -0
- data/Gemfile.lock +24 -0
- data/LICENSE.txt +22 -0
- data/README.md +29 -0
- data/Rakefile +1 -0
- data/expresspigeon-ruby.gemspec +20 -0
- data/lib/expresspigeon-ruby/version.rb +5 -0
- data/lib/expresspigeon-ruby.rb +306 -0
- data/spec/campaigns_spec.rb +109 -0
- data/spec/contacts_spec.rb +152 -0
- data/spec/lists_spec.rb +149 -0
- data/spec/messages_spec.rb +127 -0
- data/spec/pigeon_helper.rb +16 -0
- metadata +82 -0
data/.gitignore
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
*.rbc
|
2
|
+
*.sassc
|
3
|
+
.sass-cache
|
4
|
+
capybara-*.html
|
5
|
+
.rspec
|
6
|
+
/.bundle
|
7
|
+
/vendor/bundle
|
8
|
+
/log/*
|
9
|
+
/tmp/*
|
10
|
+
/db/*.sqlite3
|
11
|
+
/public/system/*
|
12
|
+
/coverage/
|
13
|
+
/spec/tmp/*
|
14
|
+
**.orig
|
15
|
+
rerun.txt
|
16
|
+
pickle-email-*.html
|
17
|
+
doc/structures.csv
|
18
|
+
*.iml
|
19
|
+
.idea/
|
data/.rvmrc
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
expresspigeon-ruby (0.0.1)
|
5
|
+
|
6
|
+
GEM
|
7
|
+
remote: https://rubygems.org/
|
8
|
+
specs:
|
9
|
+
diff-lcs (1.2.5)
|
10
|
+
rspec (2.14.1)
|
11
|
+
rspec-core (~> 2.14.0)
|
12
|
+
rspec-expectations (~> 2.14.0)
|
13
|
+
rspec-mocks (~> 2.14.0)
|
14
|
+
rspec-core (2.14.5)
|
15
|
+
rspec-expectations (2.14.3)
|
16
|
+
diff-lcs (>= 1.1.3, < 2.0)
|
17
|
+
rspec-mocks (2.14.3)
|
18
|
+
|
19
|
+
PLATFORMS
|
20
|
+
ruby
|
21
|
+
|
22
|
+
DEPENDENCIES
|
23
|
+
expresspigeon-ruby!
|
24
|
+
rspec (~> 2.6)
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2014 ExpressPigeon
|
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,29 @@
|
|
1
|
+
# Expresspigeon::Ruby
|
2
|
+
|
3
|
+
TODO: Write a gem description
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
gem 'expresspigeon-ruby'
|
10
|
+
|
11
|
+
And then execute:
|
12
|
+
|
13
|
+
$ bundle
|
14
|
+
|
15
|
+
Or install it yourself as:
|
16
|
+
|
17
|
+
$ gem install expresspigeon-ruby
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
|
21
|
+
TODO: Write usage instructions here
|
22
|
+
|
23
|
+
## Contributing
|
24
|
+
|
25
|
+
1. Fork it
|
26
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
27
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
28
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
29
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'expresspigeon-ruby/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |gem|
|
7
|
+
gem.name = "expresspigeon-ruby"
|
8
|
+
gem.version = Expresspigeon::API::VERSION
|
9
|
+
gem.authors = ["ipolevoy"]
|
10
|
+
gem.email = ["ipolevoy@groupon.com"]
|
11
|
+
gem.description = %q{ExpressPigeon Ruby API for sending transactional messages, manipulating lists, contacts nad more}
|
12
|
+
gem.summary = %q{ExpressPigeon API Ruby Wrapper}
|
13
|
+
gem.homepage = "https://github.com/expresspigeon/expresspigeon-ruby"
|
14
|
+
|
15
|
+
gem.files = `git ls-files`.split($/)
|
16
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
17
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
18
|
+
gem.require_paths = ["lib"]
|
19
|
+
gem.add_development_dependency "rspec", "~> 2.6"
|
20
|
+
end
|
@@ -0,0 +1,306 @@
|
|
1
|
+
require "expresspigeon-ruby/version"
|
2
|
+
|
3
|
+
require 'net/http'
|
4
|
+
require 'json'
|
5
|
+
require 'uri'
|
6
|
+
|
7
|
+
AUTH_KEY = ENV['EXPRESSPIGEON_AUTH_KEY']
|
8
|
+
ROOT = 'https://api.expresspigeon.com/'
|
9
|
+
#ROOT = 'http://localhost:8888/api/'
|
10
|
+
USE_SSL = true
|
11
|
+
|
12
|
+
module ExpressPigeon
|
13
|
+
module API
|
14
|
+
unless AUTH_KEY
|
15
|
+
raise 'Provide EXPRESSPIGEON_AUTH_KEY environment variable'
|
16
|
+
end
|
17
|
+
|
18
|
+
def http(path, method, params = {})
|
19
|
+
uri = URI.parse "#{ROOT}#{path}"
|
20
|
+
req = Net::HTTP.const_get("#{method}").new "#{ROOT}#{path}"
|
21
|
+
req['X-auth-key'] = AUTH_KEY
|
22
|
+
if params
|
23
|
+
req.body = params.to_json
|
24
|
+
req['Content-type'] = 'application/json'
|
25
|
+
end
|
26
|
+
|
27
|
+
if block_given?
|
28
|
+
Net::HTTP.start(uri.host, uri.port, :use_ssl => USE_SSL) do |http|
|
29
|
+
http.request req do |res|
|
30
|
+
res.read_body do |seg|
|
31
|
+
yield seg
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
else
|
36
|
+
resp = Net::HTTP.start(uri.host, uri.port, :use_ssl => USE_SSL) do |http|
|
37
|
+
http.request req
|
38
|
+
end
|
39
|
+
parsed = JSON.parse(resp.body)
|
40
|
+
if parsed.kind_of? Hash
|
41
|
+
MetaHash.new parsed
|
42
|
+
else
|
43
|
+
parsed
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def get(path, &block)
|
49
|
+
http path, 'Get', nil, &block
|
50
|
+
end
|
51
|
+
|
52
|
+
def post(path, params = {})
|
53
|
+
http path, 'Post', params
|
54
|
+
end
|
55
|
+
|
56
|
+
def del(path, params = {})
|
57
|
+
http path, 'Delete', params
|
58
|
+
end
|
59
|
+
|
60
|
+
def self.campaigns
|
61
|
+
Campaigns.new
|
62
|
+
end
|
63
|
+
|
64
|
+
def self.lists
|
65
|
+
Lists.new
|
66
|
+
end
|
67
|
+
|
68
|
+
def self.contacts
|
69
|
+
Contacts.new
|
70
|
+
end
|
71
|
+
|
72
|
+
def self.messages
|
73
|
+
Messages.new
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
end
|
78
|
+
|
79
|
+
class MetaHash < Hash
|
80
|
+
|
81
|
+
def initialize(delegate)
|
82
|
+
super
|
83
|
+
@delegate = delegate
|
84
|
+
@delegate.each_key do |k|
|
85
|
+
v = @delegate[k] # lets go only one level down for now
|
86
|
+
if v.kind_of? Hash
|
87
|
+
@delegate[k] = MetaHash.new(v)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def method_missing(m, *args, &block)
|
93
|
+
@delegate[m.to_s]
|
94
|
+
end
|
95
|
+
|
96
|
+
def to_s
|
97
|
+
@delegate.to_s
|
98
|
+
end
|
99
|
+
|
100
|
+
end
|
101
|
+
|
102
|
+
class Lists
|
103
|
+
|
104
|
+
include ExpressPigeon::API
|
105
|
+
|
106
|
+
def initialize
|
107
|
+
@endpoint = 'lists'
|
108
|
+
end
|
109
|
+
|
110
|
+
def create(list_name, from_name, reply_to)
|
111
|
+
post @endpoint, {:name => list_name, :from_name => from_name, :reply_to => reply_to}
|
112
|
+
end
|
113
|
+
|
114
|
+
|
115
|
+
# Query all lists.
|
116
|
+
# returns: array of hashes each representing a list for this user
|
117
|
+
def all
|
118
|
+
get @endpoint
|
119
|
+
end
|
120
|
+
|
121
|
+
|
122
|
+
#Updates existing list
|
123
|
+
#
|
124
|
+
#:param list_id: Id of list to be updated
|
125
|
+
#:type list_id: int
|
126
|
+
#
|
127
|
+
#:param params: JSON object represents a list to be updated
|
128
|
+
|
129
|
+
#
|
130
|
+
#:returns: EpResponse with status, code, message, and updated list
|
131
|
+
#:rtype: EpResponse
|
132
|
+
#TODO: resolve API on Python side, then implement this
|
133
|
+
#def update(list_id, params = {})
|
134
|
+
# params['id'] = list_id
|
135
|
+
# return self.ep.put(self.endpoint, params=params)
|
136
|
+
#end
|
137
|
+
|
138
|
+
|
139
|
+
# Removes a list with a given id. A list must be enabled and has no dependent subscriptions and/or scheduled campaigns.
|
140
|
+
#
|
141
|
+
# param list_id: Id of list to be removed.
|
142
|
+
# returns response hash with status, code, and message
|
143
|
+
def delete(list_id)
|
144
|
+
del "#{@endpoint}/#{list_id}"
|
145
|
+
end
|
146
|
+
|
147
|
+
def csv(list_id, &block)
|
148
|
+
get "#{@endpoint}/#{list_id}/csv", &block
|
149
|
+
end
|
150
|
+
|
151
|
+
|
152
|
+
end
|
153
|
+
|
154
|
+
class Campaigns
|
155
|
+
include ExpressPigeon::API
|
156
|
+
|
157
|
+
def initialize
|
158
|
+
@endpoint = 'campaigns'
|
159
|
+
end
|
160
|
+
|
161
|
+
def all
|
162
|
+
get @endpoint
|
163
|
+
end
|
164
|
+
|
165
|
+
def report(campaign_id)
|
166
|
+
get "#{@endpoint}/#{campaign_id}"
|
167
|
+
end
|
168
|
+
|
169
|
+
def bounced(campaign_id)
|
170
|
+
get "#{@endpoint}/#{campaign_id}/bounced"
|
171
|
+
end
|
172
|
+
|
173
|
+
def unsubscribed(campaign_id)
|
174
|
+
get "#{@endpoint}/#{campaign_id}/unsubscribed"
|
175
|
+
end
|
176
|
+
|
177
|
+
def spam(campaign_id)
|
178
|
+
get "#{@endpoint}/#{campaign_id}/spam"
|
179
|
+
end
|
180
|
+
|
181
|
+
#
|
182
|
+
# Schedules a new campaign to be sent.
|
183
|
+
# Parameters:
|
184
|
+
# * *list_id* - id of list to send to
|
185
|
+
# * *template_id* - id of template to send
|
186
|
+
# * *name* - name of a newly created campaign
|
187
|
+
# * *from_name* - from name
|
188
|
+
# * *reply_to* - reply to
|
189
|
+
# * *subject* - subject of campaign
|
190
|
+
# * *google_analytics* - true to turn Google Analytics on
|
191
|
+
def send(params = {})
|
192
|
+
post @endpoint, params
|
193
|
+
end
|
194
|
+
|
195
|
+
#
|
196
|
+
# Schedules a new campaign to be sent.
|
197
|
+
# Parameters:
|
198
|
+
# * *list_id* - id of list to send to
|
199
|
+
# * *template_id* - id of template to send
|
200
|
+
# * *name* - name of a newly created campaign
|
201
|
+
# * *from_name* - from name
|
202
|
+
# * *reply_to* - reply to
|
203
|
+
# * *subject* - subject of campaign
|
204
|
+
# * *google_analytics* - true to turn Google Analytics on
|
205
|
+
# * *schedule_for* - Specifies what time a campaign should be sent. If it is provided the campaign will
|
206
|
+
# be scheduled to this time, otherwise campaign is sent immediately. The schedule_for
|
207
|
+
# must be in ISO date format and should be in the future.
|
208
|
+
def schedule(params = {})
|
209
|
+
post @endpoint, params
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
213
|
+
|
214
|
+
class Contacts
|
215
|
+
include ExpressPigeon::API
|
216
|
+
|
217
|
+
def initialize
|
218
|
+
@endpoint = 'contacts'
|
219
|
+
end
|
220
|
+
|
221
|
+
def find_by_email(email)
|
222
|
+
get "#{@endpoint}?email=#{email}"
|
223
|
+
end
|
224
|
+
|
225
|
+
|
226
|
+
# JSON document represents a contact to be created or updated.
|
227
|
+
# The email field is required.
|
228
|
+
# When updating a contact, list_id is optional,
|
229
|
+
# since the contact is uniquely identified by email across all lists.
|
230
|
+
#
|
231
|
+
# :param list_id: Contact list ID (Fixnum) the contact will be added to
|
232
|
+
#
|
233
|
+
# :param contact: Hash describes new contact. The "email" field is required.
|
234
|
+
#
|
235
|
+
# :returns: representation of a contact
|
236
|
+
#
|
237
|
+
def upsert(list_id, contact)
|
238
|
+
post @endpoint, params = {:list_id => list_id, :contact => contact}
|
239
|
+
end
|
240
|
+
|
241
|
+
# Delete single contact. If list_id is not provided, contact will be deleted from system.
|
242
|
+
# :param email: contact email to be deleted.
|
243
|
+
# :param list_id: list id to remove contact from, if not provided, contact will be deleted from system.
|
244
|
+
def delete(email, list_id = nil)
|
245
|
+
if list_id
|
246
|
+
query = "email=#{email}&list_id=#{list_id}"
|
247
|
+
else
|
248
|
+
query = "email=#{email}"
|
249
|
+
end
|
250
|
+
del "#{@endpoint}?#{query}", nil
|
251
|
+
end
|
252
|
+
|
253
|
+
|
254
|
+
end
|
255
|
+
class Messages
|
256
|
+
|
257
|
+
include ExpressPigeon::API
|
258
|
+
|
259
|
+
def initialize
|
260
|
+
@endpoint = 'messages'
|
261
|
+
end
|
262
|
+
|
263
|
+
def send_message(template_id, to, reply_to, from_name, subject, merge_fields = nil, view_online = false, click_tracking = true)
|
264
|
+
post @endpoint, params = {template_id: template_id, :to => to, reply_to: reply_to, :from => from_name, :subject => subject,
|
265
|
+
:merge_fields => merge_fields, :view_online => view_online, :click_tracking => click_tracking}
|
266
|
+
end
|
267
|
+
|
268
|
+
def report(message_id)
|
269
|
+
get "#{@endpoint}/#{message_id}"
|
270
|
+
end
|
271
|
+
|
272
|
+
#
|
273
|
+
#
|
274
|
+
# start_date is instance of Time
|
275
|
+
# end_date is instance of Time
|
276
|
+
def reports(from_id, start_date = nil, end_date = nil)
|
277
|
+
params = []
|
278
|
+
|
279
|
+
if from_id
|
280
|
+
params << "from_id=#{from_id}"
|
281
|
+
end
|
282
|
+
|
283
|
+
if start_date and not end_date
|
284
|
+
raise 'must include both start_date and end_date'
|
285
|
+
end
|
286
|
+
if end_date and not start_date
|
287
|
+
raise 'must include both start_date and end_date'
|
288
|
+
end
|
289
|
+
|
290
|
+
if start_date and end_date
|
291
|
+
params << "start_date=#{start_date.strftime('%FT%T.%L%z')}"
|
292
|
+
params << "end_date=#{end_date.strftime('%FT%T.%L%z')}"
|
293
|
+
end
|
294
|
+
|
295
|
+
query = "#{@endpoint}?"
|
296
|
+
|
297
|
+
if params.size > 0
|
298
|
+
query << params.join('&')
|
299
|
+
end
|
300
|
+
|
301
|
+
puts "calling: #{query}"
|
302
|
+
get query
|
303
|
+
|
304
|
+
end
|
305
|
+
|
306
|
+
end
|
@@ -0,0 +1,109 @@
|
|
1
|
+
require './lib/expresspigeon-ruby'
|
2
|
+
require 'pigeon_helper'
|
3
|
+
|
4
|
+
describe 'campaigns integration test' do
|
5
|
+
|
6
|
+
include PigeonSpecHelper
|
7
|
+
it 'should return more than 0 campaign ids' do
|
8
|
+
res = PIGEON.campaigns.all
|
9
|
+
res.class.should == Array
|
10
|
+
res.size.should > 0
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'cannot send with missing parameters' do
|
14
|
+
res = PIGEON.campaigns.send(:template_id => 15233, :name => 'API Test campaign',
|
15
|
+
:from_name => 'Igor Polevoy', :reply_to => 'igor@polevoy.org',
|
16
|
+
:subject => 'API test', :google_analytics => true)
|
17
|
+
validate_response res, 400, 'error', /required parameters: list_id, template_id, name, from_name, reply_to, subject, google_analytics/
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'cannot send with bad reply_to' do
|
21
|
+
res = PIGEON.campaigns.send(:list_id => -1, :template_id => -1, :name => 'My Campaign', :from_name => 'John', :reply_to => 'j',
|
22
|
+
:subject => 'Hi', :google_analytics => false)
|
23
|
+
validate_response res, 400, 'error', /reply_to should be valid email address/
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'cannot send with non-existing template' do
|
27
|
+
res = PIGEON.campaigns.send(:list_id => -1, :template_id => -1, :name => 'My Campaign', :from_name => 'John',
|
28
|
+
:reply_to => 'j@j.j',
|
29
|
+
:subject => 'Hi', :google_analytics => false)
|
30
|
+
validate_response res, 400, 'error', /template=-1 is not found/
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'cannot send to non-existing list' do
|
34
|
+
|
35
|
+
res = PIGEON.campaigns.send(:list_id => -1, :template_id => TEMPLATE_ID, :name => 'My Campaign', :from_name => 'John',
|
36
|
+
:reply_to => 'j@j.j',
|
37
|
+
:subject => 'Hi', :google_analytics => false)
|
38
|
+
validate_response res, 400, 'error', /list=-1 is not found/
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'cannot send to disabled list' do
|
42
|
+
res = PIGEON.campaigns.send(:list_id => LIST_ID, :template_id => TEMPLATE_ID, :name => 'My Campaign', :from_name => 'John',
|
43
|
+
:reply_to => 'j@j.j',
|
44
|
+
:subject => 'Hi', :google_analytics => false)
|
45
|
+
validate_response res, 400, 'error', /list=#{DISABLED_LIST} is disabled/
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'should create new list, add contact and send successful campaign' do
|
49
|
+
|
50
|
+
list_resp = PIGEON.lists.create('My list', 'John', API_USER)
|
51
|
+
list_id = list_resp.list.id
|
52
|
+
PIGEON.contacts.upsert(list_id, {:email => API_USER})
|
53
|
+
resp = PIGEON.campaigns.send(:list_id => list_id, :template_id => TEMPLATE_ID, :name => 'My Campaign', :from_name => 'John',
|
54
|
+
:reply_to => API_USER,
|
55
|
+
:subject => 'Hi', :google_analytics => false)
|
56
|
+
validate_response resp, 200, 'success', /new campaign created successfully/
|
57
|
+
report = PIGEON.campaigns.report(resp.campaign_id)
|
58
|
+
(report.delivered == 0 or report.delivered == 1).should be_true
|
59
|
+
report.clicked.should eq 0
|
60
|
+
report.opened.should eq 0
|
61
|
+
report.spam.should eq 0
|
62
|
+
(report.in_transit == 0 or report.in_transit == 1).should be_true
|
63
|
+
report.unsubscribed.should eq 0
|
64
|
+
report.bounced.should eq 0
|
65
|
+
bounced = PIGEON.campaigns.bounced(resp.campaign_id)
|
66
|
+
unsubscribed = PIGEON.campaigns.unsubscribed(resp.campaign_id)
|
67
|
+
spam = PIGEON.campaigns.spam(resp.campaign_id)
|
68
|
+
|
69
|
+
bounced.size.should eq 0
|
70
|
+
unsubscribed.size.should eq 0
|
71
|
+
spam.size.should eq 0
|
72
|
+
|
73
|
+
resp = PIGEON.contacts.delete(API_USER)
|
74
|
+
validate_response resp, 200, 'success', /contact=non@non.non deleted successfully/
|
75
|
+
|
76
|
+
resp = PIGEON.contacts.find_by_email(API_USER)
|
77
|
+
validate_response resp, 404, 'error', /contact=non@non.non not found/
|
78
|
+
|
79
|
+
resp = PIGEON.lists.delete(list_id)
|
80
|
+
validate_response resp, 200, 'success', /deleted successfully/
|
81
|
+
end
|
82
|
+
|
83
|
+
|
84
|
+
it 'cannot send campaign if scheduling with bad date' do
|
85
|
+
|
86
|
+
list_resp = PIGEON.lists.create "My list", "John", API_USER
|
87
|
+
resp = PIGEON.campaigns.schedule :list_id => list_resp.list.id, :template_id => TEMPLATE_ID, :name => 'My Campaign',
|
88
|
+
|
89
|
+
:from_name => 'John',
|
90
|
+
:reply_to => API_USER, :subject => 'Hi',
|
91
|
+
:google_analytics => false, :schedule_for => "2013-05-28"
|
92
|
+
|
93
|
+
validate_response resp, 400, 'error', /schedule_for is not in ISO date format, example: 2013-05-28T17:19:50.779/
|
94
|
+
resp = PIGEON.lists.delete(list_resp.list.id)
|
95
|
+
validate_response resp, 200, 'success', /deleted successfully/
|
96
|
+
end
|
97
|
+
|
98
|
+
it 'should not schedule campaign with date in the past' do
|
99
|
+
list_resp = PIGEON.lists.create('My list', 'John', API_USER)
|
100
|
+
resp = PIGEON.campaigns.schedule :list_id => list_resp.list.id, :template_id => TEMPLATE_ID, :name => 'My Campaign',
|
101
|
+
:from_name => 'John',
|
102
|
+
:reply_to => API_USER, :subject => 'Hi',
|
103
|
+
:google_analytics => false, :schedule_for => '2010-05-28T17:19:50.779+0300'
|
104
|
+
|
105
|
+
validate_response resp, 400, 'error', /schedule_for should be in the future/
|
106
|
+
end
|
107
|
+
|
108
|
+
end
|
109
|
+
|
@@ -0,0 +1,152 @@
|
|
1
|
+
require './lib/expresspigeon-ruby'
|
2
|
+
require 'pigeon_helper'
|
3
|
+
|
4
|
+
describe 'contacts integration test' do
|
5
|
+
|
6
|
+
include PigeonSpecHelper
|
7
|
+
|
8
|
+
it 'should not create contact without contact data' do
|
9
|
+
resp = PIGEON.contacts.upsert(-1, {})
|
10
|
+
validate_response resp, 400, 'error', /contact and contact.email are required/
|
11
|
+
end
|
12
|
+
it 'should not create contact without email' do
|
13
|
+
resp = PIGEON.contacts.upsert -1, :email => '', :first_name => 'Marylin', :last_name => 'Monroe'
|
14
|
+
validate_response resp, 400, 'error', /contact and contact.email are required/
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'should not add contact with too many custom fields' do
|
18
|
+
custom_fields = {}
|
19
|
+
(1..25).each { |n| custom_fields["custom_field_#{n}"] = n }
|
20
|
+
resp = PIGEON.contacts.upsert -1, :email => "mary@e.e", :custom_fields => custom_fields
|
21
|
+
validate_response resp, 400, 'error', /You cannot create more than 20 custom fields. Use one of the 'custom_fields'./
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'should not create new contact without list_id' do
|
25
|
+
resp = PIGEON.contacts.upsert '', :email => 'ee@e.e', :first_name => 'Marylin', :last_name => 'Monroe'
|
26
|
+
validate_response resp, 404, 'error', /contact=ee@e.e not found/
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'test_create_with_suppressed_contact' do
|
30
|
+
resp = PIGEON.contacts.upsert -1, :email => 'suppressed@e.e'
|
31
|
+
validate_response resp, 400, 'error', /contact=suppressed@e.e is in suppress list/
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'cannot create with non-existent_list' do
|
35
|
+
resp = PIGEON.contacts.upsert -1, :email => "e@e.e"
|
36
|
+
validate_response resp, 404, 'error', /list=-1 not found/
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'creates list with contacts' do
|
40
|
+
list_response = PIGEON.lists.create 'My List', 'John Doe', 'john@doe.com'
|
41
|
+
list_id = list_response.list.id
|
42
|
+
resp = PIGEON.contacts.upsert list_id, email: "mary@e.e",
|
43
|
+
:custom_fields => {:custom_field_1 => "custom_value_1", }
|
44
|
+
validate_response resp, 200, 'success', /contact=mary@e.e created\/updated successfully/
|
45
|
+
resp.contact.custom_fields.custom_field_1.should eq 'custom_value_1'
|
46
|
+
resp.contact.email.should eq 'mary@e.e'
|
47
|
+
resp.contact.email_format.should eq 'html'
|
48
|
+
resp.contact.status.should eq 'ACTIVE'
|
49
|
+
PIGEON.lists.delete(list_id)
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'creates list non-existent custom field' do
|
53
|
+
list_response = PIGEON.lists.create 'My List', 'John Doe', 'a@a.a'
|
54
|
+
list_id = list_response.list.id
|
55
|
+
resp = PIGEON.contacts.upsert(list_id, {:email => "mary@e.e", :custom_fields => {:c => "c", }})
|
56
|
+
validate_response resp, 200, 'success', nil
|
57
|
+
PIGEON.lists.delete(list_id)
|
58
|
+
end
|
59
|
+
|
60
|
+
it 'cannot export contacts from list without list_id' do
|
61
|
+
content = ''
|
62
|
+
PIGEON.lists.csv "-1" do |c|
|
63
|
+
content << c
|
64
|
+
end
|
65
|
+
resp = JSON.parse(content)
|
66
|
+
validate_response MetaHash.new(resp), 404, 'error', /list=-1 not found/
|
67
|
+
end
|
68
|
+
|
69
|
+
it 'should get contacts from suppressed list' do
|
70
|
+
content =''
|
71
|
+
PIGEON.lists.csv "suppress_list" do |c|
|
72
|
+
content += c
|
73
|
+
end
|
74
|
+
resp = content.split /\n/
|
75
|
+
resp.size.should eq 2
|
76
|
+
resp[1].should =~ /"suppressed@e.e","Suppressed","Doe"/
|
77
|
+
end
|
78
|
+
|
79
|
+
it 'should get single contact' do
|
80
|
+
resp = PIGEON.contacts.find_by_email 'suppressed@e.e'
|
81
|
+
resp.email.should eq 'suppressed@e.e'
|
82
|
+
end
|
83
|
+
|
84
|
+
it 'should not find non existent contact' do
|
85
|
+
resp = PIGEON.contacts.find_by_email 'a@a.a'
|
86
|
+
validate_response resp, 404, 'error', /contact=a@a.a not found/
|
87
|
+
end
|
88
|
+
|
89
|
+
it 'should update contact' do
|
90
|
+
|
91
|
+
list_response = PIGEON.lists.create('My List', 'John Doe', "a@a.a")
|
92
|
+
resp = PIGEON.contacts.upsert list_response.list.id,
|
93
|
+
:email => "mary@e.e", :first_name => "Mary", :last_name => "Doe"
|
94
|
+
validate_response resp, 200, 'success', /contact=mary@e.e created\/updated successfully/
|
95
|
+
PIGEON.contacts.find_by_email("mary@e.e").last_name.should eq 'Doe'
|
96
|
+
|
97
|
+
resp = PIGEON.contacts.upsert list_response.list.id,
|
98
|
+
:email => 'mary@e.e', :first_name => 'Mary', :last_name => 'Johns'
|
99
|
+
validate_response resp, 200, 'success', /contact=mary@e.e created\/updated successfully/
|
100
|
+
PIGEON.contacts.find_by_email("mary@e.e").last_name.should eq 'Johns'
|
101
|
+
end
|
102
|
+
|
103
|
+
it 'cannot delete contact with non-existent email' do
|
104
|
+
res = PIGEON.contacts.delete("g@g.g")
|
105
|
+
validate_response res, 404, 'error', /contact=g@g.g not found/
|
106
|
+
end
|
107
|
+
|
108
|
+
it 'should not delete suppressed contact' do
|
109
|
+
res = PIGEON.contacts.delete("suppressed@e.e")
|
110
|
+
validate_response res, 400, 'error', /contact=suppressed@e.e is in suppress list/
|
111
|
+
end
|
112
|
+
|
113
|
+
it 'should delete single contact from all lists' do
|
114
|
+
list_response = PIGEON.lists.create 'My List', 'Jane Doe', 'a@a.a'
|
115
|
+
PIGEON.contacts.upsert list_response.list.id, :email => 'mary@e.e'
|
116
|
+
res = PIGEON.contacts.delete 'mary@e.e'
|
117
|
+
validate_response res, 200, 'success', /contact=mary@e.e deleted successfully/
|
118
|
+
PIGEON.lists.delete list_response.list.id
|
119
|
+
end
|
120
|
+
|
121
|
+
it 'deletes single contact from single list' do
|
122
|
+
list_response = PIGEON.lists.create 'My List', 'John D.', 'a@a.a'
|
123
|
+
list_response_2 = PIGEON.lists.create('My List2', "Jane D.", 'a@a.a')
|
124
|
+
PIGEON.contacts.upsert(list_response.list.id, {:email => 'mary@e.e'})
|
125
|
+
PIGEON.contacts.upsert(list_response_2.list.id, {:email => 'mary@e.e'})
|
126
|
+
|
127
|
+
res = PIGEON.contacts.delete 'mary@e.e', list_response.list.id
|
128
|
+
|
129
|
+
validate_response res, 200, 'success', /contact=mary@e.e deleted successfully/
|
130
|
+
|
131
|
+
contacts_exported = ''
|
132
|
+
PIGEON.lists.csv list_response.list.id do |c|
|
133
|
+
contacts_exported << c
|
134
|
+
end
|
135
|
+
contacts_exported = contacts_exported.split /\n/
|
136
|
+
contacts_exported.size.should eq 1
|
137
|
+
|
138
|
+
contacts_exported_2 = ''
|
139
|
+
PIGEON.lists.csv list_response_2.list.id do |c|
|
140
|
+
contacts_exported_2 << c
|
141
|
+
end
|
142
|
+
|
143
|
+
contacts_exported_2 = contacts_exported_2.split /\n/
|
144
|
+
contacts_exported_2.size.should eq 2
|
145
|
+
contacts_exported_2[1].should =~ /"mary@e.e"/
|
146
|
+
|
147
|
+
PIGEON.lists.delete(list_response.list.id)
|
148
|
+
PIGEON.lists.delete(list_response_2.list.id)
|
149
|
+
PIGEON.contacts.delete('mary@e.e')
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
data/spec/lists_spec.rb
ADDED
@@ -0,0 +1,149 @@
|
|
1
|
+
require './lib/expresspigeon-ruby'
|
2
|
+
require 'pigeon_helper'
|
3
|
+
|
4
|
+
describe 'contacts integration test' do
|
5
|
+
|
6
|
+
include PigeonSpecHelper
|
7
|
+
|
8
|
+
it 'test_create_and_delete_new_list(self):' do
|
9
|
+
contact_list = PIGEON.lists.create 'Active customers', 'Bob', 'bob@acmetools.com'
|
10
|
+
|
11
|
+
puts "*****************************"
|
12
|
+
puts contact_list
|
13
|
+
|
14
|
+
validate_response contact_list, 200, 'success', /list=#{contact_list.list.id} created\/updated successfully/
|
15
|
+
contact_list.list.name.should eq "Active customers"
|
16
|
+
contact_list.list.from_name.should eq "Bob"
|
17
|
+
contact_list.list.reply_to.should eq "bob@acmetools.com"
|
18
|
+
contact_list.list.contact_count.should eq 0
|
19
|
+
|
20
|
+
#TODO: uncomment when running against real test env
|
21
|
+
#contact_list.list.zip.should eq '220000'
|
22
|
+
#contact_list.list.state.should eq "AL"
|
23
|
+
#contact_list.list.address1.should eq "Coolman 11"
|
24
|
+
#contact_list.list.city.should eq "Minsk"
|
25
|
+
#contact_list.list.country.should eq "Belarus"
|
26
|
+
#contact_list.list.organization.should eq "ExpressPigeon"
|
27
|
+
|
28
|
+
res = PIGEON.lists.delete(contact_list.list.id)
|
29
|
+
validate_response res, 200, 'success', /list=#{contact_list.list.id} deleted successfully/
|
30
|
+
end
|
31
|
+
|
32
|
+
#TODO: implement Lists.update method
|
33
|
+
it 'should update existing list' do
|
34
|
+
|
35
|
+
existing_list = PIGEON.lists.create("Update", "Bob", "bob@acmetools.com")
|
36
|
+
#res = PIGEON.lists.update existing_list.list.id, :name => 'Updated Name', :from_name => 'Bill'
|
37
|
+
#
|
38
|
+
#validate_response res, 200, 'success', /list=#{res.list.id} created\/updated successfully/
|
39
|
+
#res.list.name.should eq "Updated Name"
|
40
|
+
#res.list.from_name.should eq 'Bill'
|
41
|
+
#PIGEON.lists.delete res.list.id
|
42
|
+
end
|
43
|
+
|
44
|
+
|
45
|
+
it 'should upload contacts'
|
46
|
+
|
47
|
+
list_name = "Upload_#{Kernel.rand(9999).to_s}"
|
48
|
+
existing_list = PIGEON.lists.create(list_name, 'Bob', 'bob@acmetools.com')
|
49
|
+
|
50
|
+
#res = PIGEON.lists.upload(existing_list.list.id, self.file_to_upload)
|
51
|
+
|
52
|
+
|
53
|
+
#self.assertEqual(res.status, "success")
|
54
|
+
#self.assertEqual(res.code, 200)
|
55
|
+
#self.assertEquals(res.message, "file uploaded successfully")
|
56
|
+
#self.assertTrue(res.upload_id is not None)
|
57
|
+
#
|
58
|
+
#sleep(5)
|
59
|
+
#
|
60
|
+
#res = self.api.lists.upload_status(res.upload_id)
|
61
|
+
#self.assertEqual(res.message, "file upload completed")
|
62
|
+
#self.assertEqual(res.status, "success")
|
63
|
+
#self.assertEqual(res.code, 200)
|
64
|
+
#report = res.report
|
65
|
+
#self.assertTrue(report.completed)
|
66
|
+
#self.assertFalse(report.failed)
|
67
|
+
#self.assertEqual(report.suppressed, 0)
|
68
|
+
#self.assertEqual(report.skipped, 0)
|
69
|
+
#self.assertEqual(report.list_name, list_name)
|
70
|
+
#self.assertEqual(report.imported, 2)
|
71
|
+
|
72
|
+
# def test_upsert_list_with_non_existent_id(self):
|
73
|
+
# res = self.api.lists.update(-1, {"name": "Updated Name", "from_name": "Bill"})
|
74
|
+
# self.assertEqual(res.status, "error")
|
75
|
+
# self.assertEqual(res.code, 404)
|
76
|
+
# self.assertEqual(res.message, "list=-1 not found")
|
77
|
+
#
|
78
|
+
# def test_delete_list_with_non_existent_id(self):
|
79
|
+
# res = self.api.lists.delete(-1)
|
80
|
+
# self.assertEqual(res.status, "error")
|
81
|
+
# self.assertEqual(res.code, 404)
|
82
|
+
# self.assertEqual(res.message, "list=-1 not found")
|
83
|
+
#
|
84
|
+
# def test_remove_disabled_list(self):
|
85
|
+
# res = self.api.lists.delete(130)
|
86
|
+
# self.assertEqual(res.code, 400)
|
87
|
+
# self.assertEqual(res.status, "error")
|
88
|
+
# self.assertEqual(res.message, "could not delete disabled list=130")
|
89
|
+
#
|
90
|
+
# def test_upload_without_id(self):
|
91
|
+
# res = self.api.lists.upload("", self.file_to_upload)
|
92
|
+
# self.assertEqual(res.code, 400)
|
93
|
+
# self.assertEqual(res.status, "error")
|
94
|
+
# self.assertEqual(res.message, "you must provide list_id in URL")
|
95
|
+
#
|
96
|
+
# def test_upload_with_non_existent_id(self):
|
97
|
+
# res = self.api.lists.upload(-1, self.file_to_upload)
|
98
|
+
# self.assertEqual(res.code, 404)
|
99
|
+
# self.assertEqual(res.message, "list=-1 not found")
|
100
|
+
#
|
101
|
+
# def test_upload_status_without_upload_id(self):
|
102
|
+
# res = self.api.lists.upload_status("")
|
103
|
+
# self.assertEqual(res.code, 400)
|
104
|
+
# self.assertEqual(res.status, "error")
|
105
|
+
# self.assertEqual(res.message, "you must provide upload id")
|
106
|
+
#
|
107
|
+
# def test_enabled_list_removal(self):
|
108
|
+
# list_resp = self.api.lists.create("My list", "John", os.environ['EXPRESSPIGEON_API_USER'])
|
109
|
+
# self.api.contacts.upsert(list_resp.list.id, {"email": os.environ['EXPRESSPIGEON_API_USER']})
|
110
|
+
#
|
111
|
+
# now = datetime.datetime.now(pytz.UTC)
|
112
|
+
# schedule = self.format_date(now + datetime.timedelta(hours=1))
|
113
|
+
#
|
114
|
+
# res = self.api.campaigns.schedule(list_id=list_resp.list.id, template_id=self.template_id, name="My Campaign",
|
115
|
+
# from_name="John",
|
116
|
+
# reply_to=os.environ['EXPRESSPIGEON_API_USER'], subject="Hi",
|
117
|
+
# google_analytics=False,
|
118
|
+
# schedule_for=schedule)
|
119
|
+
# self.assertEqual(res.code, 200)
|
120
|
+
# self.assertEqual(res.status, "success")
|
121
|
+
# self.assertEqual(res.message, "new campaign created successfully")
|
122
|
+
# self.assertTrue(res.campaign_id is not None)
|
123
|
+
#
|
124
|
+
# res = self.api.lists.delete(list_resp.list.id)
|
125
|
+
# self.assertEqual(res.code, 400)
|
126
|
+
# self.assertEqual(res.status, "error")
|
127
|
+
# self.assertEqual(res.message,
|
128
|
+
# "could not delete list={0}, it has dependent subscriptions and/or scheduled campaigns".format(
|
129
|
+
# list_resp.list.id))
|
130
|
+
#
|
131
|
+
# def test_export_csv(self):
|
132
|
+
# list_response = self.api.lists.create("My List", "a@a.a", "a@a.a")
|
133
|
+
# self.api.contacts.upsert(list_response.list.id, {"email": "mary@a.a"})
|
134
|
+
#
|
135
|
+
# res = self.api.lists.csv(list_response.list.id).split("\n")
|
136
|
+
# self.assertEquals(len(res), 2)
|
137
|
+
# headers = '"Email", "First name", "Last name", "City", "Phone", "Company", "Title", "Address 1", "Address 2", ' \
|
138
|
+
# '"State", "Zip", "Country", "Date of birth", "custom_field_1", "custom_field_10", "custom_field_11", ' \
|
139
|
+
# '"custom_field_12", "custom_field_13", "custom_field_18", "custom_field_19", "custom_field_2", ' \
|
140
|
+
# '"custom_field_20", "custom_field_21", "custom_field_22", "custom_field_23", "custom_field_24", ' \
|
141
|
+
# '"custom_field_3", "custom_field_4", "custom_field_5", "custom_field_6", "custom_field_7", ' \
|
142
|
+
# '"custom_field_8", "custom_field_9"'
|
143
|
+
# self.assertEquals(res[0], headers)
|
144
|
+
# self.assertEquals(res[1], '"mary@a.a",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,')
|
145
|
+
#
|
146
|
+
# self.api.lists.delete(list_response.list.id)
|
147
|
+
# self.api.contacts.delete("mary@a.a")
|
148
|
+
|
149
|
+
end
|
@@ -0,0 +1,127 @@
|
|
1
|
+
require './lib/expresspigeon-ruby'
|
2
|
+
require 'pigeon_helper'
|
3
|
+
|
4
|
+
describe 'transactional messages integration test' do
|
5
|
+
|
6
|
+
include PigeonSpecHelper
|
7
|
+
|
8
|
+
#def test_sending_message_and_report_without_params(self):
|
9
|
+
# res = self.api.messages.send_message(template_id=-1, to="", reply_to="", from_name="", subject="")
|
10
|
+
# self.assertEqual(res.code, 400)
|
11
|
+
# self.assertEqual(res.status, "error")
|
12
|
+
# self.assertEqual(res.message, "Required fields: template_id, reply_to, from, to, and subject")
|
13
|
+
#
|
14
|
+
#def test_sending_message_and_report_with_wrong_email_in_to(self):
|
15
|
+
# res = self.api.messages.send_message(template_id=-1, to="e", reply_to="a@a.a", from_name="me", subject="Hi")
|
16
|
+
# self.assertEqual(res.code, 400)
|
17
|
+
# self.assertEqual(res.status, "error")
|
18
|
+
# self.assertEqual(res.message, "Email in the 'to' field is not valid")
|
19
|
+
#
|
20
|
+
#def test_sending_message_and_report_with_wrong_email_in_reply_to(self):
|
21
|
+
# res = self.api.messages.send_message(template_id=-1, to="e@e.e", reply_to="a", from_name="me", subject="Hi")
|
22
|
+
# self.assertEqual(res.code, 400)
|
23
|
+
# self.assertEqual(res.status, "error")
|
24
|
+
# self.assertEqual(res.message, "Email in the 'reply_to' field is not valid")
|
25
|
+
#
|
26
|
+
#def test_sending_message_and_report_with_wrong_template_id(self):
|
27
|
+
# res = self.api.messages.send_message(template_id=-1, to="e@e.e", reply_to="a@a.a", from_name="me", subject="Hi")
|
28
|
+
# self.assertEqual(res.code, 400)
|
29
|
+
# self.assertEqual(res.status, "error")
|
30
|
+
# self.assertEqual(res.message, "template=-1 not found")
|
31
|
+
|
32
|
+
|
33
|
+
#TODO: complete the spec
|
34
|
+
it 'sends a single transactional message' do
|
35
|
+
message_response = PIGEON.messages.send_message 4905, ENV['TARGET_EMAIL'], ENV['TARGET_EMAIL'], "Team ExpressPigeon", "Hi there!",
|
36
|
+
:first_name => "Igor"
|
37
|
+
validate_response message_response, 200, 'success', /email queued/
|
38
|
+
report = PIGEON.messages.report(message_response.id)
|
39
|
+
report.id.should eq message_response.id
|
40
|
+
end
|
41
|
+
|
42
|
+
|
43
|
+
#
|
44
|
+
#def test_reports_with_bad_dates(self):
|
45
|
+
# res = self.api.messages.reports("abc", "")
|
46
|
+
# self.assertEquals(res.code, 400)
|
47
|
+
# self.assertEquals(res.status, "error")
|
48
|
+
# self.assertEquals(res.message, "invalid 'start_date' or 'end_date'")
|
49
|
+
#
|
50
|
+
#def test_reports_with_start_date_only(self):
|
51
|
+
# res = self.api.messages.reports("2013-03-16T11:22:23.210+0000", "")
|
52
|
+
# self.assertEquals(res.code, 400)
|
53
|
+
# self.assertEquals(res.status, "error")
|
54
|
+
# self.assertEquals(res.message, "'start_date' and 'end_date' should be provided together")
|
55
|
+
#
|
56
|
+
#def test_reports_with_end_date_only(self):
|
57
|
+
# res = self.api.messages.reports("", "2013-03-16T11:22:23.210+0000")
|
58
|
+
# self.assertEquals(res.code, 400)
|
59
|
+
# self.assertEquals(res.status, "error")
|
60
|
+
# self.assertEquals(res.message, "'start_date' and 'end_date' should be provided together")
|
61
|
+
#
|
62
|
+
#def test_sending_multiple_messages_and_get_reports(self):
|
63
|
+
# message_response = self.api.messages.send_message(template_id=self.template_id,
|
64
|
+
# to=os.environ['EXPRESSPIGEON_API_USER'],
|
65
|
+
# reply_to="a@a.a", from_name="me", subject="Hi",
|
66
|
+
# merge_fields={"first_name": "Gleb"})
|
67
|
+
# self.assertEqual(message_response.code, 200)
|
68
|
+
# self.assertEqual(message_response.status, "success")
|
69
|
+
# self.assertEqual(message_response.message, "email queued")
|
70
|
+
# self.assertTrue(message_response.id is not None and message_response.id != "")
|
71
|
+
#
|
72
|
+
# message_response_2 = self.api.messages.send_message(template_id=self.template_id,
|
73
|
+
# to=os.environ['EXPRESSPIGEON_API_USER'],
|
74
|
+
# reply_to="a@a.a", from_name="me", subject="Hi 2",
|
75
|
+
# merge_fields={"first_name": "Gleb"})
|
76
|
+
# self.assertEqual(message_response_2.code, 200)
|
77
|
+
# self.assertEqual(message_response_2.status, "success")
|
78
|
+
# self.assertEqual(message_response_2.message, "email queued")
|
79
|
+
# self.assertTrue(message_response_2.id is not None and message_response.id != "")
|
80
|
+
#
|
81
|
+
# report = self.__get_report_by_id__(message_response.id)
|
82
|
+
#
|
83
|
+
# self.assertEquals(report.id, message_response.id)
|
84
|
+
# self.assertEquals(report.email, os.environ['EXPRESSPIGEON_API_USER'])
|
85
|
+
# self.assertTrue(report.in_transit is not None)
|
86
|
+
#
|
87
|
+
# report2 = self.__get_report_by_id__(message_response_2.id)
|
88
|
+
#
|
89
|
+
# self.assertEquals(report2.id, message_response_2.id)
|
90
|
+
# self.assertEquals(report2.email, os.environ['EXPRESSPIGEON_API_USER'])
|
91
|
+
# self.assertTrue(report2.in_transit is not None)
|
92
|
+
#
|
93
|
+
it 'test_sending_multiple_messages_and_get_reports_for_today(self):' do
|
94
|
+
|
95
|
+
start = Time.now.utc - 60 # one minute ago
|
96
|
+
|
97
|
+
message_response = PIGEON.messages.send_message 4905, ENV['TARGET_EMAIL'], ENV['TARGET_EMAIL'],
|
98
|
+
'Team EP', "Hi, there!", :first_name => "Bob"
|
99
|
+
|
100
|
+
validate_response message_response, 200, 'success', /email queued/
|
101
|
+
message_response.id should_not be_nil
|
102
|
+
|
103
|
+
message_response2 = PIGEON.messages.send_message 4905, ENV['TARGET_EMAIL'], ENV['TARGET_EMAIL'],
|
104
|
+
'Team EP', "Hi, there!", :first_name => "Bob"
|
105
|
+
validate_response message_response2, 200, 'success', /email queued/
|
106
|
+
message_response2.id should_not be_nil
|
107
|
+
|
108
|
+
finish = start + 120 # two minutes after start
|
109
|
+
reports = PIGEON.messages.reports (message_response.id - 1), start, finish
|
110
|
+
|
111
|
+
reports.size.should eq 2
|
112
|
+
reports[0]['id'].should eq message_response.id
|
113
|
+
reports[1]['id'].should eq message_response2.id
|
114
|
+
|
115
|
+
reports[0]['email'].should eq ENV['TARGET_EMAIL']
|
116
|
+
reports[1]['email'].should eq ENV['TARGET_EMAIL']
|
117
|
+
end
|
118
|
+
#
|
119
|
+
#def __get_report_by_id__(self, message_id, start_date=None, end_date=None):
|
120
|
+
# reports = self.api.messages.reports() if start_date is None and end_date is None else \
|
121
|
+
# self.api.messages.reports(start_date, end_date)
|
122
|
+
# report = [r for r in reports if r.id == message_id]
|
123
|
+
# self.assertEquals(len(report), 1)
|
124
|
+
# return report[0]
|
125
|
+
|
126
|
+
|
127
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
PIGEON ||= ExpressPigeon::API
|
2
|
+
TEMPLATE_ID ||= 1
|
3
|
+
LIST_ID ||= 12
|
4
|
+
API_USER ||= "non@non.non"
|
5
|
+
DISABLED_LIST ||= 12
|
6
|
+
|
7
|
+
module PigeonSpecHelper
|
8
|
+
def validate_response res, code, status, message
|
9
|
+
res.code.should eq code
|
10
|
+
res.status.should eq status
|
11
|
+
if message
|
12
|
+
(res.message =~ message).should_not be_nil
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
16
|
+
end
|
metadata
ADDED
@@ -0,0 +1,82 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: expresspigeon-ruby
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- ipolevoy
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2014-01-28 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rspec
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '2.6'
|
22
|
+
type: :development
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ~>
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '2.6'
|
30
|
+
description: ExpressPigeon Ruby API for sending transactional messages, manipulating
|
31
|
+
lists, contacts nad more
|
32
|
+
email:
|
33
|
+
- ipolevoy@groupon.com
|
34
|
+
executables: []
|
35
|
+
extensions: []
|
36
|
+
extra_rdoc_files: []
|
37
|
+
files:
|
38
|
+
- .gitignore
|
39
|
+
- .rvmrc
|
40
|
+
- Gemfile
|
41
|
+
- Gemfile.lock
|
42
|
+
- LICENSE.txt
|
43
|
+
- README.md
|
44
|
+
- Rakefile
|
45
|
+
- expresspigeon-ruby.gemspec
|
46
|
+
- lib/expresspigeon-ruby.rb
|
47
|
+
- lib/expresspigeon-ruby/version.rb
|
48
|
+
- spec/campaigns_spec.rb
|
49
|
+
- spec/contacts_spec.rb
|
50
|
+
- spec/lists_spec.rb
|
51
|
+
- spec/messages_spec.rb
|
52
|
+
- spec/pigeon_helper.rb
|
53
|
+
homepage: https://github.com/expresspigeon/expresspigeon-ruby
|
54
|
+
licenses: []
|
55
|
+
post_install_message:
|
56
|
+
rdoc_options: []
|
57
|
+
require_paths:
|
58
|
+
- lib
|
59
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
60
|
+
none: false
|
61
|
+
requirements:
|
62
|
+
- - ! '>='
|
63
|
+
- !ruby/object:Gem::Version
|
64
|
+
version: '0'
|
65
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
66
|
+
none: false
|
67
|
+
requirements:
|
68
|
+
- - ! '>='
|
69
|
+
- !ruby/object:Gem::Version
|
70
|
+
version: '0'
|
71
|
+
requirements: []
|
72
|
+
rubyforge_project:
|
73
|
+
rubygems_version: 1.8.25
|
74
|
+
signing_key:
|
75
|
+
specification_version: 3
|
76
|
+
summary: ExpressPigeon API Ruby Wrapper
|
77
|
+
test_files:
|
78
|
+
- spec/campaigns_spec.rb
|
79
|
+
- spec/contacts_spec.rb
|
80
|
+
- spec/lists_spec.rb
|
81
|
+
- spec/messages_spec.rb
|
82
|
+
- spec/pigeon_helper.rb
|