picturehouse_uk 1.0.2 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +2 -1
  3. data/CHANGELOG.md +18 -0
  4. data/README.md +7 -10
  5. data/Rakefile +20 -7
  6. data/lib/picturehouse_uk.rb +4 -1
  7. data/lib/picturehouse_uk/cinema.rb +51 -100
  8. data/lib/picturehouse_uk/film.rb +22 -8
  9. data/lib/picturehouse_uk/internal/address_parser.rb +72 -0
  10. data/lib/picturehouse_uk/internal/cinema_page.rb +35 -0
  11. data/lib/picturehouse_uk/internal/film_with_screenings_parser.rb +87 -37
  12. data/lib/picturehouse_uk/internal/title_sanitizer.rb +49 -0
  13. data/lib/picturehouse_uk/internal/website.rb +39 -0
  14. data/lib/picturehouse_uk/screening.rb +63 -19
  15. data/lib/picturehouse_uk/version.rb +2 -2
  16. data/picturehouse_uk.gemspec +11 -11
  17. data/test/fixture_updater.rb +43 -0
  18. data/test/fixtures/address-fragments/duke-of-yorks.html +39 -0
  19. data/test/fixtures/address-fragments/hackney-picturehouse.html +12 -0
  20. data/test/fixtures/cinema/Duke_Of_Yorks.html +4370 -0
  21. data/test/fixtures/cinema/Duke_Of_Yorks/film_last.html +45 -0
  22. data/test/fixtures/cinema/Duke_Of_Yorks/film_second.html +37 -0
  23. data/test/fixtures/{abbeygate-contact-us.html → contact_us/Duke_Of_Yorks.html} +635 -156
  24. data/test/fixtures/{dukes-at-komedia-contact-us.html → contact_us/Dukes_At_Komedia.html} +582 -98
  25. data/test/fixtures/{picturehouses-homepage.html → home.html} +642 -146
  26. data/test/lib/picturehouse_uk/cinema_test.rb +127 -307
  27. data/test/lib/picturehouse_uk/film_test.rb +65 -16
  28. data/test/lib/picturehouse_uk/internal/address_parser_test.rb +55 -0
  29. data/test/lib/picturehouse_uk/internal/cinema_page_test.rb +51 -0
  30. data/test/lib/picturehouse_uk/internal/film_with_screenings_parser_test.rb +44 -151
  31. data/test/lib/picturehouse_uk/internal/title_sanitizer_test.rb +131 -0
  32. data/test/lib/picturehouse_uk/internal/website_test.rb +64 -0
  33. data/test/lib/picturehouse_uk/screening_test.rb +149 -21
  34. data/test/live/integration_test.rb +68 -0
  35. data/test/test_helper.rb +3 -1
  36. metadata +40 -43
  37. data/test/fixtures/dukes-at-komedia-cinema.html +0 -7148
  38. data/test/fixtures/film_node/blue-jasmine-done.html +0 -53
  39. data/test/fixtures/film_node/blue-jasmine-future.html +0 -55
  40. data/test/fixtures/film_node/bolshoi-spartacus.html +0 -26
  41. data/test/fixtures/film_node/captain-phillips-with-silver-screen-and-subtitles.html +0 -103
  42. data/test/fixtures/film_node/fifth-estate-with-big-scream.html +0 -73
  43. data/test/fixtures/film_node/london-film-festival-with-toddler-time.html +0 -46
  44. data/test/fixtures/film_node/met-encore-rusalka-as-live.html +0 -26
  45. data/test/fixtures/film_node/nt-encore-hamlet.html +0 -26
  46. data/test/fixtures/film_node/planes-with-kids-club.html +0 -77
  47. data/test/fixtures/film_node/royal-opera-house-don-quixote.html +0 -26
  48. data/test/fixtures/film_node/rsc-encore-richard-ii.html +0 -28
  49. data/test/fixtures/film_node/rsc-live-richard-ii.html +0 -41
  50. data/test/fixtures/film_node/rsc-live-the-two-gentlemen-of-verona-zero-cert.html +0 -19
  51. data/test/fixtures/hackney-contact-us.html +0 -998
