vrbo 1.1.0 → 2.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rspec +2 -0
- data/README.md +13 -22
- data/Rakefile +6 -7
- data/lib/vrbo.rb +5 -6
- data/lib/vrbo/availability.rb +1 -1
- data/lib/vrbo/calendar.rb +32 -31
- data/lib/vrbo/configuration.rb +1 -1
- data/lib/vrbo/version.rb +1 -1
- data/spec/fixtures/vcr_cassettes/293021.yml +247 -0
- data/spec/spec_helper.rb +105 -0
- data/spec/vrbo/availability_spec.rb +57 -0
- data/spec/vrbo/calendar_spec.rb +151 -0
- data/vrbo.gemspec +4 -0
- metadata +66 -8
- data/lib/vrbo/class_methods.rb +0 -14
- data/test/support/calendar_dates.rb +0 -47
- data/test/vrbo/availability_test.rb +0 -21
- data/test/vrbo/calendar_test.rb +0 -70
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 292464634aa7ba985ef18252adaf0cfc66554524
|
4
|
+
data.tar.gz: b3bd501182bb1ea02ac9d35bee0778013c2a3a74
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4815b659820d192c4f4ef80d05bb3c87b5afdc5ace663ec6fd4449dace169b4862462d6ec7a22aa9179e54488e5644d99274eb582e1ade9b840340b7fee01df6
|
7
|
+
data.tar.gz: df2a0fee297894982bcb946fb6cbc12579eb12014cb1e0fb21a709f486efdf2ffa0fb62085fe737c9407cc14d1653593874a723180c5ed332d389c0b2428d173
|
data/.rspec
ADDED
data/README.md
CHANGED
@@ -5,37 +5,28 @@ scrape this calendar: [http://www.vrbo.com/293021/calendar](http://www.vrbo.com/
|
|
5
5
|
|
6
6
|
## Installation
|
7
7
|
|
8
|
-
Add this line to your application's Gemfile:
|
9
|
-
|
10
|
-
gem 'vrbo'
|
11
|
-
|
12
|
-
And then execute:
|
13
|
-
|
14
|
-
$ bundle
|
15
|
-
|
16
|
-
Or install it yourself as:
|
17
|
-
|
18
8
|
$ gem install vrbo
|
19
9
|
|
20
10
|
## Usage
|
21
11
|
|
22
12
|
If you're just working with one calendar, then you can specify the VRBO calendar id in an initializer:
|
23
13
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
14
|
+
```ruby
|
15
|
+
# config/initializers/vrbo.rb
|
16
|
+
VRBO.configure do |config|
|
17
|
+
config.calendar_id = 293021
|
18
|
+
end
|
19
|
+
```
|
29
20
|
|
30
21
|
Then to lookup available dates and see if a date range is available:
|
31
22
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
23
|
+
```ruby
|
24
|
+
calendar = VRBO::Calendar.new
|
25
|
+
calendar.available?(Date.today, Date.today + 5)
|
26
|
+
#=> true/false
|
27
|
+
calendar.available_dates
|
28
|
+
#=> ["2015-11-03", "2015-11-04", "2015-11-05", ...]
|
29
|
+
```
|
39
30
|
|
40
31
|
## Contributing
|
41
32
|
|
data/Rakefile
CHANGED
@@ -1,9 +1,8 @@
|
|
1
|
-
require '
|
2
|
-
require 'rake'
|
3
|
-
require 'rake/testtask'
|
1
|
+
require 'rspec/core/rake_task'
|
4
2
|
|
5
|
-
|
6
|
-
|
7
|
-
Rake::TestTask.new do |t|
|
8
|
-
t.pattern = 'test/**/*_test.rb'
|
3
|
+
RSpec::Core::RakeTask.new(:spec) do |spec|
|
4
|
+
spec.pattern = 'spec/**/*_spec.rb'
|
9
5
|
end
|
6
|
+
|
7
|
+
desc 'Run specs'
|
8
|
+
task default: :spec
|
data/lib/vrbo.rb
CHANGED
@@ -2,14 +2,10 @@ require 'date'
|
|
2
2
|
require 'uri'
|
3
3
|
require 'net/https'
|
4
4
|
require 'mechanize'
|
5
|
-
|
6
5
|
require 'vrbo/version'
|
7
|
-
require 'vrbo/configuration'
|
8
|
-
require 'vrbo/availability'
|
9
|
-
require 'vrbo/calendar'
|
10
6
|
|
11
7
|
module VRBO
|
12
|
-
|
8
|
+
module_function
|
13
9
|
|
14
10
|
def configure
|
15
11
|
yield config
|
@@ -23,4 +19,7 @@ module VRBO
|
|
23
19
|
@config = nil
|
24
20
|
end
|
25
21
|
|
26
|
-
|
22
|
+
autoload :Configuration, 'vrbo/configuration'
|
23
|
+
autoload :Availability, 'vrbo/availability'
|
24
|
+
autoload :Calendar, 'vrbo/calendar'
|
25
|
+
end
|
data/lib/vrbo/availability.rb
CHANGED
data/lib/vrbo/calendar.rb
CHANGED
@@ -1,19 +1,21 @@
|
|
1
|
-
require 'vrbo/class_methods'
|
2
|
-
|
3
1
|
module VRBO
|
4
2
|
class Calendar
|
5
|
-
extend ClassMethods
|
6
3
|
|
7
|
-
attr_accessor :id, :
|
4
|
+
attr_accessor :id, :days
|
8
5
|
|
9
6
|
def initialize(calendar_id = nil)
|
10
7
|
@id = calendar_id || VRBO.config.calendar_id
|
11
8
|
@days = {}
|
12
|
-
@available_dates =
|
9
|
+
@available_dates = nil
|
10
|
+
end
|
11
|
+
|
12
|
+
def available_dates
|
13
|
+
@available_dates ||= Date.today.upto(Date.today + 365).map { |date| date_if_available(date) }.compact
|
13
14
|
end
|
14
15
|
|
15
|
-
|
16
|
-
|
16
|
+
# @description exclusive, drops day from departure because bookings usually go on per nightly
|
17
|
+
def available?(arrival, depart, dates = nil)
|
18
|
+
dates = dates || available_dates
|
17
19
|
available = dates.any?
|
18
20
|
arrival.upto(depart - 1).each do |date|
|
19
21
|
available = false unless dates.include?(date.to_s)
|
@@ -21,22 +23,17 @@ module VRBO
|
|
21
23
|
available
|
22
24
|
end
|
23
25
|
|
24
|
-
def find_available_dates
|
25
|
-
today = Date.today
|
26
|
-
@available_dates = today.upto(today + 365).map { |date| date_if_available(date) }.compact
|
27
|
-
end
|
28
|
-
|
29
26
|
def url(protocol = 'http')
|
30
27
|
if id
|
31
28
|
"#{protocol}://www.vrbo.com/#{id}/calendar"
|
32
29
|
else
|
33
|
-
|
30
|
+
fail ArgumentError, 'calendar_id is required! You can initialize with a calendar_id or configure the module VRBO'
|
34
31
|
end
|
35
32
|
end
|
36
33
|
|
37
|
-
|
38
|
-
|
39
|
-
|
34
|
+
#
|
35
|
+
# Private
|
36
|
+
#
|
40
37
|
|
41
38
|
def date_if_available(date)
|
42
39
|
m = date.month.to_s
|
@@ -45,24 +42,28 @@ module VRBO
|
|
45
42
|
end
|
46
43
|
|
47
44
|
def collect_days_for_month(date)
|
48
|
-
|
45
|
+
table = calendar.search('.cal-month').at("//b[contains(text(), '#{date.strftime('%B %Y')}')]/following-sibling::table")
|
46
|
+
table.search('td:not(.strike)').map { |cell| cell.children.to_s.strip }
|
47
|
+
rescue => e
|
48
|
+
puts e.class
|
49
|
+
puts e.message
|
50
|
+
puts e.backtrace
|
51
|
+
puts calendar: calendar
|
49
52
|
end
|
50
53
|
|
51
|
-
|
52
|
-
|
53
|
-
end
|
54
|
+
# , retries: 10
|
55
|
+
# collect_days_for_month(date, retries: retries - 1) if table.nil? && retries > 0
|
54
56
|
|
55
57
|
def calendar
|
56
|
-
@calendar ||= agent
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
"//b[contains(text(), '#{date.strftime('%B %Y')}')]/following-sibling::table"
|
58
|
+
@calendar ||= Mechanize.start do |agent|
|
59
|
+
agent.open_timeout = 10
|
60
|
+
agent.read_timeout = 10
|
61
|
+
agent.follow_meta_refresh = true
|
62
|
+
agent.keep_alive = true
|
63
|
+
agent.max_history = 1
|
64
|
+
agent.user_agent_alias = 'Mac Safari'
|
65
|
+
agent.get(url).parser
|
66
|
+
end
|
66
67
|
end
|
67
68
|
end
|
68
|
-
end
|
69
|
+
end
|
data/lib/vrbo/configuration.rb
CHANGED
data/lib/vrbo/version.rb
CHANGED
@@ -0,0 +1,247 @@
|
|
1
|
+
---
|
2
|
+
http_interactions:
|
3
|
+
- request:
|
4
|
+
method: get
|
5
|
+
uri: http://www.vrbo.com/293021/calendar
|
6
|
+
body:
|
7
|
+
encoding: US-ASCII
|
8
|
+
string: ''
|
9
|
+
headers:
|
10
|
+
Accept-Encoding:
|
11
|
+
- gzip,deflate,identity
|
12
|
+
Accept:
|
13
|
+
- '*/*'
|
14
|
+
User-Agent:
|
15
|
+
- Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_2) AppleWebKit/534.51.22 (KHTML,
|
16
|
+
like Gecko) Version/5.1.1 Safari/534.51.22
|
17
|
+
Accept-Charset:
|
18
|
+
- ISO-8859-1,utf-8;q=0.7,*;q=0.7
|
19
|
+
Accept-Language:
|
20
|
+
- en-us,en;q=0.5
|
21
|
+
Host:
|
22
|
+
- www.vrbo.com
|
23
|
+
Connection:
|
24
|
+
- keep-alive
|
25
|
+
Keep-Alive:
|
26
|
+
- 300
|
27
|
+
response:
|
28
|
+
status:
|
29
|
+
code: 200
|
30
|
+
message: OK
|
31
|
+
headers:
|
32
|
+
Server:
|
33
|
+
- nginx
|
34
|
+
Date:
|
35
|
+
- Wed, 04 Nov 2015 02:44:58 GMT
|
36
|
+
Content-Type:
|
37
|
+
- text/html; charset=utf-8
|
38
|
+
Transfer-Encoding:
|
39
|
+
- chunked
|
40
|
+
Connection:
|
41
|
+
- keep-alive
|
42
|
+
Vary:
|
43
|
+
- Accept-Encoding
|
44
|
+
Cache-Control:
|
45
|
+
- private
|
46
|
+
Set-Cookie:
|
47
|
+
- PpcCampaign=; path=/
|
48
|
+
- __RequestVerificationToken=GUOOk32Gm_UNUeaktYp8m1TJSb_b-wgIv-Q_7yYiK_ZzqQmjAt95jnYg6hOTlPsTJ92AUeoQbt7M5tWC_s9cH6IeO7g1;
|
49
|
+
path=/; HttpOnly
|
50
|
+
- hal=ga=0&si=1&ui=0&vi=1&pr=1; expires=Thu, 05-Nov-2015 02:44:58 GMT; path=/
|
51
|
+
- has=311c654d-3316-44e4-8a17-854a00afc4a8; expires=Thu, 05-Nov-2015 02:44:58
|
52
|
+
GMT; path=/
|
53
|
+
- hav=196004f3-753a-410d-96df-7dde37be9bf0; expires=Sat, 04-Nov-2017 01:44:58
|
54
|
+
GMT; path=/
|
55
|
+
- pr_buckets=buckets=vbr%3a1%2cvbq%3a0%2cvbp%3a1%2cvbl%3a1%2cvbz%3a0%2cvbw%3a1%2cvbaa%3a0%2cvbv%3a1%2cvbu%3a0%2cvrbobceheader%3a0%2cvba%3a1%2cvbc%3a1%2cvbg%3a0%2cvbi%3a0%2cvbk%3a0;
|
56
|
+
expires=Wed, 04-Nov-2015 02:49:58 GMT; path=/
|
57
|
+
- pr_groups=forceGroups=; expires=Fri, 04-Dec-2015 02:44:58 GMT; path=/
|
58
|
+
X-Powered-By:
|
59
|
+
- ASP.NET
|
60
|
+
Content-Encoding:
|
61
|
+
- gzip
|
62
|
+
body:
|
63
|
+
encoding: ASCII-8BIT
|
64
|
+
string: !binary |-
|
65
|
+
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
|
245
|
+
http_version:
|
246
|
+
recorded_at: Wed, 04 Nov 2015 02:44:59 GMT
|
247
|
+
recorded_with: VCR 2.9.3
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,105 @@
|
|
1
|
+
# This file was generated by the `rspec --init` command. Conventionally, all
|
2
|
+
# specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
|
3
|
+
# The generated `.rspec` file contains `--require spec_helper` which will cause
|
4
|
+
# this file to always be loaded, without a need to explicitly require it in any
|
5
|
+
# files.
|
6
|
+
#
|
7
|
+
# Given that it is always loaded, you are encouraged to keep this file as
|
8
|
+
# light-weight as possible. Requiring heavyweight dependencies from this file
|
9
|
+
# will add to the boot time of your test suite on EVERY test run, even for an
|
10
|
+
# individual file that may not need all of that loaded. Instead, consider making
|
11
|
+
# a separate helper file that requires the additional dependencies and performs
|
12
|
+
# the additional setup, and require it from the spec files that actually need
|
13
|
+
# it.
|
14
|
+
#
|
15
|
+
# The `.rspec` file also contains a few flags that are not defaults but that
|
16
|
+
# users commonly want.
|
17
|
+
require 'vcr'
|
18
|
+
require 'rspec/its'
|
19
|
+
|
20
|
+
VCR.configure do |config|
|
21
|
+
config.cassette_library_dir = 'spec/fixtures/vcr_cassettes'
|
22
|
+
config.hook_into :webmock
|
23
|
+
end
|
24
|
+
|
25
|
+
require 'vrbo'
|
26
|
+
|
27
|
+
# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
|
28
|
+
RSpec.configure do |config|
|
29
|
+
# rspec-expectations config goes here. You can use an alternate
|
30
|
+
# assertion/expectation library such as wrong or the stdlib/minitest
|
31
|
+
# assertions if you prefer.
|
32
|
+
config.expect_with :rspec do |expectations|
|
33
|
+
# This option will default to `true` in RSpec 4. It makes the `description`
|
34
|
+
# and `failure_message` of custom matchers include text for helper methods
|
35
|
+
# defined using `chain`, e.g.:
|
36
|
+
# be_bigger_than(2).and_smaller_than(4).description
|
37
|
+
# # => "be bigger than 2 and smaller than 4"
|
38
|
+
# ...rather than:
|
39
|
+
# # => "be bigger than 2"
|
40
|
+
expectations.include_chain_clauses_in_custom_matcher_descriptions = true
|
41
|
+
end
|
42
|
+
|
43
|
+
# rspec-mocks config goes here. You can use an alternate test double
|
44
|
+
# library (such as bogus or mocha) by changing the `mock_with` option here.
|
45
|
+
config.mock_with :rspec do |mocks|
|
46
|
+
# Prevents you from mocking or stubbing a method that does not exist on
|
47
|
+
# a real object. This is generally recommended, and will default to
|
48
|
+
# `true` in RSpec 4.
|
49
|
+
mocks.verify_partial_doubles = true
|
50
|
+
end
|
51
|
+
|
52
|
+
# The settings below are suggested to provide a good initial experience
|
53
|
+
# with RSpec, but feel free to customize to your heart's content.
|
54
|
+
=begin
|
55
|
+
# These two settings work together to allow you to limit a spec run
|
56
|
+
# to individual examples or groups you care about by tagging them with
|
57
|
+
# `:focus` metadata. When nothing is tagged with `:focus`, all examples
|
58
|
+
# get run.
|
59
|
+
config.filter_run :focus
|
60
|
+
config.run_all_when_everything_filtered = true
|
61
|
+
|
62
|
+
# Allows RSpec to persist some state between runs in order to support
|
63
|
+
# the `--only-failures` and `--next-failure` CLI options. We recommend
|
64
|
+
# you configure your source control system to ignore this file.
|
65
|
+
config.example_status_persistence_file_path = "spec/examples.txt"
|
66
|
+
|
67
|
+
# Limits the available syntax to the non-monkey patched syntax that is
|
68
|
+
# recommended. For more details, see:
|
69
|
+
# - http://myronmars.to/n/dev-blog/2012/06/rspecs-new-expectation-syntax
|
70
|
+
# - http://www.teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/
|
71
|
+
# - http://myronmars.to/n/dev-blog/2014/05/notable-changes-in-rspec-3#new__config_option_to_disable_rspeccore_monkey_patching
|
72
|
+
config.disable_monkey_patching!
|
73
|
+
|
74
|
+
# This setting enables warnings. It's recommended, but in some cases may
|
75
|
+
# be too noisy due to issues in dependencies.
|
76
|
+
config.warnings = true
|
77
|
+
|
78
|
+
# Many RSpec users commonly either run the entire suite or an individual
|
79
|
+
# file, and it's useful to allow more verbose output when running an
|
80
|
+
# individual spec file.
|
81
|
+
if config.files_to_run.one?
|
82
|
+
# Use the documentation formatter for detailed output,
|
83
|
+
# unless a formatter has already been configured
|
84
|
+
# (e.g. via a command-line flag).
|
85
|
+
config.default_formatter = 'doc'
|
86
|
+
end
|
87
|
+
|
88
|
+
# Print the 10 slowest examples and example groups at the
|
89
|
+
# end of the spec run, to help surface which specs are running
|
90
|
+
# particularly slow.
|
91
|
+
config.profile_examples = 10
|
92
|
+
|
93
|
+
# Run specs in random order to surface order dependencies. If you find an
|
94
|
+
# order dependency and want to debug it, you can fix the order by providing
|
95
|
+
# the seed, which is printed after each run.
|
96
|
+
# --seed 1234
|
97
|
+
config.order = :random
|
98
|
+
|
99
|
+
# Seed global randomization in this process using the `--seed` CLI option.
|
100
|
+
# Setting this allows you to use `--seed` to deterministically reproduce
|
101
|
+
# test failures related to randomization by passing the same `--seed` value
|
102
|
+
# as the one that triggered the failure.
|
103
|
+
Kernel.srand config.seed
|
104
|
+
=end
|
105
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe VRBO::Availability do
|
4
|
+
let(:dates) { %w[2015-12-13 2015-12-14 2015-12-15 2015-12-16 2015-12-17 2015-12-20] }
|
5
|
+
|
6
|
+
subject { described_class.new(dates) }
|
7
|
+
|
8
|
+
describe '#initialize' do
|
9
|
+
context 'when given an array of dates strings' do
|
10
|
+
it 'assigns @start_at to the date parsed first item' do
|
11
|
+
expect(subject.start_at).to eq Date.parse('2015-12-13')
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'removes the first item from the array (mutation)' do
|
15
|
+
expect {
|
16
|
+
subject.start_at
|
17
|
+
}.to change(dates, :length).from(6).to(5)
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'assigns the all but the first items in -dates- to @dates' do
|
21
|
+
expect(subject.dates).to eq %w[2015-12-14 2015-12-15 2015-12-16 2015-12-17 2015-12-20]
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
context 'when given nil' do
|
26
|
+
let(:dates) { nil }
|
27
|
+
|
28
|
+
it 'assigns @start_at to today' do
|
29
|
+
expect(subject.start_at).to eq Date.today
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
describe '#duration' do
|
35
|
+
context 'when given a list of dates in ascending order' do
|
36
|
+
it 'returns the length of the first sequence' do
|
37
|
+
expect(subject.duration).to eq 5
|
38
|
+
end
|
39
|
+
|
40
|
+
context 'when dates are sequential' do
|
41
|
+
let(:dates) { %w[2015-12-05 2015-12-07 2015-12-10] }
|
42
|
+
|
43
|
+
it 'returns one' do
|
44
|
+
expect(subject.duration).to eq 1
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
context 'when no dates are given' do
|
50
|
+
let(:dates) { [] }
|
51
|
+
|
52
|
+
it 'returns one' do
|
53
|
+
expect(subject.duration).to eq 1
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,151 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe VRBO::Calendar do
|
4
|
+
let(:calendar_id) { '293021' }
|
5
|
+
|
6
|
+
subject { described_class.new calendar_id }
|
7
|
+
|
8
|
+
describe '#initialize' do
|
9
|
+
its(:id) { should == calendar_id }
|
10
|
+
its(:days) { should == {} }
|
11
|
+
|
12
|
+
context 'when no -calendar_id given' do
|
13
|
+
let(:calendar_id) { nil }
|
14
|
+
|
15
|
+
before do
|
16
|
+
VRBO.configure do |config|
|
17
|
+
config.calendar_id = calendar_id
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'uses the configuration value' do
|
22
|
+
expect(subject.id).to eq calendar_id
|
23
|
+
end
|
24
|
+
|
25
|
+
after do
|
26
|
+
VRBO.reset_config
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
describe '#available_dates' do
|
32
|
+
it 'returns the available dates for the next year' do
|
33
|
+
VCR.use_cassette(calendar_id) do
|
34
|
+
expect(subject.available_dates.length).to eq 284
|
35
|
+
expect(subject.available_dates).to eq %w[2015-11-08 2015-11-09 2015-11-22 2015-11-23 2015-11-24 2015-11-25 2015-11-26 2015-11-29 2015-11-30 2015-12-10 2015-12-13 2015-12-14 2015-12-15 2015-12-16 2015-12-17 2015-12-18 2015-12-22 2015-12-23 2015-12-24 2015-12-31 2016-01-01 2016-01-05 2016-01-06 2016-01-07 2016-01-08 2016-01-11 2016-01-12 2016-01-19 2016-01-20 2016-01-21 2016-01-22 2016-01-23 2016-01-24 2016-01-25 2016-01-26 2016-01-27 2016-01-28 2016-01-29 2016-01-30 2016-01-31 2016-02-01 2016-02-06 2016-02-07 2016-02-08 2016-02-09 2016-02-10 2016-02-11 2016-02-20 2016-02-21 2016-02-25 2016-03-02 2016-03-03 2016-03-04 2016-03-05 2016-03-06 2016-03-07 2016-03-08 2016-03-09 2016-03-10 2016-03-11 2016-03-16 2016-03-17 2016-03-18 2016-03-19 2016-03-20 2016-03-21 2016-03-26 2016-03-27 2016-03-28 2016-03-29 2016-03-30 2016-03-31 2016-04-01 2016-04-02 2016-04-03 2016-04-04 2016-04-05 2016-04-06 2016-04-07 2016-04-08 2016-04-09 2016-04-10 2016-04-11 2016-04-12 2016-04-13 2016-04-14 2016-04-15 2016-04-16 2016-04-17 2016-04-18 2016-04-19 2016-04-20 2016-04-21 2016-04-22 2016-04-23 2016-04-24 2016-04-25 2016-04-26 2016-04-27 2016-04-28 2016-04-29 2016-04-30 2016-05-01 2016-05-02 2016-05-03 2016-05-04 2016-05-05 2016-05-06 2016-05-07 2016-05-08 2016-05-09 2016-05-10 2016-05-11 2016-05-12 2016-05-13 2016-05-14 2016-05-15 2016-05-16 2016-05-17 2016-05-18 2016-05-19 2016-05-20 2016-05-21 2016-05-22 2016-05-23 2016-05-24 2016-05-25 2016-05-26 2016-05-27 2016-05-28 2016-05-29 2016-05-30 2016-05-31 2016-06-01 2016-06-02 2016-06-03 2016-06-04 2016-06-05 2016-06-06 2016-06-07 2016-06-08 2016-06-09 2016-06-10 2016-06-11 2016-06-12 2016-06-13 2016-06-14 2016-06-15 2016-06-16 2016-06-17 2016-06-18 2016-06-19 2016-06-20 2016-06-21 2016-06-22 2016-06-23 2016-06-24 2016-06-27 2016-06-28 2016-06-29 2016-06-30 2016-07-01 2016-07-02 2016-07-03 2016-07-04 2016-07-05 2016-07-06 2016-07-07 2016-07-08 2016-07-09 2016-07-10 2016-07-11 2016-07-12 2016-07-13 2016-07-14 2016-07-15 2016-07-16 2016-07-17 2016-07-18 2016-07-19 2016-07-20 2016-07-21 2016-07-22 2016-07-23 2016-07-24 2016-07-25 2016-07-26 2016-07-27 2016-07-28 2016-07-29 2016-07-30 2016-07-31 2016-08-01 2016-08-02 2016-08-03 2016-08-04 2016-08-05 2016-08-06 2016-08-07 2016-08-08 2016-08-09 2016-08-10 2016-08-11 2016-08-12 2016-08-13 2016-08-14 2016-08-15 2016-08-16 2016-08-17 2016-08-18 2016-08-19 2016-08-20 2016-08-21 2016-08-22 2016-08-23 2016-08-24 2016-08-25 2016-08-26 2016-08-27 2016-08-28 2016-08-29 2016-08-30 2016-08-31 2016-09-01 2016-09-02 2016-09-03 2016-09-04 2016-09-05 2016-09-06 2016-09-07 2016-09-08 2016-09-09 2016-09-10 2016-09-11 2016-09-12 2016-09-13 2016-09-14 2016-09-15 2016-09-16 2016-09-17 2016-09-18 2016-09-19 2016-09-20 2016-09-21 2016-09-22 2016-09-23 2016-09-24 2016-09-25 2016-09-26 2016-09-27 2016-09-28 2016-09-29 2016-09-30 2016-10-01 2016-10-02 2016-10-03 2016-10-04 2016-10-05 2016-10-06 2016-10-07 2016-10-08 2016-10-09 2016-10-10 2016-10-11 2016-10-12 2016-10-13 2016-10-14 2016-10-15 2016-10-16 2016-10-17 2016-10-18 2016-10-19 2016-10-20 2016-10-21 2016-10-22 2016-10-23 2016-10-24 2016-10-25 2016-10-26 2016-10-27 2016-10-28 2016-10-29 2016-10-30 2016-10-31]
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
describe '#available?' do
|
41
|
+
let(:arrival) { Date.new(2015, 11, 8) }
|
42
|
+
let(:departure) { Date.new(2015, 11, 9) }
|
43
|
+
|
44
|
+
context 'when the requested dates are available' do
|
45
|
+
context 'when range is two days (1 night)' do
|
46
|
+
it 'returns true' do
|
47
|
+
VCR.use_cassette(calendar_id) do
|
48
|
+
expect(subject.available?(arrival, departure)).to eq true
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
context 'when range is three days (2 nights)' do
|
54
|
+
let(:departure) { Date.new(2015, 11, 10) }
|
55
|
+
|
56
|
+
it 'returns true' do
|
57
|
+
VCR.use_cassette(calendar_id) do
|
58
|
+
expect(subject.available?(arrival, departure)).to eq true
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
context 'when the requested dates are unavailable' do
|
65
|
+
let(:arrival) { Date.new(2015, 11, 22) }
|
66
|
+
let(:departure) { Date.new(2015, 11, 28) }
|
67
|
+
|
68
|
+
it 'returns false' do
|
69
|
+
VCR.use_cassette(calendar_id) do
|
70
|
+
expect(subject.available?(arrival, departure)).to eq false
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
context 'when -dates- is empty' do
|
76
|
+
it 'returns false' do
|
77
|
+
VCR.use_cassette(calendar_id) do
|
78
|
+
expect(subject).to receive(:available_dates).and_return []
|
79
|
+
expect(subject.available?(arrival, departure)).to eq false
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
context 'when the third argument -dates- is given' do
|
85
|
+
let(:dates) { %w[2015-12-13 2015-12-14 2015-12-15 2015-12-16 2015-12-17 2015-12-18] }
|
86
|
+
|
87
|
+
it 'does not call +available_dates+' do
|
88
|
+
VCR.use_cassette(calendar_id) do
|
89
|
+
expect(subject).to_not receive(:available_dates)
|
90
|
+
subject.available?(arrival, departure, dates)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
context 'when the requested dates are available' do
|
95
|
+
let(:arrival) { Date.new(2015, 12, 14) }
|
96
|
+
let(:departure) { Date.new(2015, 12, 19) }
|
97
|
+
|
98
|
+
it 'returns true' do
|
99
|
+
VCR.use_cassette(calendar_id) do
|
100
|
+
expect(subject.available?(arrival, departure, dates)).to be true
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
context 'when the requested dates are unavailable' do
|
106
|
+
it 'returns false' do
|
107
|
+
VCR.use_cassette(calendar_id) do
|
108
|
+
expect(subject.available?(arrival, departure, dates)).to be false
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
context 'when -dates- are empty' do
|
114
|
+
let(:dates) { [] }
|
115
|
+
|
116
|
+
it 'returns false' do
|
117
|
+
VCR.use_cassette(calendar_id) do
|
118
|
+
expect(subject).to_not receive(:available_dates)
|
119
|
+
expect(subject.available?(arrival, departure, dates)).to be false
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
describe '#url' do
|
127
|
+
context 'when @id is present' do
|
128
|
+
context 'when -protocol- is given' do
|
129
|
+
it 'returns the url using the given protocol' do
|
130
|
+
expect(subject.url('https')).to eq "https://www.vrbo.com/#{calendar_id}/calendar"
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
context 'when -protocol- is given' do
|
135
|
+
it 'returns the url using the default "http" protocol' do
|
136
|
+
expect(subject.url).to eq "http://www.vrbo.com/#{calendar_id}/calendar"
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
context 'when @id is missing' do
|
142
|
+
let(:calendar_id) { nil }
|
143
|
+
|
144
|
+
it 'raises an argument error' do
|
145
|
+
expect {
|
146
|
+
subject.url
|
147
|
+
}.to raise_error(ArgumentError, /calendar_id is required/)
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
data/vrbo.gemspec
CHANGED
@@ -23,4 +23,8 @@ Gem::Specification.new do |spec|
|
|
23
23
|
|
24
24
|
spec.add_development_dependency "bundler", "~> 1.3"
|
25
25
|
spec.add_development_dependency "rake"
|
26
|
+
spec.add_development_dependency "vcr", '~> 2.9'
|
27
|
+
spec.add_development_dependency "webmock", '~> 1.21'
|
28
|
+
spec.add_development_dependency "rspec", '~> 3.3'
|
29
|
+
spec.add_development_dependency "rspec-its", '~> 1.2'
|
26
30
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: vrbo
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ryan Buckley
|
@@ -66,6 +66,62 @@ dependencies:
|
|
66
66
|
- - '>='
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: vcr
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ~>
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '2.9'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ~>
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '2.9'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: webmock
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ~>
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '1.21'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ~>
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '1.21'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: rspec
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ~>
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '3.3'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ~>
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '3.3'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: rspec-its
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ~>
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '1.2'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - ~>
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '1.2'
|
69
125
|
description: Scrapes a VRBO calendar using Mechanize and returns available dates
|
70
126
|
email:
|
71
127
|
- arebuckley@gmail.com
|
@@ -74,6 +130,7 @@ extensions: []
|
|
74
130
|
extra_rdoc_files: []
|
75
131
|
files:
|
76
132
|
- .gitignore
|
133
|
+
- .rspec
|
77
134
|
- .ruby-gemset
|
78
135
|
- .ruby-version
|
79
136
|
- Gemfile
|
@@ -83,12 +140,12 @@ files:
|
|
83
140
|
- lib/vrbo.rb
|
84
141
|
- lib/vrbo/availability.rb
|
85
142
|
- lib/vrbo/calendar.rb
|
86
|
-
- lib/vrbo/class_methods.rb
|
87
143
|
- lib/vrbo/configuration.rb
|
88
144
|
- lib/vrbo/version.rb
|
89
|
-
-
|
90
|
-
-
|
91
|
-
-
|
145
|
+
- spec/fixtures/vcr_cassettes/293021.yml
|
146
|
+
- spec/spec_helper.rb
|
147
|
+
- spec/vrbo/availability_spec.rb
|
148
|
+
- spec/vrbo/calendar_spec.rb
|
92
149
|
- vrbo.gemspec
|
93
150
|
homepage: ''
|
94
151
|
licenses:
|
@@ -115,6 +172,7 @@ signing_key:
|
|
115
172
|
specification_version: 4
|
116
173
|
summary: Scrapes a VRBO calendar using Mechanize
|
117
174
|
test_files:
|
118
|
-
-
|
119
|
-
-
|
120
|
-
-
|
175
|
+
- spec/fixtures/vcr_cassettes/293021.yml
|
176
|
+
- spec/spec_helper.rb
|
177
|
+
- spec/vrbo/availability_spec.rb
|
178
|
+
- spec/vrbo/calendar_spec.rb
|
data/lib/vrbo/class_methods.rb
DELETED
@@ -1,47 +0,0 @@
|
|
1
|
-
module CalendarDates
|
2
|
-
|
3
|
-
def available?(list, a = today, b = tomorrow)
|
4
|
-
vrbo_calendar.available?(a, b, list)
|
5
|
-
end
|
6
|
-
|
7
|
-
def all
|
8
|
-
prep [today, tomorrow]
|
9
|
-
end
|
10
|
-
|
11
|
-
def random
|
12
|
-
prep all.shuffle
|
13
|
-
end
|
14
|
-
|
15
|
-
def arrival_only
|
16
|
-
prep [today]
|
17
|
-
end
|
18
|
-
|
19
|
-
def depart_only
|
20
|
-
prep [tomorrow]
|
21
|
-
end
|
22
|
-
|
23
|
-
def prep(list)
|
24
|
-
list.map(&:to_s)
|
25
|
-
end
|
26
|
-
|
27
|
-
def today
|
28
|
-
@today ||= Date.today
|
29
|
-
end
|
30
|
-
|
31
|
-
def tomorrow
|
32
|
-
@tomorrow ||= today + 1
|
33
|
-
end
|
34
|
-
|
35
|
-
def vrbo_calendar
|
36
|
-
@vrbo_calendar ||= begin
|
37
|
-
calendar = VRBO::Calendar.new
|
38
|
-
|
39
|
-
def calendar.collect_days_for_month(date)
|
40
|
-
dates = date.upto(date.next_month).to_a
|
41
|
-
dates.map(&:day).map(&:to_s).take(3)
|
42
|
-
end
|
43
|
-
|
44
|
-
calendar
|
45
|
-
end
|
46
|
-
end
|
47
|
-
end
|
@@ -1,21 +0,0 @@
|
|
1
|
-
$: << 'test'
|
2
|
-
require 'minitest/autorun'
|
3
|
-
require 'vrbo'
|
4
|
-
require 'support/calendar_dates'
|
5
|
-
|
6
|
-
class AvailabilityTest < MiniTest::Unit::TestCase
|
7
|
-
include CalendarDates
|
8
|
-
|
9
|
-
def test_new_with_params
|
10
|
-
availability = VRBO::Availability.new(all << (tomorrow + 2).to_s)
|
11
|
-
assert_equal today, availability.start_at
|
12
|
-
assert_equal 2, availability.duration
|
13
|
-
end
|
14
|
-
|
15
|
-
def test_new_without_params
|
16
|
-
availability = VRBO::Availability.new
|
17
|
-
assert_equal today, availability.start_at
|
18
|
-
assert_equal 1, availability.duration
|
19
|
-
end
|
20
|
-
|
21
|
-
end
|
data/test/vrbo/calendar_test.rb
DELETED
@@ -1,70 +0,0 @@
|
|
1
|
-
$: << 'test'
|
2
|
-
require 'minitest/autorun'
|
3
|
-
require 'vrbo'
|
4
|
-
require 'support/calendar_dates'
|
5
|
-
|
6
|
-
class CalendarTest < MiniTest::Unit::TestCase
|
7
|
-
include CalendarDates
|
8
|
-
|
9
|
-
def calendar_id
|
10
|
-
212121
|
11
|
-
end
|
12
|
-
|
13
|
-
def test_available_with_all
|
14
|
-
assert_equal true, available?(all)
|
15
|
-
end
|
16
|
-
|
17
|
-
def test_available_with_random
|
18
|
-
assert_equal true, available?(random)
|
19
|
-
end
|
20
|
-
|
21
|
-
def test_available_with_arrival
|
22
|
-
assert_equal true, available?(arrival_only)
|
23
|
-
end
|
24
|
-
|
25
|
-
def test_available_with_depart
|
26
|
-
assert_equal false, available?(depart_only)
|
27
|
-
end
|
28
|
-
|
29
|
-
def test_available_with_empty
|
30
|
-
assert_equal false, available?([])
|
31
|
-
end
|
32
|
-
|
33
|
-
def test_available_with_edge
|
34
|
-
assert_equal true, available?(all, today, tomorrow + 1)
|
35
|
-
end
|
36
|
-
|
37
|
-
def test_available_with_exceeding
|
38
|
-
assert_equal false, available?(all, today, tomorrow + 2)
|
39
|
-
end
|
40
|
-
|
41
|
-
def test_find_all_available_dates
|
42
|
-
# 3 days taken for each month (36)
|
43
|
-
assert_equal 36, vrbo_calendar.find_available_dates.length
|
44
|
-
assert_equal 12, vrbo_calendar.days.length
|
45
|
-
assert_equal today.to_s, vrbo_calendar.available_dates.first
|
46
|
-
end
|
47
|
-
|
48
|
-
def test_passing_calendar_id
|
49
|
-
calendar = VRBO::Calendar.new(calendar_id)
|
50
|
-
assert_equal calendar_id, calendar.id
|
51
|
-
assert_equal "http://www.vrbo.com/#{calendar_id}/calendar", calendar.url
|
52
|
-
assert_equal "https://www.vrbo.com/#{calendar_id}/calendar", calendar.url('https')
|
53
|
-
end
|
54
|
-
|
55
|
-
def test_no_calendar_id_given
|
56
|
-
assert_raises ArgumentError do
|
57
|
-
VRBO::Calendar.new.url
|
58
|
-
end
|
59
|
-
end
|
60
|
-
|
61
|
-
def test_calendar_id_from_config
|
62
|
-
VRBO.configure do |config|
|
63
|
-
config.calendar_id = calendar_id
|
64
|
-
end
|
65
|
-
calendar = VRBO::Calendar.new
|
66
|
-
VRBO.reset_config
|
67
|
-
assert_equal calendar_id, calendar.id
|
68
|
-
assert_equal "http://www.vrbo.com/#{calendar_id}/calendar", calendar.url
|
69
|
-
end
|
70
|
-
end
|