bobes-textmagic 0.1.0 → 0.2.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.
data/README.rdoc CHANGED
@@ -1,6 +1,39 @@
1
- = textmagic
1
+ = TextMagic
2
+
3
+ TextMagic is a Ruby interface to the TextMagic's HTTP API. You need to have
4
+ a valid TextMagic account to use this gem. Sign up at http://www.textmagic.com
5
+ to get one.
6
+
7
+ == Installation
8
+
9
+ Run
10
+
11
+ gem install textmagic
12
+
13
+ Use +sudo+ if required by your system.
14
+
15
+
16
+ == Basic usage
17
+
18
+ To create an API instance, run:
19
+
20
+ api = TextMagic::API.new(username, password)
21
+
22
+ with your credentials. Created instance will remember the username and password
23
+ and will use it for all commands.
24
+
25
+ To retrieve your account's balance, run:
26
+
27
+ api.account['balance']
28
+
29
+ To send a text message, run:
30
+
31
+ api.send 'Hi Vilma!', '441234567890'
32
+
33
+ You can even specify multiple phone numbers:
34
+
35
+ api.send 'Hi Vilma!', '314159265358', '271828182845'
2
36
 
3
- Documentation will come soon.
4
37
 
5
38
  == Copyright
6
39
 
data/VERSION.yml CHANGED
@@ -1,4 +1,4 @@
1
1
  ---
2
2
  :major: 0
3
- :minor: 1
3
+ :minor: 2
4
4
  :patch: 0
data/lib/api.rb CHANGED
@@ -2,33 +2,178 @@ module TextMagic
2
2
 
3
3
  class API
4
4
 
5
+ extend Charset
6
+ extend Validation
7
+
8
+ # Creates new API instance with specified credentials. These will be
9
+ # used in all requests to the TextMagic's HTTP gateway done through
10
+ # this instance. Multiple instances with different credentials can
11
+ # be used at the same time.
12
+ #
13
+ # Example usage:
14
+ #
15
+ # api = TextMagic::API.new('fred', 'secret')
5
16
  def initialize(username, password)
6
17
  @username = username
7
18
  @password = password
8
19
  end
9
20
 
21
+ # Executes an account command and returns a hash with account's balance
22
+ # if successful, otherwise it raises an Error.
23
+ # The returned hash will be extended with custom reader method defined
24
+ # in Response module.
25
+ #
26
+ # Example usage:
27
+ #
28
+ # api.account
29
+ # # => { 'balance' => 314.15 }
30
+ #
31
+ # Using custom reader:
32
+ #
33
+ # api.account.balance
34
+ # # => 314.15
10
35
  def account
11
36
  response = Executor.execute('account', @username, @password)
12
- response['balance'] = response['balance'].to_f
13
- response
37
+ response.extend(TextMagic::API::Response::Account)
14
38
  end
15
39
 
40
+ # Executes a send command and returns a hash with message ids, sent text and
41
+ # number of parts if successful, otherwise it raises an Error.
42
+ # The returned hash will be extended with custom reader method defined
43
+ # in Response module.
44
+ #
45
+ # This method accepts any positive number of phone numbers and an additional
46
+ # options hash.
47
+ #
48
+ # The optional parameters you can specify in the options hash are:
49
+ # * +unicode+: accepted values are true, false, 0 and 1
50
+ # * +max_length+: accepted values are nil, 1, 2 and 3, defaults to nil
51
+ # If not specified, the method will determine the unicode value based on the
52
+ # characters in the text.
53
+ #
54
+ # Example usage:
55
+ #
56
+ # api.send('Hi Vilma', '999314159265')
57
+ # # => { 'message_ids' => [141421], 'message_id_hash' => { '999314159265' => '141421' }, 'sent_text' => 'Hi Vilma', 'parts_count' => 1 }
58
+ # api.send(text, phone, :unicode => true)
59
+ # api.send(text, phone1, phone2, :max_length => 2)
60
+ # api.send(text, [phone1, phone2])
61
+ #
62
+ # Using custom readers:
63
+ #
64
+ # response = api.send('Hi Vilma', '999314159265', '999271828182')
65
+ # response.message_ids
66
+ # # => ['141421', '173205']
67
+ # response.message_id_hash
68
+ # # => { '999314159265' => '141421', '999271828182' => '173205' }
69
+ # response.message_id
70
+ # # => '141421'
71
+ # response.message_id('999271828182')
72
+ # # => '173205'
73
+ # response.parts_count
74
+ # # => 1
16
75
  def send(text, *args)
76
+ raise Error.new(1, 'Message text is empty') if text.nil? || text.blank?
17
77
  options = args.last.is_a?(Hash) ? args.pop : {}
18
- phones = args.flatten.join(',')
19
- Executor.execute('send', @username, @password, options.merge(:text => text, :phone => phones))
78
+ unicode = API.is_unicode(text)
79
+ options[:unicode] = case options[:unicode]
80
+ when 1, true: 1
81
+ when 0, false: 0
82
+ when nil: unicode ? 1 : 0
83
+ else raise Error.new(10, "Wrong parameter value #{options[:unicode]} for parameter unicode")
84
+ end
85
+ raise Error.new(6, 'Message contains invalid characters') if unicode && options[:unicode] == 0
86
+ raise Error.new(7, 'Message too long') unless API.validate_text_length(text, unicode)
87
+ phones = args.flatten
88
+ raise Error.new(9, 'Invalid phone number format') unless API.validate_phones(phones)
89
+ response = Executor.execute('send', @username, @password, options.merge(:text => text, :phone => phones.join(',')))
90
+ response.extend(TextMagic::API::Response::Send)
20
91
  end
21
92
 
93
+ # Executes a message_status command and returns a hash with states of
94
+ # messages for specified ids if successful, otherwise it raises a
95
+ # TextMagic::API::Error.
96
+ # The returned hash will be extended with custom reader method defined
97
+ # in Response module.
98
+ #
99
+ # This method accepts any positive number of ids specified as an array
100
+ # or as a list of arguments
101
+ #
102
+ # Example usage:
103
+ #
104
+ # api.message_status('141421')
105
+ # # => { '141421' => { 'text' => 'Hi Vilma', 'status' => 'd' , 'created_time' => Mon May 25 16:42:30 +0200 2009, 'reply_number' => '447624800500', 'completed_time' => nil, 'credits_cost' => 0.5 } }
106
+ # api.message_status('141421', '173205')
107
+ # api.message_status(['141421', '173205'])
108
+ #
109
+ # Using custom readers:
110
+ #
111
+ # response = api.message_status('141421', '173205')
112
+ # response['141421'].text
113
+ # # => 'Hi Vilma'
114
+ # response['141421'].status
115
+ # # => 'd'
116
+ # response['141421'].created_time
117
+ # # => Fri May 22 10:10:18 +0200 2009
22
118
  def message_status(*ids)
