sms77 0.0.1 → 0.4.0

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 (45) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -2
  3. data/README.md +26 -6
  4. data/lib/sms77.rb +0 -1
  5. data/lib/sms77/client.rb +18 -87
  6. data/lib/sms77/{contacts_action.rb → contacts.rb} +2 -2
  7. data/lib/sms77/endpoint.rb +12 -12
  8. data/lib/sms77/hooks.rb +64 -0
  9. data/lib/sms77/journal.rb +38 -0
  10. data/lib/sms77/{lookup_type.rb → lookup.rb} +2 -2
  11. data/lib/sms77/resource.rb +93 -0
  12. data/lib/sms77/resources/analytics.rb +16 -0
  13. data/lib/sms77/resources/balance.rb +16 -0
  14. data/lib/sms77/resources/contacts.rb +26 -0
  15. data/lib/sms77/resources/hooks.rb +30 -0
  16. data/lib/sms77/resources/journal.rb +16 -0
  17. data/lib/sms77/resources/lookup.rb +30 -0
  18. data/lib/sms77/resources/pricing.rb +16 -0
  19. data/lib/sms77/resources/sms.rb +16 -0
  20. data/lib/sms77/resources/status.rb +16 -0
  21. data/lib/sms77/resources/validate_for_voice.rb +16 -0
  22. data/lib/sms77/resources/voice.rb +16 -0
  23. data/lib/sms77/sms.rb +8 -0
  24. data/lib/sms77/util.rb +68 -0
  25. data/lib/sms77/version.rb +1 -1
  26. data/release.sh +8 -0
  27. data/sms77.gemspec +13 -16
  28. data/spec/EnvKeyStore.rb +15 -0
  29. data/spec/matchers.rb +23 -0
  30. data/spec/sms77/balance_spec.rb +4 -7
  31. data/spec/sms77/client_spec.rb +15 -0
  32. data/spec/sms77/contacts_spec.rb +22 -24
  33. data/spec/sms77/hooks_spec.rb +106 -0
  34. data/spec/sms77/instance_spec.rb +20 -0
  35. data/spec/sms77/journal_spec.rb +86 -0
  36. data/spec/sms77/lookup_spec.rb +73 -82
  37. data/spec/sms77/pricing_spec.rb +25 -29
  38. data/spec/sms77/sms_spec.rb +20 -20
  39. data/spec/sms77/validate_for_voice_spec.rb +6 -6
  40. data/spec/sms77/voice_spec.rb +11 -8
  41. data/spec/sms77_spec.rb +0 -8
  42. data/spec/spec_helper.rb +31 -34
  43. metadata +60 -25
  44. data/lib/sms77/header.rb +0 -7
  45. data/spec/sms77/http_spec.rb +0 -40
@@ -0,0 +1,106 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'securerandom'
4
+ require 'sms77/hooks'
5
+ require 'sms77/util'
6
+ require 'sms77/resources/hooks'
7
+ require 'spec_helper'
8
+
9
+ RSpec.describe Sms77, 'hooks' do
10
+ HOOK_ID = EnvKeyStore.new('HOOK_ID')
11
+ HELPER = Helper.new(Sms77::Resources::Hooks)
12
+
13
+ def alter_action_stub
14
+ {
15
+ :code => nil,
16
+ :success => true
17
+ }
18
+ end
19
+
20
+ def request(fn, stub, extra_params = {})
21
+ res = HELPER.request(fn, stub, extra_params)
22
+
23
+ expect(res).to be_a(Hash)
24
+
25
+ stub_keys = stub.keys
26
+
27
+ res.each do |k, v|
28
+ expect(stub_keys).to include(k)
29
+ expect(v.class).to match(stub[:"#{k}"].class)
30
+ end
31
+
32
+ res
33
+ end
34
+
35
+ it 'returns all hooks' do
36
+ res = request(HELPER.resource.method(:read), {
37
+ :code => nil,
38
+ :hooks => [
39
+ {
40
+ :created => "2020-11-04 23:04:15",
41
+ :event_type => "sms_mo",
42
+ :id => "30",
43
+ :request_method => "GET",
44
+ :target_url => "http://my.tld/testHook"
45
+ }
46
+ ],
47
+ :success => true
48
+ })
49
+
50
+ expect(res).to include(:code, :hooks, :success)
51
+ expect(res[:code]).to eq(nil)
52
+ expect(res[:hooks]).to be_a(Array)
53
+ expect(res[:success]).to be_boolean
54
+
55
+ res[:hooks].each do |hook|
56
+ expect(hook).to include(:created, :event_type, :id, :request_method, :target_url)
57
+
58
+ expect(Sms77::Util::is_valid_datetime?(hook[:created])).to be
59
+ expect(hook[:created]).to match(/^\d\d\d\d-(0?[1-9]|1[0-2])-(0?[1-9]|[12][0-9]|3[01]) (1[0-9]|2[0-3]|0[0-9]):([0-9]|[0-5][0-9]):([0-9]|[0-5][0-9])$/)
60
+ expect(Sms77::Hooks::Validator::event_type?(hook[:event_type])).to be
61
+ expect(Sms77::Util::is_positive_integer?(hook[:id])).to be
62
+ expect(Sms77::Hooks::Validator::request_method?(hook[:request_method])).to be
63
+ expect(Sms77::Hooks::Validator::target_url?(hook[:target_url])).to be
64
+ end
65
+ end
66
+
67
+ =begin
68
+ it 'subscribes' do
69
+ stub = alter_action_stub.merge({ :id => rand(1...1000000) })
70
+
71
+ res = request(HELPER.resource.method(:subscribe), stub, {
72
+ :event_type => Sms77::Hooks::EventType::NEW_INBOUND_SMS,
73
+ :request_method => Sms77::Hooks::RequestMethod::GET,
74
+ :target_url => "http://ruby.tld/#{SecureRandom.uuid}"
75
+ })
76
+
77
+ expect(Sms77::Util::is_positive_integer?(res[:id])).to be
78
+ expect(res[:id]).to be_a(Integer)
79
+ expect(stub[:id]).to match(res[:id]) unless Helper::IS_HTTP
80
+
81
+ assert_alter_response(res)
82
+
83
+ puts "Subscribed ID: #{Helper::IS_HTTP ? res[:id] : stub[:id]}"
84
+
85
+ HOOK_ID.set(res[:id])
86
+ end
87
+
88
+ it 'unsubscribes' do
89
+ id = HOOK_ID.get
90
+ res = request(HELPER.resource.method(:unubscribe), alter_action_stub, { :id => id })
91
+
92
+ assert_alter_response(res)
93
+
94
+ expect(res[:success]).to be_boolean
95
+
96
+ puts "Unsubscribed ID #{id}: #{res[:success]}"
97
+
98
+ res[:success]
99
+ end
100
+ =end
101
+
102
+ def assert_alter_response(res)
103
+ expect(res[:code]).to match(nil)
104
+ expect(res[:success]).to be_boolean
105
+ end
106
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+ require 'sms77/resource'
5
+
6
+ RSpec.describe Sms77, 'instance' do
7
+ helper = Helper.new(Sms77::Resource)
8
+
9
+ it 'checks api key' do
10
+ expect(helper.resource.api_key).to be_lengthy_string
11
+ end
12
+
13
+ it 'checks sentWith' do
14
+ expect(helper.resource.sent_with).to be_lengthy_string
15
+ end
16
+
17
+ it 'fails authentication' do
18
+ expect { Sms77::Resource.new('') }.to raise_error(RuntimeError)
19
+ end
20
+ end
@@ -0,0 +1,86 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+ require 'sms77/journal'
5
+ require 'sms77/resources/journal'
6
+ require 'sms77/sms'
7
+
8
+ RSpec.describe Sms77, 'journal' do
9
+ def valid_timestamp?(str)
10
+ str.match(/[\d]{4}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][\d]|3[0-1]) (2[0-3]|[01][\d]):[0-5][\d]/)
11
+ end
12
+
13
+ def request(type)
14
+ stub = [{
15
+ :from => "SMS",
16
+ :id => "123456789",
17
+ :price => "1.2",
18
+ :text => "Hey my friend!",
19
+ :timestamp => "2020-10-14 14:25:04",
20
+ :to => "49170123456789",
21
+ }]
22
+
23
+ helper = Helper.new(Sms77::Resources::Journal)
24
+ res = helper.request(helper.resource.method(:retrieve), stub, { type: type })
25
+
26
+ expect(res).to be_a(Array)
27
+
28
+ res.each do |journal|
29
+ expect(journal).to be_a(Hash)
30
+ expect(journal[:from]).to be_lengthy_string
31
+ expect(journal[:id]).to be_numeric
32
+ expect(Sms77::Util::valid_float?(journal[:price])).to be_truthy
33
+ expect(journal[:text]).to be_lengthy_string
34
+ expect(valid_timestamp?(journal[:timestamp])).to be_truthy
35
+ expect(journal[:to]).to be_lengthy_string
36
+ end
37
+
38
+ res
39
+ end
40
+
41
+ it 'returns all inbound messages' do
42
+ request(Sms77::Journal::Type::INBOUND)
43
+ end
44
+
45
+ it 'returns all outbound messages' do
46
+ request(Sms77::Journal::Type::OUTBOUND).each do |journal|
47
+ journal.merge!({
48
+ :connection => "http",
49
+ :dlr => "DELIVERED",
50
+ :dlr_timestamp => "2020-10-04 09:26:10.000",
51
+ :foreign_id => "MyForeignId",
52
+ :label => "MyCustomLabel",
53
+ :latency => "5.1060",
54
+ :mccmnc => "26207",
55
+ :type => "direct",
56
+ })
57
+ expect(journal[:connection]).to be_lengthy_string
58
+ expect(journal[:dlr]).to be_nil_or_lengthy_string
59
+ expect(valid_timestamp?(journal[:dlr_timestamp])).to be_truthy
60
+ expect(journal[:foreign_id]).to be_nil_or_lengthy_string
61
+ expect(journal[:label]).to be_nil_or_lengthy_string
62
+ expect(journal[:latency]).to be_nil_or_lengthy_string
63
+ expect(journal[:mccmnc]).to be_nil_or_lengthy_string
64
+ expect(Sms77::Util::in_module_constants?(journal[:type], Sms77::Sms::Type)).to be_truthy
65
+ end
66
+ end
67
+
68
+ it 'returns all voice messages' do
69
+ request(Sms77::Journal::Type::VOICE).each do |journal|
70
+ journal.merge!({
71
+ :duration => "2",
72
+ :error => "",
73
+ :status => "completed",
74
+ :xml => false,
75
+ })
76
+ expect(journal[:duration]).to be_numeric
77
+ expect(journal[:error]).to be_nil_or_lengthy_string
78
+ expect(journal[:status]).to be_lengthy_string
79
+ expect(journal[:xml]).to be_boolean
80
+ end
81
+ end
82
+
83
+ it 'returns all reply messages' do
84
+ request(Sms77::Journal::Type::REPLIES)
85
+ end
86
+ end
@@ -2,26 +2,17 @@
2
2
 
3
3
  require 'spec_helper'
4
4
  require 'sms77/endpoint'
5
- require 'sms77/lookup_type'
5
+ require 'sms77/lookup'
6
+ require 'sms77/resources/lookup'
6
7
  require 'json'
7
8
 
8
9
  RSpec.describe Sms77, 'lookup' do
9
10
  def request(type, stub, extra_args = {})
10
- Helper.stubs.get("/api/#{Sms77::Endpoint::LOOKUP}") { |_env| [200, {}, JSON.generate(stub)] } unless Helper.is_http
11
-
12
- response = Helper.client.lookup({ type: type, number: '+491771783130' }.merge(extra_args))
13
-
14
- expect(response.class).to eq(Faraday::Response)
15
-
16
- body = response.body
17
-
18
- begin
19
- body = JSON.parse(body)
20
- rescue StandardError
21
- # Ignored
22
- end
23
-
24
- body
11
+ helper = Helper.new(Sms77::Resources::Lookup)
12
+ helper.request(
13
+ helper.resource.method(type),
14
+ stub,
15
+ { number: '+491771783130' }.merge(extra_args))
25
16
  end
26
17
 
27
18
  it 'misses number to lookup' do
@@ -37,10 +28,10 @@ RSpec.describe Sms77, 'lookup' do
37
28
  success: false
