express_pigeon 1.0.4 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (96) hide show
  1. checksums.yaml +7 -0
  2. data/.env.example +1 -0
  3. data/.gitignore +19 -16
  4. data/.rspec +1 -0
  5. data/.rubocop.yml +17 -0
  6. data/.rubocop_todo.yml +15 -0
  7. data/.ruby-gemset +1 -0
  8. data/.ruby-version +1 -0
  9. data/CONTRIBUTING.md +21 -0
  10. data/Gemfile +13 -8
  11. data/Guardfile +56 -0
  12. data/LICENSE +9 -2
  13. data/README.md +4 -124
  14. data/Rakefile +1 -2
  15. data/express_pigeon.gemspec +31 -16
  16. data/lib/express_pigeon/api/campaigns.rb +62 -0
  17. data/lib/express_pigeon/api/contacts.rb +42 -0
  18. data/lib/express_pigeon/api/lists.rb +49 -0
  19. data/lib/express_pigeon/api/messages.rb +56 -0
  20. data/lib/express_pigeon/api.rb +66 -0
  21. data/lib/express_pigeon/autoresponders.rb +0 -0
  22. data/lib/express_pigeon/contacts.rb +71 -0
  23. data/lib/express_pigeon/lists.rb +111 -0
  24. data/lib/express_pigeon/meta_hash.rb +20 -0
  25. data/lib/express_pigeon/templates.rb +4 -0
  26. data/lib/express_pigeon/transactional_emails.rb +4 -0
  27. data/lib/express_pigeon/version.rb +1 -1
  28. data/lib/express_pigeon.rb +16 -442
  29. data/spec/express_pigeon/api/campaigns_spec.rb +100 -0
  30. data/spec/express_pigeon/api/contacts_spec.rb +146 -0
  31. data/spec/express_pigeon/api/lists_spec.rb +23 -0
  32. data/spec/express_pigeon/api/messages_spec.rb +36 -0
  33. data/spec/express_pigeon/contacts_spec.rb +111 -0
  34. data/spec/express_pigeon/lists_spec.rb +131 -0
  35. data/spec/fixtures/contacts.csv +2 -0
  36. data/spec/fixtures/contacts.csv.zip +0 -0
  37. data/spec/spec_helper.rb +100 -12
  38. data/vendor/cache/ast-2.0.0.gem +0 -0
  39. data/vendor/cache/astrolabe-1.3.0.gem +0 -0
  40. data/vendor/cache/awesome_print-1.2.0.gem +0 -0
  41. data/vendor/cache/byebug-3.5.1.gem +0 -0
  42. data/vendor/cache/celluloid-0.16.0.gem +0 -0
  43. data/vendor/cache/coderay-1.1.0.gem +0 -0
  44. data/vendor/cache/colorize-0.7.5.gem +0 -0
  45. data/vendor/cache/columnize-0.9.0.gem +0 -0
  46. data/vendor/cache/debugger-linecache-1.2.0.gem +0 -0
  47. data/vendor/cache/diff-lcs-1.2.5.gem +0 -0
  48. data/vendor/cache/docile-1.1.5.gem +0 -0
  49. data/vendor/cache/dotenv-1.0.2.gem +0 -0
  50. data/vendor/cache/ffi-1.9.6.gem +0 -0
  51. data/vendor/cache/formatador-0.2.5.gem +0 -0
  52. data/vendor/cache/guard-2.10.5.gem +0 -0
  53. data/vendor/cache/guard-compat-1.2.0.gem +0 -0
  54. data/vendor/cache/guard-rspec-4.5.0.gem +0 -0
  55. data/vendor/cache/hitimes-1.2.2.gem +0 -0
  56. data/vendor/cache/httmultiparty-0.3.16.gem +0 -0
  57. data/vendor/cache/httparty-0.13.3.gem +0 -0
  58. data/vendor/cache/json-1.8.1.gem +0 -0
  59. data/vendor/cache/listen-2.8.4.gem +0 -0
  60. data/vendor/cache/lumberjack-1.0.9.gem +0 -0
  61. data/vendor/cache/method_source-0.8.2.gem +0 -0
  62. data/vendor/cache/mimemagic-0.2.1.gem +0 -0
  63. data/vendor/cache/multi_json-1.10.1.gem +0 -0
  64. data/vendor/cache/multi_xml-0.5.5.gem +0 -0
  65. data/vendor/cache/multipart-post-2.0.0.gem +0 -0
  66. data/vendor/cache/nenv-0.1.1.gem +0 -0
  67. data/vendor/cache/parser-2.2.0.pre.8.gem +0 -0
  68. data/vendor/cache/powerpack-0.0.9.gem +0 -0
  69. data/vendor/cache/pry-0.10.1.gem +0 -0
  70. data/vendor/cache/pry-byebug-2.0.0.gem +0 -0
  71. data/vendor/cache/rainbow-2.0.0.gem +0 -0
  72. data/vendor/cache/rake-10.4.2.gem +0 -0
  73. data/vendor/cache/rb-fsevent-0.9.4.gem +0 -0
  74. data/vendor/cache/rb-inotify-0.9.5.gem +0 -0
  75. data/vendor/cache/rspec-3.1.0.gem +0 -0
  76. data/vendor/cache/rspec-core-3.1.7.gem +0 -0
  77. data/vendor/cache/rspec-expectations-3.1.2.gem +0 -0
  78. data/vendor/cache/rspec-mocks-3.1.3.gem +0 -0
  79. data/vendor/cache/rspec-support-3.1.2.gem +0 -0
  80. data/vendor/cache/rubocop-0.28.0.gem +0 -0
  81. data/vendor/cache/ruby-progressbar-1.7.1.gem +0 -0
  82. data/vendor/cache/simplecov-0.9.1.gem +0 -0
  83. data/vendor/cache/simplecov-html-0.8.0.gem +0 -0
  84. data/vendor/cache/slop-3.6.0.gem +0 -0
  85. data/vendor/cache/thor-0.19.1.gem +0 -0
  86. data/vendor/cache/timers-4.0.1.gem +0 -0
  87. metadata +183 -53
  88. data/.rvmrc +0 -52
  89. data/.travis.yml +0 -8
  90. data/CHANGELOG +0 -6
  91. data/bin/console +0 -12
  92. data/express_pigeon-rb.yml +0 -10
  93. data/lib/active_model/validations/date_format_validator.rb +0 -20
  94. data/script/lint +0 -6
  95. data/script/multispec +0 -23
  96. data/spec/web_forms_spec.rb +0 -164
