quicktravel_client 3.7.0 → 3.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (79) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +2 -0
  3. data/CHANGELOG.md +12 -0
  4. data/lib/quick_travel/adapter.rb +13 -25
  5. data/lib/quick_travel/booking.rb +0 -4
  6. data/lib/quick_travel/cache.rb +16 -4
  7. data/lib/quick_travel/checkout.rb +2 -1
  8. data/lib/quick_travel/client.rb +9 -1
  9. data/lib/quick_travel/init_from_hash.rb +4 -0
  10. data/lib/quick_travel/product_configuration.rb +1 -1
  11. data/lib/quick_travel/products/base.rb +4 -4
  12. data/lib/quick_travel/reservation.rb +1 -1
  13. data/lib/quick_travel/resource.rb +1 -1
  14. data/lib/quick_travel/route.rb +1 -1
  15. data/lib/quick_travel/route_stop.rb +8 -1
  16. data/lib/quick_travel/version.rb +1 -1
  17. data/quicktravel_client.gemspec +1 -1
  18. data/spec/adapter_spec.rb +34 -3
  19. data/spec/clients_spec.rb +42 -0
  20. data/spec/passenger_type_spec.rb +1 -1
  21. data/spec/product_configuration_spec.rb +11 -0
  22. data/spec/reservation_spec.rb +20 -0
  23. data/spec/spec_helper.rb +1 -3
  24. data/spec/support/cassettes/accommodation_reserve.yml +12 -4
  25. data/spec/support/cassettes/basic_product_scheduled_trips.yml +3 -1
  26. data/spec/support/cassettes/basic_product_scheduled_trips_multi_sector.yml +3 -1
  27. data/spec/support/cassettes/basic_product_scheduled_trips_unbookable.yml +3 -1
  28. data/spec/support/cassettes/booking_activate.yml +6 -2
  29. data/spec/support/cassettes/booking_cancel.yml +6 -2
  30. data/spec/support/cassettes/booking_create.yml +3 -1
  31. data/spec/support/cassettes/booking_create_accommodation.yml +3 -1
  32. data/spec/support/cassettes/booking_documents.yml +3 -1
  33. data/spec/support/cassettes/booking_non_existant.yml +3 -1
  34. data/spec/support/cassettes/booking_price_changes.yml +3 -1
  35. data/spec/support/cassettes/booking_show.yml +3 -1
  36. data/spec/support/cassettes/booking_update.yml +6 -2
  37. data/spec/support/cassettes/booking_with_documents.yml +6 -2
  38. data/spec/support/cassettes/booking_with_nested_attributes.yml +9 -3
  39. data/spec/support/cassettes/booking_with_price_changes.yml +3 -1
  40. data/spec/support/cassettes/checkout_client_token.yml +3 -1
  41. data/spec/support/cassettes/client_templates.yml +120 -0
  42. data/spec/support/cassettes/countries.yml +3 -1
  43. data/spec/support/cassettes/country_all.yml +3 -1
  44. data/spec/support/cassettes/create_reservation_fail.yml +3 -1
  45. data/spec/support/cassettes/create_reservation_with_booking.yml +3 -1
  46. data/spec/support/cassettes/locations.yml +3 -1
  47. data/spec/support/cassettes/opal_modern_pay_failed_booking.yml +3 -1
  48. data/spec/support/cassettes/opal_modern_pay_failed_create.yml +3 -1
  49. data/spec/support/cassettes/opal_modern_pay_failed_update.yml +3 -1
  50. data/spec/support/cassettes/opal_modern_pay_successful_booking.yml +3 -1
  51. data/spec/support/cassettes/opal_modern_pay_successful_response.yml +3 -1
  52. data/spec/support/cassettes/opal_modern_pay_successful_update_response.yml +3 -1
  53. data/spec/support/cassettes/opal_pay.yml +3 -1
  54. data/spec/support/cassettes/opal_pay_booking.yml +3 -1
  55. data/spec/support/cassettes/passenger_all.yml +3 -1
  56. data/spec/support/cassettes/payment_info.yml +3 -1
  57. data/spec/support/cassettes/price_quote.yml +6 -2
  58. data/spec/support/cassettes/product_date_range_bookability.yml +3 -1
  59. data/spec/support/cassettes/product_show.yml +3 -1
  60. data/spec/support/cassettes/product_show_as_agent.yml +3 -1
  61. data/spec/support/cassettes/product_type_all.yml +3 -1
  62. data/spec/support/cassettes/product_type_resource_categories.yml +3 -1
  63. data/spec/support/cassettes/product_type_resource_categories_tickets.yml +3 -1
  64. data/spec/support/cassettes/product_type_routes.yml +3 -1
  65. data/spec/support/cassettes/property.yml +3 -1
  66. data/spec/support/cassettes/property_types.yml +3 -1
  67. data/spec/support/cassettes/region_show.yml +3 -1
  68. data/spec/support/cassettes/reservation_resource.yml +3 -1
  69. data/spec/support/cassettes/reservation_with_extra_picks.yml +9 -3
  70. data/spec/support/cassettes/resource_category_all.yml +3 -1
  71. data/spec/support/cassettes/resource_category_all_for_product_type_8.yml +3 -1
  72. data/spec/support/cassettes/resource_fare_bases.yml +3 -1
  73. data/spec/support/cassettes/resource_show.yml +3 -1
  74. data/spec/support/cassettes/resource_with_price.yml +3 -1
  75. data/spec/support/cassettes/settings_basic.yml +3 -1
  76. data/spec/support/cassettes/tenant_switcher.yml +6 -2
  77. data/spec/support/cassettes/wrong_url.yml +3 -1
  78. data/spec/support/coverage_loader.rb +1 -1
  79. metadata +10 -6
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b60bf00c1c2d71210f2d1f462986abba8859b7acd216b13d68c8d4ad2c475e9d
4
- data.tar.gz: 79cb1bad6bdd5a2178577824c1196ff9e5728beda74e5474bac7f9e53e63c053
3
+ metadata.gz: f0ed55eb639dbe01ac2b6781edfccbc34b720ea04c6b8239830bf60b86406f5f
4
+ data.tar.gz: 776482e19be6a3df01a7e0f2670fda08d5a1a73d3e4fbc0429867126b2385c7b
5
5
  SHA512:
6
- metadata.gz: 205130ad17115f1f0491351af5b76242a8b67a1f384912708fa4ebad3211d428e83284c41aa8c024d82b1004371415848d47a7fd44bd86fcd375952c5eb68737
7
- data.tar.gz: b0cca6ec2c7b5dd695112ba71d112f7593c8bc174070c380aade2d3ddd5aed23b9a44eec3796c207b65ef3d87c6f6bd2f02ced5c3248e58a505907ddfcb2c1f4
6
+ metadata.gz: '098cd8f377681060a0656ac2759730d816d55b3a7e37484d0577d5644ada764566a32911909ead40a61a5f455d0a52690e4a9a29e5b551af44e4a954141a5cec'
7
+ data.tar.gz: 6efb0debce10413a072952301ba5c8fc3a2826ecd3e67a0d94550b0ff1671105e392f351e8485e29488cb6d56ad1a1be222cdcd6dc302ef887e3d9b57e8304d9
@@ -4,6 +4,8 @@ rvm:
4
4
  - 2.3
5
5
  - 2.4
6
6
  - 2.5
7
+ before_install:
8
+ - gem install bundler --version "1.17.3"
7
9
  script: bundle && bundle exec rake spec
8
10
  gemfile:
9
11
  - gemfiles/rails4.gemfile