@@ -1,16 +1,55 @@
1
1
  require_relative '../../test_helper'
2
2
 
3
3
  describe PicturehouseUk::Film do
4
+ let(:described_class) { PicturehouseUk::Film }
5
+
4
6
  describe '.new(name)' do
5
7
  it 'stores name' do
6
- film = PicturehouseUk::Film.new 'Iron Man 3'
8
+ film = described_class.new('Iron Man 3')
7
9
  film.name.must_equal 'Iron Man 3'
8
10
  end
9
11
  end
10
12
 
13
+ describe '.at(cinema_id)' do
14
+ let(:website) { Minitest::Mock.new }
15
+
16
+ subject { described_class.at('Duke_Of_Yorks') }
17
+
18
+ before do
19
+ website.expect(:cinema, cinema_html('Duke_Of_Yorks'), ['Duke_Of_Yorks'])
20
+ end
21
+
22
+ it 'returns an array of films' do
23
+ PicturehouseUk::Internal::Website.stub :new, website do
24
+ subject.must_be_instance_of(Array)
25
+ subject.each do |film|
26
+ film.must_be_instance_of(PicturehouseUk::Film)
27
+ end
28
+ end
29
+ end
30
+
31
+ it 'returns a decent number of films' do
32
+ PicturehouseUk::Internal::Website.stub :new, website do
33
+ subject.count.must_be :>, 5
34
+ end
35
+ end
36
+
37
+ it 'returns uniquely named films' do
38
+ PicturehouseUk::Internal::Website.stub :new, website do
39
+ subject.each_with_index do |item, index|
40
+ subject.each_with_index do |jtem, i|
41
+ next if index == i
42
+ item.name.wont_equal jtem.name
43
+ item.wont_equal jtem
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
49
+
11
50
  describe 'Comparable' do
12
51
  it 'includes comparable methods' do
13
- film = PicturehouseUk::Film.new 'AAAA'
52
+ film = described_class.new 'AAAA'
14
53
  film.methods.must_include :<
15
54
  film.methods.must_include :>
16
55
  film.methods.must_include :==
@@ -21,30 +60,30 @@ describe PicturehouseUk::Film do
21
60
 
22
61
  describe 'uniqueness' do
23
62
  it 'defines #hash' do
24
- film = PicturehouseUk::Film.new 'AAAA'
63
+ film = described_class.new 'AAAA'
25
64
  film.methods.must_include :hash
26
65
  end
27
66
 
28
67
  describe '#hash' do
29
68
  it 'returns a hash of the slug' do
30
- film = PicturehouseUk::Film.new 'AAAA'
69
+ film = described_class.new 'AAAA'
31
70
  film.hash == film.slug.hash
32
71
  end
33
72
  end
34
73
 
35
74
  it 'defines #eql?(other)' do
36
- film = PicturehouseUk::Film.new 'AAAA'
75
+ film = described_class.new 'AAAA'
37
76
  film.methods.must_include :eql?
38
77
  end
39
78
 
40
79
  describe 'two identically named films' do
41
- let(:film) { PicturehouseUk::Film.new 'AAAA' }
42
- let(:otherfilm) { PicturehouseUk::Film.new 'AAAA' }
80
+ let(:film) { described_class.new 'AAAA' }
81
+ let(:otherfilm) { described_class.new 'AAAA' }
43
82
 
44
83
  it 'retuns only one' do
45
84
  result = [film, otherfilm].uniq
46
85
  result.count.must_equal 1
47
- result.must_equal [ PicturehouseUk::Film.new('AAAA') ]
86
+ result.must_equal [ described_class.new('AAAA') ]
48
87
  end