38
29
  }
39
30
 
40
- body = request(Sms77::LookupType::FORMAT, stub, { number: '' })
31
+ res = request(Sms77::Lookup::Type::FORMAT, stub, { number: '' })
41
32
 
42
- expect(body).to be_kind_of(Hash)
43
- expect(body['success']).to match(false)
33
+ expect(res).to be_a(Hash)
34
+ expect(res[:success]).to match(false)
44
35
  end
45
36
 
46
37
  it 'returns number formatting details as json' do
@@ -56,18 +47,18 @@ RSpec.describe Sms77, 'lookup' do
56
47
  success: true
57
48
  }
58
49
 
59
- body = request(Sms77::LookupType::FORMAT, stub)
60
-
61
- expect(body).to be_kind_of(Hash)
62
- expect(body['carrier']).to be_kind_of(String)
63
- expect(body['country_code']).to be_kind_of(String)
64
- expect(body['country_iso']).to be_kind_of(String)
65
- expect(body['country_name']).to be_kind_of(String)
66
- expect(body['international']).to be_kind_of(String)
67
- expect(body['international_formatted']).to be_kind_of(String)
68
- expect(body['national']).to be_kind_of(String)
69
- expect(body['network_type']).to be_kind_of(String)
70
- expect(body['success']).to be_boolean
50
+ body = request(Sms77::Lookup::Type::FORMAT, stub)
51
+
52
+ expect(body).to be_a(Hash)
53
+ expect(body[:carrier]).to be_a(String)
54
+ expect(body[:country_code]).to be_a(String)
55
+ expect(body[:country_iso]).to be_a(String)
56
+ expect(body[:country_name]).to be_a(String)
57
+ expect(body[:international]).to be_a(String)
58
+ expect(body[:international_formatted]).to be_a(String)
59
+ expect(body[:national]).to be_a(String)
60
+ expect(body[:network_type]).to be_a(String)
61
+ expect(body[:success]).to be_boolean
71
62
  end
72
63
 
73
64
  it 'returns CNAM details as json' do
@@ -77,19 +68,19 @@ RSpec.describe Sms77, 'lookup' do
77
68
  number: '+491771783130',
78
69
  success: 'true'
79
70
  }
80
- body = request(Sms77::LookupType::CNAM, stub)
71
+ body = request(Sms77::Lookup::Type::CNAM, stub)
81
72
 
82
- expect(body).to be_kind_of(Hash)
83
- expect(body['code']).to be_kind_of(String)
84
- expect(body['name']).to be_kind_of(String)
85
- expect(body['number']).to be_kind_of(String)
86
- expect(body['success']).to be_kind_of(String)
73
+ expect(body).to be_a(Hash)
74
+ expect(body[:code]).to be_a(String)
75
+ expect(body[:name]).to be_a(String)
76
+ expect(body[:number]).to be_a(String)
77
+ expect(body[:success]).to be_a(String)
87
78
  end
88
79
 
89
80
  it 'returns MNP details as text' do
90
- body = request(Sms77::LookupType::MNP, 'eplus')
81
+ body = request(Sms77::Lookup::Type::MNP, 'eplus')
91
82
 
92
- expect(body).to be_kind_of(String)
83
+ expect(body).to be_a(String)
93
84
  end
94
85
 
95
86
  it 'returns MNP details as json' do
@@ -107,20 +98,20 @@ RSpec.describe Sms77, 'lookup' do
107
98
  price: 0.005,
108
99
  success: true
109
100
  }