@@ -3,6 +3,18 @@ All notable changes to this project will be documented in this file.
3
3
  This project adheres to [Semantic Versioning](http://semver.org/).
4
4
  This changelog adheres to [Keep a CHANGELOG](http://keepachangelog.com/).
5
5
 
6
+ ## [3.8.0]
7
+ ### Added
8
+ - [DC-1794] Update httparty to allow caching the whole response, also add namespace to cache key
9
+ - [DC-1418] Port NRMA portal availability cache back to EcomEngine
10
+ - [TT-4850] Added client templates
11
+ - [DC-1692] Fix error that can be thrown when checking if a product configuration can be priced
12
+ - [TT-6246] Remove Booking.delete_reservations method
13
+
14
+ ### Changed
15
+ - [DC-2997] Remove API key from body, and move it to header
16
+ - [DC-1767] include long/lat changes to Stop
17
+
6
18
  ## [3.7.0]
7
19
  ### Added
8
20
  - [DC-1437] Add relationship accesssor methods
@@ -65,7 +65,7 @@ module QuickTravel
65
65
  def self.all(opts = {})
66
66
  if lookup
67
67
  cache_name = ["#{name}.all-attrs", opts.to_param].reject(&:blank?).join('?')
68
- find_all!("#{api_base}.json", opts.merge(cache: cache_name))
68
+ find_all!("#{api_base}.json", opts.merge(cache_key: cache_name, cache_options: { disable_namespacing: true }))
69
69
  else
70
70
  find_all!("#{api_base}.json", opts)
71
71
  end
@@ -80,10 +80,6 @@ module QuickTravel
80
80
  put_and_validate("#{api_base}/#{id}.json", options)
81
81
  end
82
82
 
83
- def to_hash
84
- instance_values
85
- end
86
-
87
83
  def to_s
88
84
  if defined? @to_s
89
85
  @to_s
@@ -102,20 +98,14 @@ module QuickTravel
102
98
  end
103
99
 
104
100
  def self.find_all!(request_path, opts = {})
105
- response = if opts.key? :cache
106
- QuickTravel::Cache.cache(opts[:cache], opts[:cache_options]) {
107
- get_and_validate(request_path, opts.except(:cache, :cache_options))
108
- }
109
- else
110
- get_and_validate(request_path, opts, return_response_object: true)
111
- end
112
- full_response = response.respond_to? :parsed_response
113
- parsed_response = full_response ? response.parsed_response : response
101
+ response = QuickTravel::Cache.cache(opts[:cache_key], opts[:cache_options]) {
102
+ get_and_validate(request_path, opts.except(:cache_key, :cache_options), return_response_object: true)
103
+ }
114
104
 
115
- deserializer = Deserializer.new(parsed_response)
105
+ deserializer = Deserializer.new(response.parsed_response)
116
106
  objects = Array.wrap(deserializer.extract_under_root(self))
117
107
 
118
- if full_response && response.headers['pagination'].present?
108
+ if response.headers['pagination'].present?
119
109
  pagination_headers = ::JSON.parse(response.headers['pagination'])
120
110
  WillPaginate::Collection.create(pagination_headers['current_page'], pagination_headers['per_page'], pagination_headers['total_entries']) do |pager|
121
111
  pager.replace(objects)
@@ -202,7 +192,11 @@ module QuickTravel
202
192
  end
203
193
 
204
194
  def self.call_and_validate(http_method, path, query = {}, opts = {})
205
- Api.call_and_validate(http_method, path, query, opts)
195
+ response = QuickTravel::Cache.cache(opts[:cache_key], opts[:cache_options]) {
196
+ response_object = Api.call_and_validate(http_method, path, query, opts.except(:cache_key, :cache_options))
197
+ response_object = response_object.parsed_response if !opts[:cache_key] and !opts[:return_response_object]
198
+ response_object
199
+ }
206
200
  end
207
201
 
208
202
  def self.base_uri(uri = nil)
@@ -215,12 +209,11 @@ module QuickTravel
215
209
 
216
210
  def self.call_and_validate(http_method, path, query = {}, opts = {})
217
211
  http_params = opts.clone
218
- return_response_object = http_params.delete(:return_response_object)
219
-
220
212
  # Set default token
221
213
  http_params[:query] ||= FilterQuery.new(query).call
222
214
  http_params[:headers] ||= {}
223
215
  http_params[:headers]['Content-length'] = '0' if http_params[:body].blank?
216
+ http_params[:headers]['x-api-key'] = QuickTravel.config.access_key
224
217
  expect = http_params.delete(:expect)
225
218
 
226
219
  # Use :body instead of :query for put/post.
@@ -230,7 +223,6 @@ module QuickTravel
230
223
  if [:put, :post].include?(http_method.to_sym)
231
224
  http_params[:body].merge!(http_params.delete(:query))
232
225
  end
233
- http_params[:body][:access_key] = QuickTravel.config.access_key
234
226
  http_params[:follow_redirects] = false
235
227
 
236
228
  begin
@@ -256,11 +248,7 @@ module QuickTravel
256
248
 
257
249
  validate!(response)
258
250
 
259
- if return_response_object
260
- response
261
- else
262
- response.parsed_response
263
- end
251
+ response
264
252
  end
265
253
 
266
254
  # Do standard validations on response
@@ -157,10 +157,6 @@ module QuickTravel
157
157
  reserve(:packages, options)
158
158
  end
159
159
 
160
- def delete_reservations
161
- delete_and_validate("#{api_base}/#{@id}/reservations")
162
- end
163
-
164
160
  # Delete a reservation
165
161
  #
166
162
  # Returns current booking object after deleting the reservation
@@ -6,7 +6,10 @@ module QuickTravel
6
6
  end
7
7
  end
8
8
 
9
- def self.cache(key, cache_options = {})
9
+ def self.cache(key, cache_options = nil)
10
+ return yield unless key.present?
11
+ cache_options ||= {}
12
+ key = "#{@@namespace}_#{key}" unless cache_options[:disable_namespacing]
10
13
  cached_value = cache_store.read(key)
11
14
  return cached_value unless cached_value.nil?
12
15
  return nil unless block_given?
@@ -15,7 +18,8 @@ module QuickTravel
15
18
  yield.tap { |value| cache_store.write(key, value, cache_options) }
16
19
  end
17
20
 
18
- def self.delete(key)
21
+ def self.delete(key, namespace = true)
22
+ key = "#{@@namespace}_#{key}" if namespace
19
23
  cache_store.delete(key)
20
24
  end
21
25
 
@@ -27,8 +31,16 @@ module QuickTravel
27
31
  @@cache_store
28
32
  end
29
33
 
30
- def self.cache_store=(store)
31
- @@cache_store = store
34
+ def self.cache_store=(session)
35
+ @@cache_store = session
36
+ end
37
+
38
+ def self.namespace
39
+ @@namespace
40
+ end
41
+
42
+ def self.namespace=(namespace)
43
+ @@namespace = namespace
32
44
  end
33
45
  end
34
46
  end
@@ -46,7 +46,8 @@ module QuickTravel
46
46
  # TODO Move to an external builder?
47
47
  def self.attributes_for
48
48
  attrs = yield
49
- attrs[:completed] = attrs['progress'] == 'completed' || attrs['successful']
49
+ attrs[:completed] = attrs['progress'] == 'completed'
50
+ attrs[:completed] = attrs['successful'] if attrs['successful'].present?
50
51
  attrs[:successful] = attrs[:completed]
51
52
  attrs
52
53
  rescue AdapterError => e
@@ -1,7 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'quick_travel/adapter'
1
4
  require 'quick_travel/init_from_hash'
2
5
 
3
6
  module QuickTravel
4
- class Client
7
+ class Client < Adapter
5
8
  include QuickTravel::InitFromHash
9
+ self.api_base = '/api/clients'
10
+
11
+ def templates
12
+ get_and_validate("/api/clients/#{id}/templates")
13
+ end
6
14
  end
7
15
  end
@@ -28,6 +28,10 @@ module QuickTravel
28
28
  end
29
29
  end
30
30
  end
31
+
32
+ def to_hash
33
+ instance_values
34
+ end
31
35
  end
32
36
 
33
37
  class Parser
@@ -31,7 +31,7 @@ module QuickTravel
31
31
  end
32
32
 
33
33
  def priced?
34
- @product.pricing_details.present?
34
+ @product.try(:pricing_details).present?
35
35
  end
36
36
 
37
37
  def price
@@ -7,13 +7,13 @@ module QuickTravel
7
7
  bookable || exception_type == 'inventory'
8
8
  end
9
9
 
10
- def self.find(search_params = {})
11
- find_for_type(@reservation_for_type, search_params)
10
+ def self.find(search_params = {}, opts = {})
11
+ find_for_type(@reservation_for_type, search_params, opts)
12
12
  end
13
13
 
14
- def self.find_for_type(type, search_params = {})
14
+ def self.find_for_type(type, search_params = {}, opts = {})
15
15
  url = "/reservation_for/#{type}/find_services_for.json"
16
- product_maps = post_and_validate(url, search_params)
16
+ product_maps = post_and_validate(url, search_params, opts)
17
17
  product_maps.map { |product_map| new(product_map) }
18
18
  end
19
19
  end
@@ -42,7 +42,7 @@ module QuickTravel
42
42
  passenger_type_count = {}
43
43
  if passenger_splits.present?
44
44
  passenger_splits.each do |p|
45
- passenger = booking.find_passenger_by_id(p['consumer_id'])
45
+ passenger = booking.find_passenger_by_id(p.consumer_id)
46
46
 
47
47
  if passenger.present?
48
48
  passenger_type_count[passenger.passenger_type_id] ||= 0
@@ -13,7 +13,7 @@ module QuickTravel
13
13
 
14
14
  def self.all_with_price(opts)
15
15
  cache_key = GenerateCacheKey.new(name, opts).call
16
- find_all!("/api/resources/index_with_price.json", opts.merge(cache: cache_key))
16
+ find_all!("/api/resources/index_with_price.json", opts.merge(cache_key: cache_key))
17
17
  end
18
18
 
19
19
  def product_type
@@ -17,7 +17,7 @@ module QuickTravel
17
17
  # All routes for a given product type
18
18
  def self.all(product_type_id)
19
19
  find_all!("/product_types/#{product_type_id}/routes.json",
20
- cache: "QuickTravel::Route.all-#{product_type_id}-attrs")
20
+ cache_key: "QuickTravel::Route.all-#{product_type_id}-attrs")
21
21
  end
22
22
 
23
23
  def self.find(routes_list, route_id)
@@ -5,7 +5,14 @@ module QuickTravel
5
5
  include QuickTravel::InitFromHash
6
6
 
7
7
  def stop
8
- Stop.new({ id: stop_id, name: name, code: code, address: address })
8
+ Stop.new({
9
+ id: stop_id,
10
+ name: name,
11
+ code: code,
12
+ address: address,
13
+ longitude: longitude,
14
+ latitude: latitude
15
+ })
9
16
  end
10
17
  end
11
18
 
@@ -1,3 +1,3 @@
1
1
  module QuickTravel
2
- VERSION = '3.7.0'
2
+ VERSION = '3.8.0'
3
3
  end
@@ -16,7 +16,7 @@ Gem::Specification.new do |spec|
16
16
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
17
17
  spec.require_paths = ['lib']
18
18
 
19
- spec.add_dependency 'httparty', '0.15.7' # Bug in >16 relating to nested parameters
19
+ spec.add_dependency 'httparty', '~> 0.17'
20
20
  spec.add_dependency 'json'
21
21
  spec.add_dependency 'activesupport', '>= 2.0.0'
22
22
  spec.add_dependency 'facets'
@@ -2,7 +2,7 @@ require 'spec_helper'
2
2
  require 'quick_travel/adapter'
3
3
 
4
4
  describe QuickTravel::Adapter do
5
- let(:response) { double code: 200, parsed_response: parsed_response }
5
+ let(:response) { double code: 200, parsed_response: parsed_response, headers: {} }
6
6
  let(:parsed_response) { { test: true } }
7
7
 
8
8
  before do
@@ -26,8 +26,7 @@ describe QuickTravel::Adapter do
26
26
  let(:expected_body) {
27
27
  {
28
28
  test: true,
29
- sub_hash: { id: 42 },
30
- access_key: an_instance_of(String)
29
+ sub_hash: { id: 42 }
31
30
  }
32
31
  }
33
32
 
@@ -52,4 +51,36 @@ describe QuickTravel::Adapter do
52
51
  )