49
88
  end
50
89
  end
@@ -53,8 +92,8 @@ describe PicturehouseUk::Film do
53
92
  subject { film <=> otherfilm }
54
93
 
55
94
  describe 'film less than other' do
56
- let(:film) { PicturehouseUk::Film.new 'AAAA' }
57
- let(:otherfilm) { PicturehouseUk::Film.new 'BBBB' }
95
+ let(:film) { described_class.new 'AAAA' }
96
+ let(:otherfilm) { described_class.new 'BBBB' }
58
97
 
59
98
  it 'retuns -1' do
60
99
  subject.must_equal -1
@@ -62,8 +101,8 @@ describe PicturehouseUk::Film do
62
101
  end
63
102
 
64
103
  describe 'film greater than other' do
65
- let(:film) { PicturehouseUk::Film.new 'CCCC' }
66
- let(:otherfilm) { PicturehouseUk::Film.new 'BBBB' }
104
+ let(:film) { described_class.new 'CCCC' }
105
+ let(:otherfilm) { described_class.new 'BBBB' }
67
106
 
68
107
  it 'retuns 1' do
69
108
  subject.must_equal 1
@@ -71,8 +110,8 @@ describe PicturehouseUk::Film do
71
110
  end
72
111
 
73
112
  describe 'film same as other (exact name)' do
74
- let(:film) { PicturehouseUk::Film.new 'AAAA' }
75
- let(:otherfilm) { PicturehouseUk::Film.new 'AAAA' }
113
+ let(:film) { described_class.new 'AAAA' }
114
+ let(:otherfilm) { described_class.new 'AAAA' }
76
115
 
77
116
  it 'retuns 0' do
78
117
  subject.must_equal 0
@@ -80,8 +119,8 @@ describe PicturehouseUk::Film do
80
119
  end
81
120
 
82
121
  describe 'film same as other (inexact name)' do
83
- let(:film) { PicturehouseUk::Film.new 'blue jasmine' }
84
- let(:otherfilm) { PicturehouseUk::Film.new 'Blue Jasmine' }
122
+ let(:film) { described_class.new 'blue jasmine' }
123
+ let(:otherfilm) { described_class.new 'Blue Jasmine' }
85
124
 
86
125
  it 'retuns 0' do
87
126
  subject.must_equal 0
@@ -89,4 +128,14 @@ describe PicturehouseUk::Film do
89
128
  end
90
129
  end
91
130
  end
131
+
132
+ private
133
+
134
+ def cinema_html(filename)
135
+ read_file("../../../fixtures/cinema/#{filename}.html")
136
+ end
137
+
138
+ def read_file(filepath)
139
+ File.read(File.expand_path(filepath, __FILE__))
140
+ end
92
141
  end
