blinkbox_films 0.0.3 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 473ae721f46a03e80dcbbd541c65d5eba2b86c31
4
- data.tar.gz: e0a1422c50e3d237cdc800837789354f849dbdf2
3
+ metadata.gz: e695abee9304b0cde5c7193c45caaaba9e128104
4
+ data.tar.gz: de8ce6b1da05feb99e1b98824953d5a18601c84b
5
5
  SHA512:
6
- metadata.gz: a851e8361e2bc1e9c75cc4cb3322b1b9a5a2a1e884f9c05186a4a0a5f32a5c88fc54260c5eed808e308ec723b681e295fb85cc4511db3b61f7718f2e44a80857
7
- data.tar.gz: aa19ba80560622d0790a057767042577f0fce21f6508f3aa1e7392d082f5181bab94b7b37b9b099c25c6e1a6c1363e50d6f0c95f766a8935b9e5af7f610b3b3a
6
+ metadata.gz: 1132b4616635c34f1837e1b81428611e7e82a5282ca64949ac4ba9569e17c97532350f70b61d75d617e16d4b9e005ccf93fd0bf31c3125f8605421b91a6c5b8c
7
+ data.tar.gz: 526309666d94232b4205956ff01c9794ef890fd0fdba60295bc77e6d020b533544afc9825a29822231b8c7dafd77a377a80876da1179e3984aeb047b639f72e7
@@ -0,0 +1,26 @@
1
+ module BlinkboxFilms
2
+ class Film
3
+ def initialize(
4
+ title:,
5
+ url: nil,
6
+ image_url: nil,
7
+ certificate: nil,
8
+ release_year: nil,
9
+ running_time_in_minutes: nil,
10
+ buy_price: nil,
11
+ rental_price: nil
12
+ )
13
+ @title = title
14
+ @url = url
15
+ @image_url = image_url
16
+ @certificate = certificate
17
+ @release_year = release_year
18
+ @running_time_in_minutes = running_time_in_minutes
19
+ @buy_price = buy_price
20
+ @rental_price = rental_price
21
+ end
22
+
23
+ attr_reader :title, :url, :image_url, :certificate, :release_year,
24
+ :running_time_in_minutes, :buy_price, :rental_price
25
+ end
26
+ end
@@ -0,0 +1,69 @@
1
+ require 'uri'
2
+ require 'nokogiri'
3
+ require 'httpclient'
4
+
5
+ module BlinkboxFilms
6
+ class FilmPage
7
+ def initialize(body:, url: nil)
8
+ @body = body
9
+ @url = url
10
+ end
11
+
12
+ attr_reader :body, :url
13
+
14
+ def self.from_url(url)
15
+ response = HTTPClient.new.get(url)
16
+ FilmPage.new(body: Nokogiri::HTML(response.body), url: url)
17
+ end
18
+
19
+ def film
20
+ Film.new(
21
+ title: title,
22
+ url: url,
23
+ image_url: image_url,
24
+ release_year: release_year,
25
+ certificate: certificate,
26
+ running_time_in_minutes: running_time_in_minutes,
27
+ rental_price: rental_price,
28
+ buy_price: buy_price
29
+ )
30
+ end
31
+
32
+ def title
33
+ body.css('h1').first.content.strip
34
+ end
35
+
36
+ def image_url
37
+ body.css('.c-packShot noscript img').first.attributes['src'].value
38
+ end
39
+
40
+ def release_year
41
+ match = body.css('.g-assetInfo li').map { |n| %r{(\d{4})}.match(n.content) }.compact.first
42
+ match && match[1].to_i
43
+ end
44
+
45
+ def certificate
46
+ match = body.css('.g-assetInfo li').map { |n| %r{CERT (.*)}.match(n.content) }.compact.first
47
+ match && match[1]
48
+ end
49
+
50
+ def running_time_in_minutes
51
+ match = body.css('.g-assetInfo li').map { |n| %r{(\d+) HRS (\d+) MINS}.match(n.content) }.compact.first
52
+ match && (match[1].to_i * 60 + match[2].to_i)
53
+ end
54
+
55
+ def rental_price
56
+ select_price(body, '.c-retailButton--rental .c-retailButton__price > text()')
57
+ end
58
+
59
+ def buy_price
60
+ select_price(body, '.c-retailButton--purchase .c-retailButton__price > text()')
61
+ end
62
+
63
+ private
64
+ def select_price(body, selector)
65
+ price_tag = body.css(selector).first
66
+ price_tag && price_tag.text.strip
67
+ end
68
+ end
69
+ end
@@ -6,20 +6,20 @@ module BlinkboxFilms
6
6
  class Search