23
- Executor.execute('message_status', @username, @password, :ids => ids.flatten.join(','))
119
+ ids.flatten!
120
+ raise TextMagic::API::Error.new(4, 'Insufficient parameters') if ids.empty?
121
+ response = Executor.execute('message_status', @username, @password, :ids => ids.join(','))
122
+ response.extend(TextMagic::API::Response::MessageStatus)
24
123
  end
25
124
 
26
- def receive
27
- Executor.execute('receive', @username, @password)
125
+ # Executes a receive command and returns a hash with unread messages
126
+ # if successful, otherwise it raises an Error.
127
+ # The returned hash will be extended with custom reader method defined
128
+ # in Response module.
129
+ #
130
+ # This method accepts an optional +last_retrieved_id+ value.
131
+ #
132
+ # Example usage:
133
+ #
134
+ # api.receive
135
+ # # => { 'messages' => [{ 'message_id' => '141421', 'from' => '999314159265', 'timestamp' => Fri May 22 12:12:55 +0200 2009, 'text' => 'Hi Fred!' }], 'unread' => 0 }
136
+ # api.receive '141421'
137
+ #
138
+ # Using custom readers:
139
+ #
140
+ # response = api.receive
141
+ # response.messages
142
+ # # => [{ 'timestamp' => Fri May 22 12:12:55 +0200 2009, 'from' => '999314159265', 'text' => 'Hi Fred', 'message_id' => '141421' }]
143
+ # response.unread
144
+ # # => 0
145
+ # response.messages[0].timestamp
146
+ # # => Fri May 22 12:12:55 +0200 2009
147
+ def receive(last_retrieved_id = nil)
148
+ response = Executor.execute('receive', @username, @password, :last_retrieved_id => last_retrieved_id)
149
+ response.extend(TextMagic::API::Response::Receive)
28
150
  end
29
151
 
152
+ # Executes a delete_reply command and returns a hash with a list of deleted
153
+ # message ids if successful, otherwise it raises an Error.
154
+ # The returned hash will be extended with custom reader method defined
155
+ # in Response module.
156
+ #
157
+ # This method accepts any positive number of ids specified as an array
158
+ # or as a list of arguments.
159
+ #
160
+ # Example usage:
161
+ #
162
+ # api.delete_reply('141421')
163
+ # # => { 'deleted' => ['141421'] }
164
+ # api.delete_reply('141421', '173205')
165
+ # api.delete_reply(['141421', '173205'])
166
+ #
167
+ # Using custom readers:
168
+ #
169
+ # response = api.delete_reply('141421', '173205')
170
+ # response.deleted
171
+ # # => ['141421', '173205']
30
172
  def delete_reply(*ids)
31
- Executor.execute('delete_reply', @username, @password, :ids => ids.flatten.join(','))
173
+ ids.flatten!
174
+ raise TextMagic::API::Error.new(4, 'Insufficient parameters') if ids.empty?
175
+ response = Executor.execute('delete_reply', @username, @password, :ids => ids.join(','))
176
+ response.extend(TextMagic::API::Response::DeleteReply)
32
177
  end
33
178
  end
34
179
  end
data/lib/charset.rb ADDED
@@ -0,0 +1,23 @@
1
+ module TextMagic
2
+
3
+ class API
4
+
5
+ module Charset
6
+
7
+ GSM_CHARSET = "@£$¥èéùìòÇ\nØø\rÅåΔ_ΦΓΛΩΠΨΣΘΞ\e\f^{}\\[~]|€ÆæßÉ !\"#¤%&'()*+,-./0123456789:;<=>?¡ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÑܧ¿abcdefghijklmnopqrstuvwxyzäöñüà".scan(/./u)
8
+
9
+ # Returns +true+ if the supplied text contains only characters from
10
+ # GSM 03.38 charset, otherwise it returns +false+.
11
+ def is_gsm(text)
12
+ text.scan(/./u).each { |c| return false unless GSM_CHARSET.include?(c) }
13
+ true
14
+ end
15
+
16
+ # Returns +true+ if the supplied text contains characters outside of
17
+ # GSM 03.38 charset, otherwise it returns +false+.
18
+ def is_unicode(text)
19
+ !is_gsm(text)
20
+ end
21
+ end
22
+ end
23
+ end
data/lib/error.rb CHANGED
@@ -6,8 +6,17 @@ module TextMagic
6
6
 
7
7
  attr_reader :code, :message
8
8
 
9
- def initialize(response)
10
- @code, @message = response[:error_code], response[:error_message]
9
+ # Creates an instance of TextMagic::API::Error. Error code and message
10
+ # can be supplied as arguments or as a response hash.
11
+ #
12
+ # TextMagic::API::Error.new(code, message)
13
+ # TextMagic::API::Error.new('error_code' => code, 'error_message' => message)
14
+ def initialize(*args)
15
+ if args.first.is_a?(Hash)
16
+ @code, @message = args.first['error_code'], args.first['error_message']
17
+ else
18
+ @code, @message = args
19
+ end
11
20
  end
12
21
 
13
22
  def to_s
data/lib/executor.rb CHANGED
@@ -5,12 +5,28 @@ module TextMagic
5
5
  class Executor
6
6
 
7
7
  include HTTParty
8
- base_uri "https://www.textmagic.com/app"
8
+ base_uri "http://www.textmagic.com/app"
9
9
 
10
+ # Executes a command by sending a request to the TextMagic's HTTP
11
+ # gateway. This is a low-level generic method used by methods in
12
+ # TextMagic::API class. You should never need to use this method
13
+ # directly.
14
+ #
15
+ # Parameters specified in the +options+ hash will be added to the
16
+ # HTTP request's URI.
17
+ #
18
+ # Returns a hash with values parsed from the server's response if
19
+ # the command was successfully executed. In case the server replies
20
+ # with error, this method raises a TextMagic::API::Error.
10
21
  def self.execute(command, username, password, options = {})
22
+ raise TextMagic::API::Error.new(3, 'Command is undefined') if command.nil? || command.blank?
23
+ if username.nil? || username.blank? || password.nil? || password.blank?
24
+ raise TextMagic::API::Error.new(5, 'Invalid username & password combination')
25
+ end
11
26
  options.merge!(:username => username, :password => password, :cmd => command)