@@ -0,0 +1,55 @@
1
+ require_relative '../../../test_helper'
2
+
3
+ describe PicturehouseUk::Internal::AddressParser do
4
+ let(:described_class) { PicturehouseUk::Internal::AddressParser }
5
+
6
+ describe '#address' do
7
+ subject { described_class.new(html).address }
8
+
9
+ describe 'standard address' do # brighton
10
+ let(:html) { address_html('duke-of-yorks') }
11
+
12
+ it 'returns a hash' do
13
+ subject.class.must_equal Hash
14
+ end
15
+
16
+ it 'contains the correct keys' do
17
+ subject.must_equal(
18
+ street_address: 'Preston Circus',
19
+ extended_address: nil,
20
+ locality: 'Brighton',
21
+ postal_code: 'BN1 4NA',
22
+ country: 'United Kingdom'
23
+ )
24
+ end
25
+ end
26
+
27
+ describe 'freak address: hackney' do
28
+ let(:html) { address_html('hackney-picturehouse') }
29
+
30
+ it 'returns a hash' do
31
+ subject.class.must_equal Hash
32
+ end
33
+
34
+ it 'contains the correct keys' do
35
+ subject.must_equal(
36
+ street_address: '270 Mare Street',
37
+ extended_address: nil,
38
+ locality: 'London',
39
+ postal_code: 'E8 1HE',
40
+ country: 'United Kingdom'
41
+ )
42
+ end
43
+ end
44
+ end
45
+
46
+ private
47
+
48
+ def read_file(filepath)
49
+ File.read(File.expand_path(filepath, __FILE__))
50
+ end
51
+
52
+ def address_html(cinema)
53
+ read_file("../../../../fixtures/address-fragments/#{cinema}.html")
54
+ end
55
+ end
@@ -0,0 +1,51 @@
1
+ require_relative '../../../test_helper'
2
+
3
+ describe PicturehouseUk::Internal::CinemaPage do
4
+ let(:described_class) { PicturehouseUk::Internal::CinemaPage }
5
+
6
+ let(:website) { Minitest::Mock.new }
7
+
8
+ before do
9
+ WebMock.disable_net_connect!
10
+ end
11
+
12
+ describe '#film_html' do
13
+ subject { described_class.new('Duke_Of_Yorks').film_html }
14
+
15
+ before do
16
+ website.expect(:cinema, dukes_html, ['Duke_Of_Yorks'])
17
+ end
18
+
19
+ it 'returns an non-zero array of film screenings html fragments' do
20
+ PicturehouseUk::Internal::Website.stub :new, website do
21
+ subject.must_be_instance_of(Array)
22
+ subject.size.must_be :>, 0
23
+
24
+ subject.each do |film_html|
25
+ film_html.must_be_instance_of(String)
26
+ film_html.size.must_be :>, 0
27
+ end
28
+ end
29
+ end
30
+
31
+ it 'returns an array with correct content' do
32
+ PicturehouseUk::Internal::Website.stub :new, website do
33
+ subject[1..-1].each do |html|
34
+ html.must_include('class="imageborder"') # poster
35
+ html.must_include('class="movielink"') # title
36
+ html.must_include('epoch="') # screening
37
+ end
38
+ end
39
+ end
40
+ end
41
+
42
+ private
43
+
44
+ def read_file(filepath)
45
+ File.read(File.expand_path(filepath, __FILE__))
46
+ end
47
+
48
+ def dukes_html
49
+ read_file('../../../../fixtures/cinema/Duke_Of_Yorks.html')
50
+ end
51
+ end
@@ -1,185 +1,78 @@
1
1
  require_relative '../../../test_helper'
2
2
 
3
3
  describe PicturehouseUk::Internal::FilmWithScreeningsParser do
4
+ let(:described_class) { PicturehouseUk::Internal::FilmWithScreeningsParser }
4
5
 
5
6
  describe '#film_name' do
6
- subject { PicturehouseUk::Internal::FilmWithScreeningsParser.new(film_html).film_name }
7
+ subject { described_class.new(film_html).film_name }
7
8
 
8
- describe 'simple name' do
9
- let(:film_html) { read_film_html 'blue-jasmine-future'}
9
+ describe 'passed film html from page' do
10
+ let(:film_html) { read_film_html('Duke_Of_Yorks/film_second') }
10
11
 
11
- it 'removes certificate' do
12
- subject.must_be_instance_of String
13
- subject.must_equal 'Blue Jasmine'
12
+ it 'returns the film name' do
13
+ subject.must_be_instance_of(String)
14
+ subject.must_equal('Gone Girl')
14
15
  end
15
16
  end
16
17
 
17
- describe 'simple name with dimensionality' do
18
- let(:film_html) { read_film_html 'planes-with-kids-club'}
18
+ describe 'passed film html from end of page' do
19
+ let(:film_html) { read_film_html('Duke_Of_Yorks/film_last') }
19
20
 
