parity-sendgrid-api 0.0.4

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.
Files changed (99) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +6 -0
  3. data/.rspec +3 -0
  4. data/.travis.yml +3 -0
  5. data/.yardopts +6 -0
  6. data/Gemfile +17 -0
  7. data/Gemfile.lock +67 -0
  8. data/LICENSE +22 -0
  9. data/README.md +261 -0
  10. data/Rakefile +12 -0
  11. data/lib/sendgrid/api.rb +7 -0
  12. data/lib/sendgrid/api/client.rb +43 -0
  13. data/lib/sendgrid/api/entities/category.rb +13 -0
  14. data/lib/sendgrid/api/entities/email.rb +13 -0
  15. data/lib/sendgrid/api/entities/entity.rb +83 -0
  16. data/lib/sendgrid/api/entities/list.rb +30 -0
  17. data/lib/sendgrid/api/entities/marketing_email.rb +20 -0
  18. data/lib/sendgrid/api/entities/profile.rb +14 -0
  19. data/lib/sendgrid/api/entities/response.rb +21 -0
  20. data/lib/sendgrid/api/entities/response_insert.rb +23 -0
  21. data/lib/sendgrid/api/entities/response_remove.rb +23 -0
  22. data/lib/sendgrid/api/entities/schedule.rb +13 -0
  23. data/lib/sendgrid/api/entities/sender_address.rb +13 -0
  24. data/lib/sendgrid/api/entities/stats.rb +14 -0
  25. data/lib/sendgrid/api/newsletter/categories.rb +74 -0
  26. data/lib/sendgrid/api/newsletter/emails.rb +69 -0
  27. data/lib/sendgrid/api/newsletter/lists.rb +64 -0
  28. data/lib/sendgrid/api/newsletter/marketing_emails.rb +72 -0
  29. data/lib/sendgrid/api/newsletter/recipients.rb +55 -0
  30. data/lib/sendgrid/api/newsletter/schedule.rb +70 -0
  31. data/lib/sendgrid/api/newsletter/sender_addresses.rb +80 -0
  32. data/lib/sendgrid/api/newsletter/utils.rb +34 -0
  33. data/lib/sendgrid/api/rest/errors/error.rb +66 -0
  34. data/lib/sendgrid/api/rest/resource.rb +58 -0
  35. data/lib/sendgrid/api/rest/response/parse_error.rb +19 -0
  36. data/lib/sendgrid/api/rest/response/parse_json.rb +24 -0
  37. data/lib/sendgrid/api/service.rb +23 -0
  38. data/lib/sendgrid/api/version.rb +5 -0
  39. data/lib/sendgrid/api/web/mail.rb +44 -0
  40. data/lib/sendgrid/api/web/profile.rb +38 -0
  41. data/lib/sendgrid/api/web/stats.rb +36 -0
  42. data/sendgrid-api.gemspec +23 -0
  43. data/spec/fixtures/categories.json +11 -0
  44. data/spec/fixtures/emails/email.json +6 -0
  45. data/spec/fixtures/emails/emails.json +10 -0
  46. data/spec/fixtures/errors/already_exists.json +3 -0
  47. data/spec/fixtures/errors/bad_request.json +6 -0
  48. data/spec/fixtures/errors/database_error.json +3 -0
  49. data/spec/fixtures/errors/does_not_exist.json +3 -0
  50. data/spec/fixtures/errors/forbidden.json +3 -0
  51. data/spec/fixtures/errors/invalid_fields.json +3 -0
  52. data/spec/fixtures/errors/not_scheduled.json +3 -0
  53. data/spec/fixtures/errors/unauthorized.json +6 -0
  54. data/spec/fixtures/lists/list.json +5 -0
  55. data/spec/fixtures/lists/lists.json +11 -0
  56. data/spec/fixtures/marketing_emails/marketing_email.json +19 -0
  57. data/spec/fixtures/marketing_emails/marketing_emails.json +10 -0
  58. data/spec/fixtures/profile.json +18 -0
  59. data/spec/fixtures/recipients.json +8 -0
  60. data/spec/fixtures/schedule.json +3 -0
  61. data/spec/fixtures/sender_addresses/sender_address.json +11 -0
  62. data/spec/fixtures/sender_addresses/sender_addresses.json +11 -0
  63. data/spec/fixtures/stats.json +50 -0
  64. data/spec/fixtures/success.json +3 -0
  65. data/spec/sendgrid/api/client_spec.rb +38 -0
  66. data/spec/sendgrid/api/entities/category_spec.rb +14 -0
  67. data/spec/sendgrid/api/entities/email_spec.rb +15 -0
  68. data/spec/sendgrid/api/entities/entity_spec.rb +279 -0
  69. data/spec/sendgrid/api/entities/list_spec.rb +34 -0
  70. data/spec/sendgrid/api/entities/marketing_email_spec.rb +31 -0
  71. data/spec/sendgrid/api/entities/profile_spec.rb +26 -0
  72. data/spec/sendgrid/api/entities/response_insert_spec.rb +28 -0
  73. data/spec/sendgrid/api/entities/response_remove_spec.rb +28 -0
  74. data/spec/sendgrid/api/entities/response_spec.rb +28 -0
  75. data/spec/sendgrid/api/entities/schedule_spec.rb +14 -0
  76. data/spec/sendgrid/api/entities/sender_address_spec.rb +21 -0
  77. data/spec/sendgrid/api/entities/stats_spec.rb +25 -0
  78. data/spec/sendgrid/api/newsletter/categories_spec.rb +247 -0
  79. data/spec/sendgrid/api/newsletter/emails_spec.rb +265 -0
  80. data/spec/sendgrid/api/newsletter/lists_spec.rb +307 -0
  81. data/spec/sendgrid/api/newsletter/marketing_emails_spec.rb +306 -0
  82. data/spec/sendgrid/api/newsletter/recipients_spec.rb +252 -0
  83. data/spec/sendgrid/api/newsletter/schedule_spec.rb +263 -0
  84. data/spec/sendgrid/api/newsletter/sender_addresses_spec.rb +300 -0
  85. data/spec/sendgrid/api/rest/errors/error_spec.rb +121 -0
  86. data/spec/sendgrid/api/rest/resource_spec.rb +145 -0
  87. data/spec/sendgrid/api/rest/response/parse_error_spec.rb +39 -0
  88. data/spec/sendgrid/api/rest/response/parse_json_spec.rb +45 -0
  89. data/spec/sendgrid/api/service_spec.rb +44 -0
  90. data/spec/sendgrid/api/version_spec.rb +11 -0
  91. data/spec/sendgrid/api/web/mail_spec.rb +111 -0
  92. data/spec/sendgrid/api/web/profile_spec.rb +110 -0
  93. data/spec/sendgrid/api/web/stats_spec.rb +94 -0
  94. data/spec/spec_helper.rb +23 -0
  95. data/spec/support/helpers.rb +23 -0
  96. data/spec/support/mock.rb +30 -0
  97. data/spec/support/online.rb +114 -0
  98. data/spec/support/shared_examples.rb +104 -0
  99. metadata +225 -0