@@ -0,0 +1,146 @@
1
+ # RSpec.describe 'contacts integration test', skip: true do
2
+ # include PigeonSpecHelper
3
+ #
4
+ # it 'should not create contact without contact data' do
5
+ # resp = PIGEON.contacts.upsert(-1, {})
6
+ # validate_response resp, 400, 'error', /contact and contact.email are required/
7
+ # end
8
+ # it 'should not create contact without email' do
9
+ # resp = PIGEON.contacts.upsert -1, email: '', first_name: 'Marylin', last_name: 'Monroe'
10
+ # validate_response resp, 400, 'error', /contact and contact.email are required/
11
+ # end
12
+ #
13
+ # it 'should not add contact with too many custom fields' do
14
+ # custom_fields = {}
15
+ # (1..25).each { |n| custom_fields["custom_field_#{n}"] = n }
16
+ # resp = PIGEON.contacts.upsert -1, email: 'mary@e.e', custom_fields: custom_fields
17
+ # validate_response resp, 400, 'error', /You cannot create more than 20 custom fields. Use one of the 'custom_fields'./
18
+ # end
19
+ #
20
+ # it 'should not create new contact without list_id' do
21
+ # resp = PIGEON.contacts.upsert '', email: 'ee@e.e', first_name: 'Marylin', last_name: 'Monroe'
22
+ # validate_response resp, 404, 'error', /contact=ee@e.e not found/
23
+ # end
24
+ #
25
+ # it 'test_create_with_suppressed_contact' do
26
+ # resp = PIGEON.contacts.upsert -1, email: 'suppressed@e.e'
27
+ # validate_response resp, 400, 'error', /contact=suppressed@e.e is in suppress list/
28
+ # end
29
+ #
30
+ # it 'cannot create with non-existent_list' do
31
+ # resp = PIGEON.contacts.upsert -1, email: 'e@e.e'
32
+ # validate_response resp, 404, 'error', /list=-1 not found/
33
+ # end
34
+ #
35
+ # it 'creates list with contacts' do
36
+ # list_response = PIGEON.lists.create 'My List', 'John Doe', 'john@doe.com'
37
+ # list_id = list_response.list.id
38
+ # resp = PIGEON.contacts.upsert list_id, email: 'mary@e.e',
39
+ # custom_fields: { custom_field_1: 'custom_value_1' }
40
+ # validate_response resp, 200, 'success', /contact=mary@e.e created\/updated successfully/
41
+ # resp.contact.custom_fields.custom_field_1.should eq 'custom_value_1'
42
+ # resp.contact.email.should eq 'mary@e.e'
43
+ # resp.contact.email_format.should eq 'html'
44
+ # resp.contact.status.should eq 'ACTIVE'
45
+ # PIGEON.lists.delete(list_id)
46
+ # end
47
+ #
48
+ # it 'creates list non-existent custom field' do
49
+ # list_response = PIGEON.lists.create 'My List', 'John Doe', 'a@a.a'
50
+ # list_id = list_response.list.id
51
+ # resp = PIGEON.contacts.upsert(list_id, email: 'mary@e.e', custom_fields: { c: 'c' })
52
+ # validate_response resp, 200, 'success', nil
53
+ # PIGEON.lists.delete(list_id)
54
+ # end
55
+ #
56
+ # it 'cannot export contacts from list without list_id' do
57
+ # content = ''
58
+ # PIGEON.lists.csv '-1' do |c|
59
+ # content << c
60
+ # end
61
+ # resp = JSON.parse(content)
62
+ # validate_response MetaHash.new(resp), 404, 'error', /list=-1 not found/
63
+ # end
64
+ #
65
+ # it 'should get contacts from suppressed list' do
66
+ # content = ''
67
+ # PIGEON.lists.csv 'suppress_list' do |c|
68
+ # content += c
69
+ # end
70
+ # resp = content.split /\n/
71
+ # resp.size.should eq 2
72
+ # resp[1].should =~ /"suppressed@e.e","Suppressed","Doe"/
73
+ # end
74
+ #
75
+ # it 'should get single contact' do
76
+ # resp = PIGEON.contacts.find_by_email 'suppressed@e.e'
77
+ # resp.email.should eq 'suppressed@e.e'
78
+ # end
79
+ #
80
+ # it 'should not find non existent contact' do
81
+ # resp = PIGEON.contacts.find_by_email 'a@a.a'
82
+ # validate_response resp, 404, 'error', /contact=a@a.a not found/
83
+ # end
84
+ #
85
+ # it 'should update contact' do
86
+ # list_response = PIGEON.lists.create('My List', 'John Doe', 'a@a.a')
87
+ # resp = PIGEON.contacts.upsert list_response.list.id,
88
+ # email: 'mary@e.e', first_name: 'Mary', last_name: 'Doe'
89
+ # validate_response resp, 200, 'success', /contact=mary@e.e created\/updated successfully/
90
+ # PIGEON.contacts.find_by_email('mary@e.e').last_name.should eq 'Doe'
91
+ #
92
+ # resp = PIGEON.contacts.upsert list_response.list.id,
93
+ # email: 'mary@e.e', first_name: 'Mary', last_name: 'Johns'
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 'Johns'
96
+ # end
97
+ #
98
+ # it 'cannot delete contact with non-existent email' do
99
+ # res = PIGEON.contacts.delete('g@g.g')
100
+ # validate_response res, 404, 'error', /contact=g@g.g not found/
101
+ # end
102
+ #
103
+ # it 'should not delete suppressed contact' do
104
+ # res = PIGEON.contacts.delete('suppressed@e.e')
105
+ # validate_response res, 400, 'error', /contact=suppressed@e.e is in suppress list/
106
+ # end
107
+ #
108
+ # it 'should delete single contact from all lists' do
109
+ # list_response = PIGEON.lists.create 'My List', 'Jane Doe', 'a@a.a'
110
+ # PIGEON.contacts.upsert list_response.list.id, email: 'mary@e.e'
111
+ # res = PIGEON.contacts.delete 'mary@e.e'
112
+ # validate_response res, 200, 'success', /contact=mary@e.e deleted successfully/
113
+ # PIGEON.lists.delete list_response.list.id
114
+ # end
115
+ #
116
+ # it 'deletes single contact from single list' do
117
+ # list_response = PIGEON.lists.create 'My List', 'John D.', 'a@a.a'
118
+ # list_response_2 = PIGEON.lists.create('My List2', 'Jane D.', 'a@a.a')
119
+ # PIGEON.contacts.upsert(list_response.list.id, email: 'mary@e.e')
120
+ # PIGEON.contacts.upsert(list_response_2.list.id, email: 'mary@e.e')
121
+ #
122
+ # res = PIGEON.contacts.delete 'mary@e.e', list_response.list.id
123
+ #
124
+ # validate_response res, 200, 'success', /contact=mary@e.e deleted successfully/
125
+ #
126
+ # contacts_exported = ''
127
+ # PIGEON.lists.csv list_response.list.id do |c|
128
+ # contacts_exported << c
129
+ # end
130
+ # contacts_exported = contacts_exported.split /\n/
131
+ # contacts_exported.size.should eq 1
132
+ #
133
+ # contacts_exported_2 = ''
134
+ # PIGEON.lists.csv list_response_2.list.id do |c|
135
+ # contacts_exported_2 << c
136
+ # end
137
+ #
138
+ # contacts_exported_2 = contacts_exported_2.split /\n/
139
+ # contacts_exported_2.size.should eq 2
140
+ # contacts_exported_2[1].should =~ /"mary@e.e"/
141
+ #
142
+ # PIGEON.lists.delete(list_response.list.id)
143
+ # PIGEON.lists.delete(list_response_2.list.id)
144
+ # PIGEON.contacts.delete('mary@e.e')
145
+ # end
146
+ # #end
@@ -0,0 +1,23 @@
1
+ # RSpec.describe 'contacts integration test', skip: true do
2
+ # include PigeonSpecHelper
3
+ #
4
+ # it 'test_create_and_delete_new_list(self):' do
5
+ # contact_list = PIGEON.lists.create 'Active customers', 'Bob', 'bob@acmetools.com'
6
+ #
7
+ # validate_response contact_list, 200, 'success', /list=#{contact_list.list.id} created\/updated successfully/
8
+ # contact_list.list.name.should eq 'Active customers'
9
+ # contact_list.list.from_name.should eq 'Bob'
10
+ # contact_list.list.reply_to.should eq 'bob@acmetools.com'
11
+ # contact_list.list.contact_count.should eq 0
12
+ #
13
+ # res = PIGEON.lists.delete(contact_list.list.id)
14
+ # validate_response res, 200, 'success', /list=#{contact_list.list.id} deleted successfully/
15
+ # end
16
+ #
17
+ # it 'should update existing list' do
18
+ # existing_list = PIGEON.lists.create('Update', 'Bob', 'bob@acmetools.com')
19
+ # end
20
+ #
21
+ # list_name = "Upload_#{Kernel.rand(9999)}"
22
+ # existing_list = PIGEON.lists.create(list_name, 'Bob', 'bob@acmetools.com')
23
+ # end
@@ -0,0 +1,36 @@
1
+ # RSpec.describe 'transactional messages integration test', skip: true do
2
+ # include PigeonSpecHelper
3
+ #
4
+ # it 'sends a single transactional message' do
5
+ # message_response = PIGEON.messages.send_message 4905, ENV['TARGET_EMAIL'], ENV['TARGET_EMAIL'], 'Team ExpressPigeon', 'Hi there!', first_name: 'Igor'
6
+ #
7
+ # validate_response message_response, 200, 'success', /email queued/
8
+ # report = PIGEON.messages.report(message_response.id)
9
+ # report.id.should eq message_response.id
10
+ # end
11
+ #
12
+ # it 'test_sending_multiple_messages_and_get_reports_for_today(self):' do
13
+ # start = Time.now.utc - 60 # one minute ago
14
+ #
15
+ # message_response = PIGEON.messages.send_message 4905, ENV['TARGET_EMAIL'], ENV['TARGET_EMAIL'],
16
+ # 'Team EP', 'Hi, there!', first_name: 'Bob'
17
+ #
18
+ # validate_response message_response, 200, 'success', /email queued/
19
+ # message_response.id should_not be_nil
20
+ #
21
+ # message_response2 = PIGEON.messages.send_message 4905, ENV['TARGET_EMAIL'], ENV['TARGET_EMAIL'],
22
+ # 'Team EP', 'Hi, there!', first_name: 'Bob'
23
+ # validate_response message_response2, 200, 'success', /email queued/
24
+ # message_response2.id should_not be_nil
25
+ #
26
+ # finish = start + 120 # two minutes after start
27
+ # reports = PIGEON.messages.reports (message_response.id - 1), start, finish
28
+ #
29
+ # reports.size.should eq 2
30
+ # reports[0]['id'].should eq message_response.id
31
+ # reports[1]['id'].should eq message_response2.id
32
+ #
33
+ # reports[0]['email'].should eq ENV['TARGET_EMAIL']
34
+ # reports[1]['email'].should eq ENV['TARGET_EMAIL']
35
+ # end
36
+ # end
@@ -0,0 +1,111 @@
1
+ RSpec.describe ExpressPigeon::Contacts do
2
+ # WARN: These tests are assuming that the test
3
+ # account has three custom fields already
4
+ # defined on the account.
5
+ #
6
+ # - my_custom_text_field (no default)
7
+ # - my_custom_number_field (no default)
8
+ # - my_custom_date_field (no default)
9
+ #
10
+ # There isn't a way as of this commit to
11
+ # specify custom fields via the API. You'll
12
+ # have to configure them manually via the UI.
13
+
14
+ let(:auth_key) { ENV['EXPRESS_PIGEON_AUTH_KEY'] }
15
+ let(:name) { 'TEST List Name' }
16
+ let(:from_name) { 'Mike Hall' }
17
+ let(:reply_to) { 'mike@just3ws.com' }
18
+
19
+ let(:client) { ExpressPigeon::Contacts.new(auth_key) }
20
+
21
+ let(:contacts) do
22
+ [
23
+ {
24
+ 'email' => 'mike@just3ws.com',
25
+ 'first_name' => 'Mike',
26
+ 'last_name' => 'Hall',
27
+ 'my_custom_text_field' => 'some text value'
28
+ }
29
+ ]
30
+ end
31
+
32
+ before do
33
+ @list_a = ExpressPigeon::Lists.new(auth_key).create(
34
+ name: 'TEST List A',
35
+ from_name: 'Mike Hall',
36
+ reply_to: 'mike@just3ws.com'
37
+ )
38
+ @list_a_id = @list_a['list']['id']
39
+
40
+ @list_b = ExpressPigeon::Lists.new(auth_key).create(
41
+ name: 'TEST List B',
42
+ from_name: 'Mike Hall',
43
+ reply_to: 'mike@just3ws.com'
44
+ )
45
+ @list_b_id = @list_b['list']['id']
46
+ end
47
+
48
+ after do
49
+ ExpressPigeon::Lists.new(auth_key).index.select do |list|
50
+ list['name'] =~ /^TEST\s/i
51
+ end.map do |list|
52
+ list['id']
53
+ end.each do |list_id|
54
+ ExpressPigeon::Lists.new(auth_key).delete(list_id)
55
+ end
56
+ end
57
+
58
+ describe '#create' do
59
+ it 'creates a contact' do
60
+ response = client.create(@list_a_id, contacts)
61
+
62
+ expect(response['code']).to eq(200)
63
+ expect(response['contacts']).to eq(contacts.map { |contact| contact['email'] })
64
+ end
65
+ end
66
+
67
+ describe '#update' do
68
+ before do
69
+ client.create(@list_a_id, contacts)
70
+ end
71
+
72
+ it 'updates a contact' do
73
+ contacts.first['email'] = 'mike@ugtastic.com'
74
+
75
+ response = client.update(@list_a_id, contacts)
76
+
77
+ expect(response['code']).to eq(200)
78
+ expect(response['contacts']).to eq(contacts.map { |contact| contact['email'] })
79
+ end
80
+ end
81
+
82
+ describe '#move' do
83
+ let(:email_addresses) { ['mike@just3ws.com'] }
84
+
85
+ before do
86
+ client.create(@list_a_id, contacts)
87
+ end
88
+
89
+ it 'updates a contact' do
90
+ response = client.move(@list_a_id, @list_b_id, contacts)
91
+
92
+ expect(response['code']).to eq(200)
93
+ expect(response['message']).to eq("contacts moved from list=#{@list_a_id} to list=#{@list_b_id}")
94
+ end
95
+ end
96
+
97
+ describe '#find' do
98
+ before do
99
+ client.create(@list_a_id, contacts)
100
+ end
101
+
102
+ it 'finds an existing contact' do
103
+ response = client.find(contacts.first['email'])
104
+
105
+ expect(response.code).to eq(200)
106
+ expect(response['lists'].map { |list| list['id'] }).to include(@list_a_id)
107
+ expect(response['email']).to eq(contacts.first['email'])
108
+ expect(response['custom_fields']['my_custom_text_field']).to eq('some text value')
109
+ end
110
+ end
111
+ end
@@ -0,0 +1,131 @@
1
+ RSpec.describe ExpressPigeon::Lists do
2
+ let(:auth_key) { ENV['EXPRESS_PIGEON_AUTH_KEY'] }
3
+ let(:name) { 'TEST List Name' }
4
+ let(:from_name) { 'Mike Hall' }
5
+ let(:reply_to) { 'mike@just3ws.com' }
6
+
7
+ let(:client) { ExpressPigeon::Lists.new(auth_key) }
8
+
9
+ after do
10
+ ExpressPigeon::Lists.new(auth_key).index.select do |list|
11
+ list['name'] =~ /^TEST\s/i
12
+ end.map do |list|
13
+ list['id']
14
+ end.each do |list_id|
15
+ ExpressPigeon::Lists.new(auth_key).delete(list_id)
16
+ end
17
+ end
18
+
19
+ it '#index' do
20
+ response = client.index
21
+ expect(response.code).to eq(200)
22
+ end
23
+
24
+ it '#create' do
25
+ response = client.create(name: name, from_name: from_name, reply_to: reply_to)
26
+
27
+ expect(response['list']['id']).to be_a(Fixnum)
28
+
29
+ expect(response['code']).to eq(200)
30
+ expect(response['message']).to eq("list=#{response['list']['id']} created/updated successfully")
31
+ expect(response['list']['name']).to eq(name)
32
+ expect(response['list']['from_name']).to eq(from_name)
33
+ expect(response['list']['reply_to']).to eq(reply_to)
34
+ end
35
+
36
+ context 'existing list' do
37
+ before do
38
+ @created = client.create(name: name, from_name: from_name, reply_to: reply_to)
39
+ expect(@created['code']).to eq(200)
40
+
41
+ @list_id = @created['list']['id']
42
+ expect(@list_id).to be_a(Fixnum)
43
+ end
44
+
45
+ describe '#update(list_id, name, from_name, reply_to)' do
46
+ it 'modifies the list' do
47
+ name = 'TEST updated'
48
+ from_name = 'Changed'
49
+ reply_to = 'different@email.com'
50
+
51
+ response = client.update(
52
+ @list_id,
53
+ name: name,
54
+ from_name: from_name,
55
+ reply_to: reply_to
56
+ )
57
+
58
+ expect(response['code']).to eq(200)
59
+ expect(response['message']).to eq("list=#{@list_id} created/updated successfully")
60
+ expect(response['list']['name']).to eq(name)
61
+ expect(response['list']['from_name']).to eq(from_name)
62
+ expect(response['list']['reply_to']).to eq(reply_to)
63
+ end
64
+ end
65
+
66
+ describe '#upload(list_id, path)' do
67
+ it 'fails if file does not exist' do
68
+ path = 'thisisaninvalidfilepath'
69
+
70
+ expect { client.upload(@list_id, path) }.to raise_error("No file found at '#{path}'.")
71
+ end
72
+
73
+ it 'uploads a csv file' do
74
+ path = File.join(Dir.pwd, 'spec', 'fixtures', 'contacts.csv')
75
+ response = client.upload(@list_id, path)
76
+
77
+ expect(response['upload_id']).to be_a(Fixnum)
78
+ expect(response['code']).to eq(200)
79
+ expect(response['message']).to eq('file uploaded successfully')
80
+ end
81
+
82
+ it 'uploads a zipped csv' do
83
+ path = File.join(Dir.pwd, 'spec', 'fixtures', 'contacts.csv.zip')
84
+ response = client.upload(@list_id, path)
85
+
86
+ expect(response['upload_id']).to be_a(Fixnum)
87
+ expect(response['code']).to eq(200)
88
+ expect(response['message']).to eq('file uploaded successfully')
89
+ end
90
+
91
+ describe '#upload_status(list_id)' do
92
+ context 'already uploaded file' do
93
+ before do
94
+ path = File.join(Dir.pwd, 'spec', 'fixtures', 'contacts.csv')
95
+ @uploaded = client.upload(@list_id, path)
96
+ @upload_id = @uploaded['upload_id']
97
+ end
98
+
99
+ it 'has a status' do
100
+ response = client.upload_status(@upload_id)
101
+ expect(response['code']).to eq(200)
102
+ expect(response['report']['list_id']).to eq(@list_id)
103
+ end
104
+ end
105
+ end
106
+
107
+ describe '#download_csv(list_id, path)' do
108
+ context 'already uploaded file' do
109
+ before do
110
+ path = File.join(Dir.pwd, 'spec', 'fixtures', 'contacts.csv')
111
+ @uploaded = client.upload(@list_id, path)
112
+ end
113
+
114
+ it 'downloads a csv file' do
115
+ download_path = File.join(Dir.pwd, 'tmp', 'contacts.csv')
116
+ File.delete(download_path) if File.exist?(download_path)
117
+ response = client.download_csv(@list_id, download_path)
118
+
119
+ expect(response.code).to eq(200)
120
+ expect(File.exist?(download_path)).to eq(true)
121
+
122
+ # TODO: Parse the response.
123
+ # Right now the response is "valid" but the
124
+ # Ruby CSV parser is failing to handle the quotes.
125
+ # csv = CSV.read(download_path, headers: :first_row, quote_char: '"')
126
+ end
127
+ end
128
+ end
129
+ end
130
+ end
131
+ end
@@ -0,0 +1,2 @@
1
+ Email, First name, Last name, City, Phone, Company, Title, Address 1, Address 2, State, Zip, Country, Date of birth
2
+ "john@doe.com","John","Doe","Flagstaff",,"Acme Tools","Director","123 Pine St.",,"AZ","86001",,"04/03/1969"
Binary file
data/spec/spec_helper.rb CHANGED
@@ -1,20 +1,108 @@
1
+ require 'dotenv'
2
+ Dotenv.load
3
+
4
+ require 'express_pigeon'
5
+
6
+ # PIGEON ||= ExpressPigeon::API
7
+ TEMPLATE_ID ||= 1
8
+ LIST_ID ||= 12
9
+ API_USER ||= 'non@non.non'
10
+ DISABLED_LIST ||= 12
11
+
12
+ # module PigeonSpecHelper
13
+ # def validate_response(res, code, status, message)
14
+ # res.code.should eq code
15
+ # res.status.should eq status
16
+ # if message
17
+ # (res.message =~ message).should_not be_nil
18
+ # end
19
+ # end
20
+ # end
21
+
1
22
  # This file was generated by the `rspec --init` command. Conventionally, all