7
7
  def search(query)
8
8
  r = response(query)
9
- rentals = rental_fragments(r.body).map { |f|
10
- {
11
- :title => rental_title(f),
12
- :url => rental_url(f),
13
- :image_url => rental_image_url(f),
14
- :certificate => rental_certificate(f),
15
- :running_time_in_minutes => rental_running_time_in_minutes(f)
16
- }
9
+ films = film_fragments(r.body).map { |f|
10
+ Film.new(
11
+ title: film_title(f),
12
+ url: film_url(f),
13
+ image_url: film_image_url(f),
14
+ certificate: film_certificate(f),
15
+ running_time_in_minutes: film_running_time_in_minutes(f)
16
+ )
17
17
  }
18
18
 
19
- if rentals.empty? & !no_results_page?(r.body)
19
+ if films.empty? & !no_results_page?(r.body)
20
20
  raise BlinkboxFilms::SearchResultsPageNotRecognised
21
21
  else
22
- rentals
22
+ films
23
23
  end
24
24
  end
25
25
 
@@ -32,35 +32,35 @@ module BlinkboxFilms
32
32
  HTTPClient.new.get('http://www.blinkbox.com/search', { 'Search' => query })
33
33
  end
34
34
 
35
- def rental_fragments(page)
35
+ def film_fragments(page)
36
36
  Nokogiri::HTML(page).css('.p-searchResults li.b-assetCollection__item')
37
37
  end
38
38
 
39
- def rental_title(fragment)
39
+ def film_title(fragment)
40
40
  fragment.css('h3').first.content.strip
41
41
  end
42
42
 
43
- def rental_url(fragment)
44
- u = URI.parse(extract_rental_path_or_url(fragment))
43
+ def film_url(fragment)
44
+ u = URI.parse(extract_film_path_or_url(fragment))
45
45
  u.host ||= 'www.blinkbox.com'
46
46
  u.scheme ||= 'http'
47
47
  u.to_s
48
48
  end
49
49
 
50
- def extract_rental_path_or_url(fragment)
50
+ def extract_film_path_or_url(fragment)
51
51
  fragment.css('h3 a').first.attributes['href'].value
52
52
  end
53
53
 
54
- def rental_image_url(fragment)
54
+ def film_image_url(fragment)
55
55
  fragment.css('noscript img').first.attributes['src'].value
56
56
  end
57
57
 
58
- def rental_certificate(fragment)
58
+ def film_certificate(fragment)
59
59
  match = fragment.css('.c-assetCollectionItem__metaDataItem').map { |n| %r{CERT (\S+)}.match(n.content) }.compact.first
60
60
  match && match[1]
61
61
  end
62
62
 
63
- def rental_running_time_in_minutes(fragment)
63
+ def film_running_time_in_minutes(fragment)
64
64
  match = fragment.css('.c-assetCollectionItem__metaDataItem').map { |n| %r{(\d+) HRS? (\d+) MINS?}.match(n.content) }.compact.first
65
65
  match && (match[1].to_i * 60 + match[2].to_i)
66
66
  end
@@ -1,3 +1,4 @@
1
+ require 'blinkbox_films/film'
2
+ require 'blinkbox_films/film_page' || raise
1
3
  require 'blinkbox_films/search_results_page_not_recognised'
2
4
  require 'blinkbox_films/search'
3
-
@@ -0,0 +1,16 @@
1
+ require 'spec_helper'
2
+ require 'blinkbox_films'
3
+
4
+ describe 'A film page', :vcr do
5
+ subject { BlinkboxFilms::FilmPage.from_url('http://www.blinkbox.com/movies/the-dark-knight-(28710)').film }
6
+
7
+ it { expect(subject.title).to eq('The Dark Knight') }
8
+ it { expect(subject.url).to eq('http://www.blinkbox.com/movies/the-dark-knight-(28710)') }
9
+ it { expect(subject.image_url).to match(%r{http://cdn\d+.blinkboxmedia.com/i/contentasset3/000/028/710/gl0lloqf/v=317/w=215;h=306;rm=Crop;q=85/image.jpg}) }
10
+ it { expect(subject.release_year).to eq(2008) }
11
+ it { expect(subject.certificate).to eq('12') }
12
+ it { expect(subject.running_time_in_minutes).to eq(152) }
13
+ it { expect(subject.rental_price).to eq('£2.49') }
14
+ it { expect(subject.buy_price).to eq('£6.99') }
15
+ end
16
+
@@ -10,11 +10,11 @@ describe 'A search' do
10
10
  subject { BlinkboxFilms::Search.new.search('dark knight') }
11
11
 
12
12
  it { expect(subject).to_not be_empty }
13
- it { expect(subject.first[:title]).to eq('The Dark Knight') }
14
- it { expect(subject.first[:url]).to eq('http://www.blinkbox.com/movies/the-dark-knight-(28710)') }
15
- it { expect(subject.first[:image_url]).to eq('http://cdn2.blinkboxmedia.com/i/contentasset31/000/028/710/1gkiab4e/v=316/w=234;h=132;rm=Crop;q=85/image.jpg') }
16
- it { expect(subject.first[:certificate]).to eq('12') }
17
- it { expect(subject.first[:running_time_in_minutes]).to eq(152) }
13
+ it { expect(subject.first.title).to eq('The Dark Knight') }
14
+ it { expect(subject.first.url).to eq('http://www.blinkbox.com/movies/the-dark-knight-(28710)') }
15
+ it { expect(subject.first.image_url).to eq('http://cdn2.blinkboxmedia.com/i/contentasset31/000/028/710/1gkiab4e/v=316/w=234;h=132;rm=Crop;q=85/image.jpg') }
16
+ it { expect(subject.first.certificate).to eq('12') }
17
+ it { expect(subject.first.running_time_in_minutes).to eq(152) }
18
18
  end
19
19
 
20
20
  context 'with unrecognised page format returned' do
@@ -0,0 +1,37 @@
1
+ require 'spec_helper'
2
+
3
+ describe BlinkboxFilms::FilmPage do
4
+ describe '#buy_price' do
5
+ subject { BlinkboxFilms::FilmPage.new(body: body) }
6
+
7
+ context 'standard price' do
8
+ let(:body) {
9
+ Nokogiri::HTML('<button type="submit" class="c-retailButton c-retailButton--purchase">
10
+ BUY
11
+ <span class="c-retailButton__price">
12
+ £6.99
13
+ </span>
14
+ </button>')
15
+ }
16
+
17
+ it { expect(subject.buy_price).to eq('£6.99') }
18
+ end
19
+
20
+ context 'discount price' do
21
+ let(:body) {
22
+ Nokogiri::HTML('<button type="submit" class="c-retailButton c-retailButton--purchase">
23
+ BUY
24
+ <span class="c-retailButton__price">
25
+ £3.99
26
+ <span class="c-retailButton__saving c-retailButton__saving--purchase">
27
+ £6.99
28
+ </span>
29
+ </span>
30
+ </button>')
31
+ }
32
+
33
+ it { expect(subject.buy_price).to eq('£3.99') }
34
+ end
35
+ end
36
+ end
37
+
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: blinkbox_films
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.0.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Joel Chippindale
@@ -103,9 +103,13 @@ files:
103
103
  - LICENSE.txt
104
104
  - Rakefile
105
105
  - lib/blinkbox_films.rb
106
+ - lib/blinkbox_films/film.rb
107
+ - lib/blinkbox_films/film_page.rb
106
108
  - lib/blinkbox_films/search.rb
107
109
  - lib/blinkbox_films/search_results_page_not_recognised.rb
110
+ - spec/feature/film_page_spec.rb
108
111
  - spec/feature/search_spec.rb
112
+ - spec/lib/blinkbox_films/film_page_spec.rb
109
113
  - spec/spec_helper.rb
110
114
  homepage: https://github.com/mocoso/blinkbox_films
111
115
  licenses: