exponent-server-sdk 0.0.5 → 0.0.6

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 61012c4117f2e3c9357a2b99e92ad363fb956844
4
- data.tar.gz: 7c565d390d7e8d2b737c6c6a684a14c1f988ff97
2
+ SHA256:
3
+ metadata.gz: 9ebc8de35da4d4e4a5a826ed90de5d35d833d173a705b1972eb273d9d8f7e847
4
+ data.tar.gz: 0fda3e2471d7be6691e06a71718a263dcb488b99f5466aff8735348ff5e85ddd
5
5
  SHA512:
6
- metadata.gz: 0a21006404a04267901a8c607dd9dfd7c154e57f93c07da8d0299c4c26a3292a13393d6bbe60a0471f66e53efa21529f7b1919a9b55b1d463203f88d2cfe594b
7
- data.tar.gz: 30730a58b90f42f5cb20382abeb4affd59275d6ec78be59e511e06249ffb5324b5554d39a5e21c850ba2bc8be5cf747c2bb7e9d271eb32b247ebcae6e7d60ebc
6
+ metadata.gz: 57a08a6323c058c52de8a5c2eb75ad4878b1d6d74558b9032856281ebaeda791f66d34423e10765deb9470c21e0284021eac93aa622202076ddf46d657d7609d
7
+ data.tar.gz: 6dbf0c93e6dccaed5177a3eeac7608ddf06f35af0ad54e0123142346b5a5fb147bbddfb817a0cd9d7c67f951762378e47972ad5f4639c390aaeec35c7dbee298
@@ -1,7 +1,10 @@
1
- language: ruby
2
- rvm:
3
- - 2.4.0
4
- - 2.3.0
5
- - 2.2.0
6
- - 2.1.0
7
- - 2.0.0
1
+ language: ruby
2
+ cache: bundler
3
+ rvm:
4
+ - 2.6.0
5
+ - 2.5.0
6
+ - 2.4.0
7
+ - 2.3.0
8
+ before_install:
9
+ - gem update --system
10
+ - gem install bundler
data/README.md CHANGED
@@ -1,53 +1,58 @@
1
- # Exponent Server SDK Ruby
2
- [![Build Status](https://travis-ci.org/expo/exponent-server-sdk-ruby.svg?branch=master)](https://travis-ci.org/expo/exponent-server-sdk-ruby)
3
-
4
- Use to send push notifications to Exponent Experiences from a Ruby server.
5
-
6
- ## Installation
7
-
8
- Add this line to your application's Gemfile:
9
-
10
- ```ruby
11
- gem 'exponent-server-sdk'
12
- ```
13
-
14
- And then execute:
15
-
16
- ```shell
17
- $ bundle
18
- ```
19
-
20
- Or install it yourself as:
21
-
22
- ```shell
23
- $ gem install exponent-server-sdk
24
- ```
25
-
26
- ## Usage
27
-
28
- ### Client
29
-
30
- The push client is the preferred way. This hits the latest version of the api.
31
-
32
- ```ruby
33
- client = Exponent::Push::Client.new
34
-
35
- messages = [{
36
- to: "ExponentPushToken[xxxxxxxxxxxxxxxxxxxxxx]",
37
- sound: "default",
38
- body: "Hello world!"
39
- }, {
40
- to: "ExponentPushToken[yyyyyyyyyyyyyyyyyyyyyy]",
41
- badge: 1,
42
- body: "You've got mail"
43
- }]
44
-
45
- client.publish messages
46
- ```
47
-
48
- The complete format of the messages can be found [here.](https://docs.expo.io/versions/latest/index.html#http2-api)
49
-
50
- ## Contributing
51
-
52
- If you have problems with the code in this repository, please file issues & bug reports. We encourage you
53
- to submit a solution or a failing test to reproduce your issue. Thanks!
1
+ # Exponent Server SDK Ruby
2
+ [![Build Status](https://travis-ci.org/expo/exponent-server-sdk-ruby.svg?branch=master)](https://travis-ci.org/expo/exponent-server-sdk-ruby)
3
+ [![Gem Version](https://badge.fury.io/rb/exponent-server-sdk.svg)](https://badge.fury.io/rb/exponent-server-sdk)
4
+
5
+ Use to send push notifications to Exponent Experiences from a Ruby server.
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ ```ruby
12
+ gem 'exponent-server-sdk'
13
+ ```
14
+
15
+ And then execute:
16
+
17
+ ```shell
18
+ $ bundle
19
+ ```
20
+
21
+ Or install it yourself as:
22
+
23
+ ```shell
24
+ $ gem install exponent-server-sdk
25
+ ```
26
+
27
+ ## Usage
28
+
29
+ ### Client
30
+
31
+ The push client is the preferred way. This hits the latest version of the api.
32
+
33
+ Optional arguments: `gzip: true`
34
+
35
+
36
+ ```ruby
37
+ client = Exponent::Push::Client.new
38
+ # client = Exponent::Push::Client.new(gzip: true) # for compressed, faster requests
39
+
40
+ messages = [{
41
+ to: "ExponentPushToken[xxxxxxxxxxxxxxxxxxxxxx]",
42
+ sound: "default",
43
+ body: "Hello world!"
44
+ }, {
45
+ to: "ExponentPushToken[yyyyyyyyyyyyyyyyyyyyyy]",
46
+ badge: 1,
47
+ body: "You've got mail"
48
+ }]
49
+
50
+ client.publish messages
51
+ ```
52
+
53
+ The complete format of the messages can be found [here.](https://docs.expo.io/versions/latest/guides/push-notifications#message-format)
54
+
55
+ ## Contributing
56
+
57
+ If you have problems with the code in this repository, please file issues & bug reports. We encourage you
58
+ to submit a pull request with a solution or a failing test to reproduce your issue. Thanks!
data/Rakefile CHANGED
@@ -1,10 +1,10 @@
1
- require "bundler/gem_tasks"
2
- require "rake/testtask"
3
-
4
- Rake::TestTask.new(:test) do |t|
5
- t.libs << "test"
6
- t.libs << "lib"
7
- t.test_files = FileList['test/**/*-test.rb']
8
- end
9
-
10
- task :default => :test
1
+ require "bundler/gem_tasks"
2
+ require "rake/testtask"
3
+
4
+ Rake::TestTask.new(:test) do |t|
5
+ t.libs << "test"
6
+ t.libs << "lib"
7
+ t.test_files = FileList['test/**/*-manual_test.rb']
8
+ end
9
+
10
+ task :default => :test
@@ -1,151 +1,153 @@
1
- require 'exponent-server-sdk/version'
2
- require 'typhoeus'
3
- require 'json'
4
-
5
- module Exponent
6
- def self.is_exponent_push_token?(token)
7
- token.start_with?('ExponentPushToken')
8
- end
9
-
10
- module Push
11
-
12
- class Client
13
- def initialize(http_client = Typhoeus,
14
- response_handler = ResponseHandler.new)
15
- @http_client = http_client
16
- @response_handler = response_handler
17
- end
18
-
19
- def publish(messages)
20
- response_handler.handle(push_notifications(messages))
21
- end
22
-
23
- private
24
-
25
- attr_reader :http_client, :response_handler
26
-
27
- def push_notifications(messages)
28
- http_client.post(
29
- push_url,
30
- body: messages.to_json,
31
- headers: headers
32
- )
33
- end
34
-
35
- def push_url
36
- 'https://exp.host/--/api/v2/push/send'
37
- end
38
-
39
- def headers
40
- {
41
- 'Content-Type' => 'application/json',
42
- 'Accept' => 'application/json'
43
- }
44
- end
45
- end
46
-
47
- class ResponseHandler
48
- def initialize(error_builder = ErrorBuilder.new)
49
- @error_builder = error_builder
50
- end
51
-
52
- def handle(response)
53
- case response.code.to_s
54
- when /(^4|^5)/
55
- raise build_error_from_failure(parse_json(response))
56
- else
57
- handle_success(parse_json(response))
58
- end
59
- end
60
-
61
- private
62
-
63
- attr_reader :error_builder
64
-
65
- def parse_json(response)
66
- JSON.parse(response.body)
67
- end
68
-
69
- def build_error_from_failure(response)
70
- error_builder.build_from_erroneous(response)
71
- end
72
-
73
- def handle_success(response)
74
- extract_data(response).tap do |data|
75
- validate_status(data.fetch('status'), response)
76
- end
77
- end
78
-
79
- def extract_data(response)
80
- response.fetch('data').first
81
- end
82
-
83
- def validate_status(status, response)
84
- raise build_error_from_success(response) unless status == 'ok'
85
- end
86
-
87
- def build_error_from_success(response)
88
- error_builder.build_from_successful(response)
89
- end
90
- end
91
-
92
- class ErrorBuilder
93
- %i[erroneous successful].each do |selector|
94
- define_method(:"build_from_#{selector}") do |response|
95
- with_error_handling(response) do
96
- send "from_#{selector}_response", response
97
- end
98
- end
99
- end
100
-
101
- private
102
-
103
- def with_error_handling(response)
104
- yield(response)
105
- rescue KeyError
106
- unknown_error_format(response)
107
- end
108
-
109
- def from_erroneous_response(response)
110
- error = response.fetch('errors').first
111
- error_name = error.fetch('code')
112
- message = error.fetch('message')
113
-
114
- get_error_class(error_name).new(message)
115
- end
116
-
117
- def from_successful_response(response)
118
- data = response.fetch('data').first
119
- message = data.fetch('message')
120
-
121
- get_error_class(data.fetch('details').fetch('error')).new(message)
122
- end
123
-
124
- def validate_error_name(condition)
125
- condition ? yield : Exponent::Push::UnknownError
126
- end
127
-
128
- def get_error_class(error_name)
129
- validate_error_name(Exponent::Push.error_names.include?(error_name)) do
130
- Exponent::Push.const_get("#{error_name}Error")
131
- end
132
- end
133
-
134
- def unknown_error_format(response)
135
- Exponent::Push::UnknownError.new("Unknown error format: #{response}")
136
- end
137
- end
138
-
139
- Error = Class.new(StandardError)
140
-
141
- def self.error_names
142
- %w[DeviceNotRegistered MessageTooBig
143
- MessageRateExceeded InvalidCredentials
144
- Unknown]
145
- end
146
-
147
- error_names.each do |error_name|
148
- const_set "#{error_name}Error", Class.new(Error)
149
- end
150
- end
151
- end
1
+ require 'exponent-server-sdk/version'
2
+ require 'typhoeus'
3
+ require 'json'
4
+
5
+ module Exponent
6
+ def self.is_exponent_push_token?(token)
7
+ token.start_with?('ExponentPushToken')
8
+ end
9
+
10
+ module Push
11
+
12
+ class Client
13
+ def initialize(**args)
14
+ @http_client = args[:http_client] || Typhoeus
15
+ @response_handler = args[:response_handler] || ResponseHandler.new
16
+ @gzip = args[:gzip] == true
17
+ end
18
+
19
+ def publish(messages)
20
+ response_handler.handle(push_notifications(messages))
21
+ end
22
+
23
+ private
24
+
25
+ attr_reader :http_client, :response_handler
26
+
27
+ def push_notifications(messages)
28
+ http_client.post(
29
+ push_url,
30
+ body: messages.to_json,
31
+ headers: headers
32
+ )
33
+ end
34
+
35
+ def push_url
36
+ 'https://exp.host/--/api/v2/push/send'
37
+ end
38
+
39
+ def headers
40
+ headers = {
41
+ 'Content-Type' => 'application/json',
42
+ 'Accept' => 'application/json'
43
+ }
44
+ headers['Accept-Encoding'] = 'gzip, deflate' if @gzip
45
+ headers
46
+ end
47
+ end
48
+
49
+ class ResponseHandler
50
+ def initialize(error_builder = ErrorBuilder.new)
51
+ @error_builder = error_builder
52
+ end
53
+
54
+ def handle(response)
55
+ case response.code.to_s
56
+ when /(^4|^5)/
57
+ raise build_error_from_failure(parse_json(response))
58
+ else
59
+ handle_success(parse_json(response))
60
+ end
61
+ end
62
+
63
+ private
64
+
65
+ attr_reader :error_builder
66
+
67
+ def parse_json(response)
68
+ JSON.parse(response.body)
69
+ end
70
+
71
+ def build_error_from_failure(response)
72
+ error_builder.build_from_erroneous(response)
73
+ end
74
+
75
+ def handle_success(response)
76
+ extract_data(response).tap do |data|
77
+ validate_status(data.fetch('status'), response)
78
+ end
79
+ end
80
+
81
+ def extract_data(response)
82
+ response.fetch('data').first
83
+ end
84
+
85
+ def validate_status(status, response)
86
+ raise build_error_from_success(response) unless status == 'ok'
87
+ end
88
+
89
+ def build_error_from_success(response)
90
+ error_builder.build_from_successful(response)
91
+ end
92
+ end
93
+
94
+ class ErrorBuilder
95
+ %i[erroneous successful].each do |selector|
96
+ define_method(:"build_from_#{selector}") do |response|
97
+ with_error_handling(response) do
98
+ send "from_#{selector}_response", response
99
+ end
100
+ end
101
+ end
102
+
103
+ private
104
+
105
+ def with_error_handling(response)
106
+ yield(response)
107
+ rescue KeyError
108
+ unknown_error_format(response)
109
+ end
110
+
111
+ def from_erroneous_response(response)
112
+ error = response.fetch('errors').first
113
+ error_name = error.fetch('code')
114
+ message = error.fetch('message')
115
+
116
+ get_error_class(error_name).new(message)
117
+ end
118
+
119
+ def from_successful_response(response)
120
+ data = response.fetch('data').first
121
+ message = data.fetch('message')
122
+
123
+ get_error_class(data.fetch('details').fetch('error')).new(message)
124
+ end
125
+
126
+ def validate_error_name(condition)
127
+ condition ? yield : Exponent::Push::UnknownError
128
+ end
129
+
130
+ def get_error_class(error_name)
131
+ validate_error_name(Exponent::Push.error_names.include?(error_name)) do
132
+ Exponent::Push.const_get("#{error_name}Error")
133
+ end
134
+ end
135
+
136
+ def unknown_error_format(response)
137
+ Exponent::Push::UnknownError.new("Unknown error format: #{response}")
138
+ end
139
+ end
140
+
141
+ Error = Class.new(StandardError)
142
+
143
+ def self.error_names
144
+ %w[DeviceNotRegistered MessageTooBig
145
+ MessageRateExceeded InvalidCredentials
146
+ Unknown]
147
+ end
148
+
149
+ error_names.each do |error_name|
150
+ const_set "#{error_name}Error", Class.new(Error)
151
+ end
152
+ end
153
+ end
@@ -1,3 +1,3 @@
1
- module Exponent
2
- VERSION = '0.0.5'.freeze
3
- end
1
+ module Exponent
2
+ VERSION = '0.0.6'.freeze
3
+ end
@@ -0,0 +1,19 @@
1
+ require_relative 'lib/exponent-server-sdk'
2
+
3
+ client = Exponent::Push::Client.new
4
+
5
+ # OR use GZIP to be AWESOME
6
+ # client = Exponent::Push::Client.new(gzip: true)
7
+
8
+ messages = [{
9
+ to: 'ExponentPushToken[HbuLbNFwb5_ENuljvAePLs]',
10
+ sound: "default",
11
+ title: "You're Winning!",
12
+ body: "You just won EVERTHING!",
13
+ data: {
14
+ type: 'WINNINGS',
15
+ message: "You just won EVERTHING!"
16
+
17
+ }.to_json
18
+ }]
19
+ client.publish messages
@@ -1,195 +1,232 @@
1
- require 'minitest/autorun'
2
- require 'exponent-server-sdk'
3
-
4
- class ExponentServerSdkTest < Minitest::Test
5
- def setup
6
- @mock = MiniTest::Mock.new
7
- @response_mock = MiniTest::Mock.new
8
- @exponent = Exponent::Push::Client.new(@mock)
9
- end
10
-
11
- def test_publish_with_success
12
- @response_mock.expect(:code, 200)
13
- @response_mock.expect(:body, success_body.to_json)
14
-
15
- @mock.expect(:post, @response_mock, client_args)
16
-
17
- @exponent.publish(messages)
18
-
19
- @mock.verify
20
- end
21
-
22
- def test_publish_with_unknown_error
23
- @response_mock.expect(:code, 400)
24
- @response_mock.expect(:body, error_body.to_json)
25
- message = 'An unknown error occurred.'
26
-
27
- @mock.expect(:post, @response_mock, client_args)
28
-
29
- exception = assert_raises Exponent::Push::UnknownError do
30
- @exponent.publish(messages)
31
- end
32
-
33
- assert_equal(message, exception.message)
34
-
35
- @mock.verify
36
- end
37
-
38
- def test_publish_with_device_not_registered_error
39
- @response_mock.expect(:code, 200)
40
- @response_mock.expect(:body, not_registered_device_error_body.to_json)
41
- message = '"ExponentPushToken[42]" is not a registered push notification recipient'
42
-
43
- @mock.expect(:post, @response_mock, client_args)
44
-
45
- exception = assert_raises Exponent::Push::DeviceNotRegisteredError do
46
- @exponent.publish(messages)
47
- end
48
-
49
- assert_equal(message, exception.message)
50
-
51
- @mock.verify
52
- end
53
-
54
- def test_publish_with_message_too_big_error
55
- @response_mock.expect(:code, 200)
56
- @response_mock.expect(:body, message_too_big_error_body.to_json)
57
- message = 'Message too big'
58
-
59
- @mock.expect(:post, @response_mock, client_args)
60
-
61
- exception = assert_raises Exponent::Push::MessageTooBigError do
62
- @exponent.publish(messages)
63
- end
64
-
65
- assert_equal(message, exception.message)
66
-
67
- @mock.verify
68
- end
69
-
70
- def test_publish_with_message_rate_exceeded_error
71
- @response_mock.expect(:code, 200)
72
- @response_mock.expect(:body, message_rate_exceeded_error_body.to_json)
73
- message = 'Message rate exceeded'
74
-
75
- @mock.expect(:post, @response_mock, client_args)
76
-
77
- exception = assert_raises Exponent::Push::MessageRateExceededError do
78
- @exponent.publish(messages)
79
- end
80
-
81
- assert_equal(message, exception.message)
82
-
83
- @mock.verify
84
- end
85
-
86
- def test_publish_with_invalid_credentials_error
87
- @response_mock.expect(:code, 200)
88
- @response_mock.expect(:body, invalid_credentials_error_body.to_json)
89
- message = 'Invalid credentials'
90
-
91
- @mock.expect(:post, @response_mock, client_args)
92
-
93
- exception = assert_raises Exponent::Push::InvalidCredentialsError do
94
- @exponent.publish(messages)
95
- end
96
-
97
- assert_equal(message, exception.message)
98
-
99
- @mock.verify
100
- end
101
-
102
- def test_publish_with_apn_error
103
- @response_mock.expect(:code, 200)
104
- @response_mock.expect(:body, apn_error_body.to_json)
105
-
106
- @mock.expect(:post, @response_mock, client_args)
107
-
108
- exception = assert_raises Exponent::Push::UnknownError do
109
- @exponent.publish(messages)
110
- end
111
-
112
- assert_match(/Unknown error format/, exception.message)
113
-
114
- @mock.verify
115
- end
116
-
117
- private
118
-
119
- def success_body
120
- { 'data' => [{ 'status' => 'ok' }] }
121
- end
122
-
123
- def error_body
124
- {
125
- 'errors' => [{
126
- 'code' => 'INTERNAL_SERVER_ERROR',
127
- 'message' => 'An unknown error occurred.'
128
- }]
129
- }
130
- end
131
-
132
- def message_too_big_error_body
133
- build_error_body('MessageTooBig', 'Message too big')
134
- end
135
-
136
- def not_registered_device_error_body
137
- build_error_body(
138
- 'DeviceNotRegistered',
139
- '"ExponentPushToken[42]" is not a registered push notification recipient'
140
- )
141
- end
142
-
143
- def message_rate_exceeded_error_body
144
- build_error_body('MessageRateExceeded', 'Message rate exceeded')
145
- end
146
-
147
- def invalid_credentials_error_body
148
- build_error_body('InvalidCredentials', 'Invalid credentials')
149
- end
150
-
151
- def apn_error_body
152
- {
153
- 'data' => [{
154
- 'status' => 'error',
155
- 'message' =>
156
- 'Could not find APNs credentials for you (your_app). Check whether you are trying to send a notification to a detached app.'
157
- }]
158
- }
159
- end
160
-
161
- def client_args
162
- [
163
- 'https://exp.host/--/api/v2/push/send',
164
- {
165
- body: messages.to_json,
166
- headers: {
167
- 'Content-Type' => 'application/json',
168
- 'Accept' => 'application/json'
169
- }
170
- }
171
- ]
172
- end
173
-
174
- def messages
175
- [{
176
- to: 'ExponentPushToken[xxxxxxxxxxxxxxxxxxxxxx]',
177
- sound: 'default',
178
- body: 'Hello world!'
179
- }, {
180
- to: 'ExponentPushToken[yyyyyyyyyyyyyyyyyyyyyy]',
181
- badge: 1,
182
- body: "You've got mail"
183
- }]
184
- end
185
-
186
- def build_error_body(error_code, message)
187
- {
188
- 'data' => [{
189
- 'status' => 'error',
190
- 'message' => message,
191
- 'details' => { 'error' => error_code }
192
- }]
193
- }
194
- end
195
- end
1
+ require 'minitest/autorun'
2
+ require 'exponent-server-sdk'
3
+
4
+ class ExponentServerSdkTest < Minitest::Test
5
+ def setup
6
+ @mock = MiniTest::Mock.new
7
+ @response_mock = MiniTest::Mock.new
8
+ @exponent = Exponent::Push::Client.new(http_client: @mock)
9
+ @exponent_gzip = Exponent::Push::Client.new(http_client: @mock, gzip: true)
10
+ end
11
+
12
+ def test_publish_with_success
13
+ @response_mock.expect(:code, 200)
14
+ @response_mock.expect(:body, success_body.to_json)
15
+
16
+ @mock.expect(:post, @response_mock, client_args)
17
+
18
+ @exponent.publish(messages)
19
+
20
+ @mock.verify
21
+ end
22
+
23
+ def test_publish_with_gzip_success
24
+ @response_mock.expect(:code, 200)
25
+ @response_mock.expect(:body, success_body.to_json)
26
+
27
+ @mock.expect(:post, @response_mock, gzip_client_args)
28
+
29
+ @exponent_gzip.publish(messages)
30
+
31
+ @mock.verify
32
+ end
33
+
34
+ def test_publish_with_gzip
35
+ @response_mock.expect(:code, 200)
36
+ @response_mock.expect(:body, success_body.to_json)
37
+
38
+ @mock.expect(:post, @response_mock, gzip_client_args)
39
+
40
+ @exponent_gzip.publish(messages)
41
+
42
+ @mock.verify
43
+ end
44
+
45
+ def test_publish_with_unknown_error
46
+ @response_mock.expect(:code, 400)
47
+ @response_mock.expect(:body, error_body.to_json)
48
+ message = 'An unknown error occurred.'
49
+
50
+ @mock.expect(:post, @response_mock, client_args)
51
+
52
+ exception = assert_raises Exponent::Push::UnknownError do
53
+ @exponent.publish(messages)
54
+ end
55
+
56
+ assert_equal(message, exception.message)
57
+
58
+ @mock.verify
59
+ end
60
+
61
+ def test_publish_with_device_not_registered_error
62
+ @response_mock.expect(:code, 200)
63
+ @response_mock.expect(:body, not_registered_device_error_body.to_json)
64
+ message = '"ExponentPushToken[42]" is not a registered push notification recipient'
65
+
66
+ @mock.expect(:post, @response_mock, client_args)
67
+
68
+ exception = assert_raises Exponent::Push::DeviceNotRegisteredError do
69
+ @exponent.publish(messages)
70
+ end
71
+
72
+ assert_equal(message, exception.message)
73
+
74
+ @mock.verify
75
+ end
76
+
77
+ def test_publish_with_message_too_big_error
78
+ @response_mock.expect(:code, 200)
79
+ @response_mock.expect(:body, message_too_big_error_body.to_json)
80
+ message = 'Message too big'
81
+
82
+ @mock.expect(:post, @response_mock, client_args)
83
+
84
+ exception = assert_raises Exponent::Push::MessageTooBigError do
85
+ @exponent.publish(messages)
86
+ end
87
+
88
+ assert_equal(message, exception.message)
89
+
90
+ @mock.verify
91
+ end
92
+
93
+ def test_publish_with_message_rate_exceeded_error
94
+ @response_mock.expect(:code, 200)
95
+ @response_mock.expect(:body, message_rate_exceeded_error_body.to_json)
96
+ message = 'Message rate exceeded'
97
+
98
+ @mock.expect(:post, @response_mock, client_args)
99
+
100
+ exception = assert_raises Exponent::Push::MessageRateExceededError do
101
+ @exponent.publish(messages)
102
+ end
103
+
104
+ assert_equal(message, exception.message)
105
+
106
+ @mock.verify
107
+ end
108
+
109
+ def test_publish_with_invalid_credentials_error
110
+ @response_mock.expect(:code, 200)
111
+ @response_mock.expect(:body, invalid_credentials_error_body.to_json)
112
+ message = 'Invalid credentials'
113
+
114
+ @mock.expect(:post, @response_mock, client_args)
115
+
116
+ exception = assert_raises Exponent::Push::InvalidCredentialsError do
117
+ @exponent.publish(messages)
118
+ end
119
+
120
+ assert_equal(message, exception.message)
121
+
122
+ @mock.verify
123
+ end
124
+
125
+ def test_publish_with_apn_error
126
+ @response_mock.expect(:code, 200)
127
+ @response_mock.expect(:body, apn_error_body.to_json)
128
+
129
+ @mock.expect(:post, @response_mock, client_args)
130
+
131
+ exception = assert_raises Exponent::Push::UnknownError do
132
+ @exponent.publish(messages)
133
+ end
134
+
135
+ assert_match(/Unknown error format/, exception.message)
136
+
137
+ @mock.verify
138
+ end
139
+
140
+ private
141
+
142
+ def success_body
143
+ { 'data' => [{ 'status' => 'ok' }] }
144
+ end
145
+
146
+ def error_body
147
+ {
148
+ 'errors' => [{
149
+ 'code' => 'INTERNAL_SERVER_ERROR',
150
+ 'message' => 'An unknown error occurred.'
151
+ }]
152
+ }
153
+ end
154
+
155
+ def message_too_big_error_body
156
+ build_error_body('MessageTooBig', 'Message too big')
157
+ end
158
+
159
+ def not_registered_device_error_body
160
+ build_error_body(
161
+ 'DeviceNotRegistered',
162
+ '"ExponentPushToken[42]" is not a registered push notification recipient'
163
+ )
164
+ end
165
+
166
+ def message_rate_exceeded_error_body
167
+ build_error_body('MessageRateExceeded', 'Message rate exceeded')
168
+ end
169
+
170
+ def invalid_credentials_error_body
171
+ build_error_body('InvalidCredentials', 'Invalid credentials')
172
+ end
173
+
174
+ def apn_error_body
175
+ {
176
+ 'data' => [{
177
+ 'status' => 'error',
178
+ 'message' =>
179
+ 'Could not find APNs credentials for you (your_app). Check whether you are trying to send a notification to a detached app.'
180
+ }]
181
+ }
182
+ end
183
+
184
+ def client_args
185
+ [
186
+ 'https://exp.host/--/api/v2/push/send',
187
+ {
188
+ body: messages.to_json,
189
+ headers: {
190
+ 'Content-Type' => 'application/json',
191
+ 'Accept' => 'application/json'
192
+ }
193
+ }
194
+ ]
195
+ end
196
+
197
+ def gzip_client_args
198
+ [
199
+ 'https://exp.host/--/api/v2/push/send',
200
+ {
201
+ body: messages.to_json,
202
+ headers: {
203
+ 'Content-Type' => 'application/json',
204
+ 'Accept' => 'application/json',
205
+ 'Accept-Encoding' => 'gzip, deflate'
206
+ }
207
+ }
208
+ ]
209
+ end
210
+
211
+ def messages
212
+ [{
213
+ to: 'ExponentPushToken[xxxxxxxxxxxxxxxxxxxxxx]',
214
+ sound: 'default',
215
+ body: 'Hello world!'
216
+ }, {
217
+ to: 'ExponentPushToken[yyyyyyyyyyyyyyyyyyyyyy]',
218
+ badge: 1,
219
+ body: "You've got mail"
220
+ }]
221
+ end
222
+
223
+ def build_error_body(error_code, message)
224
+ {
225
+ 'data' => [{
226
+ 'status' => 'error',
227
+ 'message' => message,
228
+ 'details' => { 'error' => error_code }
229
+ }]
230
+ }
231
+ end
232
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: exponent-server-sdk
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.5
4
+ version: 0.0.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jesse Ruder
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2018-03-01 00:00:00.000000000 Z
12
+ date: 2019-01-07 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: typhoeus
@@ -84,7 +84,7 @@ files:
84
84
  - exponent-server-sdk.gemspec
85
85
  - lib/exponent-server-sdk.rb
86
86
  - lib/exponent-server-sdk/version.rb
87
- - manual-testing.txt
87
+ - manual_test.rb
88
88
  - test/exponent-server-sdk-test.rb
89
89
  homepage: ''
90
90
  licenses:
@@ -105,8 +105,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
105
105
  - !ruby/object:Gem::Version
106
106
  version: '0'
107
107
  requirements: []
108
- rubyforge_project:
109
- rubygems_version: 2.6.11
108
+ rubygems_version: 3.0.2
110
109
  signing_key:
111
110
  specification_version: 4
112
111
  summary: Exponent Server SDK
@@ -1,23 +0,0 @@
1
- irb -r exponent-server-sdk -I ./lib
2
-
3
- exponent = Exponent::Push::Client.new
4
-
5
- exponent.publish(
6
- exponentPushToken: 'ExponentPushToken[HbuLbNFwb5_ENuljvAePLs]',
7
- #message: 'Hello Charlie. It is ' + Time::now.to_s,
8
- message: 'Hello Charlie from Ruby',
9
- data: {a: "b"},
10
- )
11
-
12
-
13
- ipython
14
-
15
- import exponent_server_sdk
16
- import datetime
17
-
18
- exponent = exponent_server_sdk.Client()
19
-
20
- exponent.publish('ExponentPushToken[HbuLbNFwb5_ENuljvAePLs]', "Hello Charlie from Python. It is " + datetime.datetime.now().time().isoformat(), {"a": "p"})
21
-
22
-
23
-