exponent-server-sdk 0.0.2 → 0.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 937bd4d5dcc76c2a2f25ffb7add009d83c70f9b5
4
- data.tar.gz: 2548e5f9f910985944b64556f650e8eea7f40730
3
+ metadata.gz: 88ec6ffe5bd4602818f88d05b6ce235631cd4951
4
+ data.tar.gz: b5cf4200640d97ca8136dbe2788c60b1a28d1531
5
5
  SHA512:
6
- metadata.gz: 27e84460a044e4ffa79ac433ef2e1c77a19bd6048232b837ce4443374332e0a7bb3154e198b7987c910ed6d2e79b35637f7946d4036ef981b041f9ddb8c23317
7
- data.tar.gz: 0b0b4926c5a3a426192cc29f754cb7564106a4f695041ab7f89e45dcb7fa02a316d3e74be8f7aaae5068051b79eb42515ed5b39e0ec0620cceaedb941554dd14
6
+ metadata.gz: 51937e0397c547c37f7a6da6dc0b94897cf578ef47ca4271f5ee2b15c216cea04a9071893cd45e2a3ca2f729feffa60bc1b0c893640fdd72a15d4e8605caa04f
7
+ data.tar.gz: 15b4e65065e9526a407b9f274f7bb9d56427cd2ee7dd842962d1be4f0ff9812f3e65d9f6c4e6bad8b9ef45047543a6ee401ef7a0698deece9cb0de44da90ffec
data/.gitignore CHANGED
@@ -15,3 +15,5 @@ spec/reports
15
15
  test/tmp
16
16
  test/version_tmp
17
17
  tmp
18
+ *.log
19
+ .ruby-version
@@ -0,0 +1,7 @@
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
data/README.md CHANGED
@@ -1,17 +1,50 @@
1
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)
2
3
 
3
4
  Use to send push notifications to Exponent Experiences from a Ruby server.
4
5
 
6
+ If you have problems with the code in this repository, please file issues & bug reports at https://github.com/expo/expo. Thanks!
7
+
5
8
  ## Installation
6
9
 
7
10
  Add this line to your application's Gemfile:
8
11
 
9
- gem 'exponent-server-sdk'
12
+ ```ruby
13
+ gem 'exponent-server-sdk'
14
+ ```
10
15
 
11
16
  And then execute:
12
17
 
13
- $ bundle
18
+ ```shell
19
+ $ bundle
20
+ ```
14
21
 
15
22
  Or install it yourself as:
16
23
 
