ticketevolution-ruby 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (146) hide show
  1. data/.gitignore +8 -0
  2. data/.rdebugrc +1 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +6 -0
  5. data/Gemfile +7 -0
  6. data/LICENSE +23 -0
  7. data/README.markdown +237 -0
  8. data/Rakefile +124 -0
  9. data/examples/events.rb +64 -0
  10. data/lib/docs/endpoints.markdown +47 -0
  11. data/lib/docs/installation.markdown +5 -0
  12. data/lib/docs/introduction.markdown +16 -0
  13. data/lib/docs/objects.markdown +40 -0
  14. data/lib/ticket_evolution/account.rb +4 -0
  15. data/lib/ticket_evolution/accounts.rb +6 -0
  16. data/lib/ticket_evolution/address.rb +4 -0
  17. data/lib/ticket_evolution/brokerage.rb +4 -0
  18. data/lib/ticket_evolution/brokerages.rb +7 -0
  19. data/lib/ticket_evolution/categories.rb +7 -0
  20. data/lib/ticket_evolution/category.rb +4 -0
  21. data/lib/ticket_evolution/client.rb +4 -0
  22. data/lib/ticket_evolution/clients/addresses.rb +10 -0
  23. data/lib/ticket_evolution/clients/credit_cards.rb +8 -0
  24. data/lib/ticket_evolution/clients/email_addresses.rb +10 -0
  25. data/lib/ticket_evolution/clients/phone_numbers.rb +10 -0
  26. data/lib/ticket_evolution/clients.rb +8 -0
  27. data/lib/ticket_evolution/configuration.rb +4 -0
  28. data/lib/ticket_evolution/configurations.rb +6 -0
  29. data/lib/ticket_evolution/core/api_error.rb +11 -0
  30. data/lib/ticket_evolution/core/base.rb +12 -0
  31. data/lib/ticket_evolution/core/builder.rb +74 -0
  32. data/lib/ticket_evolution/core/collection.rb +32 -0
  33. data/lib/ticket_evolution/core/connection.rb +99 -0
  34. data/lib/ticket_evolution/core/datum.rb +7 -0
  35. data/lib/ticket_evolution/core/endpoint/request_handler.rb +46 -0
  36. data/lib/ticket_evolution/core/endpoint.rb +51 -0
  37. data/lib/ticket_evolution/core/model.rb +64 -0
  38. data/lib/ticket_evolution/core/models/samples.rb +8 -0
  39. data/lib/ticket_evolution/core/samples.rb +6 -0
  40. data/lib/ticket_evolution/core/singular_class.rb +7 -0
  41. data/lib/ticket_evolution/core/time.rb +19 -0
  42. data/lib/ticket_evolution/credit_card.rb +4 -0
  43. data/lib/ticket_evolution/email_address.rb +4 -0
  44. data/lib/ticket_evolution/errors/connection_not_found.rb +4 -0
  45. data/lib/ticket_evolution/errors/endpoint_configuration_error.rb +5 -0
  46. data/lib/ticket_evolution/errors/invalid_configuration.rb +4 -0
  47. data/lib/ticket_evolution/errors/method_unavailable_error.rb +4 -0
  48. data/lib/ticket_evolution/event.rb +4 -0
  49. data/lib/ticket_evolution/events.rb +7 -0
  50. data/lib/ticket_evolution/modules/create.rb +18 -0
  51. data/lib/ticket_evolution/modules/deleted.rb +13 -0
  52. data/lib/ticket_evolution/modules/list.rb +15 -0
  53. data/lib/ticket_evolution/modules/search.rb +13 -0
  54. data/lib/ticket_evolution/modules/show.rb +20 -0
  55. data/lib/ticket_evolution/modules/update.rb +24 -0
  56. data/lib/ticket_evolution/office.rb +4 -0
  57. data/lib/ticket_evolution/offices.rb +7 -0
  58. data/lib/ticket_evolution/order.rb +15 -0
  59. data/lib/ticket_evolution/orders.rb +30 -0
  60. data/lib/ticket_evolution/performer.rb +4 -0
  61. data/lib/ticket_evolution/performers.rb +8 -0
  62. data/lib/ticket_evolution/phone_number.rb +4 -0
  63. data/lib/ticket_evolution/quote.rb +4 -0
  64. data/lib/ticket_evolution/quotes.rb +7 -0
  65. data/lib/ticket_evolution/search.rb +22 -0
  66. data/lib/ticket_evolution/shipment.rb +4 -0
  67. data/lib/ticket_evolution/shipments.rb +8 -0
  68. data/lib/ticket_evolution/ticket_group.rb +4 -0
  69. data/lib/ticket_evolution/ticket_groups.rb +6 -0
  70. data/lib/ticket_evolution/user.rb +4 -0
  71. data/lib/ticket_evolution/users.rb +7 -0
  72. data/lib/ticket_evolution/venue.rb +4 -0
  73. data/lib/ticket_evolution/venues.rb +8 -0
  74. data/lib/ticket_evolution/version.rb +3 -0
  75. data/lib/ticket_evolution.rb +108 -0
  76. data/spec/fixtures/fake.rb +97 -0
  77. data/spec/fixtures/net/endpoints/accounts.yml +175 -0
  78. data/spec/fixtures/net/endpoints/brokerages.yml +257 -0
  79. data/spec/fixtures/net/endpoints/categories.yml +85 -0
  80. data/spec/fixtures/net/endpoints/clients.yml +243 -0
  81. data/spec/fixtures/net/endpoints/search.yml +93 -0
  82. data/spec/lib/ticket_evolution/account_spec.rb +7 -0
  83. data/spec/lib/ticket_evolution/accounts_spec.rb +45 -0
  84. data/spec/lib/ticket_evolution/address_spec.rb +7 -0
  85. data/spec/lib/ticket_evolution/brokerage_spec.rb +7 -0
  86. data/spec/lib/ticket_evolution/brokerages_spec.rb +50 -0
  87. data/spec/lib/ticket_evolution/categories_spec.rb +27 -0
  88. data/spec/lib/ticket_evolution/category_spec.rb +7 -0
  89. data/spec/lib/ticket_evolution/client_spec.rb +7 -0
  90. data/spec/lib/ticket_evolution/clients/addresses_spec.rb +13 -0
  91. data/spec/lib/ticket_evolution/clients/credit_cards_spec.rb +11 -0
  92. data/spec/lib/ticket_evolution/clients/email_addresses_spec.rb +13 -0
  93. data/spec/lib/ticket_evolution/clients/phone_numbers_spec.rb +13 -0
  94. data/spec/lib/ticket_evolution/clients_spec.rb +37 -0
  95. data/spec/lib/ticket_evolution/configuration_spec.rb +7 -0
  96. data/spec/lib/ticket_evolution/configurations_spec.rb +10 -0
  97. data/spec/lib/ticket_evolution/core/api_error_spec.rb +13 -0
  98. data/spec/lib/ticket_evolution/core/base_spec.rb +29 -0
  99. data/spec/lib/ticket_evolution/core/builder_spec.rb +95 -0
  100. data/spec/lib/ticket_evolution/core/collection_spec.rb +23 -0
  101. data/spec/lib/ticket_evolution/core/connection_spec.rb +220 -0
  102. data/spec/lib/ticket_evolution/core/datum_spec.rb +15 -0
  103. data/spec/lib/ticket_evolution/core/endpoint_spec.rb +12 -0
  104. data/spec/lib/ticket_evolution/core/model_spec.rb +167 -0
  105. data/spec/lib/ticket_evolution/core/time_spec.rb +28 -0
  106. data/spec/lib/ticket_evolution/credit_card_spec.rb +7 -0
  107. data/spec/lib/ticket_evolution/email_address_spec.rb +7 -0
  108. data/spec/lib/ticket_evolution/errors/connection_not_found_spec.rb +7 -0
  109. data/spec/lib/ticket_evolution/errors/endpoint_configuration_error_spec.rb +8 -0
  110. data/spec/lib/ticket_evolution/errors/invalid_configuration_spec.rb +8 -0
  111. data/spec/lib/ticket_evolution/errors/method_unavailable_error_spec.rb +7 -0
  112. data/spec/lib/ticket_evolution/event_spec.rb +7 -0
  113. data/spec/lib/ticket_evolution/events_spec.rb +11 -0
  114. data/spec/lib/ticket_evolution/office_spec.rb +7 -0
  115. data/spec/lib/ticket_evolution/offices_spec.rb +11 -0
  116. data/spec/lib/ticket_evolution/order_spec.rb +44 -0
  117. data/spec/lib/ticket_evolution/orders_spec.rb +123 -0
  118. data/spec/lib/ticket_evolution/performer_spec.rb +7 -0
  119. data/spec/lib/ticket_evolution/performers_spec.rb +12 -0
  120. data/spec/lib/ticket_evolution/phone_number_spec.rb +7 -0
  121. data/spec/lib/ticket_evolution/quote_spec.rb +7 -0
  122. data/spec/lib/ticket_evolution/quotes_spec.rb +11 -0
  123. data/spec/lib/ticket_evolution/search_spec.rb +31 -0
  124. data/spec/lib/ticket_evolution/shipment_spec.rb +7 -0
  125. data/spec/lib/ticket_evolution/shipments_spec.rb +13 -0
  126. data/spec/lib/ticket_evolution/ticket_group_spec.rb +7 -0
  127. data/spec/lib/ticket_evolution/ticket_groups_spec.rb +14 -0
  128. data/spec/lib/ticket_evolution/user_spec.rb +7 -0
  129. data/spec/lib/ticket_evolution/users_spec.rb +15 -0
  130. data/spec/lib/ticket_evolution/venue_spec.rb +7 -0
  131. data/spec/lib/ticket_evolution/venues_spec.rb +12 -0
  132. data/spec/lib/ticket_evolution_spec.rb +20 -0
  133. data/spec/shared_examples/endpoints/class.rb +241 -0
  134. data/spec/shared_examples/endpoints/create.rb +41 -0
  135. data/spec/shared_examples/endpoints/deleted.rb +41 -0
  136. data/spec/shared_examples/endpoints/list.rb +41 -0
  137. data/spec/shared_examples/endpoints/search.rb +42 -0
  138. data/spec/shared_examples/endpoints/show.rb +38 -0
  139. data/spec/shared_examples/endpoints/update.rb +59 -0
  140. data/spec/shared_examples/errors.rb +5 -0
  141. data/spec/shared_examples/models.rb +29 -0
  142. data/spec/spec_helper.rb +21 -0
  143. data/spec/support/connection.rb +10 -0
  144. data/spec/support/vcr.rb +12 -0
  145. data/ticketevolution-ruby.gemspec +33 -0
  146. metadata +384 -0