110
- body = request(Sms77::LookupType::MNP, stub, { json: 1 })
111
-
112
- expect(body).to be_kind_of(Hash)
113
- expect(body['code']).to be_kind_of(Integer)
114
- expect(body['price']).to be_kind_of(Float)
115
- expect(body['mnp']).to be_kind_of(Hash)
116
- expect(body['mnp']['country']).to be_kind_of(String)
117
- expect(body['mnp']['international_formatted']).to be_kind_of(String)
118
- expect(body['mnp']['isPorted']).to be_boolean
119
- expect(body['mnp']['mccmnc']).to be_kind_of(String)
120
- expect(body['mnp']['national_format']).to be_kind_of(String)
121
- expect(body['mnp']['network']).to be_kind_of(String)
122
- expect(body['mnp']['number']).to be_kind_of(String)
123
- expect(body['success']).to be_boolean
101
+ body = request(Sms77::Lookup::Type::MNP, stub, { json: 1 })
102
+
103
+ expect(body).to be_a(Hash)
104
+ expect(body[:code]).to be_a(Integer)
105
+ expect(body[:price]).to be_a(Float)
106
+ expect(body[:mnp]).to be_a(Hash)
107
+ expect(body[:mnp][:country]).to be_a(String)
108
+ expect(body[:mnp][:international_formatted]).to be_a(String)
109
+ expect(body[:mnp][:isPorted]).to be_boolean
110
+ expect(body[:mnp][:mccmnc]).to be_a(String)
111
+ expect(body[:mnp][:national_format]).to be_a(String)
112
+ expect(body[:mnp][:network]).to be_a(String)
113
+ expect(body[:mnp][:number]).to be_a(String)
114
+ expect(body[:success]).to be_boolean
124
115
  end
125
116
 
126
117
  it 'returns HLR details as json' do
@@ -155,34 +146,34 @@ RSpec.describe Sms77, 'lookup' do
155
146
  valid_number: 'valid'
156
147
  }
157
148
 
158
- body = request(Sms77::LookupType::HLR, stub)
159
-
160
- expect(body).to be_kind_of(Hash)
161
- expect(body['country_code']).to be_kind_of(String)
162
- expect(body['country_name']).to be_kind_of(String)
163
- expect(body['country_prefix']).to be_kind_of(String)
164
- expect(body['current_carrier']).to be_kind_of(Hash)
165
- expect(body['current_carrier']['country']).to be_kind_of(String)
166
- expect(body['current_carrier']['name']).to be_kind_of(String)
167
- expect(body['current_carrier']['network_code']).to be_kind_of(String)
168
- expect(body['current_carrier']['network_type']).to be_kind_of(String)
169
- expect(body['international_format_number']).to be_kind_of(String)
170
- expect(body['international_formatted']).to be_kind_of(String)
171
- expect(body['lookup_outcome']).to be_boolean
172
- expect(body['lookup_outcome_message']).to be_kind_of(String)
173
- expect(body['national_format_number']).to be_kind_of(String)
174
- expect(body['original_carrier']).to be_kind_of(Hash)
175
- expect(body['original_carrier']['country']).to be_kind_of(String)
176
- expect(body['original_carrier']['name']).to be_kind_of(String)
177
- expect(body['original_carrier']['network_code']).to be_kind_of(String)
178
- expect(body['original_carrier']['network_type']).to be_kind_of(String)
179
- expect(body['status']).to be_boolean
180
- expect(body['status_message']).to be_kind_of(String)
181
- expect(body['gsm_code']).to be_kind_of(String)
182
- expect(body['gsm_message']).to be_kind_of(String)
183
- expect(body['ported']).to be_kind_of(String)
184
- expect(body['reachable']).to be_kind_of(String)
185
- expect(body['roaming']).to be_kind_of(String)
186
- expect(body['valid_number']).to be_kind_of(String)
149
+ body = request(Sms77::Lookup::Type::HLR, stub)
150
+
151
+ expect(body).to be_a(Hash)
152
+ expect(body[:country_code]).to be_a(String)
153
+ expect(body[:country_name]).to be_a(String)
154
+ expect(body[:country_prefix]).to be_a(String)
155
+ assert_carrier(body[:current_carrier])
156
+ expect(body[:international_format_number]).to be_a(String)
157
+ expect(body[:international_formatted]).to be_a(String)
158
+ expect(body[:lookup_outcome]).to be_boolean
159
+ expect(body[:lookup_outcome_message]).to be_a(String)
160
+ expect(body[:national_format_number]).to be_a(String)
161
+ assert_carrier(body[:original_carrier])
162
+ expect(body[:status]).to be_boolean
163
+ expect(body[:status_message]).to be_a(String)
164
+ expect(body[:gsm_code]).to be_a(String)
165
+ expect(body[:gsm_message]).to be_a(String)
166
+ expect(body[:ported]).to be_a(String)
167
+ expect(body[:reachable]).to be_a(String)
168
+ expect(body[:roaming]).to be_a(String)
169
+ expect(body[:valid_number]).to be_a(String)
170
+ end
171
+
172
+ def assert_carrier(hash)
173
+ expect(hash).to be_a(Hash)
174
+ expect(hash[:country]).to be_a(String)
175
+ expect(hash[:name]).to be_a(String)
176
+ expect(hash[:network_code]).to be_a(String)
177
+ expect(hash[:network_type]).to be_a(String)
187
178
  end