2
23
  # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
3
- # Require this file using `require "spec_helper.rb"` to ensure that it is only
4
- # loaded once.
24
+ # The generated `.rspec` file contains `--require spec_helper` which will cause this
25
+ # file to always be loaded, without a need to explicitly require it in any files.
26
+ #
27
+ # Given that it is always loaded, you are encouraged to keep this file as
28
+ # light-weight as possible. Requiring heavyweight dependencies from this file
29
+ # will add to the boot time of your test suite on EVERY test run, even for an
30
+ # individual file that may not need all of that loaded. Instead, consider making
31
+ # a separate helper file that requires the additional dependencies and performs
32
+ # the additional setup, and require it from the spec files that actually need it.
33
+ #
34
+ # The `.rspec` file also contains a few flags that are not defaults but that
35
+ # users commonly want.
5
36
  #
6
37
  # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
38
+ RSpec.configure do |config|
39
+ # rspec-expectations config goes here. You can use an alternate
40
+ # assertion/expectation library such as wrong or the stdlib/minitest
41
+ # assertions if you prefer.
42
+ config.expect_with :rspec do |expectations|
43
+ # This option will default to `true` in RSpec 4. It makes the `description`
44
+ # and `failure_message` of custom matchers include text for helper methods
45
+ # defined using `chain`, e.g.:
46
+ # be_bigger_than(2).and_smaller_than(4).description
47
+ # # => "be bigger than 2 and smaller than 4"
48
+ # ...rather than:
49
+ # # => "be bigger than 2"
50
+ expectations.include_chain_clauses_in_custom_matcher_descriptions = true
51
+ end
7
52
 
