tapi 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/.document +5 -0
- data/Gemfile +13 -0
- data/Gemfile.lock +34 -0
- data/LICENSE.txt +20 -0
- data/README.rdoc +152 -0
- data/Rakefile +50 -0
- data/VERSION +1 -0
- data/lib/tapi.rb +9 -0
- data/lib/tapi/v3/client.rb +261 -0
- data/lib/tapi/v3/configurable.rb +27 -0
- data/lib/tapi/v3/errors.rb +26 -0
- data/lib/tapi/v3/flights/search.rb +124 -0
- data/lib/tapi/v3/generic_search.rb +97 -0
- data/lib/tapi/v3/hotels/search.rb +213 -0
- data/lib/tapi/v3/utils.rb +64 -0
- data/lib/tapi/v3/validations.rb +58 -0
- data/spec/client_spec.rb +320 -0
- data/spec/configurable_spec.rb +27 -0
- data/spec/flights/search_spec.rb +102 -0
- data/spec/hotels/search_spec.rb +143 -0
- data/spec/spec_helper.rb +12 -0
- metadata +201 -0
@@ -0,0 +1,64 @@
|
|
1
|
+
module TAPI
|
2
|
+
|
3
|
+
module Utils
|
4
|
+
|
5
|
+
module_function
|
6
|
+
|
7
|
+
def coerce_date(date)
|
8
|
+
case date
|
9
|
+
when Date then date
|
10
|
+
when String then parse_date(date)
|
11
|
+
when NilClass then nil
|
12
|
+
else
|
13
|
+
raise TypeError, "cannot coerce #{date.inspect}", caller
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def parse_date(date)
|
18
|
+
Date.strptime(date, '%d.%m.%Y')
|
19
|
+
rescue ArgumentError
|
20
|
+
begin
|
21
|
+
Date.strptime(date, '%Y-%m-%d')
|
22
|
+
rescue ArgumentError
|
23
|
+
raise TypeError, "cannot parse #{date.inspect}", caller
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def append_query(url, hash)
|
28
|
+
pairs = hash.to_a.sort {|a, b| a.first.to_s <=> b.first.to_s}
|
29
|
+
query_elements =
|
30
|
+
pairs.inject([]) do |accumulator, key_value|
|
31
|
+
key, value = key_value
|
32
|
+
case value
|
33
|
+
when Array
|
34
|
+
value.each do |v|
|
35
|
+
accumulator << "#{key}[]=#{v}"
|
36
|
+
end
|
37
|
+
else
|
38
|
+
accumulator << "#{key}=#{value}"
|
39
|
+
end
|
40
|
+
accumulator
|
41
|
+
end
|
42
|
+
if query_elements.any?
|
43
|
+
attributes = URI.escape(query_elements.join('&'))
|
44
|
+
join_char = url.include?('?') ? '&' : '?'
|
45
|
+
url + join_char + attributes
|
46
|
+
else
|
47
|
+
url
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def symbolize_keys(data)
|
52
|
+
case data
|
53
|
+
when Hash
|
54
|
+
data.inject({}){|acc, pair| acc[pair.first.to_sym] = symbolize_keys(pair.last); acc}
|
55
|
+
when Array
|
56
|
+
data.map {|e| symbolize_keys(e)}
|
57
|
+
else
|
58
|
+
data
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
module TAPI
|
2
|
+
|
3
|
+
module Validations
|
4
|
+
|
5
|
+
def has_errors?
|
6
|
+
errors.any?
|
7
|
+
end
|
8
|
+
|
9
|
+
def add_error(name, message)
|
10
|
+
(errors[name] ||= []) << message
|
11
|
+
end
|
12
|
+
|
13
|
+
def validations
|
14
|
+
@validations ||= []
|
15
|
+
end
|
16
|
+
|
17
|
+
def inherited_validations
|
18
|
+
if superclass.respond_to?(:validations)
|
19
|
+
superclass.validations + validations
|
20
|
+
else
|
21
|
+
validations
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def validate(&block)
|
26
|
+
validations << block
|
27
|
+
end
|
28
|
+
|
29
|
+
def validates_presence_of(name, message)
|
30
|
+
validate do
|
31
|
+
if send(name).blank?
|
32
|
+
add_error(name, message)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def validates_date_format_of(name, message)
|
38
|
+
validate do
|
39
|
+
begin
|
40
|
+
Utils.coerce_date(send(name))
|
41
|
+
rescue TypeError
|
42
|
+
add_error name, message
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def validates_numericality_of(name, message)
|
48
|
+
validate do
|
49
|
+
number = send(name)
|
50
|
+
unless number.is_a?(Fixnum) || /^[0-9]+$/ =~ number
|
51
|
+
add_error name, message
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
data/spec/client_spec.rb
ADDED
@@ -0,0 +1,320 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
3
|
+
|
4
|
+
describe TAPI::V3::Client, " utility methods" do
|
5
|
+
|
6
|
+
it 'should build a query string' do
|
7
|
+
TAPI::Utils.append_query('url', {}).should == 'url'
|
8
|
+
TAPI::Utils.append_query('url', {:param1 => 1, :param2 => 'zwo'}).should == 'url?param1=1¶m2=zwo'
|
9
|
+
TAPI::Utils.append_query('url?already=here', {:param1 => 1, :param2 => 'zwo'}).should == 'url?already=here¶m1=1¶m2=zwo'
|
10
|
+
TAPI::Utils.append_query('url', {:array => [1,2]}).should == 'url?array[]=1&array[]=2'
|
11
|
+
TAPI::Utils.append_query('url', {:umlaut => 'ü'}).should == 'url?umlaut=%C3%BC'
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'should symbolize keys in a hash' do
|
15
|
+
data_in = {'i_am' => {'a_nested' => 'hash'}, 'with' => {'an_array' => [2, 3, 4]}}
|
16
|
+
data_out = {:i_am => {:a_nested => 'hash'}, :with => {:an_array => [2, 3, 4]}}
|
17
|
+
TAPI::Utils.symbolize_keys(data_in).should == data_out
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'should have a default logger' do
|
21
|
+
TAPI::V3::Client.logger.class.should == Logger
|
22
|
+
TAPI::V3::Client.new({}).logger.class.should == Logger
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'should have a configurable logger' do
|
26
|
+
logger = mock('Logger').as_null_object
|
27
|
+
TAPI::V3::Client.logger = logger
|
28
|
+
TAPI::V3::Client.logger.should == logger
|
29
|
+
TAPI::V3::Client.new({}).logger.should == logger
|
30
|
+
end
|
31
|
+
|
32
|
+
it "should translate HTTP errors" do
|
33
|
+
curl = mock('Curl', :response_code => 404)
|
34
|
+
curl.stub!(:url, nil)
|
35
|
+
curl.stub!(:body_str, nil)
|
36
|
+
lambda {TAPI::V3::Client.check_for_errors(curl)}.should raise_error TAPI::NotFoundError
|
37
|
+
end
|
38
|
+
|
39
|
+
it "should raise an error for an unknown HTTP errors" do
|
40
|
+
curl = mock('Curl', :response_code => 517)
|
41
|
+
lambda {TAPI::V3::Client.check_for_errors(curl)}.should raise_error
|
42
|
+
end
|
43
|
+
|
44
|
+
it "should provide context for HTTP errors" do
|
45
|
+
curl = mock('Curl',
|
46
|
+
:response_code => 412,
|
47
|
+
:url => 'superdope.curl',
|
48
|
+
:body_str => 'dead-bodies')
|
49
|
+
|
50
|
+
error = nil
|
51
|
+
|
52
|
+
begin
|
53
|
+
TAPI::V3::Client.check_for_errors(curl)
|
54
|
+
rescue TAPI::Error => e
|
55
|
+
error = e
|
56
|
+
end
|
57
|
+
|
58
|
+
error.should_not be_nil
|
59
|
+
error.response_code.should == 412
|
60
|
+
error.response_body.should == 'dead-bodies'
|
61
|
+
error.request_url.should == 'superdope.curl'
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
|
66
|
+
describe TAPI::V3::Client, " retrieving remote data" do
|
67
|
+
|
68
|
+
it 'should have configurable authentication' do
|
69
|
+
TAPI::V3::Client.http_authentication.should == nil
|
70
|
+
TAPI::V3::Client.config = {:http_user_name => 'username', :http_password => 'password'}
|
71
|
+
TAPI::V3::Client.http_authentication.should == 'username:password'
|
72
|
+
TAPI::V3::Client.config = nil
|
73
|
+
end
|
74
|
+
|
75
|
+
it 'should retrieve data via post' do
|
76
|
+
curl = mock('Curl')
|
77
|
+
curl.should_receive(:http_post)
|
78
|
+
curl.should_receive(:body_str).and_return('the_body')
|
79
|
+
JSON.should_receive(:parse).with('the_body').and_return('the_data')
|
80
|
+
Curl::Easy.should_receive(:new).and_return(curl)
|
81
|
+
TAPI::V3::Client.should_receive(:check_for_errors).with(curl)
|
82
|
+
TAPI::V3::Client.should_receive(:new).with('the_data', nil, true)
|
83
|
+
TAPI::V3::Client.new_from_post('the_url', {:a_param => :yeah})
|
84
|
+
end
|
85
|
+
|
86
|
+
it 'should use authentication options when posting' do
|
87
|
+
curl = mock('Curl')
|
88
|
+
curl.should_receive(:http_post)
|
89
|
+
curl.should_receive(:userpwd=).with('the_authentication')
|
90
|
+
curl.should_receive(:body_str).and_return('the_body')
|
91
|
+
JSON.should_receive(:parse).with('the_body').and_return('the_data')
|
92
|
+
Curl::Easy.should_receive(:new).and_return(curl)
|
93
|
+
TAPI::V3::Client.should_receive(:http_authentication).and_return('the_authentication')
|
94
|
+
TAPI::V3::Client.should_receive(:check_for_errors).with(curl)
|
95
|
+
TAPI::V3::Client.should_receive(:new).with('the_data', nil, true)
|
96
|
+
TAPI::V3::Client.new_from_post('the_url', {:a_param => :yeah})
|
97
|
+
end
|
98
|
+
|
99
|
+
it 'should use authentication options when getting' do
|
100
|
+
curl = mock('Curl', :header_str => 'ETag the_etag')
|
101
|
+
curl.should_receive(:http_get)
|
102
|
+
curl.should_receive(:userpwd=).with('the_authentication')
|
103
|
+
curl.should_receive(:body_str).and_return('the_body')
|
104
|
+
JSON.should_receive(:parse).with('the_body').and_return('the_data')
|
105
|
+
Curl::Easy.should_receive(:new).and_return(curl)
|
106
|
+
TAPI::V3::Client.should_receive(:http_authentication).and_return('the_authentication')
|
107
|
+
TAPI::V3::Client.should_receive(:check_for_errors).with(curl)
|
108
|
+
TAPI::V3::Client.should_receive(:new).with('the_data', 'the_etag', true)
|
109
|
+
TAPI::V3::Client.new_from_get('the_url', {:a_param => :yeah})
|
110
|
+
end
|
111
|
+
|
112
|
+
it 'should retrieve data via get without an etag given' do
|
113
|
+
curl = mock('Curl', :header_str => 'ETag the_etag')
|
114
|
+
curl.should_receive(:http_get)
|
115
|
+
curl.should_receive(:body_str).and_return('the_body')
|
116
|
+
JSON.should_receive(:parse).with('the_body').and_return('the_data')
|
117
|
+
TAPI::Utils.should_receive(:append_query).with('the_url', {:a_param => :yeah}).and_return('the_url?a_param=yeah')
|
118
|
+
Curl::Easy.should_receive(:new).with('the_url?a_param=yeah').and_return(curl)
|
119
|
+
TAPI::V3::Client.should_receive(:check_for_errors).with(curl)
|
120
|
+
TAPI::V3::Client.should_receive(:new).with('the_data', 'the_etag', true).and_return('the_client')
|
121
|
+
TAPI::V3::Client.new_from_get('the_url', {:a_param => :yeah}).should == ['the_client', 'the_etag']
|
122
|
+
end
|
123
|
+
|
124
|
+
it 'should retrieve data via get with an non-matching etag given' do
|
125
|
+
curl = mock('Curl', :header_str => 'ETag remote_etag')
|
126
|
+
curl.should_receive(:http_get)
|
127
|
+
curl.should_receive(:body_str).and_return('the_body')
|
128
|
+
curl.should_receive(:headers).and_return({})
|
129
|
+
JSON.should_receive(:parse).with('the_body').and_return('the_data')
|
130
|
+
TAPI::Utils.should_receive(:append_query).with('the_url', {:a_param => :yeah}).and_return('the_url?a_param=yeah')
|
131
|
+
Curl::Easy.should_receive(:new).with('the_url?a_param=yeah').and_return(curl)
|
132
|
+
TAPI::V3::Client.should_receive(:check_for_errors).with(curl)
|
133
|
+
TAPI::V3::Client.should_receive(:new).with('the_data', 'remote_etag', true).and_return('the_client')
|
134
|
+
TAPI::V3::Client.new_from_get('the_url', {:a_param => :yeah}, 'etag').should == ['the_client', 'remote_etag']
|
135
|
+
end
|
136
|
+
|
137
|
+
it 'should retrieve data via get with no etag given' do
|
138
|
+
curl = mock('Curl', :header_str => 'nothing in here')
|
139
|
+
curl.should_receive(:http_get)
|
140
|
+
curl.should_receive(:body_str).and_return('the_body')
|
141
|
+
curl.should_receive(:headers).and_return({})
|
142
|
+
JSON.should_receive(:parse).with('the_body').and_return('the_data')
|
143
|
+
TAPI::Utils.should_receive(:append_query).with('the_url', {:a_param => :yeah}).and_return('the_url?a_param=yeah')
|
144
|
+
Curl::Easy.should_receive(:new).with('the_url?a_param=yeah').and_return(curl)
|
145
|
+
TAPI::V3::Client.should_receive(:check_for_errors).with(curl)
|
146
|
+
TAPI::V3::Client.should_receive(:new).with('the_data', nil, true).and_return('the_client')
|
147
|
+
TAPI::V3::Client.new_from_get('the_url', {:a_param => :yeah}, 'etag').should == ['the_client', nil]
|
148
|
+
end
|
149
|
+
|
150
|
+
it 'should retrieve data via get with an matching etag given' do
|
151
|
+
curl = mock('Curl', :header_str => 'ETag the_etag')
|
152
|
+
curl.should_receive(:http_get)
|
153
|
+
curl.should_not_receive(:body_str)
|
154
|
+
curl.should_receive(:headers).and_return({})
|
155
|
+
JSON.should_not_receive(:parse)
|
156
|
+
TAPI::Utils.should_receive(:append_query).with('the_url', {:a_param => :yeah}).and_return('the_url?a_param=yeah')
|
157
|
+
Curl::Easy.should_receive(:new).with('the_url?a_param=yeah').and_return(curl)
|
158
|
+
TAPI::V3::Client.should_receive(:check_for_errors).with(curl)
|
159
|
+
TAPI::V3::Client.should_not_receive(:new)
|
160
|
+
TAPI::V3::Client.new_from_get('the_url', {:a_param => :yeah}, 'the_etag').should == [nil, 'the_etag']
|
161
|
+
end
|
162
|
+
|
163
|
+
end
|
164
|
+
|
165
|
+
TAPI::V3::Data = Class.new(TAPI::V3::Client)
|
166
|
+
TAPI::V3::NewClient = Class.new
|
167
|
+
TAPI::V3::ArrayHashElement = Class.new(TAPI::V3::Client)
|
168
|
+
|
169
|
+
describe TAPI::V3::Client, " dynamic methods" do
|
170
|
+
|
171
|
+
before(:each) do
|
172
|
+
@data_hash = {
|
173
|
+
:search =>
|
174
|
+
{
|
175
|
+
:resources =>
|
176
|
+
{
|
177
|
+
:remote1_url => 'remote1_url',
|
178
|
+
:remote2_url => 'remote2_url'
|
179
|
+
},
|
180
|
+
:data =>
|
181
|
+
{
|
182
|
+
:a_hash => {:some => :data},
|
183
|
+
:array_elements => [1, 2, 3],
|
184
|
+
:a_value => 'value',
|
185
|
+
:nil => nil,
|
186
|
+
:array_hash_elements => [{:the => :one}, {:the => :other}]
|
187
|
+
}
|
188
|
+
}
|
189
|
+
}
|
190
|
+
|
191
|
+
@client = TAPI::V3::Client.new(@data_hash, nil, true)
|
192
|
+
@client.class_mapping[:some_key] = TAPI::V3::NewClient
|
193
|
+
@client.class_mapping[:data] = TAPI::V3::Data
|
194
|
+
@client.class_mapping[:array_hash_elements] = TAPI::V3::ArrayHashElement
|
195
|
+
|
196
|
+
def @client.remote_cache=(v)
|
197
|
+
@remote_cache = v
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
201
|
+
it 'should return the initial hash' do
|
202
|
+
@client.to_hash.should == @data_hash
|
203
|
+
end
|
204
|
+
|
205
|
+
it 'should raise an error when a unknown method is called' do
|
206
|
+
lambda {@client.search.giveme}.should raise_error NoMethodError
|
207
|
+
end
|
208
|
+
|
209
|
+
it 'should return nil if a key is present but value is nil' do
|
210
|
+
@client.search.data.nil.should == nil
|
211
|
+
end
|
212
|
+
|
213
|
+
it 'should raise an error when a unknown method is called' do
|
214
|
+
lambda {@client.search.fetch_giveme}.should raise_error NoMethodError
|
215
|
+
end
|
216
|
+
|
217
|
+
it 'should instanciate a new client with a sub-hash' do
|
218
|
+
@client.search.class.should == TAPI::V3::Client
|
219
|
+
end
|
220
|
+
|
221
|
+
it 'should instanciate a new client with a sub-sub-hash' do
|
222
|
+
@client.search.data.to_hash.should == @data_hash[:search][:data]
|
223
|
+
end
|
224
|
+
|
225
|
+
it 'should return a plain value' do
|
226
|
+
@client.search.data.a_value.should == 'value'
|
227
|
+
end
|
228
|
+
|
229
|
+
it 'should not shortcut to a multiple subdocuments' do
|
230
|
+
client = TAPI::V3::Client.new(:key => { :value => 'value' }, :second => { :value => 'value' })
|
231
|
+
lambda { client.value }.should raise_error NoMethodError
|
232
|
+
end
|
233
|
+
|
234
|
+
it 'should instanciate a set of new client with an array' do
|
235
|
+
@client.search.data.array_elements == [1, 2, 3]
|
236
|
+
end
|
237
|
+
|
238
|
+
it 'should know its attributes' do
|
239
|
+
@client.attributes == ['search']
|
240
|
+
@client.search.attributes == ['resources', 'data']
|
241
|
+
end
|
242
|
+
|
243
|
+
it 'should know its urls' do
|
244
|
+
expect = {:remote1_url => 'remote1_url', :remote2_url => 'remote2_url'}
|
245
|
+
@client.urls.should == expect
|
246
|
+
@client.urls.should == expect
|
247
|
+
@client.search.data.urls.should == {}
|
248
|
+
end
|
249
|
+
|
250
|
+
it 'should know its urls' do
|
251
|
+
@client.remote_calls.should == ["fetch_remote1", "fetch_remote2"]
|
252
|
+
end
|
253
|
+
|
254
|
+
it 'should be able to call a remote method' do
|
255
|
+
@client.should_receive(:get).with('remote1_url', TAPI::V3::Client, {})
|
256
|
+
@client.fetch_remote1
|
257
|
+
end
|
258
|
+
|
259
|
+
it 'should be able to call a remote method with options' do
|
260
|
+
options = {:please_consider => :this}
|
261
|
+
@client.should_receive(:get).with('remote1_url', TAPI::V3::Client, options)
|
262
|
+
@client.fetch_remote1(options)
|
263
|
+
end
|
264
|
+
|
265
|
+
it 'should find a client class' do
|
266
|
+
@client.send(:client_class, 'some_key').should == TAPI::V3::NewClient
|
267
|
+
end
|
268
|
+
|
269
|
+
it 'should instanciate with a client class' do
|
270
|
+
@client.search.data.class.should == TAPI::V3::Data
|
271
|
+
end
|
272
|
+
|
273
|
+
it 'should instanciate with an array of client classes' do
|
274
|
+
array = @client.search.data.array_hash_elements
|
275
|
+
array.length.should == 2
|
276
|
+
array.map(&:class).uniq.should == [TAPI::V3::ArrayHashElement]
|
277
|
+
end
|
278
|
+
|
279
|
+
it 'should generate url keys' do
|
280
|
+
@client.send(:url_key, 'lala').should == nil
|
281
|
+
@client.send(:url_key, 'fetch_lala').should == 'lala'
|
282
|
+
end
|
283
|
+
|
284
|
+
it 'should generate cache keys' do
|
285
|
+
k1 = @client.send(:cache_key, 'url1', {:opt1 => 1})
|
286
|
+
k2 = @client.send(:cache_key, 'url1', {:opt1 => 1, :opt2 => 2})
|
287
|
+
k3 = @client.send(:cache_key, 'url1', {:opt2 => 2, :opt1 => 1})
|
288
|
+
k1.should_not == k2
|
289
|
+
k2.should == k3
|
290
|
+
end
|
291
|
+
|
292
|
+
it 'should get data from remote if the cache is empty' do
|
293
|
+
@client.remote_cache = {}
|
294
|
+
@client.class.should_receive(:new_from_get).with('the_url', {:instanciate_as => 'the_class'}, nil).and_return(['remote_data', 'remote_etag'])
|
295
|
+
@client.send(:get, 'the_url', 'the_class').should == 'remote_data'
|
296
|
+
end
|
297
|
+
|
298
|
+
it 'should get data from cache if it is cached' do
|
299
|
+
@client.stub!(:cache_key => 'the_key')
|
300
|
+
@client.remote_cache = {'the_key' => {:etag => 'the_etag', :data => 'cached_data'}}
|
301
|
+
@client.class.should_receive(:new_from_get).with('the_url', {:instanciate_as => 'the_class'}, 'the_etag').and_return(['remote_data', 'the_etag'])
|
302
|
+
@client.send(:get, 'the_url', 'the_class').should == 'cached_data'
|
303
|
+
end
|
304
|
+
|
305
|
+
it 'should return a cached reply if :skip_refresh option is given' do
|
306
|
+
@client.stub!(:cache_key => 'the_key')
|
307
|
+
@client.remote_cache = {'the_key' => {:etag => 'the_etag', :data => 'cached_data'}}
|
308
|
+
@client.class.should_not_receive(:new_from_get)
|
309
|
+
@client.send(:get, 'the_url', 'the_class', :skip_refresh => true).should == 'cached_data'
|
310
|
+
end
|
311
|
+
|
312
|
+
it 'should get data from remote if the etag is not in the cache' do
|
313
|
+
@client.stub!(:cache_key => 'the_key')
|
314
|
+
@client.remote_cache = {'the_key' => {:etag => 'local_etag', :data => 'cached_data'}}
|
315
|
+
@client.class.should_receive(:new_from_get).with('the_url', {:instanciate_as => 'the_class'}, 'local_etag').and_return(['remote_data', 'remote_etag'])
|
316
|
+
@client.send(:get, 'the_url', 'the_class').should == 'remote_data'
|
317
|
+
end
|
318
|
+
|
319
|
+
end
|
320
|
+
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
|
3
|
+
describe TAPI::V3::Configurable, " configuration" do
|
4
|
+
before(:each) do
|
5
|
+
@klass = Class.new
|
6
|
+
@klass.send(:include, TAPI::V3::Configurable)
|
7
|
+
end
|
8
|
+
|
9
|
+
it 'should not raise an error if it is configured' do
|
10
|
+
@klass.config = {}
|
11
|
+
lambda { @klass.config }.should_not raise_error
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'should remember its configuration' do
|
15
|
+
config = {:config_data => :it_is}
|
16
|
+
@klass.config = config
|
17
|
+
@klass.config.should == config
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'should make the configuration accesible to its instances' do
|
21
|
+
config = {:config_data => :it_is}
|
22
|
+
@klass.config = config
|
23
|
+
@klass.new.config.should == config
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
|