27
+ options.delete_if { |key, value| key.nil? || key.to_s.blank? || value.nil? || value.to_s.blank? }
12
28
  response = self.get('/api', :query => options, :format => :json)
13
- raise Error.new(response) if response['error_code']
29
+ raise Error.new(response) if response && response['error_code']
14
30
  response
15
31
  end
16
32
  end
data/lib/response.rb ADDED
@@ -0,0 +1,141 @@
1
+ module TextMagic
2
+
3
+ class API
4
+
5
+ # Used to cleanup response hash and extend it with custom reader methods.
6
+ #
7
+ # === Account response hash
8
+ #
9
+ # When extended, it
10
+ # * converts the +balance+ value to +float+ and
11
+ # * adds a reader method +balance+.
12
+ #
13
+ # === Send response hash
14
+ #
15
+ # When extended, it
16
+ # * inverts the +message_id+ hash and puts it in +message_id_hash+,
17
+ # * adds an array of ids to +message_ids+,
18
+ # * adds reader methods +message_id_hash+, +message_ids+, +sent_text+ and
19
+ # +parts_count+ to the hash.
20
+ # * adds a reader method +message_id+, which returns a +message_id+ for
21
+ # a given phone number, or the first message_id if no phone number
22
+ # is specified.
23
+ #
24
+ # === Message status response hash
25
+ #
26
+ # When extended, it
27
+ # * converts the +credits_cost+ value to +float+,
28
+ # * converts the +created_time+ and +completed_time+ values to +Time+,
29
+ # * adds reader methods +text+, +status+, +reply_number+, +credits_cost+,
30
+ # +created_time+ and +completed_time+ to all values of the hash.
31
+ #
32
+ # === Receive status response hash
33
+ #
34
+ # When extended, it
35
+ # * converts the +timestamp+ value to +Time+,
36
+ # * adds reader methods +messages+ and +unread+ to the hash
37
+ # * adds reader methods +message_id+, +timestamp+, +text+ and +from+
38
+ # to all members of the +messages+ array.
39
+ #
40
+ # === Delete reply response hash
41
+ #
42
+ # When extended, it
43
+ # * adds a reader method +deleted+.
44
+ module Response
45
+
46
+ module Account #:nodoc: all
47
+
48
+ def self.extended(base)
49
+ return unless base.is_a?(Hash)
50
+ base['balance'] = base['balance'].to_f if base['balance']
51
+ end
52
+
53
+ def balance
54
+ self['balance']
55
+ end
56
+ end
57
+
58
+ module Send #:nodoc: all
59
+
60
+ def self.extended(base)
61
+ return unless base.is_a?(Hash)
62
+ base['message_id_hash'] = base.delete('message_id').invert if base['message_id']
63
+ base['message_ids'] = base['message_id_hash'].values.sort if base['message_id_hash']
64
+ end
65
+
66
+ %w(message_id_hash message_ids sent_text parts_count).each do |method|
67
+ module_eval <<-EOS
68
+ def #{method}
69
+ self['#{method}']
70
+ end
71
+ EOS
72
+ end
73
+
74
+ def message_id(phone = nil)
75
+ phone ? message_id_hash[phone] : message_ids.first
76
+ end
77
+ end
78
+
79
+ module MessageStatus #:nodoc: all
80
+
81
+ def self.extended(base)
82
+ return unless base.is_a?(Hash)
83
+ base.values.each do |status|
84
+ status['credits_cost'] = status['credits_cost'].to_f if status['credits_cost']
85
+ status['created_time'] = Time.at(status['created_time'].to_i) if status['created_time']
86
+ status['completed_time'] = Time.at(status['completed_time'].to_i) if status['completed_time']
87
+ status.extend Status
88
+ end
89
+ end
90
+
91
+ module Status
92
+
93
+ %w(text status reply_number credits_cost created_time completed_time).each do |method|
94
+ module_eval <<-EOS
95
+ def #{method}
96
+ self['#{method}']
97
+ end
98
+ EOS
99
+ end
100
+ end
101
+ end
102
+
103
+ module Receive #:nodoc: all
104
+
105
+ def self.extended(base)
106
+ return unless base.is_a?(Hash) && base['messages']
107
+ base['messages'].each do |message|
108
+ message['timestamp'] = Time.at(message['timestamp'].to_i) if message['timestamp']
109
+ message.extend Message
110
+ end
111
+ end
112
+
113
+ %w(messages unread).each do |method|
114
+ module_eval <<-EOS, __FILE__, __LINE__ + 1
115
+ def #{method}
116
+ self['#{method}']
117
+ end
118
+ EOS
119
+ end
120
+
121
+ module Message
122
+
123
+ %w(message_id timestamp text from).each do |method|
124
+ module_eval <<-EOS
125
+ def #{method}
126
+ self['#{method}']
127
+ end
128
+ EOS
129
+ end
130
+ end
131
+ end
132
+
133
+ module DeleteReply #:nodoc: all
134
+
135
+ def deleted
136
+ self['deleted']
137
+ end
138
+ end
139
+ end
140
+ end
141
+ end
data/lib/textmagic.rb CHANGED
@@ -1,9 +1,12 @@
1
1
  require 'rubygems'
2
2
  gem 'httparty'
3
3
  require 'httparty'
4
+ require 'charset'
5
+ require 'validation'
4
6
  require 'api'
7
+ require 'response'
5
8
  require 'executor'
6
9
  require 'error'
7
10
 
8
- module TextMagic
11
+ module TextMagic #:nodoc:
9
12
  end
data/lib/validation.rb ADDED
@@ -0,0 +1,34 @@
1
+ module TextMagic
2
+
3
+ class API
4
+
5
+ module Validation
6
+
7
+ MAX_LENGTH_GSM = [160, 306, 459]
8
+ MAX_LENGTH_UNICODE = [70, 134, 201]
9
+
10
+ # Validates message text length. Returns +true+ if the text length is
11
+ # within the limits for the unicode/parts combination, otherwise it
12
+ # returns +false+.
13
+ #
14
+ # Note: <em>Maximum lengths for 1, 2 and 3-part GSM 03.38 messages are
15
+ # 160, 306 and 459 respectively.
16
+ # Maximum lengths for 1, 2 and 3-part unicode messages are
17
+ # 70, 134 and 201 respectively.</em>
18
+ def validate_text_length(text, unicode, parts = 3)
19
+ max_text_length = (unicode ? MAX_LENGTH_UNICODE : MAX_LENGTH_GSM)[parts - 1]
20
+ text.size <= max_text_length
21
+ end
22
+
23
+ # Validates a list of phone numbers. Returns +true+ if the list is not empty
24
+ # and all phone numbers are digit-only strings of maximum length of 15,
25
+ # otherwise it returns +false+.
26
+ def validate_phones(*phones)
27
+ phones.flatten!
28
+ return false if phones.empty?
29
+ phones.each { |phone| return false unless phone =~ /^\d{1,15}$/ }
30
+ true
31
+ end
32
+ end
33
+ end
34
+ end
data/test/test_api.rb CHANGED
@@ -2,19 +2,10 @@ require 'test_helper'
2
2
 
