diff --git a/lib/cm_sms/configuration.rb b/lib/cm_sms/configuration.rb index 14e48a9..ebb9358 100644 --- a/lib/cm_sms/configuration.rb +++ b/lib/cm_sms/configuration.rb @@ -4,16 +4,20 @@ class ProductTokenMissing < ArgumentError; end class EndpointMissing < ArgumentError; end class PathMissing < ArgumentError; end - ENDPOINT = 'https://sgw01.cm.nl'.freeze - PATH = '/gateway.ashx'.freeze - DCS = 0 + ENDPOINTS = %w[https://gw.cmtelecom.com].map(&:freeze).freeze + PATH = '/gateway.ashx'.freeze + DCS = 0 + TIMEOUT = 10 - attr_accessor :from, :to, :product_token, :endpoint, :path, :dcs + attr_accessor :from, :to, :product_token + attr_writer :endpoints, :path, :dcs, :timeout alias api_key= product_token= + alias endpoint= endpoints= - def endpoint - @endpoint || ENDPOINT + def endpoints + endpoints = Array(@endpoints) + endpoints.empty? ? ENDPOINTS : endpoints end def path @@ -24,6 +28,10 @@ def dcs @dcs || DCS end + def timeout + @timeout || TIMEOUT + end + def defaults @defaults ||= { from: from, to: to, dcs: dcs } end diff --git a/lib/cm_sms/message.rb b/lib/cm_sms/message.rb index 526c4ce..6d94bcb 100644 --- a/lib/cm_sms/message.rb +++ b/lib/cm_sms/message.rb @@ -12,6 +12,7 @@ class ToUnplausible < ArgumentError; end class DCSNotNumeric < ArgumentError; end attr_accessor :from, :to, :body, :dcs, :reference + attr_reader :product_token, :endpoints def initialize(attributes = {}) @from = attributes[:from] @@ -20,7 +21,16 @@ def initialize(attributes = {}) @body = attributes[:body] @reference = attributes[:reference] - @product_token = CmSms.config.product_token + self.product_token = attributes[:product_token] + self.endpoints = attributes[:endpoints] + end + + def product_token=(value) + @product_token = value || CmSms.config.product_token + end + + def endpoints=(value) + @endpoints = value ? Array(value) : CmSms.config.endpoints end def dcs_numeric? @@ -64,7 +74,7 @@ def product_token_present? end def request - Request.new(to_xml) + Request.new(to_xml, @endpoints) end def deliver diff --git a/lib/cm_sms/request.rb b/lib/cm_sms/request.rb index 1bf89ef..33a4d10 100644 --- a/lib/cm_sms/request.rb +++ b/lib/cm_sms/request.rb @@ -6,18 +6,19 @@ class Request attr_reader :response - def initialize(body) + def initialize(body, endpoints = nil) @body = body - @endpoint = CmSms.config.endpoint + @endpoint = (endpoints || CmSms.config.endpoints).sample @path = CmSms.config.path end def perform - raise CmSms::Configuration::EndpointMissing, "Please provide an valid api endpoint.\nIf you leave this config blank, the default will be set to https://sgw01.cm.nl." if @endpoint.nil? || @endpoint.empty? + raise CmSms::Configuration::EndpointMissing, 'Please provide an valid api endpoint.' if @endpoint.nil? || @endpoint.empty? raise CmSms::Configuration::PathMissing, "Please provide an valid api path.\nIf you leave this config blank, the default will be set to /gateway.ashx." if @path.nil? || @path.empty? uri = URI.parse(@endpoint) - Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == 'https') do |http| + timeout = CmSms.config.timeout + Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == 'https', open_timeout: timeout, read_timeout: timeout) do |http| @response = Response.new(http.post(@path, body, 'Content-Type' => 'application/xml')) end response diff --git a/spec/cm_sms/configuration_spec.rb b/spec/cm_sms/configuration_spec.rb index 3fbe891..a9ff4ea 100644 --- a/spec/cm_sms/configuration_spec.rb +++ b/spec/cm_sms/configuration_spec.rb @@ -3,7 +3,7 @@ RSpec.describe CmSms::Configuration do it 'has a endpoit set in constant' do - expect(CmSms::Configuration::ENDPOINT).to eq 'https://sgw01.cm.nl' + expect(CmSms::Configuration::ENDPOINTS).to eq %w[https://gw.cmtelecom.com] end it 'has a path default' do @@ -12,20 +12,30 @@ let(:config) { described_class.new } - describe '#endpoint' do + describe '#endpoints' do context 'when endpoint is set through setter' do subject(:resource) do config.endpoint = 'http://local.host' config end - it 'returns the setted endpoint' do - expect(resource.endpoint).to eq 'http://local.host' + it 'returns the set endpoint' do + expect(resource.endpoints).to eq ['http://local.host'] end end - context 'when endpoint is not set' do - it 'returns the default enpoint set in constant' do - expect(config.endpoint).to eq CmSms::Configuration::ENDPOINT + context 'when endpoints is set through setter' do + subject(:resource) do + config.endpoints = %w[http://local.host http://other.host] + config + end + it 'returns the set endpoint' do + expect(resource.endpoints).to eq %w[http://local.host http://other.host] + end + end + + context 'when endpoints is not set' do + it 'returns the default endpoints set in constant' do + expect(config.endpoints).to eq CmSms::Configuration::ENDPOINTS end end end @@ -36,13 +46,13 @@ config.path = '/example' config end - it 'returns the setted path' do + it 'returns the set path' do expect(resource.path).to eq '/example' end end context 'when path is not set' do - it 'returns the default enpoint set in constant' do + it 'returns the default path set in constant' do expect(config.path).to eq CmSms::Configuration::PATH end end @@ -54,25 +64,43 @@ config.dcs = 8 config end - it 'returns the setted dcs' do + it 'returns the set dcs' do expect(resource.dcs).to eq 8 end end context 'when dcs is not set' do - it 'returns the default enpoint set in constant' do + it 'returns the default dcs set in constant' do expect(config.dcs).to eq CmSms::Configuration::DCS end end end + describe '#timeout' do + context 'when timeout is set through setter' do + subject(:resource) do + config.timeout = 20 + config + end + it 'returns the set timeout' do + expect(resource.timeout).to eq 20 + end + end + + context 'when timeout is not set' do + it 'returns the default timeout set in constant' do + expect(config.timeout).to eq CmSms::Configuration::TIMEOUT + end + end + end + describe '#product_token' do context 'when product_token is set through setter' do subject(:resource) do config.product_token = 'SOMETOKEN' config end - it 'returns the setted product_token' do + it 'returns the set product_token' do expect(resource.product_token).to eq 'SOMETOKEN' end end @@ -82,7 +110,7 @@ config.api_key = 'SOMEKEY' config end - it 'returns the setted product_token' do + it 'returns the set product_token' do expect(resource.product_token).to eq 'SOMEKEY' end end @@ -94,7 +122,7 @@ config.from = 'me' config end - it 'returns the setted from' do + it 'returns the set from' do expect(resource.from).to eq 'me' end end @@ -106,7 +134,7 @@ config.to = 'you' config end - it 'returns the setted to' do + it 'returns the set to' do expect(resource.to).to eq 'you' end end diff --git a/spec/cm_sms/message_spec.rb b/spec/cm_sms/message_spec.rb index eb9965f..bddbcc0 100644 --- a/spec/cm_sms/message_spec.rb +++ b/spec/cm_sms/message_spec.rb @@ -4,12 +4,17 @@ RSpec.describe CmSms::Message do let(:message_body) { 'Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirood tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At v' } + let(:product_token) { nil } + let(:endpoints) { nil } + let(:message) do message = described_class.new message.from = 'ACME' message.to = '+41 44 111 22 33' message.body = message_body message.reference = 'Ref:123' + message.product_token = product_token + message.endpoints = endpoints message end @@ -110,15 +115,57 @@ end end - describe '#product_token_present?' do - context 'when a valid product_token is provided' do + describe '#endpoints' do + context 'when a endpoints configured at config level' do + before { CmSms.configure { |config| config.endpoints = %w[bazqux bingbaz] } } + it { expect(message.endpoints).to eq %w[bazqux bingbaz] } + + context 'when a endpoints set on message' do + let(:endpoints) { 'foobar' } + it { expect(message.endpoints).to eq ['foobar'] } + end + end + + context 'when no endpoints is provided' do + before { CmSms.configure { |config| config.endpoints = nil } } + it { expect(message.endpoints).to eq %w[https://gw.cmtelecom.com] } + + context 'when a endpoints set on message' do + let(:endpoints) { 'foobar' } + it { expect(message.endpoints).to eq ['foobar'] } + end + end + end + + describe '#product_token and #product_token_present?' do + context 'when a product_token configured at config level' do before { CmSms.configure { |config| config.product_token = 'SOMETOKEN' } } - it { expect(message.product_token_present?).to be true } + it { expect(message.product_token).to eq 'SOMETOKEN' } + it { expect(message.product_token_present?).to eq true } + + context 'when a product_token set on message' do + let(:product_token) { 'MSGTOKEN' } + it { expect(message.product_token).to eq 'MSGTOKEN' } + it { expect(message.product_token_present?).to eq true } + end end context 'when no product_token is provided' do before { CmSms.configure { |config| config.product_token = nil } } - it { expect(message.product_token_present?).to be false } + it { expect(message.product_token).to eq nil } + it { expect(message.product_token_present?).to eq false } + + context 'when a product_token set on message' do + let(:product_token) { 'MSGTOKEN' } + it { expect(message.product_token).to eq 'MSGTOKEN' } + it { expect(message.product_token_present?).to eq true } + end + end + + context 'when no product_token is blank' do + before { CmSms.configure { |config| config.product_token = '' } } + it { expect(message.product_token).to eq '' } + it { expect(message.product_token_present?).to eq false } end end @@ -208,7 +255,22 @@ end describe '#request' do + before { CmSms.configure { |config| config.endpoints = nil } } + it { expect(message.request).to be_kind_of(CmSms::Request) } + + it do + expect(CmSms::Request).to receive(:new).with(message.to_xml, %w[https://gw.cmtelecom.com]) + message.request + end + + context 'when endpoints set' do + let(:endpoints) { 'foobar' } + it do + expect(CmSms::Request).to receive(:new).with(message.to_xml, %w[foobar]) + message.request + end + end end describe '#to_xml' do diff --git a/spec/cm_sms/request_spec.rb b/spec/cm_sms/request_spec.rb index a1901ed..3ae5dc9 100644 --- a/spec/cm_sms/request_spec.rb +++ b/spec/cm_sms/request_spec.rb @@ -12,7 +12,28 @@ message end let(:request_body) { message.to_xml } - let(:request) { described_class.new(request_body) } + let(:endpoints) { nil } + let(:request) { described_class.new(request_body, endpoints) } + + describe '@endpoint' do + before { CmSms.configuration.endpoints = nil } + + context 'endpoint is randomized to first' do + before { srand(0) } + it { expect(request.instance_variable_get('@endpoint')).to eq 'https://gw.cmtelecom.com' } + end + + context 'endpoint is randomized to second' do + before { srand(1) } + it { expect(request.instance_variable_get('@endpoint')).to eq 'https://gw.cmtelecom.com' } + end + + context 'when endpoints arg set' do + let(:endpoints) { %w[foobar bazqux] } + before { srand(0) } + it { expect(request.instance_variable_get('@endpoint')).to eq 'foobar' } + end + end describe '#perform' do context 'when the API endpoint is missing' do diff --git a/spec/cm_sms_spec.rb b/spec/cm_sms_spec.rb index 37568b7..463d085 100644 --- a/spec/cm_sms_spec.rb +++ b/spec/cm_sms_spec.rb @@ -21,7 +21,7 @@ expect(CmSms.config.from).to eq '+41 44 111 22 33' expect(CmSms.config.to).to eq '+41 44 111 22 33' expect(CmSms.config.product_token).to eq 'SOMETOKEN' - expect(CmSms.config.endpoint).to eq 'http://example.com' + expect(CmSms.config.endpoints).to eq ['http://example.com'] expect(CmSms.config.path).to eq '/example' end end