53
52
  end
54
53
  end
54
+
55
+ context 'when cache options present' do
56
+ subject(:all) do
57
+ QuickTravel::Adapter.call_and_validate(:get, 'some_path', {}, { cache_key: 'test_key', cache_options: { expires_in: 3.minutes } })
58
+ end
59
+ let(:api) { double }
60
+
61
+ before do
62
+ QuickTravel::Cache.cache_store.clear
63
+ stub_const('QuickTravel::Api', api)
64
+ allow(api).to receive(:call_and_validate) { [{id: 1}, {id: 2}] }
65
+ all
66
+ end
67
+
68
+ specify { expect(api).to have_received(:call_and_validate).once }
69
+
70
+ context 'when called again' do
71
+ before do
72
+ QuickTravel::Adapter.call_and_validate(:get, 'some_path', {}, { cache_key: 'test_key', cache_options: { expires_in: 3.minutes } })
73
+ end
74
+
75
+ specify { expect(api).to have_received(:call_and_validate).once } # not called again
76
+ end
77
+
78
+ context 'when called with different key' do
79
+ before do
80
+ QuickTravel::Adapter.call_and_validate(:get, 'some_path', {}, { cache_key: 'test_key1', cache_options: { expires_in: 3.minutes } })
81
+ end
82
+
83
+ specify { expect(api).to have_received(:call_and_validate).twice }
84
+ end
85
+ end
55
86
  end
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+ require 'quick_travel/client'
5
+
6
+ describe QuickTravel::Client do
7
+ context '#find' do
8
+ let(:templates) do
9
+ VCR.use_cassette('client_templates') do
10
+ QuickTravel::Client.find(2).templates
11
+ end
12
+ end
13
+ it 'should find the templates correctly' do
14
+ expect(templates['vehicle_templates']).to eq([
15
+ {
16
+ 'id' => 1,
17
+ 'length' => 5.0,
18
+ 'height' => 1.5,
19
+ 'width' => 1.8,
20
+ 'weight' => 1000.0,
21
+ 'details' => 'Holden Commodore',
22
+ 'registration' => 'ABC123',
23
+ 'cargo' => 'None',
24
+ 'vehicle_type_id' => 1,
25
+ 'party_id' => 9
26
+ }
27
+ ])
28
+ expect(templates['passenger_templates']).to eq([
29
+ {
30
+ 'id' => 1,
31
+ 'age' => 30,
32
+ 'title' => 'Mr',
33
+ 'first_name' => 'Homer',
34
+ 'last_name' => 'Simpson',
35
+ 'gender' => 'Male',
36
+ 'passenger_type_id' => 1,
37
+ 'party_id' => 9
38
+ }
39
+ ])
40
+ end
41
+ end
42
+ end
@@ -39,7 +39,7 @@ describe QuickTravel::PassengerType do
39
39
 