3
3
  class APITest < Test::Unit::TestCase
4
4
 
5
- def prepare_api(command, raw_response, options = {})
6
- FakeWeb.allow_net_connect = false
7
-
8
- @username, @password = random_string, random_string
9
- uri = build_uri(command, @username, @password, options)
10
- FakeWeb.register_uri(:get, uri, :string => raw_response)
11
- TextMagic::API.new(@username, @password)
12
- end
13
-
14
5
  context 'Initialization' do
15
6
 
16
7
  should 'require username and password' do
17
- lambda { TextMagic::API.new }.should raise_error
8
+ lambda { TextMagic::API.new }.should raise_error(ArgumentError)
18
9
  TextMagic::API.new(random_string, random_string)
19
10
  end
20
11
  end
@@ -22,6 +13,7 @@ class APITest < Test::Unit::TestCase
22
13
  context 'Account command' do
23
14
 
24
15
  setup do
16
+ @balance = 0.01 * rand(1e4)
25
17
  @username, @password = random_string, random_string
26
18
  @api = TextMagic::API.new(@username, @password)
27
19
  end
@@ -31,11 +23,17 @@ class APITest < Test::Unit::TestCase
31
23
  @api.account
32
24
  end
33
25
 
34
- should 'return a hash with numeric balance value' do
35
- TextMagic::API::Executor.expects(:execute).returns({ 'balance' => '3.14' })
26
+ should 'return a hash extended with TextMagic::API::Response::Account' do
27
+ TextMagic::API::Executor.expects(:execute).returns({ 'balance' => @balance.to_s })
36
28
  response = @api.account
37
29
  response.class.should == Hash
38
- response['balance'].should == 3.14
30
+ response.is_a?(TextMagic::API::Response::Account).should == true
31
+ end
32
+
33
+ should 'return a hash with balance value' do
34
+ TextMagic::API::Executor.expects(:execute).returns({ 'balance' => @balance.to_s })
35
+ response = @api.account
36
+ response['balance'].should be_close(@balance, 1e-10)
39
37
  end
40
38
  end
41
39
 
@@ -45,31 +43,80 @@ class APITest < Test::Unit::TestCase
45
43
  @username, @password = random_string, random_string
46
44
  @text, @phone = random_string, random_phone
47
45
  @api = TextMagic::API.new(@username, @password)
46
+ TextMagic::API::Executor.stubs(:execute)
48
47
  end
49
48
 
50
49
  should 'call Executor execute with correct arguments' do
51
- TextMagic::API::Executor.expects(:execute).with('send', @username, @password, :text => @text, :phone => @phone)
50
+ TextMagic::API::Executor.expects(:execute).with('send', @username, @password, :text => @text, :phone => @phone, :unicode => 0)
52
51
  @api.send(@text, @phone)
53
52
  end
54
53
 
55
54
  should 'join multiple phone numbers supplied as an array' do
56
55
  phones = Array.new(3) { random_phone }
57
- TextMagic::API::Executor.expects(:execute).with('send', @username, @password, :text => @text, :phone => phones.join(','))
56
+ TextMagic::API::Executor.expects(:execute).with('send', @username, @password, :text => @text, :phone => phones.join(','), :unicode => 0)
58
57
  @api.send(@text, phones)
59
58
  end
60
59
 
61
60
  should 'join multiple phone numbers supplied as arguments' do
62
61
  phones = Array.new(3) { random_phone }
63
- TextMagic::API::Executor.expects(:execute).with('send', @username, @password, :text => @text, :phone => phones.join(','))
62
+ TextMagic::API::Executor.expects(:execute).with('send', @username, @password, :text => @text, :phone => phones.join(','), :unicode => 0)
64
63
  @api.send(@text, *phones)
65
64
  end
66
65
 
67
- should 'return a hash with message_id, sent_text and parts_count' do
66
+ should 'replace true with 1 for unicode' do
67
+ TextMagic::API::Executor.expects(:execute).with('send', @username, @password, :text => @text, :phone => @phone, :unicode => 1)
68
+ @api.send(@text, @phone, :unicode => true)
69
+ end
70
+
71
+ should 'set unicode value to 0 if it is not set to by user and text contains only characters from GSM 03.38 charset' do
72
+ TextMagic::API::Executor.expects(:execute).with('send', @username, @password, :text => @text, :phone => @phone, :unicode => 0).times(2)
73
+ @api.send(@text, @phone)
74
+ @api.send(@text, @phone, :unicode => false)
75
+ end
76
+
77
+ should 'raise an error if unicode is set to 0 and text contains characters outside of GSM 03.38 charset' do
78
+ text = 'Вильма Привет'
79
+ lambda { @api.send(text, @phone, :unicode => false) }.should raise_error(TextMagic::API::Error)
80
+ end
81
+
82
+ should 'raise an error if unicode value is not valid' do
83
+ lambda { @api.send(@text, @phone, :unicode => 2 + rand(10)) }.should raise_error(TextMagic::API::Error)
84
+ lambda { @api.send(@text, @phone, :unicode => random_string) }.should raise_error(TextMagic::API::Error)
85
+ end
86
+
87
+ should 'raise an error if no phone numbers are specified' do
88
+ lambda { @api.send(@text) }.should raise_error(TextMagic::API::Error)
89
+ lambda { @api.send(@text, []) }.should raise_error(TextMagic::API::Error)
90
+ end
91
+
92
+ should 'raise an error if format of any of the specified phone numbers is invalid' do
93
+ TextMagic::API.expects(:validate_phones).returns(false)
94
+ lambda { @api.send(@text, random_string) }.should raise_error(TextMagic::API::Error)
95
+ end
96
+
97
+ should 'raise an error if text is empty' do
98
+ lambda { @api.send('', @phone) }.should raise_error(TextMagic::API::Error)
99
+ end
100
+
101
+ should 'raise an error if text is too long' do
102
+ TextMagic::API.expects(:validate_text_length).returns(false)
103
+ lambda { @api.send(@text, @phone) }.should raise_error(TextMagic::API::Error)
104
+ end
105
+
106
+ should 'return a hash extended with TextMagic::API::Response::Send' do
68
107
  message_id = random_string