@@ -0,0 +1,121 @@
1
+ require 'spec_helper'
2
+
3
+ module Sendgrid
4
+ module API
5
+ module REST
6
+ module Errors
7
+ describe Error do
8
+ subject { described_class }
9
+
10
+ describe '.from_response' do
11
+ context 'when response has a status error' do
12
+ context 'known status' do
13
+ let(:env) do
14
+ { :status => 400,
15
+ :body => nil }
16
+ end
17
+
18
+ subject { described_class.from_response(env) }
19
+
20
+ it { should be_instance_of(Errors::BadRequest) }
21
+ end
22
+
23
+ context 'unknown status' do
24
+ let(:env) do
25
+ { :status => 413,
26
+ :body => nil }
27
+ end
28
+
29
+ subject { described_class.from_response(env) }
30
+
31
+ it { should be_instance_of(Errors::Unknown) }
32
+ end
33
+
34
+ context 'with message' do
35
+ let(:env) do
36
+ { :status => 400,
37
+ :body => { :error => 'error message' } }
38
+ end
39
+
40
+ subject { described_class.from_response(env) }
41
+
42
+ it { should == Errors::BadRequest.new('error message') }
43
+ end
44
+
45
+ context 'with multiple messages' do
46
+ let(:env) do
47
+ { :status => 400,
48
+ :body => { :errors => ['error message 1', 'error message 2'] } }
49
+ end
50
+
51
+ subject { described_class.from_response(env) }
52
+
53
+ it { should == Errors::BadRequest.new('error message 1, error message 2') }
54
+ end
55
+ end
56
+
57
+ context 'when response has body error' do
58
+ context 'when error is a Hash' do
59
+ context 'known status' do
60
+ let(:env) do
61
+ { :status => 200,
62
+ :body => { :error => { :code => 400 } } }
63
+ end
64
+
65
+ subject { described_class.from_response(env) }
66
+
67
+ it { should be_instance_of(Errors::BadRequest) }
68
+ end
69
+
70
+ context 'unknown status' do
71
+ let(:env) do
72
+ { :status => 200,
73
+ :body => { :error => { :code => 413 } } }
74
+ end
75
+
76
+ subject { described_class.from_response(env) }
77
+
78
+ it { should be_instance_of(Errors::Unknown) }
79
+ end
80
+
81
+ context 'with message' do
82
+ let(:env) do
83
+ { :status => 200,
84
+ :body => { :error => { :code => 400,
85
+ :message => 'error message' } } }
86
+ end
87
+
88
+ subject { described_class.from_response(env) }
89
+
90
+ it { should == Errors::BadRequest.new('error message') }
91
+ end
92
+ end
93
+
94
+ context 'when error is a String' do
95
+ let(:env) do
96
+ { :status => 200,
97
+ :body => { :error => 'error message' } }
98
+ end
99
+
100
+ subject { described_class.from_response(env) }
101
+
102
+ it { should == Errors::UnprocessableEntity.new('error message') }
103
+ end
104
+ end
105
+
106
+ context 'when response has no error' do
107
+ let(:env) do
108
+ { :status => 200,
109
+ :body => nil }
110
+ end
111
+
112
+ subject { described_class.from_response(env) }
113
+
114
+ it { should be_nil }
115
+ end
116
+ end
117
+ end
118
+ end
119
+ end
120
+ end
121
+ end
@@ -0,0 +1,145 @@
1
+ require 'spec_helper'
2
+
3
+ module Sendgrid
4
+ module API
5
+ module REST
6
+ describe Resource do
7
+ subject { resource }
8
+ let(:resource) { described_class.new(user, key) }
9
+ let(:user) { 'my_user' }
10
+ let(:key) { 'my_key' }
11
+
12
+ its(:user) { should == user }
13
+ its(:key) { should == key }
14
+
15
+ it 'should have a valid ENDPOINT' do
16
+ described_class::ENDPOINT.should == 'https://sendgrid.com/api'
17
+ end
18
+
19
+ describe '#post' do
20
+ let(:url) { 'any_path' }
21
+ let(:response) { double('response') }
22
+
23
+ context 'without params' do
24
+ before do
25
+ subject.should_receive(:request).with(:post, url, {}).and_return(response)
26
+ end
27
+
28
+ it 'should perform the request' do
29
+ subject.post(url).should == response
30
+ end
31
+ end
32
+
33
+ context 'with params' do
34
+ before do
35
+ subject.should_receive(:request).with(:post, url, params).and_return(response)
36
+ end
37
+ let(:params) { {:name => 'my name'} }
38
+
39
+ it 'should perform the request' do
40
+ subject.post(url, params).should == response
41
+ end
42
+ end
43
+ end
44
+
45
+ describe '#request' do
46
+ let(:url) { 'any_path' }
47
+ let(:sg_mock) { Sendgrid::Mock.new(user, key) }
48
+
49
+ context 'without params' do
50
+ before do
51
+ sg_mock.stub_post(url)
52
+ end
53
+
54
+ it 'should perform a request' do
55
+ subject.send(:request, :post, url)
56
+ sg_mock.a_post(url).should have_been_made
57
+ end
58
+ end
59
+
60
+ context 'with params' do
61
+ before do
62
+ sg_mock.stub_post(url, params)
63
+ end
64
+ let(:params) { {:name => 'my name'} }
65
+
66
+ it 'should perform a request' do
67
+ subject.send(:request, :post, url, params)
68
+ sg_mock.a_post(url, params).should have_been_made
69
+ params.should_not include(:api_user)
70
+ params.should_not include(:api_key)
71
+ end
72
+ end
73
+
74
+ context 'catches the errors' do
75
+ it 'catches Faraday errors' do
76
+ subject.stub(:connection).and_raise(Faraday::Error::ClientError.new('unknown error'))
77
+ expect { subject.send(:request, :post, url) }.to raise_error Sendgrid::API::REST::Errors::Unknown
78
+ end
79
+
80
+ it 'catches JSON::ParserError errors' do
81
+ subject.stub(:connection).and_raise(JSON::ParserError.new('unexpected token"'))
82
+ expect { subject.send(:request, :post, url) }.to raise_error Sendgrid::API::REST::Errors::Unknown
83
+ end
84
+
85
+ it 'catches status errors' do
86
+ sg_mock.stub_post(url).to_return(:status => 400)
87
+ expect { subject.send(:request, :post, url) }.to raise_error Sendgrid::API::REST::Errors::BadRequest
88
+ end
89
+
90
+ it 'catches body errors' do
91
+ sg_mock.stub_post(url).to_return(:body => {:error => {:code => 401}}.to_json)
92
+ expect { subject.send(:request, :post, url) }.to raise_error Sendgrid::API::REST::Errors::Unauthorized
93
+ end
94
+ end
95
+
96
+ context 'parses body as JSON' do
97
+ before do
98
+ sg_mock.stub_post(url).to_return(:body => {'name' => 'my name'}.to_json)
99
+ end
100
+
101
+ subject { resource.send(:request, :post, url).body }
102
+
103
+ it { should be_instance_of(Hash) }
104
+ its([:name]) { should == 'my name'}
105
+ end
106
+ end
107
+
108
+ describe '#middleware' do
109
+ it 'should be a valid Faraday middleware' do
110
+ subject.send(:middleware).should be_instance_of(Faraday::Builder)
111
+ end
112
+
113
+ it 'should memoize the middleware' do
114
+ middleware = double('middleware')
115
+ Faraday::Builder.should_receive(:new).once.and_return(middleware)
116
+
117
+ subject.send(:middleware).should == middleware
118
+ subject.send(:middleware).should == middleware
119
+ end
120
+ end
121
+
122
+ describe '#connection' do
123
+ it 'should be a valid Faraday connection' do
124
+ subject.send(:connection).should be_instance_of(Faraday::Connection)
125
+ end
126
+
127
+ it 'should memoize the connection' do
128
+ connection = double('connection')
129
+ Faraday.should_receive(:new).once.and_return(connection)
130
+
131
+ subject.send(:connection).should == connection
132
+ subject.send(:connection).should == connection
133
+ end
134
+ end
135
+
136
+ describe '#authentication_params' do
137
+ subject { resource.send(:authentication_params) }
138
+
139
+ its([:api_user]) { should == user }
140
+ its([:api_key]) { should == key }
141
+ end
142
+ end
143
+ end
144
+ end
145
+ end
@@ -0,0 +1,39 @@
1
+ require 'spec_helper'
2
+
3
+ module Sendgrid
4
+ module API
5
+ module REST
6
+ module Response
7
+ describe ParseError do
8
+
9
+ subject { described_class.new }
10
+
11
+ describe '#on_complete' do
12
+ context 'response with error' do
13
+ before do
14
+ REST::Errors::Error.should_receive(:from_response).and_return(Errors::Error)
15
+ end
16
+ let(:env) { double('env') }
17
+
18
+ it 'should raise the error' do
19
+ expect { subject.on_complete(env) }.to raise_error(Errors::Error)
20
+ end
21
+ end
22
+
23
+ context 'response without error' do
24
+ before do
25
+ REST::Errors::Error.should_receive(:from_response).and_return(nil)
26
+ end
27
+ let(:env) { double('env') }
28
+
29
+ it 'should return nil' do
30
+ subject.on_complete(env).should be_nil
31
+ end
32
+ end
33
+ end
34
+
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,45 @@
1
+ require 'spec_helper'
2
+
3
+ module Sendgrid
4
+ module API
5
+ module REST
6
+ module Response
7
+ describe ParseJson do
8
+
9
+ subject { parse_json }
10
+ let(:parse_json) { described_class.new }
11
+
12
+ describe '#parse' do
13
+ context 'body is nil' do
14
+ let(:body) { nil }
15
+
16
+ it 'should return nil' do
17
+ subject.parse(body).should be_nil
18
+ end
19
+ end
20
+
21
+ context 'body is not a valid JSON' do
22
+ let(:body) { 'some plain text' }
23
+
24
+ it 'should raise JSON::ParserError' do
25
+ expect { subject.parse(body) }.to raise_error(JSON::ParserError)
26
+ end
27
+ end
28
+
29
+ context 'body is a valid JSON' do
30
+ let(:body) do
31
+ { 'name' => 'my name' }.to_json
32
+ end
33
+
34
+ subject { parse_json.parse(body) }
35
+
36
+ it { should be_instance_of(Hash) }
37
+ its([:name]) { should == 'my name'}
38
+ end
39
+ end
40
+
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,44 @@
1
+ require 'spec_helper'
2
+
3
+ module Sendgrid
4
+ module API
5
+ describe Service do
6
+
7
+ subject { described_class.new(resource) }
8
+ let(:resource) { double('resource') }
9
+
10
+ its(:resource) { should == resource }
11
+
12
+ describe '#perform_request' do
13
+ before do
14
+ entity.should_receive(:from_response).and_return(response)
15
+ end
16
+ let(:entity) { double('entity') }
17
+ let(:response) { double('response') }
18
+ let(:url) { double('url') }
19
+
20
+ context 'with params' do
21
+ before do
22
+ resource.should_receive(:post).with(url, params)
23
+ end
24
+ let(:params) { double('params') }
25
+
26
+ it 'should perform a request' do
27
+ subject.perform_request(entity, url, params).should == response
28
+ end
29
+ end
30
+
31
+ context 'without params' do
32
+ before do
33
+ resource.should_receive(:post).with(url, {})
34
+ end
35
+
36
+ it 'should perform a request' do
37
+ subject.perform_request(entity, url).should == response
38
+ end
39
+ end
40
+ end
41
+
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,11 @@
1
+ require 'spec_helper'
2
+
3
+ module Sendgrid
4
+ describe API do
5
+
6
+ it 'has a non-null VERSION constant' do
7
+ API::VERSION.should_not be_nil
8
+ end
9
+
10
+ end
11
+ end
@@ -0,0 +1,111 @@
1
+ require 'spec_helper'
2
+
3
+ module Sendgrid
4
+ module API
5
+ module Web
6
+ module Mail
7
+ describe Services do
8
+
9
+ subject { service }
10
+ let(:service) { described_class.new(resource) }
11
+ let(:resource) { REST::Resource.new(user, key) }
12
+ let(:user) { 'my_user' }
13
+ let(:key) { 'my_key' }
14
+ let(:sg_mock) { Sendgrid::Mock.new(user, key) }
15
+
16
+ let(:to) { 'test@coffeebeantech.com' }
17
+ let(:from) { 'test@coffeebeantech.com' }
18
+ let(:email_subject) { 'sendgrid-api mail test' }
19
+ let(:text) { 'This is an email to test the sendgrid-api gem' }
20
+ let(:files) do
21
+ { 'sample1.txt' => sample_file(:name => 'sample1.txt'),
22
+ 'sample2.txt' => sample_file(:name => 'sample2.txt') }
23
+ end
24
+ let(:x_smtpapi) do
25
+ { :category => ['sendgrid-api test'] }.to_json
26
+ end
27
+ let(:required_options) do
28
+ { :to => to, :subject => email_subject, :text => text, :from => from }
29
+ end
30
+
31
+ describe '#mail' do
32
+ let(:url) { 'mail.send.json' }
33
+
34
+ context 'with required fields' do
35
+ let(:stub_post) { sg_mock.stub_post(url, required_options) }
36
+ subject { service.send(required_options) }
37
+ it_behaves_like 'a success response'
38
+ end
39
+
40
+ context 'without required fields' do
41
+ let(:stub_post) { sg_mock.stub_post(url, :to => to) }
42
+ subject { service.send(:to => to) }
43
+ it_behaves_like 'an invalid fields response'
44
+ end
45
+
46
+ context 'with files attached' do
47
+ let(:stub_post) { stub_request(:post, sg_mock.uri(url)).with(:body => /sample1.txt/) }
48
+ subject { service.send(required_options.merge(:files => files)) }
49
+ it_behaves_like 'a success response'
50
+ end
51
+
52
+ context 'with SMTP API headers' do
53
+ let(:stub_post) { sg_mock.stub_post(url, :to => to, :subject => email_subject, :text => text, :from => from, 'x-smtpapi' => x_smtpapi) }
54
+ subject { service.send(required_options.merge(:x_smtpapi => x_smtpapi)) }
55
+ it_behaves_like 'a success response'
56
+ end
57
+
58
+ context 'when permission failed' do
59
+ let(:stub_post) { sg_mock.stub_post(url) }
60
+ subject { service.send }
61
+ it_behaves_like 'a bad request response'
62
+ end
63
+ end
64
+
65
+ describe 'online tests', :online => true do
66
+ include_examples 'online tests'
67
+
68
+ context 'when credentials are valid' do
69
+ let(:resource) { REST::Resource.new(env_user, env_key) }
70
+
71
+ describe '#mail' do
72
+ context 'with required fields' do
73
+ it 'sends the email' do
74
+ subject.send(required_options).success?.should be_true
75
+ end
76
+ end
77
+
78
+ context 'without required fields' do
79
+ it 'raises an error' do
80
+ expect { subject.send(:to => to) }.to raise_error(REST::Errors::BadRequest)
81
+ end
82
+ end
83
+
84
+ context 'with files attached' do
85
+ it 'sends the email' do
86
+ subject.send(required_options.merge(:files => files)).success?.should be_true
87
+ end
88
+ end
89
+
90
+ context 'with SMTP API headers' do
91
+ it 'sends the email' do
92
+ subject.send(required_options.merge(:x_smtpapi => x_smtpapi)).success?.should be_true
93
+ end
94
+ end
95
+ end
96
+ end
97
+
98
+ context 'when credentials are invalid' do
99
+ describe '#mail' do
100
+ it 'raises error' do
101
+ expect { subject.send(required_options) }.to raise_error(REST::Errors::BadRequest)
102
+ end
103
+ end
104
+ end
105
+ end
106
+
107
+ end
108
+ end
109
+ end
110
+ end
111
+ end