rthbound-suitcase 1.7.1

Sign up to get free protection for your applications and to get access to all the features.
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: []