69
108
  TextMagic::API::Executor.expects(:execute).returns({ 'message_id' => { message_id => @phone }, 'sent_text' => @text, 'parts_count' => 1 })
70
109
  response = @api.send(@text, @phone)
71
- response['message_id'].should == { message_id => @phone }
72
- response['sent_text'].should == @text
110
+ response.class.should == Hash
111
+ response.is_a?(TextMagic::API::Response::Send).should == true
112
+ end
113
+
114
+ should 'return a hash with message_id_hash, message_ids, sent_text and parts_count values' do
115
+ message_id = random_string
116
+ TextMagic::API::Executor.expects(:execute).returns({ 'message_id' => { message_id => @phone }, 'sent_text' => @text, 'parts_count' => 1 })
117
+ response = @api.send(@text, @phone)
118
+ response['message_id_hash'].should == { @phone => message_id }
119
+ response['message_ids'].should == [message_id]
73
120
  response['parts_count'].should == 1
74
121
  end
75
122
  end
@@ -99,9 +146,21 @@ class APITest < Test::Unit::TestCase
99
146
  @api.message_status(*ids)
100
147
  end
101
148
 
149
+ should 'not call execute and should raise an exception if no ids are specified' do
150
+ TextMagic::API::Executor.expects(:execute).never
151
+ lambda { @api.message_status }.should raise_error(TextMagic::API::Error)
152
+ end
153
+
154
+ should 'return a hash extended with TextMagic::API::Response::MessageStatus' do
155
+ TextMagic::API::Executor.expects(:execute).returns({ '8659912' => {} })
156
+ response = @api.message_status(random_string)
157
+ response.class.should == Hash
158
+ response.is_a?(TextMagic::API::Response::MessageStatus).should == true
159
+ end
160
+
102
161
  should 'return a hash with message ids as keys' do
103
162
  TextMagic::API::Executor.expects(:execute).returns({ '8659912' => {} })
104
- response = @api.message_status
163
+ response = @api.message_status(random_string)
105
164
  response['8659912'].should == {}
106
165
  end
107
166
  end
@@ -114,11 +173,24 @@ class APITest < Test::Unit::TestCase
114
173
  end
115
174
 
116
175
  should 'call Executor execute with correct arguments' do
117
- TextMagic::API::Executor.expects(:execute).with('receive', @username, @password)
176
+ TextMagic::API::Executor.expects(:execute).with('receive', @username, @password, :last_retrieved_id => nil)
118
177
  @api.receive
119
178
  end
120
179
 
121
- should 'return a hash with messages and number of unread messages' do
180
+ should 'accept last_retrieved_id optional value' do
181
+ last_retrieved_id = rand(1e10)
182
+ TextMagic::API::Executor.expects(:execute).with('receive', @username, @password, :last_retrieved_id => last_retrieved_id)
183
+ @api.receive(last_retrieved_id)
184
+ end
185
+
186
+ should 'return a hash extended with TextMagic::API::Response::Receive' do
187
+ TextMagic::API::Executor.expects(:execute).returns({ 'messages' => [], 'unread' => 0 })
188
+ response = @api.receive
189
+ response.class.should == Hash
190
+ response.is_a?(TextMagic::API::Response::Receive).should == true
191
+ end
192
+
193
+ should 'return a hash with unread and messages values' do
122
194
  TextMagic::API::Executor.expects(:execute).returns({ 'messages' => [], 'unread' => 0 })
123
195
  response = @api.receive
124
196
  response['unread'].should == 0
@@ -151,42 +223,24 @@ class APITest < Test::Unit::TestCase
151
223
  @api.delete_reply(*ids)
152
224
  end
153
225
 
154
- should 'return a hash with deleted ids' do
226
+ should 'not call execute and should raise an exception if no ids are specified' do
227
+ TextMagic::API::Executor.expects(:execute).never
228
+ lambda { @api.delete_reply }.should raise_error(TextMagic::API::Error)
229
+ end
230
+
231
+ should 'return a hash extended with TextMagic::API::Response::DeleteReply' do
155
232
  ids = Array.new(3) { random_string }
156
233
  TextMagic::API::Executor.expects(:execute).returns({ 'deleted' => ids })
157
- response = @api.receive
158
- response['deleted'].should == ids
234
+ response = @api.delete_reply(ids)
235
+ response.class.should == Hash
236
+ response.is_a?(TextMagic::API::Response::DeleteReply).should == true
237
+ end
238
+
239
+ should 'return a hash with deleted value' do
240
+ ids = Array.new(3) { random_string }
241
+ TextMagic::API::Executor.expects(:execute).returns({ 'deleted' => ids })
242
+ response = @api.delete_reply(ids)
243
+ response.deleted.should == ids
159
244
  end
160
245
  end
161
246
  end