17
- $ gem install exponent-server-sdk
24
+ ```shell
25
+ $ gem install exponent-server-sdk
26
+ ```
27
+
28
+ ## Usage
29
+
30
+ ### Client
31
+
32
+ The push client is the preferred way. This hits the latest version of the api.
33
+
34
+ ```ruby
35
+ exponent = Exponent::Push::Client.new
36
+
37
+ messages = [{
38
+ to: "ExponentPushToken[xxxxxxxxxxxxxxxxxxxxxx]",
39
+ sound: "default",
40
+ body: "Hello world!"
41
+ }, {
42
+ to: "ExponentPushToken[yyyyyyyyyyyyyyyyyyyyyy]",
43
+ badge: 1,
44
+ body: "You've got mail"
45
+ }]
46
+
47
+ exponent.publish messages
48
+ ```
49
+
50
+ The complete format of the messages can be found [here.](https://docs.expo.io/versions/v16.0.0/guides/push-notifications.html#http2-api)
data/Rakefile CHANGED
@@ -1 +1,10 @@
1
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
@@ -4,22 +4,23 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
4
  require 'exponent-server-sdk/version'
5
5
 
6
6
  Gem::Specification.new do |spec|
7
- spec.name = "exponent-server-sdk"
7
+ spec.name = 'exponent-server-sdk'
8
8
  spec.version = Exponent::VERSION
9
- spec.authors = ["Jesse Ruder"]
10
- spec.email = ["jesse@sixfivezero.net"]
9
+ spec.authors = ['Jesse Ruder', 'Pablo Gomez']
10
+ spec.email = ['jesse@sixfivezero.net', 'pablonahuelgomez@gmail.com']
11
11
  spec.summary = %q{Exponent Server SDK}
12
12
  spec.description = %q{Exponent Server SDK}
13
- spec.homepage = ""
14
- spec.license = "MIT"
13
+ spec.homepage = ''
14
+ spec.license = 'MIT'
15
15
 
16
16
  spec.files = `git ls-files -z`.split("\x0")
17
17
  spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
18
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
- spec.require_paths = ["lib"]
19
+ spec.require_paths = ['lib']
20
20
 
21
- spec.add_dependency "httparty"
21
+ spec.add_dependency 'typhoeus'
22
22
 
23
- spec.add_development_dependency "bundler", "~> 1.5"
24
- spec.add_development_dependency "rake"
23
+ spec.add_development_dependency 'bundler'
24
+ spec.add_development_dependency 'rake'
25
+ spec.add_development_dependency 'minitest'
25
26
  end
@@ -1,32 +1,111 @@
1
1
  require 'exponent-server-sdk/version'
2
-
3
- require 'httparty'
2
+ require 'typhoeus'
3
+ require 'json'
4
4
 
5
5
  module Exponent
6
+ def self.is_exponent_push_token?(token)
7
+ token.start_with?('ExponentPushToken')
8
+ end
9
+
6
10
  module Push
7
- def self.is_exponent_push_token?(token)
8
- token.start_with?('ExponentPushToken')
9
- end
11
+ Error = Class.new(StandardError)
10
12
 
11
13
  class Client
12
- def publish options
13
- data = options.delete(:data)
14
- response = HTTParty.post('https://exp.host/--/api/notify/' + ERB::Util.url_encode([options].to_json),
15
- :body => data.to_json,
16
- :headers => {
17
- 'Content-Type' => 'application/json'
18
- }
14
+
15
+ def initialize(new_http_client = nil)
16
+ @http_client = new_http_client || Typhoeus
17
+ end
18
+
19
+ def publish(messages)
20
+ handle_response(push_notifications(messages))
21
+ end
22
+
23
+ private
24
+
25
+ attr_reader :http_client
26
+
27
+ def handle_response(response)
28
+ case response.code.to_s
29
+ when /(^4|^5)/
30
+ raise Error, build_error_from_failure(parse_json(response))
31
+ else
32
+ handle_success(parse_json(response))
33
+ end
34
+ end
35
+
36
+ def parse_json(response)
37
+ JSON.parse(response.body)
38
+ end
39
+
40
+ def build_error_from_failure(response)
41
+ build_error_with_handling(response) do
42
+ extract_error_from_response(response)
43
+ end
44
+ end
45
+
46
+ def extract_error_from_response(response)
47
+ error = response.fetch('errors').first { unknown_error_format(response) }
48
+ "#{error.fetch('code')} -> #{error.fetch('message')}"
49
+ end
50
+
51
+ def build_error_with_handling(response)
52
+ yield(response)
53
+ rescue KeyError
54
+ unknown_error_format(response)
55
+ end
56
+
57
+ def push_notifications(messages)
58
+ http_client.post(
59
+ push_url,
60
+ body: messages.to_json,
61
+ headers: headers
19
62
  )
63
+ end
20
64
 
21
- case response.code
22
- when 400
23
- raise Exponent::Push::Errors::InvalidPushTokenError
65
+ def push_url
66
+ 'https://exp.host/--/api/v2/push/send'
67
+ end
68
+
69
+ def headers
70
+ {
71
+ 'Content-Type' => 'application/json',
72
+ 'Accept' => 'application/json',
73
+ 'Accept-Encoding' => 'gzip, deflate'
74
+ }
75
+ end
76
+
77
+ def handle_success(response)
78
+ data = extract_data(response)
79
+ if data.fetch('status') == 'ok'
80
+ data
81
+ else
82
+ raise Error, build_error_from_success(response)
24
83
  end
25
84
  end
26
- end
27
85
 
28
- module Errors
29
- class InvalidPushTokenError < StandardError
86
+ def build_error_from_success(response)
87
+ build_error_with_handling(response) do
88
+ extract_error_from_success(response)
89
+ end
90
+ end
91
+
92
+ def extract_error_from_success(response)
93
+ data = extract_data(response)
94
+ message = data.fetch('message')
95
+
96
+ if data['details']
97
+ "#{data.fetch('details').fetch('error')} -> #{message}"
98
+ else
99
+ "#{data.fetch('status')} -> #{message}"
100
+ end
101
+ end
102
+
103
+ def extract_data(response)
104
+ response.fetch('data').first
105
+ end
106
+
107
+ def unknown_error_format(response)
108
+ "Unknown error format: #{response}"
30
109
  end
31
110
  end
32
111
  end
@@ -1,3 +1,3 @@
1
1
  module Exponent
2
- VERSION = "0.0.2"
2
+ VERSION = '0.0.3'
3
3
  end
@@ -0,0 +1,130 @@
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_error
23
+ @response_mock.expect(:code, 400)
24
+ @response_mock.expect(:body, error_body.to_json)
25
+ message = 'INTERNAL_SERVER_ERROR -> An unknown error occurred.'
26
+
27
+ @mock.expect(:post, @response_mock, client_args)
28
+
29
+ exception = assert_raises Exponent::Push::Error 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_success_and_errors
39
+ @response_mock.expect(:code, 200)
40
+ @response_mock.expect(:body, success_with_error_body.to_json)
41
+ message = 'DeviceNotRegistered -> "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::Error 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_success_and_apn_error
55
+ @response_mock.expect(:code, 200)
56
+ @response_mock.expect(:body, success_with_apn_error_body.to_json)
57
+ message = 'error -> Could not find APNs credentials for you (your_app). Check whether you are trying to send a notification to a detached app.'
58
+
59
+ @mock.expect(:post, @response_mock, client_args)
60
+
61
+ exception = assert_raises Exponent::Push::Error do
62
+ @exponent.publish(messages)
63
+ end
64
+
65
+ assert_equal(message, exception.message)
66
+
67
+ @mock.verify
68
+ end
69
+
70
+ private
71
+
72
+ def success_body
73
+ { 'data' => [{ 'status' => 'ok' }] }
74
+ end
75
+
76
+ def error_body
77
+ {
78
+ 'errors' => [{
79
+ 'code' => 'INTERNAL_SERVER_ERROR',
80
+ 'message' => 'An unknown error occurred.'
81
+ }]
82
+ }
83
+ end
84
+
85
+ def success_with_error_body
86
+ {
87
+ 'data' => [{
88
+ 'status' => 'error',
89
+ 'message' => '"ExponentPushToken[42]" is not a registered push notification recipient',
90
+ 'details' => { 'error' => 'DeviceNotRegistered' }
91
+ }]
92
+ }
93
+ end
94
+
95
+ def success_with_apn_error_body
96
+ {
97
+ 'data' => [{
98
+ 'status' => 'error',
99
+ 'message' =>
100
+ 'Could not find APNs credentials for you (your_app). Check whether you are trying to send a notification to a detached app.'
101
+ }]
102
+ }
103
+ end
104
+
105
+ def client_args
106
+ [
107
+ 'https://exp.host/--/api/v2/push/send',
108
+ {
109
+ body: messages.to_json,
110
+ headers: {
111
+ 'Content-Type' => 'application/json',
112
+ 'Accept' => 'application/json',
113
+ 'Accept-Encoding' => 'gzip, deflate'
114
+ }
115
+ }
116
+ ]
117
+ end
118
+
119
+ def messages
120
+ [{
121
+ to: 'ExponentPushToken[xxxxxxxxxxxxxxxxxxxxxx]',
122
+ sound: 'default',
123
+ body: 'Hello world!'
124
+ }, {
125
+ to: 'ExponentPushToken[yyyyyyyyyyyyyyyyyyyyyy]',
126
+ badge: 1,
127
+ body: "You've got mail"
128
+ }]
129
+ end
130
+ end
metadata CHANGED
@@ -1,17 +1,18 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: exponent-server-sdk
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jesse Ruder
8
+ - Pablo Gomez
8
9
  autorequire:
9
10
  bindir: bin
10
11
  cert_chain: []
11
- date: 2016-06-20 00:00:00.000000000 Z
12
+ date: 2018-02-13 00:00:00.000000000 Z
12
13
  dependencies:
13
14
  - !ruby/object:Gem::Dependency
14
- name: httparty
15
+ name: typhoeus
15
16
  requirement: !ruby/object:Gem::Requirement
16
17
  requirements:
17
18
  - - ">="
@@ -28,16 +29,16 @@ dependencies:
28
29
  name: bundler
29
30
  requirement: !ruby/object:Gem::Requirement
30
31
  requirements:
31
- - - "~>"
32
+ - - ">="
32
33
  - !ruby/object:Gem::Version
33
- version: '1.5'
34
+ version: '0'
34
35
  type: :development
35
36
  prerelease: false
36
37
  version_requirements: !ruby/object:Gem::Requirement
37
38
  requirements:
38
- - - "~>"
39
+ - - ">="
39
40
  - !ruby/object:Gem::Version
40
- version: '1.5'
41
+ version: '0'
41
42
  - !ruby/object:Gem::Dependency
42
43
  name: rake
43
44
  requirement: !ruby/object:Gem::Requirement
@@ -52,14 +53,30 @@ dependencies:
52
53
  - - ">="
53
54
  - !ruby/object:Gem::Version
54
55
  version: '0'
56
+ - !ruby/object:Gem::Dependency
57
+ name: minitest
58
+ requirement: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ version: '0'
63
+ type: :development
64
+ prerelease: false
65
+ version_requirements: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - ">="
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
55
70
  description: Exponent Server SDK
56
71
  email:
57
72
  - jesse@sixfivezero.net
73
+ - pablonahuelgomez@gmail.com
58
74
  executables: []
59
75
  extensions: []
60
76
  extra_rdoc_files: []
61
77
  files:
62
78
  - ".gitignore"
79
+ - ".travis.yml"
63
80
  - Gemfile
64
81
  - LICENSE.txt
65
82
  - README.md
@@ -68,6 +85,7 @@ files:
68
85
  - lib/exponent-server-sdk.rb
69
86
  - lib/exponent-server-sdk/version.rb
70
87
  - manual-testing.txt
88
+ - test/exponent-server-sdk-test.rb
71
89
  homepage: ''
72
90
  licenses:
73
91
  - MIT
@@ -88,8 +106,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
88
106
  version: '0'
89
107
  requirements: []
90
108
  rubyforge_project:
91
- rubygems_version: 2.4.6
109
+ rubygems_version: 2.6.11
92
110
  signing_key:
93
111
  specification_version: 4
94
112
  summary: Exponent Server SDK
95
- test_files: []
113
+ test_files:
114
+ - test/exponent-server-sdk-test.rb