20
- it 'removes version designation' do
21
- subject.must_be_instance_of String
22
- subject.must_equal 'Planes'
23
- end
24
- end
25
-
26
- describe 'royal opera house with no cert' do
27
- let(:film_html) { read_film_html 'royal-opera-house-don-quixote'}
28
-
29
- it 'removes live designation, certificate and spells out Royal Opera House' do
30
- subject.must_be_instance_of String
31
- subject.must_equal 'Royal Opera House: Don Quixote'
32
- end
33
- end
34
-
35
- describe 'bolshoi with no cert' do
36
- let(:film_html) { read_film_html 'bolshoi-spartacus'}
37
-
38
- it 'removes certificate' do
39
- subject.must_be_instance_of String
40
- subject.must_equal 'Bolshoi: Spartacus'
41
- end
42
- end
43
-
44
- describe 'nt encore with no cert' do
45
- let(:film_html) { read_film_html 'nt-encore-hamlet'}
46
-
47
- it 'removes certificate' do
48
- subject.must_be_instance_of String
49
- subject.must_equal 'National Theatre: Hamlet'
50
- end
51
- end
52
-
53
- describe 'rsc live with no cert' do
54
- let(:film_html) { read_film_html 'rsc-live-richard-ii'}
55
-
56
- it 'removes certificate' do
57
- subject.must_be_instance_of String
58
- subject.must_equal 'Royal Shakespeare Company: Richard II'
59
- end
60
- end
61
-
62
- describe 'rsc encore with no cert' do
63
- let(:film_html) { read_film_html 'rsc-encore-richard-ii'}
64
-
65
- it 'removes certificate' do
66
- subject.must_be_instance_of String
67
- subject.must_equal 'Royal Shakespeare Company: Richard II'
68
- end
69
- end
70
-
71
- describe 'met encore as live with no cert' do
72
- let(:film_html) { read_film_html 'met-encore-rusalka-as-live'}
73
-
74
- it 'removes certificate' do
75
- subject.must_be_instance_of String
76
- subject.must_equal 'Met Opera: Rusalka'
77
- end
78
- end
79
-
80
- describe 'rsc live with zeroed cert' do
81
- let(:film_html) { read_film_html 'rsc-live-the-two-gentlemen-of-verona-zero-cert' }
82
-
83
- it 'removes certificate' do
84
- subject.must_be_instance_of String
85
- subject.must_equal 'Royal Shakespeare Company: The Two Gentlemen of Verona'
21
+ it 'returns the film name' do
22
+ subject.must_be_instance_of(String)
23
+ subject.must_equal('The Judge')
86
24
  end
87
25
  end
88
26
  end
89
27
 
90
- describe '#showings' do
91
- subject { PicturehouseUk::Internal::FilmWithScreeningsParser.new(film_html).showings }
28
+ describe '#to_a' do
29
+ subject { described_class.new(film_html).to_a }
92
30
 
93
- describe 'multiple screenings' do
94
- let(:film_html) { read_film_html 'blue-jasmine-future'}
31
+ describe 'passed film html from top of page' do
32
+ let(:film_html) { read_film_html('Duke_Of_Yorks/film_second') }
33
+ let(:permitted_types) { %w(baby hfr kids silver) }
95
34
 
96
- it 'returns a hash keyed by type of performance' do
97
- subject.must_be_instance_of Hash
98
- subject.keys.each { |key| key.must_be_instance_of String }
35
+ it 'returns a non-zero array of hashes' do
36
+ subject.must_be_instance_of(Array)
37
+ subject.size.must_be :>=, 1
38
+ subject.each do |hash|
39
+ hash.must_be_instance_of(Hash)
40
+ end
99
41
  end
100
42
 