188
179
  end
@@ -1,8 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'spec_helper'
4
- require 'sms77/endpoint'
5
- require 'json'
4
+ require 'sms77/resources/pricing'
6
5
 
7
6
  RSpec.describe Sms77, 'pricing' do
8
7
  it 'returns all countries pricing as json' do
@@ -36,44 +35,41 @@ RSpec.describe Sms77, 'pricing' do
36
35
  ]
37
36
  }
38
37
 
39
- Helper.stubs.get("/api/#{Sms77::Endpoint::PRICING}") { |_env| [200, {}, JSON.generate(stub)] } unless Helper.is_http
38
+ helper = Helper.new(Sms77::Resources::Pricing)
39
+ res = helper.request(helper.resource.method(:retrieve), stub)
40
+ countries = res[:countries]
40
41
 
41
- response = Helper.client.pricing
42
- body = JSON.parse(response.body)
43
- countries = body['countries']
44
-
45
- expect(response.class).to eq(Faraday::Response)
46
- expect(body).to be_kind_of(Hash)
47
- expect(body['countCountries']).to be_kind_of(Integer)
48
- expect(body['countNetworks']).to be_kind_of(Integer)
49
- expect(countries).to be_kind_of(Array)
42
+ expect(res).to be_a(Hash)
43
+ expect(res[:countCountries]).to be_a(Integer)
44
+ expect(res[:countNetworks]).to be_a(Integer)
45
+ expect(countries).to be_a(Array)
50
46
 
51
47
  countries.each do |country|
52
- networks = country['networks']
48
+ networks = country[:networks]
53
49
 
54
- expect(country).to be_kind_of(Hash)
55
- expect(country['countryCode']).to be_kind_of(String)
56
- expect(country['countryName']).to be_kind_of(String)
57
- expect(country['countryPrefix']).to be_kind_of(String)
58
- expect(networks).to be_kind_of(Array)
50
+ expect(country).to be_a(Hash)
51
+ expect(country[:countryCode]).to be_a(String)
52
+ expect(country[:countryName]).to be_a(String)
53
+ expect(country[:countryPrefix]).to be_a(String)
54
+ expect(networks).to be_a(Array)
59
55
 
60
56
  networks.each do |network|
61
- mncs = network['mncs']
62
- features = network['features']
57
+ mncs = network[:mncs]
58
+ features = network[:features]
63
59
 
64
- expect(network).to be_kind_of(Hash)
65
- expect(network['mcc']).to be_kind_of(String)
66
- expect(mncs).to be_kind_of(Array)
60
+ expect(network).to be_a(Hash)
61
+ expect(network[:mcc]).to be_a(String)
62
+ expect(mncs).to be_a(Array)
67
63
  mncs.each do |mnc|
68
- expect(mnc).to be_kind_of(String)
64
+ expect(mnc).to be_a(String)
69
65
  end
70
- expect(network['networkName']).to be_kind_of(String)
71
- expect(network['price']).to be_kind_of(Float)
72
- expect(features).to be_kind_of(Array)
66
+ expect(network[:networkName]).to be_a(String)
67
+ expect(network[:price]).to be_a(Float)
68
+ expect(features).to be_a(Array)
73
69
  features.each do |feature|
74
- expect(feature).to be_kind_of(String)
70
+ expect(feature).to be_a(String)
75
71
  end
76
- expect(network['comment']).to be_kind_of(String)
72
+ expect(network[:comment]).to be_a(String)
77
73
  end
78
74
  end
79
75
  end