162
-
163
- __END__
164
-
165
- Example responses
166
-
167
- account:
168
- {"balance":"100"}
169
-
170
- send:
171
- {"message_id":{"1234567":"444444123456"},"sent_text":"test","parts_count":1}
172
-
173
- message_status:
174
- {"8659912":{"text":"test","status":"d","created_time":"1242979818","reply_number":"447624800500","completed_time":null,"credits_cost":"0.5"},"8659914":{"text":"test","status":"d","created_time":"1242979839","reply_number":"447624800500","completed_time":null,"credits_cost":"0.5"}}
175
-
176
- receive (empty):
177
- {"messages":[],"unread":0}
178
-
179
- empty message:
180
- {"error_code":1,"error_message":"Messages text is empty"}
181
-
182
- insufficient parameters:
183
- {"error_code":4,"error_message":"Insufficient parameters"}
184
-
185
- invalid credentials:
186
- {"error_code":5,"error_message":"Invalid username & password combination"}
187
-
188
- invalid phone number format:
189
- {"error_code":9,"error_message":"Wrong phone number format"}
190
-
191
- invalid message_id:
192
- {"error_code":14,"error_message":"Message with id 8659913 does not exist"}
@@ -0,0 +1,28 @@
1
+ require 'test_helper'
2
+ require 'json'
3
+
4
+ class CharsetTest < Test::Unit::TestCase
5
+
6
+ context 'is_gsm method' do
7
+
8
+ should 'return true if all characters are in GSM 03.38 charset' do
9
+ TextMagic::API.is_gsm(('a'..'z').to_a.join).should == true
10
+ TextMagic::API.is_gsm(('A'..'Z').to_a.join).should == true
11
+ TextMagic::API.is_gsm(('0'..'9').to_a.join).should == true
12
+ TextMagic::API.is_gsm("@£$¥€").should == true
13
+ TextMagic::API.is_gsm("\n\r\e\f\\\"").should == true
14
+ TextMagic::API.is_gsm("èéùìòÇØøÅåÉÆæß").should == true
15
+ TextMagic::API.is_gsm("ΔΦΓΛΩΠΨΣΘΞ").should == true
16
+ TextMagic::API.is_gsm("^{}[~]| !#¤%&'()").should == true
17
+ TextMagic::API.is_gsm("*+,-./_:;<=>?¡¿§").should == true
18
+ TextMagic::API.is_gsm("ÖÑÜöñüàäÄ").should == true
19
+ end
20
+
21
+ should 'return false if some characters are outside of GSM 03.38 charset' do
22
+ TextMagic::API.is_gsm('Arabic: مرحبا فيلما').should == false
23
+ TextMagic::API.is_gsm('Chinese: 您好').should == false
24
+ TextMagic::API.is_gsm('Cyrilic: Вильма Привет').should == false
25
+ TextMagic::API.is_gsm('Thai: สวัสดี').should == false
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,24 @@
1
+ require 'test_helper'
2
+
3
+ class ErrorTest < Test::Unit::TestCase
4
+
5
+ context 'Initialization' do
6
+
7
+ setup do
8
+ @code = rand(1e3)
9
+ @message = random_string
10
+ end
11
+
12
+ should 'accept a hash with error_code and error_message' do
13
+ e = TextMagic::API::Error.new('error_code' => @code, 'error_message' => @message)
14
+ e.code.should == @code
15
+ e.message.should == @message
16
+ end
17
+
18
+ should 'accept error_code and error_message' do
19
+ e = TextMagic::API::Error.new(@code, @message)
20
+ e.code.should == @code
21
+ e.message.should == @message
22
+ end
23
+ end
24
+ end
@@ -13,12 +13,45 @@ class ExecutorTest < Test::Unit::TestCase
13
13
  @uri = build_uri(@command, @username, @password, @options)
14
14
  end
15
15
 
16
+ should 'not send HTTP request without command' do
17
+ TextMagic::API::Executor.expects(:get).never
18
+ lambda {
19
+ TextMagic::API::Executor.execute(nil, @username, @password, @options)
20
+ }.should raise_error(TextMagic::API::Error)
21
+ end
22
+
23
+ should 'not send HTTP request without username' do
24
+ TextMagic::API::Executor.expects(:get).never
25
+ lambda {
26
+ TextMagic::API::Executor.execute(@command, nil, @password, @options)
27
+ }.should raise_error(TextMagic::API::Error)
28
+ end
29
+
30
+ should 'not send HTTP request without password' do
31
+ TextMagic::API::Executor.expects(:get).never
32
+ lambda {
33
+ TextMagic::API::Executor.execute(@command, @username, nil, @options)
34
+ }.should raise_error(TextMagic::API::Error)
35
+ end
36
+
16
37
  should 'send a GET request to proper uri' do
17
38
  response = random_string
18
39
  FakeWeb.register_uri(:get, @uri, :string => response)
19
40
  TextMagic::API::Executor.execute(@command, @username, @password, @options)
20
41
  end
21
42
 
43
+ should 'not send parameters with empty keys' do
44
+ options_with_empty_values = @options.merge(nil => random_string, '' => random_string)
45
+ TextMagic::API::Executor.expects(:get).with('/api', :query => @options, :format => :json)
46
+ TextMagic::API::Executor.execute(@command, @username, @password, options_with_empty_values)
47
+ end
48
+
49
+ should 'not send parameters with empty values' do
50
+ options_with_empty_values = @options.merge(random_string => nil, random_string => '')
51
+ TextMagic::API::Executor.expects(:get).with('/api', :query => @options, :format => :json)
52
+ TextMagic::API::Executor.execute(@command, @username, @password, options_with_empty_values)
53
+ end
54
+
22
55
  should 'raise an error if the response contains error_code' do
23
56
  response = "{error_code:#{1 + rand(10)}}"
24
57
  FakeWeb.register_uri(:get, @uri, :string => response)
@@ -27,7 +60,7 @@ class ExecutorTest < Test::Unit::TestCase
27
60
  }.should raise_error(TextMagic::API::Error)
28
61
  end
29
62
 
30
- should 'return a hash with values in the response' do
63
+ should 'return a hash with values from the response' do
31
64
  hash = random_hash
32
65
  FakeWeb.register_uri(:get, @uri, :string => hash.to_json)
33
66
  response = TextMagic::API::Executor.execute(@command, @username, @password, @options)
data/test/test_helper.rb CHANGED
@@ -14,7 +14,7 @@ class Test::Unit::TestCase
14
14
  end
15
15
 
16
16
  def random_string(legth = 5)
17
- rand(36 ** legth).to_s(36)
17
+ Array.new(legth) { rand(36).to_s(36) }.join
18
18
  end
19
19
 
20
20
  def random_phone
@@ -29,7 +29,7 @@ end
29
29
 
30
30
  def build_uri(command, username, password, options = {})
31
31
  options.merge!(:cmd => command, :username => username, :password => password)
32
- uri = "https://www.textmagic.com:443/app/api?"
32
+ uri = "http://www.textmagic.com/app/api?"
33
33
  uri << options.collect { |key, value| "#{key}=#{value}"}.join('&')
34
34
  end
35
35
 
