rthbound-suitcase 1.7.1

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.
Files changed (45) hide show
  1. data/.gitignore +4 -0
  2. data/CHANGELOG.md +17 -0
  3. data/Gemfile +3 -0
  4. data/README.md +83 -0
  5. data/Rakefile +13 -0
  6. data/examples/hash_adapter.rb +15 -0
  7. data/examples/hotel_image_db.rb +24 -0
  8. data/examples/redis_adapter.rb +29 -0
  9. data/lib/suitcase.rb +16 -0
  10. data/lib/suitcase/car_rental.rb +57 -0
  11. data/lib/suitcase/codes.rb +5 -0
  12. data/lib/suitcase/configuration.rb +29 -0
  13. data/lib/suitcase/core_ext/string.rb +13 -0
  14. data/lib/suitcase/hotel.rb +355 -0
  15. data/lib/suitcase/hotel/amenity.rb +46 -0
  16. data/lib/suitcase/hotel/bed_type.rb +21 -0
  17. data/lib/suitcase/hotel/cache.rb +52 -0
  18. data/lib/suitcase/hotel/ean_exception.rb +35 -0
  19. data/lib/suitcase/hotel/helpers.rb +198 -0
  20. data/lib/suitcase/hotel/image.rb +19 -0
  21. data/lib/suitcase/hotel/location.rb +67 -0
  22. data/lib/suitcase/hotel/nightly_rate.rb +14 -0
  23. data/lib/suitcase/hotel/payment_option.rb +41 -0
  24. data/lib/suitcase/hotel/reservation.rb +15 -0
  25. data/lib/suitcase/hotel/room.rb +138 -0
  26. data/lib/suitcase/hotel/session.rb +7 -0
  27. data/lib/suitcase/hotel/surcharge.rb +23 -0
  28. data/lib/suitcase/version.rb +3 -0
  29. data/rthbound-suitcase.gemspec +30 -0
  30. data/test/car_rentals/car_rental_test.rb +30 -0
  31. data/test/hotels/amenity_test.rb +23 -0
  32. data/test/hotels/caching_test.rb +42 -0
  33. data/test/hotels/ean_exception_test.rb +24 -0
  34. data/test/hotels/helpers_test.rb +52 -0
  35. data/test/hotels/hotel_location_test.rb +23 -0
  36. data/test/hotels/hotel_test.rb +112 -0
  37. data/test/hotels/image_test.rb +20 -0
  38. data/test/hotels/payment_option_test.rb +15 -0
  39. data/test/hotels/reservation_test.rb +15 -0
  40. data/test/hotels/room_test.rb +50 -0
  41. data/test/hotels/session_test.rb +14 -0
  42. data/test/keys.rb +43 -0
  43. data/test/minitest_helper.rb +29 -0
  44. data/test/support/fake_response.rb +13 -0
  45. metadata +220 -0
@@ -0,0 +1,23 @@
1
+ require "minitest_helper"
2
+
3
+ describe Suitcase::Hotel::Location do
4
+ before :each do
5
+ @location = Suitcase::Hotel::Location.new({})
6
+ end
7
+
8
+ [:destination_id, :province, :country, :country_code, :city, :type,
9
+ :active].each do |accessor|
10
+ it "has an accessor for #{accessor}" do
11
+ @location.must_respond_to(accessor)
12
+ @location.must_respond_to((accessor.to_s + "=").to_sym)
13
+ end
14
+ end
15
+
16
+ describe ".find" do
17
+ it "returns an Array of Locations" do
18
+ locations = Suitcase::Hotel::Location.find(destination_string: "Lond")
19
+ locations.must_be_kind_of(Array)
20
+ locations.first.must_be_kind_of(Suitcase::Hotel::Location)
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,112 @@
1
+ require "minitest_helper"
2
+
3
+ describe Suitcase::Hotel do
4
+ before :each do
5
+ @hotel = Suitcase::Hotel.find(id: 123904)
6
+ end
7
+
8
+ [:id, :name, :address, :city, :amenities, :masked_amenities, :country_code,
9
+ :high_rate, :low_rate, :longitude, :latitude, :rating, :postal_code,
10
+ :images, :nightly_rate_total, :property_description, :number_of_floors,
11
+ :number_of_rooms, :deep_link, :tripadvisor_rating].each do |attribute|
12
+ it "has an attr_accessor for #{attribute}" do
13
+ @hotel.must_respond_to(attribute)
14
+ @hotel.must_respond_to((attribute.to_s + "=").to_sym)
15
+ end
16
+ end
17
+
18
+ describe ".find" do
19
+ it "returns a single Hotel if passed an ID" do
20
+ @hotel.must_be_kind_of(Suitcase::Hotel)
21
+ end
22
+
23
+ it "returns multiple Hotels if a location is passed in" do
24
+ hotels = Suitcase::Hotel.find(location: "London, UK")
25
+ hotels.must_be_kind_of(Array)
26
+ hotels.first.must_be_kind_of(Suitcase::Hotel)
27
+ end
28
+
29
+ it "returns multiple Hotels if a destination ID is passed in" do
30
+ hotels = Suitcase::Hotel.find(destination_id: "58870F43-9215-4662-BAA1-CC9A20FEC4F1")
31
+ hotels.must_be_kind_of(Array)
32
+ hotels.first.must_be_kind_of(Suitcase::Hotel)
33
+ end
34
+
35
+ it "returns multiple Hotels if multiple ID's are passed in" do
36
+ hotels = Suitcase::Hotel.find(ids: [123904, 191937, 220166])
37
+ hotels.must_be_kind_of(Array)
38
+ hotels.first.must_be_kind_of(Suitcase::Hotel)
39
+ end
40
+
41
+ it "returns an Array with a single Hotel if an Array with a single ID is passed in" do
42
+ hotels = Suitcase::Hotel.find(ids: [123904])
43
+ hotels.count.must_equal(1)
44
+ hotels.first.must_be_kind_of(Suitcase::Hotel)
45
+ end
46
+
47
+ it "sets a recovery attribute on the raised error when the location is not specific enough" do
48
+ begin
49
+ Suitcase::Hotel.find(location: "Mexico")
50
+ rescue Suitcase::Hotel::EANException => e
51
+ e.recoverable?.must_equal(true) if e.type == :multiple_locations
52
+ end
53
+ end
54
+
55
+ it "sets the error type when the location is not specific enough" do
56
+ begin
57
+ Suitcase::Hotel.find(location: "Mexico")
58
+ rescue Suitcase::Hotel::EANException => e
59
+ e.type.must_equal(:multiple_locations)
60
+ e.recovery.must_be_kind_of(Hash)
61
+ e.recovery[:alternate_locations].must_be_kind_of(Array)
62
+ e.recovery[:alternate_locations].first.must_be_kind_of(Suitcase::Hotel::Location)
63
+ end
64
+ end
65
+ end
66
+
67
+ describe "#images" do
68
+ it "correctly gets the URLs of the images" do
69
+ images = @hotel.images
70
+ images.must_be_kind_of(Array)
71
+ images.map { |image| URI.parse(image.url) }
72
+ end
73
+ end
74
+
75
+ describe "#thumbnail_url" do
76
+ it "returns the first image's thumbnail URL" do
77
+ @hotel.thumbnail_url.must_equal @hotel.images.first.thumbnail_url
78
+ end
79
+ end
80
+
81
+ describe "#rooms" do
82
+ before do
83
+ @info = {
84
+ arrival: "1/1/2013",
85
+ departure: "1/8/2013"
86
+ }
87
+ @rooms = @hotel.rooms(@info)
88
+ end
89
+
90
+ it "returns an Array of available Rooms" do
91
+ @rooms.must_be_kind_of(Array)
92
+ end
93
+
94
+ it "each room must contain a cancellation policy" do
95
+ @rooms.each do |r|
96
+ r.cancellation_policy.wont_be_nil
97
+ end
98
+ end
99
+
100
+ it "each room must contain the non_refundable option" do
101
+ @rooms.each do |r|
102
+ r.non_refundable.wont_be_nil
103
+ end
104
+ end
105
+
106
+ it "each room must contain the deposit_required" do
107
+ @rooms.each do |r|
108
+ r.deposit_required.wont_be_nil
109
+ end
110
+ end
111
+ end
112
+ end
@@ -0,0 +1,20 @@
1
+ require "minitest_helper"
2
+
3
+ describe Suitcase::Image do
4
+ before :each do
5
+ @image = Suitcase::Hotel.find(id: 123904).images.first
6
+ end
7
+
8
+ [:url, :id, :caption, :height, :width, :thumbnail_url, :name].each do |meth|
9
+ it "has an accessor for #{meth}" do
10
+ @image.must_respond_to(meth)
11
+ @image.must_respond_to((meth.to_s + "=").to_sym)
12
+ end
13
+ end
14
+
15
+ describe "#url" do
16
+ it "returns a valid URL" do
17
+ URI.parse(@image.url).must_be_kind_of(URI)
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,15 @@
1
+ require "minitest_helper"
2
+
3
+ describe Suitcase::Hotel::PaymentOption do
4
+ before :each do
5
+ @info = { currency_code: "USD" }
6
+ end
7
+
8
+ describe ".find" do
9
+ it "returns an Array of PaymentOption's" do
10
+ options = Suitcase::Hotel::PaymentOption.find(@info)
11
+ options.must_be_kind_of(Array)
12
+ options.first.must_be_kind_of(Suitcase::Hotel::PaymentOption)
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,15 @@
1
+ require "minitest_helper"
2
+
3
+ describe Suitcase::Hotel::Reservation do
4
+ before :each do
5
+ @reservation = Suitcase::Hotel::Reservation.new({})
6
+ end
7
+
8
+ it "has a reader for itinerary_id" do
9
+ @reservation.must_respond_to :itinerary_id
10
+ end
11
+
12
+ it "has a reader for confirmation_numbers" do
13
+ @reservation.must_respond_to :confirmation_numbers
14
+ end
15
+ end
@@ -0,0 +1,50 @@
1
+ require "minitest_helper"
2
+
3
+ describe Suitcase::Hotel::Room do
4
+ before :each do
5
+ @room = Suitcase::Hotel.find(id: 123904).rooms(arrival: Keys::RESERVATION_START_TIME, departure: Keys::RESERVATION_END_TIME).first
6
+ end
7
+
8
+ %w(arrival departure rate_code room_type_code supplier_type tax_rate
9
+ non_refundable occupancy quoted_occupancy min_guest_age total surcharge_total
10
+ average_base_rate average_base_rate average_rate max_nightly_rate
11
+ currency_code value_adds room_type_description price_breakdown total_price
12
+ average_nightly_rate promo rate_key hotel_id supplier_type bed_types
13
+ rooms).each do |attribute|
14
+ it "has an attr_accessor for #{attribute}" do
15
+ @room.must_respond_to attribute.to_sym
16
+ @room.must_respond_to (attribute + "=").to_sym
17
+ end
18
+ end
19
+
20
+ describe "#reserve!" do
21
+ before :each do
22
+ @info = { email: Keys::SENDING_EMAIL,
23
+ first_name: "Walter",
24
+ last_name: "Nelson",
25
+ home_phone: "3831039402",
26
+ payment_option: Keys::SUITCASE_PAYMENT_OPTION, # Visa
27
+ credit_card_number: Keys::CREDIT_CARD_NUMBER_TESTING,
28
+ credit_card_verification_code: Keys::CREDIT_CARD_CVV_TESTING, # CVV
29
+ credit_card_expiration_date: Keys::CREDIT_CARD_EXPIRATION_DATE_TESTING,
30
+ address1: "travelnow", # for testing
31
+ address2: "Apt. 4A",
32
+ city: "Boston",
33
+ province: "MA",
34
+ country: "US",
35
+ postal_code: "02111" }
36
+ @room.rooms[0][:bed_type] = @room.bed_types[0]
37
+ @room.rooms[0][:smoking_preference] = "NS"
38
+ end
39
+
40
+ it "returns a Suitcase::Reservation" do
41
+ reservation = @room.reserve!(@info)
42
+ reservation.must_be_kind_of(Suitcase::Hotel::Reservation)
43
+ end
44
+
45
+ it "raises errors on invalid info" do
46
+ lambda { @room.reserve!(@info.merge(credit_card_number: "")) }.must_raise Suitcase::Hotel::EANException
47
+ end
48
+ end
49
+ end
50
+
@@ -0,0 +1,14 @@
1
+ require "minitest_helper"
2
+
3
+ describe Suitcase::Hotel::Session do
4
+ before :each do
5
+ @session = Suitcase::Hotel::Session.new
6
+ end
7
+
8
+ [:id, :ip_address, :user_agent, :locale, :currency_code].each do |accessor|
9
+ it "has an accessor for #{accessor}" do
10
+ @session.must_respond_to(accessor)
11
+ @session.must_respond_to((accessor.to_s + "=").to_sym)
12
+ end
13
+ end
14
+ end
data/test/keys.rb ADDED
@@ -0,0 +1,43 @@
1
+ # Suitcase::Configuration.hotel_api_key = "your_api_key_here"
2
+ # Suitcase::Configuration.hotel_cid = "your_cid_here"
3
+ # Suitcase::Configuration.hotel_shared_secret = "your_shared_secret_here"
4
+ # Suitcase::Configuration.use_signature_auth = true
5
+
6
+ # Or configure with a block:
7
+
8
+ Suitcase.configure do |config|
9
+ config.hotel_api_key = ""
10
+ config.hotel_cid = ""
11
+
12
+ config.hotwire_api_key = ""
13
+ # config.hotel_shared_secret = "none"
14
+ # config.use_signature_auth = false
15
+ end
16
+
17
+ module Keys
18
+ RESERVATION_START_TIME = Chronic.parse("1 week from now").strftime("%m/%d/%Y")
19
+ RESERVATION_END_TIME = Chronic.parse("2 weeks from now").strftime("%m/%d/%Y")
20
+
21
+ SUITCASE_PAYMENT_OPTION = Suitcase::Hotel::PaymentOption.find(currency_code: "USD").find { |po| po.name =~ /Master/ }
22
+ CREDIT_CARD_NUMBER_TESTING = "5401999999999999"
23
+ CREDIT_CARD_CVV_TESTING = "123"
24
+ CREDIT_CARD_EXPIRATION_DATE_TESTING = "2014/03/01"
25
+
26
+ SENDING_EMAIL = "testemail@gmail.com"
27
+
28
+ VALID_RESERVATION_INFO = {
29
+ email: "testemail@gmail.com",
30
+ first_name: "Test Booking",
31
+ last_name: "Test Booking",
32
+ home_phone: "1231231234",
33
+ payment_option: SUITCASE_PAYMENT_OPTION,
34
+ credit_card_number: CREDIT_CARD_NUMBER_TESTING,
35
+ credit_card_verification_code: CREDIT_CARD_CVV_TESTING,
36
+ credit_card_expiration_date: CREDIT_CARD_EXPIRATION_DATE_TESTING,
37
+ address1: "travelnow",
38
+ city: "Boston",
39
+ province: "MA",
40
+ country: "US",
41
+ postal_code: "01234",
42
+ }
43
+ end
@@ -0,0 +1,29 @@
1
+ # Testing frameworks
2
+ require "turn"
3
+ require "minitest/spec"
4
+ require "minitest/autorun"
5
+ require "mocha"
6
+
7
+ # For making sure the dates will be valid
8
+ require "chronic"
9
+
10
+ # Debugger
11
+ require "pry"
12
+
13
+ # The gem
14
+ $: << File.dirname(__FILE__) + "/../lib"
15
+ $: << File.dirname(__FILE__)
16
+ require "suitcase"
17
+
18
+ # API keys
19
+ require "keys"
20
+
21
+ # Support files
22
+ require "support/fake_response"
23
+
24
+ # Turn configuration
25
+ Turn.config do |config|
26
+ config.format = :pretty
27
+ # config.trace = true
28
+ config.natural = true
29
+ end
@@ -0,0 +1,13 @@
1
+ class FakeResponse
2
+ def initialize(options = {})
3
+ options.each { |k, v| instance_variable_set("@#{k}", v) }
4
+ end
5
+
6
+ def method_missing(meth, *args, &blk)
7
+ if args.empty?
8
+ instance_variable_get("@#{meth}")
9
+ else
10
+ super
11
+ end
12
+ end
13
+ end
metadata ADDED
@@ -0,0 +1,220 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rthbound-suitcase
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.7.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Walter Nelson
9
+ - Tad Hosford
10
+ autorequire:
11
+ bindir: bin
12
+ cert_chain: []
13
+ date: 2012-09-08 00:00:00.000000000 Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: minitest
17
+ requirement: !ruby/object:Gem::Requirement
18
+ none: false
19
+ requirements:
20
+ - - ! '>='
21
+ - !ruby/object:Gem::Version
22
+ version: '0'
23
+ type: :development
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ none: false
27
+ requirements:
28
+ - - ! '>='
29
+ - !ruby/object:Gem::Version
30
+ version: '0'
31
+ - !ruby/object:Gem::Dependency
32
+ name: mocha
33
+ requirement: !ruby/object:Gem::Requirement
34
+ none: false
35
+ requirements:
36
+ - - ! '>='
37
+ - !ruby/object:Gem::Version
38
+ version: '0'
39
+ type: :development
40
+ prerelease: false
41
+ version_requirements: !ruby/object:Gem::Requirement
42
+ none: false
43
+ requirements:
44
+ - - ! '>='
45
+ - !ruby/object:Gem::Version
46
+ version: '0'
47
+ - !ruby/object:Gem::Dependency
48
+ name: turn
49
+ requirement: !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ! '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ type: :development
56
+ prerelease: false
57
+ version_requirements: !ruby/object:Gem::Requirement
58
+ none: false
59
+ requirements:
60
+ - - ! '>='
61
+ - !ruby/object:Gem::Version
62
+ version: '0'
63
+ - !ruby/object:Gem::Dependency
64
+ name: chronic
65
+ requirement: !ruby/object:Gem::Requirement
66
+ none: false
67
+ requirements:
68
+ - - ! '>='
69
+ - !ruby/object:Gem::Version
70
+ version: '0'
71
+ type: :development
72
+ prerelease: false
73
+ version_requirements: !ruby/object:Gem::Requirement
74
+ none: false
75
+ requirements:
76
+ - - ! '>='
77
+ - !ruby/object:Gem::Version
78
+ version: '0'
79
+ - !ruby/object:Gem::Dependency
80
+ name: rake
81
+ requirement: !ruby/object:Gem::Requirement
82
+ none: false
83
+ requirements:
84
+ - - ! '>='
85
+ - !ruby/object:Gem::Version
86
+ version: '0'
87
+ type: :development
88
+ prerelease: false
89
+ version_requirements: !ruby/object:Gem::Requirement
90
+ none: false
91
+ requirements:
92
+ - - ! '>='
93
+ - !ruby/object:Gem::Version
94
+ version: '0'
95
+ - !ruby/object:Gem::Dependency
96
+ name: pry
97
+ requirement: !ruby/object:Gem::Requirement
98
+ none: false
99
+ requirements:
100
+ - - ! '>='
101
+ - !ruby/object:Gem::Version
102
+ version: '0'
103
+ type: :development
104
+ prerelease: false
105
+ version_requirements: !ruby/object:Gem::Requirement
106
+ none: false
107
+ requirements:
108
+ - - ! '>='
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: json
113
+ requirement: !ruby/object:Gem::Requirement
114
+ none: false
115
+ requirements:
116
+ - - ! '>='
117
+ - !ruby/object:Gem::Version
118
+ version: '0'
119
+ type: :runtime
120
+ prerelease: false
121
+ version_requirements: !ruby/object:Gem::Requirement
122
+ none: false
123
+ requirements:
124
+ - - ! '>='
125
+ - !ruby/object:Gem::Version
126
+ version: '0'
127
+ - !ruby/object:Gem::Dependency
128
+ name: patron
129
+ requirement: !ruby/object:Gem::Requirement
130
+ none: false
131
+ requirements:
132
+ - - ! '>='
133
+ - !ruby/object:Gem::Version
134
+ version: '0'
135
+ type: :runtime
136
+ prerelease: false
137
+ version_requirements: !ruby/object:Gem::Requirement
138
+ none: false
139
+ requirements:
140
+ - - ! '>='
141
+ - !ruby/object:Gem::Version
142
+ version: '0'
143
+ description: Ruby library that utilizes the EAN (Expedia.com) API for locating available
144
+ hotels and the Hotwire API for rental cars.
145
+ email:
146
+ - tad@isotope11.com
147
+ executables: []
148
+ extensions: []
149
+ extra_rdoc_files: []
150
+ files:
151
+ - .gitignore
152
+ - CHANGELOG.md
153
+ - Gemfile
154
+ - README.md
155
+ - Rakefile
156
+ - examples/hash_adapter.rb
157
+ - examples/hotel_image_db.rb
158
+ - examples/redis_adapter.rb
159
+ - lib/suitcase.rb
160
+ - lib/suitcase/car_rental.rb
161
+ - lib/suitcase/codes.rb
162
+ - lib/suitcase/configuration.rb
163
+ - lib/suitcase/core_ext/string.rb
164
+ - lib/suitcase/hotel.rb
165
+ - lib/suitcase/hotel/amenity.rb
166
+ - lib/suitcase/hotel/bed_type.rb
167
+ - lib/suitcase/hotel/cache.rb
168
+ - lib/suitcase/hotel/ean_exception.rb
169
+ - lib/suitcase/hotel/helpers.rb
170
+ - lib/suitcase/hotel/image.rb
171
+ - lib/suitcase/hotel/location.rb
172
+ - lib/suitcase/hotel/nightly_rate.rb
173
+ - lib/suitcase/hotel/payment_option.rb
174
+ - lib/suitcase/hotel/reservation.rb
175
+ - lib/suitcase/hotel/room.rb
176
+ - lib/suitcase/hotel/session.rb
177
+ - lib/suitcase/hotel/surcharge.rb
178
+ - lib/suitcase/version.rb
179
+ - rthbound-suitcase.gemspec
180
+ - test/car_rentals/car_rental_test.rb
181
+ - test/hotels/amenity_test.rb
182
+ - test/hotels/caching_test.rb
183
+ - test/hotels/ean_exception_test.rb
184
+ - test/hotels/helpers_test.rb
185
+ - test/hotels/hotel_location_test.rb
186
+ - test/hotels/hotel_test.rb
187
+ - test/hotels/image_test.rb
188
+ - test/hotels/payment_option_test.rb
189
+ - test/hotels/reservation_test.rb
190
+ - test/hotels/room_test.rb
191
+ - test/hotels/session_test.rb
192
+ - test/keys.rb
193
+ - test/minitest_helper.rb
194
+ - test/support/fake_response.rb
195
+ homepage: http://github.com/rthbound/suitcase
196
+ licenses: []
197
+ post_install_message:
198
+ rdoc_options: []
199
+ require_paths:
200
+ - lib
201
+ required_ruby_version: !ruby/object:Gem::Requirement
202
+ none: false
203
+ requirements:
204
+ - - ! '>='
205
+ - !ruby/object:Gem::Version
206
+ version: '0'
207
+ required_rubygems_version: !ruby/object:Gem::Requirement
208
+ none: false
209
+ requirements:
210
+ - - ! '>='
211
+ - !ruby/object:Gem::Version
212
+ version: '0'
213
+ requirements: []
214
+ rubyforge_project:
215
+ rubygems_version: 1.8.24
216
+ signing_key:
217
+ specification_version: 3
218
+ summary: Locates available hotels and rental cars through Expedia and Hotwire. This
219
+ is a fork of Walter Nelson's gem - suitcase
220
+ test_files: []