@@ -0,0 +1,20 @@
1
+ require 'spec_helper'
2
+
3
+ describe TicketEvolution do
4
+ subject{ TicketEvolution }
5
+
6
+ it "should specify a version" do
7
+ subject::VERSION.should be
8
+ end
9
+
10
+ describe ".root" do
11
+ subject { TicketEvolution.root }
12
+
13
+ it { should be_a Pathname }
14
+
15
+ it "should end in 'ticket_evolution'" do
16
+ subject.to_s.should =~ /ticket_evolution$/
17
+ end
18
+ end
19
+ end
20
+
@@ -0,0 +1,241 @@
1
+ require 'spec_helper'
2
+
3
+ shared_examples_for "a ticket_evolution endpoint class" do
4
+ let(:connection) { TicketEvolution::Connection.new({:token => Fake.token, :secret => Fake.secret}) }
5
+ let(:sample_parent) { TicketEvolution::Samples.new }
6
+ let(:curl) { double(:curl, :http => nil) }
7
+ let(:instance) { klass.new({:parent => connection}) }
8
+ let(:path) { '/search' }
9
+ let(:full_path) { "#{instance.base_path}#{path}" }
10
+
11
+ describe "#initialize" do
12
+ context "with an options hash for it's first parameter" do
13
+ it "should create accessors for each key value pair" do
14
+ instance = klass.new({
15
+ :parent => connection,
16
+ :test => :one,
17
+ :testing => "two",
18
+ :number => 3,
19
+ :hash => {}
20
+ })
21
+ instance.parent.should == connection
22
+ instance.test.should == :one
23
+ instance.testing.should == "two"
24
+ instance.number.should == 3
25
+ instance.hash.should == {}
26
+ end
27
+
28
+ context "with a parent k/v pair" do
29
+ context "that does not inherit from TicketEvolution::Base" do
30
+ it "should raise an EndpointConfigurationError" do
31
+ message = "#{klass} instances require a parent which inherits from TicketEvolution::Base"
32
+ expect {
33
+ klass.new({:parent => Object.new})
34
+ }.to raise_error TicketEvolution::EndpointConfigurationError, message
35
+ end
36
+ end
37
+
38
+ context "that does inherit from TicketEvolution::Base" do
39
+ context "and is a TicketEvolution::Connection object" do
40
+ it "should not raise" do
41
+ expect { klass.new({:parent => connection}) }.to_not raise_error
42
+ end
43
+ end
44
+
45
+ context "and has a TicketEvolution::Connection object in it's parent chain" do
46
+ let(:sample_chain) do
47
+ TicketEvolution::Endpoint.new({
48
+ :parent => TicketEvolution::Endpoint.new({
49
+ :parent => connection
50
+ })
51
+ })
52
+ end
53
+
54
+ it "should not raise" do
55
+ expect { klass.new({:parent => klass.new({:parent => sample_chain})}) }.to_not raise_error
56
+ end
57
+ end
58
+
59
+ context "and does not have a TicketEvolution::Connection object in it's parent chain" do
60
+ it "should raise an EndpointConfigurationError" do
61
+ message = "The parent passed in the options hash must be a TicketEvolution::Connection object or have one in it's parent chain"
62
+ expect {
63
+ klass.new({:parent => sample_parent})
64
+ }.to raise_error TicketEvolution::EndpointConfigurationError, message
65
+ end
66
+ end
67
+ end
68
+ end
69
+
70
+ context "without a parent k/v pair" do
71
+ it "should raise an EndpointConfigurationError" do
72
+ message = "The options hash must include a parent key / value pair"
73
+ expect {
74
+ klass.new({})
75
+ }.to raise_error TicketEvolution::EndpointConfigurationError, message
76
+ end
77
+ end
78
+ end
79
+
80
+ context "with no first parameter or a non hash object" do
81
+ it "should raise an EndpointConfigurationError" do
82
+ message = "#{klass} instances require a hash as their first parameter"
83
+ expect { klass.new }.to raise_error TicketEvolution::EndpointConfigurationError, message
84
+ end
85
+ end
86
+ end
87
+
88
+ describe "#base_path" do
89
+ let(:endpoint_name) { klass.name.demodulize.underscore }
90
+
91
+ context "when #parent is a TicketEvolution::Connection object" do
92
+ let(:path) { "/#{endpoint_name}" }
93
+
94
+ it "should be generated based on its class name" do
95
+ klass.new({:parent => connection}).base_path.should == path
96
+ end
97
+ end
98
+
99
+ context "when #parent is not a TicketEvolution::Connection object" do
100
+ let(:instance) { klass.new({:parent => connection, :id => 1}) }
101
+ let(:path) { "/#{instance.endpoint_name}/#{instance.id}/#{endpoint_name}" }
102
+ it "should be generated based on its class name and the class names of its parents" do
103
+ klass.new({:parent => instance}).base_path.should == path
104
+ end
105
+ end
106
+ end
107
+
108
+ describe "#connection" do
109
+ context "the connection object is the parent" do
110
+ subject { klass.new({:parent => connection}) }
111
+
112
+ its(:connection) { should == connection }
113
+ end
114
+
115
+ context "the connection object is not the parent" do
116
+ subject { klass.new({:parent => TicketEvolution::Endpoint.new({:parent => connection})}) }
117
+
118
+ its(:connection) { should == connection }
119
+ end
120
+ end
121
+
122
+ describe "#build_request" do
123
+
124
+ context "which is valid" do
125
+ context "with params" do
126
+ let(:params) do
127
+ {
128
+ :page => 1,
129
+ :per_page => 10,
130
+ :name => "test"
131
+ }
132
+ end
133
+
134
+ [:GET, :POST, :PUT, :DELETE].each do |method|
135
+ it "should accept an http '#{method}' method, a url path for the call and a list of parameters as a hash and pass them to connection" do
136
+ connection.should_receive(:build_request).with(method, full_path, params).and_return(curl)
137
+
138
+ instance.build_request(method, path, params)
139
+ end
140
+ end
141
+ end
142
+
143
+ context "without params" do
144
+ [:GET, :POST, :PUT, :DELETE].each do |method|
145
+ it "should accept an http '#{method}' method and a url path for the call and pass them to connection" do
146
+ connection.should_receive(:build_request).with(method, full_path, nil).and_return(curl)
147
+
148
+ instance.build_request(method, path)
149
+ end
150
+ end
151
+ end
152
+ end
153
+
154
+ context "given an invalid http method" do
155
+ it "should raise a EndpointConfigurationError" do
156
+ message = "#{klass.to_s}#request requires it's first parameter to be a valid HTTP method"
157
+
158
+ expect { instance.request('BAD', path) }.to raise_error TicketEvolution::EndpointConfigurationError, message
159
+ end
160
+ end
161
+ end
162
+
163
+ describe "#request" do
164
+ subject { instance.request method, full_path }
165
+ let(:method) { :GET }
166
+ let(:response) { Fake.response }
167
+ let(:handler) { Fake.send(:method, :response_handler) }
168
+
169
+ before do
170
+ connection.should_receive(:build_request).and_return(curl)
171
+ instance.should_receive(:naturalize_response).and_return(response)
172
+ end
173
+
174
+ it "calls http on the return Curl object with the method for the request" do
175
+ curl.should_receive(:http).with(method)
176
+
177
+ instance.request(method, path, nil, &handler).should == Fake.response_handler(true)
178
+ end
179
+
180
+ context "when there is an error from the api" do
181
+ let(:response) { Fake.error_response }
182
+
183
+ before { curl.should_receive(:http) }
184
+
185
+ it "should return an instance of TicketEvolution::ApiError" do
186
+ subject.should be_a TicketEvolution::ApiError
187
+ end
188
+ end
189
+
190
+ context "when successful" do
191
+ let(:response) { Fake.response }
192
+
193
+ before { curl.should_receive(:http) }
194
+
195
+ it "should pass the response object to #build_object" do
196
+ instance.request(method, path, nil, &handler).should == Fake.response_handler(true)
197
+ end
198
+ end
199
+ end
200
+
201
+ describe "#naturalize_response" do
202
+ let(:path) { '/list' }
203
+ let(:instance) { klass.new({:parent => connection}) }
204
+ let(:full_path) { "#{instance.base_path}#{path}" }
205
+ let(:response_code) { 200 }
206
+ let(:response) { mock(:response, {
207
+ :header_str => "header",
208
+ :response_code => response_code,
209
+ :body_str => body_str
210
+ }) }
211
+
212
+ context "with a valid body" do
213
+ subject { instance.naturalize_response response }
214
+ let(:body_str) { "{\"test\": \"hello\"}" }
215
+
216
+ its(:header) { should == response.header_str }
217
+ its(:body) { should == MultiJson.decode(response.body_str).merge({:connection => connection}) }
218
+
219
+ TicketEvolution::Endpoint::RequestHandler::CODES.each do |code, value|
220
+ context "with response code #{code}" do
221
+ let(:response_code) { code }
222
+
223
+ its(:response_code) { should == code }
224
+ its(:server_message) { should == value.last }
225
+ end
226
+ end
227
+ end
228
+ end
229
+
230
+ context "#endpoint_name" do
231
+ it "returns the demodulized version of the endpoint name" do
232
+ instance.endpoint_name.should == klass.name.demodulize.underscore
233
+ end
234
+ end
235
+
236
+ context "#singular_class" do
237
+ it "returns the singular version of an Endpoint class" do
238
+ instance.singular_class.should == single_klass
239
+ end
240
+ end
241
+ end
@@ -0,0 +1,41 @@
1
+ require 'spec_helper'
2
+
3
+ shared_examples_for "a create endpoint" do
4
+ let(:connection) { TicketEvolution::Connection.new({:token => Fake.token, :secret => Fake.secret}) }
5
+ let(:builder_klass) { "TicketEvolution::#{klass.to_s.split('::').last.singularize.camelize}".constantize }
6
+ let(:instance) { klass.new({:parent => connection}) }
7
+
8
+ describe "#create" do
9
+ context "with params" do
10
+ let(:params) { {:name => "Bob"} }
11
+
12
+ it "should pass call request as a POST, passing params" do
13
+ instance.should_receive(:request).with(:POST, nil, instance.endpoint_name.to_sym => [params])
14
+
15
+ instance.create(params)
16
+ end
17
+ end
18
+
19
+ context "without params" do
20
+ it "should pass call request as a POST, without params" do
21
+ instance.should_receive(:request).with(:POST, nil, nil)
22
+
23
+ instance.create
24
+ end
25
+ end
26
+ end
27
+
28
+ describe "#build_for_create" do
29
+ let(:response) { Fake.create_response instance.endpoint_name, connection }
30
+
31
+ it "should invoke an instance of its builder class" do
32
+ builder_klass.should_receive(:new).with(response.body[instance.endpoint_name].first.merge({
33
+ :status_code => response.response_code,
34
+ :server_message => response.server_message,
35
+ :connection => connection
36
+ }))
37
+
38
+ instance.build_for_create(response)
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,41 @@
1
+ require 'spec_helper'
2
+
3
+ shared_examples_for "a deleted endpoint" do
4
+ let(:connection) { TicketEvolution::Connection.new({:token => Fake.token, :secret => Fake.secret}) }
5
+ let(:instance) { klass.new({:parent => connection}) }
6
+
7
+ describe "#deleted" do
8
+ context "with params" do
9
+ let(:params) { {:page => 2, :per_page => 2} }
10
+
11
+ it "should pass call request as a GET, passing params" do
12
+ instance.should_receive(:request).with(:GET, '/deleted', params)
13
+
14
+ instance.deleted(params)
15
+ end
16
+ end
17
+
18
+ context "without params" do
19
+ it "should pass call request as a GET, passing params" do
20
+ instance.should_receive(:request).with(:GET, '/deleted', nil)
21
+
22
+ instance.deleted
23
+ end
24
+ end
25
+ end
26
+
27
+ context "#build_for_deleted" do
28
+ let(:response) { Fake.list_response }
29
+
30
+ it "invokes Collection#build_from_response" do
31
+ TicketEvolution::Collection.
32
+ should_receive(:build_from_response).
33
+ with(response, klass.name.demodulize.underscore, instance.singular_class)
34
+ instance.build_for_deleted(response)
35
+ end
36
+
37
+ it "returns a collection" do
38
+ instance.build_for_deleted(response).should be_a TicketEvolution::Collection
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,41 @@
1
+ require 'spec_helper'
2
+
3
+ shared_examples_for "a list endpoint" do
4
+ let(:connection) { TicketEvolution::Connection.new({:token => Fake.token, :secret => Fake.secret}) }
5
+ let(:instance) { klass.new({:parent => connection}) }
6
+
7
+ describe "#list" do
8
+ context "with params" do
9
+ let(:params) { {:page => 2, :per_page => 2} }
10
+
11
+ it "should pass call request as a GET, passing params" do
12
+ instance.should_receive(:request).with(:GET, nil, params)
13
+
14
+ instance.list(params)
15
+ end
16
+ end
17
+
18
+ context "without params" do
19
+ it "should pass call request as a GET, passing params" do
20
+ instance.should_receive(:request).with(:GET, nil, nil)
21
+
22
+ instance.list
23
+ end
24
+ end
25
+ end
26
+
27
+ context "#build_for_list" do
28
+ let(:response) { Fake.list_response }
29
+
30
+ it "invokes Collection#build_from_response" do
31
+ TicketEvolution::Collection.
32
+ should_receive(:build_from_response).
33
+ with(response, klass.name.demodulize.underscore, instance.singular_class)
34
+ instance.build_for_list(response)
35
+ end
36
+
37
+ it "returns a collection" do
38
+ instance.build_for_list(response).should be_a TicketEvolution::Collection
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,42 @@
1
+ require 'spec_helper'
2
+
3
+ shared_examples_for "a search endpoint" do
4
+ let(:connection) { TicketEvolution::Connection.new({:token => Fake.token, :secret => Fake.secret}) }
5
+ let(:instance) { klass.new({:parent => connection}) }
6
+
7
+ describe "#search" do
8
+ context "with params" do
9
+ let(:params) { {:page => 2, :per_page => 2, :q => "test"} }
10
+
11
+ it "should pass call request as a GET, passing params" do
12
+ instance.should_receive(:request).with(:GET, '/search', params)
13
+
14
+ instance.search(params)
15
+ end
16
+ end
17
+
18
+ context "without params" do
19
+ it "should pass call request as a GET, passing params" do
20
+ instance.should_receive(:request).with(:GET, '/search', nil)
21
+
22
+ instance.search
23
+ end
24
+ end
25
+ end
26
+
27
+ context "#build_for_search" do
28
+ let(:response) { Fake.list_response }
29
+
30
+ it "invokes Collection#build_from_response" do
31
+ TicketEvolution::Collection.
32
+ should_receive(:build_from_response).
33
+ with(response, klass.name.demodulize.underscore, instance.singular_class)
34
+ instance.build_for_search(response)
35
+ end
36
+
37
+ it "returns a collection" do
38
+ instance.build_for_search(response).should be_a TicketEvolution::Collection
39
+ end
40
+ end
41
+
42
+ end
@@ -0,0 +1,38 @@
1
+ require 'spec_helper'
2
+
3
+ shared_examples_for "a show endpoint" do
4
+ let(:connection) { TicketEvolution::Connection.new({:token => Fake.token, :secret => Fake.secret}) }
5
+ let(:builder_klass) { "TicketEvolution::#{klass.to_s.split('::').last.singularize.camelize}".constantize }
6
+ let(:instance) { klass.new({:parent => connection}) }
7
+
8
+ describe "#show" do
9
+ context "with id" do
10
+ let(:id) { 1 }
11
+
12
+ it "should pass call request as a GET, passing the id as a piece of the path" do
13
+ instance.should_receive(:request).with(:GET, "/#{id}")
14
+
15
+ instance.show(id)
16
+ end
17
+ end
18
+
19
+ context "without id" do
20
+ it "should raise an ArgumentError" do
21
+ expect { instance.show }.to raise_error ArgumentError
22
+ end
23
+ end
24
+ end
25
+
26
+ describe "#build_for_show" do
27
+ let(:response) { Fake.show_response }
28
+
29
+ it "should invoke an instance of its builder class" do
30
+ builder_klass.should_receive(:new).with(response.body.merge({
31
+ :status_code => response.response_code,
32
+ :server_message => response.server_message})
33
+ )
34
+
35
+ instance.build_for_show(response)
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,59 @@
1
+ require 'spec_helper'
2
+
3
+ shared_examples_for "an update endpoint" do
4
+ let(:connection) { TicketEvolution::Connection.new({:token => Fake.token, :secret => Fake.secret}) }
5
+ let(:instance) { klass.new({:parent => connection}) }
6
+
7
+ describe "#update" do
8
+ context "with an id" do
9
+ let(:instance) { klass.new({:parent => connection, :id => 1}) }
10
+
11
+ context "with params" do
12
+ let(:params) { {:name => "Bob"} }
13
+
14
+ it "should pass call request as a PUT, passing params" do
15
+ instance.should_receive(:request).with(:PUT, "/#{instance.id}", params)
16
+
17
+ instance.update(params)
18
+ end
19
+ end
20
+
21
+ context "without params" do
22
+ it "should pass call request as a PUT, passing params" do
23
+ instance.should_receive(:request).with(:PUT, "/#{instance.id}", nil)
24
+
25
+ instance.update
26
+ end
27
+ end
28
+ end
29
+
30
+ context "without an id" do
31
+ it "should raise an UnavailableMethodError if there is no id" do
32
+ message = "#{klass.to_s}#update can only be called if there is an id present on this #{klass.to_s} instance"
33
+ expect { instance.update }.to raise_error TicketEvolution::MethodUnavailableError, message
34
+ end
35
+ end
36
+ end
37
+
38
+ describe ".included" do
39
+ let(:model_klass) { instance.singular_class }
40
+ let(:model_instance) { model_klass.new(attributes.merge({:connection => connection})) }
41
+ let(:attributes) { HashWithIndifferentAccess.new(update_base.merge({:one => 1, :two => "two", :three => nil, :id => 1})) }
42
+ let(:stored_attributes) { attributes.delete_if{|k, v| k == 'id'} }
43
+ let(:updated_attributes) { HashWithIndifferentAccess.new({:one => "one", :three => 3}) }
44
+ let(:merged_attributes) { attributes.merge(updated_attributes) }
45
+
46
+ it "should set an update_attributes method on it's corresponding TE:Model class which adds to it's attributes and calls #update" do
47
+ model_instance.should respond_to :update_attributes
48
+ klass.any_instance.should_receive(:update).with(updated_attributes).and_return(nil)
49
+ model_instance.update_attributes(updated_attributes)
50
+ model_instance.attributes.should == merged_attributes
51
+ end
52
+
53
+ it "should set a save method on it's corresponding TE:Model class which calls #update with it's attributes" do
54
+ model_instance.should respond_to :save
55
+ klass.any_instance.should_receive(:update).with(stored_attributes).and_return(nil)
56
+ model_instance.save
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,5 @@
1
+ require 'spec_helper'
2
+
3
+ shared_examples_for "a ticket_evolution error class" do
4
+ its(:ancestors) { should include Exception }
5
+ end
@@ -0,0 +1,29 @@
1
+ require 'spec_helper'
2
+
3
+ shared_examples_for "a ticket_evolution model" do
4
+ let(:klass) { subject }
5
+ let(:instance) { klass.new({:connection => Fake.connection}) }
6
+
7
+ its(:ancestors) { should include TicketEvolution::Model }
8
+
9
+ describe "#attributes" do
10
+ let(:hash) { { "hash" => { "test" => "1.. 2... 3...." } } }
11
+
12
+ it "should return a hash of attribute key/pair values" do
13
+ instance.one = 1
14
+ instance.two = 2
15
+ instance.three = nil
16
+
17
+ instance.attributes.should == {"one" => 1, "two" => 2, "three" => nil}
18
+ end
19
+
20
+ it "should return a HashWithIndifferentAccess" do
21
+ instance.attributes.should be_a HashWithIndifferentAccess
22
+ end
23
+
24
+ it "should convert OpenStruct based objects back into hashes recursively" do
25
+ instance.hash = hash
26
+ instance.attributes.should == { "hash" => hash }
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,21 @@
1
+ require "ap"
2
+ require File.join(File.dirname(File.expand_path(__FILE__)), '..', 'lib', 'ticket_evolution.rb')
3
+ require 'active_support/ordered_hash' unless RUBY_VERSION =~ /^1\.9/
4
+
5
+ @spec_path = Pathname.new(File.join(File.dirname(File.expand_path(__FILE__))))
6
+
7
+ Dir[File.join(@spec_path, 'support/*.rb')].each { |file| require(file) }
8
+
9
+ RSpec.configure do |config|
10
+ end
11
+
12
+ require @spec_path + 'fixtures' + 'fake.rb'
13
+ require @spec_path + 'shared_examples' + 'endpoints' + 'class.rb'
14
+ require @spec_path + 'shared_examples' + 'endpoints' + 'create.rb'
15
+ require @spec_path + 'shared_examples' + 'endpoints' + 'deleted.rb'
16
+ require @spec_path + 'shared_examples' + 'endpoints' + 'list.rb'
17
+ require @spec_path + 'shared_examples' + 'endpoints' + 'search.rb'
18
+ require @spec_path + 'shared_examples' + 'endpoints' + 'show.rb'
19
+ require @spec_path + 'shared_examples' + 'endpoints' + 'update.rb'
20
+ require @spec_path + 'shared_examples' + 'errors.rb'
21
+ require @spec_path + 'shared_examples' + 'models.rb'
@@ -0,0 +1,10 @@
1
+ module ConnectionSupport
2
+ def connection
3
+ TicketEvolution::Connection.new(
4
+ :token => "b2b5a7a33b1a78896ed1b53d81c5c9cc",
5
+ :secret => "m2bAipNKfNnzz9z88+z2cgDy4Tb+QjIudmpJkJcr"
6
+ )
7
+ end
8
+
9
+ RSpec.configure {|c| c.include self}
10
+ end
@@ -0,0 +1,12 @@
1
+ require 'vcr'
2
+
3
+ VCR.config do |config|
4
+ config.cassette_library_dir = File.join(File.dirname(__FILE__), '..', 'fixtures', 'net')
5
+ config.default_cassette_options = { :record => :none }
6
+ config.ignore_localhost = true
7
+ config.stub_with(:webmock)
8
+ end
9
+
10
+ RSpec.configure do |config|
11
+ config.extend(VCR::RSpec::Macros)
12
+ end
@@ -0,0 +1,33 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.join(File.dirname(File.expand_path(__FILE__)), 'lib', 'ticket_evolution', 'version')
3
+
4
+ Gem::Specification.new do |s|
5
+ s.name = 'ticketevolution-ruby'
6
+ s.version = TicketEvolution::VERSION
7
+ s.platform = Gem::Platform::RUBY
8
+ s.authors = ['David Malin', 'Ticket Evolution']
9
+ s.email = ['dev@ticketevolution.com']
10
+ s.homepage = 'http://api.ticketevolution.com'
11
+ s.summary = 'Integration gem for Ticket Evolution\'s api'
12
+ s.description = ''
13
+
14
+ s.required_rubygems_version = '>= 1.3.5'
15
+
16
+ s.add_dependency 'activesupport'
17
+ s.add_dependency 'i18n'
18
+ s.add_dependency 'curb'
19
+ s.add_dependency 'yajl-ruby'
20
+ s.add_dependency 'multi_json'
21
+ s.add_dependency 'nokogiri'
22
+
23
+ s.add_development_dependency 'rspec', '>= 2.7.1'
24
+ s.add_development_dependency 'vcr'
25
+ s.add_development_dependency 'webmock'
26
+ s.add_development_dependency 'awesome_print'
27
+ s.add_development_dependency 'rake'
28
+
29
+ s.files = `git ls-files`.split("\n")
30
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
31
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
32
+ s.require_paths = ["lib"]
33
+ end