@@ -0,0 +1,176 @@
1
+ require 'test_helper'
2
+
3
+ class ResponseTest < Test::Unit::TestCase
4
+
5
+ context 'Account response' do
6
+
7
+ setup do
8
+ @balance = 0.1 * rand(1e4)
9
+ @response = { 'balance' => @balance.to_s }
10
+ @response.extend TextMagic::API::Response::Account
11
+ end
12
+
13
+ should 'allow access to balance' do
14
+ @response.balance.should be_close(@balance, 1e-10)
15
+ end
16
+ end
17
+
18
+ context 'Send response' do
19
+
20
+ setup do
21
+ @message_id = {
22
+ '141421' => '999314159265',
23
+ '173205' => '999271828182'
24
+ }
25
+ @text = random_string
26
+ @parts_count = rand(10)
27
+ @response = {
28
+ 'message_id' => @message_id,
29
+ 'sent_text' => @text,
30
+ 'parts_count' => @parts_count
31
+ }
32
+ @response.extend TextMagic::API::Response::Send
33
+ end
34
+
35
+ should 'allow access to inverted message_id hash' do
36
+ @response.message_id_hash.should == @message_id.invert
37
+ end
38
+
39
+ should 'allow access to message_ids array' do
40
+ @response.message_ids.should == ['141421', '173205']
41
+ end
42
+
43
+ should 'allow access to message_id for a given phone number' do
44
+ @response.message_id('999314159265').should == '141421'
45
+ @response.message_id('999271828182').should == '173205'
46
+ end
47
+
48
+ should 'allow access to sent_text' do
49
+ @response.sent_text.should == @text
50
+ end
51
+
52
+ should 'allow access to parts_count' do
53
+ @response.parts_count.should == @parts_count
54
+ end
55
+ end
56
+
57
+ context 'MessageStatus response' do
58
+
59
+ setup do
60
+ @text = random_string
61
+ @reply_number = random_phone
62
+ @created_time = (Time.now - 30).to_i
63
+ @completed_time = (Time.now - 20).to_i
64
+ @credits_cost = 0.01 * rand(300)
65
+ @response = {
66
+ '141421' => {
67
+ 'text' => @text,
68
+ 'status' => 'd',
69
+ 'created_time' => @created_time,
70
+ 'reply_number' => @reply_number,
71
+ 'completed_time' => @completed_time,
72
+ 'credits_cost' => @credits_cost
73
+ },
74
+ '173205' => {
75
+ 'text' => 'test',
76
+ 'status' => 'r',
77
+ 'created_time' => '1242979839',
78
+ 'reply_number' => '447624800500',
79
+ 'completed_time' => nil,
80
+ 'credits_cost' => 0.5
81
+ }
82
+ }
83
+ @response.extend TextMagic::API::Response::MessageStatus
84
+ end
85
+
86
+ should 'allow access to text for all statuses' do
87
+ @response['141421'].text.should == @text
88
+ @response['173205'].text.should == 'test'
89
+ end
90
+
91
+ should 'allow access to status for a given message_id' do
92
+ @response['141421'].status.should == 'd'
93
+ @response['173205'].status.should == 'r'
94
+ end
95
+
96
+ should 'allow access to reply_number for a given message_id' do
97
+ @response['141421'].reply_number.should == @reply_number
98
+ @response['173205'].reply_number.should == '447624800500'
99
+ end
100
+
101
+ should 'allow access to created_time for a given message_id' do
102
+ @response['141421'].created_time.should == Time.at(@created_time)
103
+ @response['173205'].created_time.should == Time.at(1242979839)
104
+ end
105
+
106
+ should 'allow access to completed_time for a given message_id' do
107
+ @response['141421'].completed_time.should == Time.at(@completed_time)
108
+ @response['173205'].completed_time.should == nil
109
+ end
110
+
111
+ should 'allow access to credits_cost for a given message_id' do
112
+ @response['141421'].credits_cost.should be_close(@credits_cost, 1e-10)
113
+ @response['173205'].credits_cost.should be_close(0.5, 1e-10)
114
+ end
115
+ end
116
+
117
+ context 'Receive response' do
118
+
119
+ setup do
120
+ @timestamp = (Time.now - 30).to_i
121
+ @message1 = {
122
+ 'timestamp' => @timestamp,
123
+ 'from' => '999314159265',
124
+ 'text' => 'Hi Fred',
125
+ 'message_id' => '141421'
126
+ }
127
+ @message2 = {
128
+ 'timestamp' => 1243244148,
129
+ 'from' => '999271828182',
130
+ 'text' => 'Hello buddy',
131
+ 'message_id' => '173205'
132
+ }
133
+ @messages = [@message1, @message2]
134
+ @unread = rand(1e4)
135
+ @response = { 'unread' => @unread, 'messages' => @messages }
136
+ @response.extend TextMagic::API::Response::Receive
137
+ end
138
+
139
+ should 'allow access to unread' do
140
+ @response.unread.should == @unread
141
+ end
142
+
143
+ should 'allow access to messages array' do
144
+ @response.messages.should == @messages
145
+ end
146
+
147
+ should 'allow access to message_id for all messages' do
148
+ @response.messages.first.message_id.should == '141421'
149
+ end
150
+
151
+ should 'allow access to timestamp for all messages' do
152
+ @response.messages.first.timestamp.should == Time.at(@timestamp)
153
+ end
154
+
155
+ should 'allow access to from for all messages' do
156
+ @response.messages.first.from.should == '999314159265'
157
+ end
158
+
159
+ should 'allow access to text for all messages' do
160
+ @response.messages.first.text.should == 'Hi Fred'
161
+ end
162
+ end
163
+
164
+ context 'DeleteReply response' do
165
+
166
+ setup do
167
+ @ids = ['141421', '1780826']
168
+ @response = { 'deleted' => @ids }
169
+ @response.extend TextMagic::API::Response::DeleteReply
170
+ end
171
+
172
+ should 'allow access to deleted' do
173
+ @response.deleted.should == @ids
174
+ end
175
+ end
176
+ end
@@ -0,0 +1,99 @@
1
+ require 'test_helper'
2
+ require 'json'
3
+
4
+ class ValidationTest < Test::Unit::TestCase
5
+
6
+ context 'validate_text_length method for non-unicode texts' do
7
+
8
+ should 'return true if parts limit is set to 1 and text length is less than or equal to 160' do
9
+ TextMagic::API.validate_text_length(random_string(160), false, 1).should == true
10
+ end
11
+
12
+ should 'return false if parts limit is set to 1 and text length is greater than 160' do
13
+ TextMagic::API.validate_text_length(random_string(161), false, 1).should == false
14
+ end
15
+
16
+ should 'return true if parts limit is set to 2 and text length is less than or equal to 306' do
17
+ TextMagic::API.validate_text_length(random_string(306), false, 2).should == true
18
+ end
19
+
20
+ should 'return false if parts limit is set to 2 and text length is greater than 306' do
21
+ TextMagic::API.validate_text_length(random_string(307), false, 2).should == false
22
+ end
23
+
24
+ should 'return true if parts limit is set to 3 or is not specified and text length is less than or equal to 459' do
25
+ TextMagic::API.validate_text_length(random_string(459), false).should == true
26
+ TextMagic::API.validate_text_length(random_string(459), false, 3).should == true
27
+ end
28
+
29
+ should 'return false if parts limit is set to 3 or is not specified and text length is greater than 459' do
30
+ TextMagic::API.validate_text_length(random_string(460), false).should == false
31
+ TextMagic::API.validate_text_length(random_string(460), false, 3).should == false
32
+ end
33
+ end
34
+
35
+ context 'validate_text_length method for unicode texts' do
36
+
37
+ should 'return true if parts limit is set to 1 and text length is less than or equal to 70' do
38
+ TextMagic::API.validate_text_length(random_string(70), true, 1).should == true
39
+ end
40
+
41
+ should 'return false if parts limit is set to 1 and text length is greater than 70' do
42
+ TextMagic::API.validate_text_length(random_string(71), true, 1).should == false
43
+ end
44
+
45
+ should 'return true if parts limit is set to 2 and text length is less than or equal to 134' do
46
+ TextMagic::API.validate_text_length(random_string(134), true, 2).should == true
47
+ end
48
+
49
+ should 'return false if parts limit is set to 2 and text length is greater than 134' do
50
+ TextMagic::API.validate_text_length(random_string(135), true, 2).should == false
51
+ end
52
+
53
+ should 'return true if parts limit is set to 3 or is not specified and text length is less than or equal to 201' do
54
+ TextMagic::API.validate_text_length(random_string(201), true).should == true
55
+ TextMagic::API.validate_text_length(random_string(201), true, 3).should == true
56
+ end
57
+
58
+ should 'return false if parts limit is set to 3 or is not specified and text length is greater than 201' do
59
+ TextMagic::API.validate_text_length(random_string(202), true).should == false
60
+ TextMagic::API.validate_text_length(random_string(202), true, 3).should == false
61
+ end
62
+ end
63
+
64
+ context 'validate_phones method' do
65
+
66
+ should 'return true if phone number consists of up to 15 digits' do
67
+ TextMagic::API.validate_phones(rand(10 ** 15).to_s).should == true
68
+ end
69
+
70
+ should 'return false if phone number is longer than 15 digits' do
71
+ TextMagic::API.validate_phones((10 ** 16 + rand(10 ** 15)).to_s).should == false
72
+ end
73
+
74
+ should 'return false if phone number contains non-digits' do
75
+ TextMagic::API.validate_phones(random_string).should == false
76
+ end
77
+
78
+ should 'return false if phone number is empty' do
79
+ TextMagic::API.validate_phones('').should == false
80
+ end
81
+
82
+ should 'return true if all phone numbers in a list are valid' do
83
+ phone1, phone2 = rand(10 ** 15).to_s, rand(10 ** 15).to_s
84
+ TextMagic::API.validate_phones(phone1, phone2).should == true
85
+ TextMagic::API.validate_phones([phone1, phone2]).should == true
86
+ end
87
+
88
+ should 'return false if phone numbers list is empty' do
89
+ TextMagic::API.validate_phones().should == false
90
+ end
91
+
92
+ should 'return false if format of any of phone numbers in a list is invalid' do
93
+ phone1 = rand(10 ** 15).to_s, rand(10 ** 15).to_s
94
+ phone2 = random_string
95
+ TextMagic::API.validate_phones(phone1, phone2).should == false
96
+ TextMagic::API.validate_phones([phone1, phone2]).should == false
97
+ end
98
+ end
99
+ end
data/textmagic.gemspec CHANGED
@@ -2,11 +2,11 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = %q{textmagic}
5
- s.version = "0.1.0"
5
+ s.version = "0.2.0"
6
6
 