40
40
  before do
41
41
  stub_const('QuickTravel::Api', api)
42
- allow(api).to receive(:call_and_validate) { [{id: 1}, {id: 2}] }
42
+ allow(api).to receive(:call_and_validate) { double(parsed_response: [{id: 1}, {id: 2}], headers: {}) }
43
43
  end
44
44
 
45
45
  context 'when called the first time' do
@@ -127,6 +127,17 @@ describe QuickTravel::ProductConfiguration do
127
127
  let(:pricing_details) { nil }
128
128
  it { is_expected.not_to be_priced }
129
129
  end
130
+
131
+ context 'when pricing details are omitted' do
132
+ let(:product) do
133
+ double(
134
+ extras: extras,
135
+ available?: available
136
+ )
137
+ end
138
+
139
+ it { is_expected.not_to be_priced }
140
+ end
130
141
  end
131
142
 
132
143
  context '#price' do
@@ -48,3 +48,23 @@ describe QuickTravel::Reservation do
48
48
  expect(@reservation.gross_including_packaged_item).to be_an_instance_of Money
49
49
  end
50
50
  end
51
+
52
+ describe QuickTravel::Reservation do
53
+ before(:each) do
54
+ VCR.use_cassette('reservation_with_extra_picks') do
55
+ @booking = QuickTravel::Booking.find(1)
56
+ @reservation = @booking.reservations.first
57
+ end
58
+ end
59
+
60
+ it 'should convert hash to objects' do
61
+ expect(@reservation.passenger_splits.first).to be_an_instance_of QuickTravel::PassengerSplit
62
+ end
63
+
64
+ let(:test_type) { double(name: 'test') }
65
+
66
+ it 'should not raise error in passenger count' do
67
+ allow(QuickTravel::PassengerType).to receive(:find).and_return(test_type)
68
+ expect{ @reservation.passengers_count(@booking) }.not_to raise_error
69
+ end
70
+ end