53
+ # rspec-mocks config goes here. You can use an alternate test double
54
+ # library (such as bogus or mocha) by changing the `mock_with` option here.
55
+ config.mock_with :rspec do |mocks|
56
+ # Prevents you from mocking or stubbing a method that does not exist on
57
+ # a real object. This is generally recommended, and will default to
58
+ # `true` in RSpec 4.
59
+ mocks.verify_partial_doubles = true
60
+ end
8
61
 
9
- $LOAD_PATH.unshift '.'
10
- $LOAD_PATH.unshift File.dirname(__FILE__) + "/../lib"
11
- require 'activemodel-rspec'
12
- require 'rspec/given'
13
-
14
- RSpec.configure do |config|
15
- config.include ActiveModelMatchers
16
- config.treat_symbols_as_metadata_keys_with_true_values = true
17
- config.run_all_when_everything_filtered = true
62
+ # The settings below are suggested to provide a good initial experience
63
+ # with RSpec, but feel free to customize to your heart's content.
64
+ # These two settings work together to allow you to limit a spec run
65
+ # to individual examples or groups you care about by tagging them with
66
+ # `:focus` metadata. When nothing is tagged with `:focus`, all examples
67
+ # get run.
18
68
  config.filter_run :focus
19
- config.filter_run_excluding :live => true
69
+ config.run_all_when_everything_filtered = true
70
+
71
+ # Limits the available syntax to the non-monkey patched syntax that is recommended.
72
+ # For more details, see:
73
+ # - http://myronmars.to/n/dev-blog/2012/06/rspecs-new-expectation-syntax
74
+ # - http://teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/
75
+ # - http://myronmars.to/n/dev-blog/2014/05/notable-changes-in-rspec-3#new__config_option_to_disable_rspeccore_monkey_patching
76
+ # config.disable_monkey_patching!
77
+
78
+ # This setting enables warnings. It's recommended, but in some cases may
79
+ # be too noisy due to issues in dependencies.
80
+ config.warnings = true
81
+
82
+ # Many RSpec users commonly either run the entire suite or an individual
83
+ # file, and it's useful to allow more verbose output when running an
84
+ # individual spec file.
85
+ if config.files_to_run.one?
86
+ # Use the documentation formatter for detailed output,
87
+ # unless a formatter has already been configured
88
+ # (e.g. via a command-line flag).
89
+ config.default_formatter = 'progress'
90
+ end
91
+
92
+ # Print the 10 slowest examples and example groups at the
93
+ # end of the spec run, to help surface which specs are running
94
+ # particularly slow.
95
+ config.profile_examples = 10
96
+
97
+ # Run specs in random order to surface order dependencies. If you find an
98
+ # order dependency and want to debug it, you can fix the order by providing
99
+ # the seed, which is printed after each run.
100
+ # --seed 1234
101
+ config.order = :random
102
+
103
+ # Seed global randomization in this process using the `--seed` CLI option.
104
+ # Setting this allows you to use `--seed` to deterministically reproduce
105
+ # test failures related to randomization by passing the same `--seed` value
106
+ # as the one that triggered the failure.
107
+ Kernel.srand config.seed
20
108
  end
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file