7
7
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
8
8
  s.authors = ["Vladimir Bobes Tuzinsky"]
9
- s.date = %q{2009-05-22}
9
+ s.date = %q{2009-05-25}
10
10
  s.email = %q{vladimir.tuzinsky@gmail.com}
11
11
  s.extra_rdoc_files = [
12
12
  "LICENSE",
@@ -20,13 +20,19 @@ Gem::Specification.new do |s|
20
20
  "Rakefile",
21
21
  "VERSION.yml",
22
22
  "lib/api.rb",
23
+ "lib/charset.rb",
23
24
  "lib/error.rb",
24
25
  "lib/executor.rb",
26
+ "lib/response.rb",
25
27
  "lib/textmagic.rb",
28
+ "lib/validation.rb",
26
29
  "test/test_api.rb",
30
+ "test/test_charset.rb",
31
+ "test/test_error.rb",
27
32
  "test/test_executor.rb",
28
33
  "test/test_helper.rb",
29
- "test/test_textmagic.rb",
34
+ "test/test_response.rb",
35
+ "test/test_validation.rb",
30
36
  "textmagic.gemspec"
31
37
  ]
32
38
  s.has_rdoc = true
@@ -38,9 +44,12 @@ Gem::Specification.new do |s|
38
44
  s.summary = %q{Ruby interface to the TextMagic's SMS gateway}
39
45
  s.test_files = [
40
46
  "test/test_api.rb",
47
+ "test/test_charset.rb",
48
+ "test/test_error.rb",
41
49
  "test/test_executor.rb",
42
50
  "test/test_helper.rb",
43
- "test/test_textmagic.rb"
51
+ "test/test_response.rb",
52
+ "test/test_validation.rb"
44
53
  ]
45
54
 
46
55
  if s.respond_to? :specification_version then
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bobes-textmagic
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Vladimir Bobes Tuzinsky
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-05-22 00:00:00 -07:00
12
+ date: 2009-05-25 00:00:00 -07:00
13
13
  default_executable:
14
14
  dependencies: []
15
15
 
@@ -30,13 +30,19 @@ files:
30
30
  - Rakefile
31
31
  - VERSION.yml
32
32
  - lib/api.rb
33
+ - lib/charset.rb
33
34
  - lib/error.rb
34
35
  - lib/executor.rb
36
+ - lib/response.rb
35
37
  - lib/textmagic.rb
38
+ - lib/validation.rb
36
39
  - test/test_api.rb
40
+ - test/test_charset.rb
41
+ - test/test_error.rb
37
42
  - test/test_executor.rb
38
43
  - test/test_helper.rb
39
- - test/test_textmagic.rb
44
+ - test/test_response.rb
45
+ - test/test_validation.rb
40
46
  - textmagic.gemspec
41
47
  has_rdoc: true
42
48
  homepage: http://github.com/bobes/textmagic
@@ -66,6 +72,9 @@ specification_version: 2
66
72
  summary: Ruby interface to the TextMagic's SMS gateway
67
73
  test_files:
68
74
  - test/test_api.rb
75
+ - test/test_charset.rb
76
+ - test/test_error.rb
69
77
  - test/test_executor.rb
70
78
  - test/test_helper.rb
71
- - test/test_textmagic.rb
79
+ - test/test_response.rb
80
+ - test/test_validation.rb
@@ -1,4 +0,0 @@
1
- require 'test_helper'
2
-
3
- # class TextmagicTest < Test::Unit::TestCase
4
- # end