101
- it 'returns an array of Times for each type of performance' do
102
- subject.each do |key, value|
103
- value.must_be_instance_of Array
104
- value.each do |item|
105
- item.must_be_instance_of Time
43
+ it 'contains properly completed hashes' do
44
+ subject.each do |hash|
45
+ hash[:booking_url].must_include('http://www.picturehouses.co.uk')
46
+ hash[:dimension].must_match(/\A[23]d\z/)
47
+ hash[:time].must_be_instance_of(Time)
48
+ hash[:variant].must_be_instance_of(Array)
49
+ hash[:variant].each do |type|
50
+ type.must_be_instance_of(String)
51
+ permitted_types.must_include(type)
106
52
  end
107
53
  end
108
54
  end
109
-
110
- it 'returns the correct number of Times' do
111
- subject.keys.must_equal ['2d']
112
- subject['2d'].count.must_equal 2
113
- end
114
-
115
- it 'returns Times in UTC' do
116
- subject['2d'].first.must_equal Time.utc(2013, 10, 15, 9, 30, 0)
117
- subject['2d'].last.must_equal Time.utc(2013, 10, 15, 20, 15, 0)
118
- end
119
55
  end
120
56
 
121
- describe 'screenings including OAP & subtitled' do
122
- let(:film_html) { read_film_html 'captain-phillips-with-silver-screen-and-subtitles'}
57
+ describe 'passed film html from top of dbox cinema page' do
58
+ let(:film_html) { read_film_html('Duke_Of_Yorks/film_last') }
59
+ let(:permitted_types) { %w(baby dbox hfr kids silver) }
123
60
 
124
- it 'returns an array of Times for each type of performance' do
125
- subject.each do |key, value|
126
- value.must_be_instance_of Array
127
- value.each do |item|
128
- item.must_be_instance_of Time
61
+ it 'returns a hash with allowed variants' do
62
+ subject.each do |hash|
63
+ hash[:variant].each do |type|
64
+ type.must_be_instance_of(String)
65
+ permitted_types.must_include(type)
129
66
  end
130
67
  end
131
68
  end
132
-
133
- it 'returns the correct number of Times' do
134
- subject.keys.sort.must_equal ['2d', 'silver', 'subtitled']
135
-
136
- subject['2d'].count.must_equal 1
137
- subject['silver'].count.must_equal 2
138
- subject['subtitled'].count.must_equal 1
139
- end
140
- end
141
-
142
- describe 'screenings including toddler time' do
143
- let(:film_html) { read_film_html 'london-film-festival-with-toddler-time'}
144
-
145
- it 'returns the correct number of Times' do
146
- subject.keys.must_equal ['kids']
147
- subject['kids'].count.must_equal 1
148
- end
149
- end
150
-
151
- describe 'screenings including baby' do
152
- let(:film_html) { read_film_html 'fifth-estate-with-big-scream'}
153
-
154
- it 'returns the correct number of Times' do
155
- subject.keys.sort.must_equal ['2d', 'baby']
156
-
157
- subject['2d'].count.must_equal 4
158
- subject['baby'].count.must_equal 1
159
- end
160
- end
161
-
162
- describe 'screenings including kids' do
163
- let(:film_html) { read_film_html 'planes-with-kids-club'}
164
-
165
- it 'returns the correct number of Times' do
166
- subject.keys.must_equal ['kids']
167
- subject['kids'].count.must_equal 1
168
- end
169
- end
170
-
171
- describe 'expired screenings' do
172
- let(:film_html) { read_film_html 'blue-jasmine-done'}
173
-
174
- it 'returns an empty hash' do
175
- subject.must_be_instance_of Hash
176
- subject.must_be_empty
177
- end
178
69
  end
179
70
  end
180
71
 
72
+ private
73
+
181
74
  def read_film_html(filename)
182
- path = "../../../../fixtures/film_node"
183
- File.read(File.expand_path("#{path}/#{filename}.html", __FILE__))
75
+ path = '../../../../fixtures/cinema/'
76
+ File.read(File.expand_path(path + "#{filename}.html", __FILE__))
184
77
  end
185
78
  end